diff --git a/NSspi/Contexts/Context.cs b/NSspi/Contexts/Context.cs index 9d56176..68252ed 100644 --- a/NSspi/Contexts/Context.cs +++ b/NSspi/Contexts/Context.cs @@ -11,9 +11,24 @@ using NSspi.Credentials; namespace NSspi.Contexts { - public class Context : IDisposable + /// + /// Represents a security context and provides common functionality required for all security + /// contexts. + /// + /// + /// This class is abstract and has a protected constructor and Initialize method. The exact + /// initialization implementation is provided by a subclasses, which may perform initialization + /// in a variety of manners. + /// + public abstract class Context : IDisposable { - public Context( Credential cred ) + /// + /// Performs basic initialization of a new instance of the Context class. + /// Initialization is not complete until the ContextHandle property has been set + /// and the Initialize method has been called. + /// + /// + protected Context( Credential cred ) { this.Credential = cred; @@ -28,10 +43,19 @@ namespace NSspi.Contexts /// public bool Initialized { get; private set; } + /// + /// The credential being used by the context to authenticate itself to other actors. + /// protected Credential Credential { get; private set; } + /// + /// A reference to the security context's handle. + /// public SafeContextHandle ContextHandle { get; private set; } + /// + /// The name of the authenticating authority for the context. + /// public string AuthorityName { get @@ -41,6 +65,9 @@ namespace NSspi.Contexts } } + /// + /// The logon username that the context represents. + /// public string ContextUserName { get @@ -50,8 +77,14 @@ namespace NSspi.Contexts } } + /// + /// The UTC time when the context expires. + /// public DateTime Expiry { get; private set; } + /// + /// Whether the context has been disposed. + /// public bool Disposed { get; private set; } /// @@ -64,12 +97,19 @@ namespace NSspi.Contexts this.Initialized = true; } + /// + /// Releases all resources associated with the context. + /// public void Dispose() { Dispose( true ); GC.SuppressFinalize( this ); } + /// + /// Releases resources associated with the context. + /// + /// If true, release managed resources, else release only unmanaged resources. protected virtual void Dispose( bool disposing ) { if( this.Disposed ) { return; } @@ -83,18 +123,19 @@ namespace NSspi.Contexts } /// - /// Encrypts the byte array using the context's session key. The encrypted data is stored in a new - /// byte array, which is formatted such that the first four bytes are the original message length - /// as an unsigned integer and the remaining bytes are the encrypted bytes of the original message. + /// Encrypts the byte array using the context's session key. /// /// - /// The resulting byte array stores the SSPI buffer data in the following buffer format: - /// - Token - /// - Data - /// - Padding + /// The structure of the returned data is as follows: + /// - 2 bytes, an unsigned big-endian integer indicating the length of the trailer buffer size + /// - 4 bytes, an unsigned big-endian integer indicating the length of the message buffer size. + /// - 2 bytes, an unsigned big-endian integer indicating the length of the encryption padding buffer size. + /// - The trailer buffer + /// - The message buffer + /// - The padding buffer. /// - /// - /// + /// The raw message to encrypt. + /// The packed and encrypted message. public byte[] Encrypt( byte[] input ) { // The message is encrypted in place in the buffer we provide to Win32 EncryptMessage @@ -163,6 +204,20 @@ namespace NSspi.Contexts return result; } + /// + /// Decrypts a previously encrypted message. + /// + /// + /// The expected format of the buffer is as follows: + /// - 2 bytes, an unsigned big-endian integer indicating the length of the trailer buffer size + /// - 4 bytes, an unsigned big-endian integer indicating the length of the message buffer size. + /// - 2 bytes, an unsigned big-endian integer indicating the length of the encryption padding buffer size. + /// - The trailer buffer + /// - The message buffer + /// - The padding buffer. + /// + /// The packed and encrypted data. + /// The original plaintext message. public byte[] Decrypt( byte[] input ) { SecPkgContext_Sizes sizes; @@ -263,6 +318,18 @@ namespace NSspi.Contexts return result; } + /// + /// Signs the message using the context's session key. + /// + /// + /// The structure of the returned buffer is as follows: + /// - 4 bytes, unsigned big-endian integer indicating the length of the plaintext message + /// - 2 bytes, unsigned big-endian integer indicating the length of the signture + /// - The plaintext message + /// - The message's signature. + /// + /// + /// public byte[] MakeSignature( byte[] message ) { SecurityStatus status = SecurityStatus.InternalError; @@ -322,6 +389,19 @@ namespace NSspi.Contexts return outMessage; } + /// + /// Verifies the signature of a signed message + /// + /// + /// The expected structure of the signed message buffer is as follows: + /// - 4 bytes, unsigned integer in big endian format indicating the length of the plaintext message + /// - 2 bytes, unsigned integer in big endian format indicating the length of the signture + /// - The plaintext message + /// - The message's signature. + /// + /// The packed signed message. + /// The extracted original message. + /// True if the message has a valid signature, false otherwise. public bool VerifySignature( byte[] signedMessage, out byte[] origMessage ) { SecurityStatus status = SecurityStatus.InternalError; @@ -390,6 +470,10 @@ namespace NSspi.Contexts } } + /// + /// Queries the security package's expections regarding message/token/signature/padding buffer sizes. + /// + /// private SecPkgContext_Sizes QueryBufferSizes() { SecPkgContext_Sizes sizes = new SecPkgContext_Sizes(); @@ -432,6 +516,11 @@ namespace NSspi.Contexts return sizes; } + /// + /// Queries a string-valued context attribute by the named attribute. + /// + /// The string-valued attribute to query. + /// private string QueryContextString(ContextQueryAttrib attrib) { SecPkgContext_String stringAttrib; @@ -492,6 +581,10 @@ namespace NSspi.Contexts return result; } + /// + /// Verifies that the object's lifecycle (initialization / disposition) state is suitable for using the + /// object. + /// private void CheckLifecycle() { if( this.Initialized == false )