1 //
2 // Author:
3 //   Jb Evain (jbevain@gmail.com)
4 //
5 // Copyright (c) 2008 - 2015 Jb Evain
6 // Copyright (c) 2008 - 2011 Novell, Inc.
7 //
8 // Licensed under the MIT/X11 license.
9 //
10 
11 using System;
12 
13 using Mono.Collections.Generic;
14 
15 namespace Mono.Cecil {
16 
17 	public enum SecurityAction : ushort {
18 		Request = 1,
19 		Demand = 2,
20 		Assert = 3,
21 		Deny = 4,
22 		PermitOnly = 5,
23 		LinkDemand = 6,
24 		InheritDemand = 7,
25 		RequestMinimum = 8,
26 		RequestOptional = 9,
27 		RequestRefuse = 10,
28 		PreJitGrant = 11,
29 		PreJitDeny = 12,
30 		NonCasDemand = 13,
31 		NonCasLinkDemand = 14,
32 		NonCasInheritance = 15
33 	}
34 
35 	public interface ISecurityDeclarationProvider : IMetadataTokenProvider {
36 
37 		bool HasSecurityDeclarations { get; }
38 		Collection<SecurityDeclaration> SecurityDeclarations { get; }
39 	}
40 
41 	public sealed class SecurityAttribute : ICustomAttribute {
42 
43 		TypeReference attribute_type;
44 
45 		internal Collection<CustomAttributeNamedArgument> fields;
46 		internal Collection<CustomAttributeNamedArgument> properties;
47 
48 		public TypeReference AttributeType {
49 			get { return attribute_type; }
50 			set { attribute_type = value; }
51 		}
52 
53 		public bool HasFields {
54 			get { return !fields.IsNullOrEmpty (); }
55 		}
56 
57 		public Collection<CustomAttributeNamedArgument> Fields {
58 			get { return fields ?? (fields = new Collection<CustomAttributeNamedArgument> ()); }
59 		}
60 
61 		public bool HasProperties {
62 			get { return !properties.IsNullOrEmpty (); }
63 		}
64 
65 		public Collection<CustomAttributeNamedArgument> Properties {
66 			get { return properties ?? (properties = new Collection<CustomAttributeNamedArgument> ()); }
67 		}
68 
SecurityAttribute(TypeReference attributeType)69 		public SecurityAttribute (TypeReference attributeType)
70 		{
71 			this.attribute_type = attributeType;
72 		}
73 
74 		bool ICustomAttribute.HasConstructorArguments {
75 			get { return false; }
76 		}
77 
78 		Collection<CustomAttributeArgument> ICustomAttribute.ConstructorArguments {
79 			get { throw new NotSupportedException (); }
80 		}
81 	}
82 
83 	public sealed class SecurityDeclaration {
84 
85 		readonly internal uint signature;
86 		byte [] blob;
87 		readonly ModuleDefinition module;
88 
89 		internal bool resolved;
90 		SecurityAction action;
91 		internal Collection<SecurityAttribute> security_attributes;
92 
93 		public SecurityAction Action {
94 			get { return action; }
95 			set { action = value; }
96 		}
97 
98 		public bool HasSecurityAttributes {
99 			get {
100 				Resolve ();
101 
102 				return !security_attributes.IsNullOrEmpty ();
103 			}
104 		}
105 
106 		public Collection<SecurityAttribute> SecurityAttributes {
107 			get {
108 				Resolve ();
109 
110 				return security_attributes ?? (security_attributes = new Collection<SecurityAttribute> ());
111 			}
112 		}
113 
114 		internal bool HasImage {
115 			get { return module != null && module.HasImage; }
116 		}
117 
SecurityDeclaration(SecurityAction action, uint signature, ModuleDefinition module)118 		internal SecurityDeclaration (SecurityAction action, uint signature, ModuleDefinition module)
119 		{
120 			this.action = action;
121 			this.signature = signature;
122 			this.module = module;
123 		}
124 
SecurityDeclaration(SecurityAction action)125 		public SecurityDeclaration (SecurityAction action)
126 		{
127 			this.action = action;
128 			this.resolved = true;
129 		}
130 
SecurityDeclaration(SecurityAction action, byte [] blob)131 		public SecurityDeclaration (SecurityAction action, byte [] blob)
132 		{
133 			this.action = action;
134 			this.resolved = false;
135 			this.blob = blob;
136 		}
137 
GetBlob()138 		public byte [] GetBlob ()
139 		{
140 			if (blob != null)
141 				return blob;
142 
143 			if (!HasImage || signature == 0)
144 				throw new NotSupportedException ();
145 
146 			return blob = module.Read (this, (declaration, reader) => reader.ReadSecurityDeclarationBlob (declaration.signature));
147 		}
148 
Resolve()149 		void Resolve ()
150 		{
151 			if (resolved || !HasImage)
152 				return;
153 
154 			module.Read (this, (declaration, reader) => reader.ReadSecurityDeclarationSignature (declaration));
155 			resolved = true;
156 		}
157 	}
158 
159 	static partial class Mixin {
160 
GetHasSecurityDeclarations( this ISecurityDeclarationProvider self, ModuleDefinition module)161 		public static bool GetHasSecurityDeclarations (
162 			this ISecurityDeclarationProvider self,
163 			ModuleDefinition module)
164 		{
165 			return module.HasImage () && module.Read (self, (provider, reader) => reader.HasSecurityDeclarations (provider));
166 		}
167 
GetSecurityDeclarations( this ISecurityDeclarationProvider self, ref Collection<SecurityDeclaration> variable, ModuleDefinition module)168 		public static Collection<SecurityDeclaration> GetSecurityDeclarations (
169 			this ISecurityDeclarationProvider self,
170 			ref Collection<SecurityDeclaration> variable,
171 			ModuleDefinition module)
172 		{
173 			return module.HasImage ()
174 				? module.Read (ref variable, self, (provider, reader) => reader.ReadSecurityDeclarations (provider))
175 				: variable = new Collection<SecurityDeclaration>();
176 		}
177 	}
178 }
179