2010-04-15 Jb Evain <jbevain@novell.com>
[mcs.git] / tools / security / permview.cs
blob0f20d1f880dfb0fa188578bf193faf4901f4915f
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 //
10 using System;
11 using System.Collections;
12 using System.IO;
13 using System.Reflection;
14 using System.Security;
15 using System.Security.Permissions;
16 using System.Text;
18 using Mono.Cecil;
20 [assembly: AssemblyTitle ("Mono PermView")]
21 [assembly: AssemblyDescription ("Managed Permission Viewer for .NET assemblies")]
23 namespace Mono.Tools {
25 class SecurityElementComparer : IComparer {
27 public int Compare (object x, object y)
29 SecurityElement sx = (x as SecurityElement);
30 SecurityElement sy = (y as SecurityElement);
31 if (sx == null)
32 return (sy == null) ? 0 : -1;
33 else if (sy == null)
34 return 1;
36 // compare by name (type name, method name, action name)
37 return String.Compare (sx.Attribute ("Name"), sy.Attribute ("Name"));
41 class PermView {
43 private const string NotSpecified = "\tNot specified.";
45 static private void Help ()
47 Console.WriteLine ("Usage: permview [options] assembly{0}", Environment.NewLine);
48 Console.WriteLine ("where options are:");
49 Console.WriteLine (" -output filename Output information into specified file.");
50 Console.WriteLine (" -decl Show declarative security attributes on classes and methods.");
51 Console.WriteLine (" -xml Output in XML format");
52 Console.WriteLine (" -help Show help informations (this text)");
53 Console.WriteLine ();
56 static bool declarative = false;
57 static bool xmloutput = false;
59 static TextWriter ProcessOptions (string[] args)
61 TextWriter tw = Console.Out;
62 for (int i=0; i < args.Length - 1; i++) {
63 switch (args [i].ToUpper ()) {
64 case "/DECL":
65 case "-DECL":
66 case "--DECL":
67 declarative = true;
68 break;
69 case "/OUTPUT":
70 case "-OUTPUT":
71 case "--OUTPUT":
72 tw = (TextWriter) new StreamWriter (args [++i]);
73 break;
74 case "/XML":
75 case "-XML":
76 case "--XML":
77 xmloutput = true;
78 break;
79 case "/HELP":
80 case "/H":
81 case "-HELP":
82 case "-H":
83 case "--HELP":
84 case "--H":
85 case "-?":
86 case "--?":
87 Help ();
88 return null;
91 return tw;
94 static bool ProcessAssemblyOnly (TextWriter tw, AssemblyDefinition ad)
96 bool result = true;
97 string minimal = NotSpecified + Environment.NewLine;
98 string optional = NotSpecified + Environment.NewLine;
99 string refused = NotSpecified + Environment.NewLine;
101 foreach (SecurityDeclaration decl in ad.SecurityDeclarations) {
102 switch (decl.Action) {
103 case Mono.Cecil.SecurityAction.RequestMinimum:
104 minimal = decl.PermissionSet.ToString ();
105 break;
106 case Mono.Cecil.SecurityAction.RequestOptional:
107 optional = decl.PermissionSet.ToString ();
108 break;
109 case Mono.Cecil.SecurityAction.RequestRefuse:
110 refused = decl.PermissionSet.ToString ();
111 break;
112 default:
113 tw.WriteLine ("Invalid assembly level declaration {0}{1}{2}",
114 decl.Action, Environment.NewLine, decl.PermissionSet);
115 result = false;
116 break;
120 tw.WriteLine ("Minimal Permission Set:");
121 tw.WriteLine (minimal);
122 tw.WriteLine ("Optional Permission Set:");
123 tw.WriteLine (optional);
124 tw.WriteLine ("Refused Permission Set:");
125 tw.WriteLine (refused);
126 return result;
129 static void ShowSecurity (TextWriter tw, string header, SecurityDeclarationCollection declarations)
131 foreach (SecurityDeclaration declsec in declarations) {
132 tw.WriteLine ("{0} {1} Permission Set:{2}{3}", header,
133 declsec.Action, Environment.NewLine, declsec.PermissionSet);
137 static bool ProcessAssemblyComplete (TextWriter tw, AssemblyDefinition ad)
139 if (ad.SecurityDeclarations.Count > 0) {
140 ShowSecurity (tw, "Assembly", ad.SecurityDeclarations);
143 foreach (ModuleDefinition module in ad.Modules) {
145 foreach (TypeDefinition type in module.Types) {
147 if (type.SecurityDeclarations.Count > 0) {
148 ShowSecurity (tw, "Class " + type.ToString (), ad.SecurityDeclarations);
151 foreach (MethodDefinition method in type.Methods) {
152 if (method.SecurityDeclarations.Count > 0) {
153 ShowSecurity (tw, "Method " + method.ToString (), method.SecurityDeclarations);
158 return true;
161 static void AddAttribute (SecurityElement se, string attr, string value)
163 value = value.Replace ("&", "&amp;");
164 se.AddAttribute (attr, value);
167 static SecurityElement AddSecurityXml (SecurityDeclarationCollection declarations)
169 ArrayList list = new ArrayList ();
170 foreach (SecurityDeclaration declsec in declarations) {
171 SecurityElement child = new SecurityElement ("Action");
172 AddAttribute (child, "Name", declsec.Action.ToString ());
173 child.AddChild (declsec.PermissionSet.ToXml ());
174 list.Add (child);
176 // sort actions
177 list.Sort (Comparer);
179 SecurityElement se = new SecurityElement ("Actions");
180 foreach (SecurityElement child in list) {
181 se.AddChild (child);
183 return se;
186 static SecurityElementComparer comparer;
187 static IComparer Comparer {
188 get {
189 if (comparer == null)
190 comparer = new SecurityElementComparer ();
191 return comparer;
195 static bool ProcessAssemblyXml (TextWriter tw, AssemblyDefinition ad)
197 SecurityElement se = new SecurityElement ("Assembly");
198 se.AddAttribute ("Name", ad.Name.FullName);
200 if (ad.SecurityDeclarations.Count > 0) {
201 se.AddChild (AddSecurityXml (ad.SecurityDeclarations));
204 ArrayList tlist = new ArrayList ();
205 ArrayList mlist = new ArrayList ();
207 foreach (ModuleDefinition module in ad.Modules) {
209 foreach (TypeDefinition type in module.Types) {
211 SecurityElement klass = new SecurityElement ("Class");
212 SecurityElement methods = new SecurityElement ("Methods");
214 SecurityElement typelem = null;
215 if (type.SecurityDeclarations.Count > 0) {
216 typelem = AddSecurityXml (type.SecurityDeclarations);
219 if (mlist.Count > 0)
220 mlist.Clear ();
222 foreach (MethodDefinition method in type.Methods) {
223 if (method.SecurityDeclarations.Count > 0) {
224 SecurityElement meth = new SecurityElement ("Method");
225 AddAttribute (meth, "Name", method.ToString ());
226 meth.AddChild (AddSecurityXml (method.SecurityDeclarations));
227 mlist.Add (meth);
231 // sort methods
232 mlist.Sort (Comparer);
233 foreach (SecurityElement method in mlist) {
234 methods.AddChild (method);
237 if ((typelem != null) || ((methods.Children != null) && (methods.Children.Count > 0))) {
238 AddAttribute (klass, "Name", type.ToString ());
239 if (typelem != null)
240 klass.AddChild (typelem);
241 if ((methods.Children != null) && (methods.Children.Count > 0))
242 klass.AddChild (methods);
243 tlist.Add (klass);
247 // sort types
248 tlist.Sort (Comparer);
249 foreach (SecurityElement type in tlist) {
250 se.AddChild (type);
254 tw.WriteLine (se.ToString ());
255 return true;
258 [STAThread]
259 static int Main (string[] args)
261 try {
262 Console.WriteLine (new AssemblyInfo ().ToString ());
263 if (args.Length == 0) {
264 Help ();
265 return 0;
268 TextWriter tw = ProcessOptions (args);
269 if (tw == null)
270 return 0;
272 string assemblyName = args [args.Length - 1];
273 AssemblyDefinition ad = AssemblyFactory.GetAssembly (assemblyName);
274 if (ad != null) {
275 bool complete = false;
277 if (declarative) {
278 // full output (assembly+classes+methods)
279 complete = ProcessAssemblyComplete (tw, ad);
280 } else if (xmloutput) {
281 // full output in XML (for easier diffs after c14n)
282 complete = ProcessAssemblyXml (tw, ad);
283 } else {
284 // default (assembly only)
285 complete = ProcessAssemblyOnly (tw, ad);
288 if (!complete) {
289 Console.Error.WriteLine ("Couldn't reflect informations.");
290 return 1;
292 } else {
293 Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
294 return 2;
296 tw.Close ();
298 catch (Exception e) {
299 Console.Error.WriteLine ("Error: " + e.ToString ());
300 Help ();
301 return 3;
303 return 0;