Ejemplo n.º 1
0
HANDLE NetlibInitSecurityProvider(const TCHAR* szProvider, const TCHAR* szPrincipal)
{
	HANDLE hSecurity = NULL;

	if (mir_tstrcmpi(szProvider, _T("Basic")) == 0) {
		NtlmHandleType* hNtlm = (NtlmHandleType*)mir_calloc(sizeof(NtlmHandleType));
		hNtlm->szProvider = mir_tstrdup(szProvider);
		SecInvalidateHandle(&hNtlm->hClientContext);
		SecInvalidateHandle(&hNtlm->hClientCredential);
		ntlmCnt++;

		return hNtlm;
	}

	mir_cslock lck(csSec);

	PSecPkgInfo ntlmSecurityPackageInfo;
	bool isGSSAPI = mir_tstrcmpi(szProvider, _T("GSSAPI")) == 0;
	const TCHAR *szProviderC = isGSSAPI ? _T("Kerberos") : szProvider;
	SECURITY_STATUS sc = QuerySecurityPackageInfo((LPTSTR)szProviderC, &ntlmSecurityPackageInfo);
	if (sc == SEC_E_OK) {
		NtlmHandleType* hNtlm;

		hSecurity = hNtlm = (NtlmHandleType*)mir_calloc(sizeof(NtlmHandleType));
		hNtlm->cbMaxToken = ntlmSecurityPackageInfo->cbMaxToken;
		FreeContextBuffer(ntlmSecurityPackageInfo);

		hNtlm->szProvider = mir_tstrdup(szProvider);
		hNtlm->szPrincipal = mir_tstrdup(szPrincipal ? szPrincipal : _T(""));
		SecInvalidateHandle(&hNtlm->hClientContext);
		SecInvalidateHandle(&hNtlm->hClientCredential);
		ntlmCnt++;
	}
	return hSecurity;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
SECURITY_STATUS
WINAPI
EnumerateSecurityPackagesA(
	PULONG pcPackages,
	PSecPkgInfoA* ppPackageInfo
	)
{
    SECURITY_STATUS ret;
    PSecPkgInfoW info = NULL;

    ret = EnumerateSecurityPackagesW(pcPackages, &info);
    if (ret == SEC_E_OK && *pcPackages && info)
    {
        /* *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
        if (*pcPackages && !*ppPackageInfo)
        {
            *pcPackages = 0;
            ret = SEC_E_INSUFFICIENT_MEMORY;
        } */
        FreeContextBuffer(info);
    }
    *ppPackageInfo = NULL;
	UNIMPLEMENTED;

    return ret;
}
int TestEnumerateSecurityPackages(int argc, char* argv[])
{
	int index;
	ULONG cPackages;
	SECURITY_STATUS status;
	SecPkgInfo* pPackageInfo;

	sspi_GlobalInit();

	status = EnumerateSecurityPackages(&cPackages, &pPackageInfo);

	if (status != SEC_E_OK)
	{
		sspi_GlobalFinish();
		return -1;	
	}

	_tprintf(_T("\nEnumerateSecurityPackages (%")_T(PRIu32)_T("):\n"), cPackages);

	for (index = 0; index < (int) cPackages; index++)
	{
		_tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo[index].Name, pPackageInfo[index].Comment);
	}

	FreeContextBuffer(pPackageInfo);
	sspi_GlobalFinish();

	return 0;
}
Ejemplo n.º 5
0
static apr_status_t
cleanup_sec_buffer(void *data)
{
    FreeContextBuffer(data);

    return APR_SUCCESS;
}
Ejemplo n.º 6
0
BOOLEAN
SrvIsKerberosAvailable(
    VOID
    )
/*++

Routine Description:

    Checks whether Kerberos is one of the supported security packages.

Arguments:


Return Value:

    TRUE if Kerberos is available, FALSE if otherwise or error.

--*/

{
    NTSTATUS Status;
    ULONG PackageCount, Index;
    PSecPkgInfoW Packages;
    BOOLEAN FoundKerberos = FALSE;

    //
    // Get the list of packages from the security driver
    //

    Status = EnumerateSecurityPackages(
                &PackageCount,
                &Packages
                );
    if (!NT_SUCCESS(Status)) {
        return(FALSE);
    }

    //
    // Loop through the list looking for Kerberos
    //

    for (Index = 0; Index < PackageCount ; Index++ ) {
        if (!_wcsicmp(Packages[Index].Name, MICROSOFT_KERBEROS_NAME_W)) {
            FoundKerberos = TRUE;
            break;
        }
    }

    FreeContextBuffer(Packages);
    return(FoundKerberos);

}
Ejemplo n.º 7
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;
	}
