コード例 #1
0
ファイル: sspi-server.c プロジェクト: Brainiarc7/pbis
static
DWORD
SignServer(
    IN INT nSocket,
    IN CredHandle *pServerCreds,
    IN ULONG AscFlags
    )
{
    DWORD dwError = ERROR_SUCCESS;
    ULONG ulQop = 0;
    INT nContextAcquired = 0;
    ULONG nIndex = 0;
    SecBuffer TransmitBuffer;
    SecBuffer MsgBuffer;
    SecBuffer WrapBuffers[2] = {0};
    SecBufferDesc WrapBufferDesc;
    CtxtHandle Context;
    SecPkgContext_Names Names;
    SecPkgContext_Sizes Sizes;
    SecPkgContext_SessionKey SessionKey;

    memset(&TransmitBuffer, 0, sizeof(SecBuffer));
    memset(&MsgBuffer, 0, sizeof(SecBuffer));
    memset(&WrapBufferDesc, 0, sizeof(SecBufferDesc));
    memset(&Context, 0, sizeof(CtxtHandle));
    memset(&Names, 0, sizeof(SecPkgContext_Names));
    memset(&Sizes, 0, sizeof(SecPkgContext_Sizes));
    memset(&SessionKey, 0, sizeof(SecPkgContext_SessionKey));

    /* Establish a context with the client */
    dwError = ServerEstablishContext(
        nSocket,
        pServerCreds,
        &Context,
        AscFlags
        );

    BAIL_ON_ERROR(dwError);

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_NAMES,
        &Names
        );

    if (dwError)
    {
        printf("Unable to query context: %d\n", dwError);
    }
    else
    {
        printf("Context is for user: %s\n", Names.sUserName);
    }

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_SESSION_KEY,
        &SessionKey
        );

    if (dwError)
    {
        printf("Unable to query context: %X\n", dwError);
    }
    else
    {
        printf("Session Key: ");
        for(nIndex = 0; nIndex < SessionKey.SessionKeyLength; nIndex++)
        {
            printf("%02X ", SessionKey.SessionKey[nIndex]);
        }
        printf("\n\n");
    }

    printf("Server accepted context successfully!\n");

    // for clean up... once we've established a context, we must clean it up on
    // future failures.
    nContextAcquired = 1;

    dwError = QueryContextAttributes
        (
        &Context,
        SECPKG_ATTR_SIZES,
        &Sizes
        );

    BAIL_ON_ERROR(dwError);

    /* Receive the sealed message token */
    dwError = RecvToken(nSocket, &TransmitBuffer);
    BAIL_ON_ERROR(dwError);

    printf("RECEIVED:\n");
    DumpBuffer(TransmitBuffer.pvBuffer, TransmitBuffer.cbBuffer);
    printf("\n");

    WrapBufferDesc.cBuffers = 2;
    WrapBufferDesc.pBuffers = WrapBuffers;
    WrapBufferDesc.ulVersion = SECBUFFER_VERSION;

    WrapBuffers[0].BufferType = SECBUFFER_TOKEN;
    WrapBuffers[0].pvBuffer = TransmitBuffer.pvBuffer;
    WrapBuffers[0].cbBuffer = Sizes.cbMaxSignature;

    WrapBuffers[1].BufferType = SECBUFFER_DATA;
    WrapBuffers[1].cbBuffer = TransmitBuffer.cbBuffer - Sizes.cbMaxSignature;
    WrapBuffers[1].pvBuffer = (PBYTE)TransmitBuffer.pvBuffer + Sizes.cbMaxSignature;

    dwError = DecryptMessage(
        &Context,
        &WrapBufferDesc,
        0,                  // no sequence number
        &ulQop
        );

    if (dwError)
    {
        // When we bail, this var will try to be freed which is a bad thing...
        // the memory will be freed when TransmitBuffer is freed, so it's ok
        // to set this buffer to NULL here.
        WrapBuffers[1].pvBuffer = NULL;
        printf("Unable to decrypt message\n");
    }

    BAIL_ON_ERROR(dwError);

    MsgBuffer = WrapBuffers[1];

    printf("Received message '%.*s' from client\n", MsgBuffer.cbBuffer, MsgBuffer.pvBuffer);

    /* Produce a signature block for the message */

    WrapBuffers[0] = MsgBuffer;

    WrapBuffers[1].BufferType = SECBUFFER_TOKEN;
    WrapBuffers[1].cbBuffer = Sizes.cbMaxSignature;
    WrapBuffers[1].pvBuffer = malloc(Sizes.cbMaxSignature);

    if (WrapBuffers[1].pvBuffer == NULL)
    {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        BAIL_ON_ERROR(dwError);
    }

    dwError = MakeSignature(
        &Context,
        0,
        &WrapBufferDesc,
        0
        );

    if (dwError)
    {
        printf("Unable to MakeSignature");
    }

    BAIL_ON_ERROR(dwError);

    free(TransmitBuffer.pvBuffer);

    TransmitBuffer = WrapBuffers[1];
    WrapBuffers[1].pvBuffer = NULL;
    WrapBuffers[1].cbBuffer = 0;

    /* Send the signature block to the client */

    dwError = SendToken(nSocket, &TransmitBuffer);
    BAIL_ON_ERROR(dwError);

    free(TransmitBuffer.pvBuffer);
    TransmitBuffer.pvBuffer = NULL;
    TransmitBuffer.cbBuffer = 0;

    /* Delete context */

    dwError = DeleteSecurityContext( &Context );
    BAIL_ON_ERROR(dwError);

finish:
    return dwError;
error:
    if (Names.sUserName)
    {
        FreeContextBuffer(Names.sUserName);
    }
    if (TransmitBuffer.pvBuffer)
    {
        free(TransmitBuffer.pvBuffer);
        TransmitBuffer.pvBuffer = NULL;
        TransmitBuffer.cbBuffer = 0;
    }
    if (WrapBuffers[1].pvBuffer)
    {
        free(WrapBuffers[1].pvBuffer);
        WrapBuffers[1].pvBuffer = NULL;
        WrapBuffers[1].cbBuffer = 0;
    }
    if (nContextAcquired)
    {
        DeleteSecurityContext(&Context);
    }
    goto finish;
}
コード例 #2
0
ファイル: sspi-server.c プロジェクト: Brainiarc7/pbis
static
DWORD
ServerEstablishContext(
    IN INT nSocket,
    IN CredHandle *pServerCreds,
    OUT CtxtHandle *pContext,
    IN ULONG AscFlags
    )
{
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwLoopError = ERROR_SUCCESS;
    ULONG nRetFlags = 0;
    SecBufferDesc InputDesc;
    SecBufferDesc OutputDesc;
    SecBuffer SendTokenBuffer;
    SecBuffer RecvTokenBuffer;
    TimeStamp Expiry;
    PCtxtHandle pContextHandle = NULL;
    INT nContextAcquired = 0;

    memset(&InputDesc, 0, sizeof(SecBufferDesc));
    memset(&OutputDesc, 0, sizeof(SecBufferDesc));
    memset(&SendTokenBuffer, 0, sizeof(SecBuffer));
    memset(&RecvTokenBuffer, 0, sizeof(SecBuffer));
    memset(&Expiry, 0, sizeof(TimeStamp));

    memset(pContext, 0, sizeof(CtxtHandle));

    InputDesc.cBuffers = 1;
    InputDesc.ulVersion = SECBUFFER_VERSION;
    InputDesc.pBuffers = &RecvTokenBuffer;

    OutputDesc.cBuffers = 1;
    OutputDesc.ulVersion = SECBUFFER_VERSION;
    OutputDesc.pBuffers = &SendTokenBuffer;

    printf("ASC flags requested (0x%08x):\n", AscFlags);
    DumpAscReqFlags(AscFlags);

    do
    {
        dwError = RecvToken(nSocket, &RecvTokenBuffer);
        BAIL_ON_ERROR(dwError);

        printf("RECEIVED:\n");
        DumpBuffer(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer);
        DumpNtlmMessage(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer);
        printf("\n");

        RecvTokenBuffer.BufferType = SECBUFFER_TOKEN;
        SendTokenBuffer.cbBuffer = 0;
        SendTokenBuffer.pvBuffer = NULL;
        SendTokenBuffer.BufferType = SECBUFFER_TOKEN;

        // we need to use dwLoopErr in this case because we may get
        // back a "continue" command.  In those cases, we still
        // need dwError to be used and set seperatly based on other
        // calls.
        dwLoopError = AcceptSecurityContext(
            pServerCreds,
            pContextHandle,
            &InputDesc,
            AscFlags,
            SECURITY_NATIVE_DREP,
            pContext,
            &OutputDesc,
            &nRetFlags,
            &Expiry
            );

        if (SEC_E_OK != dwLoopError && SEC_I_CONTINUE_NEEDED != dwLoopError)
        {
            dwError = dwLoopError;
            BAIL_ON_ERROR(dwError);
        }

        if (SEC_I_CONTINUE_NEEDED == dwLoopError)
        {
            printf("Context partially accepted...\n");
            DumpBuffer(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer);
            DumpNtlmMessage(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer);
            if (nRetFlags)
            {
                printf("ASC flags returned (0x%08x):\n", nRetFlags);
                DumpAscRetFlags(nRetFlags);
            }
            printf("\n");
        }
        else
        {
            printf("Context FULLY accepted!\n");
            printf("ASC flags returned (0x%08x):\n", nRetFlags);
            DumpAscRetFlags(nRetFlags);
            printf("\n");
        }

        nContextAcquired = 1;

        pContextHandle = pContext;
        free(RecvTokenBuffer.pvBuffer);
        RecvTokenBuffer.pvBuffer = NULL;

        if (SendTokenBuffer.cbBuffer != 0)
        {
            dwError = SendToken(nSocket, &SendTokenBuffer);
            BAIL_ON_ERROR(dwError);

            FreeContextBuffer(SendTokenBuffer.pvBuffer);
            SendTokenBuffer.pvBuffer = NULL;
        }

    } while (dwLoopError == SEC_I_CONTINUE_NEEDED);

finish:
    return dwError;
error:
    if (RecvTokenBuffer.pvBuffer)
    {
        free(RecvTokenBuffer.pvBuffer);
        RecvTokenBuffer.pvBuffer = NULL;
    }
    if (SendTokenBuffer.cbBuffer)
    {
        FreeContextBuffer(SendTokenBuffer.pvBuffer);
        SendTokenBuffer.pvBuffer = NULL;
        SendTokenBuffer.cbBuffer = 0;
    }
    if (nContextAcquired)
    {
        DeleteSecurityContext(pContext);
    }
    goto finish;
}
コード例 #3
0
SECURITY_STATUS ma_schannel_handshake_loop(MARIADB_PVIO *pvio, my_bool InitialRead, SecBuffer *pExtraData)
{
  SecBufferDesc   OutBuffer, InBuffer;
  SecBuffer       InBuffers[2], OutBuffers;
  DWORD           dwSSPIFlags, dwSSPIOutFlags, cbData, cbIoBuffer;
  TimeStamp       tsExpiry;
  SECURITY_STATUS rc;
  PUCHAR          IoBuffer;
  BOOL            fDoRead;
  MARIADB_TLS     *ctls= pvio->ctls;
  SC_CTX          *sctx= (SC_CTX *)ctls->ssl;


  dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
                ISC_REQ_REPLAY_DETECT |
                ISC_REQ_CONFIDENTIALITY |
                ISC_RET_EXTENDED_ERROR |
                ISC_REQ_ALLOCATE_MEMORY | 
                ISC_REQ_STREAM;


  /* Allocate data buffer */
  if (!(IoBuffer = LocalAlloc(LMEM_FIXED, SC_IO_BUFFER_SIZE)))
    return SEC_E_INSUFFICIENT_MEMORY;

  cbIoBuffer = 0;
  fDoRead = InitialRead;

  /* handshake loop: We will leave a handshake is finished
     or an error occurs */

  rc = SEC_I_CONTINUE_NEEDED;

  while (rc == SEC_I_CONTINUE_NEEDED ||
         rc == SEC_E_INCOMPLETE_MESSAGE ||
         rc == SEC_I_INCOMPLETE_CREDENTIALS )
  {
    /* Read data */
    if (rc == SEC_E_INCOMPLETE_MESSAGE ||
        !cbIoBuffer)
    {
      if(fDoRead)
      {
        cbData = (DWORD)pvio->methods->read(pvio, IoBuffer + cbIoBuffer, (size_t)(SC_IO_BUFFER_SIZE - cbIoBuffer));
        if (cbData == SOCKET_ERROR || cbData == 0)
        {
          rc = SEC_E_INTERNAL_ERROR;
          break;
        }
        cbIoBuffer += cbData;
      }
      else
        fDoRead = TRUE;
    }

    /* input buffers
       First buffer stores data received from server. leftover data
       will be stored in second buffer with BufferType SECBUFFER_EXTRA */

    InBuffers[0].pvBuffer   = IoBuffer;
    InBuffers[0].cbBuffer   = cbIoBuffer;
    InBuffers[0].BufferType = SECBUFFER_TOKEN;

    InBuffers[1].pvBuffer   = NULL;
    InBuffers[1].cbBuffer   = 0;
    InBuffers[1].BufferType = SECBUFFER_EMPTY;

    InBuffer.cBuffers       = 2;
    InBuffer.pBuffers       = InBuffers;
    InBuffer.ulVersion      = SECBUFFER_VERSION;


    /* output buffer */
    OutBuffers.pvBuffer  = NULL;
    OutBuffers.BufferType= SECBUFFER_TOKEN;
    OutBuffers.cbBuffer  = 0;

    OutBuffer.cBuffers      = 1;
    OutBuffer.pBuffers      = &OutBuffers;
    OutBuffer.ulVersion     = SECBUFFER_VERSION;


    rc = InitializeSecurityContextA(&sctx->CredHdl,
                                    &sctx->ctxt,
                                    NULL,
                                    dwSSPIFlags,
                                    0,
                                    SECURITY_NATIVE_DREP,
                                    &InBuffer,
                                    0,
                                    NULL,
                                    &OutBuffer,
                                    &dwSSPIOutFlags,
                                    &tsExpiry );


    if (rc == SEC_E_OK  ||
        rc == SEC_I_CONTINUE_NEEDED ||
        FAILED(rc) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
    {
      if(OutBuffers.cbBuffer && OutBuffers.pvBuffer)
      {
        cbData= (DWORD)pvio->methods->write(pvio, (uchar *)OutBuffers.pvBuffer, (size_t)OutBuffers.cbBuffer);
        if(cbData == SOCKET_ERROR || cbData == 0)
        {
          FreeContextBuffer(OutBuffers.pvBuffer);
          DeleteSecurityContext(&sctx->ctxt);
          return SEC_E_INTERNAL_ERROR;
        }

        /* Free output context buffer */
        FreeContextBuffer(OutBuffers.pvBuffer);
        OutBuffers.pvBuffer = NULL;
      }
    }

    /* check if we need to read more data */
    switch (rc) {
    case SEC_E_INCOMPLETE_MESSAGE:
      /* we didn't receive all data, so just continue loop */
      continue;
      break;
    case SEC_E_OK:
      /* handshake completed, but we need to check if extra
         data was sent (which contains encrypted application data) */
      if (InBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        if (!(pExtraData->pvBuffer= LocalAlloc(0, InBuffers[1].cbBuffer)))
          return SEC_E_INSUFFICIENT_MEMORY;
        
        MoveMemory(pExtraData->pvBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer );
        pExtraData->BufferType = SECBUFFER_TOKEN;
        pExtraData->cbBuffer   = InBuffers[1].cbBuffer;
      }
      else
      {
        pExtraData->BufferType= SECBUFFER_EMPTY;
        pExtraData->pvBuffer= NULL;
        pExtraData->cbBuffer= 0;
      }
    break;
 
    case SEC_I_INCOMPLETE_CREDENTIALS:
      /* Provided credentials didn't contain a valid client certificate.
         We will try to connect anonymously, using current credentials */
      fDoRead= FALSE;
      rc= SEC_I_CONTINUE_NEEDED;
      continue;
      break;
    default:
      if (FAILED(rc))
      {
        ma_schannel_set_sec_error(pvio, rc);
        goto loopend;
      }
      break;
    }

    if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
    {
      MoveMemory( IoBuffer, IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer), InBuffers[1].cbBuffer );
      cbIoBuffer = InBuffers[1].cbBuffer;
    }

    cbIoBuffer = 0;
  }
loopend:
  if (FAILED(rc)) 
    DeleteSecurityContext(&sctx->ctxt);
  LocalFree(IoBuffer);

  return rc;
}
コード例 #4
0
SECURITY_STATUS ma_schannel_client_handshake(MARIADB_TLS *ctls)
{
  MARIADB_PVIO *pvio;
  SECURITY_STATUS sRet;
  DWORD OutFlags;
  DWORD r;
  SC_CTX *sctx;
  SecBuffer ExtraData;
  DWORD SFlags= ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
                ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | 
                ISC_REQ_USE_SUPPLIED_CREDS |
                ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM;
  
  SecBufferDesc	BufferOut;
  SecBuffer  BuffersOut;

  if (!ctls || !ctls->pvio)
    return 1;

  pvio= ctls->pvio;
  sctx= (SC_CTX *)ctls->ssl;

  /* Initialie securifty context */
  BuffersOut.BufferType= SECBUFFER_TOKEN;
  BuffersOut.cbBuffer= 0;
  BuffersOut.pvBuffer= NULL;


  BufferOut.cBuffers= 1;
  BufferOut.pBuffers= &BuffersOut;
  BufferOut.ulVersion= SECBUFFER_VERSION;

  sRet = InitializeSecurityContext(&sctx->CredHdl,
                                    NULL,
                                    pvio->mysql->host,
                                    SFlags,
                                    0,
                                    SECURITY_NATIVE_DREP,
                                    NULL,
                                    0,
                                    &sctx->ctxt,
                                    &BufferOut,
                                    &OutFlags,
                                    NULL);

  if(sRet != SEC_I_CONTINUE_NEEDED)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    return sRet;
  }

  /* send client hello packaet */
  if(BuffersOut.cbBuffer != 0 && BuffersOut.pvBuffer != NULL)
  {  
    r= (DWORD)pvio->methods->write(pvio, (uchar *)BuffersOut.pvBuffer, (size_t)BuffersOut.cbBuffer);
    if (r <= 0)
    {
      sRet= SEC_E_INTERNAL_ERROR;
      goto end;
    }
  }
  sRet= ma_schannel_handshake_loop(pvio, TRUE, &ExtraData);

  /* allocate IO-Buffer for write operations: After handshake
  was successfull, we are able now to calculate payload */
  if ((sRet = QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_STREAM_SIZES, &sctx->Sizes )))
    goto end;

  sctx->IoBufferSize= SCHANNEL_PAYLOAD(sctx->Sizes);
  if (!(sctx->IoBuffer= (PUCHAR)LocalAlloc(0, sctx->IoBufferSize)))
  {
    sRet= SEC_E_INSUFFICIENT_MEMORY;
    goto end;
  }
    
  return sRet;
