Exemplo n.º 1
3
BOOL ClientAuthenticate(const char *name, const char *hostname)
{
	int rc, rcISC;
	SEC_WINNT_AUTH_IDENTITY nameAndPwd = {0};
	int bytesReceived = 0, bytesSent = 0;
	char myTokenSource[256];
	TimeStamp useBefore;
	DWORD ctxReq, ctxAttr;
	int dwRead,dwWritten;
	// input and output buffers
	SecBufferDesc obd, ibd;
	SecBuffer ob, ib[2];
	BOOL haveInbuffer = FALSE;
	BOOL haveContext = FALSE;
	SCHANNEL_CRED cred = {0};
	PCCERT_CONTEXT cert = NULL;

	HANDLE hMy = CertOpenSystemStore(0,"MY");
	if(!hMy)
	{
		rcISC = SEC_E_NO_CREDENTIALS;
		server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC));
		return FALSE;
    }

	if(name)
	{
		cert = CertFindCertificateInStore(hMy, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (const wchar_t *)cvs::wide(name),	NULL);
		if(!cert)
		{
			rcISC = SEC_E_NO_CREDENTIALS;
			server_error(1,"No certificate for '%s': %s\n",name,GetErrorString(rcISC));
			return FALSE;
		}
	}

	cred.dwVersion = SCHANNEL_CRED_VERSION;
	cred.dwFlags = SCH_CRED_USE_DEFAULT_CREDS;

	if(cert)
	{
		cred.cCreds     = 1;
		cred.paCred     = &cert;
	}

	rc = AcquireCredentialsHandle( NULL, "SChannel", SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credHandle, &useBefore );

	ctxReq = ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS;
	strncpy(myTokenSource,hostname,sizeof(myTokenSource));

	CertCloseStore(hMy,0);

	ib[0].pvBuffer = NULL;

	while ( 1 )
	{
		obd.ulVersion = SECBUFFER_VERSION;
		obd.cBuffers = 1;
		obd.pBuffers = &ob; // just one buffer
		ob.BufferType = SECBUFFER_TOKEN; // preping a token here
		ob.cbBuffer = secPackInfo->cbMaxToken;
		ob.pvBuffer = malloc(secPackInfo->cbMaxToken);

		rcISC = InitializeSecurityContext( &credHandle, haveContext? &contextHandle: NULL,
			myTokenSource, ctxReq, 0, SECURITY_NATIVE_DREP, haveInbuffer? &ibd: NULL,
			0, &contextHandle, &obd, &ctxAttr, &useBefore );

		if ( ib[0].pvBuffer != NULL )
		{
			free(ib[0].pvBuffer);
			ib[0].pvBuffer = NULL;
		}

		if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE || rcISC == SEC_I_COMPLETE_NEEDED )
		{
			CompleteAuthToken( &contextHandle, &obd );
			if ( rcISC == SEC_I_COMPLETE_NEEDED )
				rcISC = SEC_E_OK;
			else if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE )
				rcISC = SEC_I_CONTINUE_NEEDED;
		}

		if(rcISC<0)
		{
			server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC));
		}

		// send the output buffer off to the server
		if ( ob.cbBuffer != 0 )
		{
			if((dwWritten=tcp_write( (const char *) ob.pvBuffer, ob.cbBuffer))<=0)
				break;
			bytesSent += dwWritten;
		}
		free(ob.pvBuffer);
		ob.pvBuffer = NULL;
		ob.cbBuffer = 0;

		if ( rcISC != SEC_I_CONTINUE_NEEDED )
			break;

		// prepare to get the server's response
		ibd.ulVersion = SECBUFFER_VERSION;
		ibd.cBuffers = 2;
		ibd.pBuffers = ib; // just one buffer
		ib[0].BufferType = SECBUFFER_TOKEN; // preping a token here
		ib[0].cbBuffer = secPackInfo->cbMaxToken;
		ib[0].pvBuffer = malloc(secPackInfo->cbMaxToken);
		ib[1].cbBuffer = 0;
		ib[1].pvBuffer = NULL;
		ib[1].BufferType = SECBUFFER_EMPTY; // Spare stuff

		// receive the server's response
		if((dwRead=tcp_read(ib[0].pvBuffer,ib[0].cbBuffer))<=0)
			break;
		bytesReceived += dwRead;

		// by now we have an input buffer and a client context

		haveInbuffer = TRUE;
		haveContext = TRUE;
	}

	// we arrive here as soon as InitializeSecurityContext()
	// returns != SEC_I_CONTINUE_NEEDED.

	if ( rcISC != SEC_E_OK )
		haveContext = FALSE;
	else
		haveContext = TRUE; /* Looopback kerberos needs this */

	return haveContext;
}
Exemplo n.º 2
0
void test()
{
	SchannelCredential schannelCredential(SECPKG_CRED_OUTBOUND, NULL);

	CtxtHandle contextHandle;

	SecBufferArray<1> outputBufferArray;
	initializeSecBuffer(outputBufferArray[0], SECBUFFER_TOKEN, tokenBuffer, sizeof(tokenBuffer));

	ULONG contextAttributes;

	SECURITY_STATUS result = InitializeSecurityContext(
		&schannelCredential.getHandle(),
		NULL,
		NULL,
		0,
		0,
		0,
		NULL,
		0,
		&contextHandle,
		&outputBufferArray.getDescriptor(),
		&contextAttributes,
		NULL);

	std::cout << outputBufferArray[0].cbBuffer << '\n';
}
Exemplo n.º 3
0
void LSSLContext::Shutdown(LSockByteStream* SockByteStream, const TCHAR* TargetName)
{
	//SSPI: отключение от сервера
	//сначала выставим нужный статус у контекста
	DWORD ShutdownToken = SCHANNEL_SHUTDOWN;
	SecBufferDesc ShutDownBufferDesc;
	SecBuffer     ShutDownBuffers[1];
	ShutDownBufferDesc.cBuffers = 1;
	ShutDownBufferDesc.pBuffers = ShutDownBuffers;
	ShutDownBufferDesc.ulVersion = SECBUFFER_VERSION;
	ShutDownBuffers[0].pvBuffer   = &ShutdownToken;
	ShutDownBuffers[0].BufferType = SECBUFFER_TOKEN;
	ShutDownBuffers[0].cbBuffer   = sizeof(ShutdownToken);

	//VERIFY(SEC_E_OK==ApplyControlToken(GetContextHandle(), &ShutDownBufferDesc));

	//затем получим данные для отправки
	ShutDownBuffers[0].BufferType = SECBUFFER_TOKEN;
	ShutDownBuffers[0].pvBuffer   = 0;
	ShutDownBuffers[0].cbBuffer   = 0;

	/*VERIFY(SEC_E_OK==*/InitializeSecurityContext(&m_hUserCred, GetContextHandle(), const_cast<TCHAR*>(TargetName),
		                                       m_ReqContextAttr, 0, 0, 0, 0, 0,
		                                       &ShutDownBufferDesc, &m_ContextAttr, &m_ContextExpiry)/*)*/;

	//ASSERT(ShutDownBuffers[0].pvBuffer&&ShutDownBuffers[0].cbBuffer);

	//WS: отправим обработанные SCHANNEL данные
	SockByteStream->RawSend(ShutDownBuffers[0].pvBuffer, ShutDownBuffers[0].cbBuffer);

	FreeContextBuffer(ShutDownBuffers[0].pvBuffer);
	ShutDownBuffers[0].pvBuffer=0;
	ShutDownBuffers[0].cbBuffer=0;
}
Exemplo n.º 4
0
/* sqAuthContinue: Submit a token to the authentication session.
   Arguments:
     handle - the authentication session handle
     token - the pointer to the token data
     tokensize - the length of the token data.
   Returns:
     An integer status code.
     <0 - Error. The error code is platform specific.
      0 - OK. The session is authenticated.
      1 - Another server-roundtrip is needed.
*/
int sqAuthContinue(int handle, char *token, int tokensize) {
  sqAuthData *auth = (sqAuthData*)handle;
  SECURITY_STATUS ret;
  ULONG flags = DEFAULT_AUTH_FLAGS;
  ULONG attrs = 0;

  if(auth == NULL) return -1;

  auth->inbuf[0].BufferType = SECBUFFER_TOKEN;
  auth->inbuf[0].cbBuffer = tokensize;
  auth->inbuf[0].pvBuffer = token;
  auth->inbuf[1].BufferType = SECBUFFER_EMPTY;
  auth->inbuf[1].cbBuffer = 0;
  auth->inbuf[1].pvBuffer = NULL;
  auth->sbdIn.cBuffers = 2;

  ret = InitializeSecurityContext(&auth->cred,
				  &auth->ctxt,
				  auth->principal,
				  flags, 
				  0,
				  SECURITY_NETWORK_DREP, 
				  &auth->sbdIn, 
				  0,
				  NULL,
				  &auth->sbdOut,
				  &attrs, 
				  NULL);


  if (FAILED(ret)) {
    if(debug) printf("InitializeSecurityContext failed: %x\n", ret);
    return -(ret & 0x7FFFFFFF);
  }

  if(debug) printf("InitializeSecurityContext returned: %x\n", ret);

  /* Complete token if needed */
  if(ret == SEC_I_COMPLETE_NEEDED || ret == SEC_I_COMPLETE_AND_CONTINUE)  {
    SECURITY_STATUS ss;
    ss = CompleteAuthToken (&auth->ctxt, &auth->sbdOut);
    if(FAILED(ss)) {
      if(debug) printf("CompleteAuthToken failed: %x\n", ss);
      return ss;
    }
   }

  if(ret == SEC_E_OK || ret == SEC_I_COMPLETE_NEEDED) {
    /* success; session is established */
    return 0;
  }

  if(ret == SEC_I_CONTINUE_NEEDED || ret == SEC_I_COMPLETE_AND_CONTINUE) {
    /* need another round trip */
    return 1;
  }
  return -ret;
}
Exemplo n.º 5
0
int SSL_SOCKET :: ClientOff()
	{
	// Client wants to disconnect

	SECURITY_STATUS ss;
	Z<SecBuffer> OutBuffers(100);
	DWORD dwType = SCHANNEL_SHUTDOWN;
	OutBuffers[0].pvBuffer   = &dwType;
   OutBuffers[0].BufferType = SECBUFFER_TOKEN;
   OutBuffers[0].cbBuffer   = sizeof(dwType);

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

	for(;;)
		{
		ss =  ApplyControlToken(&hCtx, &sbout);
		if (FAILED(ss))
			return -1;


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

		OutBuffers[0].pvBuffer   = NULL;
		OutBuffers[0].BufferType = SECBUFFER_TOKEN;
		OutBuffers[0].cbBuffer   = 0;
		sbout.cBuffers  = 1;
		sbout.pBuffers  = OutBuffers;
		sbout.ulVersion = SECBUFFER_VERSION;

		ss = InitializeSecurityContext(&hCred,&hCtx,NULL,dwSSPIFlags,0,SECURITY_NATIVE_DREP, NULL,0,&hCtx,&sbout,&dwSSPIOutFlags,0);
		if (FAILED(ss))
			return -1;

	   PBYTE           pbMessage;
		DWORD           cbMessage;
		pbMessage = (BYTE *)(OutBuffers[0].pvBuffer);
		cbMessage = OutBuffers[0].cbBuffer;

		if (pbMessage != NULL && cbMessage != 0) 
			{
			int rval = ssend_p((char*)pbMessage, cbMessage);
			FreeContextBuffer(pbMessage);
			return rval;
			}
		break;
		}
	return 1;
	}