Ejemplo n.º 8
0
static int destroy(const struct plugin_interface *plugin)
{
	protocol_interface *protocol = (protocol_interface*)plugin;
	free(protocol->auth_username);
	free(protocol->auth_password);
	free(protocol->auth_repository);

	free(g_sslBufferIn);
	free(g_sslBufferOut);

	FreeContextBuffer( secPackInfo );
	return 0;
}
Ejemplo n.º 9
0
static void test_kerberos(void)
{
    SecPkgInfoA *info;
    TimeStamp ttl;
    CredHandle cred;
    SECURITY_STATUS status;

    SEC_CHAR provider[] = {'K','e','r','b','e','r','o','s',0};

    static const ULONG expected_flags =
          SECPKG_FLAG_INTEGRITY
        | SECPKG_FLAG_PRIVACY
        | SECPKG_FLAG_TOKEN_ONLY
        | SECPKG_FLAG_DATAGRAM
        | SECPKG_FLAG_CONNECTION
        | SECPKG_FLAG_MULTI_REQUIRED
        | SECPKG_FLAG_EXTENDED_ERROR
        | SECPKG_FLAG_IMPERSONATION
        | SECPKG_FLAG_ACCEPT_WIN32_NAME
        | SECPKG_FLAG_NEGOTIABLE
        | SECPKG_FLAG_GSS_COMPATIBLE
        | SECPKG_FLAG_LOGON
        | SECPKG_FLAG_MUTUAL_AUTH
        | SECPKG_FLAG_DELEGATION
        | SECPKG_FLAG_READONLY_WITH_CHECKSUM;
    static const ULONG optional_mask =
          SECPKG_FLAG_RESTRICTED_TOKENS
        | SECPKG_FLAG_APPCONTAINER_CHECKS;

    status = QuerySecurityPackageInfoA(provider, &info);
    ok(status == SEC_E_OK, "Kerberos package not installed, skipping test\n");
    if(status != SEC_E_OK)
        return;

    ok( (info->fCapabilities & ~optional_mask) == expected_flags, "got %08x, expected %08x\n", info->fCapabilities, expected_flags );
    ok( info->wVersion == 1, "got %u\n", info->wVersion );
    ok( info->wRPCID == RPC_C_AUTHN_GSS_KERBEROS, "got %u\n", info->wRPCID );
    ok( info->cbMaxToken >= 12000, "got %u\n", info->cbMaxToken );
    ok( !lstrcmpA( info->Name, "Kerberos" ), "got %s\n", info->Name );
    ok( !lstrcmpA( info->Comment, "Microsoft Kerberos V1.0" ), "got %s\n", info->Comment );
    FreeContextBuffer( info );

    status = AcquireCredentialsHandleA( NULL, provider, SECPKG_CRED_OUTBOUND, NULL,
                                        NULL, NULL, NULL, &cred, &ttl );
    todo_wine ok( status == SEC_E_OK, "AcquireCredentialsHandleA returned %08x\n", status );
    if(status == SEC_E_OK)
        FreeCredentialHandle( &cred );
}
Ejemplo n.º 10
0
void RPC_ENTRY kull_m_rpc_drsr_RpcSecurityCallback(void *Context)
{
	RPC_STATUS rpcStatus;
	SECURITY_STATUS secStatus;
	PCtxtHandle data = NULL;

	rpcStatus = I_RpcBindingInqSecurityContext(Context, (LPVOID *) &data);
	if(rpcStatus == RPC_S_OK)
	{
		if(kull_m_rpc_drsr_g_sKey.SessionKey)
		{
			FreeContextBuffer(kull_m_rpc_drsr_g_sKey.SessionKey);
			kull_m_rpc_drsr_g_sKey.SessionKeyLength = 0;
			kull_m_rpc_drsr_g_sKey.SessionKey = NULL;
		}
		secStatus = QueryContextAttributes(data, SECPKG_ATTR_SESSION_KEY, (LPVOID) &kull_m_rpc_drsr_g_sKey);
		if(secStatus != SEC_E_OK)
			PRINT_ERROR(L"QueryContextAttributes %08x\n", secStatus);
	}
	else PRINT_ERROR(L"I_RpcBindingInqSecurityContext %08x\n", rpcStatus);
}
Ejemplo n.º 11
0
BOOL AcquireCreds()
{
    SECURITY_STATUS   ss;
    TimeStamp         Lifetime;
    PSecPkgInfo       pkgInfo;

    //  Set the default package to negotiate.
    tstrcpy_s(g_lpPackageName, 1024, TEXT("Negotiate"));

    // Initialize the security package.
    ss = QuerySecurityPackageInfo(g_lpPackageName, &pkgInfo);

    // get the max token size
    g_cbMaxMessage = pkgInfo->cbMaxToken;
    FreeContextBuffer(pkgInfo);

    // set the max token sizes
    g_pInBuf = (PBYTE)malloc(g_cbMaxMessage);
    g_pOutBuf = (PBYTE)malloc(g_cbMaxMessage);

    // get the security handles
    ss = AcquireCredentialsHandle(
        NULL,
        g_lpPackageName,
        SECPKG_CRED_INBOUND,
        NULL,
        NULL,
        NULL,
        NULL,
        &hcred,
        &Lifetime);

    if (!SEC_SUCCESS(ss))
    {
        fprintf(stderr, "AcquireCreds failed: 0x%08x\n", ss);
        return(FALSE);
    }

    return (TRUE);
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
void test_EnumerateSecurityPackages(void)
{
	uint32 cPackages;
	SECURITY_STATUS status;
	SecPkgInfo* pPackageInfo;

	status = EnumerateSecurityPackages(&cPackages, &pPackageInfo);

	if (status == SEC_E_OK)
	{
		int index;

		printf("\nEnumerateSecurityPackages (%d):\n", cPackages);

		for (index = 0; index < cPackages; index++)
		{
			printf("\"%s\", \"%s\"\n",
					pPackageInfo[index].Name, pPackageInfo[index].Comment);
		}
	}

	FreeContextBuffer(pPackageInfo);
}
Ejemplo n.º 15
0
/* Copies the data from a SecBufferDesc to dstBuf */
static sqInt sqCopyDescToken(sqSSL *ssl, SecBufferDesc sbd, char *dstBuf, sqInt dstLen) {
	unsigned int i;
	int result = 0;

	if(ssl->loglevel) printf("sqCopyDescToken: \n");
	for(i = 0; i < sbd.cBuffers; i++) {
		SecBuffer *buf = sbd.pBuffers + i;
		if(ssl->loglevel) printf("\t type=%d, size=%d\n", buf->BufferType, buf->cbBuffer);
		if(buf->BufferType == SECBUFFER_TOKEN) {
			int count = buf->cbBuffer;
			if(count > dstLen) return SQSSL_BUFFER_TOO_SMALL;
			memcpy(dstBuf, buf->pvBuffer, count);
			result += count;
			dstBuf += count;
			dstLen -= count;
			FreeContextBuffer(buf->pvBuffer);
		}
		if(buf->BufferType == SECBUFFER_EXTRA) {
			/* XXXX: Preserve contents for the next round */
			if(ssl->loglevel) printf("sqCopyDescToken: Unexpectedly encountered SECBUFFER_EXTRA\n");
		}
	}
	return result;
}
Ejemplo n.º 16
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);
}
Ejemplo n.º 17
0
static
DWORD
ServerEstablishContext(
    IN INT nSocket,
    IN CredHandle *pServerCreds,
    OUT CtxtHandle *pContext,
    IN ULONG AscFlags
    )
{
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwLoopError = ERROR_SUCCESS;
    ULONG nRetFlags = 0;
    SecBufferDesc InputDesc;
    SecBufferDesc OutputDesc;
    SecBuffer SendTokenBuffer;
    SecBuffer RecvTokenBuffer;
    TimeStamp Expiry;
    PCtxtHandle pContextHandle = NULL;
    INT nContextAcquired = 0;

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

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

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

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

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

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

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

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

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

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

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

        nContextAcquired = 1;

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

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

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

    } while (dwLoopError == SEC_I_CONTINUE_NEEDED);

