2007-07-31 Sebastien Pouliot <sebastien@ximian.com>
authorSebastien Pouliot <sebastien@ximian.com>
Tue, 31 Jul 2007 18:53:09 +0000 (18:53 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Tue, 31 Jul 2007 18:53:09 +0000 (18:53 -0000)
* AssemblyInfo.cs: Update copyright notices.
* Makefile: Build the *full*, Cecil-enabled, permview.
* permview.cs: Updated from Cecil repository.

svn path=/trunk/mcs/; revision=83135

mcs/tools/security/AssemblyInfo.cs
mcs/tools/security/ChangeLog
mcs/tools/security/Makefile
mcs/tools/security/permview.cs

index 04c538d0603b0bc9fea1e757d2b00b259280cdda..b7e8f4770a2f169152946f271868cbe92acc5ced 100644 (file)
@@ -4,7 +4,7 @@
 // Author:
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
-// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2004-2007 Novell Inc. (http://www.novell.com)
 //
 
 using System;
@@ -17,7 +17,7 @@ using System.Text;
 
 [assembly: AssemblyCompany("Motus Technologies, Novell")]
 [assembly: AssemblyProduct("Mono Security Tools")]
-[assembly: AssemblyCopyright("Copyright 2002, 2003 Motus Technologies. Copyright 2004-2006 Novell. BSD licensed.")]
+[assembly: AssemblyCopyright("Copyright 2002, 2003 Motus Technologies. Copyright 2004-2007 Novell. BSD licensed.")]
 [assembly: AssemblyVersion (Consts.MonoVersion)]
 
 //[assembly: AssemblyConfiguration("")]
index 9ef84615e329129bddfdc05f089d878a89f46a81..47159716d7336c6e7f2d7bb349210bd10e5c2a04 100644 (file)
@@ -1,3 +1,9 @@
+2007-07-31  Sebastien Pouliot  <sebastien@ximian.com>
+
+       * AssemblyInfo.cs: Update copyright notices.
+       * Makefile: Build the *full*, Cecil-enabled, permview.
+       * permview.cs: Updated from Cecil repository.
+
 2007-04-26  Sebastien Pouliot  <sebastien@ximian.com>
 
        * signcode.cs: Fix individual/commercial mixup (#81462).
index 53e823ab2e909d41aec85d13a2b4037506056e38..f1f7e5ffe667a2dc5c44edf3609ba5a540b7b077 100644 (file)
@@ -60,5 +60,8 @@ dist-local: dist-default
 sn.exe $(topdir)/class/lib/$(PROFILE)/sn.exe: $(SN_SOURCES)
        $(CSCOMPILE) /out:$@ $(SN_SOURCES)
 
+permview.exe: permview.cs
+       $(CSCOMPILE) $^ $(HELPER_SOURCES) -r:Mono.Cecil.dll
+
 %.exe: %.cs $(HELPER_SOURCES)
        $(CSCOMPILE) $^
index 64d11813cde27e5a5d1e790d7c15d5a48dc9c25c..0f20d1f880dfb0fa188578bf193faf4901f4915f 100644 (file)
@@ -4,7 +4,7 @@
 // Author:
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)
 //
 
 using System;
@@ -13,269 +13,246 @@ using System.IO;
 using System.Reflection;
 using System.Security;
 using System.Security.Permissions;
+using System.Text;
+
+using Mono.Cecil;
 
 [assembly: AssemblyTitle ("Mono PermView")]
 [assembly: AssemblyDescription ("Managed Permission Viewer for .NET assemblies")]
 
-namespace Mono.Tools {
-
-       // There is no "managed way" to get this information using Fx 1.0/1.1
-       // so we must reflect inside Mono's corlib to find it. This also means
-       // that this won't work under MS runtime. Hopefully this will change
-       // with Fx 2.0 and Mono's PermView 2.0 should be working on both runtime.
-
-       // Notes:
-       // * Oct CTP started to return declarative security attributes with 
-       //   GetCustomAttributes, so this wont work with beta1 or previous 2.0 CTP
-       // * Dec/Nov CTP (and probably Oct CTP too) are bugged and always report 
-       //   LinkDemand as the SecurityAction (reported as FDBK19290)
+namespace Mono.Tools {\r
+\r
+       class SecurityElementComparer : IComparer {\r
+\r
+               public int Compare (object x, object y)\r
+               {\r
+                       SecurityElement sx = (x as SecurityElement);\r
+                       SecurityElement sy = (y as SecurityElement);\r
+                       if (sx == null)\r
+                               return (sy == null) ? 0 : -1;\r
+                       else if (sy == null)\r
+                               return 1;\r
+\r
+                       // compare by name (type name, method name, action name)\r
+                       return String.Compare (sx.Attribute ("Name"), sy.Attribute ("Name"));\r
+               }\r
+       }
 
        class PermView {
 
+               private const string NotSpecified = "\tNot specified.";
+
                static private void Help () 
                {
                        Console.WriteLine ("Usage: permview [options] assembly{0}", Environment.NewLine);
                        Console.WriteLine ("where options are:");
                        Console.WriteLine (" -output filename  Output information into specified file.");
-                       Console.WriteLine (" -decl             Show declarative security attributes on classes and methods.");
+                       Console.WriteLine (" -decl             Show declarative security attributes on classes and methods.");\r
+                       Console.WriteLine (" -xml              Output in XML format");\r
                        Console.WriteLine (" -help             Show help informations (this text)");
                        Console.WriteLine ();
                }
 
                static bool declarative = false;
+               static bool xmloutput = false;
 
-               static void ShowPermissionSet (TextWriter tw, string header, PermissionSet ps)
+               static TextWriter ProcessOptions (string[] args)
                {
-                       if (header != null)
-                               tw.WriteLine (header);
-
-                       if ((ps == null) || ((ps.Count == 0) && !ps.IsUnrestricted ())) {
-                               tw.WriteLine ("\tNone");
-                       } else {
-                               tw.WriteLine (ps.ToString ());
+                       TextWriter tw = Console.Out;
+                       for (int i=0; i < args.Length - 1; i++) {
+                               switch (args [i].ToUpper ()) {
+                               case "/DECL":
+                               case "-DECL":
+                               case "--DECL":
+                                       declarative = true;
+                                       break;
+                               case "/OUTPUT":
+                               case "-OUTPUT":
+                               case "--OUTPUT":
+                                       tw = (TextWriter) new StreamWriter (args [++i]);
+                                       break;
+                               case "/XML":
+                               case "-XML":
+                               case "--XML":
+                                       xmloutput = true;
+                                       break;
+                               case "/HELP":
+                               case "/H":
+                               case "-HELP":
+                               case "-H":
+                               case "--HELP":
+                               case "--H":
+                               case "-?":
+                               case "--?":
+                                       Help ();
+                                       return null;
+                               }
                        }
-
-                       tw.WriteLine ();
+                       return tw;
                }
 
-#if NET_2_0
-               static PermissionSet GetPermissionSet (SecurityAttribute sa)
+               static bool ProcessAssemblyOnly (TextWriter tw, AssemblyDefinition ad) 
                {
-                       PermissionSet ps = null;
-                       if (sa is PermissionSetAttribute) {
-                               ps = (sa as PermissionSetAttribute).CreatePermissionSet ();
-                       } else {
-                               ps = new PermissionSet (PermissionState.None);
-                               IPermission p = sa.CreatePermission ();
-                               ps.AddPermission (p);
+                       bool result = true;
+                       string minimal = NotSpecified + Environment.NewLine;
+                       string optional = NotSpecified + Environment.NewLine;
+                       string refused = NotSpecified + Environment.NewLine;
+
+                       foreach (SecurityDeclaration decl in ad.SecurityDeclarations) {
+                               switch (decl.Action) {
+                               case Mono.Cecil.SecurityAction.RequestMinimum:
+                                       minimal = decl.PermissionSet.ToString ();
+                                       break;
+                               case Mono.Cecil.SecurityAction.RequestOptional:
+                                       optional = decl.PermissionSet.ToString ();
+                                       break;
+                               case Mono.Cecil.SecurityAction.RequestRefuse:
+                                       refused = decl.PermissionSet.ToString ();
+                                       break;
+                               default:
+                                       tw.WriteLine ("Invalid assembly level declaration {0}{1}{2}",
+                                               decl.Action, Environment.NewLine, decl.PermissionSet);
+                                       result = false;
+                                       break;
+                               }
                        }
-                       return ps;
+
+                       tw.WriteLine ("Minimal Permission Set:");
+                       tw.WriteLine (minimal);
+                       tw.WriteLine ("Optional Permission Set:");
+                       tw.WriteLine (optional);
+                       tw.WriteLine ("Refused Permission Set:");
+                       tw.WriteLine (refused);
+                       return result;
                }
-#else
-               static PermissionSet GetPermissionSet (Assembly a, string name)
+
+               static void ShowSecurity (TextWriter tw, string header, SecurityDeclarationCollection declarations)
                {
-                       FieldInfo fi = typeof (Assembly).GetField (name, BindingFlags.Instance | BindingFlags.NonPublic);
-                       if (fi == null)
-                               throw new NotSupportedException ("Wrong runtime ?");
-                       return (PermissionSet) fi.GetValue (a);
+                       foreach (SecurityDeclaration declsec in declarations) {
+                               tw.WriteLine ("{0} {1} Permission Set:{2}{3}", header,
+                                       declsec.Action, Environment.NewLine, declsec.PermissionSet);
+                       }
                }
-#endif
 
-               static bool ProcessAssemblyOnly (TextWriter tw, Assembly a) 
+               static bool ProcessAssemblyComplete (TextWriter tw, AssemblyDefinition ad)
                {
-#if NET_2_0
-                       // This should work for all 2.0 runtime - unless we hit a bug :-(
-                       object[] attrs = a.GetCustomAttributes (false);
-                       foreach (object attr in attrs) {\r
-                               if (attr is SecurityAttribute) {
-                                       SecurityAttribute sa = (attr as SecurityAttribute);
-                                       switch (sa.Action) {
-                                       case SecurityAction.RequestMinimum:\r
-                                               ShowPermissionSet (tw, "Minimum Permission Set:", GetPermissionSet (sa));\r
-                                               break;\r
-                                       case SecurityAction.RequestOptional:\r
-                                               ShowPermissionSet (tw, "Optional Permission Set:", GetPermissionSet (sa));\r
-                                               break;\r
-                                       case SecurityAction.RequestRefuse:\r
-                                               ShowPermissionSet (tw, "Refused Permission Set:", GetPermissionSet (sa));\r
-                                               break;\r
-                                       default:\r
-                                               // Bug in VS.NET 2005 Nov CTP - Every action is a LinkDemand :(\r
-                                               string msg = String.Format ("ERROR {0} Permission Set:", sa.Action);\r
-                                               ShowPermissionSet (tw, msg, GetPermissionSet (sa));\r
-                                               break;
+                       if (ad.SecurityDeclarations.Count > 0) {
+                               ShowSecurity (tw, "Assembly", ad.SecurityDeclarations);
+                       }
+
+                       foreach (ModuleDefinition module in ad.Modules) {
+
+                               foreach (TypeDefinition type in module.Types) {
+
+                                       if (type.SecurityDeclarations.Count > 0) {
+                                               ShowSecurity (tw, "Class " + type.ToString (), ad.SecurityDeclarations);
+                                       }
+
+                                       foreach (MethodDefinition method in type.Methods) {
+                                               if (method.SecurityDeclarations.Count > 0) {
+                                                       ShowSecurity (tw, "Method " + method.ToString (), method.SecurityDeclarations);
+                                               }
                                        }
                                }
                        }
-#else
-                       // Note: This will only work using the Mono runtime as we P/Invoke
-                       // into Mono's corlib to get the required informations.
-
-                       Type t = typeof (Assembly);
-
-                       // Minimum, Optional and Refuse permission set are only evaluated
-                       // on demand (delayed as much as possible). A call Resolve will
-                       // trigger their retrieval from the assembly metadata
-                       MethodInfo resolve = t.GetMethod ("Resolve", BindingFlags.Instance | BindingFlags.NonPublic);
-                       if (resolve == null)
-                               return false;
-                       resolve.Invoke (a, null);
-
-                       ShowPermissionSet (tw, "Minimal Permission Set:", GetPermissionSet (a, "_minimum"));
-                       ShowPermissionSet (tw, "Optional Permission Set:", GetPermissionSet (a, "_optional"));
-                       ShowPermissionSet (tw, "Refused Permission Set:", GetPermissionSet (a, "_refuse"));
-#endif
                        return true;
                }
 
-/*             static SecurityAction[] actions = {
-                       SecurityAction.LinkDemand,
-                       SecurityAction.InheritanceDemand,
-                       SecurityAction.Demand,
-                       (SecurityAction) 13,                            // Hack for NonCasDemand
-                       (SecurityAction) 14,                            // Hack for NonCasLinkDemand
-                       (SecurityAction) 15,                            // Hack for NonCasInheritanceDemand
-                       SecurityAction.Assert,
-                       SecurityAction.Deny,
-                       SecurityAction.PermitOnly,
-               };
-
-               static MethodInfo method_getdeclsec;
-
-               static PermissionSet GetDeclarativeSecurity (MethodInfo mi, SecurityAction action)
+               static void AddAttribute (SecurityElement se, string attr, string value)
                {
-                       if (method_getdeclsec == null) {
-                               Type t = typeof (Int32).Assembly.GetType ("System.Reflection.MonoMethod");
-                               method_getdeclsec = t.GetMethod ("GetDeclarativeSecurity", BindingFlags.Instance | BindingFlags.Public);
-                       }
-                       return (PermissionSet) method_getdeclsec.Invoke (mi, new object [1] { action });
+                       value = value.Replace ("&", "&amp;");
+                       se.AddAttribute (attr, value);
                }
-*/
-               static void ProcessMethod (TextWriter tw, MethodInfo mi) 
+
+               static SecurityElement AddSecurityXml (SecurityDeclarationCollection declarations)
                {\r
-                       // no need to process methods without security informations\r
-                       if ((mi.Attributes & MethodAttributes.HasSecurity) == MethodAttributes.HasSecurity) {
-#if NET_2_0\r
-                               object[] attrs = mi.GetCustomAttributes (false);\r
-                               foreach (object attr in attrs) {\r
-                                       if (attr is SecurityAttribute) {\r
-                                               SecurityAttribute sa = (attr as SecurityAttribute);\r
-                                               tw.WriteLine ("Method {0} {1} Permission Set", mi, sa.Action);\r
-                                               ShowPermissionSet (tw, null, GetPermissionSet (sa));\r
-                                       }\r
-                               }
-#else
-/*                             foreach (SecurityAction action in actions) {
-                                       PermissionSet ps = GetDeclarativeSecurity (mi, action);
-                                       if (ps != null) {
-                                               tw.WriteLine ("Method {0} {1} Permission Set", mi, action);
-                                               ShowPermissionSet (tw, null, ps);
-                                       }
-                               }*/
-#endif\r
+                       ArrayList list = new ArrayList ();\r
+                       foreach (SecurityDeclaration declsec in declarations) {\r
+                               SecurityElement child = new SecurityElement ("Action");\r
+                               AddAttribute (child, "Name", declsec.Action.ToString ());\r
+                               child.AddChild (declsec.PermissionSet.ToXml ());\r
+                               list.Add (child);\r
                        }\r
-               }
+                       // sort actions\r
+                       list.Sort (Comparer);
 
-               static BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
-                       BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.SetProperty;
+                       SecurityElement se = new SecurityElement ("Actions");
+                       foreach (SecurityElement child in list) {
+                               se.AddChild (child);
+                       }
+                       return se;
+               }\r
+\r
+               static SecurityElementComparer comparer;
+               static IComparer Comparer {
+                       get {
+                               if (comparer == null)
+                                       comparer = new SecurityElementComparer ();
+                               return comparer;
+                       }
+               }
 
-               static void ProcessType (TextWriter tw, Type t) 
+               static bool ProcessAssemblyXml (TextWriter tw, AssemblyDefinition ad)
                {\r
-                       // no need to process types without security informations\r
-                       if ((t.Attributes & TypeAttributes.HasSecurity) == TypeAttributes.HasSecurity) {\r
-#if NET_2_0\r
-                               object[] attrs = t.GetCustomAttributes (false);
-                               foreach (object attr in attrs) {\r
-                                       if (attr is SecurityAttribute) {
-                                               SecurityAttribute sa = (attr as SecurityAttribute);\r
-                                               tw.WriteLine ("Class {0} {1} Permission Set", t, sa.Action);\r
-                                               ShowPermissionSet (tw, null, GetPermissionSet (sa));
-                                       }
-                               }
-#else
-                               tw.WriteLine ("Class {0} 'SecurityAction' Permission Set", t);
-                               // SecurityAction
-                               ShowPermissionSet (tw, null, null);
-#endif\r
-                       }\r
-               }
+                       SecurityElement se = new SecurityElement ("Assembly");
+                       se.AddAttribute ("Name", ad.Name.FullName);
 
-               static bool ProcessAssemblyComplete (TextWriter tw, Assembly a) 
-               {
-#if NET_2_0\r
-                       string header = "Assembly {0} Permission Set";\r
-                       object [] attrs = a.GetCustomAttributes (false);\r
-                       foreach (object attr in attrs) {\r
-                               if (attr is SecurityAttribute) {\r
-                                       SecurityAttribute sa = (attr as SecurityAttribute);\r
-                                       // Bug in VS.NET 2005 Nov CTP - Evrything action is a LinkDemand\r
-                                       ShowPermissionSet (tw, String.Format (header, sa.Action.ToString ()), GetPermissionSet (sa));\r
-                               }\r
-                       }
-#else
-                       tw.WriteLine ("Currently unsupported");
-                       return false;
-/*                     Type t = typeof (Assembly);
-                       FieldInfo fi = t.GetField ("_minimum", BindingFlags.Instance | BindingFlags.NonPublic);
-                       if (fi == null)
-                               return false;
-                       PermissionSet ps = (PermissionSet) fi.GetValue (a);
-                       if (ps != null)
-                               ShowPermissionSet (tw, "Assembly RequestMinimum Permission Set:", ps);
-                       
-                       fi = t.GetField ("_optional", BindingFlags.Instance | BindingFlags.NonPublic);
-                       if (fi == null)
-                               return false;
-                       ps = (PermissionSet) fi.GetValue (a);
-                       if (ps != null)
-                               ShowPermissionSet (tw, "Assembly RequestOptional Permission Set:", ps);
-
-                       fi = t.GetField ("_refuse", BindingFlags.Instance | BindingFlags.NonPublic);
-                       if (fi == null)
-                               return false;
-                       ps = (PermissionSet) fi.GetValue (a);
-                       if (ps != null)
-                               ShowPermissionSet (tw, "Assembly RequestRefuse Permission Set:", ps);*/
-#endif\r
-/*                     Type [] types = a.GetTypes ();\r
-                       foreach (Type type in types) {\r
-                               ProcessType (tw, type);\r
-                               foreach (MethodInfo mi in type.GetMethods (flags)) {\r
-                                       ProcessMethod (tw, mi);\r
-                               }\r
+                       if (ad.SecurityDeclarations.Count > 0) {
+                               se.AddChild (AddSecurityXml (ad.SecurityDeclarations));
                        }
+
+                       ArrayList tlist = new ArrayList ();\r
+                       ArrayList mlist = new ArrayList ();
+
+                       foreach (ModuleDefinition module in ad.Modules) {
+
+                               foreach (TypeDefinition type in module.Types) {
+
+                                       SecurityElement klass = new SecurityElement ("Class");
+                                       SecurityElement methods = new SecurityElement ("Methods");
+
+                                       SecurityElement typelem = null;
+                                       if (type.SecurityDeclarations.Count > 0) {
+                                               typelem = AddSecurityXml (type.SecurityDeclarations);
+                                       }\r
 \r
-                       return true;*/
-               }
+                                       if (mlist.Count > 0)\r
+                                               mlist.Clear ();
 
-               static TextWriter ProcessOptions (string[] args)
-               {
-                       TextWriter tw = Console.Out;
-                       for (int i=0; i < args.Length - 1; i++) {
-                               switch (args [i].ToUpper ()) {
-                               case "/DECL":
-                               case "-DECL":
-                               case "--DECL":
-                                       declarative = true;
-                                       break;
-                               case "/OUTPUT":
-                               case "-OUTPUT":
-                               case "--OUTPUT":
-                                       tw = (TextWriter) new StreamWriter (args [++i]);
-                                       break;
-                               case "/HELP":
-                               case "/H":
-                               case "-HELP":
-                               case "-H":
-                               case "--HELP":
-                               case "--H":
-                               case "-?":
-                               case "--?":
-                                       Help ();
-                                       return null;
+                                       foreach (MethodDefinition method in type.Methods) {
+                                               if (method.SecurityDeclarations.Count > 0) {\r
+                                                       SecurityElement meth = new SecurityElement ("Method");
+                                                       AddAttribute (meth, "Name", method.ToString ());
+                                                       meth.AddChild (AddSecurityXml (method.SecurityDeclarations));
+                                                       mlist.Add (meth);
+                                               }
+                                       }
+
+                                       // sort methods\r
+                                       mlist.Sort (Comparer);\r
+                                       foreach (SecurityElement method in mlist) {\r
+                                               methods.AddChild (method);\r
+                                       }
+
+                                       if ((typelem != null) || ((methods.Children != null) && (methods.Children.Count > 0))) {
+                                               AddAttribute (klass, "Name", type.ToString ());\r
+                                               if (typelem != null)
+                                                       klass.AddChild (typelem);
+                                               if ((methods.Children != null) && (methods.Children.Count > 0))
+                                                       klass.AddChild (methods);
+                                               tlist.Add (klass);
+                                       }
+                               }
+
+                               // sort types
+                               tlist.Sort (Comparer);\r
+                               foreach (SecurityElement type in tlist) {\r
+                                       se.AddChild (type);\r
                                }
                        }
-                       return tw;
+
+                       tw.WriteLine (se.ToString ());
+                       return true;
                }
 
                [STAThread]
@@ -293,13 +270,23 @@ namespace Mono.Tools {
                                        return 0;
 
                                string assemblyName = args [args.Length - 1];
-                               Assembly a = Assembly.LoadFile (Path.GetFullPath (assemblyName));
-                               if (a != null) {
-                                       bool complete = (declarative ?
-                                               ProcessAssemblyComplete (tw, a) :
-                                               ProcessAssemblyOnly (tw, a));
+                               AssemblyDefinition ad = AssemblyFactory.GetAssembly (assemblyName);
+                               if (ad != null) {
+                                       bool complete = false;
+                                       
+                                       if (declarative) {
+                                               // full output (assembly+classes+methods)
+                                               complete = ProcessAssemblyComplete (tw, ad);
+                                       } else if (xmloutput) {
+                                               // full output in XML (for easier diffs after c14n)
+                                               complete = ProcessAssemblyXml (tw, ad);
+                                       } else {
+                                               // default (assembly only)
+                                               complete = ProcessAssemblyOnly (tw, ad);
+                                       }
+
                                        if (!complete) {
-                                               Console.Error.WriteLine ("Couldn't reflect informations. Wrong runtime ?");
+                                               Console.Error.WriteLine ("Couldn't reflect informations.");
                                                return 1;
                                        }
                                } else {