end:
  LocalFree(sctx->IoBuffer);
  sctx->IoBufferSize= 0;
  FreeContextBuffer(BuffersOut.pvBuffer);
  DeleteSecurityContext(&sctx->ctxt);
  return sRet;
}
コード例 #5
0
ファイル: sspisvcs.c プロジェクト: greenplum-db/gpclients
static
SECURITY_STATUS
SchannelClientHandshakeLoop(
	SOCKET		Socket,		/* in */
	PCredHandle	phCreds,	/* in */
	CtxtHandle	*phContext,	/* i-o */
	BOOL		fDoInitialRead,	/* in */
	SecBuffer	*pExtraData)	/* out */
{
	SecBufferDesc	InBuffer;
	SecBuffer	InBuffers[2];
	SecBufferDesc	OutBuffer;
	SecBuffer	OutBuffers[1];
	DWORD		dwSSPIFlags;
	DWORD		dwSSPIOutFlags;
	TimeStamp	tsExpiry;
	SECURITY_STATUS	scRet;
	DWORD		cbData;

	PUCHAR		IoBuffer;
	DWORD		cbIoBuffer;
	BOOL		fDoRead;
	int		retry_count;

	dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT	|
			ISC_REQ_REPLAY_DETECT	|
			ISC_REQ_CONFIDENTIALITY	|
			ISC_RET_EXTENDED_ERROR	|
			ISC_REQ_ALLOCATE_MEMORY	|
			ISC_REQ_STREAM;

	/*
	 * Allocate data buffer.
	 */

	IoBuffer = malloc(IO_BUFFER_SIZE);
	if (IoBuffer == NULL)
	{
		mylog("**** Out of memory (1)\n");
		return SEC_E_INTERNAL_ERROR;
	}

	cbIoBuffer = 0;
	fDoRead = fDoInitialRead;
	/* 
	 * Loop until the handshake is finished or an error occurs.
	 */

	retry_count = 0;
	scRet = SEC_I_CONTINUE_NEEDED;
	while (scRet == SEC_I_CONTINUE_NEEDED	||
		scRet == SEC_E_INCOMPLETE_MESSAGE	||
		scRet == SEC_I_INCOMPLETE_CREDENTIALS) 
	{
		/*
		 * Read data from server.
		 */
		if( 0 == cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE)
		{
			if (fDoRead)
			{
				cbData = recv(Socket, 
						IoBuffer + cbIoBuffer, 
						IO_BUFFER_SIZE - cbIoBuffer, 
						0);
				if (cbData == SOCKET_ERROR)
				{
					int	gerrno = SOCK_ERRNO;

					mylog("**** Error %d reading data from server\n", gerrno);
					switch (gerrno)
					{
						case EINTR:
							continue;
						case ECONNRESET:
							break;
						case EWOULDBLOCK:
							retry_count++;
							if (Socket_wait_for_ready(Socket, FALSE, retry_count) >= 0)
								continue;
						default:
							scRet = SEC_E_INTERNAL_ERROR;
							break;
					}
					break;
				}
				else if(cbData == 0)
				{
					mylog("**** Server unexpectedly disconnected\n");
					scRet = SEC_E_INTERNAL_ERROR;
					break;
				}
				mylog("%d bytes of handshake data received\n", cbData);
				cbIoBuffer += cbData;
				retry_count = 0;
			}
			else
			{
				fDoRead = TRUE;
			}
		}
		/*
		 * Set up the input buffers. Buffer 0 is used to pass in data
		 * received from the server. Schannel will consume some or all
		 * of this. Leftover data (if any) will be placed in buffer 1 and
		 * given a buffer type of SECBUFFER_EXTRA.
		 */
		InBuffers[0].pvBuffer	= IoBuffer;
		InBuffers[0].cbBuffer	= cbIoBuffer;
		InBuffers[0].BufferType	= SECBUFFER_TOKEN;

		InBuffers[1].pvBuffer	= NULL;
		InBuffers[1].cbBuffer	= 0;
		InBuffers[1].BufferType	= SECBUFFER_EMPTY;

		InBuffer.cBuffers	= 2;
		InBuffer.pBuffers	= InBuffers;
		InBuffer.ulVersion	= SECBUFFER_VERSION;

		/*
		 * Set up the output buffers. These are initialized to NULL
		 * so as to make it less likely we'll attempt to free random
		 * garbage later.
		 */

		OutBuffers[0].pvBuffer	= NULL;
		OutBuffers[0].BufferType= SECBUFFER_TOKEN;
		OutBuffers[0].cbBuffer	= 0;

		OutBuffer.cBuffers	= 1;
		OutBuffer.pBuffers	= OutBuffers;
		OutBuffer.ulVersion	= SECBUFFER_VERSION;

		/*
		 * Call InitializeSecurityContext.
		 */

		scRet = InitializeSecurityContext(phCreds,
						phContext,
						NULL,
						dwSSPIFlags,
						0,
						SECURITY_NATIVE_DREP,
						&InBuffer,
						0,
						NULL,
						&OutBuffer,
						&dwSSPIOutFlags,
						&tsExpiry);

		/*
		 * If InitializeSecurityContext was successful (or if the error was 
		 * one of the special extended ones), send the contends of the output
		 * buffer to the server.
		 */

		if( scRet == SEC_E_OK	||
		    scRet == SEC_I_CONTINUE_NEEDED	||
		    FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
		{
			if (OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
			{
				cbData = sendall(Socket,
						OutBuffers[0].pvBuffer,
						OutBuffers[0].cbBuffer);
				if (cbData == SOCKET_ERROR || cbData == 0)
				{
					mylog("**** Error %d sending data to server (2)\n", 
						SOCK_ERRNO);
					FreeContextBuffer(OutBuffers[0].pvBuffer);
					DeleteSecurityContext(phContext);
					return SEC_E_INTERNAL_ERROR;
				}

				mylog("%d bytes of handshake data sent\n", cbData);
				/* Free output buffer. */
				FreeContextBuffer(OutBuffers[0].pvBuffer);
				OutBuffers[0].pvBuffer = NULL;
			}
		}

		/*
		 * If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE,
		 * then we need to read more data from the server and try again.
		 */

		if (scRet == SEC_E_INCOMPLETE_MESSAGE)
		{
			continue;
		}

		/*
		 * If InitializeSecurityContext returned SEC_E_OK, then the 
		 * handshake completed successfully.
		 */

		if(scRet == SEC_E_OK)
		{
			/*
			 * If the "extra" buffer contains data, this is encrypted application
			 * protocol layer stuff. It needs to be saved. The application layer
			 * will later decrypt it with DecryptMessage.
			 */
			mylog("Handshake was successful\n");

			if (InBuffers[1].BufferType == SECBUFFER_EXTRA)
			{
				pExtraData->pvBuffer = malloc(InBuffers[1].cbBuffer);
				if (pExtraData->pvBuffer == NULL)
				{
					mylog("**** Out of memory (2)\n");
					return SEC_E_INTERNAL_ERROR;
				}

				memmove(pExtraData->pvBuffer,
					IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer),
					InBuffers[1].cbBuffer);

				pExtraData->cbBuffer   = InBuffers[1].cbBuffer;
				pExtraData->BufferType = SECBUFFER_TOKEN;

				mylog("%d bytes of app data was bundled with handshake data\n",
					pExtraData->cbBuffer);
			}
			else
			{
				pExtraData->pvBuffer   = NULL;
				pExtraData->cbBuffer   = 0;
				pExtraData->BufferType = SECBUFFER_EMPTY;
			}

			/*
			 * Bail out to quit
			 */

			break;
		}

		/*
		 * Check for fatal error.
		 */

		if(FAILED(scRet))
		{
			mylog("**** Error 0x%p returned by InitializeSecurityContext (2)\n", scRet);
			break;
		}

		/*
		 * If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS,
		 * then the server just requested client authentication. 
		 */

		if (scRet == SEC_I_INCOMPLETE_CREDENTIALS)
		{
			/*
			 * Busted. The server has requested client authentication and
			 * the credential we supplied didn't contain a client certificate.
			 *

			 * 
			 * This function will read the list of trusted certificate
			 * authorities ("issuers") that was received from the server
			 * and attempt to find a suitable client certificate that
			 * was issued by one of these. If this function is successful, 
			 * then we will connect using the new certificate. Otherwise,
			 * we will attempt to connect anonymously (using our current
			 * credentials).
			 */
            
			GetNewSchannelClientCredentials(phCreds, phContext);

			/* Go around again. */
			fDoRead = FALSE;
			scRet = SEC_I_CONTINUE_NEEDED;
			continue;
		}
		/*
		 * Copy any leftover data from the "extra" buffer, and go around
		 * again.
		 */

		if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
		{
			memmove(IoBuffer,
				IoBuffer + (cbIoBuffer - InBuffers[1].cbBuffer),
				InBuffers[1].cbBuffer);

			cbIoBuffer = InBuffers[1].cbBuffer;
		}
		else
		{
			cbIoBuffer = 0;
		}
	}

	/* Delete the security context in the case of a fatal error. */
	if (FAILED(scRet))
	{
		DeleteSecurityContext(phContext);
	}

	free(IoBuffer);

	return scRet;
}
コード例 #6
0
SECURITY_STATUS getToken(char **negotiateToken, WCHAR *targetName, WCHAR *hostName)
{
	//----------------------------------------------------------------------
	unsigned long cPackages;
	PSecPkgInfo PackageInfo;
	SECURITY_STATUS stat;

	// Get the name of the package
	stat = EnumerateSecurityPackages(
		&cPackages,
		&PackageInfo);

	if (stat != SEC_E_OK)
	{
		wprintf(
			L"Security function failed with error: %i\n",
			stat);
		return stat;
	}

	SEC_WCHAR *szPackage = PackageInfo->Name;
	unsigned long m_cbMaxToken = PackageInfo->cbMaxToken;

	PBYTE m_pOutBuf = (PBYTE)malloc(m_cbMaxToken);

	//--------------------------------------------------------------------

	CredHandle hCredential;
	TimeStamp tsExpiry;
	PSEC_WINNT_AUTH_IDENTITY_OPAQUE pAuthIdentity = NULL; // The structure for storing user data entered

	stat = AcquireCredentialsHandle(
		NULL,
		szPackage,
		SECPKG_CRED_OUTBOUND,
		NULL,
		pAuthIdentity,
		NULL,
		NULL,
		&hCredential,
		&tsExpiry);

	if (stat != SEC_E_OK)
	{
		wprintf(
			L"Credentials function failed with error: %i\n",
			stat);
		return stat;
	}

	//--------------------------------------------------------------------

	CtxtHandle		m_hCtxt;
	SecBufferDesc	outSecBufDesc;
	SecBuffer		outSecBuf;

	unsigned long	fContextAttr;


	// prepare output buffer
	outSecBufDesc.ulVersion = 0;
	outSecBufDesc.cBuffers = 1;
	outSecBufDesc.pBuffers = &outSecBuf;
	outSecBuf.cbBuffer = m_cbMaxToken;
	outSecBuf.BufferType = SECBUFFER_TOKEN;
	outSecBuf.pvBuffer = m_pOutBuf;

	stat = InitializeSecurityContext(
		&hCredential,
		NULL,
		targetName,
		ISC_REQ_CONFIDENTIALITY,
		0,	// reserved1
		SECURITY_NATIVE_DREP,
		NULL,
		0,	// reserved2
		&m_hCtxt,
		&outSecBufDesc,
		&fContextAttr,
		&tsExpiry);

	FreeCredentialsHandle(&hCredential);

	switch (stat)
	{
	case SEC_I_CONTINUE_NEEDED: 
	case SEC_I_COMPLETE_AND_CONTINUE: CompleteAuthToken(&m_hCtxt, &outSecBufDesc); break;
	case SEC_E_OK: break;
	default: return stat;
	}

	DeleteSecurityContext(&m_hCtxt);
	FreeContextBuffer(PackageInfo);

	if (outSecBuf.cbBuffer)
	{
		base64_encode(reinterpret_cast < char* > (m_pOutBuf), outSecBuf.cbBuffer, negotiateToken);
	}
	else
	{
		return -1;
	}

	if (strlen(*negotiateToken) < 500)
	{
		CREDUI_INFO creduiInfo = { 0 };
		creduiInfo.cbSize = sizeof(creduiInfo);
		// Change the message text and caption to the actual text for your dialog.
		SEC_WCHAR message[NI_MAXHOST];

		_snwprintf_s(
			message,
			NI_MAXHOST,
			_TRUNCATE,
			L"Enter your username and password to connect to %s",
			hostName);

		creduiInfo.pszCaptionText = L"Connect to the proxy-server";
		creduiInfo.pszMessageText = message;

		BOOL fSave = TRUE; // Checkmark "Remember user"

		
		stat = SspiPromptForCredentials(
			targetName,
			&creduiInfo,
			0,
			szPackage,
			NULL,
			&pAuthIdentity,
			&fSave,
			0);
	}

	return SEC_E_OK;
}
コード例 #7
0
ファイル: netconnection.c プロジェクト: GYGit/reactos
static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
{
    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
    SecHandle *cred = &cred_handle;
    BYTE *read_buf;
    SIZE_T read_buf_size = 2048;
    ULONG attrs = 0;
    CtxtHandle ctx;
    SSIZE_T size;
    int bits;
    const CERT_CONTEXT *cert;
    SECURITY_STATUS status;
    DWORD res = ERROR_SUCCESS;

    const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
        |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;

    if(!ensure_cred_handle())
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;

    if(compat_mode) {
        if(!have_compat_cred_handle)
            return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
        cred = &compat_cred_handle;
    }

    read_buf = heap_alloc(read_buf_size);
    if(!read_buf)
        return ERROR_OUTOFMEMORY;

    status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0,
            &ctx, &out_desc, &attrs, NULL);

    assert(status != SEC_E_OK);

    set_socket_blocking(connection, TRUE);

    while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) {
        if(out_buf.cbBuffer) {
            assert(status == SEC_I_CONTINUE_NEEDED);

            TRACE("sending %u bytes\n", out_buf.cbBuffer);

            size = sock_send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
            if(size != out_buf.cbBuffer) {
                ERR("send failed\n");
                status = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
                break;
            }

            FreeContextBuffer(out_buf.pvBuffer);
            out_buf.pvBuffer = NULL;
            out_buf.cbBuffer = 0;
        }

        if(status == SEC_I_CONTINUE_NEEDED) {
            assert(in_bufs[1].cbBuffer < read_buf_size);

            memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
            in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;

            in_bufs[1].BufferType = SECBUFFER_EMPTY;
            in_bufs[1].cbBuffer = 0;
            in_bufs[1].pvBuffer = NULL;
        }

        assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
        assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);

        if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
            BYTE *new_read_buf;

            new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
            if(!new_read_buf) {
                status = E_OUTOFMEMORY;
                break;
            }

            in_bufs[0].pvBuffer = read_buf = new_read_buf;
            read_buf_size += 1024;
        }

        size = sock_recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
        if(size < 1) {
            WARN("recv error\n");
            res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
            break;
        }

        TRACE("recv %lu bytes\n", size);

        in_bufs[0].cbBuffer += size;
        in_bufs[0].pvBuffer = read_buf;
        status = InitializeSecurityContextW(cred, &ctx, connection->server->name,  isc_req_flags, 0, 0, &in_desc,
                0, NULL, &out_desc, &attrs, NULL);
        TRACE("InitializeSecurityContext ret %08x\n", status);

        if(status == SEC_E_OK) {
            if(SecIsValidHandle(&connection->ssl_ctx))
                DeleteSecurityContext(&connection->ssl_ctx);
            connection->ssl_ctx = ctx;

            if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
                FIXME("SECBUFFER_EXTRA not supported\n");

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &connection->ssl_sizes);
            if(status != SEC_E_OK) {
                WARN("Could not get sizes\n");
                break;
            }

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
            if(status == SEC_E_OK) {
                res = netconn_verify_cert(connection, cert, cert->hCertStore);
                CertFreeCertificateContext(cert);
                if(res != ERROR_SUCCESS) {
                    WARN("cert verify failed: %u\n", res);
                    break;
                }
            }else {
                WARN("Could not get cert\n");
                break;
            }

            connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage
                    + connection->ssl_sizes.cbTrailer);
            if(!connection->ssl_buf) {
                res = GetLastError();
                break;
            }
        }
    }

    heap_free(read_buf);

    if(status != SEC_E_OK || res != ERROR_SUCCESS) {
        WARN("Failed to establish SSL connection: %08x (%u)\n", status, res);
        heap_free(connection->ssl_buf);
        connection->ssl_buf = NULL;
        return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
    }

    TRACE("established SSL connection\n");
    connection->secure = TRUE;
    connection->security_flags |= SECURITY_FLAG_SECURE;

    bits = NETCON_GetCipherStrength(connection);
    if (bits >= 128)
        connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG;
    else if (bits >= 56)
        connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
    else
        connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK;

    if(connection->mask_errors)
        connection->server->security_flags = connection->security_flags;
    return ERROR_SUCCESS;
}
コード例 #8
0
ファイル: sspi.c プロジェクト: jianglei12138/ghostscript
/*
 * '_sspiConnect()' - Make an SSL connection. This function
 *                    assumes a TCP/IP connection has already
 *                    been successfully made
 */