finish:
    return dwError;
error:
    if (RecvTokenBuffer.pvBuffer)
    {
        free(RecvTokenBuffer.pvBuffer);
        RecvTokenBuffer.pvBuffer = NULL;
    }
    if (SendTokenBuffer.cbBuffer)
    {
        FreeContextBuffer(SendTokenBuffer.pvBuffer);
        SendTokenBuffer.pvBuffer = NULL;
        SendTokenBuffer.cbBuffer = 0;
    }
    if (nContextAcquired)
    {
        DeleteSecurityContext(pContext);
    }
    goto finish;
}
Ejemplo n.º 18
0
int credssp_server_authenticate(rdpCredssp* credssp)
{
	uint32 cbMaxToken;
	uint32 fContextReq;
	uint32 pfContextAttr;
	SECURITY_STATUS status;
	CredHandle credentials;
	TimeStamp expiration;
	SecPkgInfo* pPackageInfo;
	PSecBuffer p_buffer;
	SecBuffer input_buffer;
	SecBuffer output_buffer;
	SecBufferDesc input_buffer_desc;
	SecBufferDesc output_buffer_desc;
	boolean have_context;
	boolean have_input_buffer;
	boolean have_pub_key_auth;

	sspi_GlobalInit();

	if (credssp_ntlm_server_init(credssp) == 0)
		return 0;

	credssp->table = InitSecurityInterface();

	status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo);

	if (status != SEC_E_OK)
	{
		printf("QuerySecurityPackageInfo status: 0x%08X\n", status);
		return 0;
	}

	cbMaxToken = pPackageInfo->cbMaxToken;

	status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
			SECPKG_CRED_INBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration);

	if (status != SEC_E_OK)
	{
		printf("AcquireCredentialsHandle status: 0x%08X\n", status);
		return 0;
	}

	have_context = false;
	have_input_buffer = false;
	have_pub_key_auth = false;
	memset(&input_buffer, 0, sizeof(SecBuffer));
	memset(&output_buffer, 0, sizeof(SecBuffer));
	memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes));

	fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
			ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;

	while (true)
	{
		input_buffer_desc.ulVersion = SECBUFFER_VERSION;
		input_buffer_desc.cBuffers = 1;
		input_buffer_desc.pBuffers = &input_buffer;
		input_buffer.BufferType = SECBUFFER_TOKEN;

		/* receive authentication token */

		input_buffer_desc.ulVersion = SECBUFFER_VERSION;
		input_buffer_desc.cBuffers = 1;
		input_buffer_desc.pBuffers = &input_buffer;
		input_buffer.BufferType = SECBUFFER_TOKEN;

		if (credssp_recv(credssp) < 0)
			return -1;

#ifdef WITH_DEBUG_CREDSSP
		printf("Receiving Authentication Token\n");
		credssp_buffer_print(credssp);
#endif

		p_buffer = &input_buffer_desc.pBuffers[0];
		p_buffer->pvBuffer = credssp->negoToken.pvBuffer;
		p_buffer->cbBuffer = credssp->negoToken.cbBuffer;

		output_buffer_desc.ulVersion = SECBUFFER_VERSION;
		output_buffer_desc.cBuffers = 1;
		output_buffer_desc.pBuffers = &output_buffer;
		output_buffer.BufferType = SECBUFFER_TOKEN;
		output_buffer.cbBuffer = cbMaxToken;
		output_buffer.pvBuffer = xmalloc(output_buffer.cbBuffer);

		status = credssp->table->AcceptSecurityContext(&credentials,
			have_context? &credssp->context: NULL,
			&input_buffer_desc, 0, SECURITY_NATIVE_DREP, &credssp->context,
			&output_buffer_desc, &pfContextAttr, &expiration);

		if (input_buffer.pvBuffer != NULL)
		{
			xfree(input_buffer.pvBuffer);
			input_buffer.pvBuffer = NULL;
		}

		p_buffer = &output_buffer_desc.pBuffers[0];
		credssp->negoToken.pvBuffer = p_buffer->pvBuffer;
		credssp->negoToken.cbBuffer = p_buffer->cbBuffer;

		if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
		{
			if (credssp->table->CompleteAuthToken != NULL)
				credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc);

			have_pub_key_auth = true;

			sspi_SecBufferFree(&credssp->negoToken);
			credssp->negoToken.pvBuffer = NULL;
			credssp->negoToken.cbBuffer = 0;

			if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK)
			{
				printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n");
				return 0;
			}

			if (have_pub_key_auth)
			{
				uint8* p;
				SecBuffer Buffers[2];
				SecBufferDesc Message;

				Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */
				Buffers[1].BufferType = SECBUFFER_TOKEN; /* Signature */

				Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer;
				Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer);
				memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer);

				Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature;
				Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer);

				Message.cBuffers = 2;
				Message.ulVersion = SECBUFFER_VERSION;
				Message.pBuffers = (PSecBuffer) &Buffers;

				p = (uint8*) Buffers[0].pvBuffer;
				p[0]++; /* Public Key +1 */

				sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer);

				credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0);

				p = (uint8*) credssp->pubKeyAuth.pvBuffer;
				memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */
				memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */
			}

			if (status == SEC_I_COMPLETE_NEEDED)
				status = SEC_E_OK;
			else if (status == SEC_I_COMPLETE_AND_CONTINUE)
				status = SEC_I_CONTINUE_NEEDED;
		}

		/* send authentication token */

#ifdef WITH_DEBUG_CREDSSP
		printf("Sending Authentication Token\n");
		credssp_buffer_print(credssp);