Exemplo n.º 6
0
static int tls_client_handshake(URLContext *h)
{
    TLSContext *c = h->priv_data;
    TLSShared *s = &c->tls_shared;
    SecBuffer outbuf;
    SecBufferDesc outbuf_desc;
    SECURITY_STATUS sspi_ret;
    int ret;

    init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
    init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);

    c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
                       ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
                       ISC_REQ_STREAM;

    sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
                                         NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
                                         &c->ctxt_timestamp);
    if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
        av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret);
        ret = AVERROR_UNKNOWN;
        goto fail;
    }

    ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
    FreeContextBuffer(outbuf.pvBuffer);
    if (ret < 0 || ret != outbuf.cbBuffer) {
        av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
        ret = AVERROR(EIO);
        goto fail;
    }

    return tls_client_handshake_loop(h, 1);

fail:
    DeleteSecurityContext(&c->ctxt_handle);
    return ret;
}
Exemplo n.º 7
0
static int tls_shutdown_client(URLContext *h)
{
    TLSContext *c = h->priv_data;
    TLSShared *s = &c->tls_shared;
    int ret;

    if (c->connected) {
        SecBufferDesc BuffDesc;
        SecBuffer Buffer;
        SECURITY_STATUS sspi_ret;
        SecBuffer outbuf;
        SecBufferDesc outbuf_desc;

        DWORD dwshut = SCHANNEL_SHUTDOWN;
        init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
        init_sec_buffer_desc(&BuffDesc, &Buffer, 1);

        sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc);
        if (sspi_ret != SEC_E_OK)
            av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n");

        init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
        init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);

        sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host,
                                             c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle,
                                             &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
        if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) {
            ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
            FreeContextBuffer(outbuf.pvBuffer);
            if (ret < 0 || ret != outbuf.cbBuffer)
                av_log(h, AV_LOG_ERROR, "Failed to send close message\n");
        }

        c->connected = 0;
    }
    return 0;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
/*
 * '_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);
}
Exemplo n.º 10
0
BOOL GenClientContext (
BYTE       *pIn,
DWORD       cbIn,
BYTE       *pOut,
DWORD      *pcbOut,
BOOL       *pfDone,
CHAR       *pszTarget,
CredHandle *hCred,
struct _SecHandle *hcText)
{
	SECURITY_STATUS   ss;
	TimeStamp         Lifetime;
	SecBufferDesc     OutBuffDesc;
	SecBuffer         OutSecBuff;
	SecBufferDesc     InBuffDesc;
	SecBuffer         InSecBuff;
	ULONG             ContextAttributes;
	static TCHAR      lpPackageName[1024];

	if( NULL == pIn )  
	{   
		strcpy_s(lpPackageName, 1024 * sizeof(TCHAR), "Negotiate");
		ss = AcquireCredentialsHandle (
		NULL, 
		lpPackageName,
		SECPKG_CRED_OUTBOUND,
		NULL, 
		NULL, 
		NULL, 
		NULL, 
		hCred,
		&Lifetime);

		if (!(SEC_SUCCESS (ss)))
		{
			MyHandleError("AcquireCreds failed ");
		}
	}

	//--------------------------------------------------------------------
	//  Prepare the buffers.

	OutBuffDesc.ulVersion = 0;
	OutBuffDesc.cBuffers  = 1;
	OutBuffDesc.pBuffers  = &OutSecBuff;

	OutSecBuff.cbBuffer   = *pcbOut;
	OutSecBuff.BufferType = SECBUFFER_TOKEN;
	OutSecBuff.pvBuffer   = pOut;

	//-------------------------------------------------------------------
	//  The input buffer is created only if a message has been received 
	//  from the server.

	if (pIn)   
	{
		InBuffDesc.ulVersion = 0;
		InBuffDesc.cBuffers  = 1;
		InBuffDesc.pBuffers  = &InSecBuff;

		InSecBuff.cbBuffer   = cbIn;
		InSecBuff.BufferType = SECBUFFER_TOKEN;
		InSecBuff.pvBuffer   = pIn;

		ss = InitializeSecurityContext (
		hCred,
		hcText,
		pszTarget,
		MessageAttribute, 
		0,
		SECURITY_NATIVE_DREP,
		&InBuffDesc,
		0, 
		hcText,
		&OutBuffDesc,
		&ContextAttributes,
		&Lifetime);
	}
	else
	{
		ss = InitializeSecurityContext (
		hCred,
		NULL,
		pszTarget,
		MessageAttribute, 
		0, 
		SECURITY_NATIVE_DREP,
		NULL,
		0, 
		hcText,
		&OutBuffDesc,
		&ContextAttributes,
		&Lifetime);
	}

	if (!SEC_SUCCESS (ss))  
	{
		MyHandleError ("InitializeSecurityContext failed " );
	}

	//-------------------------------------------------------------------
	//  If necessary, complete the token.

	if ((SEC_I_COMPLETE_NEEDED == ss) 
			|| (SEC_I_COMPLETE_AND_CONTINUE == ss))  
	{
		ss = CompleteAuthToken (hcText, &OutBuffDesc);
		if (!SEC_SUCCESS(ss))  
		{
			fprintf (stderr, "complete failed: 0x%08x\n", ss);
			return FALSE;
		}
	}

	*pcbOut = OutSecBuff.cbBuffer;

	*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
	(SEC_I_COMPLETE_AND_CONTINUE == ss));

	printf ("Token buffer generated (%lu bytes):\n", OutSecBuff.cbBuffer);
	PrintHexDump (OutSecBuff.cbBuffer, (PBYTE)OutSecBuff.pvBuffer);
	return TRUE;

}
Exemplo n.º 11
0
int SSL_SOCKET :: ClientLoop()
	{
	SECURITY_STATUS ss = SEC_I_CONTINUE_NEEDED;
	Z<char> t(0x11000);
	Z<SecBuffer> bufsi(100);
	Z<SecBuffer> bufso(100);
	int pt = 0;

	// Loop using InitializeSecurityContext until success
	for(;;)
		{
		if (ss != SEC_I_CONTINUE_NEEDED && ss != SEC_E_INCOMPLETE_MESSAGE && ss != SEC_I_INCOMPLETE_CREDENTIALS)
			break;

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

		dwSSPIFlags |= ISC_REQ_MANUAL_CRED_VALIDATION;
	
		if (InitContext == 0)
			{
			// Initialize sbout
		   bufso[0].pvBuffer   = NULL;
			bufso[0].BufferType = SECBUFFER_TOKEN;
			bufso[0].cbBuffer   = 0;
			sbout.ulVersion = SECBUFFER_VERSION;
			sbout.cBuffers = 1;
			sbout.pBuffers = bufso;
			}
		else
			{
			// Get Some data from the remote site

			// Add also extradata?
			if (ExtraDataSize)
				{
				memcpy(t,ExtraData,ExtraDataSize);
				pt += ExtraDataSize;
				ExtraDataSize = 0;
				}


			int rval = recv(X,t + pt,0x10000,0);
			if (rval == 0 || rval == -1)
				return rval;
			pt += rval;

			// Put this data into the buffer so InitializeSecurityContext will do

			bufsi[0].BufferType = SECBUFFER_TOKEN;
			bufsi[0].cbBuffer = pt;
			bufsi[0].pvBuffer = t;
			bufsi[1].BufferType = SECBUFFER_EMPTY;
			bufsi[1].cbBuffer = 0;
			bufsi[1].pvBuffer = 0;
			sbin.ulVersion = SECBUFFER_VERSION;
			sbin.pBuffers = bufsi;
			sbin.cBuffers = 2;

			bufso[0].pvBuffer  = NULL;
			bufso[0].BufferType= SECBUFFER_TOKEN;
         bufso[0].cbBuffer  = 0;
			sbout.cBuffers      = 1;
			sbout.pBuffers      = bufso;
			sbout.ulVersion     = SECBUFFER_VERSION;

			}

	   DWORD dwSSPIOutFlags = 0;

		SEC_E_INTERNAL_ERROR;
		ss = InitializeSecurityContext(
			&hCred,
			InitContext ? &hCtx : 0,
			dn,
			dwSSPIFlags,
			0,
			0,//SECURITY_NATIVE_DREP,
			InitContext ? &sbin : 0,
			0,
			InitContext ? 0 : &hCtx,
			&sbout,
			&dwSSPIOutFlags,
			0);

		if (ss == SEC_E_INCOMPLETE_MESSAGE)
			continue; // allow more

		pt = 0;

		if (FAILED(ss))
			return -1;

		if (InitContext == 0 && ss != SEC_I_CONTINUE_NEEDED)
			return -1;

		// Handle possible ExtraData
/*		if (bufsi[1].BufferType == SECBUFFER_EXTRA)
			{
			ExtraDataSize = bufsi[1].cbBuffer;
			ExtraData.Resize(ExtraDataSize + 10);
			memcpy(ExtraData,bufsi[1].pvBuffer,ExtraDataSize);
			}
*/

		if (!InitContext)
			{
			// Send the data we got to the remote part
			//cbData = Send(OutBuffers[0].pvBuffer,OutBuffers[0].cbBuffer);
			int rval = ssend_p((char*)bufso[0].pvBuffer,bufso[0].cbBuffer);
			FreeContextBuffer(bufso[0].pvBuffer);
			if (rval != bufso[0].cbBuffer)
				return -1;
			InitContext = true;
			continue;
			}

		// Pass data to the remote site
		int rval = ssend_p((char*)bufso[0].pvBuffer,bufso[0].cbBuffer);
		FreeContextBuffer(bufso[0].pvBuffer);
		if (rval != bufso[0].cbBuffer)
			return -1;


		if (ss == S_OK)
			break; // wow!!
		
		}
	return 0;
	}
