diff --git a/Contexts/ClientContext.cs b/Contexts/ClientContext.cs
index 17744ac..c4270c2 100644
--- a/Contexts/ClientContext.cs
+++ b/Contexts/ClientContext.cs
@@ -50,14 +50,18 @@ namespace NSspi.Contexts
}
outTokenBuffer = new SecureBuffer( new byte[12288], BufferType.Token );
- serverBuffer = new SecureBuffer( serverToken, BufferType.Token );
+ serverBuffer = null;
+ if ( serverToken != null )
+ {
+ serverBuffer = new SecureBuffer( serverToken, BufferType.Token );
+ }
using ( outAdapter = new SecureBufferAdapter( outTokenBuffer ) )
{
if ( prevContextHandle == 0 )
{
- status = NativeMethods.InitializeSecurityContext_1(
+ status = ContextNativeMethods.InitializeSecurityContext_1(
ref credHandle,
IntPtr.Zero,
this.serverPrinc,
@@ -76,7 +80,7 @@ namespace NSspi.Contexts
{
using ( serverAdapter = new SecureBufferAdapter( serverBuffer ) )
{
- status = NativeMethods.InitializeSecurityContext_2(
+ status = ContextNativeMethods.InitializeSecurityContext_2(
ref credHandle,
ref prevContextHandle,
this.serverPrinc,
diff --git a/Contexts/Context.cs b/Contexts/Context.cs
index cac0346..89e4aa1 100644
--- a/Contexts/Context.cs
+++ b/Contexts/Context.cs
@@ -1,4 +1,5 @@
-using System;
+using NSspi.Contexts;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -42,7 +43,7 @@ namespace NSspi
}
long contextHandleCopy = this.ContextHandle;
- NativeMethods.DeleteSecurityContext( ref contextHandleCopy );
+ ContextNativeMethods.DeleteSecurityContext( ref contextHandleCopy );
this.ContextHandle = 0;
diff --git a/Contexts/ContextNativeMethods.cs b/Contexts/ContextNativeMethods.cs
index dd57f76..32fb3ed 100644
--- a/Contexts/ContextNativeMethods.cs
+++ b/Contexts/ContextNativeMethods.cs
@@ -61,5 +61,92 @@ namespace NSspi.Contexts
ref ContextAttrib outputAttribs,
ref long expiry
);
+
+ // When used in the ClientContext:
+ /*
+ SECURITY_STATUS sResult = InitializeSecurityContext(
+ phCredential, // [in] handle to the credentials
+ NULL, // [in/out] handle of partially formed context. Always NULL the first time through
+ pwszServerPrincipalName, // [in] name of the target of the context. Not needed by NTLM
+ reqContextAttributes, // [in] required context attributes
+ 0, // [reserved] reserved; must be zero
+ SECURITY_NATIVE_DREP, // [in] data representation on the target
+ NULL, // [in/out] pointer to the input buffers. Always NULL the first time through
+ 0, // [reserved] reserved; must be zero
+ this->contextHandle, // [in/out] receives the new context handle (must be pre-allocated)
+ &outBuffDesc, // [out] pointer to the output buffers
+ pulContextAttributes, // [out] receives the context attributes
+ &tsLifeSpan // [out] receives the life span of the security context
+ );
+ */
+ /*
+ SECURITY_STATUS SEC_Entry InitializeSecurityContext(
+ _In_opt_ PCredHandle phCredential,
+ _In_opt_ PCtxtHandle phContext,
+ _In_opt_ SEC_CHAR *pszTargetName,
+ _In_ ULONG fContextReq,
+ _In_ ULONG Reserved1,
+ _In_ ULONG TargetDataRep,
+ _In_opt_ PSecBufferDesc pInput,
+ _In_ ULONG Reserved2,
+ _Inout_opt_ PCtxtHandle phNewContext,
+ _Inout_opt_ PSecBufferDesc pOutput,
+ _Out_ PULONG pfContextAttr,
+ _Out_opt_ PTimeStamp ptsExpiry
+ );
+ */
+
+ [DllImport(
+ "Secur32.dll",
+ EntryPoint = "InitializeSecurityContext",
+ CallingConvention = CallingConvention.Winapi,
+ CharSet = CharSet.Unicode,
+ SetLastError = true
+ )]
+ public static extern SecurityStatus InitializeSecurityContext_1(
+ ref long credentialHandle,
+ IntPtr zero,
+ string serverPrincipleName,
+ ContextAttrib requiredAttribs,
+ int reserved1,
+ SecureBufferDataRep dataRep,
+ IntPtr inputBuffer,
+ int reserved2,
+ ref long newContextHandle,
+ IntPtr outputBuffer,
+ ref ContextAttrib contextAttribs,
+ ref long expiry
+ );
+
+ [DllImport(
+ "Secur32.dll",
+ EntryPoint = "InitializeSecurityContext",
+ CallingConvention = CallingConvention.Winapi,
+ CharSet = CharSet.Unicode,
+ SetLastError = true
+ )]
+ public static extern SecurityStatus InitializeSecurityContext_2(
+ ref long credentialHandle,
+ ref long previousHandle,
+ string serverPrincipleName,
+ ContextAttrib requiredAttribs,
+ int reserved1,
+ SecureBufferDataRep dataRep,
+ IntPtr inputBuffer,
+ int reserved2,
+ ref long newContextHandle,
+ IntPtr outputBuffer,
+ ref ContextAttrib contextAttribs,
+ ref long expiry
+ );
+
+ [DllImport(
+ "Secur32.dll",
+ EntryPoint = "DeleteSecurityContext",
+ CallingConvention = CallingConvention.Winapi,
+ CharSet = CharSet.Unicode,
+ SetLastError = true
+ )]
+ public static extern SecurityStatus DeleteSecurityContext( ref long contextHandle );
}
}
diff --git a/Contexts/ServerContext.cs b/Contexts/ServerContext.cs
index 5776670..5bec16b 100644
--- a/Contexts/ServerContext.cs
+++ b/Contexts/ServerContext.cs
@@ -75,6 +75,16 @@ namespace NSspi.Contexts
{
nextToken = null;
this.complete = true;
+
+ if ( outBuffer.Length != 0 )
+ {
+ nextToken = new byte[outBuffer.Length];
+ Array.Copy( outBuffer.Buffer, nextToken, nextToken.Length );
+ }
+ else
+ {
+ nextToken = null;
+ }
}
else if ( status == SecurityStatus.ContinueNeeded )
{
diff --git a/NSspi.csproj b/NSspi.csproj
index baacf47..b18a9bc 100644
--- a/NSspi.csproj
+++ b/NSspi.csproj
@@ -48,6 +48,7 @@
+
diff --git a/NativeMethods.cs b/NativeMethods.cs
index 432a4dd..64b7f4e 100644
--- a/NativeMethods.cs
+++ b/NativeMethods.cs
@@ -129,93 +129,5 @@ namespace NSspi
public IntPtr Name;
}
-
-
- // When used in the ClientContext:
- /*
- SECURITY_STATUS sResult = InitializeSecurityContext(
- phCredential, // [in] handle to the credentials
- NULL, // [in/out] handle of partially formed context. Always NULL the first time through
- pwszServerPrincipalName, // [in] name of the target of the context. Not needed by NTLM
- reqContextAttributes, // [in] required context attributes
- 0, // [reserved] reserved; must be zero
- SECURITY_NATIVE_DREP, // [in] data representation on the target
- NULL, // [in/out] pointer to the input buffers. Always NULL the first time through
- 0, // [reserved] reserved; must be zero
- this->contextHandle, // [in/out] receives the new context handle (must be pre-allocated)
- &outBuffDesc, // [out] pointer to the output buffers
- pulContextAttributes, // [out] receives the context attributes
- &tsLifeSpan // [out] receives the life span of the security context
- );
- */
- /*
- SECURITY_STATUS SEC_Entry InitializeSecurityContext(
- _In_opt_ PCredHandle phCredential,
- _In_opt_ PCtxtHandle phContext,
- _In_opt_ SEC_CHAR *pszTargetName,
- _In_ ULONG fContextReq,
- _In_ ULONG Reserved1,
- _In_ ULONG TargetDataRep,
- _In_opt_ PSecBufferDesc pInput,
- _In_ ULONG Reserved2,
- _Inout_opt_ PCtxtHandle phNewContext,
- _Inout_opt_ PSecBufferDesc pOutput,
- _Out_ PULONG pfContextAttr,
- _Out_opt_ PTimeStamp ptsExpiry
- );
- */
-
- [DllImport(
- "Secur32.dll",
- EntryPoint = "InitializeSecurityContext",
- CallingConvention = CallingConvention.Winapi,
- CharSet = CharSet.Unicode,
- SetLastError = true
- )]
- public static extern SecurityStatus InitializeSecurityContext_1(
- ref long credentialHandle,
- IntPtr zero,
- string serverPrincipleName,
- ContextAttrib requiredAttribs,
- int reserved1,
- SecureBufferDataRep dataRep,
- IntPtr inputBuffer,
- int reserved2,
- ref long newContextHandle,
- IntPtr outputBuffer,
- ref ContextAttrib contextAttribs,
- ref long expiry
- );
-
- [DllImport(
- "Secur32.dll",
- EntryPoint = "InitializeSecurityContext",
- CallingConvention = CallingConvention.Winapi,
- CharSet = CharSet.Unicode,
- SetLastError = true
- )]
- public static extern SecurityStatus InitializeSecurityContext_2(
- ref long credentialHandle,
- ref long previousHandle,
- string serverPrincipleName,
- ContextAttrib requiredAttribs,
- int reserved1,
- SecureBufferDataRep dataRep,
- IntPtr inputBuffer,
- int reserved2,
- ref long newContextHandle,
- IntPtr outputBuffer,
- ref ContextAttrib contextAttribs,
- ref long expiry
- );
-
- [DllImport(
- "Secur32.dll",
- EntryPoint = "DeleteSecurityContext",
- CallingConvention = CallingConvention.Winapi,
- CharSet = CharSet.Unicode,
- SetLastError = true
- )]
- public static extern SecurityStatus DeleteSecurityContext( ref long contextHandle );
}
}
diff --git a/Program.cs b/Program.cs
index 2327a41..568679d 100644
--- a/Program.cs
+++ b/Program.cs
@@ -38,15 +38,25 @@ namespace NSspi
private static void CredTest()
{
- ClientCredential cred = null;
- ClientContext client;
+ ClientCredential clientCred = null;
+ ClientContext client = null;
+
+ ServerCredential serverCred = null;
+ ServerContext server = null;
+
+ byte[] clientToken;
+ byte[] serverToken;
+
+ SecurityStatus clientStatus;
+ SecurityStatus serverStatus;
+
try
{
- cred = new ClientCredential( SecurityPackage.Negotiate );
- Console.Out.WriteLine( cred.Name );
+ clientCred = new ClientCredential( SecurityPackage.Negotiate );
+ Console.Out.WriteLine( clientCred.Name );
client = new ClientContext(
- cred,
+ clientCred,
"",
ContextAttrib.MutualAuth |
ContextAttrib.InitIdentify |
@@ -54,14 +64,56 @@ namespace NSspi
ContextAttrib.ReplayDetect |
ContextAttrib.SequenceDetect
);
+
+ serverCred = new ServerCredential( SecurityPackage.Negotiate );
+
+ server = new ServerContext(
+ serverCred,
+ ContextAttrib.MutualAuth |
+ ContextAttrib.AcceptIdentify |
+ ContextAttrib.Confidentiality |
+ ContextAttrib.ReplayDetect |
+ ContextAttrib.SequenceDetect
+ );
+
+ clientToken = null;
+ serverToken = null;
+
+ clientStatus = client.Init( serverToken, out clientToken );
+
+ while ( true )
+ {
+ serverStatus = server.AcceptToken( clientToken, out serverToken );
+
+ if ( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
+
+ clientStatus = client.Init( serverToken, out clientToken );
+
+ if ( serverStatus != SecurityStatus.ContinueNeeded && clientStatus != SecurityStatus.ContinueNeeded ) { break; }
+ }
Console.Out.Flush();
}
finally
{
- if( cred != null )
+ if ( server != null )
{
- cred.Dispose();
+ server.Dispose();
+ }
+
+ if ( client != null )
+ {
+ client.Dispose();
+ }
+
+ if( clientCred != null )
+ {
+ clientCred.Dispose();
+ }
+
+ if ( serverCred != null )
+ {
+ serverCred.Dispose();
}
}
}