// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** CLASS: XMLUtil ** ** [....] ** ** PURPOSE: Helpers for XML input & output ** ===========================================================*/ namespace System.Security.Util { using System; using System.Security; using System.Security.Permissions; using System.Security.Policy; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.IO; using System.Text; using System.Runtime.CompilerServices; using PermissionState = System.Security.Permissions.PermissionState; using BindingFlags = System.Reflection.BindingFlags; using Assembly = System.Reflection.Assembly; using System.Threading; using System.Globalization; using System.Reflection; using System.Diagnostics.Contracts; internal static class XMLUtil { // // Warning: Element constructors have side-effects on their // third argument. // private const String BuiltInPermission = "System.Security.Permissions."; #if FEATURE_CAS_POLICY private const String BuiltInMembershipCondition = "System.Security.Policy."; private const String BuiltInCodeGroup = "System.Security.Policy."; private const String BuiltInApplicationSecurityManager = "System.Security.Policy."; private static readonly char[] sepChar = {',', ' '}; #endif public static SecurityElement NewPermissionElement (IPermission ip) { return NewPermissionElement (ip.GetType ().FullName) ; } public static SecurityElement NewPermissionElement (String name) { SecurityElement ecr = new SecurityElement( "Permission" ); ecr.AddAttribute( "class", name ); return ecr; } public static void AddClassAttribute( SecurityElement element, Type type, String typename ) { // Replace any quotes with apostrophes so that we can include quoted materials // within classnames. Notably the assembly name member 'loc' uses a quoted string. // NOTE: this makes assumptions as to what reflection is expecting for a type string // it will need to be updated if reflection changes what it wants. if ( typename == null ) typename = type.FullName; Contract.Assert( type.FullName.Equals( typename ), "Incorrect class name passed! Was : " + typename + " Shoule be: " + type.FullName); element.AddAttribute( "class", typename + ", " + type.Module.Assembly.FullName.Replace( '\"', '\'' ) ); } internal static bool ParseElementForAssemblyIdentification(SecurityElement el, out String className, out String assemblyName, // for example "WindowsBase" out String assemblyVersion) { className = null; assemblyName = null; assemblyVersion = null; String fullClassName = el.Attribute( "class" ); if (fullClassName == null) { return false; } if (fullClassName.IndexOf('\'') >= 0) { fullClassName = fullClassName.Replace( '\'', '\"' ); } int commaIndex = fullClassName.IndexOf( ',' ); int namespaceClassNameLength; // If the classname is tagged with assembly information, find where // the assembly information begins. if (commaIndex == -1) { return false; } namespaceClassNameLength = commaIndex; className = fullClassName.Substring(0, namespaceClassNameLength); String assemblyFullName = fullClassName.Substring(commaIndex + 1); AssemblyName an = new AssemblyName(assemblyFullName); assemblyName = an.Name; assemblyVersion = an.Version.ToString(); return true; } [System.Security.SecurityCritical] // auto-generated private static bool ParseElementForObjectCreation( SecurityElement el, String requiredNamespace, out String className, out int classNameStart, out int classNameLength ) { className = null; classNameStart = 0; classNameLength = 0; int requiredNamespaceLength = requiredNamespace.Length; String fullClassName = el.Attribute( "class" ); if (fullClassName == null) { throw new ArgumentException( Environment.GetResourceString( "Argument_NoClass" ) ); } if (fullClassName.IndexOf('\'') >= 0) { fullClassName = fullClassName.Replace( '\'', '\"' ); } if (!PermissionToken.IsMscorlibClassName( fullClassName )) { return false; } int commaIndex = fullClassName.IndexOf( ',' ); int namespaceClassNameLength; // If the classname is tagged with assembly information, find where // the assembly information begins. if (commaIndex == -1) { namespaceClassNameLength = fullClassName.Length; } else { namespaceClassNameLength = commaIndex; } // Only if the length of the class name is greater than the namespace info // on our requiredNamespace do we continue // with our check. if (namespaceClassNameLength > requiredNamespaceLength) { // Make sure we are in the required namespace. if (fullClassName.StartsWith(requiredNamespace, StringComparison.Ordinal)) { className = fullClassName; classNameLength = namespaceClassNameLength - requiredNamespaceLength; classNameStart = requiredNamespaceLength; return true; } } return false; } #if FEATURE_CAS_POLICY public static String SecurityObjectToXmlString(Object ob) { if(ob == null) return ""; PermissionSet pset = ob as PermissionSet; if(pset != null) return pset.ToXml().ToString(); return ((IPermission)ob).ToXml().ToString(); } [System.Security.SecurityCritical] // auto-generated public static Object XmlStringToSecurityObject(String s) { if(s == null) return null; if(s.Length < 1) return null; return SecurityElement.FromString(s).ToSecurityObject(); } #endif // FEATURE_CAS_POLICY [SecuritySafeCritical] public static IPermission CreatePermission (SecurityElement el, PermissionState permState, bool ignoreTypeLoadFailures) { if (el == null || !(el.Tag.Equals("Permission") || el.Tag.Equals("IPermission")) ) throw new ArgumentException( String.Format( null, Environment.GetResourceString( "Argument_WrongElementType" ), "" ) ) ; Contract.EndContractBlock(); String className; int classNameLength; int classNameStart; if (!ParseElementForObjectCreation( el, BuiltInPermission, out className, out classNameStart, out classNameLength )) { goto USEREFLECTION; } // We have a built in permission, figure out which it is. // UIPermission // FileIOPermission // SecurityPermission // PrincipalPermission // ReflectionPermission // FileDialogPermission // EnvironmentPermission // GacIdentityPermission // UrlIdentityPermission // SiteIdentityPermission // ZoneIdentityPermission // KeyContainerPermission // UnsafeForHostPermission // HostProtectionPermission // StrongNameIdentityPermission #if !FEATURE_CORECLR // IsolatedStorageFilePermission #endif #if !FEATURE_PAL // RegistryPermission // PublisherIdentityPermission #endif // !FEATURE_PAL switch (classNameLength) { case 12: // UIPermission if (String.Compare(className, classNameStart, "UIPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new UIPermission( permState ); else goto USEREFLECTION; case 16: // FileIOPermission if (String.Compare(className, classNameStart, "FileIOPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new FileIOPermission( permState ); else goto USEREFLECTION; case 18: #if !FEATURE_PAL // RegistryPermission // SecurityPermission if (className[classNameStart] == 'R') { if (String.Compare(className, classNameStart, "RegistryPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new RegistryPermission( permState ); else goto USEREFLECTION; } else { if (String.Compare(className, classNameStart, "SecurityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new SecurityPermission( permState ); else goto USEREFLECTION; } #else // !FEATURE_PAL if (String.Compare(className, classNameStart, "SecurityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new SecurityPermission( permState ); else goto USEREFLECTION; #endif // !FEATURE_PAL #if !FEATURE_CORECLR case 19: // PrincipalPermission if (String.Compare(className, classNameStart, "PrincipalPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new PrincipalPermission( permState ); else goto USEREFLECTION; #endif // !FEATURE_CORECLR case 20: // ReflectionPermission // FileDialogPermission if (className[classNameStart] == 'R') { if (String.Compare(className, classNameStart, "ReflectionPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new ReflectionPermission( permState ); else goto USEREFLECTION; } else { if (String.Compare(className, classNameStart, "FileDialogPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new FileDialogPermission( permState ); else goto USEREFLECTION; } case 21: // EnvironmentPermission // UrlIdentityPermission // GacIdentityPermission if (className[classNameStart] == 'E') { if (String.Compare(className, classNameStart, "EnvironmentPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new EnvironmentPermission( permState ); else goto USEREFLECTION; } else if (className[classNameStart] == 'U') { if (String.Compare(className, classNameStart, "UrlIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new UrlIdentityPermission( permState ); else goto USEREFLECTION; } else { if (String.Compare(className, classNameStart, "GacIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new GacIdentityPermission( permState ); else goto USEREFLECTION; } case 22: // SiteIdentityPermission // ZoneIdentityPermission // KeyContainerPermission if (className[classNameStart] == 'S') { if (String.Compare(className, classNameStart, "SiteIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new SiteIdentityPermission( permState ); else goto USEREFLECTION; } else if (className[classNameStart] == 'Z') { if (String.Compare(className, classNameStart, "ZoneIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new ZoneIdentityPermission( permState ); else goto USEREFLECTION; } else { #if !FEATURE_PAL if (String.Compare(className, classNameStart, "KeyContainerPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new KeyContainerPermission( permState ); else #endif // !FEATURE_PAL goto USEREFLECTION; } case 24: // HostProtectionPermission if (String.Compare(className, classNameStart, "HostProtectionPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new HostProtectionPermission( permState ); else goto USEREFLECTION; #if FEATURE_X509 && FEATURE_CAS_POLICY case 27: // PublisherIdentityPermission if (String.Compare(className, classNameStart, "PublisherIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new PublisherIdentityPermission( permState ); else goto USEREFLECTION; #endif // FEATURE_X509 && FEATURE_CAS_POLICY case 28: // StrongNameIdentityPermission if (String.Compare(className, classNameStart, "StrongNameIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new StrongNameIdentityPermission( permState ); else goto USEREFLECTION; #if !FEATURE_CORECLR case 29: // IsolatedStorageFilePermission if (String.Compare(className, classNameStart, "IsolatedStorageFilePermission", 0, classNameLength, StringComparison.Ordinal) == 0) return new IsolatedStorageFilePermission( permState ); else goto USEREFLECTION; #endif default: goto USEREFLECTION; } USEREFLECTION: Object[] objs = new Object[1]; objs[0] = permState; Type permClass = null; IPermission perm = null; new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); permClass = GetClassFromElement(el, ignoreTypeLoadFailures); if (permClass == null) return null; if (!(typeof(IPermission).IsAssignableFrom(permClass))) throw new ArgumentException( Environment.GetResourceString("Argument_NotAPermissionType") ); perm = (IPermission) Activator.CreateInstance(permClass, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, objs, null ); return perm; } #if FEATURE_CAS_POLICY #pragma warning disable 618 // CodeGroups are obsolete [System.Security.SecuritySafeCritical] // auto-generated public static CodeGroup CreateCodeGroup (SecurityElement el) { if (el == null || !el.Tag.Equals("CodeGroup")) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_WrongElementType" ), "" ) ) ; Contract.EndContractBlock(); String className; int classNameLength; int classNameStart; if (!ParseElementForObjectCreation( el, BuiltInCodeGroup, out className, out classNameStart, out classNameLength )) { goto USEREFLECTION; } switch (classNameLength) { case 12: // NetCodeGroup if (String.Compare(className, classNameStart, "NetCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) return new NetCodeGroup(); else goto USEREFLECTION; case 13: // FileCodeGroup if (String.Compare(className, classNameStart, "FileCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) return new FileCodeGroup(); else goto USEREFLECTION; case 14: // UnionCodeGroup if (String.Compare(className, classNameStart, "UnionCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) return new UnionCodeGroup(); else goto USEREFLECTION; case 19: // FirstMatchCodeGroup if (String.Compare(className, classNameStart, "FirstMatchCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0) return new FirstMatchCodeGroup(); else goto USEREFLECTION; default: goto USEREFLECTION; } USEREFLECTION: Type groupClass = null; CodeGroup group = null; new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); groupClass = GetClassFromElement(el, true); if (groupClass == null) return null; if (!(typeof(CodeGroup).IsAssignableFrom(groupClass))) throw new ArgumentException( Environment.GetResourceString("Argument_NotACodeGroupType") ); group = (CodeGroup) Activator.CreateInstance(groupClass, true); Contract.Assert( groupClass.Module.Assembly != Assembly.GetExecutingAssembly(), "This path should not get called for mscorlib based classes" ); return group; } #pragma warning restore 618 [System.Security.SecurityCritical] // auto-generated internal static IMembershipCondition CreateMembershipCondition( SecurityElement el ) { if (el == null || !el.Tag.Equals("IMembershipCondition")) throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_WrongElementType" ), "" ) ) ; Contract.EndContractBlock(); String className; int classNameStart; int classNameLength; if (!ParseElementForObjectCreation( el, BuiltInMembershipCondition, out className, out classNameStart, out classNameLength )) { goto USEREFLECTION; } // We have a built in membership condition, figure out which it is. // Here's the list of built in membership conditions as of 9/17/2002 // System.Security.Policy.AllMembershipCondition // System.Security.Policy.URLMembershipCondition // System.Security.Policy.SHA1MembershipCondition // System.Security.Policy.SiteMembershipCondition // System.Security.Policy.ZoneMembershipCondition // System.Security.Policy.PublisherMembershipCondition // System.Security.Policy.StrongNameMembershipCondition // System.Security.Policy.ApplicationMembershipCondition // System.Security.Policy.DomainApplicationMembershipCondition // System.Security.Policy.ApplicationDirectoryMembershipCondition switch (classNameLength) { case 22: // AllMembershipCondition // URLMembershipCondition if (className[classNameStart] == 'A') { if (String.Compare(className, classNameStart, "AllMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new AllMembershipCondition(); else goto USEREFLECTION; } else { if (String.Compare(className, classNameStart, "UrlMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new UrlMembershipCondition(); else goto USEREFLECTION; } case 23: #if !FEATURE_PAL // HashMembershipCondition // SiteMembershipCondition // ZoneMembershipCondition if (className[classNameStart] == 'H') { if (String.Compare(className, classNameStart, "HashMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new HashMembershipCondition(); else goto USEREFLECTION; } else if (className[classNameStart] == 'S') #else // SiteMembershipCondition // ZoneMembershipCondition if (className[classNameStart] == 'S') #endif // !FEATURE_PAL { if (String.Compare(className, classNameStart, "SiteMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new SiteMembershipCondition(); else goto USEREFLECTION; } else { if (String.Compare(className, classNameStart, "ZoneMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new ZoneMembershipCondition(); else goto USEREFLECTION; } case 28: #if !FEATURE_PAL // PublisherMembershipCondition if (String.Compare(className, classNameStart, "PublisherMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new PublisherMembershipCondition(); else #endif // !FEATURE_PAL goto USEREFLECTION; case 29: // StrongNameMembershipCondition if (String.Compare(className, classNameStart, "StrongNameMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new StrongNameMembershipCondition(); else goto USEREFLECTION; case 39: // ApplicationDirectoryMembershipCondition if (String.Compare(className, classNameStart, "ApplicationDirectoryMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0) return new ApplicationDirectoryMembershipCondition(); else goto USEREFLECTION; default: goto USEREFLECTION; } USEREFLECTION: Type condClass = null; IMembershipCondition cond = null; new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); condClass = GetClassFromElement(el, true); if (condClass == null) return null; if (!(typeof(IMembershipCondition).IsAssignableFrom(condClass))) throw new ArgumentException( Environment.GetResourceString("Argument_NotAMembershipCondition") ); cond = (IMembershipCondition) Activator.CreateInstance(condClass, true); return cond; } #endif //#if FEATURE_CAS_POLICY internal static Type GetClassFromElement (SecurityElement el, bool ignoreTypeLoadFailures) { String className = el.Attribute( "class" ); if (className == null) { if (ignoreTypeLoadFailures) return null; else throw new ArgumentException( String.Format( null, Environment.GetResourceString("Argument_InvalidXMLMissingAttr"), "class") ); } if (ignoreTypeLoadFailures) { try { return Type.GetType(className, false, false); } catch (SecurityException) { return null; } } else return Type.GetType(className, true, false); } public static bool IsPermissionElement (IPermission ip, SecurityElement el) { if (!el.Tag.Equals ("Permission") && !el.Tag.Equals ("IPermission")) return false; return true; } public static bool IsUnrestricted (SecurityElement el) { String sUnrestricted = el.Attribute( "Unrestricted" ); if (sUnrestricted == null) return false; return sUnrestricted.Equals( "true" ) || sUnrestricted.Equals( "TRUE" ) || sUnrestricted.Equals( "True" ); } public static String BitFieldEnumToString( Type type, Object value ) { int iValue = (int)value; if (iValue == 0) return Enum.GetName( type, 0 ); StringBuilder result = StringBuilderCache.Acquire(); bool first = true; int flag = 0x1; for (int i = 1; i < 32; ++i) { if ((flag & iValue) != 0) { String sFlag = Enum.GetName( type, flag ); if (sFlag == null) continue; if (!first) { result.Append( ", " ); } result.Append( sFlag ); first = false; } flag = flag << 1; } return StringBuilderCache.GetStringAndRelease(result); } } }