Exemplo n.º 12
0
void LSSLContext::Handshake(LSockByteStream* SockByteStream, const TCHAR* TargetName)
{
	SecPkgInfo* PkgInfo;
	/*VERIFY(SEC_E_OK==*/QuerySecurityPackageInfo(UNISP_NAME, &PkgInfo)/*)*/;
	std::vector<BYTE> SockDataBuf(PkgInfo->cbMaxToken);
	FreeContextBuffer(PkgInfo);

	//SSPI:HandShake
	SecBufferDesc InBufferDesc;
	SecBuffer     InBuffers[2];
	InBufferDesc.ulVersion = SECBUFFER_VERSION;
	InBufferDesc.pBuffers = InBuffers;
	InBufferDesc.cBuffers = 2;

	SecBufferDesc OutBufferDesc;
	SecBuffer     OutBuffers[1];
	OutBufferDesc.ulVersion = SECBUFFER_VERSION;
	OutBufferDesc.pBuffers = OutBuffers;
	OutBufferDesc.cBuffers = 1;

	//первичное обращение об инициализации контекста
	OutBuffers[0].BufferType = SECBUFFER_TOKEN;
	OutBuffers[0].pvBuffer   = NULL;
	OutBuffers[0].cbBuffer   = 0;
	SECURITY_STATUS sec_s = InitializeSecurityContext(&m_hUserCred, 0, const_cast<TCHAR*>(TargetName),
		m_ReqContextAttr, 0, 0, NULL, 0, &m_hContext, &OutBufferDesc, &m_ContextAttr, &m_ContextExpiry);
	//ASSERT(SEC_E_OK==sec_s||SEC_I_CONTINUE_NEEDED==sec_s);

	unsigned int SockDataSize=0;
	bool WasExtra=false;
	while(SEC_I_CONTINUE_NEEDED==sec_s){
		//оба поля должны быть либо указаны либо не указаны, т.к. иначе не совсем понятно что это означает
		//ASSERT((OutBuffers[0].pvBuffer&&OutBuffers[0].cbBuffer)||(!OutBuffers[0].pvBuffer&&!OutBuffers[0].cbBuffer));
		//отсылаем только если есть что отсылать
		if(OutBuffers[0].pvBuffer&&OutBuffers[0].cbBuffer){
			//ASSERT(OutBuffers[0].pvBuffer);
			//ASSERT(OutBuffers[0].cbBuffer);
		
			//WS: отправим обработанные SCHANNEL данные
			SockByteStream->RawSend(OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer);
		
			//SSPI:освободим выделенную SCHANNEL память
			FreeContextBuffer(OutBuffers[0].pvBuffer);
		}
	
		//OutBuffers[0].BufferType=SECBUFFER_EMPTY; OutBuffers[0].pvBuffer=0; OutBuffers[0].cbBuffer=0;//нет необходимости
		do{
			//ASSERT(SockDataBuf.size()>SockDataSize);

			//WS:получим ответ сервера (или его часть)
			if(!WasExtra){
				SockDataSize+= SockByteStream->RawRecv(&SockDataBuf[SockDataSize], SockDataBuf.size()-SockDataSize);
			}
			else{
				//пропустим 1 получение данных, т.к. в SECBUFFER_EXTRA может быть полный пакет,
				//и как следствие сервер ничего уже посылать не будет.
				//если же пакет все же не полный то получим SEC_E_INCOMPLETE_MESSAGE,
				//и просто выполним лишнюю итерацию.
				WasExtra=false;
			}

			//SSPI:передадим этот ответ в InitializeSecurityContext, и в случае если он скажет что надо еще данных -
			//опять запросим данные с сервера. и так до тех пор пока SCHANNEL не скажет "хватит".
			InBuffers[0].BufferType = SECBUFFER_TOKEN;
			InBuffers[0].pvBuffer   = &SockDataBuf[0];
			InBuffers[0].cbBuffer   = SockDataSize;
			InBuffers[1].BufferType = SECBUFFER_EMPTY;
			InBuffers[1].pvBuffer   = NULL;
			InBuffers[1].cbBuffer   = 0;

			sec_s = InitializeSecurityContext(&m_hUserCred, &m_hContext, const_cast<TCHAR*>(TargetName),
				m_ReqContextAttr, 0, 0, &InBufferDesc, 0, 0, &OutBufferDesc, &m_ContextAttr, &m_ContextExpiry);
		}while(SEC_E_INCOMPLETE_MESSAGE==sec_s);
	
		//ASSERT(SEC_E_OK==sec_s||SEC_I_CONTINUE_NEEDED==sec_s);

		//может быть SECBUFFER_EXTRA
		//ASSERT(SECBUFFER_EXTRA!=InBuffers[0].BufferType);//такого вроде не должно быть
		if(SECBUFFER_EXTRA==InBuffers[1].BufferType){
			WasExtra=true;
			if(SEC_I_CONTINUE_NEEDED==sec_s){
				//Handshake еще не завершен. просто сервер выслал больше данных чем нужно было на данном шаге.
				//переносим эти данные на следующую итерацию
				memmove(&SockDataBuf[0],
						((BYTE*)InBuffers[0].pvBuffer)+InBuffers[0].cbBuffer-InBuffers[1].cbBuffer,
				        InBuffers[1].cbBuffer);
				SockDataSize=InBuffers[1].cbBuffer;
			}
			else{
				//если Handshake уже завершен, значит SECBUFFER_EXTRA относится уже к основному протоколу обмена.
				//значит нужно сохранить эту информацию во временном хранилище.
				m_HandshakeExtra.insert(m_HandshakeExtra.end(),
					((BYTE*)InBuffers[0].pvBuffer)+InBuffers[0].cbBuffer-InBuffers[1].cbBuffer,
					((BYTE*)InBuffers[0].pvBuffer)+InBuffers[0].cbBuffer);
				SockDataSize=0;
			}
		}
		else{
			SockDataSize=0;
		}
	}

	//ASSERT(0==OutBuffers[0].pvBuffer);//по идее не должно быть выделенной памяти.
}
Exemplo n.º 13
0
/* sqConnectSSL: Start/continue an SSL client handshake.
	Arguments:
		handle - the SSL handle
		srcBuf - the input token sent by the remote peer
		srcLen - the size of the input token
		dstBuf - the output buffer for a new token
		dstLen - the size of the output buffer
	Returns: The size of the output token or an error code.
*/
sqInt sqConnectSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt dstLen) {
	SecBufferDesc *sbdIn = NULL;
	SECURITY_STATUS ret;
	SCHANNEL_CRED sc_cred = { 0 };
	ULONG sslFlags, retFlags;
	sqSSL *ssl = sslFromHandle(handle);

	/* Verify state of session */
	if(ssl == NULL || (ssl->state != SQSSL_UNUSED && ssl->state != SQSSL_CONNECTING)) {
		return SQSSL_INVALID_STATE;
	}

	if(ssl->dataLen + srcLen > ssl->dataMax) {
		/* resize the data buffer */
		ssl->dataMax += (srcLen < 4096) ? (4096) : (srcLen+1024);
		ssl->dataBuf = realloc(ssl->dataBuf, ssl->dataMax);
		if(!ssl->dataBuf) return SQSSL_OUT_OF_MEMORY;
	}
	if(ssl->loglevel) printf("sqConnectSSL: input token %d bytes\n", srcLen);
	memcpy(ssl->dataBuf + ssl->dataLen, srcBuf, srcLen);
	ssl->dataLen += srcLen;

	/* Standard flags for SSL connection */
	sslFlags = 
		ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_EXTENDED_ERROR |
		ISC_REQ_INTEGRITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_STREAM |
		ISC_REQ_MANUAL_CRED_VALIDATION;

	/* Set up the input and output buffers */
	ssl->inbuf[0].BufferType = SECBUFFER_TOKEN;
	ssl->inbuf[0].cbBuffer = ssl->dataLen;
	ssl->inbuf[0].pvBuffer = ssl->dataBuf;
	ssl->inbuf[1].BufferType = SECBUFFER_EMPTY;
	ssl->inbuf[1].cbBuffer = 0;
	ssl->inbuf[1].pvBuffer = NULL;
	ssl->inbuf[2].BufferType = SECBUFFER_EMPTY;
	ssl->inbuf[2].cbBuffer = 0;
	ssl->inbuf[2].pvBuffer = NULL;
	ssl->inbuf[3].BufferType = SECBUFFER_EMPTY;
	ssl->inbuf[3].cbBuffer = 0;
	ssl->inbuf[3].pvBuffer = NULL;
	ssl->sbdIn.cBuffers = 4;

	ssl->outbuf[0].BufferType = SECBUFFER_EMPTY;
	ssl->outbuf[0].cbBuffer = 0;
	ssl->outbuf[0].pvBuffer = NULL;
	ssl->outbuf[1].BufferType = SECBUFFER_EMPTY;
	ssl->outbuf[1].cbBuffer = 0;
	ssl->outbuf[1].pvBuffer = NULL;
	ssl->sbdOut.cBuffers = 2;

	if(ssl->loglevel) printf("sqConnectSSL: Input to InitSecCtxt is %d bytes\n", ssl->dataLen);

	if(ssl->state == SQSSL_UNUSED) {
		ssl->state = SQSSL_CONNECTING;

		if(!sqSetupCert(ssl, ssl->certName, 0)) 
			/* FIXME. We need a different error code here. */
			return SQSSL_GENERIC_ERROR;

		ret = InitializeSecurityContext(&ssl->sslCred, NULL, NULL,
										sslFlags, 0, 0, NULL, 0, &ssl->sslCtxt,
										&ssl->sbdOut, &retFlags, NULL);
	} else {
		ret = InitializeSecurityContext(&ssl->sslCred, &ssl->sslCtxt, NULL,
										sslFlags, 0, 0, &ssl->sbdIn, 0, NULL,
										&ssl->sbdOut, &retFlags, NULL);
	}

	if(ssl->loglevel) printf("InitializeSecurityContext returned: %x\n", ret);

	if(ssl->loglevel) sqPrintSBD("Input Buffers:", ssl->sbdIn);
	if(ssl->loglevel) sqPrintSBD("Output Buffers:", ssl->sbdOut);

	if(ret != SEC_E_OK) {
		int count;
		/* Handle various failure conditions */
		switch(ret) {
			case SEC_E_INCOMPLETE_MESSAGE:
				/* not enough data for the handshake to complete */
				return SQSSL_NEED_MORE_DATA;
			case SEC_I_CONTINUE_NEEDED:
				/* Send contents back to peer and come back with more data */
				count = sqCopyDescToken(ssl, ssl->sbdOut, dstBuf, dstLen);
				/* Sanity checks for buffers */
				if(ssl->inbuf[0].BufferType != SECBUFFER_TOKEN) {
					if(ssl->loglevel) printf("sqConnectSSL: Unexpected buffer[0].BufferType -- %d\n", ssl->inbuf[0].BufferType);
				}
				if(ssl->inbuf[2].BufferType != SECBUFFER_EMPTY) {
					if(ssl->loglevel) printf("sqConnectSSL: Unexpected buffer[2].BufferType -- %d\n", ssl->inbuf[0].BufferType);
				}

				/* If there is SECBUFFER_EXTRA in the input we need to retain it */
				if(ssl->inbuf[1].BufferType == SECBUFFER_EXTRA) {
					int extra = ssl->inbuf[1].cbBuffer;
					if(ssl->loglevel) printf("sqConnectSSL: Retaining %d token bytes\n", extra);
					memmove(ssl->dataBuf, ssl->dataBuf + (ssl->dataLen - extra), extra);
					ssl->dataLen = extra;
				} else ssl->dataLen = 0;

				/* Don't return zero (SQSSL_OK) when more data is needed */
				return count ? count : SQSSL_NEED_MORE_DATA;
			default:
				if(ssl->loglevel) printf("Unexpected return code %d\n", ret);
				return SQSSL_GENERIC_ERROR;
		}
	}

	/* TODO: Look at retFlags */
	ssl->state = SQSSL_CONNECTED;
	/* If there is SECBUFFER_EXTRA in the input we need to retain it */
	if(ssl->inbuf[1].BufferType == SECBUFFER_EXTRA) {
		int extra = ssl->inbuf[1].cbBuffer;
		if(ssl->loglevel) printf("sqConnectSSL: Retaining %d token bytes\n", extra);
		memmove(ssl->dataBuf, ssl->dataBuf + (ssl->dataLen - extra), extra);
		ssl->dataLen = extra;
	} else {
		sqCopyExtraData(ssl, ssl->sbdOut);
	}
    ret = QueryContextAttributes(&ssl->sslCtxt, SECPKG_ATTR_STREAM_SIZES, &ssl->sslSizes);
	if(ssl->loglevel) printf("sqConnectSSL: Maximum message size is %d bytes\n", ssl->sslSizes.cbMaximumMessage);

	/* Extract the peer name */
	sqExtractPeerName(ssl);

	/* Verify the certificate (sets certFlags) */
	sqVerifyCert(ssl, false);

	return SQSSL_OK;
}
Exemplo n.º 14
0
static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;

    if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + size) == 0)
    {
        memcpy(tls_io_instance->received_bytes + tls_io_instance->received_byte_count, buffer, size);
        tls_io_instance->received_byte_count += size;

        if (size > tls_io_instance->needed_bytes)
        {
            tls_io_instance->needed_bytes = 0;
        }
        else
        {
            tls_io_instance->needed_bytes -= size;
        }

        switch (tls_io_instance->tlsio_state)
        {
        default:
            break;

        case TLSIO_STATE_ERROR:
            break;

        case TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT:
        {
            if (tls_io_instance->needed_bytes == 0)
            {
                SecBuffer input_buffers[2];
                SecBuffer output_buffers[2];
                ULONG context_attributes;

                /* we need to try and perform the second (next) step of the init */
                input_buffers[0].cbBuffer = tls_io_instance->received_byte_count;
                input_buffers[0].BufferType = SECBUFFER_TOKEN;
                input_buffers[0].pvBuffer = (void*)tls_io_instance->received_bytes;
                input_buffers[1].cbBuffer = 0;
                input_buffers[1].BufferType = SECBUFFER_EMPTY;
                input_buffers[1].pvBuffer = 0;

                SecBufferDesc input_buffers_desc;
                input_buffers_desc.cBuffers = 2;
                input_buffers_desc.pBuffers = input_buffers;
                input_buffers_desc.ulVersion = SECBUFFER_VERSION;

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

                SecBufferDesc output_buffers_desc;
                output_buffers_desc.cBuffers = 2;
                output_buffers_desc.pBuffers = output_buffers;
                output_buffers_desc.ulVersion = SECBUFFER_VERSION;

                SECURITY_STATUS status = InitializeSecurityContext(&tls_io_instance->credential_handle,
                    &tls_io_instance->security_context, (SEC_CHAR*)tls_io_instance->host_name, ISC_REQ_EXTENDED_ERROR | ISC_REQ_STREAM | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, &input_buffers_desc, 0,
                    &tls_io_instance->security_context, &output_buffers_desc,
                    &context_attributes, NULL);

                switch (status)
                {
                case SEC_E_INCOMPLETE_MESSAGE:
                    if (input_buffers[1].BufferType != SECBUFFER_MISSING)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        tls_io_instance->needed_bytes = input_buffers[1].cbBuffer;
                        tls_io_instance->consumed_bytes += tls_io_instance->needed_bytes;
                        if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + tls_io_instance->needed_bytes) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            if (tls_io_instance->on_io_open_complete != NULL)
                            {
                                tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                            }
                        }
                    }
                    break;
                case SEC_E_OK:
                    memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + tls_io_instance->consumed_bytes, tls_io_instance->received_byte_count - tls_io_instance->consumed_bytes);
                    tls_io_instance->received_byte_count -= tls_io_instance->consumed_bytes;

                    tls_io_instance->needed_bytes = 1;
                    tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;

                    if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_OK);
                        }
                    }

                    break;

                case SEC_I_COMPLETE_NEEDED:
                case SEC_I_CONTINUE_NEEDED:
                case SEC_I_COMPLETE_AND_CONTINUE:
                    if ((output_buffers[0].cbBuffer > 0) && xio_send(tls_io_instance->socket_io, output_buffers[0].pvBuffer, output_buffers[0].cbBuffer, NULL, NULL) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + tls_io_instance->consumed_bytes, tls_io_instance->received_byte_count - tls_io_instance->consumed_bytes);
                        tls_io_instance->received_byte_count -= tls_io_instance->consumed_bytes;

                        /* set the needed bytes to 1, to get on the next byte how many we actually need */
                        tls_io_instance->needed_bytes = 1;
                        tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;
                        if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                        {
                            FreeCredentialHandle(&tls_io_instance->credential_handle);
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            if (tls_io_instance->on_io_open_complete != NULL)
                            {
                                tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                            }
                        }
                        else
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT;
                        }
                    }
                    break;
                }
            }

            break;

        case TLSIO_STATE_OPEN:
        {
            if (tls_io_instance->needed_bytes == 0)
            {
                SecBuffer security_buffers[4];
                SecBufferDesc security_buffers_desc;

                security_buffers[0].BufferType = SECBUFFER_DATA;
                security_buffers[0].pvBuffer = tls_io_instance->received_bytes;
                security_buffers[0].cbBuffer = tls_io_instance->received_byte_count;
                security_buffers[1].BufferType = SECBUFFER_EMPTY;
                security_buffers[2].BufferType = SECBUFFER_EMPTY;
                security_buffers[3].BufferType = SECBUFFER_EMPTY;

                security_buffers_desc.cBuffers = sizeof(security_buffers) / sizeof(security_buffers[0]);
                security_buffers_desc.pBuffers = security_buffers;
                security_buffers_desc.ulVersion = SECBUFFER_VERSION;

                SECURITY_STATUS status = DecryptMessage(&tls_io_instance->security_context, &security_buffers_desc, 0, NULL);
                switch (status)
                {
                case SEC_E_INCOMPLETE_MESSAGE:
                    if (security_buffers[1].BufferType != SECBUFFER_MISSING)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    else
                    {
                        tls_io_instance->needed_bytes = security_buffers[1].cbBuffer;
                        tls_io_instance->consumed_bytes += tls_io_instance->needed_bytes;
                        if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + tls_io_instance->needed_bytes) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            indicate_error(tls_io_instance);
                        }
                    }
                    break;

                case SEC_E_OK:
                    if (security_buffers[1].BufferType != SECBUFFER_DATA)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    else
                    {
                        size_t i;
                        for (i = 0; i < security_buffers[1].cbBuffer; i++)
                        {
                            LOG(tls_io_instance->logger_log, 0, "<-%02x ", ((unsigned char*)security_buffers[1].pvBuffer)[i]);
                        }

                        /* notify of the received data */
                        if (tls_io_instance->on_bytes_received != NULL)
                        {
                            tls_io_instance->on_bytes_received(tls_io_instance->open_callback_context, security_buffers[1].pvBuffer, security_buffers[1].cbBuffer);
                        }

                        (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + tls_io_instance->consumed_bytes, tls_io_instance->received_byte_count - tls_io_instance->consumed_bytes);
                        tls_io_instance->received_byte_count -= tls_io_instance->consumed_bytes;

                        tls_io_instance->needed_bytes = 1;
                        tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;

                        if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            indicate_error(tls_io_instance);
                        }
                    }
                    break;
                }
            }

            break;
        }
        }
        }
    }
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
apr_status_t
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
                            const char *service,
                            const char *hostname,
                            serf__kerb_buffer_t *input_buf,
                            serf__kerb_buffer_t *output_buf,
                            apr_pool_t *scratch_pool,
                            apr_pool_t *result_pool
                            )
{
    SECURITY_STATUS status;
    ULONG actual_attr;
    SecBuffer sspi_in_buffer;
    SecBufferDesc sspi_in_buffer_desc;
    SecBuffer sspi_out_buffer;
    SecBufferDesc sspi_out_buffer_desc;
    char *target_name;
    apr_status_t apr_status;
    const char *canonname;

    apr_status = get_canonical_hostname(&canonname, hostname, scratch_pool);
    if (apr_status) {
        return apr_status;
    }
    target_name = apr_pstrcat(scratch_pool, service, "/", canonname, NULL);

    /* Prepare input buffer description. */
    sspi_in_buffer.BufferType = SECBUFFER_TOKEN;
    sspi_in_buffer.pvBuffer = input_buf->value;
    sspi_in_buffer.cbBuffer = input_buf->length; 

    sspi_in_buffer_desc.cBuffers = 1;
    sspi_in_buffer_desc.pBuffers = &sspi_in_buffer;
    sspi_in_buffer_desc.ulVersion = SECBUFFER_VERSION;

    /* Output buffers. Output buffer will be allocated by system. */
    sspi_out_buffer.BufferType = SECBUFFER_TOKEN;
    sspi_out_buffer.pvBuffer = NULL; 
    sspi_out_buffer.cbBuffer = 0;

    sspi_out_buffer_desc.cBuffers = 1;
    sspi_out_buffer_desc.pBuffers = &sspi_out_buffer;
    sspi_out_buffer_desc.ulVersion = SECBUFFER_VERSION;

    status = InitializeSecurityContext(
        &ctx->sspi_credentials,
        ctx->initalized ? &ctx->sspi_context : NULL,
        target_name,
        ISC_REQ_ALLOCATE_MEMORY
        | ISC_REQ_MUTUAL_AUTH
        | ISC_REQ_CONFIDENTIALITY,
        0,                          /* Reserved1 */
        SECURITY_NETWORK_DREP,
        &sspi_in_buffer_desc,
        0,                          /* Reserved2 */
        &ctx->sspi_context,
        &sspi_out_buffer_desc,
        &actual_attr,
        NULL);

    if (sspi_out_buffer.cbBuffer > 0) {
        apr_pool_cleanup_register(result_pool, sspi_out_buffer.pvBuffer,
                                  cleanup_sec_buffer,
                                  apr_pool_cleanup_null);
    }

    ctx->initalized = TRUE;

    /* Finish authentication if SSPI requires so. */
    if (status == SEC_I_COMPLETE_NEEDED
        || status == SEC_I_COMPLETE_AND_CONTINUE)
    {
        CompleteAuthToken(&ctx->sspi_context, &sspi_out_buffer_desc);
    }

    output_buf->value = sspi_out_buffer.pvBuffer;
    output_buf->length = sspi_out_buffer.cbBuffer;

    switch(status) {
    case SEC_I_COMPLETE_AND_CONTINUE:
    case SEC_I_CONTINUE_NEEDED:
        return APR_EAGAIN;

    case SEC_I_COMPLETE_NEEDED:
    case SEC_E_OK:
        return APR_SUCCESS;

    default:
        return map_sspi_status(status);
    }
}
Exemplo n.º 18
0
static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    size_t consumed_bytes;

    LOG(tls_io_instance->logger_log, LOG_LINE, "%d received on tls_schannel", size);

    if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + size) == 0)
    {
        memcpy(tls_io_instance->received_bytes + tls_io_instance->received_byte_count, buffer, size);
        tls_io_instance->received_byte_count += size;

        if (size > tls_io_instance->needed_bytes)
        {
            tls_io_instance->needed_bytes = 0;
        }
        else
        {
            tls_io_instance->needed_bytes -= size;
        }

        /* Drain what we received */
        while (tls_io_instance->needed_bytes == 0)
        {
            if (tls_io_instance->tlsio_state == TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT)
            {
                SecBuffer input_buffers[2];
                SecBuffer output_buffers[2];
                ULONG context_attributes;

                /* we need to try and perform the second (next) step of the init */
                input_buffers[0].cbBuffer = tls_io_instance->received_byte_count;
                input_buffers[0].BufferType = SECBUFFER_TOKEN;
                input_buffers[0].pvBuffer = (void*)tls_io_instance->received_bytes;
                input_buffers[1].cbBuffer = 0;
                input_buffers[1].BufferType = SECBUFFER_EMPTY;
                input_buffers[1].pvBuffer = 0;

                SecBufferDesc input_buffers_desc;
                input_buffers_desc.cBuffers = 2;
                input_buffers_desc.pBuffers = input_buffers;
                input_buffers_desc.ulVersion = SECBUFFER_VERSION;

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

                SecBufferDesc output_buffers_desc;
                output_buffers_desc.cBuffers = 2;
                output_buffers_desc.pBuffers = output_buffers;
                output_buffers_desc.ulVersion = SECBUFFER_VERSION;

                unsigned long flags = ISC_REQ_EXTENDED_ERROR | ISC_REQ_STREAM | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_USE_SUPPLIED_CREDS;
                SECURITY_STATUS status = InitializeSecurityContext(&tls_io_instance->credential_handle,
                    &tls_io_instance->security_context, (SEC_CHAR*)tls_io_instance->host_name, flags, 0, 0, &input_buffers_desc, 0,
                    &tls_io_instance->security_context, &output_buffers_desc,
                    &context_attributes, NULL);

                switch (status)
                {
                case SEC_E_INCOMPLETE_MESSAGE:
                    if (input_buffers[1].BufferType != SECBUFFER_MISSING)
                    {
                        //If SECBUFFER_MISSING not sent, try to read byte by byte. 
                        tls_io_instance->needed_bytes = 1;
                    }
                    else
                    {
                        tls_io_instance->needed_bytes = input_buffers[1].cbBuffer;
                    }

                    if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + tls_io_instance->needed_bytes) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
                        }
                    }

                    break;
                case SEC_E_OK:
                    consumed_bytes = tls_io_instance->received_byte_count;
                    /* Any extra bytes left over or did we fully consume the receive buffer? */
                    if (input_buffers[1].BufferType == SECBUFFER_EXTRA)
                    {
                        consumed_bytes -= input_buffers[1].cbBuffer;
                        (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + consumed_bytes, tls_io_instance->received_byte_count - consumed_bytes);
                    }
                    tls_io_instance->received_byte_count -= consumed_bytes;

                    /* if nothing more to consume, set the needed bytes to 1, to get on the next byte how many we actually need */
                    tls_io_instance->needed_bytes = tls_io_instance->received_byte_count == 0 ? 1 : 0;

                    if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_OK);
                        }
                    }
                    break;
                case SEC_I_COMPLETE_NEEDED:
                case SEC_I_CONTINUE_NEEDED:
                case SEC_I_COMPLETE_AND_CONTINUE:
                    if ((output_buffers[0].cbBuffer > 0) && xio_send(tls_io_instance->socket_io, output_buffers[0].pvBuffer, output_buffers[0].cbBuffer, NULL, NULL) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        consumed_bytes = tls_io_instance->received_byte_count;
                        /* Any extra bytes left over or did we fully consume the receive buffer? */
                        if (input_buffers[1].BufferType == SECBUFFER_EXTRA)
                        {
                            consumed_bytes -= input_buffers[1].cbBuffer;
                            (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + consumed_bytes, tls_io_instance->received_byte_count - consumed_bytes);
                        }
                        tls_io_instance->received_byte_count -= consumed_bytes;

                        /* if nothing more to consume, set the needed bytes to 1, to get on the next byte how many we actually need */
                        tls_io_instance->needed_bytes = tls_io_instance->received_byte_count == 0 ? 1 : 0;

                        if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            if (tls_io_instance->on_io_open_complete != NULL)
                            {
                                tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
                            }
                        }
                        else
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT;
                        }
                    }
                    break;
                case SEC_E_UNTRUSTED_ROOT:
                    tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                    if (tls_io_instance->on_io_open_complete != NULL)
                    {
                        tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
                    }
                    break;
                default:
                    {
                        LPVOID srcText = NULL;
                        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                            status, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)srcText, 0, NULL) > 0)
                        {
                            LogError("[%#x] %s", status, (LPTSTR)srcText);
                            LocalFree(srcText);
                        }
                        else
                        {
                            LogError("[%#x]", status);
                        }

                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    break;
                }
            }
            else if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN)
            {
                SecBuffer security_buffers[4];
                SecBufferDesc security_buffers_desc;

                security_buffers[0].BufferType = SECBUFFER_DATA;
                security_buffers[0].pvBuffer = tls_io_instance->received_bytes;
                security_buffers[0].cbBuffer = tls_io_instance->received_byte_count;
                security_buffers[1].BufferType = SECBUFFER_EMPTY;
                security_buffers[2].BufferType = SECBUFFER_EMPTY;
                security_buffers[3].BufferType = SECBUFFER_EMPTY;

                security_buffers_desc.cBuffers = sizeof(security_buffers) / sizeof(security_buffers[0]);
                security_buffers_desc.pBuffers = security_buffers;
                security_buffers_desc.ulVersion = SECBUFFER_VERSION;

                SECURITY_STATUS status = DecryptMessage(&tls_io_instance->security_context, &security_buffers_desc, 0, NULL);
                switch (status)
                {
                case SEC_E_INCOMPLETE_MESSAGE:
                    if (security_buffers[1].BufferType != SECBUFFER_MISSING)
                    {
                        //If SECBUFFER_MISSING not sent, try to read byte by byte.
                        tls_io_instance->needed_bytes = 1;
                    }
                    else
                    {
                        tls_io_instance->needed_bytes = security_buffers[1].cbBuffer;
                    }

                    if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + tls_io_instance->needed_bytes) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    break;
                case SEC_E_OK:
                    if (security_buffers[1].BufferType != SECBUFFER_DATA)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    else
                    {
                        size_t i;
                        if (tls_io_instance->logger_log)
                        {
                            for (i = 0; i < security_buffers[1].cbBuffer; i++)
                            {
                                LOG(tls_io_instance->logger_log, 0, "-> %02x ", ((unsigned char*)security_buffers[1].pvBuffer)[i]);
                            }
                            LOG(tls_io_instance->logger_log, LOG_LINE, "");
                        }

                        /* notify of the received data */
                        if (tls_io_instance->on_bytes_received != NULL)
                        {
                            tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, security_buffers[1].pvBuffer, security_buffers[1].cbBuffer);
                        }

                        consumed_bytes = tls_io_instance->received_byte_count;

                        LOG(tls_io_instance->logger_log, LOG_LINE, "%d consumed", tls_io_instance->received_byte_count);

                        for (i = 0; i < sizeof(security_buffers) / sizeof(security_buffers[0]); i++)
                        {
                            /* Any extra bytes left over or did we fully consume the receive buffer? */
                            if (security_buffers[i].BufferType == SECBUFFER_EXTRA)
                            {
                                consumed_bytes -= security_buffers[i].cbBuffer;
                                (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + consumed_bytes, tls_io_instance->received_byte_count - consumed_bytes);
                                break;
                            }
                        }
                        tls_io_instance->received_byte_count -= consumed_bytes;

                        /* if nothing more to consume, set the needed bytes to 1, to get on the next byte how many we actually need */
                        tls_io_instance->needed_bytes = tls_io_instance->received_byte_count == 0 ? 1 : 0;

                        if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            indicate_error(tls_io_instance);
                        }
                    }
                    break;
                default:
                    {
                        LPVOID srcText = NULL;
                        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
                            status, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)srcText, 0, NULL) > 0)
                        {
                            LogError("[%#x] %s", status, (LPTSTR)srcText);
                            LocalFree(srcText);
                        }
                        else
                        {
                            LogError("[%#x]", status);
                        }

                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    break;
                }
            }
            else
            {
                /* Received data in error or other state */
                break;
            }
        }
    
    }
}
Exemplo n.º 19
0
void SchannelContext::continueHandshake(const SafeByteArray& data) 
{
	appendNewData(data);

	while (!m_receivedData.empty())
	{
		SecBuffer inBuffers[2];

		// Provide Schannel with the remote host's handshake data
		inBuffers[0].pvBuffer	 = (char*)(&m_receivedData[0]);
		inBuffers[0].cbBuffer	 = (unsigned long)m_receivedData.size();
		inBuffers[0].BufferType  = SECBUFFER_TOKEN;

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

		SecBufferDesc inBufferDesc = {0};
		inBufferDesc.cBuffers   = 2;
		inBufferDesc.pBuffers   = inBuffers;
		inBufferDesc.ulVersion  = SECBUFFER_VERSION;

		SecBuffer outBuffers[2];

		// We let Schannel allocate the output buffer for us
		outBuffers[0].pvBuffer   = NULL;
		outBuffers[0].cbBuffer   = 0;
		outBuffers[0].BufferType = SECBUFFER_TOKEN;

		// Contains alert data if an alert is generated
		outBuffers[1].pvBuffer   = NULL;
		outBuffers[1].cbBuffer   = 0;
		outBuffers[1].BufferType = SECBUFFER_ALERT;

		// Make sure the output buffers are freed
		ScopedSecBuffer scopedOutputData(&outBuffers[0]);
		ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]);

		SecBufferDesc outBufferDesc = {0};
		outBufferDesc.cBuffers   = 2;
		outBufferDesc.pBuffers   = outBuffers;
		outBufferDesc.ulVersion  = SECBUFFER_VERSION;

		SECURITY_STATUS status = InitializeSecurityContext(
			m_credHandle,
			m_ctxtHandle,
			NULL,
			m_ctxtFlags,
			0,
			0,
			&inBufferDesc,
			0,
			NULL,
			&outBufferDesc,
			&m_secContext,
			NULL);

		if (status == SEC_E_INCOMPLETE_MESSAGE)	
		{
			// Wait for more data to arrive
			break;
		}
		else if (status == SEC_I_CONTINUE_NEEDED) 
		{
			SecBuffer* pDataBuffer = &outBuffers[0];
			SecBuffer* pExtraBuffer = &inBuffers[1];
			
			if (pDataBuffer && pDataBuffer->cbBuffer > 0 && pDataBuffer->pvBuffer != NULL)
				sendDataOnNetwork(pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);

			if (pExtraBuffer->BufferType == SECBUFFER_EXTRA)
				m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
			else
				m_receivedData.clear();

			break;
		}
		else if (status == SEC_E_OK) 
		{
			status = validateServerCertificate();
			if (status != SEC_E_OK)
				handleCertError(status);

			SecBuffer* pExtraBuffer = &inBuffers[1];
			
			if (pExtraBuffer && pExtraBuffer->cbBuffer > 0)
				m_receivedData.erase(m_receivedData.begin(), m_receivedData.end() - pExtraBuffer->cbBuffer);
			else
				m_receivedData.clear();

			m_state = Connected;
			determineStreamSizes();

			onConnected();
		} 
		else 
		{
			// We failed to initialize the security context
			handleCertError(status);
			indicateError();
			return;
		}
	}
}
Exemplo n.º 20
0
static int tls_client_handshake_loop(URLContext *h, int initial)
{
    TLSContext *c = h->priv_data;
    TLSShared *s = &c->tls_shared;
    SECURITY_STATUS sspi_ret;
    SecBuffer outbuf[3];
    SecBufferDesc outbuf_desc;
    SecBuffer inbuf[2];
    SecBufferDesc inbuf_desc;
    int i, ret = 0, read_data = initial;

    if (c->enc_buf == NULL) {
        c->enc_buf_offset = 0;
        ret = av_reallocp(&c->enc_buf, SCHANNEL_INITIAL_BUFFER_SIZE);
        if (ret < 0)
            goto fail;
        c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
    }

    if (c->dec_buf == NULL) {
        c->dec_buf_offset = 0;
        ret = av_reallocp(&c->dec_buf, SCHANNEL_INITIAL_BUFFER_SIZE);
        if (ret < 0)
            goto fail;
        c->dec_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
    }

    while (1) {
        if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) {
            c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
            ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
            if (ret < 0) {
                c->enc_buf_size = c->enc_buf_offset = 0;
                goto fail;
            }
        }

        if (read_data) {
            ret = ffurl_read(c->tls_shared.tcp, c->enc_buf + c->enc_buf_offset,
                             c->enc_buf_size - c->enc_buf_offset);
            if (ret < 0) {
                av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
                goto fail;
            }
            c->enc_buf_offset += ret;
        }

        /* input buffers */
        init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
        init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
        init_sec_buffer_desc(&inbuf_desc, inbuf, 2);

        if (inbuf[0].pvBuffer == NULL) {
            av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
            ret = AVERROR(ENOMEM);
            goto fail;
        }

        memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);

        /* output buffers */
        init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
        init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
        init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
        init_sec_buffer_desc(&outbuf_desc, outbuf, 3);

        sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags,
                                             0, 0, &inbuf_desc, 0, NULL, &outbuf_desc, &c->context_flags,
                                             &c->ctxt_timestamp);
        av_freep(&inbuf[0].pvBuffer);

        if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
            av_log(h, AV_LOG_DEBUG, "Received incomplete handshake, need more data\n");
            read_data = 1;
            continue;
        }

        /* remote requests a client certificate - attempt to continue without one anyway */
        if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
            !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
            av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
            c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
            read_data = 0;
            continue;
        }

        /* continue handshake */
        if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_E_OK) {
            for (i = 0; i < 3; i++) {
                if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
                    ret = ffurl_write(c->tls_shared.tcp, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
                    if (ret < 0 || ret != outbuf[i].cbBuffer) {
                        av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
                        ret = AVERROR(EIO);
                        goto fail;
                    }
                }

                if (outbuf[i].pvBuffer != NULL) {
                    FreeContextBuffer(outbuf[i].pvBuffer);
                    outbuf[i].pvBuffer = NULL;
                }
            }
        } else {
            if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
                av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
            else
                av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
            ret = AVERROR_UNKNOWN;
            goto fail;
        }

        if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
            if (c->enc_buf_offset > inbuf[1].cbBuffer) {
                memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
                        inbuf[1].cbBuffer);
                c->enc_buf_offset = inbuf[1].cbBuffer;
                if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
                    read_data = 0;
                    continue;
                }
            }
        } else {
            c->enc_buf_offset  = 0;
        }

        if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
            read_data = 1;
            continue;
        }

        break;
    }

    return 0;