BOOL					/* O - 1 on success, 0 on failure */
_sspiConnect(_sspi_struct_t *conn,	/* I - Client connection */
             const CHAR *hostname)	/* I - Server hostname */
{
  PCCERT_CONTEXT	serverCert;	/* Server certificate */
  DWORD			dwSSPIFlags;	/* SSL connection attributes we want */
  DWORD			dwSSPIOutFlags;	/* SSL connection attributes we got */
  TimeStamp		tsExpiry;	/* Time stamp */
  SECURITY_STATUS	scRet;		/* Status */
  DWORD			cbData;		/* Data count */
  SecBufferDesc		inBuffer;	/* Array of SecBuffer structs */
  SecBuffer		inBuffers[2];	/* Security package buffer */
  SecBufferDesc		outBuffer;	/* Array of SecBuffer structs */
  SecBuffer		outBuffers[1];	/* Security package buffer */
  BOOL			ok = TRUE;	/* Return value */

  serverCert  = NULL;

  dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT   |
                ISC_REQ_REPLAY_DETECT     |
                ISC_REQ_CONFIDENTIALITY   |
                ISC_RET_EXTENDED_ERROR    |
                ISC_REQ_ALLOCATE_MEMORY   |
                ISC_REQ_STREAM;

 /*
  * Initiate a ClientHello message and generate a token.
  */
  outBuffers[0].pvBuffer   = NULL;
  outBuffers[0].BufferType = SECBUFFER_TOKEN;
  outBuffers[0].cbBuffer   = 0;

  outBuffer.cBuffers = 1;
  outBuffer.pBuffers = outBuffers;
  outBuffer.ulVersion = SECBUFFER_VERSION;

  scRet = InitializeSecurityContext(&conn->creds, NULL, TEXT(""), dwSSPIFlags,
                                    0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context,
                                    &outBuffer, &dwSSPIOutFlags, &tsExpiry);

  if (scRet != SEC_I_CONTINUE_NEEDED)
  {
    DEBUG_printf(("_sspiConnect: InitializeSecurityContext(1) failed: %x", scRet));
    ok = FALSE;
    goto cleanup;
  }

 /*
  * Send response to server if there is one.
  */
  if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
  {
    cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);

    if ((cbData == SOCKET_ERROR) || !cbData)
    {
      DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError()));
      FreeContextBuffer(outBuffers[0].pvBuffer);
      DeleteSecurityContext(&conn->context);
      ok = FALSE;
      goto cleanup;
    }

    DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData));

   /*
    * Free output buffer.
    */
    FreeContextBuffer(outBuffers[0].pvBuffer);
    outBuffers[0].pvBuffer = NULL;
  }

  dwSSPIFlags = ISC_REQ_MANUAL_CRED_VALIDATION |
	            ISC_REQ_SEQUENCE_DETECT        |
                ISC_REQ_REPLAY_DETECT          |
                ISC_REQ_CONFIDENTIALITY        |
                ISC_RET_EXTENDED_ERROR         |
                ISC_REQ_ALLOCATE_MEMORY        |
                ISC_REQ_STREAM;

  conn->decryptBufferUsed = 0;

 /*
  * Loop until the handshake is finished or an error occurs.
  */
  scRet = SEC_I_CONTINUE_NEEDED;

  while(scRet == SEC_I_CONTINUE_NEEDED        ||
        scRet == SEC_E_INCOMPLETE_MESSAGE     ||
        scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  {
    if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE))
    {
      if (conn->decryptBufferLength <= conn->decryptBufferUsed)
      {
        conn->decryptBufferLength += 4096;
        conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer, conn->decryptBufferLength);

        if (!conn->decryptBuffer)
        {
          DEBUG_printf(("_sspiConnect: unable to allocate %d byte decrypt buffer",
                        conn->decryptBufferLength));
          SetLastError(E_OUTOFMEMORY);
          ok = FALSE;
          goto cleanup;
        }
      }

      cbData = recv(conn->sock, conn->decryptBuffer + conn->decryptBufferUsed,
                    (int) (conn->decryptBufferLength - conn->decryptBufferUsed), 0);

      if (cbData == SOCKET_ERROR)
      {
        DEBUG_printf(("_sspiConnect: recv failed: %d", WSAGetLastError()));
        ok = FALSE;
        goto cleanup;
      }
      else if (cbData == 0)
      {
        DEBUG_printf(("_sspiConnect: server unexpectedly disconnected"));
        ok = FALSE;
        goto cleanup;
      }

      DEBUG_printf(("_sspiConnect: %d bytes of handshake data received",
                    cbData));

      conn->decryptBufferUsed += cbData;
    }

   /*
    * Set up the input buffers. Buffer 0 is used to pass in data
    * received from the server. Schannel will consume some or all
    * of this. Leftover data (if any) will be placed in buffer 1 and
    * given a buffer type of SECBUFFER_EXTRA.
    */
    inBuffers[0].pvBuffer   = conn->decryptBuffer;
    inBuffers[0].cbBuffer   = (unsigned long) conn->decryptBufferUsed;
    inBuffers[0].BufferType = SECBUFFER_TOKEN;

    inBuffers[1].pvBuffer   = NULL;
    inBuffers[1].cbBuffer   = 0;
    inBuffers[1].BufferType = SECBUFFER_EMPTY;

    inBuffer.cBuffers       = 2;
    inBuffer.pBuffers       = inBuffers;
    inBuffer.ulVersion      = SECBUFFER_VERSION;

   /*
    * Set up the output buffers. These are initialized to NULL
    * so as to make it less likely we'll attempt to free random
    * garbage later.
    */
    outBuffers[0].pvBuffer  = NULL;
    outBuffers[0].BufferType= SECBUFFER_TOKEN;
    outBuffers[0].cbBuffer  = 0;

    outBuffer.cBuffers      = 1;
    outBuffer.pBuffers      = outBuffers;
    outBuffer.ulVersion     = SECBUFFER_VERSION;

   /*
    * Call InitializeSecurityContext.
    */
    scRet = InitializeSecurityContext(&conn->creds, &conn->context, NULL, dwSSPIFlags,
                                      0, SECURITY_NATIVE_DREP, &inBuffer, 0, NULL,
                                      &outBuffer, &dwSSPIOutFlags, &tsExpiry);

   /*
    * If InitializeSecurityContext was successful (or if the error was
    * one of the special extended ones), send the contends of the output
    * buffer to the server.
    */
    if (scRet == SEC_E_OK                ||
        scRet == SEC_I_CONTINUE_NEEDED   ||
        FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
    {
      if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
      {
        cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);

        if ((cbData == SOCKET_ERROR) || !cbData)
        {
          DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError()));
          FreeContextBuffer(outBuffers[0].pvBuffer);
          DeleteSecurityContext(&conn->context);
          ok = FALSE;
          goto cleanup;
        }

        DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData));

       /*
        * Free output buffer.
        */
        FreeContextBuffer(outBuffers[0].pvBuffer);
        outBuffers[0].pvBuffer = NULL;
      }
    }

   /*
    * If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE,
    * then we need to read more data from the server and try again.
    */
    if (scRet == SEC_E_INCOMPLETE_MESSAGE)
      continue;

   /*
    * If InitializeSecurityContext returned SEC_E_OK, then the
    * handshake completed successfully.
    */
    if (scRet == SEC_E_OK)
    {
     /*
      * If the "extra" buffer contains data, this is encrypted application
      * protocol layer stuff. It needs to be saved. The application layer
      * will later decrypt it with DecryptMessage.
      */
      DEBUG_printf(("_sspiConnect: Handshake was successful"));

      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        if (conn->decryptBufferLength < inBuffers[1].cbBuffer)
        {
          conn->decryptBuffer = realloc(conn->decryptBuffer, inBuffers[1].cbBuffer);

          if (!conn->decryptBuffer)
          {
            DEBUG_printf(("_sspiConnect: unable to allocate %d bytes for decrypt buffer",
                          inBuffers[1].cbBuffer));
            SetLastError(E_OUTOFMEMORY);
            ok = FALSE;
            goto cleanup;
          }
        }

        memmove(conn->decryptBuffer,
                conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer),
                inBuffers[1].cbBuffer);

        conn->decryptBufferUsed = inBuffers[1].cbBuffer;

        DEBUG_printf(("_sspiConnect: %d bytes of app data was bundled with handshake data",
                      conn->decryptBufferUsed));
      }
      else
        conn->decryptBufferUsed = 0;

     /*
      * Bail out to quit
      */
      break;
    }

   /*
    * Check for fatal error.
    */
    if (FAILED(scRet))
    {
      DEBUG_printf(("_sspiConnect: InitializeSecurityContext(2) failed: %x", scRet));
      ok = FALSE;
      break;
    }

   /*
    * If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS,
    * then the server just requested client authentication.
    */
    if (scRet == SEC_I_INCOMPLETE_CREDENTIALS)
    {
     /*
      * Unimplemented
      */
      DEBUG_printf(("_sspiConnect: server requested client credentials"));
      ok = FALSE;
      break;
    }

   /*
    * Copy any leftover data from the "extra" buffer, and go around
    * again.
    */
    if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
    {
      memmove(conn->decryptBuffer,
              conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer),
              inBuffers[1].cbBuffer);

      conn->decryptBufferUsed = inBuffers[1].cbBuffer;
    }
    else
    {
      conn->decryptBufferUsed = 0;
    }
  }

  if (ok)
  {
    conn->contextInitialized = TRUE;

   /*
    * Get the server cert
    */
    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (VOID*) &serverCert );

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_REMOTE_CERT_CONTEXT): %x", scRet));
      ok = FALSE;
      goto cleanup;
    }

    scRet = sspi_verify_certificate(serverCert, hostname, conn->certFlags);

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiConnect: sspi_verify_certificate failed: %x", scRet));
      ok = FALSE;
      goto cleanup;
    }

   /*
    * Find out how big the header/trailer will be:
    */
    scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes);

    if (scRet != SEC_E_OK)
    {
      DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_STREAM_SIZES): %x", scRet));
      ok = FALSE;
    }
  }