#endif

		credssp_send(credssp);
		credssp_buffer_free(credssp);

		if (status != SEC_I_CONTINUE_NEEDED)
			break;

		have_context = true;
	}

	/* Receive encrypted credentials */

	if (credssp_recv(credssp) < 0)
		return -1;

	if (status != SEC_E_OK)
	{
		printf("AcceptSecurityContext status: 0x%08X\n", status);
		return 0;
	}

	status = credssp->table->ImpersonateSecurityContext(&credssp->context);

	if (status != SEC_E_OK)
	{
		printf("ImpersonateSecurityContext status: 0x%08X\n", status);
		return 0;
	}
	else
	{
		status = credssp->table->RevertSecurityContext(&credssp->context);

		if (status != SEC_E_OK)
		{
			printf("RevertSecurityContext status: 0x%08X\n", status);
			return 0;
		}
	}

	FreeContextBuffer(pPackageInfo);

	return 1;
}
Ejemplo n.º 19
0
int sserver_auth_protocol_connect(const struct protocol_interface *protocol, const char *auth_string)
{
	CScramble scramble;
	char *tmp;
	int certonly;
	char *client_version = NULL;
	char keyfile[256];
	const char *hostname = NULL;

    if (!strcmp (auth_string, "BEGIN SSL VERIFICATION REQUEST"))
		sserver_protocol_interface.verify_only = 1;
    else if (!strcmp (auth_string, "BEGIN SSL AUTH REQUEST"))
		sserver_protocol_interface.verify_only = 0;
	else
		return CVSPROTO_NOTME;

	write(current_server()->out_fd,SSERVER_INIT_STRING,sizeof(SSERVER_INIT_STRING)-1);

	if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CertificatesOnly",keyfile,sizeof(keyfile)))
		certonly = atoi(keyfile);
	if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","ServerDnsName",keyfile,sizeof(keyfile)))
		hostname = keyfile;

	if(!ServerAuthenticate(hostname))
		return CVSPROTO_AUTHFAIL;

	QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes);

	g_sslBufferInPos=g_sslBufferOutPos=0;
	g_sslBufferInLen=g_sslBufferOutLen=0;

    set_encrypted_channel(1); /* Error must go through us now */

	PCERT_CONTEXT sc;
	PCCERT_CHAIN_CONTEXT pcc;
	CERT_SIMPLE_CHAIN  *psc;
	CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) };
	DWORD trust,rc;
	BOOL cert = FALSE;
	
	rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc);
	if(rc && rc!=SEC_E_NO_CREDENTIALS)
		server_error(1,"Couldn't get client certificate");

	if(rc!=SEC_E_NO_CREDENTIALS) /* The client doesn't have to send us a cert. as cvs uses passwords normally */
	{
		if(!CertGetCertificateChain(NULL, sc, NULL, NULL, &para, 0, NULL, &pcc))
			server_error(1,"Couldn't get client certificate chain");

		psc = pcc->rgpChain[0];
		trust = psc->TrustStatus.dwErrorStatus;
	 
		if (trust)
		{
			if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT))
				server_error(1,"Client sent self signed certificate");
			else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID))
				server_error(1,"Client certificate expired");
			else
				server_error(1,"Client certificate verification failed - %08x",trust);
		}

		CertFreeCertificateChain(pcc);
		FreeContextBuffer(sc);

		cert = TRUE;
	}
 
    /* Get the three important pieces of information in order. */
    /* See above comment about error handling.  */

	/* get version, if sent.  1.0 clients didn't have this handshake so we have to handle that. */
	server_getline (protocol, &client_version, MAX_PATH);
	if(strncmp(client_version,"SSERVER-CLIENT ",15))
	{
		sserver_protocol_interface.auth_repository = client_version;
		client_version = NULL;
	}
	else
    	server_getline (protocol, &sserver_protocol_interface.auth_repository, MAX_PATH);
    server_getline (protocol, &sserver_protocol_interface.auth_username, MAX_PATH);
	server_getline (protocol, &sserver_protocol_interface.auth_password, MAX_PATH);

	if(client_version) free(client_version);
	client_version = NULL;

    /* ... and make sure the protocol ends on the right foot. */
    /* See above comment about error handling.  */
    server_getline(protocol, &tmp, MAX_PATH);
    if (strcmp (tmp,
		sserver_protocol_interface.verify_only ?
		"END SSL VERIFICATION REQUEST" : "END SSL AUTH REQUEST")
	!= 0)
    {
		server_printf ("bad auth protocol end: %s\n", tmp);
		free(tmp);
		return CVSPROTO_FAIL;
    }

	strcpy(sserver_protocol_interface.auth_password, scramble.Unscramble(sserver_protocol_interface.auth_password));

	free(tmp);

	switch(certonly)
	{
	case 0:
		break;
	case 1:
		if(!cert)
		{
			server_error(0,"E Login requires a valid client certificate.\n");
			return CVSPROTO_AUTHFAIL;
		}
		free(sserver_protocol_interface.auth_password);
		sserver_protocol_interface.auth_password = NULL;
		break;
	case 2:
		if(!cert)
		{
			server_error(0,"E Login requires a valid client certificate.\n");
			return CVSPROTO_AUTHFAIL;
		}
		break;
	};

	return CVSPROTO_SUCCESS;
}
Ejemplo n.º 20
0
int sserver_connect(const struct protocol_interface *protocol, int verify_only)
{
	char crypt_password[64];
	char server_version[128];
	char tmp_keyname[256];
	const char *begin_request = "BEGIN SSL AUTH REQUEST";
	const char *end_request = "END SSL AUTH REQUEST";
	const char *username = NULL;
	const char *cert = current_server()->current_root->optional_3;
	int l;
	int sserver_version = 0;
	int strict = 0;
	CScramble scramble;
	bool send_client_version = false;

	if(current_server()->current_root->optional_1)
	{
	  sserver_version = atoi(current_server()->current_root->optional_1);
	  if(sserver_version != 0 && sserver_version != 1)
	  {
	    server_error(0,"version must be one of:");
	    server_error(0,"0 - All CVSNT-type servers");
	    server_error(0,"1 - Unix server using Corey Minards' sserver patches");
	    server_error(1,"Please specify a valid value");
	  }
	}

	if(!CGlobalSettings::GetUserValue("cvsnt","sserver","StrictChecking",server_version,sizeof(server_version)))
	{
	  strict = atoi(server_version);
	}

	if(!cert && !CGlobalSettings::GetUserValue("cvsnt","sserver","ClientCert",tmp_keyname,sizeof(tmp_keyname)))
	{
	  cert = tmp_keyname;
	}

	if(current_server()->current_root->optional_2)
		strict = atoi(current_server()->current_root->optional_2);

	if(sserver_version == 1) /* Old sserver */
	{
	  begin_request = verify_only?"BEGIN SSL VERIFICATION REQUEST":"BEGIN SSL REQUEST";
	  end_request = verify_only?"END SSL VERIFICATION REQUEST":"END SSL REQUEST";
	}
	else if(verify_only)
	{
		begin_request = "BEGIN SSL VERIFICATION REQUEST";
		end_request = "END SSL VERIFICATION REQUEST";
	}
	username = get_username(current_server()->current_root);

	if(!username || !current_server()->current_root->hostname || !current_server()->current_root->directory)
		return CVSPROTO_BADPARMS;

	if(tcp_connect(current_server()->current_root))
		return CVSPROTO_FAIL;
	if(current_server()->current_root->password)
		strncpy(crypt_password,scramble.Scramble(current_server()->current_root->password),sizeof(crypt_password));
	else
	{
		if(sserver_get_user_password(username,current_server()->current_root->hostname,current_server()->current_root->port,current_server()->current_root->directory,crypt_password,sizeof(crypt_password)))
		{
			/* Using null password - trace something out here */
			server_error(0,"Using an empty password; you may need to do 'cvs login' with a real password\n");
			strncpy(crypt_password,scramble.Scramble(""),sizeof(crypt_password));
		}
	}

	if(sserver_version == 0) /* Pre-CVSNT had no version check */
	{
	  if(tcp_printf("%s\n",begin_request)<0)
		return CVSPROTO_FAIL;
	  for(;;)
	  {
		*server_version='\0';
		if((l=tcp_readline(server_version,sizeof(server_version))<0))
			return CVSPROTO_FAIL;
		if(*server_version)
			break;
#ifdef _WIN32
		Sleep(10);
#else
		usleep(10);
#endif
	  }
	  if(strncmp(server_version,"SSERVER ",8))
	  {
	  	  server_error(0,"%s\n",server_version);
		  return CVSPROTO_FAIL;
	  }
	  if(strncmp(server_version+8,"1.0 ",4))
		  send_client_version = true;
	}

	if(!ClientAuthenticate(cert,current_server()->current_root->hostname))
		return CVSPROTO_AUTHFAIL;

	QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes);

	PCERT_CONTEXT sc;
	PCCERT_CHAIN_CONTEXT pcc;
	CERT_SIMPLE_CHAIN  *psc;
	CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) };
	DWORD trust,rc;
	
	rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc);
	if(rc)
		server_error(1,"Couldn't get server certificate");

	if(!CertGetCertificateChain(NULL, sc, NULL, NULL, &para, 0, NULL, &pcc))
		server_error(1,"Couldn't get server certificate chain");

    psc = pcc->rgpChain[0];
	trust = psc->TrustStatus.dwErrorStatus;
 
    if (trust)
    {
        if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT))
            ; // Seld signed
        else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID))
			server_error(1,"Server certificate expired");
        else
			server_error(1,"Server certificate verification failed - %08x",trust);
    }

	if(strict)
	{
		char certname[256];

		CertGetNameString(sc, CERT_NAME_DNS_TYPE, 0, NULL, certname, sizeof(certname));
		  if(strcasecmp(certname,current_server()->current_root->hostname))
			server_error(1, "Certificate CommonName '%s' does not match server name '%s'\n",certname,current_server()->current_root->hostname);
	}

	CertFreeCertificateChain(pcc);
	FreeContextBuffer(sc);
 
	g_sslBufferInPos=g_sslBufferOutPos=0;
	g_sslBufferInLen=g_sslBufferOutLen=0;

	if(sserver_version == 1)
	{
	  if(sserver_printf("%s\n",begin_request)<0)
		return CVSPROTO_FAIL;
	}

    // For server versions 1.1+ send CLIENT_VERSION_STRING
	if(send_client_version && sserver_printf(SSERVER_CLIENT_VERSION_STRING)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n%s\n",current_server()->current_root->directory,username)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n",crypt_password)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n",end_request)<0)
		return CVSPROTO_FAIL;
	return CVSPROTO_SUCCESS;
}
Ejemplo n.º 21
0
int credssp_client_authenticate(rdpCredssp* credssp)
{
	uint32 cbMaxLen;
	uint32 fContextReq;
	uint32 pfContextAttr;
	SECURITY_STATUS status;
	CRED_HANDLE credentials;
	SEC_TIMESTAMP expiration;
	SEC_PKG_INFO* pPackageInfo;
	SEC_AUTH_IDENTITY identity;
	SEC_BUFFER* p_sec_buffer;
	SEC_BUFFER input_sec_buffer;
	SEC_BUFFER output_sec_buffer;
	SEC_BUFFER_DESC input_sec_buffer_desc;
	SEC_BUFFER_DESC output_sec_buffer_desc;
	boolean have_context;
	boolean have_input_buffer;
	boolean have_pub_key_auth;
	rdpSettings* settings = credssp->settings;

	sspi_GlobalInit();

	if (credssp_ntlmssp_client_init(credssp) == 0)
		return 0;

	credssp->table = InitSecurityInterface();

	status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo);

	if (status != SEC_E_OK)
	{
		printf("QuerySecurityPackageInfo status: 0x%08X\n", status);
		return 0;
	}

	cbMaxLen = pPackageInfo->cbMaxToken;

	identity.User = (uint16*) xstrdup(settings->username);
	identity.UserLength = strlen(settings->username);

	if (settings->domain)
	{
		identity.Domain = (uint16*) xstrdup(settings->domain);
		identity.DomainLength = strlen(settings->domain);
	}
	else
	{
		identity.Domain = (uint16*) NULL;
		identity.DomainLength = 0;
	}

	identity.Password = (uint16*) xstrdup(settings->password);
	identity.PasswordLength = strlen(settings->password);

	identity.Flags = SEC_AUTH_IDENTITY_ANSI;

	status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
			SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration);

	if (status != SEC_E_OK)
	{
		printf("AcquireCredentialsHandle status: 0x%08X\n", status);
		return 0;
	}

	have_context = false;
	have_input_buffer = false;
	have_pub_key_auth = false;
	memset(&input_sec_buffer, 0, sizeof(SEC_BUFFER));
	memset(&output_sec_buffer, 0, sizeof(SEC_BUFFER));
	memset(&credssp->ContextSizes, 0, sizeof(SEC_PKG_CONTEXT_SIZES));

	fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
			ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;

	while (true)
	{
		output_sec_buffer_desc.ulVersion = SECBUFFER_VERSION;
		output_sec_buffer_desc.cBuffers = 1;
		output_sec_buffer_desc.pBuffers = &output_sec_buffer;
		output_sec_buffer.BufferType = SECBUFFER_TOKEN;
		output_sec_buffer.cbBuffer = cbMaxLen;
		output_sec_buffer.pvBuffer = xmalloc(output_sec_buffer.cbBuffer);

		status = credssp->table->InitializeSecurityContext(&credentials,
				(have_context) ? &credssp->context : NULL,
				NULL, fContextReq, 0, SECURITY_NATIVE_DREP,
				(have_input_buffer) ? &input_sec_buffer_desc : NULL,
				0, &credssp->context, &output_sec_buffer_desc, &pfContextAttr, &expiration);

		if (input_sec_buffer.pvBuffer != NULL)
		{
			xfree(input_sec_buffer.pvBuffer);
			input_sec_buffer.pvBuffer = NULL;
		}

		if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED))
		{
			if (credssp->table->CompleteAuthToken != NULL)
				credssp->table->CompleteAuthToken(&credssp->context, &output_sec_buffer_desc);

			have_pub_key_auth = true;

			if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK)
			{
				printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n");
				return 0;
			}

			if (have_pub_key_auth)
			{
				uint8* p;
				SEC_BUFFER Buffers[2];
				SEC_BUFFER_DESC Message;

				Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */
				Buffers[1].BufferType = SECBUFFER_PADDING; /* Signature */

				Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer;
				Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer);
				memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer);

				Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature;
				Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer);

				Message.cBuffers = 2;
				Message.ulVersion = SECBUFFER_VERSION;
				Message.pBuffers = (SEC_BUFFER*) &Buffers;

				sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer);

				credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0);

				p = (uint8*) credssp->pubKeyAuth.pvBuffer;
				memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */
				memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */
			}

			if (status == SEC_I_COMPLETE_NEEDED)
				status = SEC_E_OK;
			else if (status == SEC_I_COMPLETE_AND_CONTINUE)
				status = SEC_I_CONTINUE_NEEDED;
		}

		/* send authentication token to server */

		if (output_sec_buffer.cbBuffer > 0)
		{
			p_sec_buffer = &output_sec_buffer_desc.pBuffers[0];

			credssp->negoToken.pvBuffer = p_sec_buffer->pvBuffer;
			credssp->negoToken.cbBuffer = p_sec_buffer->cbBuffer;

#ifdef WITH_DEBUG_CREDSSP
			printf("Sending Authentication Token\n");
			freerdp_hexdump(credssp->negoToken.data, credssp->negoToken.length);
#endif

			credssp_send(credssp, &credssp->negoToken, NULL,
					(have_pub_key_auth) ? &credssp->pubKeyAuth : NULL);

			if (have_pub_key_auth)
			{
				have_pub_key_auth = false;
				sspi_SecBufferFree(&credssp->pubKeyAuth);
			}

			xfree(output_sec_buffer.pvBuffer);
			output_sec_buffer.pvBuffer = NULL;
		}

		if (status != SEC_I_CONTINUE_NEEDED)
			break;

		/* receive server response and place in input buffer */

		input_sec_buffer_desc.ulVersion = SECBUFFER_VERSION;
		input_sec_buffer_desc.cBuffers = 1;
		input_sec_buffer_desc.pBuffers = &input_sec_buffer;
		input_sec_buffer.BufferType = SECBUFFER_TOKEN;

		if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0)
			return -1;

