The Labs \ Source Viewer \ SSCLI \ System.Security \ PermissionTokenFactory

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Security
  16. {
  17.     using System;
  18.     using System.Security.Util;
  19.     using Hashtable = System.Collections.Hashtable;
  20.     using System.Runtime.Remoting.Activation;
  21.     using System.Security.Permissions;
  22.     using System.Reflection;
  23.     using System.Collections;
  24.     using System.Threading;
  25.     using System.Globalization;
  26.    
  27.     [Flags()]
  28.     internal enum PermissionTokenType
  29.     {
  30.         Normal = 1,
  31.         IUnrestricted = 2,
  32.         DontKnow = 4,
  33.         BuiltIn = 8
  34.     }
  35.    
  36.     [Serializable()]
  37.     internal sealed class PermissionTokenKeyComparer : IEqualityComparer
  38.     {
  39.         private Comparer _caseSensitiveComparer;
  40.         private TextInfo _info;
  41.        
  42.         public PermissionTokenKeyComparer(CultureInfo culture)
  43.         {
  44.             _caseSensitiveComparer = new Comparer(culture);
  45.             _info = culture.TextInfo;
  46.         }
  47.        
  48.         public int Compare(object a, object b)
  49.         {
  50.             string strA = a as string;
  51.             string strB = b as string;
  52.            
  53.             // if it's not a string then we just call the object comparer
  54.             if (strA == null || strB == null)
  55.                 return _caseSensitiveComparer.Compare(a, b);
  56.            
  57.             int i = _caseSensitiveComparer.Compare(a, b);
  58.             if (i == 0)
  59.                 return 0;
  60.            
  61.             if (SecurityManager._IsSameType(strA, strB))
  62.                 return 0;
  63.            
  64.             return i;
  65.         }
  66.        
  67.         public new bool Equals(object a, object b)
  68.         {
  69.             if (a == b)
  70.                 return true;
  71.             if (a == null || b == null)
  72.                 return false;
  73.             return Compare(a, b) == 0;
  74.         }
  75.        
  76.         // The data structure consuming this will be responsible for dealing with null objects as keys.
  77.         public int GetHashCode(object obj)
  78.         {
  79.             string str = obj as string;
  80.            
  81.             if (str == null)
  82.                 return obj.GetHashCode();
  83.            
  84.             int iComma = str.IndexOf(',');
  85.             if (iComma == -1)
  86.                 iComma = str.Length;
  87.            
  88.             int accumulator = 0;
  89.             for (int i = 0; i < iComma; ++i) {
  90.                 accumulator = (accumulator << 7) ^ str[i] ^ (accumulator >> 25);
  91.             }
  92.            
  93.             return accumulator;
  94.         }
  95.     }
  96.    
  97.     [Serializable()]
  98.     internal sealed class PermissionToken : ISecurityEncodable
  99.     {
  100.         private static readonly PermissionTokenFactory s_theTokenFactory;
  101.         private static ReflectionPermission s_reflectPerm = null;
  102.         private const string c_mscorlibName = "mscorlib";
  103.        
  104.         internal int m_index;
  105.         internal PermissionTokenType m_type;
  106.         internal string m_strTypeName;
  107.         static internal TokenBasedSet s_tokenSet = new TokenBasedSet();
  108.        
  109.         static internal bool IsMscorlibClassName(string className)
  110.         {
  111.             BCLDebug.Assert(c_mscorlibName == Assembly.GetExecutingAssembly().nGetSimpleName(), "mscorlib name mismatch");
  112.            
  113.             // If the class name does not look like a fully qualified name, we cannot simply determine if it's
  114.             // an mscorlib.dll type so we should return true so the type can be matched with the
  115.             // right index in the TokenBasedSet.
  116.             int index = className.IndexOf(',');
  117.             if (index == -1)
  118.                 return true;
  119.            
  120.             index = className.LastIndexOf(']');
  121.             if (index == -1)
  122.                 index = 0;
  123.            
  124.             // Search for the string 'mscorlib' in the classname. If we find it, we will conservatively assume it's an mscorlib.dll type and load it.
  125.             for (int i = index; i < className.Length; i++) {
  126.                 if (className[i] == 'm' || className[i] == 'M') {
  127.                     if (String.Compare(className, i, c_mscorlibName, 0, c_mscorlibName.Length, StringComparison.OrdinalIgnoreCase) == 0)
  128.                         return true;
  129.                 }
  130.             }
  131.             return false;
  132.         }
  133.        
  134.         static PermissionToken()
  135.         {
  136.             s_theTokenFactory = new PermissionTokenFactory(4);
  137.         }
  138.        
  139.         internal PermissionToken()
  140.         {
  141.         }
  142.        
  143.         internal PermissionToken(int index, PermissionTokenType type, string strTypeName)
  144.         {
  145.             m_index = index;
  146.             m_type = type;
  147.             m_strTypeName = strTypeName;
  148.         }
  149.        
  150.         public static PermissionToken GetToken(Type cls)
  151.         {
  152.             if (cls == null)
  153.                 return null;
  154.            
  155.             if (cls.GetInterface("System.Security.Permissions.IBuiltInPermission") != null) {
  156.                 if (s_reflectPerm == null)
  157.                     s_reflectPerm = new ReflectionPermission(PermissionState.Unrestricted);
  158.                 s_reflectPerm.Assert();
  159.                 MethodInfo method = cls.GetMethod("GetTokenIndex", BindingFlags.Static | BindingFlags.NonPublic);
  160.                 BCLDebug.Assert(method != null, "IBuiltInPermission types should have a static method called 'GetTokenIndex'");
  161.                 return s_theTokenFactory.BuiltInGetToken((int)method.Invoke(null, null), null, cls);
  162.             }
  163.             else {
  164.                 return s_theTokenFactory.GetToken(cls, null);
  165.             }
  166.         }
  167.        
  168.         public static PermissionToken GetToken(IPermission perm)
  169.         {
  170.             if (perm == null)
  171.                 return null;
  172.            
  173.             IBuiltInPermission ibPerm = perm as IBuiltInPermission;
  174.            
  175.             if (ibPerm != null)
  176.                 return s_theTokenFactory.BuiltInGetToken(ibPerm.GetTokenIndex(), perm, null);
  177.             else
  178.                 return s_theTokenFactory.GetToken(perm.GetType(), perm);
  179.         }
  180.        
  181.         public static PermissionToken GetToken(string typeStr)
  182.         {
  183.             return GetToken(typeStr, false);
  184.         }
  185.        
  186.         public static PermissionToken GetToken(string typeStr, bool bCreateMscorlib)
  187.         {
  188.             if (typeStr == null)
  189.                 return null;
  190.            
  191.             if (IsMscorlibClassName(typeStr)) {
  192.                 if (!bCreateMscorlib) {
  193.                     return null;
  194.                 }
  195.                 else {
  196.                     return FindToken(Type.GetType(typeStr));
  197.                 }
  198.             }
  199.             else {
  200.                 PermissionToken token = s_theTokenFactory.GetToken(typeStr);
  201.                 #if _DEBUG
  202.                 new PermissionSet(PermissionState.Unrestricted).Assert();
  203.                 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  204.                 Type type = RuntimeType.PrivateGetType(typeStr.Trim().Replace('\'', '"'), false, false, ref stackMark);
  205.                 BCLDebug.Assert((type == null) || (type.Module.Assembly != System.Reflection.Assembly.GetExecutingAssembly()) || (typeStr.IndexOf("mscorlib", StringComparison.Ordinal) < 0), "We should not go through this path for mscorlib based permissions");
  206.                 #endif
  207.                 return token;
  208.             }
  209.         }
  210.        
  211.         public static PermissionToken FindToken(Type cls)
  212.         {
  213.             if (cls == null)
  214.                 return null;
  215.            
  216.             if (cls.GetInterface("System.Security.Permissions.IBuiltInPermission") != null) {
  217.                 if (s_reflectPerm == null)
  218.                     s_reflectPerm = new ReflectionPermission(PermissionState.Unrestricted);
  219.                 s_reflectPerm.Assert();
  220.                 MethodInfo method = cls.GetMethod("GetTokenIndex", BindingFlags.Static | BindingFlags.NonPublic);
  221.                 BCLDebug.Assert(method != null, "IBuiltInPermission types should have a static method called 'GetTokenIndex'");
  222.                 return s_theTokenFactory.BuiltInGetToken((int)method.Invoke(null, null), null, cls);
  223.             }
  224.             else {
  225.                 return s_theTokenFactory.FindToken(cls);
  226.             }
  227.         }
  228.        
  229.         public static PermissionToken FindTokenByIndex(int i)
  230.         {
  231.             return s_theTokenFactory.FindTokenByIndex(i);
  232.         }
  233.        
  234.         public static bool IsTokenProperlyAssigned(IPermission perm, PermissionToken token)
  235.         {
  236.             PermissionToken heldToken = GetToken(perm);
  237.             if (heldToken.m_index != token.m_index)
  238.                 return false;
  239.            
  240.             if (token.m_type != heldToken.m_type)
  241.                 return false;
  242.            
  243.             if (perm.GetType().Module.Assembly == Assembly.GetExecutingAssembly() && heldToken.m_index >= BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED)
  244.                 return false;
  245.            
  246.             return true;
  247.         }
  248.        
  249.         public SecurityElement ToXml()
  250.         {
  251.             BCLDebug.Assert((m_type & PermissionTokenType.DontKnow) == 0, "Should have valid token type when ToXml is called");
  252.             SecurityElement elRoot = new SecurityElement("PermissionToken");
  253.             if ((m_type & PermissionTokenType.BuiltIn) != 0)
  254.                 elRoot.AddAttribute("Index", "" + this.m_index);
  255.             else
  256.                 elRoot.AddAttribute("Name", SecurityElement.Escape(m_strTypeName));
  257.             elRoot.AddAttribute("Type", m_type.ToString("F"));
  258.             return elRoot;
  259.         }
  260.        
  261.         public void FromXml(SecurityElement elRoot)
  262.         {
  263.             // For the most part there is no parameter checking here since this is an
  264.             // internal class and the serialization/deserialization path is controlled.
  265.            
  266.             if (!elRoot.Tag.Equals("PermissionToken"))
  267.                 BCLDebug.Assert(false, "Tried to deserialize non-PermissionToken element here");
  268.            
  269.             string strName = elRoot.Attribute("Name");
  270.             PermissionToken realToken;
  271.             if (strName != null)
  272.                 realToken = GetToken(strName, true);
  273.             else
  274.                 realToken = FindTokenByIndex(Int32.Parse(elRoot.Attribute("Index"), CultureInfo.InvariantCulture));
  275.            
  276.             this.m_index = realToken.m_index;
  277.             this.m_type = (PermissionTokenType)Enum.Parse(typeof(PermissionTokenType), elRoot.Attribute("Type"));
  278.             BCLDebug.Assert((this.m_type & PermissionTokenType.DontKnow) == 0, "Should have valid token type when FromXml is called.");
  279.             this.m_strTypeName = realToken.m_strTypeName;
  280.         }
  281.     }
  282.    
  283.     // Package access only
  284.     internal class PermissionTokenFactory
  285.     {
  286.         private int m_size;
  287.         private int m_index;
  288.         private Hashtable m_tokenTable;
  289.         // Cache of tokens by class string name
  290.         private Hashtable m_handleTable;
  291.         // Cache of tokens by type handle (IntPtr)
  292.         private Hashtable m_indexTable;
  293.         // Cache of tokens by index
  294.         // We keep an array of tokens for our built-in permissions.
  295.         // This is ordered in terms of unrestricted perms first, normals
  296.         // second. Of course, all the ordering is based on the individual
  297.         // permissions sticking to the deal, so we do some simple boundary
  298.         // checking but mainly leave it to faith.
  299.        
  300.         private PermissionToken[] m_builtIn;
  301.        
  302.         private const string s_unrestrictedPermissionInferfaceName = "System.Security.Permissions.IUnrestrictedPermission";
  303.        
  304.         internal PermissionTokenFactory(int size)
  305.         {
  306.             m_builtIn = new PermissionToken[BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED];
  307.            
  308.             m_size = size;
  309.             m_index = BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED;
  310.             m_tokenTable = null;
  311.             m_handleTable = new Hashtable(size);
  312.             m_indexTable = new Hashtable(size);
  313.         }
  314.        
  315.         internal PermissionToken FindToken(Type cls)
  316.         {
  317.             IntPtr typePtr = cls.TypeHandle.Value;
  318.            
  319.             PermissionToken tok = (PermissionToken)m_handleTable[typePtr];
  320.            
  321.             if (tok != null)
  322.                 return tok;
  323.            
  324.             if (m_tokenTable == null)
  325.                 return null;
  326.            
  327.             tok = (PermissionToken)m_tokenTable[cls.AssemblyQualifiedName];
  328.            
  329.             if (tok != null) {
  330.                 lock (this) {
  331.                     m_handleTable.Add(typePtr, tok);
  332.                 }
  333.             }
  334.            
  335.             return tok;
  336.         }
  337.        
  338.         internal PermissionToken FindTokenByIndex(int i)
  339.         {
  340.             PermissionToken token;
  341.            
  342.             if (i < BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED) {
  343.                 token = BuiltInGetToken(i, null, null);
  344.             }
  345.             else {
  346.                 token = (PermissionToken)m_indexTable[i];
  347.             }
  348.            
  349.             return token;
  350.         }
  351.        
  352.         internal PermissionToken GetToken(Type cls, IPermission perm)
  353.         {
  354.             BCLDebug.Assert(cls != null, "Must pass in valid type");
  355.            
  356.             IntPtr typePtr = cls.TypeHandle.Value;
  357.             object tok = m_handleTable[typePtr];
  358.             if (tok == null) {
  359.                 string typeStr = cls.AssemblyQualifiedName;
  360.                 tok = m_tokenTable != null ? m_tokenTable[typeStr] : null;
  361.                 // Assumes asynchronous lookups are safe
  362.                 if (tok == null) {
  363.                     lock (this) {
  364.                         if (m_tokenTable != null)
  365.                             tok = m_tokenTable[typeStr];
  366.                         else
  367.                             // Make sure it wasn't just added
  368.                             m_tokenTable = new Hashtable(m_size, 1f, new PermissionTokenKeyComparer(CultureInfo.InvariantCulture));
  369.                        
  370.                         if (tok == null) {
  371.                             if (perm != null) {
  372.                                 if (CodeAccessPermission.CanUnrestrictedOverride(perm))
  373.                                     tok = new PermissionToken(m_index++, PermissionTokenType.IUnrestricted, typeStr);
  374.                                 else
  375.                                     tok = new PermissionToken(m_index++, PermissionTokenType.Normal, typeStr);
  376.                             }
  377.                             else {
  378.                                 if (cls.GetInterface(s_unrestrictedPermissionInferfaceName) != null)
  379.                                     tok = new PermissionToken(m_index++, PermissionTokenType.IUnrestricted, typeStr);
  380.                                 else
  381.                                     tok = new PermissionToken(m_index++, PermissionTokenType.Normal, typeStr);
  382.                             }
  383.                             m_tokenTable.Add(typeStr, tok);
  384.                             m_indexTable.Add(m_index - 1, tok);
  385.                             PermissionToken.s_tokenSet.SetItem(((PermissionToken)tok).m_index, tok);
  386.                         }
  387.                        
  388.                         if (!m_handleTable.Contains(typePtr))
  389.                             m_handleTable.Add(typePtr, tok);
  390.                     }
  391.                 }
  392.                 else {
  393.                     lock (this) {
  394.                         if (!m_handleTable.Contains(typePtr))
  395.                             m_handleTable.Add(typePtr, tok);
  396.                     }
  397.                 }
  398.             }
  399.            
  400.             if ((((PermissionToken)tok).m_type & PermissionTokenType.DontKnow) != 0) {
  401.                 if (perm != null) {
  402.                     BCLDebug.Assert(!(perm is IBuiltInPermission), "This should not be called for built-ins");
  403.                     if (CodeAccessPermission.CanUnrestrictedOverride(perm))
  404.                         ((PermissionToken)tok).m_type = PermissionTokenType.IUnrestricted;
  405.                     else
  406.                         ((PermissionToken)tok).m_type = PermissionTokenType.Normal;
  407.                     ((PermissionToken)tok).m_strTypeName = perm.GetType().AssemblyQualifiedName;
  408.                 }
  409.                 else {
  410.                     BCLDebug.Assert(cls.GetInterface("System.Security.Permissions.IBuiltInPermission") == null, "This shoudl not be called for built-ins");
  411.                     if (cls.GetInterface(s_unrestrictedPermissionInferfaceName) != null)
  412.                         ((PermissionToken)tok).m_type = PermissionTokenType.IUnrestricted;
  413.                     else
  414.                         ((PermissionToken)tok).m_type = PermissionTokenType.Normal;
  415.                     ((PermissionToken)tok).m_strTypeName = cls.AssemblyQualifiedName;
  416.                 }
  417.             }
  418.            
  419.             return (PermissionToken)tok;
  420.         }
  421.        
  422.         internal PermissionToken GetToken(string typeStr)
  423.         {
  424.             object tok = null;
  425.             tok = m_tokenTable != null ? m_tokenTable[typeStr] : null;
  426.             // Assumes asynchronous lookups are safe
  427.             if (tok == null) {
  428.                 lock (this) {
  429.                     if (m_tokenTable != null)
  430.                         tok = m_tokenTable[typeStr];
  431.                     else
  432.                         // Make sure it wasn't just added
  433.                         m_tokenTable = new Hashtable(m_size, 1f, new PermissionTokenKeyComparer(CultureInfo.InvariantCulture));
  434.                    
  435.                     if (tok == null) {
  436.                         tok = new PermissionToken(m_index++, PermissionTokenType.DontKnow, typeStr);
  437.                         m_tokenTable.Add(typeStr, tok);
  438.                         m_indexTable.Add(m_index - 1, tok);
  439.                         PermissionToken.s_tokenSet.SetItem(((PermissionToken)tok).m_index, tok);
  440.                     }
  441.                 }
  442.             }
  443.            
  444.             return (PermissionToken)tok;
  445.         }
  446.        
  447.         internal PermissionToken BuiltInGetToken(int index, IPermission perm, Type cls)
  448.         {
  449.             PermissionToken token = m_builtIn[index];
  450.            
  451.             if (token == null) {
  452.                 lock (this) {
  453.                     token = m_builtIn[index];
  454.                    
  455.                     if (token == null) {
  456.                         PermissionTokenType permType = PermissionTokenType.DontKnow;
  457.                        
  458.                         if (perm != null) {
  459.                             if (CodeAccessSecurityEngine.DoesFullTrustMeanFullTrust() || perm is IUnrestrictedPermission)
  460.                                 permType = PermissionTokenType.IUnrestricted;
  461.                             else
  462.                                 permType = PermissionTokenType.Normal;
  463.                         }
  464.                         else if (cls != null) {
  465.                             if (CodeAccessSecurityEngine.DoesFullTrustMeanFullTrust() || cls.GetInterface("System.Security.Permissions.IUnrestrictedPermission") != null)
  466.                                 permType = PermissionTokenType.IUnrestricted;
  467.                             else
  468.                                 permType = PermissionTokenType.Normal;
  469.                         }
  470.                        
  471.                         token = new PermissionToken(index, permType | PermissionTokenType.BuiltIn, null);
  472.                         m_builtIn[index] = token;
  473.                         PermissionToken.s_tokenSet.SetItem(token.m_index, token);
  474.                     }
  475.                 }
  476.             }
  477.            
  478.             if ((token.m_type & PermissionTokenType.DontKnow) != 0) {
  479.                 token.m_type = PermissionTokenType.BuiltIn;
  480.                
  481.                 if (perm != null) {
  482.                     if (CodeAccessSecurityEngine.DoesFullTrustMeanFullTrust() || perm is IUnrestrictedPermission)
  483.                         token.m_type |= PermissionTokenType.IUnrestricted;
  484.                     else
  485.                         token.m_type |= PermissionTokenType.Normal;
  486.                 }
  487.                 else if (cls != null) {
  488.                     if (CodeAccessSecurityEngine.DoesFullTrustMeanFullTrust() || cls.GetInterface("System.Security.Permissions.IUnrestrictedPermission") != null)
  489.                         token.m_type |= PermissionTokenType.IUnrestricted;
  490.                     else
  491.                         token.m_type |= PermissionTokenType.Normal;
  492.                 }
  493.                 else
  494.                     token.m_type |= PermissionTokenType.DontKnow;
  495.             }
  496.            
  497.             return token;
  498.         }
  499.     }
  500. }

Developer Fusion