File: permview.cs

package info (click to toggle)
mono 1.2.2.1-1
  • links: PTS
  • area: main
  • in suites: etch-m68k
  • size: 142,728 kB
  • ctags: 256,408
  • sloc: cs: 1,495,736; ansic: 249,442; sh: 18,304; xml: 12,463; makefile: 5,046; perl: 1,248; asm: 635; yacc: 285; sql: 7
file content (319 lines) | stat: -rw-r--r-- 10,105 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
//
// permview.cs: Managed Permission Viewer for .NET assemblies
//
// Author:
//	Sebastien Pouliot  <sebastien@ximian.com>
//
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
//

using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Security;
using System.Security.Permissions;

[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)

	class PermView {

		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 (" -help             Show help informations (this text)");
			Console.WriteLine ();
		}

		static bool declarative = false;

		static void ShowPermissionSet (TextWriter tw, string header, PermissionSet ps)
		{
			if (header != null)
				tw.WriteLine (header);

			if ((ps == null) || ((ps.Count == 0) && !ps.IsUnrestricted ())) {
				tw.WriteLine ("\tNone");
			} else {
				tw.WriteLine (ps.ToString ());
			}

			tw.WriteLine ();
		}

#if NET_2_0
		static PermissionSet GetPermissionSet (SecurityAttribute sa)
		{
			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);
			}
			return ps;
		}
#else
		static PermissionSet GetPermissionSet (Assembly a, string name)
		{
			FieldInfo fi = typeof (Assembly).GetField (name, BindingFlags.Instance | BindingFlags.NonPublic);
			if (fi == null)
				throw new NotSupportedException ("Wrong runtime ?");
			return (PermissionSet) fi.GetValue (a);
		}
#endif

		static bool ProcessAssemblyOnly (TextWriter tw, Assembly a) 
		{
#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) {
				if (attr is SecurityAttribute) {
					SecurityAttribute sa = (attr as SecurityAttribute);
					switch (sa.Action) {
					case SecurityAction.RequestMinimum:
						ShowPermissionSet (tw, "Minimum Permission Set:", GetPermissionSet (sa));
						break;
					case SecurityAction.RequestOptional:
						ShowPermissionSet (tw, "Optional Permission Set:", GetPermissionSet (sa));
						break;
					case SecurityAction.RequestRefuse:
						ShowPermissionSet (tw, "Refused Permission Set:", GetPermissionSet (sa));
						break;
					default:
						// Bug in VS.NET 2005 Nov CTP - Every action is a LinkDemand :(
						string msg = String.Format ("ERROR {0} Permission Set:", sa.Action);
						ShowPermissionSet (tw, msg, GetPermissionSet (sa));
						break;
					}
				}
			}
#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)
		{
			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 });
		}
*/
		static void ProcessMethod (TextWriter tw, MethodInfo mi) 
		{
			// no need to process methods without security informations
			if ((mi.Attributes & MethodAttributes.HasSecurity) == MethodAttributes.HasSecurity) {
#if NET_2_0
				object[] attrs = mi.GetCustomAttributes (false);
				foreach (object attr in attrs) {
					if (attr is SecurityAttribute) {
						SecurityAttribute sa = (attr as SecurityAttribute);
						tw.WriteLine ("Method {0} {1} Permission Set", mi, sa.Action);
						ShowPermissionSet (tw, null, GetPermissionSet (sa));
					}
				}
#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
			}
		}

		static BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
			BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.SetProperty;

		static void ProcessType (TextWriter tw, Type t) 
		{
			// no need to process types without security informations
			if ((t.Attributes & TypeAttributes.HasSecurity) == TypeAttributes.HasSecurity) {
#if NET_2_0
				object[] attrs = t.GetCustomAttributes (false);
				foreach (object attr in attrs) {
					if (attr is SecurityAttribute) {
						SecurityAttribute sa = (attr as SecurityAttribute);
						tw.WriteLine ("Class {0} {1} Permission Set", t, sa.Action);
						ShowPermissionSet (tw, null, GetPermissionSet (sa));
					}
				}
#else
				tw.WriteLine ("Class {0} 'SecurityAction' Permission Set", t);
				// SecurityAction
				ShowPermissionSet (tw, null, null);
#endif
			}
		}

		static bool ProcessAssemblyComplete (TextWriter tw, Assembly a) 
		{
#if NET_2_0
			string header = "Assembly {0} Permission Set";
			object [] attrs = a.GetCustomAttributes (false);
			foreach (object attr in attrs) {
				if (attr is SecurityAttribute) {
					SecurityAttribute sa = (attr as SecurityAttribute);
					// Bug in VS.NET 2005 Nov CTP - Evrything action is a LinkDemand
					ShowPermissionSet (tw, String.Format (header, sa.Action.ToString ()), GetPermissionSet (sa));
				}
			}
#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
/*			Type [] types = a.GetTypes ();
			foreach (Type type in types) {
				ProcessType (tw, type);
				foreach (MethodInfo mi in type.GetMethods (flags)) {
					ProcessMethod (tw, mi);
				}
			}

			return true;*/
		}

		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;
				}
			}
			return tw;
		}

		[STAThread]
		static int Main (string[] args) 
		{
			try {
				Console.WriteLine (new AssemblyInfo ().ToString ());
				if (args.Length == 0) {
					Help ();
					return 0;
				}

				TextWriter tw = ProcessOptions (args);
				if (tw == null)
					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));
					if (!complete) {
						Console.Error.WriteLine ("Couldn't reflect informations. Wrong runtime ?");
						return 1;
					}
				} else {
					Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
					return 2;
				}
				tw.Close ();
			}
			catch (Exception e) {
				Console.Error.WriteLine ("Error: " + e.ToString ());
				Help ();
				return 3;
			}
			return 0;
		}
	}
}