#ifdef WITH_DEBUG_CREDSSP
		printf("Receiving Authentication Token\n");
		freerdp_hexdump(credssp->negoToken.data, credssp->negoToken.length);
#endif

		p_sec_buffer = &input_sec_buffer_desc.pBuffers[0];
		p_sec_buffer->pvBuffer = credssp->negoToken.pvBuffer;
		p_sec_buffer->cbBuffer = credssp->negoToken.cbBuffer;

		have_input_buffer = true;
		have_context = true;
	}

	/* Encrypted Public Key +1 */
	if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0)
		return -1;

	/* Verify Server Public Key Echo */

	status = credssp_verify_public_key_echo(credssp);

	if (status != SEC_E_OK)
		return 0;

	/* Send encrypted credentials */

	status = credssp_encrypt_ts_credentials(credssp);

	if (status != SEC_E_OK)
		return 0;

	credssp_send(credssp, NULL, &credssp->authInfo, NULL);

	/* Free resources */

	//sspi_SecBufferFree(&credssp->negoToken);
	sspi_SecBufferFree(&credssp->authInfo);

	FreeCredentialsHandle(&credentials);
	FreeContextBuffer(pPackageInfo);

	return 1;
}
Ejemplo n.º 22
0
int
_mongoc_sspi_auth_sspi_client_step (mongoc_sspi_client_state_t *state,
                                    SEC_CHAR *challenge)
{
   SecBufferDesc inbuf;
   SecBuffer inBufs[1];
   SecBufferDesc outbuf;
   SecBuffer outBufs[1];
   ULONG ignored;
   SECURITY_STATUS status = MONGOC_SSPI_AUTH_GSS_CONTINUE;
   DWORD len;

   if (state->response != NULL) {
      free (state->response);
      state->response = NULL;
   }

   inbuf.ulVersion = SECBUFFER_VERSION;
   inbuf.cBuffers = 1;
   inbuf.pBuffers = inBufs;
   inBufs[0].pvBuffer = NULL;
   inBufs[0].cbBuffer = 0;
   inBufs[0].BufferType = SECBUFFER_TOKEN;
   if (state->haveCtx) {
      inBufs[0].pvBuffer = _mongoc_sspi_base64_decode (challenge, &len);
      if (!inBufs[0].pvBuffer) {
         return MONGOC_SSPI_AUTH_GSS_ERROR;
      }
      inBufs[0].cbBuffer = len;
   }

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

   status = InitializeSecurityContextW (/* CredHandle */
                                        &state->cred,
                                        /* CtxtHandle (NULL on first call) */
                                        state->haveCtx ? &state->ctx : NULL,
                                        /* Service Principal Name */
                                        state->spn,
                                        /* Flags */
                                        ISC_REQ_ALLOCATE_MEMORY | state->flags,
                                        /* Always 0 */
                                        0,
                                        /* Target data representation */
                                        SECURITY_NETWORK_DREP,
                                        /* Challenge (NULL on first call) */
                                        state->haveCtx ? &inbuf : NULL,
                                        /* Always 0 */
                                        0,
                                        /* CtxtHandle (Set on first call) */
                                        &state->ctx,
                                        /* Output */
                                        &outbuf,
                                        /* Context attributes */
                                        &ignored,
                                        /* Expiry (We don't use this) */
                                        NULL);
   if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
      _mongoc_sspi_set_gsserror (status, "InitializeSecurityContext");
      status = MONGOC_SSPI_AUTH_GSS_ERROR;
      goto done;
   }
   state->haveCtx = 1;
   if (outBufs[0].cbBuffer) {
      state->response =
         _mongoc_sspi_base64_encode (outBufs[0].pvBuffer, outBufs[0].cbBuffer);
      if (!state->response) {
         status = MONGOC_SSPI_AUTH_GSS_ERROR;
         goto done;
      }
   }
   if (status == SEC_E_OK) {
      /* Get authenticated username. */
      SecPkgContext_NamesW names;
      status = QueryContextAttributesW (&state->ctx, SECPKG_ATTR_NAMES, &names);
      if (status != SEC_E_OK) {
         _mongoc_sspi_set_gsserror (status, "QueryContextAttributesW");
         status = MONGOC_SSPI_AUTH_GSS_ERROR;
         goto done;
      }
      state->username = _mongoc_sspi_wide_to_utf8 (names.sUserName);
      if (state->username == NULL) {
         FreeContextBuffer (names.sUserName);
         status = MONGOC_SSPI_AUTH_GSS_ERROR;
         goto done;
      }
      FreeContextBuffer (names.sUserName);
      status = MONGOC_SSPI_AUTH_GSS_COMPLETE;
   } else {
      status = MONGOC_SSPI_AUTH_GSS_CONTINUE;
   }
