Esempio n. 1
0
void NETCON_unload(void)
{
    if(cred_handle_initialized)
        FreeCredentialsHandle(&cred_handle);
    if(have_compat_cred_handle)
        FreeCredentialsHandle(&compat_cred_handle);
    DeleteCriticalSection(&init_sechandle_cs);
}
Esempio n. 2
0
SSL_SOCKET :: ~SSL_SOCKET()
{
	if (Type == 0)
	ClientOff();
	else
	ServerOff();

	if (hCtx.dwLower || hCtx.dwLower)
	{
		DeleteSecurityContext(&hCtx);
	}

	if (hCred.dwLower || hCred.dwLower)
	{
		FreeCredentialsHandle(&hCred);
	}

	if (OurCertificate && !IsExternalCert)
	{
		CertFreeCertificateContext(OurCertificate);
		OurCertificate = 0;
	}

	if (hCS)
	CertCloseStore(hCS,0);
	hCS = 0;
}
Esempio n. 3
0
void netconn_unload( void )
{
    if(cred_handle_initialized)
        FreeCredentialsHandle(&cred_handle);
    DeleteCriticalSection(&init_sechandle_cs);
#ifndef HAVE_GETADDRINFO
    DeleteCriticalSection(&cs_gethostbyname);
#endif
}
Esempio n. 4
0
/* sqAuthDestroy: Destroys the authentication session.
   Arguments:
     handle - the authentication handle
   Returns: Zero if successful, an error code otherwise.
*/
int sqAuthDestroy(int handle) {
  sqAuthData *auth = (sqAuthData*)handle;

  if(auth == NULL) return -1;

  DeleteSecurityContext(&auth->ctxt);
  FreeCredentialsHandle(&auth->cred);
  free(auth);
  return 0;
}
Esempio n. 5
0
LSSLContext::~LSSLContext()
{
	BYTE stub1[sizeof(m_hContext)]; memset(stub1, 0, sizeof(stub1));
	if(0!=memcmp(&m_hContext, stub1, sizeof(m_hContext))){//возможно глупость так проверять на инициализированность
		/*VERIFY(SEC_E_OK==*/DeleteSecurityContext(GetContextHandle())/*)*/;
		memset(&m_hContext, 0, sizeof(m_hContext));
	}

	BYTE stub2[sizeof(m_hUserCred)]; memset(stub2, 0, sizeof(stub2));
	if(0!=memcmp(&m_hUserCred, stub2, sizeof(m_hUserCred))){//возможно глупость так проверять на инициализированность
		/*VERIFY(SEC_E_OK==*/FreeCredentialsHandle(&m_hUserCred)/*)*/;
		memset(&m_hUserCred, 0, sizeof(m_hUserCred));
	}
}
/* sqDestroySSL: Destroys an SSL instance.
	Arguments:
		handle - the SSL handle
	Returns: Non-zero if successful.
*/
sqInt sqDestroySSL(sqInt handle) {
	sqSSL *ssl = sslFromHandle(handle);
	if(ssl == NULL) return 0;

	FreeCredentialsHandle(&ssl->sslCred);
	DeleteSecurityContext(&ssl->sslCtxt);

	if(ssl->certName) free(ssl->certName);
	if(ssl->peerName) free(ssl->peerName);
	if(ssl->dataBuf) free(ssl->dataBuf);

	free(ssl);
	handleBuf[handle] = NULL;
	return 1;
}
Esempio n. 7
0
/* Cleans the SSPI context object, when the pool used to create it gets
   cleared or destroyed. */
