diff --git a/NSspi/Contexts/ClientContext.cs b/NSspi/Contexts/ClientContext.cs index 06be5ba..93b5e4e 100644 --- a/NSspi/Contexts/ClientContext.cs +++ b/NSspi/Contexts/ClientContext.cs @@ -9,12 +9,30 @@ using NSspi.Credentials; namespace NSspi.Contexts { + /// + /// Represents a client security context. Provides the means to establish a shared security context + /// with the server and to encrypt, decrypt, sign and verify messages to and from the server. + /// + /// + /// A client and server establish a shared security context by exchanging authentication tokens. Once + /// the shared context is established, the client and server can pass messages to each other, encrypted, + /// signed, etc, using the established parameters of the shared context. + /// public class ClientContext : Context { private ContextAttrib requestedAttribs; private ContextAttrib finalAttribs; private string serverPrinc; + /// + /// Initializes a new instance of the ClientContext class. The context is not fully initialized and usable + /// until the authentication cycle has been completed. + /// + /// The security credential to authenticate as. + /// The principle name of the server to connect to, or null for any. + /// Requested attributes that describe the desired properties of the + /// context once it is established. If a context cannot be established that satisfies the indicated + /// properties, the context initialization is aborted. public ClientContext( ClientCredential cred, string serverPrinc, ContextAttrib requestedAttribs ) : base( cred ) { @@ -22,6 +40,28 @@ namespace NSspi.Contexts this.requestedAttribs = requestedAttribs; } + /// + /// Performs and continues the authentication cycle. + /// + /// + /// This method is performed iteratively to start, continue, and end the authentication cycle with the + /// server. Each stage works by acquiring a token from one side, presenting it to the other side + /// which in turn may generate a new token. + /// + /// The cycle typically starts and ends with the client. On the first invocation on the client, + /// no server token exists, and null is provided in its place. The client returns its status, providing + /// its output token for the server. The server accepts the clients token as input and provides a + /// token as output to send back to the client. This cycle continues until the server and client + /// both indicate, typically, a SecurityStatus of 'OK'. + /// + /// The most recently received token from the server, or null if beginning + /// the authentication cycle. + /// The clients next authentication token in the authentication cycle. + /// A status message indicating the progression of the authentication cycle. + /// A status of 'OK' indicates that the cycle is complete, from the client's perspective. If the outToken + /// is not null, it must be sent to the server. + /// A status of 'Continue' indicates that the output token should be sent to the server and + /// a response should be anticipated. public SecurityStatus Init( byte[] serverToken, out byte[] outToken ) { TimeStamp rawExpiry = new TimeStamp(); diff --git a/NSspi/Contexts/ContextNativeMethods.cs b/NSspi/Contexts/ContextNativeMethods.cs index 08f845d..b3c6663 100644 --- a/NSspi/Contexts/ContextNativeMethods.cs +++ b/NSspi/Contexts/ContextNativeMethods.cs @@ -11,6 +11,9 @@ using NSspi.Contexts; namespace NSspi.Contexts { + /// + /// Declares native methods calls for security context-related win32 functions. + /// internal static class ContextNativeMethods { /* @@ -173,7 +176,15 @@ namespace NSspi.Contexts [DllImport( "Secur32.dll", EntryPoint = "RevertSecurityContext", CharSet = CharSet.Unicode )] internal static extern SecurityStatus RevertSecurityContext( ref RawSspiHandle contextHandle ); - + /// + /// Safely invokes the native EncryptMessage function, making sure that handle ref counting is + /// performed in a proper CER. + /// + /// + /// + /// + /// + /// internal static SecurityStatus SafeEncryptMessage( SafeContextHandle handle, int qualityOfProtection, @@ -216,6 +227,15 @@ namespace NSspi.Contexts return status; } + /// + /// Safely invokes the native DecryptMessage function, making sure that handle ref counting is + /// performed in a proper CER. + /// + /// + /// + /// + /// + /// internal static SecurityStatus SafeDecryptMessage( SafeContextHandle handle, int qualityOfProtection, @@ -258,6 +278,15 @@ namespace NSspi.Contexts return status; } + /// + /// Safely invokes the native MakeSignature function, making sure that handle ref counting is + /// performed in a proper CER. + /// + /// + /// + /// + /// + /// internal static SecurityStatus SafeMakeSignature( SafeContextHandle handle, int qualityOfProtection, @@ -300,6 +329,15 @@ namespace NSspi.Contexts return status; } + /// + /// Safely invokes the native VerifySignature function, making sure that handle ref counting is + /// performed in a proper CER. + /// + /// + /// + /// + /// + /// internal static SecurityStatus SafeVerifySignature( SafeContextHandle handle, int qualityOfProtection, diff --git a/NSspi/Contexts/ImpersonationHandle.cs b/NSspi/Contexts/ImpersonationHandle.cs index 56ff7aa..0e27d26 100644 --- a/NSspi/Contexts/ImpersonationHandle.cs +++ b/NSspi/Contexts/ImpersonationHandle.cs @@ -6,21 +6,27 @@ using System.Threading.Tasks; namespace NSspi.Contexts { + /// + /// Represents impersonation performed on a server on behalf of a client. + /// + /// + /// The handle controls the lifetime of impersonation, and will revert the impersonation + /// if it is disposed, or if it is finalized ie by being leaked and garbage collected. + /// + /// If the handle is accidentally leaked while operations are performed on behalf of the user, + /// impersonation may be reverted at any arbitrary time, perhaps during those operations. + /// This may lead to operations being performed in the security context of the server, + /// potentially leading to security vulnerabilities. + /// public class ImpersonationHandle : IDisposable { - // Notes: - // Impersonate: - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375497(v=vs.85).aspx - // - // Revert: - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa379446(v=vs.85).aspx - // - // QuerySecurityPkgInfo (to learn if it supports impersonation): - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa379359(v=vs.85).aspx - private bool disposed; private ServerContext server; + /// + /// Initializes a new instance of the ImpersonationHandle. Does not perform impersonation. + /// + /// The server context that is performing impersonation. internal ImpersonationHandle(ServerContext server) { this.server = server; @@ -32,6 +38,9 @@ namespace NSspi.Contexts Dispose( false ); } + /// + /// Reverts the impersonation. + /// public void Dispose() { Dispose( true ); diff --git a/NSspi/Contexts/SafeContextHandle.cs b/NSspi/Contexts/SafeContextHandle.cs index 7fbddf7..277614e 100644 --- a/NSspi/Contexts/SafeContextHandle.cs +++ b/NSspi/Contexts/SafeContextHandle.cs @@ -7,7 +7,9 @@ using System.Threading.Tasks; namespace NSspi.Contexts { - + /// + /// Captures an unmanaged security context handle. + /// public class SafeContextHandle : SafeSspiHandle { public SafeContextHandle() diff --git a/NSspi/Contexts/ServerContext.cs b/NSspi/Contexts/ServerContext.cs index 37bc0f2..fa09af7 100644 --- a/NSspi/Contexts/ServerContext.cs +++ b/NSspi/Contexts/ServerContext.cs @@ -34,6 +34,28 @@ namespace NSspi.Contexts /// public bool SupportsImpersonate { get; private set; } + /// + /// Performs and continues the authentication cycle. + /// + /// + /// This method is performed iteratively to continue and end the authentication cycle with the + /// client. Each stage works by acquiring a token from one side, presenting it to the other side + /// which in turn may generate a new token. + /// + /// The cycle typically starts and ends with the client. On the first invocation on the client, + /// no server token exists, and null is provided in its place. The client returns its status, providing + /// its output token for the server. The server accepts the clients token as input and provides a + /// token as output to send back to the client. This cycle continues until the server and client + /// both indicate, typically, a SecurityStatus of 'OK'. + /// + /// The most recently received token from the client. + /// The servers next authentication token in the cycle, that must + /// be sent to the client. + /// A status message indicating the progression of the authentication cycle. + /// A status of 'OK' indicates that the cycle is complete, from the servers's perspective. If the nextToken + /// is not null, it must be sent to the client. + /// A status of 'Continue' indicates that the output token should be sent to the client and + /// a response should be anticipated. public SecurityStatus AcceptToken( byte[] clientToken, out byte[] nextToken ) { SecureBuffer clientBuffer; @@ -125,6 +147,19 @@ namespace NSspi.Contexts return status; } + /// + /// Changes the current thread's security context to impersonate the user of the client. + /// + /// + /// Requires that the security package provided with the server's credentials, as well as the + /// client's credentials, support impersonation. + /// + /// Currently, only one thread may initiate impersonation per security context. Impersonation may + /// follow threads created by the initial impersonation thread, however. + /// + /// A handle to capture the lifetime of the impersonation. Dispose the handle to revert + /// impersonation. If the handle is leaked, the impersonation will automatically revert at a + /// non-deterministic time when the handle is finalized by the Garbage Collector. public ImpersonationHandle ImpersonateClient() { ImpersonationHandle handle; @@ -192,6 +227,9 @@ namespace NSspi.Contexts return handle; } + /// + /// Called by the ImpersonationHandle when it is released, either by disposale or finalization. + /// internal void RevertImpersonate() { bool gotRef = false;