done:
   if (inBufs[0].pvBuffer) {
      free (inBufs[0].pvBuffer);
   }
   if (outBufs[0].pvBuffer) {
      FreeContextBuffer (outBufs[0].pvBuffer);
   }
   return status;
}
Ejemplo n.º 23
0
void test_InitializeSecurityContext(void)
{
	uint32 cbMaxLen;
	uint32 fContextReq;
	void* output_buffer;
	CtxtHandle context;
	uint32 pfContextAttr;
	SECURITY_STATUS status;
	CredHandle credentials;
	TimeStamp expiration;
	SecPkgInfo* pPackageInfo;
	SEC_WINNT_AUTH_IDENTITY identity;
	SecurityFunctionTable* table;
	SecBuffer* p_SecBuffer;
	SecBuffer output_SecBuffer;
	SecBufferDesc output_SecBuffer_desc;

	table = InitSecurityInterface();

	status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo);

	if (status != SEC_E_OK)
	{
		printf("QuerySecurityPackageInfo status: 0x%08X\n", status);
		return;
	}

	cbMaxLen = pPackageInfo->cbMaxToken;

	identity.User = (uint16*) xstrdup(test_User);
	identity.UserLength = sizeof(test_User);
	identity.Domain = (uint16*) xstrdup(test_Domain);
	identity.DomainLength = sizeof(test_Domain);
	identity.Password = (uint16*) xstrdup(test_Password);
	identity.PasswordLength = sizeof(test_Password);
	identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

	status = table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
			SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration);

	if (status != SEC_E_OK)
	{
		printf("AcquireCredentialsHandle status: 0x%08X\n", status);
		return;
	}

	fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;

	output_buffer = xmalloc(cbMaxLen);

	output_SecBuffer_desc.ulVersion = 0;
	output_SecBuffer_desc.cBuffers = 1;
	output_SecBuffer_desc.pBuffers = &output_SecBuffer;

	output_SecBuffer.cbBuffer = cbMaxLen;
	output_SecBuffer.BufferType = SECBUFFER_TOKEN;
	output_SecBuffer.pvBuffer = output_buffer;

	status = table->InitializeSecurityContext(&credentials, NULL, NULL, fContextReq, 0, 0, NULL, 0,
			&context, &output_SecBuffer_desc, &pfContextAttr, &expiration);

	if (status != SEC_I_CONTINUE_NEEDED)
	{
		printf("InitializeSecurityContext status: 0x%08X\n", status);
		return;
	}

	printf("cBuffers: %d ulVersion: %d\n", output_SecBuffer_desc.cBuffers, output_SecBuffer_desc.ulVersion);

	p_SecBuffer = &output_SecBuffer_desc.pBuffers[0];

	printf("BufferType: 0x%04X cbBuffer:%d\n", p_SecBuffer->BufferType, p_SecBuffer->cbBuffer);

	freerdp_hexdump((uint8*) p_SecBuffer->pvBuffer, p_SecBuffer->cbBuffer);

	table->FreeCredentialsHandle(&credentials);

	FreeContextBuffer(pPackageInfo);
}
Ejemplo n.º 24
0
/*
 * '_sspiAccept()' - Accept an SSL/TLS connection
 */