static apr_status_t
cleanup_ctx(void *data)
{
    serf__kerb_context_t *ctx = data;

    if (SecIsValidHandle(&ctx->sspi_context)) {
        DeleteSecurityContext(&ctx->sspi_context);
        SecInvalidateHandle(&ctx->sspi_context);
    }

    if (SecIsValidHandle(&ctx->sspi_credentials)) {
        FreeCredentialsHandle(&ctx->sspi_context);
        SecInvalidateHandle(&ctx->sspi_context);
    }

    return APR_SUCCESS;
}
Esempio n. 8
0
static int tls_close(URLContext *h)
{
    TLSContext *c = h->priv_data;

    tls_shutdown_client(h);

    DeleteSecurityContext(&c->ctxt_handle);
    FreeCredentialsHandle(&c->cred_handle);

    av_freep(&c->enc_buf);
    c->enc_buf_size = c->enc_buf_offset = 0;

    av_freep(&c->dec_buf);
    c->dec_buf_size = c->dec_buf_offset = 0;

    if (c->tls_shared.tcp)
        ffurl_close(c->tls_shared.tcp);
    return 0;
}
Esempio n. 9
0
void NetlibDestroySecurityProvider(HANDLE hSecurity)
{
	if (hSecurity == NULL)
		return;

	mir_cslock lck(csSec);

	if (ntlmCnt != 0) {
		NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity;
		if (hNtlm != NULL) {
			if (SecIsValidHandle(&hNtlm->hClientContext))
				DeleteSecurityContext(&hNtlm->hClientContext);
			if (SecIsValidHandle(&hNtlm->hClientCredential))
				FreeCredentialsHandle(&hNtlm->hClientCredential);
			mir_free(hNtlm->szProvider);
			mir_free(hNtlm->szPrincipal);
			mir_free(hNtlm);
		}

		--ntlmCnt;
	}
}
Esempio n. 10
0
VOID
destroy_sspi_client_state(sspi_client_state* state) {
    if (state->haveCtx) {
        DeleteSecurityContext(&state->ctx);
        state->haveCtx = 0;
    }
    if (state->haveCred) {
        FreeCredentialsHandle(&state->cred);
        state->haveCred = 0;
    }
    if (state->spn != NULL) {
        free(state->spn);
        state->spn = NULL;
    }
    if (state->response != NULL) {
        free(state->response);
        state->response = NULL;
    }
    if (state->username != NULL) {
        free(state->username);
        state->username = NULL;
    }
}
Esempio n. 11
0
static void
GetNewSchannelClientCredentials(
		CredHandle *phCreds,
		CtxtHandle *phContext)
{
	SCHANNEL_CRED	SchannelCred;
	CredHandle	hCreds;
	SecPkgContext_IssuerListInfoEx	IssuerListInfo;
	PCCERT_CHAIN_CONTEXT		pChainContext;
	CERT_CHAIN_FIND_BY_ISSUER_PARA	FindByIssuerPara;
	PCCERT_CONTEXT	pCertContext;
	TimeStamp	tsExpiry;
	SECURITY_STATUS	Status;

	/*
	 * Read list of trusted issuers from schannel.
	 */

	Status = QueryContextAttributes(phContext,
					SECPKG_ATTR_ISSUER_LIST_EX,
					(PVOID)&IssuerListInfo);
	if (Status != SEC_E_OK)
	{
		mylog("Error 0x%p querying issuer list info\n", Status);
		return;
	}

	/*
	 * Enumerate the client certificates.
	 */

	ZeroMemory(&FindByIssuerPara, sizeof(FindByIssuerPara));

	FindByIssuerPara.cbSize = sizeof(FindByIssuerPara);
	FindByIssuerPara.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
	FindByIssuerPara.dwKeySpec	= 0;
	FindByIssuerPara.cIssuer	= IssuerListInfo.cIssuers;
	FindByIssuerPara.rgIssuer	= IssuerListInfo.aIssuers;

	pChainContext = NULL;

	while (TRUE)
	{
		/* Find a certificate chain. */
		pChainContext = CertFindChainInStore(hMyCertStore,
						X509_ASN_ENCODING,
						0,
						CERT_CHAIN_FIND_BY_ISSUER,
						&FindByIssuerPara,
						pChainContext);
		if (pChainContext == NULL)
		{
			mylog("Error 0x%p finding cert chain\n", GetLastError());
			break;
		}
		mylog("\ncertificate chain found\n");

		/* Get pointer to leaf certificate context. */
		pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;

		ZeroMemory(&SchannelCred, sizeof(SchannelCred));
        	/* Create schannel credential. */
        	SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
        	SchannelCred.cCreds = 1;
        	SchannelCred.paCred = &pCertContext;

        	Status = AcquireCredentialsHandle(
                            NULL,		/* Name of principal */
                            UNI_SCHANNEL,	/* Name of package */
                            SECPKG_CRED_OUTBOUND,	/* Flags indicating use */
                            NULL,		/* Pointer to logon ID */
                            &SchannelCred,	/* Package specific data */
                            NULL,		/* Pointer to GetKey() func */
                            NULL,		/* Value to pass to GetKey() */
                            &hCreds,		/* (out) Cred Handle */
                            &tsExpiry);		/* (out) Lifetime (optional) */
		if (Status != SEC_E_OK)
		{
			 mylog("**** Error 0x%p returned by AcquireCredentialsHandle\n", Status);
			continue;
		}
		mylog("\nnew schannel credential created\n");

		/* Destroy the old credentials. */
		FreeCredentialsHandle(phCreds);

		*phCreds = hCreds;

		/*
		 * As you can see, this sample code maintains a single credential
		 * handle, replacing it as necessary. This is a little unusual.
		 *
		 * Many applications maintain a global credential handle that's
		 * anonymous (that is, it doesn't contain a client certificate),
		 * which is used to connect to all servers. If a particular server
		 * should require client authentication, then a new credential 
		 * is created for use when connecting to that server. The global
		 * anonymous credential is retained for future connections to
		 * other servers.
		 *
		 * Maintaining a single anonymous credential that's used whenever
		 * possible is most efficient, since creating new credentials all
		 * the time is rather expensive.
		 */

		break;
	}
}
Esempio n. 12
0
int credssp_client_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_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;
	}

	cbMaxToken = pPackageInfo->cbMaxToken;

	status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
			SECPKG_CRED_OUTBOUND, 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)
	{
		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->InitializeSecurityContext(&credentials,
				(have_context) ? &credssp->context : NULL,
				NULL, fContextReq, 0, SECURITY_NATIVE_DREP,
				(have_input_buffer) ? &input_buffer_desc : NULL,
				0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration);

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

		if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK))
		{
			if (credssp->table->CompleteAuthToken != NULL)
				credssp->table->CompleteAuthToken(&credssp->context, &output_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;
				SecBuffer Buffers[2];
				SecBufferDesc Message;
				SECURITY_STATUS encrypt_status;

				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;

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

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

				if (encrypt_status != SEC_E_OK)
				{
					printf("EncryptMessage status: 0x%08X\n", encrypt_status);
					return 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 */
				xfree(Buffers[0].pvBuffer);
				xfree(Buffers[1].pvBuffer);
			}

			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_buffer.cbBuffer > 0)
		{
			p_buffer = &output_buffer_desc.pBuffers[0];

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

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

			credssp_send(credssp);
			credssp_buffer_free(credssp);
		}

		if (status != SEC_I_CONTINUE_NEEDED)
			break;

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

		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");
		freerdp_hexdump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer);