cleanup:

  if (serverCert)
    CertFreeCertificateContext(serverCert);

  return (ok);
}
コード例 #9
0
static int
pg_SSPI_recvauth(Port *port)
{
	int			mtype;
	StringInfoData buf;
	SECURITY_STATUS r;
	CredHandle	sspicred;
	CtxtHandle *sspictx = NULL,
				newctx;
	TimeStamp	expiry;
	ULONG		contextattr;
	SecBufferDesc inbuf;
	SecBufferDesc outbuf;
	SecBuffer	OutBuffers[1];
	SecBuffer	InBuffers[1];
	HANDLE		token;
	TOKEN_USER *tokenuser;
	DWORD		retlen;
	char		accountname[MAXPGPATH];
	char		domainname[MAXPGPATH];
	DWORD		accountnamesize = sizeof(accountname);
	DWORD		domainnamesize = sizeof(domainname);
	SID_NAME_USE accountnameuse;
	HMODULE		secur32;
	QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;

	/*
	 * SSPI auth is not supported for protocol versions before 3, because it
	 * relies on the overall message length word to determine the SSPI payload
	 * size in AuthenticationGSSContinue and PasswordMessage messages.
	 * (This is, in fact, a design error in our SSPI support, because protocol
	 * messages are supposed to be parsable without relying on the length
	 * word; but it's not worth changing it now.)
	 */
	if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
		ereport(FATAL,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("SSPI is not supported in protocol version 2")));

	/*
	 * Acquire a handle to the server credentials.
	 */
	r = AcquireCredentialsHandle(NULL,
								 "negotiate",
								 SECPKG_CRED_INBOUND,
								 NULL,
								 NULL,
								 NULL,
								 NULL,
								 &sspicred,
								 &expiry);
	if (r != SEC_E_OK)
		pg_SSPI_error(ERROR,
			   gettext_noop("could not acquire SSPI credentials handle"), r);

	/*
	 * Loop through SSPI message exchange. This exchange can consist of
	 * multiple messags sent in both directions. First message is always from
	 * the client. All messages from client to server are password packets
	 * (type 'p').
	 */
	do
	{
		mtype = pq_getbyte();
		if (mtype != 'p')
		{
			/* Only log error if client didn't disconnect. */
			if (mtype != EOF)
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("expected SSPI response, got message type %d",
								mtype)));
			return STATUS_ERROR;
		}

		/* Get the actual SSPI token */
		initStringInfo(&buf);
		if (pq_getmessage(&buf, 2000))
		{
			/* EOF - pq_getmessage already logged error */
			pfree(buf.data);
			return STATUS_ERROR;
		}

		/* Map to SSPI style buffer */
		inbuf.ulVersion = SECBUFFER_VERSION;
		inbuf.cBuffers = 1;
		inbuf.pBuffers = InBuffers;
		InBuffers[0].pvBuffer = buf.data;
		InBuffers[0].cbBuffer = buf.len;
		InBuffers[0].BufferType = SECBUFFER_TOKEN;

		/* Prepare output buffer */
		OutBuffers[0].pvBuffer = NULL;
		OutBuffers[0].BufferType = SECBUFFER_TOKEN;
		OutBuffers[0].cbBuffer = 0;
		outbuf.cBuffers = 1;
		outbuf.pBuffers = OutBuffers;
		outbuf.ulVersion = SECBUFFER_VERSION;


		elog(DEBUG4, "Processing received SSPI token of length %u",
			 (unsigned int) buf.len);

		r = AcceptSecurityContext(&sspicred,
								  sspictx,
								  &inbuf,
								  ASC_REQ_ALLOCATE_MEMORY,
								  SECURITY_NETWORK_DREP,
								  &newctx,
								  &outbuf,
								  &contextattr,
								  NULL);

		/* input buffer no longer used */
		pfree(buf.data);

		if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
		{
			/*
			 * Negotiation generated data to be sent to the client.
			 */
			elog(DEBUG4, "sending SSPI response token of length %u",
				 (unsigned int) outbuf.pBuffers[0].cbBuffer);

			port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
			port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;

			sendAuthRequest(port, AUTH_REQ_GSS_CONT);

			FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
		}

		if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
		{
			if (sspictx != NULL)
			{
				DeleteSecurityContext(sspictx);
				free(sspictx);
			}
			FreeCredentialsHandle(&sspicred);
			pg_SSPI_error(ERROR,
				  gettext_noop("could not accept SSPI security context"), r);
		}

		if (sspictx == NULL)
		{
			sspictx = malloc(sizeof(CtxtHandle));
			if (sspictx == NULL)
				ereport(ERROR,
						(errmsg("out of memory")));

			memcpy(sspictx, &newctx, sizeof(CtxtHandle));
		}

		if (r == SEC_I_CONTINUE_NEEDED)
			elog(DEBUG4, "SSPI continue needed");

	} while (r == SEC_I_CONTINUE_NEEDED);


	/*
	 * Release service principal credentials
	 */
	FreeCredentialsHandle(&sspicred);


	/*
	 * SEC_E_OK indicates that authentication is now complete.
	 *
	 * Get the name of the user that authenticated, and compare it to the pg
	 * username that was specified for the connection.
	 *
	 * MingW is missing the export for QuerySecurityContextToken in the
	 * secur32 library, so we have to load it dynamically.
	 */

	secur32 = LoadLibrary("SECUR32.DLL");
	if (secur32 == NULL)
		ereport(ERROR,
				(errmsg_internal("could not load secur32.dll: %d",
								 (int) GetLastError())));

	_QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)
		GetProcAddress(secur32, "QuerySecurityContextToken");
	if (_QuerySecurityContextToken == NULL)
	{
		FreeLibrary(secur32);
		ereport(ERROR,
				(errmsg_internal("could not locate QuerySecurityContextToken in secur32.dll: %d",
								 (int) GetLastError())));
	}

	r = (_QuerySecurityContextToken) (sspictx, &token);
	if (r != SEC_E_OK)
	{
		FreeLibrary(secur32);
		pg_SSPI_error(ERROR,
			   gettext_noop("could not get security token from context"), r);
	}

	FreeLibrary(secur32);

	/*
	 * No longer need the security context, everything from here on uses the
	 * token instead.
	 */
	DeleteSecurityContext(sspictx);
	free(sspictx);

	if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
		ereport(ERROR,
			 (errmsg_internal("could not get token user size: error code %d",
							  (int) GetLastError())));

	tokenuser = malloc(retlen);
	if (tokenuser == NULL)
		ereport(ERROR,
				(errmsg("out of memory")));

	if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
		ereport(ERROR,
				(errmsg_internal("could not get user token: error code %d",
								 (int) GetLastError())));

	if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
						  domainname, &domainnamesize, &accountnameuse))
		ereport(ERROR,
			  (errmsg_internal("could not lookup acconut sid: error code %d",
							   (int) GetLastError())));

	free(tokenuser);

	/*
	 * Compare realm/domain if requested. In SSPI, always compare case
	 * insensitive.
	 */
	if (pg_krb_realm && strlen(pg_krb_realm))
	{
		if (pg_strcasecmp(pg_krb_realm, domainname))
		{
			elog(DEBUG2,
				 "SSPI domain (%s) and configured domain (%s) don't match",
				 domainname, pg_krb_realm);

			return STATUS_ERROR;
		}
	}

	/*
	 * We have the username (without domain/realm) in accountname, compare to
	 * the supplied value. In SSPI, always compare case insensitive.
	 */
	if (pg_strcasecmp(port->user_name, accountname))
	{
		/* GSS name and PGUSER are not equivalent */
		elog(DEBUG2,
			 "provided username (%s) and SSPI username (%s) don't match",
			 port->user_name, accountname);

		return STATUS_ERROR;
	}

	return STATUS_OK;
}
コード例 #10
0
ファイル: netlibsecurity.cpp プロジェクト: ybznek/miranda-ng
char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge, const TCHAR* login, const TCHAR* psw, bool http, unsigned& complete)
{
	if (hSecurity == NULL || ntlmCnt == 0)
		return NULL;

	SecBufferDesc outputBufferDescriptor, inputBufferDescriptor;
	SecBuffer outputSecurityToken, inputSecurityToken;
	TimeStamp tokenExpiration;
	ULONG contextAttributes;
	char *szOutputToken;

	NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity;
	if (mir_tstrcmpi(hNtlm->szProvider, _T("Basic"))) {
		bool isGSSAPI = mir_tstrcmpi(hNtlm->szProvider, _T("GSSAPI")) == 0;
		TCHAR *szProvider = isGSSAPI ? (TCHAR*)_T("Kerberos") : hNtlm->szProvider;
		bool hasChallenge = szChallenge != NULL && szChallenge[0] != '\0';
		if (hasChallenge) {
			unsigned tokenLen;
			BYTE *token = (BYTE*)mir_base64_decode(szChallenge, &tokenLen);
			if (token == NULL)
				return NULL;

			if (isGSSAPI && complete)
				return CompleteGssapi(hSecurity, token, tokenLen);

			inputBufferDescriptor.cBuffers = 1;
			inputBufferDescriptor.pBuffers = &inputSecurityToken;
			inputBufferDescriptor.ulVersion = SECBUFFER_VERSION;
			inputSecurityToken.BufferType = SECBUFFER_TOKEN;
			inputSecurityToken.cbBuffer = tokenLen;
			inputSecurityToken.pvBuffer = token;

			// try to decode the domain name from the NTLM challenge
			if (login != NULL && login[0] != '\0' && !hNtlm->hasDomain) {
				NtlmType2packet* pkt = (NtlmType2packet*)token;
				if (!strncmp(pkt->sign, "NTLMSSP", 8) && pkt->type == 2) {

					wchar_t* domainName = (wchar_t*)&token[pkt->targetName.offset];
					int domainLen = pkt->targetName.len;

					// Negotiate ANSI? if yes, convert the ANSI name to unicode
					if ((pkt->flags & 1) == 0) {
						int bufsz = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, NULL, 0);
						wchar_t* buf = (wchar_t*)alloca(bufsz * sizeof(wchar_t));
						domainLen = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, buf, bufsz) - 1;
						domainName = buf;
					}
					else domainLen /= sizeof(wchar_t);

					if (domainLen) {
						size_t newLoginLen = mir_tstrlen(login) + domainLen + 1;
						TCHAR *newLogin = (TCHAR*)alloca(newLoginLen * sizeof(TCHAR));

						_tcsncpy(newLogin, domainName, domainLen);
						newLogin[domainLen] = '\\';
						mir_tstrcpy(newLogin + domainLen + 1, login);

						char* szChl = NtlmCreateResponseFromChallenge(hSecurity, NULL, newLogin, psw, http, complete);
						mir_free(szChl);
					}
				}
			}
		}
		else {
			if (SecIsValidHandle(&hNtlm->hClientContext))
				DeleteSecurityContext(&hNtlm->hClientContext);
			if (SecIsValidHandle(&hNtlm->hClientCredential))
				FreeCredentialsHandle(&hNtlm->hClientCredential);

			SEC_WINNT_AUTH_IDENTITY auth;

			if (login != NULL && login[0] != '\0') {
				memset(&auth, 0, sizeof(auth));

				NetlibLogf(NULL, "Security login requested, user: %S pssw: %s", login, psw ? "(exist)" : "(no psw)");

				const TCHAR* loginName = login;
				const TCHAR* domainName = _tcschr(login, '\\');
				size_t domainLen = 0;
				size_t loginLen = mir_tstrlen(loginName);
				if (domainName != NULL) {
					loginName = domainName + 1;
					loginLen = mir_tstrlen(loginName);
					domainLen = domainName - login;
					domainName = login;
				}
				else if ((domainName = _tcschr(login, '@')) != NULL) {
					loginName = login;
					loginLen = domainName - login;
					domainLen = mir_tstrlen(++domainName);
				}

				auth.User = (PWORD)loginName;
				auth.UserLength = (ULONG)loginLen;
				auth.Password = (PWORD)psw;
				auth.PasswordLength = (ULONG)mir_tstrlen(psw);
				auth.Domain = (PWORD)domainName;
				auth.DomainLength = (ULONG)domainLen;
				auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

				hNtlm->hasDomain = domainLen != 0;
			}

			SECURITY_STATUS sc = AcquireCredentialsHandle(NULL, szProvider,
				SECPKG_CRED_OUTBOUND, NULL, hNtlm->hasDomain ? &auth : NULL, NULL, NULL,
				&hNtlm->hClientCredential, &tokenExpiration);
			if (sc != SEC_E_OK) {
				ReportSecError(sc, __LINE__);
				return NULL;
			}
		}

		outputBufferDescriptor.cBuffers = 1;
		outputBufferDescriptor.pBuffers = &outputSecurityToken;
		outputBufferDescriptor.ulVersion = SECBUFFER_VERSION;
		outputSecurityToken.BufferType = SECBUFFER_TOKEN;
		outputSecurityToken.cbBuffer = hNtlm->cbMaxToken;
		outputSecurityToken.pvBuffer = alloca(outputSecurityToken.cbBuffer);

		SECURITY_STATUS sc = InitializeSecurityContext(&hNtlm->hClientCredential,
			hasChallenge ? &hNtlm->hClientContext : NULL,
			hNtlm->szPrincipal, isGSSAPI ? ISC_REQ_MUTUAL_AUTH | ISC_REQ_STREAM : 0, 0, SECURITY_NATIVE_DREP,
			hasChallenge ? &inputBufferDescriptor : NULL, 0, &hNtlm->hClientContext,
			&outputBufferDescriptor, &contextAttributes, &tokenExpiration);

		complete = (sc != SEC_I_COMPLETE_AND_CONTINUE && sc != SEC_I_CONTINUE_NEEDED);

		if (sc == SEC_I_COMPLETE_NEEDED || sc == SEC_I_COMPLETE_AND_CONTINUE)
			sc = CompleteAuthToken(&hNtlm->hClientContext, &outputBufferDescriptor);

		if (sc != SEC_E_OK && sc != SEC_I_CONTINUE_NEEDED) {
			ReportSecError(sc, __LINE__);
			return NULL;
		}

		szOutputToken = mir_base64_encode((PBYTE)outputSecurityToken.pvBuffer, outputSecurityToken.cbBuffer);
	}
	else {
		if (!login || !psw) return NULL;

		char *szLogin = mir_t2a(login);
		char *szPassw = mir_t2a(psw);

		size_t authLen = mir_strlen(szLogin) + mir_strlen(szPassw) + 5;
		char *szAuth = (char*)alloca(authLen);

		int len = mir_snprintf(szAuth, authLen, "%s:%s", szLogin, szPassw);
		szOutputToken = mir_base64_encode((BYTE*)szAuth, len);
		complete = true;

		mir_free(szPassw);
		mir_free(szLogin);
	}

	if (szOutputToken == NULL)
		return NULL;

	if (!http)
		return szOutputToken;

	ptrA szProvider(mir_t2a(hNtlm->szProvider));
	size_t resLen = mir_strlen(szOutputToken) + mir_strlen(szProvider) + 10;
	char *result = (char*)mir_alloc(resLen);
	mir_snprintf(result, resLen, "%s %s", szProvider, szOutputToken);
	mir_free(szOutputToken);
	return result;
}
コード例 #11
0
ファイル: net.c プロジェクト: Moteesh/reactos
netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int timeout )
{
    netconn_t *conn;
    unsigned int addr_len;
    BOOL ret = FALSE;
    int res;
    ULONG state;

    conn = heap_alloc_zero(sizeof(*conn));
    if (!conn) return NULL;
    conn->host = host;
    conn->sockaddr = *sockaddr;
    if ((conn->socket = socket( sockaddr->ss_family, SOCK_STREAM, 0 )) == -1)
    {
        WARN("unable to create socket (%s)\n", strerror(errno));
        set_last_error( sock_get_error( errno ) );
        heap_free(conn);
        return NULL;
    }

    switch (conn->sockaddr.ss_family)
    {
    case AF_INET:
        addr_len = sizeof(struct sockaddr_in);
        break;
    case AF_INET6:
        addr_len = sizeof(struct sockaddr_in6);
        break;
    default:
        assert(0);
    }

    if (timeout > 0)
    {
        state = 1;
        ioctlsocket( conn->socket, FIONBIO, &state );
    }

    for (;;)
    {
        res = 0;
        if (connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, addr_len ) < 0)
        {
            res = sock_get_error( errno );
            if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
            {
#ifdef __REACTOS__
                /* ReactOS: use select instead of poll */
                fd_set outfd;
                struct timeval tv;

                FD_ZERO(&outfd);
                FD_SET(conn->socket, &outfd);

                tv.tv_sec = 0;
                tv.tv_usec = timeout * 1000;
                for (;;)
                {
                    res = 0;

                    if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
#else
                struct pollfd pfd;

                pfd.fd = conn->socket;
                pfd.events = POLLOUT;
                for (;;)
                {
                    res = 0;
                    if (poll( &pfd, 1, timeout ) > 0)
#endif
                    {
                        ret = TRUE;
                        break;
                    }
                    else
                    {
                        res = sock_get_error( errno );
                        if (res != WSAEINTR) break;
                    }
                }
            }
            if (res != WSAEINTR) break;
        }
        else
        {
            ret = TRUE;
            break;
        }
    }
    if (timeout > 0)
    {
        state = 0;
        ioctlsocket( conn->socket, FIONBIO, &state );
    }
    if (!ret)
    {
        WARN("unable to connect to host (%d)\n", res);
        set_last_error( res );
        netconn_close( conn );
        return NULL;
    }
    return conn;
}

