2 // StrongNameManager.cs - StrongName Management
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2004 Novell (http://www.novell.com)
11 using System.Collections;
12 using System.Globalization;
14 using System.Reflection;
15 using System.Security;
16 using System.Security.Cryptography;
19 using Mono.Security.Cryptography;
22 namespace Mono.Security {
26 * in_gac ---------------------------------\
34 * bool StrongNameManager.MustVerify
38 * Token --------------------------\
43 * Assembly Name --------------------------|
48 * User ---------------------------|
53 * return false return true
54 * SKIP VERIFICATION VERIFY ASSEMBLY
57 internal class StrongNameManager {
59 private class Element {
60 internal Hashtable assemblies;
64 assemblies = new Hashtable ();
67 public Element (string assembly, string users) : this ()
69 assemblies.Add (assembly, users);
72 public string GetUsers (string assembly)
74 return (string) assemblies [assembly];
78 static private Hashtable mappings;
79 static private Hashtable tokens;
81 static StrongNameManager ()
85 // note: more than one configuration file can be loaded at the
86 // same time (e.g. user specific and machine specific config).
87 static public void LoadConfig (string filename)
89 if (File.Exists (filename)) {
90 SecurityParser sp = new SecurityParser ();
91 using (StreamReader sr = new StreamReader (filename)) {
92 string xml = sr.ReadToEnd ();
95 SecurityElement root = sp.ToXml ();
96 if ((root != null) && (root.Tag == "configuration")) {
97 SecurityElement strongnames = root.SearchForChildByTag ("strongNames");
98 if ((strongnames != null) && (strongnames.Children.Count > 0)) {
99 SecurityElement mapping = strongnames.SearchForChildByTag ("pubTokenMapping");
100 if ((mapping != null) && (mapping.Children.Count > 0)) {
101 LoadMapping (mapping);
104 SecurityElement settings = strongnames.SearchForChildByTag ("verificationSettings");
105 if ((settings != null) && (settings.Children.Count > 0)) {
106 LoadVerificationSettings (settings);
113 static private void LoadMapping (SecurityElement mapping)
115 if (mappings == null) {
116 mappings = new Hashtable ();
119 lock (mappings.SyncRoot) {
120 foreach (SecurityElement item in mapping.Children) {
121 if (item.Tag != "map")
124 string token = item.Attribute ("Token");
125 if ((token == null) || (token.Length != 16))
126 continue; // invalid entry
127 token = token.ToUpper (CultureInfo.InvariantCulture);
129 string publicKey = item.Attribute ("PublicKey");
130 if (publicKey == null)
131 continue; // invalid entry
133 // watch for duplicate entries
134 if (mappings [token] == null) {
135 mappings.Add (token, publicKey);
138 // replace existing mapping
139 mappings [token] = publicKey;
145 static private void LoadVerificationSettings (SecurityElement settings)
147 if (tokens == null) {
148 tokens = new Hashtable ();
151 lock (tokens.SyncRoot) {
152 foreach (SecurityElement item in settings.Children) {
153 if (item.Tag != "skip")
156 string token = item.Attribute ("Token");
158 continue; // bad entry
159 token = token.ToUpper (CultureInfo.InvariantCulture);
161 string assembly = item.Attribute ("Assembly");
162 if (assembly == null)
165 string users = item.Attribute ("Users");
169 Element el = (Element) tokens [token];
172 el = new Element (assembly, users);
173 tokens.Add (token, el);
178 string a = (string) el.assemblies [assembly];
181 el.assemblies.Add (assembly, users);
187 // all users (drop current users)
188 el.assemblies [assembly] = "*";
192 // new users, add to existing
193 string existing = (string) el.assemblies [assembly];
194 string newusers = String.Concat (existing, ",", users);
195 el.assemblies [assembly] = newusers;
200 static public byte[] GetMappedPublicKey (byte[] token)
202 if ((mappings == null) || (token == null))
205 string t = CryptoConvert.ToHex (token);
206 string pk = (string) mappings [t];
210 return CryptoConvert.FromHex (pk);
213 // it is possible to skip verification for assemblies
214 // or a strongname public key using the "sn" tool.
215 // note: only the runtime checks if the assembly is loaded
216 // from the GAC to skip verification
217 static public bool MustVerify (AssemblyName an)
219 if ((an == null) || (tokens == null))
222 string token = CryptoConvert.ToHex (an.GetPublicKeyToken ());
223 Element el = (Element) tokens [token];
225 // look for this specific assembly first
226 string users = el.GetUsers (an.Name);
228 // nothing for the specific assembly
229 // so look for "*" assembly
230 users = el.GetUsers ("*");
234 // applicable to any user ?
237 // applicable to the current user ?
238 return (users.IndexOf (Environment.UserName) < 0);
242 // we must check verify the strongname on the assembly
246 public override string ToString ()
248 StringBuilder sb = new StringBuilder ();
249 sb.Append ("Public Key Token\tAssemblies\t\tUsers");
250 sb.Append (Environment.NewLine);
251 if (tokens == null) {
253 return sb.ToString ();
256 foreach (DictionaryEntry token in tokens) {
257 sb.Append ((string)token.Key);
258 Element t = (Element) token.Value;
260 foreach (DictionaryEntry assembly in t.assemblies) {
266 sb.Append ("\t\t\t");
268 sb.Append ((string)assembly.Key);
270 string users = (string)assembly.Value;
274 sb.Append (Environment.NewLine);
277 return sb.ToString ();