/// <summary>
/// Initialize authentication sequence for the client
/// </summary>
/// <returns>Token to be sent to the server</returns>
public SSPIResponse StartClientAuthentication(string targetMachine, uint targetPort)
{
// Save the server we're authenticating against
_targetMachineSPN = string.Format("MSSQLSvc/{0}:{1}", targetMachine, targetPort);
// Allocate a new instance of the client security buffer of the specified size
SecBufferDesc clientSecBuffer = new SecBufferDesc(_maxTokenBufferSize);
try
{
// Return code from the security API call
int secReturnCode = 0;
// New context attribute
uint contextAttribute = 0;
// Initialize token lifetime container
SecurityInteger lifeTime = new SecurityInteger();
// Delegate into security API
secReturnCode = SecurityWrapper.InitializeSecurityContext(ref _outboundCredential,
IntPtr.Zero,
_targetMachineSPN,
(int)(SecContextRequirements.MutualAuthentication | SecContextRequirements.Delegate | SecContextRequirements.ExtendedError),
0,
(int)SecDataRepresentation.Native,
IntPtr.Zero,
0,
out _clientContext,
out clientSecBuffer,
out contextAttribute,
out lifeTime);
// Check the return code
if (secReturnCode != (int)SecResult.Ok && secReturnCode != (int)SecResult.ContinueNeeded)
{
// Operation failed
throw new Win32Exception(secReturnCode, "Failed to generate initial security context");
}
// Convert to byte array and indication whether this is a last call
return new SSPIResponse(clientSecBuffer.ToArray(), secReturnCode != (int)SecResult.ContinueNeeded && secReturnCode != (int)SecResult.CompleteAndContinue);
}
finally
{
// Dispose server security buffer
clientSecBuffer.Dispose();
}
}