fail:
    /* free any remaining output data */
    for (i = 0; i < 3; i++) {
        if (outbuf[i].pvBuffer != NULL) {
            FreeContextBuffer(outbuf[i].pvBuffer);
            outbuf[i].pvBuffer = NULL;
        }
    }

    return ret;
}
Exemplo n.º 21
0
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;
}
Exemplo n.º 22
0
int sqAuthInitiate(char *method, char *username, char *password, char *domain, char *principal){
  SEC_WINNT_AUTH_IDENTITY credentials;
  SECURITY_STATUS ret;
  ULONG flags = DEFAULT_AUTH_FLAGS;
  ULONG attrs = 0;
  sqAuthData *auth;


  if(debug) {
    printf("sqAuthInitiate: method=%s, user=%s, pass=%s, domain=%s\n",
	   method, username, password, domain);
  }

  auth = calloc(1, sizeof(sqAuthData));
  if(principal) auth->principal = strdup(principal);
  auth->sbdIn.ulVersion = SECBUFFER_VERSION;
  auth->sbdIn.pBuffers = auth->inbuf;
  auth->sbdOut.ulVersion = SECBUFFER_VERSION;
  auth->sbdOut.pBuffers = auth->outbuf;

  /* initialize additional credentials */
  memset(&credentials,0,sizeof(SEC_WINNT_AUTH_IDENTITY));

  // XXXX: fixme. use unicode and utf8 conversion
  credentials.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
  if(username) {
    credentials.User = username;
    credentials.UserLength = strlen(username);
  }
  if(password) {
    credentials.Password = password;
    credentials.PasswordLength = strlen(password);
  }
  if(domain) {
    credentials.Domain = domain;
    credentials.DomainLength = strlen(domain);
  }

  ret = AcquireCredentialsHandle(NULL, method, SECPKG_CRED_OUTBOUND, NULL,
								 username ? &credentials : NULL,
                                 NULL, NULL, &auth->cred, &auth->expiry);

  if (ret != SEC_E_OK) {
    if(debug) printf("AquireCredentialsHandle error: %x\n", ret);
    return 0;
  }

  auth->outbuf[0].BufferType = SECBUFFER_TOKEN;
  auth->outbuf[0].cbBuffer = 0;
  auth->outbuf[0].pvBuffer = NULL;
  auth->outbuf[1].BufferType = SECBUFFER_EMPTY;
  auth->outbuf[1].cbBuffer = 0;
  auth->outbuf[1].pvBuffer = NULL;
  auth->sbdOut.cBuffers = 2;

  ret = InitializeSecurityContext(&auth->cred, 
				  NULL, 
				  auth->principal,
				  flags, 
				  0, 
				  SECURITY_NETWORK_DREP,
				  NULL,
				  0,
				  &auth->ctxt,
				  &auth->sbdOut,
				  &attrs,
				  NULL);

  /* The only expected return value here is SEC_I_CONTINUE_NEEDED
     since we're just trying to establish the auth session */
  if(ret != SEC_I_CONTINUE_NEEDED) {
    if(debug) printf("InitializeSecurityContext returned: %x\n", ret);
    return 0;
  }
  /* XXXX: fixme. return a real handle */
  return (int)auth;

}
Exemplo n.º 23
0
OM_uint32 gss_init_sec_context (OM_uint32 *minor_status,
				gss_cred_id_t claimant_cred_handle,
				gss_ctx_id_t *context_handle,
				gss_name_t target_name,gss_OID mech_type,
				OM_uint32 req_flags,OM_uint32 time_req,
				gss_channel_bindings_t input_chan_bindings,
				gss_buffer_t input_token,
				gss_OID *actual_mech_type,
				gss_buffer_t output_token,OM_uint32 *ret_flags,
				OM_uint32 *time_rec)
{
  OM_uint32 i;
  OM_uint32 major_status;
  TimeStamp expiry;
  SecBuffer ibuf[1],obuf[1];
  SecBufferDesc ibufs,obufs;
  *minor_status = 0;		/* never any minor status */
				/* error if non-default time requested */
  if (time_req) return GSS_S_FAILURE;
  if (mech_type && memcmp (mech_type,gss_mech_krb5,sizeof (gss_OID)))
    return GSS_S_BAD_MECH;
				/* ditto if any channel bindings */
  if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS)
    return GSS_S_BAD_BINDINGS;

				/* apply default credential if necessary */
  if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
    claimant_cred_handle = gss_default_cred;
				/* create output buffer storage as needed */
  req_flags |= ISC_REQ_ALLOCATE_MEMORY;
				/* make output buffer */
  obuf[0].BufferType = SECBUFFER_TOKEN;
  obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;
				/* output buffer descriptor */
  obufs.ulVersion = SECBUFFER_VERSION;
  obufs.cBuffers = 1;
  obufs.pBuffers = obuf;
				/* first time caller? */
  if (*context_handle == GSS_C_NO_CONTEXT) {
				/* yes, set up output context handle */
    PCtxtHandle ctx = (PCtxtHandle) fs_get (sizeof (CtxtHandle));
    major_status = InitializeSecurityContext (claimant_cred_handle,NIL,
					      target_name,req_flags,0,
					      SECURITY_NETWORK_DREP,NIL,0,ctx,
					      &obufs,
					      ret_flags ? ret_flags : &i,
					      &expiry);
    *context_handle = ctx;	/* return updated context */
  }
  else {			/* no, make SSPI buffer from GSSAPI buffer */
    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
    ibuf[0].cbBuffer = input_token->length;
    ibuf[0].pvBuffer = input_token->value;
				/* input buffer descriptor */
    ibufs.ulVersion = SECBUFFER_VERSION;
    ibufs.cBuffers = 1;
    ibufs.pBuffers = ibuf;
    major_status = InitializeSecurityContext (claimant_cred_handle,
					      *context_handle,target_name,
					      req_flags,0,
					      SECURITY_NETWORK_DREP,&ibufs,0,
					      *context_handle,&obufs,
					      ret_flags ? ret_flags : &i,
					      &expiry);
  }
				/* return output */
  output_token->value = obuf[0].pvBuffer;
  output_token->length = obuf[0].cbBuffer;
				/* in case client wanted lifetime returned */
  if (time_rec) *time_rec = expiry.LowPart;
  return major_status;
}
Exemplo n.º 24
0
static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags)
{
  SECURITY_STATUS e;
  ULONG a;
  TimeStamp t;
  SecBuffer ibuf[2],obuf[1];
  SecBufferDesc ibufs,obufs;
  SCHANNEL_CRED tlscred;
  CERT_CONTEXT *cert;
  CERT_CHAIN_PARA chparam;
  CERT_CHAIN_CONTEXT *chain;
  SSL_EXTRA_CERT_CHAIN_POLICY_PARA policy;
  CERT_CHAIN_POLICY_PARA polparam;
  CERT_CHAIN_POLICY_STATUS status;
  char tmp[MAILTMPLEN],certname[256];
  char *reason = NIL;
  ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
    ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY |
      ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR |
	ISC_REQ_MANUAL_CRED_VALIDATION;
  LPSTR usage[] = {
    szOID_PKIX_KP_SERVER_AUTH,
    szOID_SERVER_GATED_CRYPTO,
    szOID_SGC_NETSCAPE
  };
  PWSTR whost = NIL;
  char *buf = (char *) fs_get (ssltsz);
  unsigned long size = 0;
  sslcertificatequery_t scq =
    (sslcertificatequery_t) mail_parameters (NIL,GET_SSLCERTIFICATEQUERY,NIL);
  sslfailure_t sf = (sslfailure_t) mail_parameters (NIL,GET_SSLFAILURE,NIL);
  SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,
					    sizeof (SSLSTREAM));
  stream->tcpstream = tstream;	/* bind TCP stream */
				/* initialize TLS credential */
  memset (&tlscred,0,sizeof (SCHANNEL_CRED));
  tlscred.dwVersion = SCHANNEL_CRED_VERSION;
  tlscred.grbitEnabledProtocols = SP_PROT_TLS1;

				/* acquire credentials */
  if (AcquireCredentialsHandle
      (NIL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NIL,(flags & NET_TLSCLIENT) ?
       &tlscred : NIL,NIL,NIL,&stream->cred,&t)
      != SEC_E_OK) reason = "Acquire credentials handle failed";
  else while (!reason) {	/* negotiate security context */
				/* initialize buffers */
    ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = buf;
    ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NIL;
    obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;
    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
    ibuf[1].BufferType = SECBUFFER_EMPTY;
				/* initialize buffer descriptors */
    ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
    ibufs.cBuffers = 2; obufs.cBuffers = 1;
    ibufs.pBuffers = ibuf; obufs.pBuffers = obuf;
				/* negotiate security */
    e = InitializeSecurityContext
      (&stream->cred,size ? &stream->context : NIL,host,req,0,
       SECURITY_NETWORK_DREP,size? &ibufs:NIL,0,&stream->context,&obufs,&a,&t);
				/* have an output buffer we need to send? */
    if (obuf[0].pvBuffer && obuf[0].cbBuffer) {
      if (!tcp_sout (stream->tcpstream,obuf[0].pvBuffer,obuf[0].cbBuffer))
	reason = "Unexpected TCP output disconnect";
				/* free the buffer */
      FreeContextBuffer (obuf[0].pvBuffer);
    }
    if (!reason) switch (e) {	/* negotiation state */
    case SEC_I_INCOMPLETE_CREDENTIALS:
      break;			/* server wants client auth */
    case SEC_I_CONTINUE_NEEDED:
      if (size) {		/* continue, read any data? */
				/* yes, anything regurgiated back to us? */
	if (ibuf[1].BufferType == SECBUFFER_EXTRA) {
				/* yes, set this as the new data */
	  memmove (buf,buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);
	  size = ibuf[1].cbBuffer;
	  break;
	}
	size = 0;		/* otherwise, read more stuff from server */
      }
    case SEC_E_INCOMPLETE_MESSAGE:
				/* need to read more data from server */
      if (!tcp_getdata (stream->tcpstream))
	reason = "Unexpected TCP input disconnect";
      else {
	memcpy (buf+size,stream->tcpstream->iptr,stream->tcpstream->ictr);
	size += stream->tcpstream->ictr;
				/* empty it from TCP's buffers */
	stream->tcpstream->iptr += stream->tcpstream->ictr;
	stream->tcpstream->ictr = 0;
      }
      break;

    case SEC_E_OK:		/* success, any data to be regurgitated? */
      if (ibuf[1].BufferType == SECBUFFER_EXTRA) {
				/* yes, set this as the new data */
	memmove (stream->tcpstream->iptr = stream->tcpstream->ibuf,
		 buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);
	stream->tcpstream->ictr = ibuf[1].cbBuffer;
      }
      if (!(flags & NET_NOVALIDATECERT)) {
				/* need validation, make wchar of host */
	if (!((size = MultiByteToWideChar (CP_ACP,0,host,-1,NIL,0)) &&
	      (whost = (PWSTR) fs_get (size*sizeof (WCHAR))) &&
	      MultiByteToWideChar (CP_ACP,0,host,-1,whost,size)))
	  fatal ("Can't make wchar of host name!");
				/* get certificate */
	if ((QueryContextAttributes
	     (&stream->context,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&cert) !=
	     SEC_E_OK) || !cert) {
	  reason = "*Unable to get certificate";
	  strcpy (certname,"<no certificate>");
	}
	else {			/* get certificate subject name */
	  CertNameToStr (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
			 &cert->pCertInfo->Subject,CERT_X500_NAME_STR,
			 certname,255);
				/* build certificate chain */
	  memset (&chparam,0,sizeof (chparam));
	  chparam.cbSize = sizeof (chparam);
	  chparam.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	  chparam.RequestedUsage.Usage.rgpszUsageIdentifier = usage;
	  chparam.RequestedUsage.Usage.cUsageIdentifier =
	    sizeof (usage) / sizeof (LPSTR);
	  if (!CertGetCertificateChain
	      (NIL,cert,NIL,cert->hCertStore,&chparam,NIL,NIL,&chain))
	    reason = ssl_analyze_status (GetLastError (),tmp);
	  else {		/* validate certificate chain */
	    memset (&policy,0,sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA));
	    policy.cbStruct = sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA);
	    policy.dwAuthType = AUTHTYPE_SERVER;
	    policy.fdwChecks = NIL;
	    policy.pwszServerName = whost;
	    memset (&polparam,0,sizeof (polparam));
	    polparam.cbSize = sizeof (polparam);
	    polparam.pvExtraPolicyPara = &policy;
	    memset (&status,0,sizeof (status));
	    status.cbSize = sizeof (status);
	    if (!CertVerifyCertificateChainPolicy
		(CERT_CHAIN_POLICY_SSL,chain,&polparam,&status))
	      reason = ssl_analyze_status (GetLastError (),tmp);
	    else if (status.dwError)
	      reason = ssl_analyze_status (status.dwError,tmp);
	    CertFreeCertificateChain (chain);
	  }
	}
	if (whost) fs_give ((void **) &whost);

	if (reason) {		/* got an error? */
				/* application callback */
	  if (scq) reason = (*scq) ((*reason == '*') ? reason + 1 : reason,
				    host,certname) ? NIL : "";
	  else if (*certname) {	/* error message to return via mm_log() */
	    sprintf (buf,"*%.128s: %.255s",
		     (*reason == '*') ? reason + 1 : reason,certname);
	    reason = buf;
	  }
	}
      }
      if (reason ||
	  (reason = ssl_analyze_status
	   (QueryContextAttributes
	    (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes),buf)))
	break;			/* error in certificate or getting sizes */
      fs_give ((void **) &buf);	/* flush temporary buffer */
				/* make maximum-sized buffers */
      stream->bufsize = stream->sizes.cbHeader +
	stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer;
      if (stream->sizes.cbMaximumMessage < SSLBUFLEN)
	fatal ("cbMaximumMessage is less than SSLBUFLEN!");
      else if (stream->sizes.cbMaximumMessage < 16384) {
	sprintf (tmp,"WINDOWS BUG: cbMaximumMessage = %ld, should be 16384",
		 (long) stream->sizes.cbMaximumMessage);
	mm_log (tmp,NIL);
      }
      stream->ibuf = (char *) fs_get (stream->bufsize);
      stream->obuf = (char *) fs_get (stream->bufsize);
      return stream;
    default:
      reason = ssl_analyze_status (e,buf);
    }
  }
  ssl_close (stream);		/* failed to do SSL */
  stream = NIL;			/* no stream returned */
  switch (*reason) {		/* analyze reason */
  case '*':			/* certificate failure */
    ++reason;			/* skip over certificate failure indication */
				/* pass to error callback */
    if (sf) (*sf) (host,reason,flags);
    else {			/* no error callback, build error message */
      sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason);
      mm_log (tmp,ERROR);
    }
  case '\0':			/* user answered no to certificate callback */
    if (flags & NET_TRYSSL)	/* return dummy stream to stop tryssl */
      stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,
				     sizeof (SSLSTREAM));
    break;
  default:			/* non-certificate failure */
    if (flags & NET_TRYSSL);	/* no error output if tryssl */
				/* pass to error callback */
    else if (sf) (*sf) (host,reason,flags);
    else {			/* no error callback, build error message */
      sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason);
      mm_log (tmp,ERROR);
    }
    break;
  }
  fs_give ((void **) &buf);	/* flush temporary buffer */
  return stream;
}
Exemplo n.º 25
0
void SchannelContext::connect() 
{
	ScopedCertContext pCertContext;

	m_state = Connecting;

	// If a user name is specified, then attempt to find a client
	// certificate. Otherwise, just create a NULL credential.
	if (!m_cert_name.empty())
	{
		if (m_my_cert_store == NULL)
		{
			m_my_cert_store = CertOpenSystemStore(0, m_cert_store_name.c_str());
			if (!m_my_cert_store)
			{
/////			printf( "**** Error 0x%x returned by CertOpenSystemStore\n", GetLastError() );
				indicateError();
				return;
			}
		}

		pCertContext = findCertificateInStore( m_my_cert_store, m_cert_name );
		if (pCertContext == NULL)
		{
/////		printf("**** Error 0x%x returned by CertFindCertificateInStore\n", GetLastError());
			indicateError();
			return;
		}
	}

	// We use an empty list for client certificates
	PCCERT_CONTEXT clientCerts[1] = {0};

	SCHANNEL_CRED sc = {0};
	sc.dwVersion = SCHANNEL_CRED_VERSION;

/////SSL3?
	sc.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
	sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;

	if (pCertContext)
	{
		sc.cCreds = 1;
		sc.paCred = pCertContext.GetPointer();
		sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
	}
	else
	{
		sc.cCreds = 0; // Let Crypto API find the appropriate certificate for us
		sc.paCred = clientCerts;
		sc.dwFlags |= SCH_CRED_USE_DEFAULT_CREDS;
	}

	// Swiften performs the server name check for us
	sc.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;

	SECURITY_STATUS status = AcquireCredentialsHandle(
		NULL,
		UNISP_NAME,
		SECPKG_CRED_OUTBOUND,
		NULL,
		&sc,
		NULL,
		NULL,
		m_credHandle.Reset(),
		NULL);
	
	if (status != SEC_E_OK) 
	{
		// We failed to obtain the credentials handle
		indicateError();
		return;
	}

	SecBuffer outBuffers[2];

	// We let Schannel allocate the output buffer for us
	outBuffers[0].pvBuffer   = NULL;
	outBuffers[0].cbBuffer   = 0;
	outBuffers[0].BufferType = SECBUFFER_TOKEN;

	// Contains alert data if an alert is generated
	outBuffers[1].pvBuffer   = NULL;
	outBuffers[1].cbBuffer   = 0;
	outBuffers[1].BufferType = SECBUFFER_ALERT;

	// Make sure the output buffers are freed
	ScopedSecBuffer scopedOutputData(&outBuffers[0]);
	ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]);

	SecBufferDesc outBufferDesc = {0};
	outBufferDesc.cBuffers   = 2;
	outBufferDesc.pBuffers   = outBuffers;
	outBufferDesc.ulVersion  = SECBUFFER_VERSION;

	// Create the initial security context
	status = InitializeSecurityContext(
		m_credHandle,
		NULL,
		NULL,
		m_ctxtFlags,
		0,
		0,
		NULL,
		0,
		m_ctxtHandle.Reset(),
		&outBufferDesc,
		&m_secContext,
		NULL);

	if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) 
	{
		// We failed to initialize the security context
		handleCertError(status);
		indicateError();
		return;
	}

	// Start the handshake
	sendDataOnNetwork(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer);

	if (status == SEC_E_OK) 
	{
		status = validateServerCertificate();
		if (status != SEC_E_OK)
			handleCertError(status);

		m_state = Connected;
		determineStreamSizes();

		onConnected();
	}
}
Exemplo n.º 26
0
static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT io_open_result)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO)
    {
        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
        indicate_error(tls_io_instance);
    }
    else
    {
        SecBuffer init_security_buffers[2];
        ULONG context_attributes;
        SECURITY_STATUS status;
        SCHANNEL_CRED auth_data;

        auth_data.dwVersion = SCHANNEL_CRED_VERSION;
        auth_data.cCreds = 0;
        auth_data.paCred = NULL;
        auth_data.hRootStore = NULL;
        auth_data.cSupportedAlgs = 0;
        auth_data.palgSupportedAlgs = NULL;
        auth_data.grbitEnabledProtocols = 0;
        auth_data.dwMinimumCipherStrength = 0;
        auth_data.dwMaximumCipherStrength = 0;
        auth_data.dwSessionLifespan = 0;
        auth_data.dwFlags = SCH_USE_STRONG_CRYPTO | SCH_CRED_NO_DEFAULT_CREDS;
        auth_data.dwCredFormat = 0;

        status = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
            &auth_data, NULL, NULL, &tls_io_instance->credential_handle, NULL);
        if (status != SEC_E_OK)
        {
            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
            indicate_error(tls_io_instance);
        }
        else
        {
            tls_io_instance->credential_handle_allocated = true;

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

            SecBufferDesc security_buffers_desc;
            security_buffers_desc.cBuffers = 2;
            security_buffers_desc.pBuffers = init_security_buffers;
            security_buffers_desc.ulVersion = SECBUFFER_VERSION;

            status = InitializeSecurityContext(&tls_io_instance->credential_handle,
                NULL, (SEC_CHAR*)tls_io_instance->host_name, ISC_REQ_EXTENDED_ERROR | ISC_REQ_STREAM | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, NULL, 0,
                &tls_io_instance->security_context, &security_buffers_desc,
                &context_attributes, NULL);

            if ((status == SEC_I_COMPLETE_NEEDED) || (status == SEC_I_CONTINUE_NEEDED) || (status == SEC_I_COMPLETE_AND_CONTINUE))
            {
                if (xio_send(tls_io_instance->socket_io, init_security_buffers[0].pvBuffer, init_security_buffers[0].cbBuffer, NULL, NULL) != 0)
                {
                    tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                    indicate_error(tls_io_instance);
                }
                else
                {
                    /* set the needed bytes to 1, to get on the next byte how many we actually need */
                    tls_io_instance->needed_bytes = 1;
                    if (resize_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    else
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT;
                    }
                }
            }
        }
    }
}
Exemplo n.º 27
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;
}
Exemplo n.º 28
0
/*
 * Continue SSPI authentication with next token as needed.
 */