BOOL netconn_close( netconn_t *conn )
{
    int res;

    if (conn->secure)
    {
        heap_free( conn->peek_msg_mem );
        heap_free(conn->ssl_buf);
        heap_free(conn->extra_buf);
        DeleteSecurityContext(&conn->ssl_ctx);
    }
    res = closesocket( conn->socket );
    release_host( conn->host );
    heap_free(conn);
    if (res == -1)
    {
        set_last_error( sock_get_error( errno ) );
        return FALSE;
    }
    return TRUE;
}
コード例 #12
0
ファイル: sspi-client.c プロジェクト: Brainiarc7/pbis
static
DWORD
ClientEstablishContext(
    IN PCSTR pSPN,
    IN INT nSocket,
    IN PCSTR pServiceName,
    IN PCSTR pServicePassword,
    IN PCSTR pServiceRealm,
    IN ULONG DelegFlag,
    OUT CtxtHandle *pSspiContext,
    IN PCSTR pSecPkgName,
    OUT ULONG *pRetFlags
    )
{
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwLoopError = ERROR_SUCCESS;
    PCtxtHandle pContextHandle = NULL;
    INT nCredentialsAcquired = 0;
    INT nContextAcquired = 0;

    SecBuffer SendTokenBuffer;
    SecBuffer RecvTokenBuffer;
    SecBufferDesc InputDesc;
    SecBufferDesc OutputDesc;
    CredHandle CredHandle;
    TimeStamp Expiry;
    SEC_WINNT_AUTH_IDENTITY AuthIdentity;
    PSEC_WINNT_AUTH_IDENTITY pAuthId = NULL;

    memset(&SendTokenBuffer, 0, sizeof(SecBuffer));
    memset(&RecvTokenBuffer, 0, sizeof(SecBuffer));
    memset(&InputDesc, 0, sizeof(SecBufferDesc));
    memset(&OutputDesc, 0, sizeof(SecBufferDesc));
    memset(&CredHandle, 0, sizeof(CredHandle));
    memset(&Expiry, 0, sizeof(TimeStamp));
    memset(&AuthIdentity, 0, sizeof(AuthIdentity));

    memset(pSspiContext, 0, sizeof(CtxtHandle));
    *pRetFlags = 0;

    InputDesc.cBuffers = 1;
    InputDesc.pBuffers = &RecvTokenBuffer;
    InputDesc.ulVersion = SECBUFFER_VERSION;

    RecvTokenBuffer.BufferType = SECBUFFER_TOKEN;
    RecvTokenBuffer.cbBuffer = 0;
    RecvTokenBuffer.pvBuffer = NULL;

    OutputDesc.cBuffers = 1;
    OutputDesc.pBuffers = &SendTokenBuffer;
    OutputDesc.ulVersion = SECBUFFER_VERSION;

    SendTokenBuffer.BufferType = SECBUFFER_TOKEN;
    SendTokenBuffer.cbBuffer = 0;
    SendTokenBuffer.pvBuffer = NULL;

    CredHandle.dwLower = 0;
    CredHandle.dwUpper = 0;

    if (pServiceName)
    {
        AuthIdentity.User = (PBYTE) pServiceName;
        AuthIdentity.UserLength = (DWORD)strlen(pServiceName);
        pAuthId = &AuthIdentity;
    }

    if (pServicePassword)
    {
        AuthIdentity.Password = (PBYTE) pServicePassword;
        AuthIdentity.PasswordLength = (DWORD)strlen(pServicePassword);
        pAuthId = &AuthIdentity;
    }

    if (pServiceRealm)
    {
        AuthIdentity.Domain = (PBYTE) pServiceRealm;
        AuthIdentity.DomainLength = (DWORD)strlen(pServiceRealm);
        pAuthId = &AuthIdentity;
    }
    AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

    dwError = AcquireCredentialsHandle(
        NULL,                       // no principal name
        (PSTR) pSecPkgName,                // package name
        SECPKG_CRED_OUTBOUND,
        NULL,                       // no logon id
        pAuthId,
        NULL,                       // no get key fn
        NULL,                       // noget key arg
        &CredHandle,
        &Expiry
        );

    BAIL_ON_ERROR(dwError);

    nCredentialsAcquired = 1;

   /*
    * Perform the context-establishement loop.
    */

    pSspiContext->dwLower = 0;
    pSspiContext->dwUpper = 0;

    do
    {
        // we need to use dwLoopErr in this case because we may get
        // back a "continue" command.  In those cases, we still
        // need dwError to be used and set seperatly based on other
        // calls.
        dwLoopError =
            InitializeSecurityContext(
                &CredHandle,
                pContextHandle,
                (PSTR) pSPN,
                DelegFlag,
                0,          // reserved
                SECURITY_NATIVE_DREP,
                &InputDesc,
                0,          // reserved
                pSspiContext,
                &OutputDesc,
                pRetFlags,
                &Expiry
                );

        if (SEC_E_OK != dwLoopError && SEC_I_CONTINUE_NEEDED != dwLoopError)
        {
            dwError = dwLoopError;
            BAIL_ON_ERROR(dwError);
        }

        nContextAcquired = 1;

        if (SEC_I_CONTINUE_NEEDED == dwLoopError)
        {
	    PNTLM_NEGOTIATE_MESSAGE pMsg = (PNTLM_NEGOTIATE_MESSAGE) SendTokenBuffer.pvBuffer;
	    // Adjust any flags for debugging
	    // pMsg->NtlmFlags |= NTLM_FLAG_SEAL;
            printf("Context partially initialized...\n");

            DumpBuffer(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer);
            DumpNtlmMessage(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer);
            printf("\n");
            printf("Flags returned:\n");
            DumpIscRetFlags(*pRetFlags);
            printf("\n");
        }
        else
        {
	    PNTLM_RESPONSE_MESSAGE pMsg = (PNTLM_RESPONSE_MESSAGE) SendTokenBuffer.pvBuffer;
	    // Adjust any flags for debugging
	    //pMsg->NtlmFlags |= NTLM_FLAG_SEAL;

            printf("Context FULLY initialized!\n");
            DumpBuffer(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer);
            DumpNtlmMessage(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer);
            printf("\n");
            printf("Flags returned:\n");
            DumpIscRetFlags(*pRetFlags);
            printf("\n");
        }

        pContextHandle = pSspiContext;

        if (RecvTokenBuffer.pvBuffer)
        {
            free(RecvTokenBuffer.pvBuffer);
            RecvTokenBuffer.pvBuffer = NULL;
            RecvTokenBuffer.cbBuffer = 0;
        }

        if (SendTokenBuffer.cbBuffer != 0)
        {
            dwError = SendToken(nSocket, &SendTokenBuffer);
            BAIL_ON_ERROR(dwError);
        }

        FreeContextBuffer(SendTokenBuffer.pvBuffer);
        SendTokenBuffer.pvBuffer = NULL;
        SendTokenBuffer.cbBuffer = 0;

        if (SEC_I_CONTINUE_NEEDED == dwLoopError)
        {
            dwError = RecvToken(nSocket, &RecvTokenBuffer);
            BAIL_ON_ERROR(dwError);
            printf("RECEIVED:\n");
            DumpBuffer(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer);
            DumpNtlmMessage(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer);
            printf("\n");
        }

    } while (dwLoopError == SEC_I_CONTINUE_NEEDED);

    FreeCredentialsHandle(&CredHandle);

finish:
    return dwError;
error:
    if (nCredentialsAcquired)
    {
        FreeCredentialsHandle(&CredHandle);
    }
    if (nContextAcquired)
    {
        DeleteSecurityContext(pSspiContext);
        memset(pSspiContext, 0, sizeof(CtxtHandle));
    }
    if (RecvTokenBuffer.pvBuffer)
    {
        free(RecvTokenBuffer.pvBuffer);
    }
    if (SendTokenBuffer.cbBuffer)
    {
        FreeContextBuffer(SendTokenBuffer.pvBuffer);
    }

    goto finish;
}
コード例 #13
0
ファイル: sspi-client.c プロジェクト: Brainiarc7/pbis
static
DWORD
CallServer(
    IN PCSTR pHost,
    IN USHORT usPort,
    IN PCSTR pSPN,
    IN PCSTR pServiceName,
    IN PCSTR pServicePassword,
    IN PCSTR pServiceRealm,
    IN ULONG DelegFlag,
    IN PCSTR pMsg,
    IN PCSTR pSecPkgName,
    IN INT nSignOnly
    )
{
    DWORD dwError = ERROR_SUCCESS;
    SecBuffer WrapBuffers[3] = {0};
    INT nSocket = INVALID_SOCKET;
    ULONG nIndex = 0;
    ULONG RetFlags = 0;
    ULONG QopState = 0;
    INT nContextAcquired = 0;

    CtxtHandle Context;
    SecBuffer InBuffer;
    SecBuffer OutBuffer;
    SecBufferDesc InBufferDesc;
    SecPkgContext_Sizes Sizes;
    SecPkgContext_Names Names;
#if 0
    SecPkgContext_AccessToken Token;
    SecPkgContext_NativeNames NativeNames;
    HANDLE TokenHandle;
    SecPkgContext_Authority Authority;
    TOKEN_USER User;
    DWORD NeedLength = 0;
#endif
    SecPkgContext_TargetInformation Target;
    SecPkgContext_SessionKey SessionKey;

    memset(&Context, 0, sizeof(CtxtHandle));
    memset(&InBuffer, 0, sizeof(SecBuffer));
    memset(&OutBuffer, 0, sizeof(SecBuffer));
    memset(&InBufferDesc, 0, sizeof(SecBufferDesc));
    memset(&Sizes, 0, sizeof(SecPkgContext_Sizes));

    /* Open connection */

    dwError = ConnectToServer(pHost, usPort, &nSocket);
    BAIL_ON_ERROR(dwError);

    /* Establish context */
    dwError = ClientEstablishContext(
            pSPN,
            nSocket,
            pServiceName,
            pServicePassword,
            pServiceRealm,
            DelegFlag,
            &Context,
            pSecPkgName,
            &RetFlags
            );

    BAIL_ON_ERROR(dwError);

    nContextAcquired = 1;

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_NAMES,
        &Names);
    BAIL_ON_ERROR(dwError);

    printf("Context is for user: %s\n", Names.sUserName);

