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 ();