BOOL					/* O - 1 on success, 0 on failure */
_sspiAccept(_sspi_struct_t *conn)	/* I  - Client connection */
{
  DWORD			dwSSPIFlags;	/* SSL connection attributes we want */
  DWORD			dwSSPIOutFlags;	/* SSL connection attributes we got */
  TimeStamp		tsExpiry;	/* Time stamp */
  SECURITY_STATUS	scRet;		/* SSPI Status */
  SecBufferDesc		inBuffer;	/* Array of SecBuffer structs */
  SecBuffer		inBuffers[2];	/* Security package buffer */
  SecBufferDesc		outBuffer;	/* Array of SecBuffer structs */
  SecBuffer		outBuffers[1];	/* Security package buffer */
  DWORD			num = 0;	/* 32 bit status value */
  BOOL			fInitContext = TRUE;
					/* Has the context been init'd? */
  BOOL			ok = TRUE;	/* Return value */

  if (!conn)
    return (FALSE);

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

  conn->decryptBufferUsed = 0;

 /*
  * Set OutBuffer for AcceptSecurityContext call
  */
  outBuffer.cBuffers = 1;
  outBuffer.pBuffers = outBuffers;
  outBuffer.ulVersion = SECBUFFER_VERSION;

  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(("_sspiAccept: unable to allocate %d byte decrypt buffer",
                        conn->decryptBufferLength));
          ok = FALSE;
          goto cleanup;
        }
      }

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

        if ((num == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
          Sleep(1);
        else
          break;
      }

      if (num == SOCKET_ERROR)
      {
        DEBUG_printf(("_sspiAccept: recv failed: %d", WSAGetLastError()));
        ok = FALSE;
        goto cleanup;
      }
      else if (num == 0)
      {
        DEBUG_printf(("_sspiAccept: client disconnected"));
        ok = FALSE;
        goto cleanup;
      }

      DEBUG_printf(("_sspiAccept: received %d (handshake) bytes from client",
                    num));
      conn->decryptBufferUsed += num;
    }

   /*
    * InBuffers[1] is for getting extra data that
    * SSPI/SCHANNEL doesn't proccess on this
    * run around the loop.
    */
    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;

   /*
    * Initialize these so if we fail, pvBuffer contains NULL,
    * so we don't try to free random garbage at the quit
    */
    outBuffers[0].pvBuffer   = NULL;
    outBuffers[0].BufferType = SECBUFFER_TOKEN;
    outBuffers[0].cbBuffer   = 0;

    scRet = AcceptSecurityContext(&conn->creds, (fInitContext?NULL:&conn->context),
                                  &inBuffer, dwSSPIFlags, SECURITY_NATIVE_DREP,
                                  (fInitContext?&conn->context:NULL), &outBuffer,
                                  &dwSSPIOutFlags, &tsExpiry);

    fInitContext = FALSE;

    if (scRet == SEC_E_OK              ||
        scRet == SEC_I_CONTINUE_NEEDED ||
        (FAILED(scRet) && ((dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR) != 0)))
    {
      if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer)
      {
       /*
        * Send response to server if there is one
        */
        num = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);

        if ((num == SOCKET_ERROR) || (num == 0))
        {
          DEBUG_printf(("_sspiAccept: handshake send failed: %d", WSAGetLastError()));
          ok = FALSE;
          goto cleanup;
        }

        DEBUG_printf(("_sspiAccept: send %d handshake bytes to client",
                     outBuffers[0].cbBuffer));

        FreeContextBuffer(outBuffers[0].pvBuffer);
        outBuffers[0].pvBuffer = NULL;
      }
    }

    if (scRet == SEC_E_OK)
    {
     /*
      * If there's extra data then save it for
      * next time we go to decrypt
      */
      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        memcpy(conn->decryptBuffer,
               (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)),
               inBuffers[1].cbBuffer);
        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
      }
      else
      {
        conn->decryptBufferUsed = 0;
      }

      ok = TRUE;
      break;
    }
    else if (FAILED(scRet) && (scRet != SEC_E_INCOMPLETE_MESSAGE))
    {
      DEBUG_printf(("_sspiAccept: AcceptSecurityContext failed: %x", scRet));
      ok = FALSE;
      break;
    }

    if (scRet != SEC_E_INCOMPLETE_MESSAGE &&
        scRet != SEC_I_INCOMPLETE_CREDENTIALS)
    {
      if (inBuffers[1].BufferType == SECBUFFER_EXTRA)
      {
        memcpy(conn->decryptBuffer,
               (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)),
               inBuffers[1].cbBuffer);
        conn->decryptBufferUsed = inBuffers[1].cbBuffer;
      }
      else
      {
        conn->decryptBufferUsed = 0;
      }
    }
  }

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

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

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