#if 0
    dwError = QueryContextAttributes(
                    &Context,
                    SECPKG_ATTR_ACCESS_TOKEN,
                    &Token);
    BAIL_ON_ERROR(dwError);

    dwError = GetTokenInformation(
                    &Context,
                    TokenUser,
                    &User,
                    sizeof(User),
                    &NeedLength);
    BAIL_ON_ERROR(dwError);

    dwError = QuerySecurityContextToken(
            &Context,
            &TokenHandle);
    BAIL_ON_ERROR(dwError);

    dwError = QueryContextAttributes(
                    &Context,
                    SECPKG_ATTR_AUTHORITY,
                    &Authority);
    BAIL_ON_ERROR(dwError);

    printf("Authority is %s\n", Authority.sAuthorityName);

    dwError = QueryContextAttributes(
                    &Context,
                    SECPKG_ATTR_NATIVE_NAMES,
                    &NativeNames);
    BAIL_ON_ERROR(dwError);
#endif

    dwError = QueryContextAttributes(
                    &Context,
                    SECPKG_ATTR_TARGET_INFORMATION,
                    &Target);
    if (dwError == SEC_E_UNSUPPORTED_FUNCTION)
    {
        printf("Querying server is unsupported\n");
    }
    else
    {
        BAIL_ON_ERROR(dwError);

        printf("Context is for server %s\n", Target.MarshalledTargetInfo);
    }

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_SESSION_KEY,
        &SessionKey);

    if(!dwError)
    {
        printf("Session Key: ");
        for(nIndex = 0; nIndex < SessionKey.SessionKeyLength; nIndex++)
        {
            printf("%02X ", SessionKey.SessionKey[nIndex]);
        }
        printf("\n");
    }

    dwError = QueryContextAttributes(
        &Context,
        SECPKG_ATTR_SIZES,
        &Sizes
        );

    BAIL_ON_ERROR(dwError);

    /* Seal the message */
    InBuffer.pvBuffer = (PVOID) pMsg;
    InBuffer.cbBuffer = (ULONG)strlen(pMsg) + 1;

    //
    // Prepare to encrypt the message
    //

    InBufferDesc.cBuffers = 3;
    InBufferDesc.pBuffers = WrapBuffers;
    InBufferDesc.ulVersion = SECBUFFER_VERSION;

    WrapBuffers[0].cbBuffer = Sizes.cbSecurityTrailer;
    WrapBuffers[0].BufferType = SECBUFFER_TOKEN;
    WrapBuffers[0].pvBuffer = malloc(Sizes.cbSecurityTrailer);

    if (WrapBuffers[0].pvBuffer == NULL)
    {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        BAIL_ON_ERROR(dwError);
    }

    WrapBuffers[1].BufferType = SECBUFFER_DATA;
    WrapBuffers[1].cbBuffer = InBuffer.cbBuffer;
    WrapBuffers[1].pvBuffer = malloc(WrapBuffers[1].cbBuffer);

    if (WrapBuffers[1].pvBuffer == NULL)
    {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        BAIL_ON_ERROR(dwError);
    }

    memcpy(
        WrapBuffers[1].pvBuffer,
        InBuffer.pvBuffer,
        InBuffer.cbBuffer
        );

    WrapBuffers[2].BufferType = SECBUFFER_PADDING;
    WrapBuffers[2].cbBuffer = Sizes.cbBlockSize;
    WrapBuffers[2].pvBuffer = malloc(WrapBuffers[2].cbBuffer);

    if (WrapBuffers[2].pvBuffer == NULL)
    {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        BAIL_ON_ERROR(dwError);
    }

    if (nSignOnly)
    {
        printf("Signing only (not encrypting)\n");
    }

    dwError = EncryptMessage(
        &Context,
        nSignOnly ? SECQOP_WRAP_NO_ENCRYPT : 0,
        &InBufferDesc,
        0);

    BAIL_ON_ERROR(dwError);

    //
    // Create the mesage to send to server
    //

    OutBuffer.cbBuffer = WrapBuffers[0].cbBuffer + WrapBuffers[1].cbBuffer + WrapBuffers[2].cbBuffer;
    OutBuffer.pvBuffer = malloc(OutBuffer.cbBuffer);

    if (OutBuffer.pvBuffer == NULL)
    {
        dwError = ERROR_NOT_ENOUGH_MEMORY;
        BAIL_ON_ERROR(dwError);
    }

    memcpy(
        OutBuffer.pvBuffer,
        WrapBuffers[0].pvBuffer,
        WrapBuffers[0].cbBuffer
        );
    memcpy(
        (PUCHAR) OutBuffer.pvBuffer + (int) WrapBuffers[0].cbBuffer,
        WrapBuffers[1].pvBuffer,
        WrapBuffers[1].cbBuffer
        );
    memcpy(
        (PUCHAR) OutBuffer.pvBuffer + WrapBuffers[0].cbBuffer + WrapBuffers[1].cbBuffer,
        WrapBuffers[2].pvBuffer,
        WrapBuffers[2].cbBuffer
        );

    /* Send to server */
    dwError = SendToken(nSocket, &OutBuffer);
    BAIL_ON_ERROR(dwError);
    printf("Encrypted and sent '%s' to server\n", pMsg);

    free(OutBuffer.pvBuffer);
    OutBuffer.pvBuffer = NULL;
    OutBuffer.cbBuffer = 0;
    free(WrapBuffers[0].pvBuffer);
    WrapBuffers[0].pvBuffer = NULL;
    free(WrapBuffers[1].pvBuffer);
    WrapBuffers[1].pvBuffer = NULL;

    /* Read signature block into OutBuffer */
    dwError = RecvToken(nSocket, &OutBuffer);
    BAIL_ON_ERROR(dwError);

    /* Verify signature block */

    InBufferDesc.cBuffers = 2;
    WrapBuffers[0] = InBuffer;
    WrapBuffers[0].BufferType = SECBUFFER_DATA;
    WrapBuffers[1] = OutBuffer;
    WrapBuffers[1].BufferType = SECBUFFER_TOKEN;

    dwError = VerifySignature(&Context, &InBufferDesc, 0, &QopState);
    BAIL_ON_ERROR(dwError);

    free(OutBuffer.pvBuffer);
    OutBuffer.pvBuffer = NULL;

    /* Delete context */
    dwError = DeleteSecurityContext(&Context);
    BAIL_ON_ERROR(dwError);

    closesocket(nSocket);

finish:
    return dwError;
error:
    if (nContextAcquired)
    {
        DeleteSecurityContext(&Context);
    }
    if (INVALID_SOCKET != nSocket)
    {
        closesocket(nSocket);
    }
    if (WrapBuffers[0].pvBuffer)
    {
        free(WrapBuffers[0].pvBuffer);
    }
    if (WrapBuffers[1].pvBuffer)
    {
        free(WrapBuffers[1].pvBuffer);
    }
    if (WrapBuffers[2].pvBuffer)
    {
        free(WrapBuffers[2].pvBuffer);
    }
    if (OutBuffer.pvBuffer)
    {
        free(OutBuffer.pvBuffer);
    }

    goto finish;
}
コード例 #14
0
ファイル: net.c プロジェクト: Strongc/reactos
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
{
    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
    BYTE *read_buf;
    SIZE_T read_buf_size = 2048;
    ULONG attrs = 0;
    CtxtHandle ctx;
    SSIZE_T size;
    const CERT_CONTEXT *cert;
    SECURITY_STATUS status;
    DWORD res = ERROR_SUCCESS;

    const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
                                |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;

    if(!ensure_cred_handle())
        return FALSE;

    read_buf = heap_alloc(read_buf_size);
    if(!read_buf)
        return FALSE;

    status = InitializeSecurityContextW(&cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0,
                                        &ctx, &out_desc, &attrs, NULL);

    assert(status != SEC_E_OK);

    while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) {
        if(out_buf.cbBuffer) {
            assert(status == SEC_I_CONTINUE_NEEDED);

            TRACE("sending %u bytes\n", out_buf.cbBuffer);

            size = sock_send(conn->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
            if(size != out_buf.cbBuffer) {
                ERR("send failed\n");
                res = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
                break;
            }

            FreeContextBuffer(out_buf.pvBuffer);
            out_buf.pvBuffer = NULL;
            out_buf.cbBuffer = 0;
        }

        if(status == SEC_I_CONTINUE_NEEDED) {
            assert(in_bufs[1].cbBuffer < read_buf_size);

            memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
            in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;

            in_bufs[1].BufferType = SECBUFFER_EMPTY;
            in_bufs[1].cbBuffer = 0;
            in_bufs[1].pvBuffer = NULL;
        }

        assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
        assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);

        if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
            BYTE *new_read_buf;

            new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
            if(!new_read_buf) {
                status = E_OUTOFMEMORY;
                break;
            }

            in_bufs[0].pvBuffer = read_buf = new_read_buf;
            read_buf_size += 1024;
        }

        size = sock_recv(conn->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
        if(size < 1) {
            WARN("recv error\n");
            status = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
            break;
        }

        TRACE("recv %lu bytes\n", size);

        in_bufs[0].cbBuffer += size;
        in_bufs[0].pvBuffer = read_buf;
        status = InitializeSecurityContextW(&cred_handle, &ctx, hostname,  isc_req_flags, 0, 0, &in_desc,
                                            0, NULL, &out_desc, &attrs, NULL);
        TRACE("InitializeSecurityContext ret %08x\n", status);

        if(status == SEC_E_OK) {
            if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
                FIXME("SECBUFFER_EXTRA not supported\n");

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &conn->ssl_sizes);
            if(status != SEC_E_OK) {
                WARN("Could not get sizes\n");
                break;
            }

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
            if(status == SEC_E_OK) {
                res = netconn_verify_cert(cert, hostname, conn->security_flags);
                CertFreeCertificateContext(cert);
                if(res != ERROR_SUCCESS) {
                    WARN("cert verify failed: %u\n", res);
                    break;
                }
            } else {
                WARN("Could not get cert\n");
                break;
            }

            conn->ssl_buf = heap_alloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
            if(!conn->ssl_buf) {
                res = GetLastError();
                break;
            }
        }
    }

    heap_free(read_buf);

    if(status != SEC_E_OK || res != ERROR_SUCCESS) {
        WARN("Failed to initialize security context failed: %08x\n", status);
        heap_free(conn->ssl_buf);
        conn->ssl_buf = NULL;
        DeleteSecurityContext(&ctx);
        set_last_error(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR);
        return FALSE;
    }


    TRACE("established SSL connection\n");
    conn->secure = TRUE;
    conn->ssl_ctx = ctx;
    return TRUE;
}
コード例 #15
0
ファイル: access.c プロジェクト: Gaikokujin/WinNT4
NTSTATUS
DoUserLogon (
    IN PLOGON_INFO LogonInfo
    )

/*++

Routine Description:

    Validates a username/password combination by interfacing to the
    security subsystem.

Arguments:

    LogonInfo - Pointer to a block containing in/out information about
        the logon.

Return Value:

    NTSTATUS from the security system.

--*/

