Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / CryptoSession.cs / 1 / CryptoSession.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace Microsoft.InfoCards { using System; using System.Collections; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Xml; using System.Security.Principal; using System.ServiceModel.Security; using System.Threading; using Microsoft.InfoCards.Diagnostics; using IDT=Microsoft.InfoCards.Diagnostics.InfoCardTrace; using System.IO; using System.Xml; // // Summary: // This class manages a cryptography session associated with a specific token issued by the service. // // Remarks: // Whenever a token is issued by the service a session id corresponding to an instance of this class is also // issued. When Indigo or the client app needs to sign proof tokens with the private keys of a particular info // card they can use the session id passed out with the token in order to do so. The CryptoSession is disposed // whenever the token expires, or the client process to which the token was issued exits. // internal abstract class CryptoSession { public static readonly TimeSpan MaxSessionLifetime = new TimeSpan( 1, 0, 0 );//1 hour class CryptoSessionDictionary : HandleDictionary{ } // // NOTE!!!!!!!!!! // This enum must match up with the HandleType enum in clients RpcInfoCardCryptoHandle class. // NOTE!!!!!!!!!! // protected enum SessionType { Asymmetric = 1, Symmetric = 2, Transfrom = 3, Hash = 4 }; const int m_MaxSessionCount = Int32.MaxValue / 2; static CryptoSessionDictionary s_sessionCollection = new CryptoSessionDictionary(); static object s_syncRoot = new Object(); Process m_process; // The client process that owns this session. int m_sessionid; // A unique id for this instance. EventHandler m_processExitHandler; // The callback for client process exit. EventHandler m_serviceStoppingHandler; // The callback for service process stopping. System.Threading.Timer m_timer; // The timer that goes off when this session expires. bool m_isDisposed; object m_syncRoot; WindowsIdentity m_identity; // Stores the client identity. DateTime m_expiration; SessionType m_type; // // Summary: // Constructs a new CryptoSession. // // Parameters: // process - The process to which the token was issued. // expiration - The session expiration time. // identity - The identity of the client. // key - The private key associated with the infocard from which the token was issued. // protected CryptoSession( Process process, DateTime expiration, WindowsIdentity identity, object key, SessionType type ) { IDT.Assert( null != key, "null key passed in to CryptoSession ctor" ); // // Make our own process object so that we can control it's lifetime. // try { m_process = ProcessMonitor.GetProcessById( process.Id ); } catch ( ArgumentException e ) { // // The client process is gone. The user must have cancelled. // throw IDT.ThrowHelperError( new ProcessExitedException( SR.GetString( SR.ServiceClientProcessExited, process.Id ), e ) ); } m_syncRoot = new object(); m_identity = identity; m_expiration = expiration; m_type = type; lock ( s_syncRoot ) { int sessionid; try { sessionid = s_sessionCollection.GetNewHandle(); } catch ( IndexOutOfRangeException e ) { throw IDT.ThrowHelperError( new ServiceBusyException( SR.GetString( SR.ServiceTooManyCryptoSessions, s_sessionCollection.MaxSize ), e ) ); } bool success = false; try { m_processExitHandler = new EventHandler( OnProcessExit ); m_process.Exited += m_processExitHandler; // // Make sure the process hasn't exited before we hooked into // the event. // if ( process.HasExited || m_process.HasExited ) { throw IDT.ThrowHelperError( new ProcessExitedException( SR.GetString( SR.ServiceProcessHasExited ) ) ); } TimeSpan sessionLifeTime = expiration - DateTime.UtcNow; if( sessionLifeTime > MaxSessionLifetime ) { sessionLifeTime = MaxSessionLifetime; } m_timer = new System.Threading.Timer( IDT.ThunkCallback(new TimerCallback(OnTimeout)), null, // no state sessionLifeTime, new TimeSpan( 0, 0, 0, 0, -1 ) ); // // Add event handler to be notified when service is stopping. // m_serviceStoppingHandler = new EventHandler( OnServiceStopping ); InfoCardService.Stopping += m_serviceStoppingHandler; s_sessionCollection[ sessionid ] = this; m_sessionid = sessionid; success = true; } finally { if( !success ) { s_sessionCollection.Remove( sessionid ); } } } } protected uint ProcessId { get { return ( uint )m_process.Id; } } protected Process ProcessObj { get { return m_process; } } protected WindowsIdentity Identity { get { return m_identity; } } protected SecurityIdentifier ClientSid { get { return m_identity.User; } } protected DateTime Expiration { get { return m_expiration; } } // // Summary: // Serializes the CryptoSession to a BinaryWriter // public void Write( BinaryWriter bwriter ) { bwriter.Write( ( int )m_type ); bwriter.Write( m_sessionid ); bwriter.Write( m_expiration.ToFileTime() ); OnWrite( bwriter ); } // // Summary: // Called by the timer when this session has timed out. // private void OnTimeout( object state ) { Dispose(); } // // Summary // Called by the Process.Exited event when the client process exits. // // Remarks // The event is raised from a thread running as system. // // Parameters // sender - Specifies sender of event. // e - Specifies event arguments. // private void OnProcessExit( object sender, EventArgs e ) { DisposeAsClient(); } // // Summary // Handles service stopping event. // // Remarks // The event is raised from a thread running as system. // // Parameters // sender - Specifies sender of event. // e - Specifies event arguments. // private void OnServiceStopping( object sender, EventArgs e ) { DisposeAsClient(); } // // Summary // Impersonates the client before disposing. // private void DisposeAsClient() { try { // // Impersonate the client before disposing as the cryptographic // context uses the security context of the caller. // WindowsImpersonationContext context = m_identity.Impersonate(); try { Dispose(); } finally { context.Undo(); } } catch( Exception ) { throw; } } protected void ThrowIfDisposed() { if ( m_isDisposed ) { throw IDT.ThrowHelperError( new ObjectDisposedException( "CryptoSession " + m_sessionid ) ); } } // // Summary: // Called when it is time to Dispose // protected virtual void OnDispose() { } // // Summary: // Called when it is time to Serialize. // protected virtual void OnWrite( BinaryWriter bwriter ) { } // // Summary: // Removes any references to this cryptosession from the global table, stops listening for timers and stops // listening for process exit. public void Dispose() { IDT.TraceDebug( "disposing a cryptosession object" ); bool didDispose = false; lock ( m_syncRoot ) { if ( !m_isDisposed ) { m_isDisposed = true; didDispose = true; // // Remove service stopping event handler from registered handlers. // if( null != m_serviceStoppingHandler ) { InfoCardService.Stopping -= m_serviceStoppingHandler; m_serviceStoppingHandler = null; } if ( null != m_process ) { if ( null != m_processExitHandler ) { m_process.Exited -= m_processExitHandler; m_processExitHandler = null; } m_process = null; } if ( null != m_timer ) { m_timer.Dispose(); m_timer = null; } OnDispose(); } } if ( didDispose ) { lock ( s_syncRoot ) { s_sessionCollection.Remove( m_sessionid ); } } } // // Summary: // Creates a CryptoSession object corresponding to the type of key passed in. // static public CryptoSession Create( Process process, DateTime expiration, WindowsIdentity identity, RSACryptoServiceProvider key ) { return new AsymmetricCryptoSession( process, expiration, identity, key ); } // // Summary: // Creates a CryptoSession object corresponding to the type of key passed in. // static public CryptoSession Create( Process process, DateTime expiration, WindowsIdentity identity, byte[ ] key ) { return new SymmetricCryptoSession( process, expiration, identity, key ); } // // Summary: // Looks up an existing CryptoSession based on sessionid and processid. // static public CryptoSession Find( int sessionId, uint processId, SecurityIdentifier clientSid ) { CryptoSession session; lock ( s_syncRoot ) { if ( s_sessionCollection.ContainsHandle( sessionId ) ) { session = s_sessionCollection[ sessionId ]; } else { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceUnknownCryptoSessionId ) ) ); } if ( session.ProcessId != processId ) { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceUnknownCryptoSessionId ) ) ); } if ( session.ClientSid != clientSid ) { throw IDT.ThrowHelperError( new CommunicationException( SR.GetString( SR.ServiceUnknownCryptoSessionId ) ) ); } } return session; } } // // Summary: // A strictly Asymmetric CryptoSession. Wraps an RSACryptoServiceProvider. // internal class AsymmetricCryptoSession : CryptoSession { RSACryptoServiceProvider m_provider; public AsymmetricCryptoSession( Process process, DateTime expirationTime, WindowsIdentity identity, RSACryptoServiceProvider key ) : base( process, expirationTime, identity, key, CryptoSession.SessionType.Asymmetric ) { // // due to the fact the handles must be closed as the user, // we can not let finialization dispose these objects. // // Since we will own the reference to the RSACryptoServiceProvider // we do not need to duplicate it // m_provider = key; } protected override void OnWrite( BinaryWriter bwriter ) { bwriter.Write( m_provider.KeySize ); Utility.SerializeString( bwriter, m_provider.KeyExchangeAlgorithm ); Utility.SerializeString( bwriter, m_provider.SignatureAlgorithm ); } protected override void OnDispose() { m_provider.Clear(); // // Dispose this explicitly, as the keys are created using // the user's identity. If the finallizer gets it, it will throw // becuase it always runs as LSA. // ((IDisposable)m_provider).Dispose(); m_provider = null; } // // Summary: // Encrypts a buffer of data. // // Paramters: // inData - The data to encyrpt. // // Returns: // Returns a buffer of encrypted data. // public byte[] Encrypt( bool fOAEP, byte[] inData ) { ThrowIfDisposed(); return m_provider.Encrypt( inData, fOAEP ); } // // Summary: // Decrypts a buffer of data. // // Paramters: // inData - The data to decyrpt. // // Returns: // Returns a buffer of decrypted data. // public byte[] Decrypt( bool fOAEP, byte[] inData ) { ThrowIfDisposed(); return m_provider.Decrypt( inData, fOAEP ); } // // Summary: // Signs a hash. // // Parameters: // hash - The hash to sign. // hashAlgOid - A string OID that identifies the algorithm used to create the hash. // // Returns: // Returns a signature. // public byte[] SignHash( byte[] hash, string hashAlgOid ) { ThrowIfDisposed(); return m_provider.SignHash( hash, hashAlgOid ); } // // Summary: // Verifies that a hash and signature match. // // Parameters: // hash - The hash to sign. // hashAlgOid - A string OID that identifies the algorithm used to create the hash. // sig - A signature that should match the hash. // // Returns: // true if the hash and signature match, otherwise false. // public bool VerifyHash( byte[] hash, string hashAlgOid, byte[] sig ) { ThrowIfDisposed(); return m_provider.VerifyHash( hash, hashAlgOid, sig ); } } // // Summary: // A strictly SymmetricCryptoSession. Currently wraps a RijndaelManaged instance. // internal class SymmetricCryptoSession : CryptoSession { public enum Direction { Encrypt = 1, Decrypt = 2 }; SymmetricAlgorithm m_alg; public SymmetricCryptoSession( Process process, DateTime expiration, WindowsIdentity identity, byte[] key ) : base( process, expiration, identity, key, CryptoSession.SessionType.Symmetric ) { m_alg = new RijndaelManaged(); m_alg.Key = key; } protected override void OnDispose() { m_alg.Clear(); // // Dispose this explicitly, as the keys are created using // the user's identity. If the finallizer gets it, it will throw // becuase it always runs as LSA. // ((IDisposable)m_alg).Dispose(); m_alg = null; } protected override void OnWrite(BinaryWriter bwriter) { bwriter.Write( m_alg.KeySize ); bwriter.Write( m_alg.BlockSize ); bwriter.Write( m_alg.FeedbackSize ); } public byte[] GenerateDerivedKey( string algorithmUri, byte[] label, byte[] nonce, int derivedKeyLength, int offset) { if( algorithmUri == SecurityAlgorithms.Psha1KeyDerivation || algorithmUri == SecurityAlgorithms.Psha1KeyDerivationDec2005 ) { return new Psha1DerivedKeyGenerator( m_alg.Key ).GenerateDerivedKey( label, nonce, derivedKeyLength, offset ); } else { throw IDT.ThrowHelperWarning( new InfoCardArgumentException( SR.GetString( SR.ServiceUnsupportedKeyDerivationAlgorithm, algorithmUri ) ) ); } } // // Summary: // Wraps the CreateDecryptor/CreateEncryptor of an AsymmetricAlgorithm, and returns a TransformCryptoSession. // public TransformCryptoSession GetCryptoTransform( CipherMode mode, PaddingMode padding, int feedbackSize, Direction direction, byte[] iv ) { m_alg.Mode = mode; m_alg.Padding = padding; m_alg.IV = iv; ICryptoTransform icrypto; if ( Direction.Encrypt == direction ) { icrypto = m_alg.CreateEncryptor(); } else { icrypto = m_alg.CreateDecryptor(); } return new TransformCryptoSession( ProcessObj, Expiration, Identity, icrypto ); } // // Summary: // Returns a HashCryptoSession based on the key held by this session. // public HashCryptoSession GetKeyedHash() { KeyedHashAlgorithm keyedHashAlgorithm = new HMACSHA1( m_alg.Key ); keyedHashAlgorithm.Initialize(); return new HashCryptoSession( ProcessObj, Expiration, Identity, keyedHashAlgorithm ); } } // // Summary: // Wraps an ICryptoTransform and exports it from the service. // internal class TransformCryptoSession : CryptoSession { ICryptoTransform m_icrypto; public TransformCryptoSession( Process process, DateTime expiration, WindowsIdentity identity, ICryptoTransform icrypto ) : base( process, expiration, identity, icrypto, CryptoSession.SessionType.Transfrom ) { m_icrypto = icrypto; } protected override void OnDispose() { m_icrypto.Dispose(); } protected override void OnWrite(BinaryWriter bwriter) { bwriter.Write( m_icrypto.InputBlockSize ); bwriter.Write( m_icrypto.OutputBlockSize ); bwriter.Write( m_icrypto.CanTransformMultipleBlocks ); bwriter.Write( m_icrypto.CanReuseTransform ); } // // Summary: // Simple wrapper for the the ICryptoTransform.TransformBlock method. // public int TransformBlock( byte[] inData, out byte[] outData ) { int count; outData = new byte[ m_icrypto.OutputBlockSize ]; count = m_icrypto.TransformBlock( inData, 0, inData.Length, outData, 0 ); return count; } // // Summary: // Simple wrapper for the the ICryptoTransform.TransformFinalBlock method. // public byte[] TransformFinalBlock( byte[] inData ) { return m_icrypto.TransformFinalBlock( inData, 0, inData.Length ); } } // // Summary: // Wraps a KeyedHashAlgorithm. // internal class HashCryptoSession : CryptoSession { KeyedHashAlgorithm m_hash; public HashCryptoSession( Process process, DateTime expiration, WindowsIdentity identity, KeyedHashAlgorithm hash ) : base( process, expiration, identity, hash, CryptoSession.SessionType.Hash ) { m_hash = hash; } protected override void OnDispose() { m_hash.Clear(); // // Dispose this explicitly, as the keys are created using // the user's identity. If the finallizer gets it, it will throw // becuase it always runs as LSA. // ((IDisposable)m_hash).Dispose(); m_hash = null; } protected override void OnWrite(BinaryWriter bwriter) { bwriter.Write( m_hash.HashSize ); bwriter.Write( m_hash.InputBlockSize ); bwriter.Write( m_hash.OutputBlockSize ); bwriter.Write( m_hash.CanTransformMultipleBlocks ); bwriter.Write( m_hash.CanReuseTransform ); } // // Summary: // Uses the KeyedHashAlgorithm.TransformBlock method to implement the equivalent of the // KeyedHashAlgorithm.HashCore method. // public void HashCore( byte[] inData ) { m_hash.TransformBlock( inData, 0, inData.Length, null, 0 ); } // // Summary: // Uses the KeyedHashAlgorithm.TransformFinalBlock method to implement the equivalent of the // KeyedHashAlgorithm.HashFinal method. This method differs from the HashFinal method in the fact // that it takes the final buffer as input. // public byte[] HashFinal( byte[] inData ) { try { m_hash.TransformFinalBlock( inData, 0, inData.Length ); } finally { m_hash.Initialize(); } return m_hash.Hash; } } } // 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
- XAMLParseException.cs
- Sql8ExpressionRewriter.cs
- ArrayHelper.cs
- BitmapEffect.cs
- InheritedPropertyChangedEventArgs.cs
- ParseChildrenAsPropertiesAttribute.cs
- ApplicationServiceHelper.cs
- BinaryParser.cs
- ThemeDictionaryExtension.cs
- OleDbEnumerator.cs
- ProcessStartInfo.cs
- SqlUserDefinedTypeAttribute.cs
- _ConnectionGroup.cs
- TrackingProfileDeserializationException.cs
- DoubleAnimationClockResource.cs
- DynamicDiscoSearcher.cs
- ManifestResourceInfo.cs
- EditingCommands.cs
- ProgressChangedEventArgs.cs
- RowsCopiedEventArgs.cs
- StreamingContext.cs
- JoinGraph.cs
- InvalidChannelBindingException.cs
- XmlEncodedRawTextWriter.cs
- GridLengthConverter.cs
- UnmanagedMemoryStreamWrapper.cs
- ParserStreamGeometryContext.cs
- FloaterBaseParagraph.cs
- TextRunCacheImp.cs
- MetadataUtilsSmi.cs
- TemplateKey.cs
- CatalogZone.cs
- Pair.cs
- TextElementEditingBehaviorAttribute.cs
- SocketInformation.cs
- PrivateFontCollection.cs
- TypeLoadException.cs
- CodeRegionDirective.cs
- AuthenticationService.cs
- WorkflowShape.cs
- WorkflowMarkupSerializationManager.cs
- BrowserCapabilitiesCompiler.cs
- ThemeDirectoryCompiler.cs
- EntityTransaction.cs
- EventMappingSettings.cs
- DataSetMappper.cs
- EncoderParameters.cs
- MarshalDirectiveException.cs
- WebPartDisplayModeCollection.cs
- TrackingSection.cs
- PaintEvent.cs
- SafeLibraryHandle.cs
- LookupBindingPropertiesAttribute.cs
- ClientApiGenerator.cs
- TextTreeTextElementNode.cs
- SimpleHandlerFactory.cs
- MergeFailedEvent.cs
- RealizedColumnsBlock.cs
- SoapSchemaMember.cs
- ProfessionalColorTable.cs
- CodeAttributeDeclarationCollection.cs
- TextStore.cs
- BindingMAnagerBase.cs
- KerberosSecurityTokenProvider.cs
- SamlAssertionKeyIdentifierClause.cs
- DataGridCell.cs
- ReferenceEqualityComparer.cs
- DirectoryObjectSecurity.cs
- ClientProxyGenerator.cs
- MsmqHostedTransportManager.cs
- ApplicationManager.cs
- WindowsListViewItemCheckBox.cs
- TransactionFilter.cs
- XPathChildIterator.cs
- HWStack.cs
- MatrixConverter.cs
- CellParaClient.cs
- Facet.cs
- ServiceBusyException.cs
- HierarchicalDataTemplate.cs
- BitmapEffectOutputConnector.cs
- DefaultValueTypeConverter.cs
- AssemblyResolver.cs
- SQLInt32Storage.cs
- FormConverter.cs
- BatchParser.cs
- TableRowGroup.cs
- DiagnosticStrings.cs
- DateTimeUtil.cs
- TextRenderer.cs
- AssemblyCollection.cs
- StreamGeometry.cs
- RowTypePropertyElement.cs
- PipeException.cs
- ModuleConfigurationInfo.cs
- IDReferencePropertyAttribute.cs
- XmlSchemaSubstitutionGroup.cs
- TextRangeEditLists.cs
- HttpContextServiceHost.cs
- Debugger.cs