cleanup:

  return (ok);
}
Ejemplo n.º 25
0
/*
 * '_sspiFree()' - Close a connection and free resources
 */
void
_sspiFree(_sspi_struct_t *conn)		/* I  - Client connection */
{
  if (!conn)
    return;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  free(conn);
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
0
int SSL_SOCKET :: ServerLoop()
	{
	// Loop AcceptSecurityContext
	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;
	
		// Get Some data from the remote site
		int rval = recv(X,t + pt,0x10000,0);
		if (rval == 0 || rval == -1)
			return -1;
		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;
		bufso[1].BufferType = SECBUFFER_EMPTY;
		bufso[1].cbBuffer = 0;
		bufso[1].pvBuffer = 0;
		sbout.cBuffers      = 2;
		sbout.pBuffers      = bufso;
		sbout.ulVersion     = SECBUFFER_VERSION;


		SEC_E_INTERNAL_ERROR;
		DWORD flg = 0;
		ss = AcceptSecurityContext(
			&hCred,
			InitContext ? &hCtx : 0,
			&sbin,
			ASC_REQ_ALLOCATE_MEMORY,0,
			InitContext ? 0 : &hCtx,
			&sbout,
			&flg,
			0);

		InitContext = true;

		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;

		// Pass data to the remote site
		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;
	}
Ejemplo n.º 28
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;
	}
Ejemplo n.º 29
0
static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
{
    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
    SecHandle *cred = &cred_handle;
    BYTE *read_buf;
    SIZE_T read_buf_size = 2048;
    ULONG attrs = 0;
    CtxtHandle ctx;
    SSIZE_T size;
    int bits;
    const CERT_CONTEXT *cert;
    SECURITY_STATUS status;
    DWORD res = ERROR_SUCCESS;

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

    if(!ensure_cred_handle())
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;

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

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

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

    assert(status != SEC_E_OK);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    heap_free(read_buf);

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

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

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

    if(connection->mask_errors)
        connection->server->security_flags = connection->security_flags;
    return ERROR_SUCCESS;
}
Ejemplo n.º 30
0
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
{
    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
    BYTE *read_buf;
    SIZE_T read_buf_size = 2048;
    ULONG attrs = 0;
    CtxtHandle ctx;
    SSIZE_T size;
    const CERT_CONTEXT *cert;
    SECURITY_STATUS status;
    DWORD res = ERROR_SUCCESS;

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

    if(!ensure_cred_handle())
        return FALSE;

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

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

    assert(status != SEC_E_OK);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    heap_free(read_buf);

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


    TRACE("established SSL connection\n");
    conn->secure = TRUE;
    conn->ssl_ctx = ctx;
    return TRUE;
}