{
    NTSTATUS status, subStatus, freeStatus;
    ULONG actualUserInfoBufferLength;
    ULONG oldSessionCount;
    LUID LogonId;
    ULONG Catts;
    LARGE_INTEGER Expiry;
    ULONG BufferOffset;
    SecBufferDesc InputToken;
    SecBuffer InputBuffers[2];
    SecBufferDesc OutputToken;
    SecBuffer OutputBuffer;
    PNTLM_AUTHENTICATE_MESSAGE NtlmInToken = NULL;
    PAUTHENTICATE_MESSAGE InToken = NULL;
    PNTLM_ACCEPT_RESPONSE OutToken = NULL;
    ULONG NtlmInTokenSize;
    ULONG InTokenSize;
    ULONG OutTokenSize;
    ULONG AllocateSize;

    ULONG profileBufferLength;

    PAGED_CODE( );

    LogonInfo->IsNullSession = FALSE;
    LogonInfo->IsAdmin = FALSE;

#if DBG
    SrvLogonCount++;
#endif

    //
    // If this is a null session request, use the cached null session
    // token, which was created during server startup.
    //

    if ( (LogonInfo->UserNameLength == 0) &&
         (LogonInfo->CaseSensitivePasswordLength == 0) &&
         ( (LogonInfo->CaseInsensitivePasswordLength == 0) ||
           ( (LogonInfo->CaseInsensitivePasswordLength == 1) &&
             (*LogonInfo->CaseInsensitivePassword == '\0') ) ) ) {

        LogonInfo->IsNullSession = TRUE;
#if DBG
        SrvNullLogonCount++;
#endif

        if ( !CONTEXT_NULL(SrvNullSessionToken) ) {

            LogonInfo->HaveHandle = TRUE;
            LogonInfo->Token = SrvNullSessionToken;

            LogonInfo->KickOffTime.QuadPart = 0x7FFFFFFFFFFFFFFF;
            LogonInfo->LogOffTime.QuadPart = 0x7FFFFFFFFFFFFFFF;

            LogonInfo->GuestLogon = FALSE;
            LogonInfo->EncryptedLogon = FALSE;

            return STATUS_SUCCESS;
        }

    }

    //
    // This is the main body of the Cairo logon user code
    //

    //
    // First make sure we have a credential handle
    //

    if ((SrvHaveCreds & HAVENTLM) == 0) {

        status = AcquireLMCredentials();

        if (!NT_SUCCESS(status)) {
            goto error_exit;
        }
    }

    //
    // Figure out how big a buffer we need.  We put all the messages
    // in one buffer for efficiency's sake.
    //

    NtlmInTokenSize = sizeof(NTLM_AUTHENTICATE_MESSAGE);
    NtlmInTokenSize = (NtlmInTokenSize + 3) & 0xfffffffc;

    InTokenSize = sizeof(AUTHENTICATE_MESSAGE) +
            LogonInfo->UserNameLength +
            LogonInfo->WorkstationNameLength +
            LogonInfo->DomainNameLength +
            LogonInfo->CaseInsensitivePasswordLength +
            ROUND_UP_COUNT(LogonInfo->CaseSensitivePasswordLength, sizeof(USHORT));


    InTokenSize = (InTokenSize + 3) & 0xfffffffc;

    OutTokenSize = sizeof(NTLM_ACCEPT_RESPONSE);
    OutTokenSize = (OutTokenSize + 3) & 0xfffffffc;

    //
    // Round this up to 8 byte boundary becaus the out token needs to be
    // quad word aligned for the LARGE_INTEGER.
    //

    AllocateSize = ((NtlmInTokenSize + InTokenSize + 7) & 0xfffffff8) + OutTokenSize;

    status = NtAllocateVirtualMemory(
                 NtCurrentProcess( ),
                 &InToken,
                 0L,
                 &AllocateSize,
                 MEM_COMMIT,
                 PAGE_READWRITE
                 );

    if ( !NT_SUCCESS(status) ) {

        INTERNAL_ERROR(
            ERROR_LEVEL_EXPECTED,
            "SrvValidateUser: NtAllocateVirtualMemory failed: %X\n.",
            status,
            NULL
            );

        SrvLogError(
            SrvDeviceObject,
            EVENT_SRV_NO_VIRTUAL_MEMORY,
            status,
            &actualUserInfoBufferLength,
            sizeof(ULONG),
            NULL,
            0
            );

        status = STATUS_INSUFF_SERVER_RESOURCES;
        goto error_exit;
    }

    //
    // Zero the input tokens
    //

    RtlZeroMemory(
        InToken,
        InTokenSize + NtlmInTokenSize
        );

    NtlmInToken = (PNTLM_AUTHENTICATE_MESSAGE) ((PUCHAR) InToken + InTokenSize);
    OutToken = (PNTLM_ACCEPT_RESPONSE) ((PUCHAR) (((ULONG) NtlmInToken + NtlmInTokenSize + 7) & 0xfffffff8));

    //
    // First set up the NtlmInToken, since it is the easiest.
    //

    RtlCopyMemory(
        NtlmInToken->ChallengeToClient,
        LogonInfo->EncryptionKey,
        MSV1_0_CHALLENGE_LENGTH
        );

    NtlmInToken->ParameterControl = 0;


    //
    // Okay, now for the tought part - marshalling the AUTHENTICATE_MESSAGE
    //

    RtlCopyMemory(  InToken->Signature,
                    NTLMSSP_SIGNATURE,
                    sizeof(NTLMSSP_SIGNATURE));

    InToken->MessageType = NtLmAuthenticate;

    BufferOffset = sizeof(AUTHENTICATE_MESSAGE);

    //
    // LM password - case insensitive
    //

    InToken->LmChallengeResponse.Buffer = (PCHAR) BufferOffset;
    InToken->LmChallengeResponse.Length =
        InToken->LmChallengeResponse.MaximumLength =
            (USHORT) LogonInfo->CaseInsensitivePasswordLength;

    RtlCopyMemory(  BufferOffset + (PCHAR) InToken,
                    LogonInfo->CaseInsensitivePassword,
                    LogonInfo->CaseInsensitivePasswordLength);

    BufferOffset += ROUND_UP_COUNT(LogonInfo->CaseInsensitivePasswordLength, sizeof(USHORT));

    //
    // NT password - case sensitive
    //

    InToken->NtChallengeResponse.Buffer = (PCHAR) BufferOffset;
    InToken->NtChallengeResponse.Length =
        InToken->NtChallengeResponse.MaximumLength =
            (USHORT) LogonInfo->CaseSensitivePasswordLength;

    RtlCopyMemory(  BufferOffset + (PCHAR) InToken,
                    LogonInfo->CaseSensitivePassword,
                    LogonInfo->CaseSensitivePasswordLength);

    BufferOffset += LogonInfo->CaseSensitivePasswordLength;

    //
    // Domain Name
    //

    InToken->DomainName.Buffer = (PCHAR) BufferOffset;
    InToken->DomainName.Length =
        InToken->DomainName.MaximumLength =
            (USHORT) LogonInfo->DomainNameLength;

    RtlCopyMemory(  BufferOffset + (PCHAR) InToken,
                    LogonInfo->DomainName,
                    LogonInfo->DomainNameLength);

    BufferOffset += LogonInfo->DomainNameLength;

    //
    // Workstation Name
    //

    InToken->Workstation.Buffer = (PCHAR) BufferOffset;
    InToken->Workstation.Length =
        InToken->Workstation.MaximumLength =
            (USHORT) LogonInfo->WorkstationNameLength;

    RtlCopyMemory(  BufferOffset + (PCHAR) InToken,
                    LogonInfo->WorkstationName,
                    LogonInfo->WorkstationNameLength);

    BufferOffset += LogonInfo->WorkstationNameLength;


    //
    // User Name
    //

    InToken->UserName.Buffer = (PCHAR) BufferOffset;
    InToken->UserName.Length =
        InToken->UserName.MaximumLength =
            (USHORT) LogonInfo->UserNameLength;

    RtlCopyMemory(  BufferOffset + (PCHAR) InToken,
                    LogonInfo->UserName,
                    LogonInfo->UserNameLength);

    BufferOffset += LogonInfo->UserNameLength;



    //
    // Setup all the buffers properly
    //

    InputToken.pBuffers = InputBuffers;
    InputToken.cBuffers = 2;
    InputToken.ulVersion = 0;
    InputBuffers[0].pvBuffer = InToken;
    InputBuffers[0].cbBuffer = InTokenSize;
    InputBuffers[0].BufferType = SECBUFFER_TOKEN;
    InputBuffers[1].pvBuffer = NtlmInToken;
    InputBuffers[1].cbBuffer = NtlmInTokenSize;
    InputBuffers[1].BufferType = SECBUFFER_TOKEN;

    OutputToken.pBuffers = &OutputBuffer;
    OutputToken.cBuffers = 1;
    OutputToken.ulVersion = 0;
    OutputBuffer.pvBuffer = OutToken;
    OutputBuffer.cbBuffer = OutTokenSize;
    OutputBuffer.BufferType = SECBUFFER_TOKEN;

    SrvStatistics.SessionLogonAttempts++;

    status = AcceptSecurityContext(
                &SrvLmLsaHandle,
                NULL,
                &InputToken,
                0,
                SECURITY_NATIVE_DREP,
                &LogonInfo->Token,
                &OutputToken,
                &Catts,
                (PTimeStamp) &Expiry
                );

    status = MapSecurityError( status );

    if ( !NT_SUCCESS(status) ) {


        LogonInfo->Token.dwLower = 0;
        LogonInfo->Token.dwUpper = 0;


        INTERNAL_ERROR(
            ERROR_LEVEL_EXPECTED,
            "SrvValidateUser: LsaLogonUser failed: %X",
            status,
            NULL
            );

        freeStatus = NtFreeVirtualMemory(
                        NtCurrentProcess( ),
                        (PVOID *)&InToken,
                        &AllocateSize,
                        MEM_RELEASE
                        );

        ASSERT(NT_SUCCESS(freeStatus));

        goto error_exit;
    }


    LogonInfo->KickOffTime = OutToken->KickoffTime;
    LogonInfo->LogOffTime = Expiry;
    LogonInfo->GuestLogon = (BOOLEAN)(OutToken->UserFlags & LOGON_GUEST);
    LogonInfo->EncryptedLogon = (BOOLEAN)!(OutToken->UserFlags & LOGON_NOENCRYPTION);
    LogonInfo->LogonId = OutToken->LogonId;
    LogonInfo->HaveHandle = TRUE;

    if ( (OutToken->UserFlags & LOGON_USED_LM_PASSWORD) &&
        LogonInfo->NtSmbs ) {

        ASSERT( MSV1_0_USER_SESSION_KEY_LENGTH >=
                MSV1_0_LANMAN_SESSION_KEY_LENGTH );

        RtlZeroMemory(
            LogonInfo->NtUserSessionKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );

        RtlCopyMemory(
            LogonInfo->NtUserSessionKey,
            OutToken->LanmanSessionKey,
            MSV1_0_LANMAN_SESSION_KEY_LENGTH
            );

        //
        // Turn on bit 1 to tell the client that we are using
        // the lm session key instead of the user session key.
        //

        LogonInfo->Action |= SMB_SETUP_USE_LANMAN_KEY;

    } else {

        RtlCopyMemory(
            LogonInfo->NtUserSessionKey,
            OutToken->UserSessionKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );

    }

    RtlCopyMemory(
        LogonInfo->LanManSessionKey,
        OutToken->LanmanSessionKey,
        MSV1_0_LANMAN_SESSION_KEY_LENGTH
        );

    freeStatus = NtFreeVirtualMemory(
                    NtCurrentProcess( ),
                    (PVOID *)&InToken,
                    &AllocateSize,
                    MEM_RELEASE
                    );

    ASSERT(NT_SUCCESS(freeStatus));

    //
    // Note whether or not this user is an administrator
    //

    LogonInfo->IsAdmin = SrvIsAdmin( LogonInfo->Token );

    //
    // One last check:  Is our session count being exceeded?
    //   We will let the session be exceeded by 1 iff the client
    //   is an administrator.
    //

    if( LogonInfo->IsNullSession == FALSE ) {

        oldSessionCount = ExInterlockedAddUlong(
                          &SrvStatistics.CurrentNumberOfSessions,
                          1,
                          &GLOBAL_SPIN_LOCK(Statistics)
                          );

        if ( oldSessionCount >= SrvMaxUsers ) {
            if( oldSessionCount != SrvMaxUsers || !LogonInfo->IsAdmin ) {

                ExInterlockedAddUlong(
                    &SrvStatistics.CurrentNumberOfSessions,
                    (ULONG)-1,
                    &GLOBAL_SPIN_LOCK(Statistics)
                    );


                DeleteSecurityContext( &LogonInfo->Token );
                RtlZeroMemory( &LogonInfo->Token, sizeof( LogonInfo->Token ) );

                status = STATUS_REQUEST_NOT_ACCEPTED;
                goto error_exit;
            }
        }
    }

    return STATUS_SUCCESS;

error_exit:

    return status;

} // DoUserLogon
コード例 #16
0
ファイル: sspi.c プロジェクト: jianglei12138/ghostscript
/*
 * '_sspiFree()' - Close a connection and free resources
 */
