Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / RightsManagementProvider.cs / 1 / RightsManagementProvider.cs
//------------------------------------------------------------------------------ //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // RightsManagementProvider. // // History: // 06/10/05 - [....] created //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.IO.Packaging; using System.Security; using System.Security.Permissions; using System.Security.RightsManagement; using System.Windows.TrustUI; using MS.Internal.Documents.Application; using MS.Internal.Permissions; using MS.Internal.PresentationUI; using MS.Internal.WindowsBase; // for SecurityHelper using Microsoft.Win32; namespace MS.Internal.Documents { ////// RightsManagementProvider is used to connect DRP to RM APIs /// ////// This class is a facade for the RM APIs. It is the model between the Manager /// and the EncryptedPackageEnvelope and System.Security.RightsManagement classes. /// internal class RightsManagementProvider : IRightsManagementProvider, IDisposable { #region Constructors //------------------------------------------------------------------------- // Constructors //------------------------------------------------------------------------- ////// A constructor that takes an encrypted package. This /// can be null /// <The encrypted package /// ////// Critical /// 1) Sets _encryptedPackage that is marked SecurityCritical. /// [MS.Internal.PresentationUI.FriendAccessAllowed] [SecurityCritical] public RightsManagementProvider(EncryptedPackageEnvelope encryptedPackage) { _encryptedPackageEnvelope = encryptedPackage; } #endregion Constructors #region IRightsManagementProvider //-------------------------------------------------------------------------- // IRightsManagementProvider //------------------------------------------------------------------------- ////// Is the XPS document RM-protected? /// ////// Critical /// 1) Accesses critical data CurrentPublishLicense /// TreatAsSafe /// 1) Does not leak critical data /// bool IRightsManagementProvider.IsProtected { [SecurityCritical, SecurityTreatAsSafe] get { InitializeMembers(); return (CurrentPublishLicense != null); } } ////// Gets the rights granted in the current use license. /// ////// The caller cannot modify the contents of this license because the /// setters on the RightsManagementLicense class are SecurityCritical. /// RightsManagementLicense IRightsManagementProvider.CurrentUseLicense { get { return _rmUseLicense.Value; } } ////// Gets or sets the publish license associated with the current package. /// Setting the current publish license invalidates any saved use licenses. /// ////// Critical /// 1) Accessing SecurityCritical data _newPublishLicense /// 2) Sets critical for set _useLicense and _rmUseLicense to known safe /// value null /// PublishLicense IRightsManagementProvider.CurrentPublishLicense { [SecurityCritical] get { return _currentPublishLicense; } [SecurityCritical] set { _currentPublishLicense = value; // Invalidate the saved use license and grants _useLicense.Value = null; _rmUseLicense.Value = null; } } ////// Gets the currently active user. /// ////// Critical /// 1) Exposes critical data (the currently active user) /// RightsManagementUser IRightsManagementProvider.CurrentUser { [SecurityCritical] get { return _user.Value; } } ////// Enrolls a new user and sets up the secure environment. /// /// The account type to use to initialize the /// secure environment ////// Critical /// 1) Accessing GetApplicationManifest which is critical /// 2) Asserts for RightsManagementPermission to call /// SecureEnvironment.Create /// 3) Sets SecurityCriticalDataForSet variable _secureEnvironment /// TreatAsSafe /// 1) Data into assert is critical or generated locally. Data coming out /// of the assert is _secureEnvironment, and all methods on instances /// of SecureEnvironment require assert. /// 2) The new value is generated using static method /// SecureEnvironment.Create using return value GetApplicationManifest() which is /// critical (as well as 2 enums which are determined locally). /// [SecurityCritical, SecurityTreatAsSafe] void IRightsManagementProvider.InitializeEnvironment(EnrollmentAccountType accountType) { InitializeMembers(); CleanUpSecureEnvironment(); try { AuthenticationType authType; UserActivationMode userActMode; switch (accountType) { case (EnrollmentAccountType.Network): { authType = AuthenticationType.Windows; userActMode = UserActivationMode.Permanent; break; } case (EnrollmentAccountType.Temporary): { authType = AuthenticationType.Windows; userActMode = UserActivationMode.Temporary; break; } case (EnrollmentAccountType.NET): { authType = AuthenticationType.Passport; userActMode = UserActivationMode.Permanent; break; } default: { throw new NotSupportedException(); } } _rmPermission.Assert(); // BlessedAssert try { _secureEnvironment.Value = SecureEnvironment.Create( GetApplicationManifest(), authType, userActMode); } finally { RightsManagementPermission.RevertAssert(); } } // If the secure environment initialization fails, or the AccountType is // set incorrectly, we need to clean out the SecureEnvironment. catch { CleanUpSecureEnvironment(); throw; } Trace.SafeWrite( Trace.Rights, "SecureEnvironment was initialized as part of enrollment."); SetUserFromSecureEnvironment(); } ////// Sets up the secure environment for a particular user. /// /// The user for whom to set up the environment. ////// Critical /// 1) Accesses GetApplicationManifest which is critical. /// 2) Asserts for RightsManagementPermission to call /// SecureEnvironment.Create. /// 3) Sets SecurityCriticalDataForSet _secureEnvironment /// [SecurityCritical] void IRightsManagementProvider.InitializeEnvironment(RightsManagementUser user) { InitializeMembers(); CleanUpSecureEnvironment(); _rmPermission.Assert(); // BlessedAssert try { _secureEnvironment.Value = SecureEnvironment.Create( GetApplicationManifest(), user); } finally { RightsManagementPermission.RevertAssert(); } Trace.SafeWriteIf( (_secureEnvironment.Value != null), Trace.Rights, "SecureEnvironment was initialized for a specific user."); SetUserFromSecureEnvironment(); } ////// Loads a use license for the user from the package. /// This requires InitializeEnvironment to have been called. /// ///Whether or not a use license could be loaded directly from the /// package ////// Critical /// 1) Asserts for EnvelopePermissionSet to load a use license from the /// encrypted package envelope /// 2) Sets the critical value _useLicense from a UseLicense /// TreatAsSafe /// 1) Data into elevation is critical for set. /// 2) The use license is loaded from critical data for set /// _encryptedPackage and is based on critical data for set _user. /// [SecurityCritical, SecurityTreatAsSafe] bool IRightsManagementProvider.LoadUseLicense() { if (!IsProtected) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoPackageToDecrypt)); } UseLicense useLicense; SecurityHelper.EnvelopePermissionSet.Assert(); // BlessedAssert try { useLicense = _encryptedPackageEnvelope .RightsManagementInformation.LoadUseLicense(_user.Value); } finally { CodeAccessPermission.RevertAll(); } if (useLicense != null) { Trace.SafeWrite(Trace.Rights, "Existing use license was found."); _useLicense.Value = useLicense; } return (useLicense != null); } ////// Acquires a use license for the package. /// This requires InitializeEnvironment to have been called. /// ///Whether or not a use license could be acquired ////// Critical /// 1) Asserts for RightsManagementPermission to call AcquireUseLicense /// 2) Asserts for RightsManagementPermission to call SaveUseLicense /// 3) Accesses critical data CurrentPublishLicense /// 4) Sets the critical data _useLicense from the result from the /// AcquireUseLicense call /// /// TreatAsSafe /// 1) Data into elevation is critical for set or returned from a critical /// property. /// 2) Data into elevation is critical for set. /// 3) Does not leak the publish license. /// 4) Result is from the RM API and is derived from critical data /// [SecurityCritical, SecurityTreatAsSafe] bool IRightsManagementProvider.AcquireUseLicense() { if (!IsProtected) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoPackageToDecrypt)); } UseLicense useLicense = null; RightsManagementException rmException = null; _rmPermission.Assert(); // BlessedAssert try { useLicense = CurrentPublishLicense.AcquireUseLicense(_secureEnvironment.Value); } catch(RightsManagementException e) { rmException = e; } finally { RightsManagementPermission.RevertAssert(); } if (useLicense != null) { Trace.SafeWrite(Trace.Rights, "A new use license was acquired."); _useLicense.Value = useLicense; } else { Trace.SafeWrite( Trace.Rights, "New use license acquisition failed: {0}", rmException.Message); } return (useLicense != null); } ////// Saves the current use license and embeds it in the package. /// This requires a use license to have been acquired. /// ////// Critical /// 1) Asserts for EnvelopePermissionSet in order to save the use license /// to a package passed in as an argument /// [SecurityCritical] void IRightsManagementProvider.SaveUseLicense(EncryptedPackageEnvelope package) { if (!IsProtected) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoPackageToDecrypt)); } if (_useLicense.Value == null) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoUseLicense)); } if (AllowLicenseCaching) { Trace.SafeWrite(Trace.Rights, "Writing Use License to package."); // Attempt to write the acquired license back to the package if (package.FileOpenAccess != FileAccess.Read) { SecurityHelper.EnvelopePermissionSet.Assert(); // BlessedAssert try { package.RightsManagementInformation. SaveUseLicense(_user.Value, _useLicense.Value); } finally { CodeAccessPermission.RevertAll(); } } } else { Trace.SafeWrite(Trace.Rights, "NOLICCACHE is set, not writing Use License to package."); } } ////// Binds the use license to the secure environment. This sets the /// CurrentUseLicense property to the appropriate value. /// This requires the use license to be set beforehand. /// ////// Critical /// 1) Calls critical function GenerateCryptoProvider /// 2) Asserts for RightsManagementPermission to get bound grants from the /// CryptoProvider and set the CryptoProvider in the encrypted package /// 3) Modifies CriticalDataForSet _encryptedPackage /// 4) Calls critical function ConvertGrantList /// 5) Sets the SecurityCriticalDataForSet object _rmLicense by converting /// the UseLicense and bound grants. /// 6) Accesses critical property CurrentPublishLicense /// 7) Asserts for RightsManagementPermission to decrypt the publish /// license. /// 8) Modifies CriticalDataForSet _unsignedPublishLicense /// /// TreatAsSafe /// 1) The CryptoProvider is not leaked; it is only saved in /// _encryptedPackage, which is critical for get. /// 2) Data into and out of elevation is critical for set or not leaked /// outside this function. The grants are available indirectly through /// the CurrentUseLicense property, but they are not considered /// critical in this context. /// 3) The CryptoProvider set in _encryptedPackage is retrieved from /// critical function GenerateCryptoProvider. /// 4) The values passed in to the critical function come from critical /// for set member fields _user and _useLicense and the bound grants /// come from a CryptoProvider which comes from a critical call. The /// result of the call is a RightsManagementLicense object, from which /// it is not possible to get any critical information (chiefly the /// user name) without calling critical code. /// 5) The data comes from critical function ConvertGrantList. /// 6) The publish license is not saved or leaked, and the operation is /// performed only if the current user is guaranteed to be the owner /// of the document. /// 7) The publish license is decrypted only if the user is the owner of /// the document. Also, it is impossible to get any information out of /// the saved unsigned publish license without asserting for the /// RightsManagementPermission. /// 8) The unsigned license is saved only if the user is the owner of the /// document and is set from a call made under an assert. /// /// [SecurityCritical, SecurityTreatAsSafe] void IRightsManagementProvider.BindUseLicense() { if (!IsProtected) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoPackageToDecrypt)); } if (_useLicense.Value == null) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoUseLicense)); } // If a CryptoProvider is already set in the EncryptedPackageEnvelope, // we can't set it again. As a result we should use the existing one if // possible. CryptoProvider cryptoProvider = null; ReadOnlyCollectiongrants = null; _rmPermission.Assert(); // BlessedAssert try { cryptoProvider = _encryptedPackageEnvelope.RightsManagementInformation.CryptoProvider; if (cryptoProvider != null) { grants = cryptoProvider.BoundGrants; } } finally { RightsManagementPermission.RevertAssert(); } // If there is no CryptoProvider set in the envelope, we need to create // one and associate it with the envelope now if (cryptoProvider == null) { cryptoProvider = GenerateCryptoProvider(); _rmPermission.Assert(); // BlessedAssert try { grants = cryptoProvider.BoundGrants; _encryptedPackageEnvelope.RightsManagementInformation.CryptoProvider = cryptoProvider; } finally { RightsManagementPermission.RevertAssert(); } } // Create our RM license object using the grants retrieved from the // CryptoProvider Invariant.Assert( grants != null, "CryptoProvider had no bound grants."); _rmUseLicense.Value = ConvertGrantList(_user.Value, grants); // If possible use the CryptoProvider to decrypt the publish license if (HasPermission( _rmUseLicense.Value, RightsManagementPermissions.AllowOwner)) { _rmPermission.Assert(); // BlessedAssert try { _unsignedPublishLicense.Value = CurrentPublishLicense.DecryptUnsignedPublishLicense( cryptoProvider); } finally { RightsManagementPermission.RevertAssert(); } Trace.SafeWrite( Trace.Rights, "Publish license was decrypted."); } } /// /// Gets a list of all credentials available to the current user. /// ///A list of all available credentials ////// Critical /// 1) Asserts for RightsManagementPermission to call /// SecureEnvironment.GetActivatedUsers() /// 2) Calls SecurityCritical function CreateUser to create /// RightsManagementUser objects from RightsManagementUser objects returned from /// the RM APIs. /// [SecurityCritical] ReadOnlyCollectionIRightsManagementProvider.GetAvailableCredentials() { ReadOnlyCollection users; _rmPermission.Assert(); // BlessedAssert try { users = SecureEnvironment.GetActivatedUsers(); } finally { RightsManagementPermission.RevertAssert(); } List rmUsers = new List (users.Count); foreach (ContentUser user in users) { rmUsers.Add(RightsManagementUser.CreateUser(user)); } return new ReadOnlyCollection (rmUsers); } /// /// Gets the default credentials. /// ///Default credentials ////// Critical /// 1) Calls critical code RightsManagementProvider.GetAvailableCredentials /// and treating User as critical data. /// 2) Asserts for RegistryPermission to read default credentials from /// registry. Registry keys and values to access are private const /// strings. /// 3) Calls SecurityCritical RightsManagementUser.CreateUser function /// with data retrieved from the registry. /// [SecurityCritical] RightsManagementUser IRightsManagementProvider.GetDefaultCredentials() { RightsManagementUser defaultUser = null; string defaultUserName = null; int defaultAccountType = -1; //invalid account ReadOnlyCollectionusers = ((IRightsManagementProvider)this).GetAvailableCredentials(); (new RegistryPermission( RegistryPermissionAccess.Read, _registryBaseForXpsViewer)) .Assert(); // BlessedAssert try { using (RegistryKey defaultRMKey = Registry.CurrentUser.OpenSubKey( _registryLocationForDefaultUser)) { if (defaultRMKey != null) { // Get account name and validate it as a string. object keyValue = defaultRMKey.GetValue(_registryValueNameForAccountName); if ((keyValue != null) && (defaultRMKey.GetValueKind(_registryValueNameForAccountName) == RegistryValueKind.String)) { defaultUserName = (string)keyValue; } // Get account type and validate it as an int. keyValue = defaultRMKey.GetValue(_registryValueNameForAccountType); if ((keyValue != null) && (defaultRMKey.GetValueKind(_registryValueNameForAccountType) == RegistryValueKind.DWord)) { defaultAccountType = (int)keyValue; } } } } finally { RegistryPermission.RevertAssert(); } //lets match up the user/type string with an actual avalable user if ((users.Count > 0) && (defaultUserName != null)) { RightsManagementUser user = RightsManagementUser.CreateUser( defaultUserName, (AuthenticationType)defaultAccountType); int index = users.IndexOf(user); //Did we find the new default user in our Available users? if (index != -1) { defaultUser = users[index]; } } if ((defaultUser == null) && (users.Count > 0)) { //If we get here then default doesn't match any available users. //Select first user as default. defaultUser = users[0]; } return defaultUser; } /// /// Sets the default credentials. /// ////// Critical /// 1) Calls critical code RightsManagementProvider.GetAvailableCredentials /// but data retrieved is only saved locally and not leaked. /// 2) Asserts for RegistryPermission to set default credentials in /// registry. Registry keys and values to access are private const /// strings, but data set in the registry comes from an argument to the /// function. /// 3) Accesses Critical properties on RightsManagementUser objects, but /// does not leak them; the function only saves them in the registry. /// [SecurityCritical] void IRightsManagementProvider.SetDefaultCredentials(RightsManagementUser user) { if (user == null) { throw new ArgumentNullException("user"); } //Get AvailableCreds list so we can match new default user. ReadOnlyCollectionusers = ((IRightsManagementProvider)this).GetAvailableCredentials(); int index = users.IndexOf(user); //Did we find the new default user in our Available users? //If not, doesn't save to registry. if (index != -1) { string defaultUserName = users[index].Name; int defaultAccountType = (int)users[index].AuthenticationType; (new RegistryPermission( RegistryPermissionAccess.AllAccess, _registryBaseForXpsViewer)) .Assert(); //BlessedAssert try { using (RegistryKey defaultRMKey = Registry.CurrentUser.CreateSubKey( _registryLocationForDefaultUser)) { if (defaultRMKey != null) { defaultRMKey.SetValue( _registryValueNameForAccountName, defaultUserName); defaultRMKey.SetValue( _registryValueNameForAccountType, defaultAccountType); } } } finally { RegistryPermission.RevertAssert(); } } } /// /// Removes user from available credentials. /// ////// Critical /// 1) Elevation to remove RM user account. /// [SecurityCritical] void IRightsManagementProvider.RemoveCredentials(RightsManagementUser user) { if (user == null) { throw new ArgumentNullException("user"); } _rmPermission.Assert(); // BlessedAssert try { SecureEnvironment.RemoveActivatedUser(user); } finally { RightsManagementPermission.RevertAssert(); } } ////// Gets a dictionary of all users and grants stored in the package. /// ///All the users and licenses in the package, keyed by User. /// ////// Critical /// 1) Sets SecurityCriticalForSet rights dictionary. /// 2) Returns personally identifiable information in rights dictionary /// (e-mail addresses of all users who have rights to the document). /// 3) Asserts for RightsManagementPermission to get user objects from /// ContentGrant objects. /// 4) Asserts for RightsManagementPermission to get the owner of the /// unsigned license. /// 5) Calls SecurityCritical function CreateGrant to create a grant for /// the owner. /// 6) Calls (several times) RightsManagementUser.CreateUser with a /// ContentUser object as an argument /// 7) Calls critical function ConvertGrantList to convert the list of /// grants retrieved from the unsigned publish license. /// TreatAsSafe /// 1) Data for rights dictionary comes from either the publish license /// or the unsigned publish license, both of which are critical for /// set objects. /// 2) The personally identifiable information in RightsManagementUser /// objects can only be accessed from critical code. /// 3) The only critical information retrieved from under this assert is /// the user's e-mail address, which is not accessible as described in /// #2 above. /// 4) The only critical information retrieved from under this assert is /// the owner's e-mail address, which is not accessible as described in /// #2 above. /// 5) The arguments to the CreateGrant function are the user and the /// Owner right. The user being given the Owner grant is the owner user /// retrieved from the critical for set unsigned license under an /// assert, so it is OK to create a grant for this user. /// 6) The ContentUser objects always come from information loaded from /// the critical for set unsigned publish license. /// 7) All data into the critical function comes from the unsigned publish /// license. The data retrieved only contains one piece of critical /// information, the user name, and this is can only be accessed by /// critical code. /// [SecurityCritical, SecurityTreatAsSafe] IDictionaryIRightsManagementProvider.GetAllAccessRights() { if (IsProtected && _rightsDictionary.Value == null && _rmUseLicense.Value != null && _rmUseLicense.Value.HasPermission(RightsManagementPermissions.AllowOwner) && _unsignedPublishLicense.Value != null) { UnsignedPublishLicense unsignedLicense = _unsignedPublishLicense.Value; IDictionary > grantDictionary = new Dictionary >(); // Add all the grants from the unsigned license to the dictionary foreach (ContentGrant grant in GetGrantsFromUnsignedLicense(unsignedLicense)) { ContentUser contentUser = null; _rmPermission.Assert(); //BlessedAssert try { contentUser = grant.User; } finally { RightsManagementPermission.RevertAssert(); } RightsManagementUser user = RightsManagementUser.CreateUser(contentUser); if (!grantDictionary.ContainsKey(user)) { grantDictionary[user] = new List (); } grantDictionary[user].Add(grant); } ContentUser contentUserOwner = null; _rmPermission.Assert(); //BlessedAssert try { contentUserOwner = unsignedLicense.Owner; } finally { RightsManagementPermission.RevertAssert(); } RightsManagementUser owner = RightsManagementUser.CreateUser(contentUserOwner); // Add a grant for the owner of the document to the dictionary if (!grantDictionary.ContainsKey(owner)) { grantDictionary[owner] = new List (1); } ContentGrant ownerGrant = CreateGrant( owner, ContentRight.Owner, DateTime.MinValue, DateTime.MaxValue); grantDictionary[owner].Add(ownerGrant); // Convert the grant dictionary to a dictionary of licenses IDictionary dictionary = new Dictionary ( grantDictionary.Count); foreach (RightsManagementUser user in grantDictionary.Keys) { RightsManagementLicense currentLicense = ConvertGrantList(user, grantDictionary[user]); dictionary[user] = currentLicense; } _rightsDictionary.Value = (IDictionary )dictionary; } return _rightsDictionary.Value; } /// /// Decrypt the encrypted package into a metro stream. /// ////// Critical /// 1) Asserts for EnvelopePermissionSet to get a decrypted stream from /// the encrypted package. /// TreatAsSafe /// 1) Data into assert is critical for set. The operation of decrypting /// the package is critical, but the decrypted stream is not critical. /// [SecurityCritical, SecurityTreatAsSafe] Stream IRightsManagementProvider.DecryptPackage() { if (_encryptedPackageEnvelope == null) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNoPackageToDecrypt)); } Stream result; Trace.SafeWrite(Trace.Rights, "Decrypting the document."); SecurityHelper.EnvelopePermissionSet.Assert(); // BlessedAssert try { result = _encryptedPackageEnvelope.GetPackageStream(); } finally { CodeAccessPermission.RevertAll(); } return result; } ////// Create an encrypted package from a stream using the current publish license. /// /// The stream to encrypt ///An EncryptedPackageEnvelope around the stream. ////// Critical /// 1) Accesses critical data CurrentPublishLicense /// 2) Calls critical function GenerateCryptoProvider /// 3) Asserts for EnvelopePermissionSet to create a new encrypted envelope /// 4) Calls critical method IRightsManagementProvider.SaveUseLicense /// TreatAsSafe /// 1) Does not leak critical data. The publish license is saved /// (encrypted) in the encrypted package created, but this cannot be /// accessed without the RightsManagementPermission. /// 2) The returned value is only saved locally. /// 3) Data into assert is critical for set or returned from a critical /// function. Only the Create operation itself is critical; the /// result object is not itself critical, since retrieving any useful /// information (such as encrypted content or the publish license) /// requires an assert. /// 4) The use license is, as expected, saved into the encrypted envelope /// that was just created. /// [SecurityCritical, SecurityTreatAsSafe] EncryptedPackageEnvelope IRightsManagementProvider.EncryptPackage(Stream ciphered) { // If the publish license is to not encrypt, return null if (CurrentPublishLicense == null) { return null; } // If the user doesn't have rights to encrypt data, we also should not // attempt to create an EncryptedPackageEnvelope, since we could never // write to it RightsManagementLicense currentUseLicense = ((IRightsManagementProvider)this).CurrentUseLicense; if (currentUseLicense != null && !HasPermission(currentUseLicense, RightsManagementPermissions.AllowEdit)) { return null; } CryptoProvider cp = GenerateCryptoProvider(); EncryptedPackageEnvelope result = null; SecurityHelper.EnvelopePermissionSet.Assert(); // BlessedAssert try { result = EncryptedPackageEnvelope.Create( ciphered, CurrentPublishLicense, cp); } finally { CodeAccessPermission.RevertAll(); } // Always save the use license back into any new RM protected document if (result != null) { ((IRightsManagementProvider)this).SaveUseLicense(result); } return result; } ////// Generates an unsigned publish license for the package from a collection /// of licenses. /// /// /// The list of licenses from which to generate a publish license /// /// The optional date until when the publish license will be valid /// /// A URI to contact to request additional permissions ////// Critical /// 1) Sets the SecurityCriticalDataForSet object _rightsDictionary /// 2) Asserts for RightsManagementPermission to create a new unsigned /// publish license. No data goes into this assert, and any access to /// the UnsignedPublishLicense object created requires another assert. /// 3) Asserts for RightsManagementPermission to set properties on the /// unsigned publish license that come from the arguments to this /// function. The properties in the arguments are safely critical for /// set. All other non-argument data is retrieved from member /// variables of this class that are critical for set. /// 4) Sets the SecurityCriticalDataForSet object _unsignedPublishLicense. /// This is set from information passed in to this function as an /// argument. /// [SecurityCritical] void IRightsManagementProvider.GenerateUnsignedPublishLicense( IListlicenses) { if (licenses == null) { throw new ArgumentNullException("licenses"); } // If the document is already protected, only owners can republish it // with different permissions if (IsProtected && !HasPermission( _rmUseLicense.Value, RightsManagementPermissions.AllowOwner)) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNotOwnerOfDocument)); } Trace.SafeWrite( Trace.Rights, "Creating a publish license for the document."); // // Create the unsigned publish license // UnsignedPublishLicense unsignedPublishLicense = null; _rmPermission.Assert(); //BlessedAssert try { unsignedPublishLicense = new UnsignedPublishLicense(); } finally { RightsManagementPermission.RevertAssert(); } ICollection licenseGrants = GetGrantsFromUnsignedLicense(unsignedPublishLicense); // // Retrieve the referral information from the first license // string referralInfoName = string.Empty; Uri referralInfoUri = null; if (licenses.Count > 0) { referralInfoName = licenses[0].ReferralInfoName; referralInfoUri = licenses[0].ReferralInfoUri; } // // Generate grants from the licenses passed in // Dictionary rights = new Dictionary (); // Look through each license passed in and generate grants from it foreach (RightsManagementLicense rmLicense in licenses) { // If the user has not already been granted rights, add the grants // given to the user to the grants dictionary and the grant list if (!rights.ContainsKey(rmLicense.LicensedUser)) { rights[rmLicense.LicensedUser] = rmLicense; IList grantList = GetGrantsFromLicense(rmLicense); foreach (ContentGrant grant in grantList) { licenseGrants.Add(grant); } } } // If the current user was not specified as an owner, add the user to // the rights dictionary and grant the user admin privileges forever if (!rights.ContainsKey(_user.Value)) { ContentGrant ownerGrant = CreateGrant( _user.Value, ContentRight.Owner, DateTime.MinValue, DateTime.MaxValue); // Add the grant to the unsigned publish license licenseGrants.Add(ownerGrant); // Add the grant to the rights dictionary IList grantList = new List (); grantList.Add(ownerGrant); rights[_user.Value] = ConvertGrantList(_user.Value, grantList); } // // Set up remaining properties of the unsigned publish license // _rmPermission.Assert(); //BlessedAssert try { unsignedPublishLicense.Owner = _user.Value; unsignedPublishLicense.ReferralInfoName = referralInfoName; unsignedPublishLicense.ReferralInfoUri = referralInfoUri; } finally { RightsManagementPermission.RevertAssert(); } // // Save temporary unsigned license and rights dictionary for signing // _temporaryRightsDictionary.Value = rights; _temporaryUnsignedPublishLicense.Value = unsignedPublishLicense; } /// /// Generates an unsigned publish license for the package from /// the template. /// /// /// The template from which to generate a publish license ////// Critical /// 1) Sets the SecurityCriticalDataForSet object _temporaryRightsDictionary /// 2) Asserts for RightsManagementPermission to create a new unsigned /// publish license. The template parameter value is used to create /// the UnsignedPublishLicense, during which the template is validated. /// 3) Sets the SecurityCriticalDataForSet object _temporaryUnsignedPublishLicense. /// This is set from information passed in to this function as an /// argument. /// 4) Asserts for RightsManagementPermission executes some critical /// methods to check and set the owner and some grants in the document. /// These are set from critical member variables or from data derived /// from the argument to this function. /// [SecurityCritical] void IRightsManagementProvider.GenerateUnsignedPublishLicense(string template) { if (string.IsNullOrEmpty(template)) { throw new NullReferenceException("template"); } UnsignedPublishLicense unsignedPublishLicense = null; _rmPermission.Assert(); //BlessedAssert try { // Create the license from the template. unsignedPublishLicense = new UnsignedPublishLicense(template); } finally { RightsManagementPermission.RevertAssert(); } // Get who is currently listed as the owner of the document in the // publish license ContentUser currentOwnerFromLicense = null; _rmPermission.Assert(); //BlessedAssert try { currentOwnerFromLicense = unsignedPublishLicense.Owner; } finally { RightsManagementPermission.RevertAssert(); } RightsManagementUser currentOwner = null; if (currentOwnerFromLicense != null) { currentOwner = RightsManagementUser.CreateUser( currentOwnerFromLicense); } // If the listed owner is not the current user, change the listed owner // and ensure that the old owner still maintains owner rights on the // document if (!_user.Value.Equals(currentOwner)) { ContentGrant currentOwnerGrant = null; if (currentOwner != null) { currentOwnerGrant = CreateGrant( currentOwner, ContentRight.Owner, DateTime.MinValue, DateTime.MaxValue); } _rmPermission.Assert(); //BlessedAssert try { unsignedPublishLicense.Owner = _user.Value; if (currentOwnerGrant != null) { unsignedPublishLicense.Grants.Add(currentOwnerGrant); } } finally { RightsManagementPermission.RevertAssert(); } } // Assign the new publish license. _temporaryRightsDictionary.Value = null; _temporaryUnsignedPublishLicense.Value = unsignedPublishLicense; } ////// Signs the unsigned publish license and saves a corresponding updated use /// license. /// This requires GenerateUnsignedPublishLicense to have been called. /// ////// Critical /// 1) Asserts for UnmanagedCode permission to sign the publish license /// 2) Sets the SecurityCriticalData object _newPublishLicense /// 3) Sets the SecurityCriticalDataForSet object _useLicense /// 4) Calls critical function CreateGrant /// 5) Calls critical function ConvertGrantList /// TreatAsSafe /// 1) Unmanaged operation is to sign the unsigned publish license, only if /// the user owns the document or the document is not protected. Thus /// the user can never get any more rights than he or she already has. /// The unsigned publish license is also critical for set. /// 2) The new publish license is set from the critical unsigned publish /// license. /// 3) The use license is only set if the user is the owner of the /// document, or the document is unprotected. It grants the current /// user owner and view rights, which he or she already has to have had /// to be able to generate a publish license. The unsigned publish /// license from whose signing the use license is generated is also /// critical for set. /// 4) The grant is created for the critical for set user and gives him or /// her the owner right, which he or she already must have had. /// 5) The arguments to ConvertGrantList are either critical for set or /// come from the Sign operation on the critical for set unsigned /// publish license. The list of grants contains only the grant /// created by the safe operation described in #4. /// [SecurityCritical, SecurityTreatAsSafe] void IRightsManagementProvider.SignPublishLicense() { // If the document is already protected, only owners can republish it if (IsProtected && !HasPermission(_rmUseLicense.Value, RightsManagementPermissions.AllowOwner)) { throw new InvalidOperationException( SR.Get(SRID.RMProviderExceptionNotOwnerOfDocument)); } UseLicense useLicense; Trace.SafeWrite( Trace.Rights, "Signing the publish license for the document."); _rmPermission.Assert(); // BlessedAssert try { CurrentPublishLicense = _temporaryUnsignedPublishLicense.Value.Sign( _secureEnvironment.Value, out useLicense); } finally { RightsManagementPermission.RevertAssert(); } _useLicense.Value = useLicense; // Copy and clear temporary values _unsignedPublishLicense.Value = _temporaryUnsignedPublishLicense.Value; _rightsDictionary.Value = _temporaryRightsDictionary.Value; _temporaryUnsignedPublishLicense.Value = null; _temporaryRightsDictionary.Value = null; // If the RightsDictionary exists then set use license. if (_rightsDictionary.Value != null) { _rmUseLicense.Value = _rightsDictionary.Value[_user.Value]; } else { // Since the RightsDictionary doesn't exist (most likely because we're using // a template), generate the owner data. ListgrantList = new List (); grantList.Add(CreateGrant(_user.Value, ContentRight.Owner, DateTime.MinValue, DateTime.MaxValue)); _rmUseLicense.Value = ConvertGrantList(_user.Value, grantList); } } /// /// Saves the current set of licenses. /// ////// Critical /// 1) Sets several critical and critical for set variables to their /// current corresponding values. This is critical, since these values /// should be overwritten only when trusted code requests it. /// [SecurityCritical] void IRightsManagementProvider.SaveCurrentLicenses() { // Save the current publish license and use licenses for rollback _lastSavedPublishLicense = _currentPublishLicense; _lastSavedRMUseLicense.Value = _rmUseLicense.Value; _lastSavedUseLicense.Value = _useLicense.Value; _lastSavedRightsDictionary.Value = _rightsDictionary.Value; } ////// Reverts to the last saved set of licenses. /// ////// Critical /// 1) Sets several critical and critical for set variables to saved values /// [SecurityCritical] void IRightsManagementProvider.RevertToSavedLicenses() { CurrentPublishLicense = _lastSavedPublishLicense; _useLicense.Value = _lastSavedUseLicense.Value; _rmUseLicense.Value = _lastSavedRMUseLicense.Value; _rightsDictionary.Value = _lastSavedRightsDictionary.Value; _lastSavedPublishLicense = null; _lastSavedUseLicense.Value = null; _lastSavedRMUseLicense.Value = null; _lastSavedRightsDictionary.Value = null; } ////// Sets the encapsulated EncryptedPackageEnvelope to a new value and loads /// a new publish license from it. If the new publish license is the same /// as the old one, the function restores the old use license. /// /// The new encrypted package /// Whether or not the new encrypted /// package has a different publish license ////// Critical /// 1) Setting critical data objects _encryptedPackage, /// _rmUseLicense, and CurrentPublishLicense, all from the encrypted /// package passed as a parameter /// 2) Copies critical data _publishLicenseFromEnvelope, but does not leak /// it outside the method. /// 3) Asserts for RightsManagementPermission to call ToString on the old /// and new publish licenses. The string representations are not leaked. /// 4) Calls Critical function GenerateCryptoProvider, but saves it only /// in a critical for get member variable. /// 5) Asserts for RightsManagementPermission to save the CryptoProvider /// returned from GenerateCryptoProvider in the encrypted package. /// [SecurityCritical] void IRightsManagementProvider.SetEncryptedPackage(EncryptedPackageEnvelope newPackage, out bool publishLicenseChanged) { PublishLicense savedPublishLicense = null; UseLicense savedUseLicense = null; RightsManagementLicense savedRMLicense = null; // Save the current set of licenses. In case the publish license in the // new encrypted package envelope is the same, these will be restored. if (_publishLicenseFromEnvelope != null) { savedPublishLicense = _publishLicenseFromEnvelope; savedUseLicense = _useLicense.Value; savedRMLicense = _rmUseLicense.Value; } _encryptedPackageEnvelope = newPackage; _publishLicenseFromEnvelope = null; CurrentPublishLicense = null; InitializeMembers(); publishLicenseChanged = true; // If both publish licenses are non-null, compare them if (savedPublishLicense != null && _publishLicenseFromEnvelope != null) { string serializedSavedPublishLicense = string.Empty; string serializedNewPublishLicense = string.Empty; _rmPermission.Assert(); //BlessedAssert try { serializedSavedPublishLicense = savedPublishLicense.ToString(); serializedNewPublishLicense = _publishLicenseFromEnvelope.ToString(); } finally { RightsManagementPermission.RevertAssert(); } publishLicenseChanged = !string.Equals( serializedSavedPublishLicense, serializedNewPublishLicense, StringComparison.Ordinal); } // If both publish licenses are null, that means the document wasn't // protected before and still isn't protected, so the publish license // hasn't changed. else if (savedPublishLicense == null && _publishLicenseFromEnvelope == null) { publishLicenseChanged = false; } if (IsProtected && !publishLicenseChanged) { // If the publish license hasn't changed, restore the saved use // license and generate a new CryptoProvider from it. _useLicense.Value = savedUseLicense; _rmUseLicense.Value = savedRMLicense; CryptoProvider cryptoProvider = GenerateCryptoProvider(); _rmPermission.Assert(); try { _encryptedPackageEnvelope.RightsManagementInformation.CryptoProvider = cryptoProvider; } finally { RightsManagementPermission.RevertAssert(); } } // Since the encrypted package envelope has been changed, the last saved // licenses aren't applicable any more. _lastSavedPublishLicense = null; _lastSavedUseLicense.Value = null; _lastSavedRMUseLicense.Value = null; _lastSavedRightsDictionary.Value = null; Trace.SafeWrite( Trace.Rights, "SetEncryptedPackage called. publishLicenseChanged: {0}", publishLicenseChanged); } #endregion IRightsManagementProvider #region IDisposable Members //-------------------------------------------------------------------------- // IDisposable Members //-------------------------------------------------------------------------- ////// Disposes everything that needs to be disposed. /// ////// Critical /// 1) Accesses critical data _cryptoProviders. /// 2) Asserts for RightsManagementPermission to dispose CryptoProvider /// objects. /// TreatAsSafe /// 1) Data from _cryptoProviders is not saved. /// 2) Doesn't leak any information from under the assert. /// [SecurityCritical, SecurityTreatAsSafe] public void Dispose() { if (_cryptoProviders != null) { foreach (CryptoProvider cryptoProvider in _cryptoProviders) { _rmPermission.Assert(); //BlessedAssert try { cryptoProvider.Dispose(); } finally { RightsManagementPermission.RevertAssert(); } } _cryptoProviders = null; } CleanUpSecureEnvironment(); GC.SuppressFinalize(this); } #endregion IDisposable Members #region Private Methods //------------------------------------------------------------------------- // Private Methods //-------------------------------------------------------------------------- ////// Destroys the RightsManagementProvider. /// ~RightsManagementProvider() { Dispose(); } ////// Binds the current use license to the current secure environment to get /// a new CryptoProvider. /// ////// Critical /// 1) Asserts for RightsManagementPermission to get a new CryptoProvider. /// Data going into the assert comes from critical for set member /// variables. /// 2) Adds the new CryptoProvider to the critical list of CryptoProviders. /// [SecurityCritical] private CryptoProvider GenerateCryptoProvider() { CryptoProvider cryptoProvider = null; _rmPermission.Assert(); // BlessedAssert try { cryptoProvider = _useLicense.Value.Bind(_secureEnvironment.Value); Trace.SafeWrite( Trace.Rights, "The CryptoProvider was initialized."); } finally { RightsManagementPermission.RevertAssert(); } // Add a reference to the CryptoProvider to the list of CryptoProviders // for disposal if (cryptoProvider != null) { if (_cryptoProviders == null) { IListcryptoProviders = new List (); _cryptoProviders = cryptoProviders; } _cryptoProviders.Add(cryptoProvider); } return cryptoProvider; } /// /// Checks whether the specified license has the specified permission. /// /// The license to check /// The permission for which to check ///Whether or not the license has the permission ////// Critical /// 1) Marked Critical to audit changes since security decisions are based /// on output from this function. /// TreatAsSafe /// 1) This is only marked critical to audit changes. No unsafe operations /// are performed. /// [SecurityCritical, SecurityTreatAsSafe] private static bool HasPermission( RightsManagementLicense license, RightsManagementPermissions permission) { return license.HasPermission(permission); } ////// Adds referral information read from the current publish license to a /// use license. /// /// The use license (grant list) to which to add /// referral information ////// Critical /// 1) Asserts for RightsManagementPermission to read referral information /// from the publish license /// 2) Sets critical data ReferralInfoName and ReferralInfoUri from the /// publish license /// TreatAsSafe /// 1) Referral information is not leaked - it is critical for get to read /// it from the use license. /// 2) The critical data is set directly from the publish license, which /// is critical for set. /// [SecurityCritical, SecurityTreatAsSafe] private void AddReferralInfo(RightsManagementLicense rmLicense) { // If there is no publish license yet there is no information to add if (CurrentPublishLicense == null) { return; } _rmPermission.Assert(); try { rmLicense.ReferralInfoName = CurrentPublishLicense.ReferralInfoName; rmLicense.ReferralInfoUri = CurrentPublishLicense.ReferralInfoUri; } finally { RightsManagementPermission.RevertAssert(); } } ////// Converts a collection of grants into a "license" that is usable /// internally by this component. /// /// The UseLicense to convert ////// Critical /// 1) Sets critical information in a RightsManagementLicense object. /// This information comes from parameters passed in to this function. /// (The information about rights granted is instead retrieved through /// the Critical for set _encryptedPackage.) /// 2) Asserts for RightsManagementPermission to get the validity dates /// from a UseLicense object. We do not consider this information /// critical data in this context. /// 3) Asserts for RightsManagementPermission to get the actual rights /// granted in the grant list. We do not consider this information /// critical data in this context. /// [SecurityCritical] private RightsManagementLicense ConvertGrantList( RightsManagementUser user, IListgrantList) { RightsManagementLicense rmLicense = new RightsManagementLicense(); rmLicense.LicensedUser = user; rmLicense.LicensePermissions = RightsManagementPermissions.AllowNothing; rmLicense.ValidFrom = DateTime.MinValue; rmLicense.ValidUntil = DateTime.MaxValue; AddReferralInfo(rmLicense); if (grantList != null) { bool canSign = false; DateTime validFrom = DateTime.MinValue; DateTime validUntil = DateTime.MaxValue; foreach (ContentGrant grant in grantList) { ContentRight right; _rmPermission.Assert(); //BlessedAssert try { right = grant.Right; if (grant.ValidFrom > validFrom) { validFrom = grant.ValidFrom; } if (grant.ValidUntil < validUntil) { validUntil = grant.ValidUntil; } } finally { RightsManagementPermission.RevertAssert(); } switch (right) { // Translate each grant into a Mongoose permission case ContentRight.View: rmLicense.AddPermission( RightsManagementPermissions.AllowView); break; case ContentRight.Print: rmLicense.AddPermission( RightsManagementPermissions.AllowPrint); break; case ContentRight.Extract: rmLicense.AddPermission( RightsManagementPermissions.AllowCopy); break; case ContentRight.Owner: rmLicense.AddPermission( RightsManagementPermissions.AllowOwner); break; // The Edit grant can mean two things: // // 1) Without any other grants, it means basically nothing // since Mongoose doesn't support editing documents. // 2) In conjunction with the Sign grant, it means that // the user can sign the document. // // As a result we have to keep track of the edit and sign // grants separately and determine later whether both were // granted before we can allow the user to sign. case ContentRight.Edit: rmLicense.AddPermission( RightsManagementPermissions.AllowEdit); break; case ContentRight.Sign: canSign = true; break; case ContentRight.DocumentEdit: // DocumentEdit is a custom right, that when applied with // Edit, we want to treat as our custom right, Sign. canSign = true; break; } } if (rmLicense.HasPermission(RightsManagementPermissions.AllowEdit) && canSign) { rmLicense.AddPermission( RightsManagementPermissions.AllowSign); } rmLicense.ValidFrom = validFrom; rmLicense.ValidUntil = validUntil; } return rmLicense; } /// /// Generates a list of Grant objects corresponding to the data contained /// in a RightsManagementLicense object. /// /// The RightsManagementLicense to transform ///A list of Grant objects ////// Critical /// 1) Calls critical function CreateGrant with information from the /// license object passed in as an argument. /// TreatAsSafe /// 1) Permissions granted in the license object are critical for set. /// [SecurityCritical, SecurityTreatAsSafe] private IListGetGrantsFromLicense( RightsManagementLicense rmLicense) { RightsManagementUser user = rmLicense.LicensedUser; List grants = new List (); // Translate each Mongoose permission into a grant if (HasPermission(rmLicense, RightsManagementPermissions.AllowView)) { grants.Add( CreateGrant( user, ContentRight.View, rmLicense.ValidFrom, rmLicense.ValidUntil)); } if (HasPermission(rmLicense, RightsManagementPermissions.AllowPrint)) { grants.Add( CreateGrant( user, ContentRight.Print, rmLicense.ValidFrom, rmLicense.ValidUntil)); } if (HasPermission(rmLicense, RightsManagementPermissions.AllowCopy)) { grants.Add( CreateGrant( user, ContentRight.Extract, rmLicense.ValidFrom, rmLicense.ValidUntil)); } bool editRightGranted = false; if (HasPermission(rmLicense, RightsManagementPermissions.AllowEdit)) { grants.Add( CreateGrant( user, ContentRight.Edit, rmLicense.ValidFrom, rmLicense.ValidUntil)); editRightGranted = true; } if (HasPermission(rmLicense, RightsManagementPermissions.AllowSign)) { // The sign permission translates to the combination of the Edit // and Sign grants. If the user was already granted Edit, there is // no need to grant it again. if (!editRightGranted) { grants.Add( CreateGrant( user, ContentRight.Edit, rmLicense.ValidFrom, rmLicense.ValidUntil)); } grants.Add( CreateGrant( user, ContentRight.Sign, rmLicense.ValidFrom, rmLicense.ValidUntil)); } if (HasPermission(rmLicense, RightsManagementPermissions.AllowOwner)) { grants.Add( CreateGrant( user, ContentRight.Owner, rmLicense.ValidFrom, rmLicense.ValidUntil)); } return grants; } /// /// Initializes the necessary member variables. This can be called more /// than once without ill effect. /// ////// Critical /// 1) Asserts for RightsManagementPermission to load a publish license /// from the encrypted package. /// 2) Accesses critical data _publishLicenseFromEnvelope /// 3) Sets critical property CurrentPublishLicense /// 4) Accesses _encryptedPackage which is SecurityCritical /// TreatAsSafe /// 1) The publish license is saved as critical data, so it is not leaked. /// 2) It is accessed only to check for null and is not null. It is set /// from critical data _encryptedPackage. /// 3) The new publish license is set directly from critical data /// _publishLicenseFromEnvelope. /// 4) Does not leak information. /// [SecurityCritical, SecurityTreatAsSafe] private void InitializeMembers() { if (_encryptedPackageEnvelope != null && _publishLicenseFromEnvelope == null) { RightsManagementInformation rmInfo = _encryptedPackageEnvelope.RightsManagementInformation; PublishLicense publishLicense = null; _rmPermission.Assert(); //BlessedAssert try { publishLicense = rmInfo.LoadPublishLicense(); } finally { RightsManagementPermission.RevertAssert(); } if (publishLicense == null) { throw new FileFormatException( SR.Get(SRID.RMProviderExceptionNoPublishLicense)); } _publishLicenseFromEnvelope = publishLicense; CurrentPublishLicense = publishLicense; } } ////// Cleans up the SecureEnvironment member. /// ////// Critical /// 1) Asserts RightsManagementPermission to call the Dispose method /// on _secureEnvironment /// 2) Sets SecurityCriticalDataForSet object _secureEnvironment /// TreatAsSafe /// 1) The assert is made to call Dispose on _secureEnvironment, which /// is marked as SecurityCriticalDataForSet. /// 2) The new value being assigned to _secureEnvironment is null. /// [SecurityCritical, SecurityTreatAsSafe] private void CleanUpSecureEnvironment() { if (_secureEnvironment.Value != null) { _rmPermission.Assert(); // BlessedAssert try { _secureEnvironment.Value.Dispose(); } finally { RightsManagementPermission.RevertAssert(); } _secureEnvironment.Value = null; } } ////// Sets the currently active user from the value stored in the saved /// secure environment. /// /// Critical /// 1) Asserts for RightsManagementPermission to get the value of the /// _secureEnvironment.Value.User parameter /// 2) Sets SecurityCriticalDataForSet variable _user /// 3) Calls SecurityCritical function RightsManagementUser.CreateUser /// TreatAsSafe /// 1) _secureEnvironment is SecurityCriticalDataForSet, and the call is /// reading a property value which requires asserts to access any data /// from it. /// 2) The _user variable is set from SecurityCritical function /// RightsManagementUser.CreateUser. /// 3) The argument to the CreateUser function is information that is /// retrieved from the SecureEnvironment created by SecurityCritical /// method Create. [SecurityCritical, SecurityTreatAsSafe] private void SetUserFromSecureEnvironment() { _rmPermission.Assert(); // BlessedAssert try { _user.Value = RightsManagementUser.CreateUser(_secureEnvironment.Value.User); } finally { RightsManagementPermission.RevertAssert(); } } ////// Creates a ContentGrant object with the given user and rights. /// /// The user for whom the grant applies /// The right to grant ///A new ContentGrant object ////// Critical /// 1) Asserts for RightsManagementPermission to create a ContentGrant /// object with arguments passed in to this function /// [SecurityCritical] private ContentGrant CreateGrant(RightsManagementUser user, ContentRight right, DateTime validFrom, DateTime validUntil) { _rmPermission.Assert(); //BlessedAssert try { return new ContentGrant(user, right, validFrom, validUntil); } finally { RightsManagementPermission.RevertAssert(); } } ////// Gets a collection of grants from an unsigned publish license. /// /// An unsigned publish license ///A collection of grants ////// Critical /// 1) Asserts for RightsManagementPermission to get a list of grants from /// an unsigned publish license. /// TreatAsSafe /// 1) Accessing any information in the actual grant objects in the list /// requires an assert for RightsManagementPermission. /// [SecurityCritical, SecurityTreatAsSafe] private ICollectionGetGrantsFromUnsignedLicense( UnsignedPublishLicense unsignedLicense) { ICollection grants = null; if (unsignedLicense != null) { _rmPermission.Assert(); //BlessedAssert try { grants = unsignedLicense.Grants; } finally { RightsManagementPermission.RevertAssert(); } } return grants; } /// /// Cleans up the SecureEnvironment member. /// ////// Critical /// Must assert for SecurityPermission to get path to running executable (XPSViewer.exe unmanaged code) /// Must assert for FileIOPermission to read XPSViewerManifest.xml. /// [SecurityCritical] private string GetApplicationManifest() { //Content of the RM application Manifest System.Diagnostics.ProcessModule processModule = null; //Get the current Process and MainModule. new SecurityPermission(PermissionState.Unrestricted).Assert(); //BlessedAssert try { System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess(); processModule = currentProcess.MainModule; } finally { //Revert the SecurityPermission assert SecurityPermission.RevertAssert(); } Invariant.Assert( processModule != null, "Failed to get Process Module"); string fileName = processModule.FileName; string applicationManifest = null; //Using exe module path, create path to application manifest file (XPSViewerManifest.xml) string applicationManifestFileLocation = Path.Combine( Path.GetDirectoryName(fileName), _applicationManifestFileName); new FileIOPermission(FileIOPermissionAccess.Read, applicationManifestFileLocation).Assert(); //BlessedAssert try { // Create an instance of StreamReader to read from a file. // The using statement also closes the StreamReader. using (StreamReader sr = new StreamReader(applicationManifestFileLocation)) { applicationManifest = sr.ReadToEnd(); } } finally { FileIOPermission.RevertAssert(); } return applicationManifest; } #endregion Private Methods #region Private Properties //------------------------------------------------------------------------- // Private Properties //------------------------------------------------------------------------- ////// Gets whether the XPS document is RM protected. This is a convenient way /// to use the IsProtected property without having to cast to an instance /// of IRightsManagementProvider each time. /// private bool IsProtected { get { return ((IRightsManagementProvider)this).IsProtected; } } ////// Gets or sets the current publish license that will be used for saving /// an encrypted document. This is a convenient way to use the /// CurrentPublishLicense property without having to cast to an instance of /// IRightsManagementProvider each time. /// ////// Critical /// 1) Calls critical property /// IRightsManagementProvider.CurrentPublishLicense /// private PublishLicense CurrentPublishLicense { [SecurityCritical] get { return ((IRightsManagementProvider)this).CurrentPublishLicense; } [SecurityCritical] set { ((IRightsManagementProvider)this).CurrentPublishLicense = value; } } ////// Indicates whether the current Use License allows caching of the license /// back to the container. /// private bool AllowLicenseCaching { [SecurityCritical, SecurityTreatAsSafe] get { bool result = false; _rmPermission.Assert(); // BlessedAssert try { // If the key pair "NOLICCACHE","1" (in _noLicCacheKeyValuePair) is present // in the Use License's ApplicationData, this signifies that license // caching should be disabled (and thus we will return false here) result = !(_useLicense.Value != null && _useLicense.Value.ApplicationData != null && _useLicense.Value.ApplicationData.Contains(_noLicCacheKeyValuePair)); } finally { RightsManagementPermission.RevertAssert(); } return result; } } #endregion Private Properties #region Private Fields //------------------------------------------------------------------------- // Private Fields //-------------------------------------------------------------------------- ////// Critical: 1) Asserts for RightsManagementPermission in order to check the /// ApplicationData dictionary. /// /// TreatAsSafe: 1) The knowledge of whether License Caching is allowed is not /// confidential information. /// ////// The underlying EncryptedPackageEnvelope class from the RM APIs. /// [SecurityCritical] EncryptedPackageEnvelope _encryptedPackageEnvelope; ////// The currently active secure environment. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated object /// without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_secureEnvironment; /// /// The use license the user has for the currently open package. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// object without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_useLicense; /// /// The last saved use license. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// object without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_lastSavedUseLicense; /// /// A copy of the unsigned publish license. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// object without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_unsignedPublishLicense; /// /// A generated unsigned publish license that has not yet been signed. Once /// it is signed, it will replace the _unsignedPublishLicense above. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// object without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_temporaryUnsignedPublishLicense; /// /// The publish license saved in the current _encryptedPackage. /// [SecurityCritical] PublishLicense _publishLicenseFromEnvelope; ////// The current publish license, which may be different from /// _publishLicenseFromEnvelope above if the user has committed a publishing /// operation. /// [SecurityCritical] PublishLicense _currentPublishLicense; ////// The last saved publish license. /// [SecurityCritical] PublishLicense _lastSavedPublishLicense; ////// The specially formatted version of the use license describing what /// rights the current user has on the document. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// object without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_rmUseLicense; /// /// The last saved RM use license. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// object without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet_lastSavedRMUseLicense; /// /// The user for whom this document has been opened. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from a RightsManagementUser /// object outside critical code. /// SecurityCriticalDataForSet_user; /// /// A dictionary of rights granted to users on this document. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// objects without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet< IDictionary> _rightsDictionary; /// /// The last saved version of the dictionary of rights granted to users. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// objects without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet< IDictionary> _lastSavedRightsDictionary; /// /// A dictionary of rights corresponding to the rights granted in a /// temporary unsigned publish license. /// ////// This information does not need to be critical for get because it is /// not possible to get critical information from the encapsulated user /// objects without asserting for RightsManagementPermission. /// SecurityCriticalDataForSet< IDictionary> _temporaryRightsDictionary; /// /// A list of all the CryptoProviders generated /// ////// Since CryptoProvider objects can only be generated from under an assert /// the data the list contains is critical. /// [SecurityCritical] IList_cryptoProviders; //Name of the RM application manifest. /// /// Critical /// 1) Data is used in elevation. /// [SecurityCritical] private const string _applicationManifestFileName = "XPSViewerManifest.xml"; ////// Critical /// 1) Data is used in elevation. /// /// TreatAsSafe /// 1) Marked critical only to audit changes. /// [SecurityCritical, SecurityTreatAsSafe] private const string _registryLocationForDefaultUser = @"Software\Microsoft\XPSViewer\"; ////// Critical /// 1) Data is used in elevation. /// /// TreatAsSafe /// 1) Marked critical only to audit changes. /// [SecurityCritical, SecurityTreatAsSafe] private const string _registryBaseForXpsViewer = @"HKEY_CURRENT_USER\Software\Microsoft\XPSViewer\"; ////// Critical /// 1) Data is used in elevation. /// /// TreatAsSafe /// 1) Marked critical only to audit changes. /// [SecurityCritical, SecurityTreatAsSafe] private const string _registryValueNameForAccountName = "AccountName"; ////// Critical /// 1) Data is used in elevation. /// /// TreatAsSafe /// 1) Marked critical only to audit changes. /// [SecurityCritical, SecurityTreatAsSafe] private const string _registryValueNameForAccountType = "AccountType"; ////// The Key/Value pair for the NOLICCACHE publishing option. This disables /// caching of the Use License in the container if present. /// [SecurityCritical] private readonly KeyValuePair/// Critical /// 1) Data is used to determine which Use License property to check, /// we want to ensure this is not maliciously used to read properties /// other than NOLICCACHE. /// ///_noLicCacheKeyValuePair = new KeyValuePair ("NOLICCACHE", "1"); /// /// Critical /// 1) Creation of the permission is critical as the code will be /// asserting for it and we do not want it replaced without review. /// TreatAsSafe /// 1) Future reviewers, this value should only ever represent /// RightsManagementPermission. It should not be changed without /// reviewing all uses of it in the class. (This is safe because it�s /// being reviewed.) /// [SecurityCritical, SecurityTreatAsSafe] private static RightsManagementPermission _rmPermission = new RightsManagementPermission(); #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- control.ime.cs
- SharedStatics.cs
- RecognizeCompletedEventArgs.cs
- SessionViewState.cs
- DbConnectionFactory.cs
- WinFormsUtils.cs
- MethodCallConverter.cs
- AttributedMetaModel.cs
- UniqueIdentifierService.cs
- HtmlCommandAdapter.cs
- XmlSchemaObjectCollection.cs
- CharKeyFrameCollection.cs
- HierarchicalDataBoundControl.cs
- Byte.cs
- DataGrid.cs
- SslStreamSecurityUpgradeProvider.cs
- FixedSOMPageConstructor.cs
- ContactManager.cs
- Internal.cs
- TraceSource.cs
- URLString.cs
- CallTemplateAction.cs
- AnnotationAdorner.cs
- BaseTemplateCodeDomTreeGenerator.cs
- WebPartEditorOkVerb.cs
- PeerDuplexChannel.cs
- DataTemplate.cs
- XPathChildIterator.cs
- ExpandableObjectConverter.cs
- InstanceData.cs
- DebugHandleTracker.cs
- GlyphRunDrawing.cs
- AssemblyBuilder.cs
- CqlParserHelpers.cs
- IndentTextWriter.cs
- XPathNodeList.cs
- MinMaxParagraphWidth.cs
- JapaneseCalendar.cs
- ErrorLog.cs
- SqlUtils.cs
- HtmlTable.cs
- Point3DValueSerializer.cs
- ContextProperty.cs
- MaterialGroup.cs
- AppDomainUnloadedException.cs
- WebPartManager.cs
- NegationPusher.cs
- NumericExpr.cs
- NetCodeGroup.cs
- OrderedEnumerableRowCollection.cs
- DataView.cs
- ScrollChangedEventArgs.cs
- MimeTypeAttribute.cs
- XmlSiteMapProvider.cs
- XsdBuildProvider.cs
- Profiler.cs
- CharConverter.cs
- PeerApplication.cs
- ApplicationProxyInternal.cs
- ThrowHelper.cs
- SqlUtils.cs
- ProcessManager.cs
- GridViewCommandEventArgs.cs
- ZipArchive.cs
- WebHttpBindingCollectionElement.cs
- LeftCellWrapper.cs
- ProgressChangedEventArgs.cs
- DetailsViewRowCollection.cs
- MeshGeometry3D.cs
- ProcessProtocolHandler.cs
- Clock.cs
- EntityCommandDefinition.cs
- DependencyPropertyHelper.cs
- ArrayListCollectionBase.cs
- RtfControls.cs
- SqlConnectionFactory.cs
- ItemMap.cs
- ContainerUIElement3D.cs
- Rotation3DAnimation.cs
- ZoneButton.cs
- IMembershipProvider.cs
- HostSecurityManager.cs
- SendAgentStatusRequest.cs
- SqlServer2KCompatibilityAnnotation.cs
- RSAOAEPKeyExchangeFormatter.cs
- HttpHandlerActionCollection.cs
- PropVariant.cs
- DynamicILGenerator.cs
- DescendentsWalkerBase.cs
- DiscoveryExceptionDictionary.cs
- FormViewInsertEventArgs.cs
- FaultDescription.cs
- MetadataSet.cs
- PageRouteHandler.cs
- ListControlConvertEventArgs.cs
- CopyAction.cs
- ToolZoneDesigner.cs
- MaterialCollection.cs
- FilePrompt.cs