From c64765fbdf4669a1bdda303acae723187d1da2f2 Mon Sep 17 00:00:00 2001 From: antiduh Date: Sat, 21 Jun 2014 16:32:34 +0000 Subject: [PATCH] I can now successfully call InitializeSecurityContext and get a status of ContinueNeeded. --- Contexts/ClientContext.cs | 49 ++++++++++++++++++++++++++----- Contexts/ContextAttrib.cs | 8 ++--- Contexts/SecureBuffer.cs | 20 +++++++++++++ Contexts/SecureBufferDataRep.cs | 18 ++++++++++++ Contexts/SecureBufferDesc.cs | 23 +++++++++++++++ Contexts/SecureBufferType.cs | 26 +++++++++++++++++ Credentials/Credential.cs | 6 ++-- NSspi.csproj | 5 ++++ NativeMethods.cs | 18 ++++++++---- Program.cs | 21 +++++++++---- SecurityStatus.cs | 52 +++++++++++++++++++++++++++------ 11 files changed, 210 insertions(+), 36 deletions(-) create mode 100644 Contexts/SecureBuffer.cs create mode 100644 Contexts/SecureBufferDataRep.cs create mode 100644 Contexts/SecureBufferDesc.cs create mode 100644 Contexts/SecureBufferType.cs diff --git a/Contexts/ClientContext.cs b/Contexts/ClientContext.cs index 209280a..53baa40 100644 --- a/Contexts/ClientContext.cs +++ b/Contexts/ClientContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -8,7 +9,7 @@ namespace NSspi.Contexts { public class ClientContext : Context { - public ClientContext( ClientCredential cred, string serverPrinc, ContextReqAttrib attribs ) + public ClientContext( ClientCredential cred, string serverPrinc, ContextAttrib attribs ) : base( cred ) { long credHandle = base.Credential.CredentialHandle; @@ -17,26 +18,58 @@ namespace NSspi.Contexts long newContextHandle = 0; long expiry = 0; - int newContextAttribs = 0; + ContextAttrib newContextAttribs = 0; SecurityStatus status; + SecureBufferDesc descriptor; + SecureBuffer secureBuffer; + byte[] tokenBuffer = new byte[100000]; + GCHandle tokenBufferHandle; + GCHandle bufferArrayHandle; + GCHandle descriptorHandle; + SecureBuffer[] bufferArray; + + tokenBufferHandle = GCHandle.Alloc( tokenBuffer, GCHandleType.Pinned ); + + secureBuffer = new SecureBuffer(); + secureBuffer.Type = BufferType.Token; + secureBuffer.Count = tokenBuffer.Length; + secureBuffer.Buffer = tokenBufferHandle.AddrOfPinnedObject(); + + bufferArray = new SecureBuffer[1]; + bufferArray[0] = secureBuffer; + bufferArrayHandle = GCHandle.Alloc( bufferArray, GCHandleType.Pinned ); - - status = NativeMethods.InitializeSecurityContext_Client( + descriptor = new SecureBufferDesc(); + descriptor.Version = SecureBufferDesc.ApiVersion; + descriptor.NumBuffers = bufferArray.Length; + descriptor.Buffers = bufferArrayHandle.AddrOfPinnedObject(); + + descriptorHandle = GCHandle.Alloc( descriptor, GCHandleType.Pinned ); + + status = NativeMethods.InitializeSecurityContext_Client1( ref credHandle, - ref prevContextHandle, + IntPtr.Zero, serverPrinc, + attribs, 0, - 0, - 0, + SecureBufferDataRep.Network, IntPtr.Zero, 0, ref newContextHandle, - IntPtr.Zero, + descriptorHandle.AddrOfPinnedObject(), ref newContextAttribs, ref expiry ); + descriptorHandle.Free(); + bufferArrayHandle.Free(); + tokenBufferHandle.Free(); + + secureBuffer = bufferArray[0]; + + Console.Out.WriteLine( status ); + base.ContextHandle = newContextHandle; } } diff --git a/Contexts/ContextAttrib.cs b/Contexts/ContextAttrib.cs index 9d2b5fb..2ead196 100644 --- a/Contexts/ContextAttrib.cs +++ b/Contexts/ContextAttrib.cs @@ -43,11 +43,6 @@ namespace NSspi.Contexts /// ReplayDetect = 0x00000004, - // The context must be allowed to detect out-of-order - // delivery of packets later through the message support - // functions. Use of this flag implies all of the - // conditions specified by the Integrity flag. - /// /// Detect messages received out of sequence when using the message support functionality. /// This flag implies all of the conditions specified by the Integrity flag - out-of-order sequence @@ -126,6 +121,9 @@ namespace NSspi.Contexts /// AcceptIntegrity = 0x00020000, + InitIdentify = 0x00020000, + AcceptIdentify = 0x00080000, + /// /// An Schannel provider connection is instructed to not authenticate the server automatically. /// diff --git a/Contexts/SecureBuffer.cs b/Contexts/SecureBuffer.cs new file mode 100644 index 0000000..adfffcf --- /dev/null +++ b/Contexts/SecureBuffer.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi.Contexts +{ + [StructLayout( LayoutKind.Sequential )] + public unsafe struct SecureBuffer + { + public int Count; + + public BufferType Type; + + // A pointer to a byte[] + public IntPtr Buffer; + } +} diff --git a/Contexts/SecureBufferDataRep.cs b/Contexts/SecureBufferDataRep.cs new file mode 100644 index 0000000..734fd26 --- /dev/null +++ b/Contexts/SecureBufferDataRep.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi.Contexts +{ + public enum SecureBufferDataRep : int + { + /* + #define SECURITY_NATIVE_DREP 0x00000010 + #define SECURITY_NETWORK_DREP 0x00000000 + */ + Nativee = 0x10, + Network = 0x00 + } +} diff --git a/Contexts/SecureBufferDesc.cs b/Contexts/SecureBufferDesc.cs new file mode 100644 index 0000000..5671e54 --- /dev/null +++ b/Contexts/SecureBufferDesc.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi.Contexts +{ + [StructLayout( LayoutKind.Sequential)] + public unsafe struct SecureBufferDesc + { + public int Version; + public int NumBuffers; + + // A pointer to a SecureBuffer[] + public IntPtr Buffers; + + public const int ApiVersion = 0; + } + + +} diff --git a/Contexts/SecureBufferType.cs b/Contexts/SecureBufferType.cs new file mode 100644 index 0000000..fdab381 --- /dev/null +++ b/Contexts/SecureBufferType.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi.Contexts +{ + public enum BufferType : int + { + Empty = 0x00, + Data = 0x01, + Token = 0x02, + Parameters = 0x03, + Missing = 0x04, + Extra = 0x05, + Trailer = 0x06, + Header = 0x07, + Padding = 0x09, + Stream = 0x0A, + ChannelBindings = 0x0E, + TargetHost = 0x10, + ReadOnlyFlag = unchecked( (int)0x80000000 ), + ReadOnlyWithChecksum = 0x10000000 + } +} diff --git a/Credentials/Credential.cs b/Credentials/Credential.cs index 724759a..eb3e042 100644 --- a/Credentials/Credential.cs +++ b/Credentials/Credential.cs @@ -78,7 +78,7 @@ namespace NSspi ref this.expiry ); - if ( status != SecurityStatus.Success ) + if ( status != SecurityStatus.OK ) { throw new SSPIException( "Failed to call AcquireCredentialHandle", status ); } @@ -117,7 +117,7 @@ namespace NSspi ref carrier ); - if ( status == SecurityStatus.Success ) + if ( status == SecurityStatus.OK ) { name = Marshal.PtrToStringUni( carrier.Name ); NativeMethods.FreeContextBuffer( carrier.Name ); @@ -155,7 +155,7 @@ namespace NSspi this.disposed = true; - if ( disposing && result != SecurityStatus.Success ) + if ( disposing && result != SecurityStatus.OK ) { throw new SSPIException( "Failed to release credentials handle", result ); } diff --git a/NSspi.csproj b/NSspi.csproj index e9ebffb..f23a55a 100644 --- a/NSspi.csproj +++ b/NSspi.csproj @@ -20,6 +20,7 @@ DEBUG;TRACE prompt 4 + true pdbonly @@ -47,6 +48,10 @@ + + + + diff --git a/NativeMethods.cs b/NativeMethods.cs index 85b8772..693108d 100644 --- a/NativeMethods.cs +++ b/NativeMethods.cs @@ -1,4 +1,5 @@ -using System; +using NSspi.Contexts; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -11,6 +12,11 @@ namespace NSspi { // http://msdn.microsoft.com/en-us/library/windows/desktop/aa374713(v=vs.85).aspx + // The REMSSPI sample: + + // A C++ pure client/server example: + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380536(v=vs.85).aspx + /* SECURITY_STATUS sResult = AcquireCredentialsHandle( NULL, // [in] name of principal. NULL = principal of current security context @@ -166,18 +172,18 @@ namespace NSspi CharSet = CharSet.Unicode, SetLastError = true )] - public static extern SecurityStatus InitializeSecurityContext_Client( + public static extern SecurityStatus InitializeSecurityContext_Client1( ref long credentialHandle, - ref long prevContextHandle, + IntPtr zero, string serverPrincipleName, - int requiredAttribs, + ContextAttrib requiredAttribs, int reserved1, - int dataRep, + SecureBufferDataRep dataRep, IntPtr inputBuffer, int reserved2, ref long newContextHandle, IntPtr outputBuffer, - ref int contextAttribs, + ref ContextAttrib contextAttribs, ref long expiry ); diff --git a/Program.cs b/Program.cs index dc35a5d..2327a41 100644 --- a/Program.cs +++ b/Program.cs @@ -1,4 +1,5 @@ -using System; +using NSspi.Contexts; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -37,13 +38,23 @@ namespace NSspi private static void CredTest() { - Credential cred = null; + ClientCredential cred = null; + ClientContext client; try { - cred = new Credential( SecurityPackage.Negotiate, CredentialType.Client ); + cred = new ClientCredential( SecurityPackage.Negotiate ); + Console.Out.WriteLine( cred.Name ); - string name = cred.Name; - Console.Out.WriteLine( name ); + client = new ClientContext( + cred, + "", + ContextAttrib.MutualAuth | + ContextAttrib.InitIdentify | + ContextAttrib.Confidentiality | + ContextAttrib.ReplayDetect | + ContextAttrib.SequenceDetect + ); + Console.Out.Flush(); } finally diff --git a/SecurityStatus.cs b/SecurityStatus.cs index 62ed767..34936b8 100644 --- a/SecurityStatus.cs +++ b/SecurityStatus.cs @@ -20,15 +20,49 @@ namespace NSspi #define SEC_E_NO_CREDENTIALS _HRESULT_TYPEDEF_(0x8009030EL) */ - public enum SecurityStatus : uint + public enum SecurityStatus : int { - Success = 0, - InsufficientMemory = 0x80090300, - InvalidHandle = 0x80090301, - InternalError = 0x80090304, - SecPkgNotFound = 0x80090305, - NotOwner = 0x80090306, - NoCredentials = 0x8009030E, - UnknownCredentials = 0x8009030D + // Success / Informational + OK = 0x00000000, + ContinueNeeded = unchecked( (int)0x00090312 ), + CompleteNeeded = unchecked( (int)0x00090313 ), + CompAndContinue = unchecked( (int)0x00090314 ), + ContextExpired = unchecked( (int)0x00090317 ), + CredentialsNeeded = unchecked( (int)0x00090320 ), + Renegotiate = unchecked( (int)0x00090321 ), + + // Errors + OutOfMemory = unchecked( (int)0x80090300 ), + InvalidHandle = unchecked( (int)0x80090301 ), + Unsupported = unchecked( (int)0x80090302 ), + TargetUnknown = unchecked( (int)0x80090303 ), + InternalError = unchecked( (int)0x80090304 ), + PackageNotFound = unchecked( (int)0x80090305 ), + NotOwner = unchecked( (int)0x80090306 ), + CannotInstall = unchecked( (int)0x80090307 ), + InvalidToken = unchecked( (int)0x80090308 ), + CannotPack = unchecked( (int)0x80090309 ), + QopNotSupported = unchecked( (int)0x8009030A ), + NoImpersonation = unchecked( (int)0x8009030B ), + LogonDenied = unchecked( (int)0x8009030C ), + UnknownCredentials = unchecked( (int)0x8009030D ), + NoCredentials = unchecked( (int)0x8009030E ), + MessageAltered = unchecked( (int)0x8009030F ), + OutOfSequence = unchecked( (int)0x80090310 ), + NoAuthenticatingAuthority = unchecked( (int)0x80090311 ), + IncompleteMessage = unchecked( (int)0x80090318 ), + IncompleteCredentials = unchecked( (int)0x80090320 ), + BufferNotEnough = unchecked( (int)0x80090321 ), + WrongPrincipal = unchecked( (int)0x80090322 ), + TimeSkew = unchecked( (int)0x80090324 ), + UntrustedRoot = unchecked( (int)0x80090325 ), + IllegalMessage = unchecked( (int)0x80090326 ), + CertUnknown = unchecked( (int)0x80090327 ), + CertExpired = unchecked( (int)0x80090328 ), + AlgorithmMismatch = unchecked( (int)0x80090331 ), + SecurityQosFailed = unchecked( (int)0x80090332 ), + SmartcardLogonRequired = unchecked( (int)0x8009033E ), + UnsupportedPreauth = unchecked( (int)0x80090343 ), + BadBinding = unchecked( (int)0x80090346 ) } }