static internal extern int InitializeSecurityContext(ref SecurityHandle phCredential, IntPtr phContext, string pszTargetName, uint fContextReq, int Reserved1, uint TargetDataRep, IntPtr pInput, int Reserved2, out SecurityHandle phNewContext, out SecBufferDesc pOutput, out uint pfContextAttr, out SecurityInteger ptsTimeStamp);
static internal extern int AcceptSecurityContext(ref SecurityHandle phCredential, ref SecurityHandle phContext, ref SecBufferDesc pInput, uint fContextReq, uint TargetDataRep, out SecurityHandle phNewContext, out SecBufferDesc pOutput, out uint pfContextAttr, out SecurityInteger ptsTimeStamp);
static internal extern int CompleteAuthToken(ref SecurityHandle phContext, out SecBufferDesc pOutput);
internal static extern int CompleteAuthToken(ref SecurityHandle phContext, out SecBufferDesc pOutput);
/// <summary> /// Initialize authentication sequence for the client /// </summary> /// <param name="clientToken">Payload received from the server</param> /// <returns>Token to be sent to the server</returns> public SSPIResponse ContinueClientAuthentication(byte[] clientToken) { // Wrap client token with the security buffer SecBufferDesc serverSecBuffer = new SecBufferDesc(clientToken); try { // 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, ref _clientContext, _targetMachineSPN, (int)(SecContextRequirements.MutualAuthentication | SecContextRequirements.Delegate | SecContextRequirements.ExtendedError), 0, (int)SecDataRepresentation.Native, ref serverSecBuffer, 0, out _clientContext, out clientSecBuffer, out contextAttribute, out lifeTime); // Check the return code if (secReturnCode != (int)SecResult.Ok && secReturnCode != (int)SecResult.ContinueNeeded && secReturnCode != (int)SecResult.CompleteAndContinue) { // Operation failed throw new Win32Exception(secReturnCode, "Failed to generate security context"); } // NOTE: Digest SSP call to "CompleteAuthToken" is intentionally omitted because we don't support Digest today. // 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 client security buffer clientSecBuffer.Dispose(); } } finally { // Dispose server security buffer serverSecBuffer.Dispose(); } }
/// <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(); } }
/// <summary> /// Continue authentication sequence for the server /// </summary> /// <param name="clientToken">Token received from the client</param> /// <returns>Token to be sent to the client in response</returns> public SSPIResponse ContinueServerAuthentication(byte[] clientToken) { // Wrap client token with the security buffer SecBufferDesc clientSecBuffer = new SecBufferDesc(clientToken); try { // Allocate a new instance of the server security buffer of the specified size SecBufferDesc serverSecBuffer = 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.AcceptSecurityContext(ref _inboundCredential, ref _serverContext, ref clientSecBuffer, (int)SecContextRequirements.MutualAuthentication, (int)SecDataRepresentation.Native, out _serverContext, out serverSecBuffer, 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 accept security context"); } // Convert to byte array and indication whether this is a last call return new SSPIResponse(serverSecBuffer.ToArray(), secReturnCode != (int)SecResult.ContinueNeeded); } finally { // Dispose server security buffer serverSecBuffer.Dispose(); } } finally { // Dispose client security buffer clientSecBuffer.Dispose(); } }