2 // permview.cs: Managed Permission Viewer for .NET assemblies
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 using System.Collections;
13 using System.Reflection;
14 using System.Security;
15 using System.Security.Permissions;
17 [assembly: AssemblyTitle ("Mono PermView")]
18 [assembly: AssemblyDescription ("Managed Permission Viewer for .NET assemblies")]
20 namespace Mono.Tools {
22 // There is no "managed way" to get this information using Fx 1.0/1.1
23 // so we must reflect inside Mono's corlib to find it. This also means
24 // that this won't work under MS runtime. Hopefully this will change
25 // with Fx 2.0 and Mono's PermView 2.0 should be working on both runtime.
28 // * Oct CTP started to return declarative security attributes with
29 // GetCustomAttributes, so this wont work with beta1 or previous 2.0 CTP
30 // * Dec/Nov CTP (and probably Oct CTP too) are bugged and always report
31 // LinkDemand as the SecurityAction (reported as FDBK19290)
35 static private void Help ()
37 Console.WriteLine ("Usage: permview [options] assembly{0}", Environment.NewLine);
38 Console.WriteLine ("where options are:");
39 Console.WriteLine (" -output filename Output information into specified file.");
40 Console.WriteLine (" -decl Show declarative security attributes on classes and methods.");
41 Console.WriteLine (" -help Show help informations (this text)");
45 static bool declarative = false;
47 static void ShowPermissionSet (TextWriter tw, string header, PermissionSet ps)
50 tw.WriteLine (header);
52 if ((ps == null) || ((ps.Count == 0) && !ps.IsUnrestricted ())) {
53 tw.WriteLine ("\tNone");
55 tw.WriteLine (ps.ToString ());
62 static PermissionSet GetPermissionSet (SecurityAttribute sa)
64 PermissionSet ps = null;
65 if (sa is PermissionSetAttribute) {
66 ps = (sa as PermissionSetAttribute).CreatePermissionSet ();
68 ps = new PermissionSet (PermissionState.None);
69 IPermission p = sa.CreatePermission ();
75 static PermissionSet GetPermissionSet (Assembly a, string name)
77 FieldInfo fi = typeof (Assembly).GetField (name, BindingFlags.Instance | BindingFlags.NonPublic);
79 throw new NotSupportedException ("Wrong runtime ?");
80 return (PermissionSet) fi.GetValue (a);
84 static bool ProcessAssemblyOnly (TextWriter tw, Assembly a)
87 // This should work for all 2.0 runtime - unless we hit a bug :-(
88 object[] attrs = a.GetCustomAttributes (false);
89 foreach (object attr in attrs) {
\r
90 if (attr is SecurityAttribute) {
91 SecurityAttribute sa = (attr as SecurityAttribute);
93 case SecurityAction.RequestMinimum:
\r
94 ShowPermissionSet (tw, "Minimum Permission Set:", GetPermissionSet (sa));
\r
96 case SecurityAction.RequestOptional:
\r
97 ShowPermissionSet (tw, "Optional Permission Set:", GetPermissionSet (sa));
\r
99 case SecurityAction.RequestRefuse:
\r
100 ShowPermissionSet (tw, "Refused Permission Set:", GetPermissionSet (sa));
\r
103 // Bug in VS.NET 2005 Nov CTP - Every action is a LinkDemand :(
\r
104 string msg = String.Format ("ERROR {0} Permission Set:", sa.Action);
\r
105 ShowPermissionSet (tw, msg, GetPermissionSet (sa));
\r
111 // Note: This will only work using the Mono runtime as we P/Invoke
112 // into Mono's corlib to get the required informations.
114 Type t = typeof (Assembly);
116 // Minimum, Optional and Refuse permission set are only evaluated
117 // on demand (delayed as much as possible). A call Resolve will
118 // trigger their retrieval from the assembly metadata
119 MethodInfo resolve = t.GetMethod ("Resolve", BindingFlags.Instance | BindingFlags.NonPublic);
122 resolve.Invoke (a, null);
124 ShowPermissionSet (tw, "Minimal Permission Set:", GetPermissionSet (a, "_minimum"));
125 ShowPermissionSet (tw, "Optional Permission Set:", GetPermissionSet (a, "_optional"));
126 ShowPermissionSet (tw, "Refused Permission Set:", GetPermissionSet (a, "_refuse"));
131 /* static SecurityAction[] actions = {
132 SecurityAction.LinkDemand,
133 SecurityAction.InheritanceDemand,
134 SecurityAction.Demand,
135 (SecurityAction) 13, // Hack for NonCasDemand
136 (SecurityAction) 14, // Hack for NonCasLinkDemand
137 (SecurityAction) 15, // Hack for NonCasInheritanceDemand
138 SecurityAction.Assert,
140 SecurityAction.PermitOnly,
143 static MethodInfo method_getdeclsec;
145 static PermissionSet GetDeclarativeSecurity (MethodInfo mi, SecurityAction action)
147 if (method_getdeclsec == null) {
148 Type t = typeof (Int32).Assembly.GetType ("System.Reflection.MonoMethod");
149 method_getdeclsec = t.GetMethod ("GetDeclarativeSecurity", BindingFlags.Instance | BindingFlags.Public);
151 return (PermissionSet) method_getdeclsec.Invoke (mi, new object [1] { action });
154 static void ProcessMethod (TextWriter tw, MethodInfo mi)
156 // no need to process methods without security informations
\r
157 if ((mi.Attributes & MethodAttributes.HasSecurity) == MethodAttributes.HasSecurity) {
159 object[] attrs = mi.GetCustomAttributes (false);
\r
160 foreach (object attr in attrs) {
\r
161 if (attr is SecurityAttribute) {
\r
162 SecurityAttribute sa = (attr as SecurityAttribute);
\r
163 tw.WriteLine ("Method {0} {1} Permission Set", mi, sa.Action);
\r
164 ShowPermissionSet (tw, null, GetPermissionSet (sa));
\r
168 /* foreach (SecurityAction action in actions) {
169 PermissionSet ps = GetDeclarativeSecurity (mi, action);
171 tw.WriteLine ("Method {0} {1} Permission Set", mi, action);
172 ShowPermissionSet (tw, null, ps);
179 static BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
180 BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.SetProperty;
182 static void ProcessType (TextWriter tw, Type t)
184 // no need to process types without security informations
\r
185 if ((t.Attributes & TypeAttributes.HasSecurity) == TypeAttributes.HasSecurity) {
\r
187 object[] attrs = t.GetCustomAttributes (false);
188 foreach (object attr in attrs) {
\r
189 if (attr is SecurityAttribute) {
190 SecurityAttribute sa = (attr as SecurityAttribute);
\r
191 tw.WriteLine ("Class {0} {1} Permission Set", t, sa.Action);
\r
192 ShowPermissionSet (tw, null, GetPermissionSet (sa));
196 tw.WriteLine ("Class {0} 'SecurityAction' Permission Set", t);
198 ShowPermissionSet (tw, null, null);
203 static bool ProcessAssemblyComplete (TextWriter tw, Assembly a)
206 string header = "Assembly {0} Permission Set";
\r
207 object [] attrs = a.GetCustomAttributes (false);
\r
208 foreach (object attr in attrs) {
\r
209 if (attr is SecurityAttribute) {
\r
210 SecurityAttribute sa = (attr as SecurityAttribute);
\r
211 // Bug in VS.NET 2005 Nov CTP - Evrything action is a LinkDemand
\r
212 ShowPermissionSet (tw, String.Format (header, sa.Action.ToString ()), GetPermissionSet (sa));
\r
216 tw.WriteLine ("Currently unsupported");
218 /* Type t = typeof (Assembly);
219 FieldInfo fi = t.GetField ("_minimum", BindingFlags.Instance | BindingFlags.NonPublic);
222 PermissionSet ps = (PermissionSet) fi.GetValue (a);
224 ShowPermissionSet (tw, "Assembly RequestMinimum Permission Set:", ps);
226 fi = t.GetField ("_optional", BindingFlags.Instance | BindingFlags.NonPublic);
229 ps = (PermissionSet) fi.GetValue (a);
231 ShowPermissionSet (tw, "Assembly RequestOptional Permission Set:", ps);
233 fi = t.GetField ("_refuse", BindingFlags.Instance | BindingFlags.NonPublic);
236 ps = (PermissionSet) fi.GetValue (a);
238 ShowPermissionSet (tw, "Assembly RequestRefuse Permission Set:", ps);*/
240 /* Type [] types = a.GetTypes ();
\r
241 foreach (Type type in types) {
\r
242 ProcessType (tw, type);
\r
243 foreach (MethodInfo mi in type.GetMethods (flags)) {
\r
244 ProcessMethod (tw, mi);
\r
251 static TextWriter ProcessOptions (string[] args)
253 TextWriter tw = Console.Out;
254 for (int i=0; i < args.Length - 1; i++) {
255 switch (args [i].ToUpper ()) {
264 tw = (TextWriter) new StreamWriter (args [++i]);
282 static int Main (string[] args)
285 Console.WriteLine (new AssemblyInfo ().ToString ());
286 if (args.Length == 0) {
291 TextWriter tw = ProcessOptions (args);
295 string assemblyName = args [args.Length - 1];
296 Assembly a = Assembly.LoadFile (Path.GetFullPath (assemblyName));
298 bool complete = (declarative ?
299 ProcessAssemblyComplete (tw, a) :
300 ProcessAssemblyOnly (tw, a));
302 Console.Error.WriteLine ("Couldn't reflect informations. Wrong runtime ?");
306 Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
311 catch (Exception e) {
312 Console.Error.WriteLine ("Error: " + e.ToString ());