Merge pull request #1179 from ludovic-henry/pr25-threadpool
[mono.git] / mcs / class / System.Web / System.Web.Security / RolePrincipal.cs
index 78d3381afebd95a438e80ab828c6ea0ec3e736ea..b210f8274765a079709791812c9a109135b0eadc 100644 (file)
@@ -6,7 +6,7 @@
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2003 Ben Maurer
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
-
 using System.Collections.Specialized;
 using System.Security.Permissions;
 using System.Security.Principal;
+using System.Web.Configuration;
+using System.Web.Util;
+using System.IO;
+using System.Text;
 
 namespace System.Web.Security {
 
        [Serializable]
        [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
-       public sealed class RolePrincipal : IPrincipal {
+#if NET_4_0
+       public
+#else
+       public sealed
+#endif
+       class RolePrincipal : IPrincipal {
+
+               IIdentity _identity;
+               bool _listChanged;
+               string[] _cachedArray;
+               HybridDictionary _cachedRoles;
+               readonly string _providerName;
+
+               int _version = 1;
+               string _cookiePath;
+               DateTime _issueDate;
+               DateTime _expireDate;
 
-               private IIdentity identity;
-               private bool listChanged;
-               string[] cachedArray;
-               private HybridDictionary cachedRoles;
-               readonly string providerName;
 
                public RolePrincipal (IIdentity identity)
                {
                        if (identity == null)
                                throw new ArgumentNullException ("identity");
-                       this.identity = identity;
+                       
+                       this._identity = identity;
+                       this._cookiePath = RoleManagerConfig.CookiePath;
+                       this._issueDate = DateTime.Now;
+                       this._expireDate = _issueDate.Add (RoleManagerConfig.CookieTimeout);
                }
 
-               [MonoTODO ("Not implemented")]
                public RolePrincipal (IIdentity identity, string encryptedTicket)
                        : this (identity)
                {
-                       throw new NotImplementedException ();
+                       DecryptTicket (encryptedTicket);
                }
 
                public RolePrincipal (string providerName, IIdentity identity)
@@ -66,109 +82,219 @@ namespace System.Web.Security {
                        if (providerName == null)
                                throw new ArgumentNullException ("providerName");
 
-                       this.providerName = providerName;
+                       this._providerName = providerName;
                }
 
-               [MonoTODO ("Not implemented")]
                public RolePrincipal (string providerName, IIdentity identity, string encryptedTicket)
-                       : this (identity)
+                       : this (providerName, identity)
                {
-                       if (providerName == null)
-                               throw new ArgumentNullException ("providerName");
-
-                       this.providerName = providerName;
-
-                       throw new NotImplementedException ();
+                       DecryptTicket (encryptedTicket);
                }
 
                public string [] GetRoles ()
                {
-                       if (!identity.IsAuthenticated)
+                       if (!_identity.IsAuthenticated)
                                return new string[0];
 
-                       if (cachedRoles == null) {
-                               cachedArray = Provider.GetRolesForUser (identity.Name);
-                               cachedRoles = new HybridDictionary (true);
+                       if (!IsRoleListCached || Expired) {
+                               _cachedArray = Provider.GetRolesForUser (_identity.Name);
+                               _cachedRoles = new HybridDictionary (true);
 
-                               foreach (string r in cachedArray)
-                                       cachedRoles.Add(r, r);
+                               foreach (string r in _cachedArray)
+                                       _cachedRoles.Add(r, r);
+
+                               _listChanged = true;
                        }
 
-                       return cachedArray;
+                       return _cachedArray;
                }
                
                public bool IsInRole (string role)
                {
-                       if (!identity.IsAuthenticated)
+                       if (!_identity.IsAuthenticated)
                                return false;
 
                        GetRoles ();
 
-                       return cachedRoles[role] != null;
+                       return _cachedRoles [role] != null;
                }
                
-               [MonoTODO ("Not implemented")]
                public string ToEncryptedTicket ()
                {
-                       throw new NotImplementedException ();
-               }
+                       string roles = string.Join (",", GetRoles ());
+                       string cookiePath = RoleManagerConfig.CookiePath;
+                       int approxTicketLen = roles.Length + cookiePath.Length + 64;
+
+                       if (_cachedArray.Length > Roles.MaxCachedResults)
+                              return null;
+
+                       MemoryStream ticket = new MemoryStream (approxTicketLen);
+                       BinaryWriter writer = new BinaryWriter (ticket);
+
+                       // version
+                       writer.Write (Version);
                
+                       // issue datetime
+                       DateTime issueDate = DateTime.Now;
+                       writer.Write (issueDate.Ticks);
+
+                       // expiration datetime
+                       writer.Write (_expireDate.Ticks);
+
+                       writer.Write (cookiePath);
+                       writer.Write (roles);
+
+                       CookieProtection cookieProtection = RoleManagerConfig.CookieProtection;
+
+                       byte[] ticket_data = ticket.GetBuffer ();
+                       if (cookieProtection == CookieProtection.All) {
+                               ticket_data = MachineKeySectionUtils.EncryptSign (MachineConfig, ticket_data);
+                       } else if (cookieProtection == CookieProtection.Encryption) {
+                               ticket_data = MachineKeySectionUtils.Encrypt (MachineConfig, ticket_data);
+                       } else if (cookieProtection == CookieProtection.Validation) {
+                               ticket_data = MachineKeySectionUtils.Sign (MachineConfig, ticket_data);
+                       }
+
+                       return GetBase64FromBytes (ticket_data, 0, ticket_data.Length);
+               }
+
+               void DecryptTicket (string encryptedTicket)
+               {
+                       if (encryptedTicket == null || encryptedTicket == String.Empty)
+                               throw new ArgumentException ("Invalid encrypted ticket", "encryptedTicket");
+
+                       byte [] ticketBytes = GetBytesFromBase64 (encryptedTicket);
+                       byte [] decryptedTicketBytes = null;
+
+                       CookieProtection cookieProtection = RoleManagerConfig.CookieProtection;
+
+                       if (cookieProtection == CookieProtection.All) {
+                               decryptedTicketBytes = MachineKeySectionUtils.VerifyDecrypt (MachineConfig, ticketBytes);
+                       } else if (cookieProtection == CookieProtection.Encryption) {
+                               decryptedTicketBytes = MachineKeySectionUtils.Decrypt (MachineConfig, ticketBytes);
+                       } else if (cookieProtection == CookieProtection.Validation) {
+                               decryptedTicketBytes = MachineKeySectionUtils.Verify (MachineConfig, ticketBytes);
+                       }
+
+                       if (decryptedTicketBytes == null)
+                               throw new HttpException ("ticket validation failed");
+
+                       MemoryStream ticket = new MemoryStream (decryptedTicketBytes);
+                       BinaryReader reader = new BinaryReader (ticket);
+
+                       // version
+                       _version = reader.ReadInt32 ();
+
+                       // issued date
+                       _issueDate = new DateTime (reader.ReadInt64 ());
+
+                       // expire date
+                       _expireDate = new DateTime (reader.ReadInt64 ());
+
+                       // cookie path
+                       _cookiePath = reader.ReadString ();
+                       
+                       // roles
+                       string roles = reader.ReadString ();
+
+                       if (!Expired) {
+                               InitializeRoles (roles);
+                               //update ticket if less than half of CookieTimeout remaining.
+                               if (Roles.CookieSlidingExpiration){
+                                       if (_expireDate-DateTime.Now < TimeSpan.FromTicks (RoleManagerConfig.CookieTimeout.Ticks/2))    {
+                                               _issueDate = DateTime.Now;
+                                               _expireDate = DateTime.Now.Add (RoleManagerConfig.CookieTimeout);
+                                               SetDirty ();
+                                       }
+                               }
+                       } else {
+                               // issue a new ticket
+                               _issueDate = DateTime.Now;
+                               _expireDate = _issueDate.Add (RoleManagerConfig.CookieTimeout);
+                       }
+               }
+
+               void InitializeRoles (string decryptedRoles)
+               {
+                       _cachedArray = decryptedRoles.Split (',');
+                       _cachedRoles = new HybridDictionary (true);
+
+                       foreach (string r in _cachedArray)
+                               _cachedRoles.Add (r, r);
+               }
+
                public bool CachedListChanged {
-                       get { return listChanged; }
+                       get { return _listChanged; }
                }
                
-               [MonoTODO ("Not implemented")]
                public string CookiePath {
-                       get { throw new NotImplementedException (); }
+                       get { return _cookiePath; }
                }
                
-               [MonoTODO ("Not implemented")]
                public bool Expired {
-                       get { throw new NotImplementedException (); }
+                       get { return ExpireDate < DateTime.Now; }
                }
                
-               [MonoTODO ("Not implemented")]
                public DateTime ExpireDate {
-                       get { throw new NotImplementedException (); }
+                       get { return _expireDate; }
                }
                
                public IIdentity Identity {
-                       get { return identity; }
+                       get { return _identity; }
                }
                
                public bool IsRoleListCached {
-                       get { return cachedRoles != null; }
+                       get { return (_cachedRoles != null) && RoleManagerConfig.CacheRolesInCookie; }
                }
                
-               [MonoTODO ("Not implemented")]
                public DateTime IssueDate {
-                       get { throw new NotImplementedException (); }
+                       get { return _issueDate; }
                }
                
                public string ProviderName {
-                       get { return String.IsNullOrEmpty(providerName) ? Provider.Name : providerName; }
+                       get { return String.IsNullOrEmpty(_providerName) ? Provider.Name : _providerName; }
                }
                
                public int Version {
-                       get { return 1; }
+                       get { return _version; }
                }
 
                RoleProvider Provider {
                        get {
-                               if (String.IsNullOrEmpty(providerName))
+                               if (String.IsNullOrEmpty (_providerName))
                                        return Roles.Provider;
 
-                               return Roles.Providers [providerName];
+                               return Roles.Providers [_providerName];
                        }
                }
 
                public void SetDirty ()
                {
-                       listChanged = true;
-                       cachedRoles = null;
-                       cachedArray = null;
+                       _listChanged = true;
+                       _cachedRoles = null;
+                       _cachedArray = null;
+               }
+
+               static string GetBase64FromBytes (byte [] bytes, int offset, int len)
+               {
+                       return Convert.ToBase64String (bytes, offset, len);
+               }
+
+               static byte [] GetBytesFromBase64 (string base64String)
+               {
+                       return Convert.FromBase64String (base64String);
+               }
+
+               RoleManagerSection RoleManagerConfig
+               {
+                       get { return (RoleManagerSection) WebConfigurationManager.GetSection ("system.web/roleManager"); }
+               }
+
+               MachineKeySection MachineConfig
+               {
+                       get { return (MachineKeySection) WebConfigurationManager.GetSection ("system.web/machineKey"); }
                }
        }
 }
-#endif
+