2 // StrongNameManager.cs - StrongName Management
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2004 Novell (http://www.novell.com)
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Collections
;
35 using System
.Globalization
;
37 using System
.Reflection
;
38 using System
.Security
;
39 using System
.Security
.Cryptography
;
42 using Mono
.Security
.Cryptography
;
45 namespace Mono
.Security
{
49 * in_gac ---------------------------------\
57 * bool StrongNameManager.MustVerify
61 * Token --------------------------\
66 * Assembly Name --------------------------|
71 * User ---------------------------|
76 * return false return true
77 * SKIP VERIFICATION VERIFY ASSEMBLY
80 internal class StrongNameManager
{
82 private class Element
{
83 internal Hashtable assemblies
;
87 assemblies
= new Hashtable ();
90 public Element (string assembly
, string users
) : this ()
92 assemblies
.Add (assembly
, users
);
95 public string GetUsers (string assembly
)
97 return (string) assemblies
[assembly
];
101 static private Hashtable mappings
;
102 static private Hashtable tokens
;
104 static StrongNameManager ()
108 // note: more than one configuration file can be loaded at the
109 // same time (e.g. user specific and machine specific config).
110 static public void LoadConfig (string filename
)
112 if (File
.Exists (filename
)) {
113 SecurityParser sp
= new SecurityParser ();
114 using (StreamReader sr
= new StreamReader (filename
)) {
115 string xml
= sr
.ReadToEnd ();
118 SecurityElement root
= sp
.ToXml ();
119 if ((root
!= null) && (root
.Tag
== "configuration")) {
120 SecurityElement strongnames
= root
.SearchForChildByTag ("strongNames");
121 if ((strongnames
!= null) && (strongnames
.Children
.Count
> 0)) {
122 SecurityElement mapping
= strongnames
.SearchForChildByTag ("pubTokenMapping");
123 if ((mapping
!= null) && (mapping
.Children
.Count
> 0)) {
124 LoadMapping (mapping
);
127 SecurityElement settings
= strongnames
.SearchForChildByTag ("verificationSettings");
128 if ((settings
!= null) && (settings
.Children
.Count
> 0)) {
129 LoadVerificationSettings (settings
);
136 static private void LoadMapping (SecurityElement mapping
)
138 if (mappings
== null) {
139 mappings
= new Hashtable ();
142 lock (mappings
.SyncRoot
) {
143 foreach (SecurityElement item
in mapping
.Children
) {
144 if (item
.Tag
!= "map")
147 string token
= item
.Attribute ("Token");
148 if ((token
== null) || (token
.Length
!= 16))
149 continue; // invalid entry
150 token
= token
.ToUpper (CultureInfo
.InvariantCulture
);
152 string publicKey
= item
.Attribute ("PublicKey");
153 if (publicKey
== null)
154 continue; // invalid entry
156 // watch for duplicate entries
157 if (mappings
[token
] == null) {
158 mappings
.Add (token
, publicKey
);
161 // replace existing mapping
162 mappings
[token
] = publicKey
;
168 static private void LoadVerificationSettings (SecurityElement settings
)
170 if (tokens
== null) {
171 tokens
= new Hashtable ();
174 lock (tokens
.SyncRoot
) {
175 foreach (SecurityElement item
in settings
.Children
) {
176 if (item
.Tag
!= "skip")
179 string token
= item
.Attribute ("Token");
181 continue; // bad entry
182 token
= token
.ToUpper (CultureInfo
.InvariantCulture
);
184 string assembly
= item
.Attribute ("Assembly");
185 if (assembly
== null)
188 string users
= item
.Attribute ("Users");
192 Element el
= (Element
) tokens
[token
];
195 el
= new Element (assembly
, users
);
196 tokens
.Add (token
, el
);
201 string a
= (string) el
.assemblies
[assembly
];
204 el
.assemblies
.Add (assembly
, users
);
210 // all users (drop current users)
211 el
.assemblies
[assembly
] = "*";
215 // new users, add to existing
216 string existing
= (string) el
.assemblies
[assembly
];
217 string newusers
= String
.Concat (existing
, ",", users
);
218 el
.assemblies
[assembly
] = newusers
;
223 static public byte[] GetMappedPublicKey (byte[] token
)
225 if ((mappings
== null) || (token
== null))
228 string t
= CryptoConvert
.ToHex (token
);
229 string pk
= (string) mappings
[t
];
233 return CryptoConvert
.FromHex (pk
);
236 // it is possible to skip verification for assemblies
237 // or a strongname public key using the "sn" tool.
238 // note: only the runtime checks if the assembly is loaded
239 // from the GAC to skip verification
240 static public bool MustVerify (AssemblyName an
)
242 if ((an
== null) || (tokens
== null))
245 string token
= CryptoConvert
.ToHex (an
.GetPublicKeyToken ());
246 Element el
= (Element
) tokens
[token
];
248 // look for this specific assembly first
249 string users
= el
.GetUsers (an
.Name
);
251 // nothing for the specific assembly
252 // so look for "*" assembly
253 users
= el
.GetUsers ("*");
257 // applicable to any user ?
260 // applicable to the current user ?
261 return (users
.IndexOf (Environment
.UserName
) < 0);
265 // we must check verify the strongname on the assembly
269 public override string ToString ()
271 StringBuilder sb
= new StringBuilder ();
272 sb
.Append ("Public Key Token\tAssemblies\t\tUsers");
273 sb
.Append (Environment
.NewLine
);
274 foreach (DictionaryEntry token
in tokens
) {
275 sb
.Append ((string)token
.Key
);
276 Element t
= (Element
) token
.Value
;
278 foreach (DictionaryEntry assembly
in t
.assemblies
) {
284 sb
.Append ("\t\t\t");
286 sb
.Append ((string)assembly
.Key
);
288 string users
= (string)assembly
.Value
;
292 sb
.Append (Environment
.NewLine
);
295 return sb
.ToString ();