static int
pg_SSPI_continue(PGconn *conn)
{
	SECURITY_STATUS r;
	CtxtHandle	newContext;
	ULONG		contextAttr;
	SecBufferDesc inbuf;
	SecBufferDesc outbuf;
	SecBuffer	OutBuffers[1];
	SecBuffer	InBuffers[1];

	if (conn->sspictx != NULL)
	{
		/*
		 * On runs other than the first we have some data to send. Put this
		 * data in a SecBuffer type structure.
		 */
		inbuf.ulVersion = SECBUFFER_VERSION;
		inbuf.cBuffers = 1;
		inbuf.pBuffers = InBuffers;
		InBuffers[0].pvBuffer = conn->ginbuf.value;
		InBuffers[0].cbBuffer = conn->ginbuf.length;
		InBuffers[0].BufferType = SECBUFFER_TOKEN;
	}

	OutBuffers[0].pvBuffer = NULL;
	OutBuffers[0].BufferType = SECBUFFER_TOKEN;
	OutBuffers[0].cbBuffer = 0;
	outbuf.cBuffers = 1;
	outbuf.pBuffers = OutBuffers;
	outbuf.ulVersion = SECBUFFER_VERSION;

	r = InitializeSecurityContext(conn->sspicred,
								  conn->sspictx,
								  conn->sspitarget,
								  ISC_REQ_ALLOCATE_MEMORY,
								  0,
								  SECURITY_NETWORK_DREP,
								  (conn->sspictx == NULL) ? NULL : &inbuf,
								  0,
								  &newContext,
								  &outbuf,
								  &contextAttr,
								  NULL);

	if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
	{
		pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);

		return STATUS_ERROR;
	}

	if (conn->sspictx == NULL)
	{
		/* On first run, transfer retreived context handle */
		conn->sspictx = malloc(sizeof(CtxtHandle));
		if (conn->sspictx == NULL)
		{
			printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
			return STATUS_ERROR;
		}
		memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
	}
	else
	{
		/*
		 * On subsequent runs when we had data to send, free buffers that
		 * contained this data.
		 */
		free(conn->ginbuf.value);
		conn->ginbuf.value = NULL;
		conn->ginbuf.length = 0;
	}

	/*
	 * If SSPI returned any data to be sent to the server (as it normally
	 * would), send this data as a password packet.
	 */
	if (outbuf.cBuffers > 0)
	{
		if (outbuf.cBuffers != 1)
		{
			/*
			 * This should never happen, at least not for Kerberos
			 * authentication. Keep check in case it shows up with other
			 * authentication methods later.
			 */
			printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
			return STATUS_ERROR;
		}

		/*
		 * If the negotiation is complete, there may be zero bytes to send.
		 * The server is at this point not expecting any more data, so don't
		 * send it.
		 */
		if (outbuf.pBuffers[0].cbBuffer > 0)
		{
			if (pqPacketSend(conn, 'p',
				   outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
			{
				FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
				return STATUS_ERROR;
			}
		}
		FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
	}

	/* Cleanup is handled by the code in freePGconn() */
	return STATUS_OK;
}
Exemplo n.º 29
0
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);
}