#endif

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

		have_input_buffer = true;
		have_context = true;
	}

	/* Encrypted Public Key +1 */
	if (credssp_recv(credssp) < 0)
		return -1;

	/* Verify Server Public Key Echo */

	status = credssp_verify_public_key_echo(credssp);
	credssp_buffer_free(credssp);

	if (status != SEC_E_OK)
		return 0;

	/* Send encrypted credentials */

	status = credssp_encrypt_ts_credentials(credssp);

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

	credssp_send(credssp);
	credssp_buffer_free(credssp);

	/* Free resources */

	FreeCredentialsHandle(&credentials);
	FreeContextBuffer(pPackageInfo);

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

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

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

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

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

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

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


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

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

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

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

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

			sendAuthRequest(port, AUTH_REQ_GSS_CONT);

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

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

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

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

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

	} while (r == SEC_I_CONTINUE_NEEDED);


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


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

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

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

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

	FreeLibrary(secur32);

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

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

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

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

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

	free(tokenuser);

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

			return STATUS_ERROR;
		}
	}

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

		return STATUS_ERROR;
	}

	return STATUS_OK;
}
Esempio n. 14
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;
}
Esempio n. 15
0
INT
_cdecl
main(
    IN INT argc,
    IN PCHAR* argv
    )
{
    DWORD dwError = ERROR_SUCCESS;
    INT nListenSocket = INVALID_SOCKET;
    INT nAcceptSocket = INVALID_SOCKET;
    USHORT usVersionRequired = 0x0101;
    USHORT usPort = 4444;
    INT nOnce = 0;
    PCHAR pServiceName = NULL;
    PCHAR pServicePassword = NULL;
    PCHAR pServiceRealm = NULL;
    WSADATA SocketData;
    CredHandle ServerCreds;
    INT nServerCredsAcquired = 0;
    INT nSocketsStarted = 0;
    ULONG AscFlags =
        //ASC_REQ_MUTUAL_AUTH |
        //ASC_REQ_CONFIDENTIALITY |
        ASC_REQ_INTEGRITY |
        ASC_REQ_ALLOCATE_MEMORY;
    PCHAR pSecPkgName = NTLMSP_NAME_A;

    FLAGMAPPING FlagMappings[] = {
        INIT_FLAGMAPPING( CONFIDENTIALITY ),
        INIT_FLAGMAPPING( DELEGATE ),
        INIT_FLAGMAPPING( INTEGRITY ),
        INIT_FLAGMAPPING( USE_SESSION_KEY ),
        INIT_FLAGMAPPING( REPLAY_DETECT ),
        INIT_FLAGMAPPING( SEQUENCE_DETECT )
    };

    memset(&SocketData, 0, sizeof(WSADATA));
    memset(&ServerCreds, 0, sizeof(CredHandle));

    argc--; argv++;

    while (argc)
    {
        if (strcmp(*argv, "-port") == 0)
        {
            argc--; argv++;
            if (!argc)
            {
                dwError = Usage();
                BAIL_ON_ERROR(dwError);
            }
            usPort = (u_short)atoi(*argv);
        }
        else if (strcmp(*argv, "-once") == 0)
        {
            nOnce = 1;
        }
        else if (strcmp(*argv, "-k") == 0)
        {
            pSecPkgName = MICROSOFT_KERBEROS_NAME_A;
        }
        else if (strcmp(*argv, "-spnego") == 0)
        {
            pSecPkgName = NEGOSSP_NAME;
        }
        else if (strcmp(*argv, "-c") == 0)
        {
            argv++;
            argc--;

            if (argc < 3)
            {
                dwError = Usage();
                BAIL_ON_ERROR(dwError);
            }

            pServiceName = *argv;
            argv++;
            argc--;
            pServicePassword = *argv;
            argv++;
            argc--;
            pServiceRealm = *argv;
        }
        else
        {
            int i;
            BOOLEAN bFound = FALSE;

            for (i = 0; i < (sizeof(FlagMappings)/sizeof(FLAGMAPPING)); i++)
            {
                if (_strcmpi( *argv, FlagMappings[ i ].name ) == 0)
                {
                    bFound = TRUE;
                    AscFlags |= FlagMappings[ i ].value ;
                    break;
                }
            }

            if (!bFound)
            {
                break;
            }
        }

        argc--; argv++;
    }

    dwError = WSAStartup(usVersionRequired, &SocketData);
    if (0 != dwError)
    {
        dwError = WSAGetLastError();
        BAIL_ON_ERROR(dwError);
    }

    nSocketsStarted = 1;

    dwError = CreateSocket(usPort, &nListenSocket);

    BAIL_ON_ERROR(dwError);

    do
    {
        dwError = ServerAcquireCreds(
            pServiceName,
            pServicePassword,
            pServiceRealm,
            pSecPkgName,
            &ServerCreds
            );
        BAIL_ON_ERROR(dwError);

        nServerCredsAcquired = 1;

        /* Accept a TCP connection */
        printf("Listening...\n");
        nAcceptSocket = (int)accept(nListenSocket, NULL, 0);

        if (INVALID_SOCKET == nAcceptSocket)
        {
            dwError = WSAGetLastError();
            BAIL_ON_ERROR(dwError);
        }

        dwError = SignServer(
            nAcceptSocket,
            &ServerCreds,
            AscFlags
            );

        if (dwError)
        {
            printf("Finished with error code: %d\n", dwError);
        }

        if (nServerCredsAcquired)
        {
            FreeCredentialsHandle(&ServerCreds);
            nServerCredsAcquired = 0;
        }

        closesocket(nAcceptSocket);

    } while (!nOnce);

    closesocket(nListenSocket);

    FreeCredentialsHandle(&ServerCreds);

    WSACleanup();

finish:
    return dwError;
error:
    if (nServerCredsAcquired)
    {
        FreeCredentialsHandle(&ServerCreds);
    }
    if (INVALID_SOCKET != nListenSocket)
    {
        closesocket(nListenSocket);
    }
    if (INVALID_SOCKET != nAcceptSocket)
    {
        closesocket(nAcceptSocket);
    }
    if (nSocketsStarted)
    {
        WSACleanup();
    }
    goto finish;
}
Esempio n. 16
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;
}
Esempio n. 17
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;
}
Esempio n. 18
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;
}