void
_sspiFree(_sspi_struct_t *conn)		/* I  - Client connection */
{
  if (!conn)
    return;

  if (conn->contextInitialized)
  {
    SecBufferDesc	message;	/* Array of SecBuffer struct */
    SecBuffer		buffers[1] = { 0 };
					/* Security package buffer */
    DWORD		dwType;		/* Type */
    DWORD		status;		/* Status */

  /*
   * Notify schannel that we are about to close the connection.
   */
   dwType = SCHANNEL_SHUTDOWN;

   buffers[0].pvBuffer   = &dwType;
   buffers[0].BufferType = SECBUFFER_TOKEN;
   buffers[0].cbBuffer   = sizeof(dwType);

   message.cBuffers  = 1;
   message.pBuffers  = buffers;
   message.ulVersion = SECBUFFER_VERSION;

   status = ApplyControlToken(&conn->context, &message);

   if (SUCCEEDED(status))
   {
     PBYTE	pbMessage;		/* Message buffer */
     DWORD	cbMessage;		/* Message buffer count */
     DWORD	cbData;			/* Data count */
     DWORD	dwSSPIFlags;		/* SSL attributes we requested */
     DWORD	dwSSPIOutFlags;		/* SSL attributes we received */
     TimeStamp	tsExpiry;		/* Time stamp */

     dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT     |
                   ASC_REQ_REPLAY_DETECT       |
                   ASC_REQ_CONFIDENTIALITY     |
                   ASC_REQ_EXTENDED_ERROR      |
                   ASC_REQ_ALLOCATE_MEMORY     |
                   ASC_REQ_STREAM;

     buffers[0].pvBuffer   = NULL;
     buffers[0].BufferType = SECBUFFER_TOKEN;
     buffers[0].cbBuffer   = 0;

     message.cBuffers  = 1;
     message.pBuffers  = buffers;
     message.ulVersion = SECBUFFER_VERSION;

     status = AcceptSecurityContext(&conn->creds, &conn->context, NULL,
                                    dwSSPIFlags, SECURITY_NATIVE_DREP, NULL,
                                    &message, &dwSSPIOutFlags, &tsExpiry);

      if (SUCCEEDED(status))
      {
        pbMessage = buffers[0].pvBuffer;
        cbMessage = buffers[0].cbBuffer;

       /*
        * Send the close notify message to the client.
        */
        if (pbMessage && cbMessage)
        {
          cbData = send(conn->sock, pbMessage, cbMessage, 0);
          if ((cbData == SOCKET_ERROR) || (cbData == 0))
          {
            status = WSAGetLastError();
            DEBUG_printf(("_sspiFree: sending close notify failed: %d", status));
          }
          else
          {
            FreeContextBuffer(pbMessage);
          }
        }
      }
      else
      {
        DEBUG_printf(("_sspiFree: AcceptSecurityContext failed: %x", status));
      }
    }
    else
    {
      DEBUG_printf(("_sspiFree: ApplyControlToken failed: %x", status));
    }

    DeleteSecurityContext(&conn->context);
    conn->contextInitialized = FALSE;
  }

  if (conn->decryptBuffer)
  {
    free(conn->decryptBuffer);
    conn->decryptBuffer = NULL;
  }

  if (conn->readBuffer)
  {
    free(conn->readBuffer);
    conn->readBuffer = NULL;
  }

  if (conn->sock != INVALID_SOCKET)
  {
    closesocket(conn->sock);
    conn->sock = INVALID_SOCKET;
  }

  free(conn);
}
コード例 #17
0
ファイル: access.c プロジェクト: Gaikokujin/WinNT4
NTSTATUS
SrvValidateBlob(
    IN PSESSION Session,
    IN PCONNECTION Connection,
    IN PUNICODE_STRING UserName,
    IN OUT PCHAR Blob,
    IN OUT ULONG *BlobLength
    )

/*++

Routine Description:

    Validates a Kerberos Blob sent from the client

Arguments:

    Session - A pointer to a session block so that this routine can
        insert a user token.

    Connection - A pointer to the connection this user is on.

    UserName - ASCIIZ string corresponding to the user name to validate.

    Blob - The Blob to validate and the place to return the output
    Blob. Note this means that this string space has to be
    long enough to hold the maximum length Blob.

    BlobLength - The length of the aforementioned Blob

Return Value:

    NTSTATUS from the security system.

--*/

{
    NTSTATUS Status;
    ULONG Catts;
    LARGE_INTEGER Expiry;
    PUCHAR AllocateMemory = NULL;
    ULONG AllocateLength = *BlobLength;
    BOOLEAN virtualMemoryAllocated = FALSE;
    SecBufferDesc InputToken;
    SecBuffer InputBuffer;
    SecBufferDesc OutputToken;
    SecBuffer OutputBuffer;
    ULONG oldSessionCount;

    AllocateLength += 16;

    Status = NtAllocateVirtualMemory(
                NtCurrentProcess(),
                &AllocateMemory,
                0,
                &AllocateLength,
                MEM_COMMIT,
                PAGE_READWRITE
                );

    if ( !NT_SUCCESS(Status) ) {
        INTERNAL_ERROR( ERROR_LEVEL_UNEXPECTED,
                        "Could not allocate Blob Memory %lC\n",
                        Status,
                        NULL);
        goto get_out;
    }

    virtualMemoryAllocated = TRUE;


    if ( (SrvHaveCreds & HAVEKERBEROS) == 0 ) { // Need to get cred handle first

        UNICODE_STRING Kerb;

        Kerb.Length = Kerb.MaximumLength = 16;
        Kerb.Buffer = (LPWSTR) AllocateMemory;
        RtlCopyMemory( Kerb.Buffer, MICROSOFT_KERBEROS_NAME, 16);

        Status = AcquireCredentialsHandle(
                    NULL,              // Default principal
                    (PSECURITY_STRING) &Kerb,
                    SECPKG_CRED_INBOUND,   // Need to define this
                    NULL,               // No LUID
                    NULL,               // no AuthData
                    NULL,               // no GetKeyFn
                    NULL,               // no GetKeyArg
                    &SrvKerberosLsaHandle,
                    (PTimeStamp)&Expiry
                    );

        if ( !NT_SUCCESS(Status) ) {
            Status = MapSecurityError(Status);
            goto get_out;
        }
        SrvHaveCreds |= HAVEKERBEROS;
    }

    RtlCopyMemory( AllocateMemory, Blob, *BlobLength );
    InputToken.pBuffers = &InputBuffer;
    InputToken.cBuffers = 1;
    InputToken.ulVersion = 0;
    InputBuffer.pvBuffer = AllocateMemory;
    InputBuffer.cbBuffer = *BlobLength;
    InputBuffer.BufferType = SECBUFFER_TOKEN;

    OutputToken.pBuffers = &OutputBuffer;
    OutputToken.cBuffers = 1;
    OutputToken.ulVersion = 0;
    OutputBuffer.pvBuffer = AllocateMemory;
    OutputBuffer.cbBuffer = *BlobLength;
    OutputBuffer.BufferType = SECBUFFER_TOKEN;

    SrvStatistics.SessionLogonAttempts++;

    Status = AcceptSecurityContext(
                &SrvKerberosLsaHandle,
                (PCtxtHandle)NULL,
                &InputToken,
                ASC_REQ_EXTENDED_ERROR,               // fContextReq
                SECURITY_NATIVE_DREP,
                &Session->UserHandle,
                &OutputToken,
                &Catts,
                (PTimeStamp)&Expiry
                );

    Status = MapSecurityError( Status );

    if ( NT_SUCCESS(Status)
              ||
         (Catts & ASC_RET_EXTENDED_ERROR) )
    {
        *BlobLength = OutputBuffer.cbBuffer;
        RtlCopyMemory( Blob, AllocateMemory, *BlobLength );

        //
        // BUGBUG
        // All of the following values need to come from someplace
        // And while we're at it, get the LogonId as well
        //

        if(NT_SUCCESS(Status))
        {

            //
            // Note whether or not this user is an administrator
            //

            Session->IsAdmin = SrvIsAdmin( Session->UserHandle );

            //
            // fiddle with the session structures iff the
            // security context was actually accepted
            //

            Session->HaveHandle = TRUE;
            Session->KickOffTime = Expiry;
            Session->LogOffTime = Expiry;
            Session->GuestLogon = FALSE;   // No guest logon this way
            Session->EncryptedLogon = TRUE;

            //
            // See if the session count is being exceeded.  We'll allow it only
            //   if the new client is an administrator
            //
            oldSessionCount = ExInterlockedAddUlong(
                              &SrvStatistics.CurrentNumberOfSessions,
                              1,
                              &GLOBAL_SPIN_LOCK(Statistics)
                              );

            if ( oldSessionCount >= SrvMaxUsers ) {
                if( oldSessionCount != SrvMaxUsers || !SrvIsAdmin( Session->UserHandle ) ) {

                    ExInterlockedAddUlong(
                        &SrvStatistics.CurrentNumberOfSessions,
                        (ULONG)-1,
                        &GLOBAL_SPIN_LOCK(Statistics)
                        );

                    DeleteSecurityContext( &Session->UserHandle );
                    Session->HaveHandle = FALSE;

                    Status = STATUS_REQUEST_NOT_ACCEPTED;
                    goto get_out;
                }
            }
        }
    }
    else
    {
        *BlobLength = 0;
    }

get_out:

    if (virtualMemoryAllocated) {
        (VOID)NtFreeVirtualMemory(
                NtCurrentProcess(),
                &AllocateMemory,
                &AllocateLength,
                MEM_DECOMMIT
                );
    }

    return Status;

} // SrvValidateBlob
コード例 #18
0
ファイル: sspi_client.cpp プロジェクト: Budskii/ulib-win
void main()
{

	SOCKET            Client_Socket;
	BYTE              Data[BIG_BUFF];
	PCHAR             pMessage;
	WSADATA           wsaData;
	CredHandle        hCred;
	struct _SecHandle hCtxt;
	SECURITY_STATUS   ss;
	DWORD             cbRead;
	ULONG             cbMaxSignature;
	ULONG             cbSecurityTrailer;
	SecPkgContext_Sizes            SecPkgContextSizes;
	SecPkgContext_NegotiationInfo  SecPkgNegInfo;
	BOOL DoAuthentication (SOCKET s);

	//-------------------------------------------------------------------
	//  Initialize the socket and the SSP security package.

	if(WSAStartup (0x0101, &wsaData))
	{
		MyHandleError("Could not initialize winsock ");
	}

	//--------------------------------------------------------------------
	//  Connect to a server.

	if (!ConnectAuthSocket (
				&Client_Socket,
				&hCred,
				&hCtxt))
	{
		MyHandleError("Authenticated server connection ");
	}

	//--------------------------------------------------------------------
	//   An authenticated session with a server has been established.
	//   Receive and manage a message from the server.
	//   First, find and display the name of the negotiated
	//   SSP and the size of the signature and the encryption 
	//   trailer blocks for this SSP.

	ss = QueryContextAttributes(
	&hCtxt,
	SECPKG_ATTR_NEGOTIATION_INFO,
	&SecPkgNegInfo );

	if (!SEC_SUCCESS(ss))  
	{
		MyHandleError("QueryContextAttributes failed ");
	}
	else
	{
		printf("Package Name: %s\n", SecPkgNegInfo.PackageInfo->Name);
	}

	ss = QueryContextAttributes(
	&hCtxt,
	SECPKG_ATTR_SIZES,
	&SecPkgContextSizes );

	if (!SEC_SUCCESS(ss))  
	{
		MyHandleError("Query context ");
	}

	cbMaxSignature = SecPkgContextSizes.cbMaxSignature;
	cbSecurityTrailer = SecPkgContextSizes.cbSecurityTrailer;

	printf("InitializeSecurityContext result = 0x%08x\n", ss);

	//--------------------------------------------------------------------
	//   Decrypt and display the message from the server.

	if (!ReceiveBytes(
				Client_Socket, 
				Data, 
				BIG_BUFF, 
				&cbRead))
	{
		MyHandleError("No response from server ");
	}

	if (0 == cbRead)
	{
		MyHandleError("Zero bytes received ");
	}

	pMessage = (PCHAR) DecryptThis(
	Data, 
	&cbRead,
	&hCtxt,
	cbSecurityTrailer);

	printf ("The message from the server is \n ->  %.*s \n",
	cbRead, pMessage);

	//--------------------------------------------------------------------
	//  Terminate socket and security package.

	DeleteSecurityContext (&hCtxt);
	FreeCredentialHandle (&hCred); 
	shutdown (Client_Socket, 2);
	closesocket (Client_Socket);
	if (SOCKET_ERROR == WSACleanup ())
	{
		MyHandleError("Problem with socket cleanup ");
	}

	exit (EXIT_SUCCESS);
}  // end main
コード例 #19
0
ファイル: sspisvcs.c プロジェクト: greenplum-db/gpclients
static
SECURITY_STATUS
PerformSchannelClientHandshake(
	SOCKET		Socket,		/* in */
	PCredHandle	phCreds,	/* in */
	LPSTR		pszServerName,	/* in */
	CtxtHandle	*phContext,	/* out */
	SecBuffer	*pExtraData)	/* out */
{
	SecBufferDesc	OutBuffer;
	SecBuffer	OutBuffers[1];
	DWORD		dwSSPIFlags;
	DWORD		dwSSPIOutFlags;
	TimeStamp	tsExpiry;
	SECURITY_STATUS	scRet;
	DWORD		cbData;

	dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT	|
			ISC_REQ_REPLAY_DETECT	|
			ISC_REQ_CONFIDENTIALITY	|
			ISC_RET_EXTENDED_ERROR	|
			ISC_REQ_ALLOCATE_MEMORY	|
			ISC_REQ_STREAM;

	/*
	 *  Initiate a ClientHello message and generate a token.
	 */

	OutBuffers[0].pvBuffer	= NULL;
	OutBuffers[0].BufferType = SECBUFFER_TOKEN;
	OutBuffers[0].cbBuffer	= 0;

	OutBuffer.cBuffers = 1;
	OutBuffer.pBuffers = OutBuffers;
	OutBuffer.ulVersion = SECBUFFER_VERSION;

	scRet = InitializeSecurityContext(
					phCreds,
					NULL,
					pszServerName,
					dwSSPIFlags,
					0,
					SECURITY_NATIVE_DREP,
					NULL,
					0,
					phContext,
					&OutBuffer,
					&dwSSPIOutFlags,
					&tsExpiry);

	if (scRet != SEC_I_CONTINUE_NEEDED)
	{
		mylog("**** Error %d returned by InitializeSecurityContext (1)\n", scRet);
		return scRet;
	}

	/* Send response to server if there is one. */
	if (OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
	{
		cbData = sendall(Socket,
				OutBuffers[0].pvBuffer,
				OutBuffers[0].cbBuffer);
		if (cbData <= 0)
		{
			mylog("**** Error %d sending data to server (1)\n", SOCK_ERRNO);
			FreeContextBuffer(OutBuffers[0].pvBuffer);
			DeleteSecurityContext(phContext);
			return SEC_E_INTERNAL_ERROR;
		}

		mylog("%d bytes of handshake data sent\n", cbData);

		/* Free output buffer. */
		FreeContextBuffer(OutBuffers[0].pvBuffer);
		OutBuffers[0].pvBuffer = NULL;
	}


	return SchannelClientHandshakeLoop(Socket, phCreds, phContext, TRUE, pExtraData);
}