2 // InjectSecurityAttributes.cs
5 // Jb Evain (jbevain@novell.com)
7 // (C) 2009 Novell, Inc.
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Collections
;
35 using Mono
.Linker
.Steps
;
39 namespace Mono
.Tuner
{
41 public class InjectSecurityAttributes
: BaseStep
{
48 protected enum AttributeType
{
53 const string _safe_critical
= "System.Security.SecuritySafeCriticalAttribute";
54 const string _critical
= "System.Security.SecurityCriticalAttribute";
56 const string sec_attr_folder
= "secattrs";
58 protected AssemblyDefinition _assembly
;
60 MethodDefinition _safe_critical_ctor
;
61 MethodDefinition _critical_ctor
;
65 protected override bool ConditionToProcess ()
67 if (!Context
.HasParameter (sec_attr_folder
)) {
68 Console
.Error
.WriteLine ("Warning: no secattrs folder specified.");
72 data_folder
= Context
.GetParameter (sec_attr_folder
);
76 protected override void ProcessAssembly (AssemblyDefinition assembly
)
78 if (Annotations
.GetAction (assembly
) != AssemblyAction
.Link
)
81 string secattr_file
= Path
.Combine (
83 assembly
.Name
.Name
+ ".secattr");
85 if (!File
.Exists (secattr_file
)) {
86 Console
.Error
.WriteLine ("Warning: file '{0}' not found, skipping.", secattr_file
);
92 // remove existing [SecurityCritical] and [SecuritySafeCritical]
93 RemoveSecurityAttributes ();
95 // add [SecurityCritical] and [SecuritySafeCritical] from the data file
96 ProcessSecurityAttributeFile (secattr_file
);
99 protected void RemoveSecurityAttributes ()
101 foreach (TypeDefinition type
in _assembly
.MainModule
.Types
) {
102 RemoveSecurityAttributes (type
);
104 if (type
.HasConstructors
)
105 foreach (MethodDefinition ctor
in type
.Constructors
)
106 RemoveSecurityAttributes (ctor
);
109 foreach (MethodDefinition method
in type
.Methods
)
110 RemoveSecurityAttributes (method
);
114 static void RemoveSecurityDeclarations (IHasSecurity provider
)
116 // also remove already existing CAS security declarations
118 if (provider
== null)
121 if (!provider
.HasSecurityDeclarations
)
124 provider
.SecurityDeclarations
.Clear ();
127 static void RemoveSecurityAttributes (ICustomAttributeProvider provider
)
129 RemoveSecurityDeclarations (provider
as IHasSecurity
);
131 if (!provider
.HasCustomAttributes
)
134 CustomAttributeCollection attributes
= provider
.CustomAttributes
;
135 for (int i
= 0; i
< attributes
.Count
; i
++) {
136 CustomAttribute attribute
= attributes
[i
];
137 switch (attribute
.Constructor
.DeclaringType
.FullName
) {
140 attributes
.RemoveAt (i
--);
146 void ProcessSecurityAttributeFile (string file
)
148 using (StreamReader reader
= File
.OpenText (file
)) {
150 while ((line
= reader
.ReadLine ()) != null)
155 void ProcessLine (string line
)
157 if (line
== null || line
.Length
< 6)
160 int sep
= line
.IndexOf (": ");
164 string marker
= line
.Substring (0, sep
);
165 string target
= line
.Substring (sep
+ 2);
167 ProcessSecurityAttributeEntry (
168 DecomposeAttributeType (marker
),
169 DecomposeTargetKind (marker
),
173 static AttributeType
DecomposeAttributeType (string marker
)
175 if (marker
.StartsWith ("SC"))
176 return AttributeType
.Critical
;
177 else if (marker
.StartsWith ("SSC"))
178 return AttributeType
.SafeCritical
;
180 throw new ArgumentException ();
183 static TargetKind
DecomposeTargetKind (string marker
)
185 switch (marker
[marker
.Length
- 1]) {
187 return TargetKind
.Type
;
189 return TargetKind
.Method
;
191 throw new ArgumentException ();
195 void ProcessSecurityAttributeEntry (AttributeType type
, TargetKind kind
, string target
)
197 ICustomAttributeProvider provider
= GetTarget (kind
, target
);
198 if (provider
== null)
202 case AttributeType
.Critical
:
203 AddCriticalAttribute (provider
);
205 case AttributeType
.SafeCritical
:
206 AddSafeCriticalAttribute (provider
);
211 protected void AddCriticalAttribute (ICustomAttributeProvider provider
)
213 // a [SecurityCritical] replaces a [SecuritySafeCritical]
214 if (HasSecurityAttribute (provider
, AttributeType
.SafeCritical
))
215 RemoveSecurityAttributes (provider
);
217 AddSecurityAttribute (provider
, AttributeType
.Critical
);
220 void AddSafeCriticalAttribute (ICustomAttributeProvider provider
)
222 // a [SecuritySafeCritical] is ignored if a [SecurityCritical] is present
223 if (HasSecurityAttribute (provider
, AttributeType
.Critical
))
226 AddSecurityAttribute (provider
, AttributeType
.SafeCritical
);
229 void AddSecurityAttribute (ICustomAttributeProvider provider
, AttributeType type
)
231 if (HasSecurityAttribute (provider
, type
))
234 CustomAttributeCollection attributes
= provider
.CustomAttributes
;
236 case AttributeType
.Critical
:
237 attributes
.Add (CreateCriticalAttribute ());
239 case AttributeType
.SafeCritical
:
240 attributes
.Add (CreateSafeCriticalAttribute ());
245 protected static bool HasSecurityAttribute (ICustomAttributeProvider provider
, AttributeType type
)
247 if (!provider
.HasCustomAttributes
)
250 foreach (CustomAttribute attribute
in provider
.CustomAttributes
) {
251 switch (attribute
.Constructor
.DeclaringType
.Name
) {
253 if (type
== AttributeType
.Critical
)
258 if (type
== AttributeType
.SafeCritical
)
268 ICustomAttributeProvider
GetTarget (TargetKind kind
, string target
)
271 case TargetKind
.Type
:
272 return GetType (target
);
273 case TargetKind
.Method
:
274 return GetMethod (target
);
276 throw new ArgumentException ();
280 TypeDefinition
GetType (string fullname
)
282 return _assembly
.MainModule
.Types
[fullname
];
285 MethodDefinition
GetMethod (string signature
)
287 int pos
= signature
.IndexOf (" ");
289 throw new ArgumentException ();
291 string tmp
= signature
.Substring (pos
+ 1);
293 pos
= tmp
.IndexOf ("::");
295 throw new ArgumentException ();
297 string type_name
= tmp
.Substring (0, pos
);
299 int parpos
= tmp
.IndexOf ("(");
301 throw new ArgumentException ();
303 string method_name
= tmp
.Substring (pos
+ 2, parpos
- pos
- 2);
305 TypeDefinition type
= GetType (type_name
);
309 return method_name
.StartsWith (".c") ?
310 GetMethod (type
.Constructors
, signature
) :
311 GetMethod (type
.Methods
, signature
);
314 static MethodDefinition
GetMethod (IEnumerable methods
, string signature
)
316 foreach (MethodDefinition method
in methods
)
317 if (GetFullName (method
) == signature
)
323 static string GetFullName (MethodReference method
)
325 int sentinel
= method
.GetSentinel ();
327 StringBuilder sb
= new StringBuilder ();
328 sb
.Append (method
.ReturnType
.ReturnType
.FullName
);
330 sb
.Append (method
.DeclaringType
.FullName
);
332 sb
.Append (method
.Name
);
333 if (method
.HasGenericParameters
) {
335 for (int i
= 0; i
< method
.GenericParameters
.Count
; i
++ ) {
338 sb
.Append (method
.GenericParameters
[i
].Name
);
343 if (method
.HasParameters
) {
344 for (int i
= 0; i
< method
.Parameters
.Count
; i
++) {
351 sb
.Append (method
.Parameters
[i
].ParameterType
.FullName
);
355 return sb
.ToString ();
358 static MethodDefinition
GetDefaultConstructor (TypeDefinition type
)
360 foreach (MethodDefinition ctor
in type
.Constructors
)
361 if (ctor
.Parameters
.Count
== 0)
367 MethodDefinition
GetSafeCriticalCtor ()
369 if (_safe_critical_ctor
!= null)
370 return _safe_critical_ctor
;
372 TypeDefinition safe_critical_type
= Context
.GetType (_safe_critical
);
373 if (safe_critical_type
== null)
374 throw new InvalidOperationException (String
.Format ("{0} type not found", _safe_critical
));
376 _safe_critical_ctor
= GetDefaultConstructor (safe_critical_type
);
377 return _safe_critical_ctor
;
380 MethodDefinition
GetCriticalCtor ()
382 if (_critical_ctor
!= null)
383 return _critical_ctor
;
385 TypeDefinition critical_type
= Context
.GetType (_critical
);
386 if (critical_type
== null)
387 throw new InvalidOperationException (String
.Format ("{0} type not found", _critical
));
389 _critical_ctor
= GetDefaultConstructor (critical_type
);
390 return _critical_ctor
;
393 MethodReference
Import (MethodDefinition method
)
395 return _assembly
.MainModule
.Import (method
);
398 CustomAttribute
CreateSafeCriticalAttribute ()
400 return new CustomAttribute (Import (GetSafeCriticalCtor ()));
403 CustomAttribute
CreateCriticalAttribute ()
405 return new CustomAttribute (Import (GetCriticalCtor ()));