libfreerdp-core: start TSG integration with libfreerdp-sspi

This commit is contained in:
Marc-André Moreau 2012-03-26 23:20:25 -04:00
parent 1743a9464f
commit 809cc99b82
2 changed files with 229 additions and 63 deletions

View File

@ -29,37 +29,6 @@
#define HTTP_STREAM_SIZE 0xFFFF
rdpRpch* rpch_new(rdpSettings* settings)
{
rdpRpch* rpch;
rpch = (rdpRpch*) xzalloc(sizeof(rdpRpch));
rpch->http_in = (rdpRpchHTTP*) xzalloc(sizeof(rdpRpchHTTP));
rpch->http_out = (rdpRpchHTTP*) xzalloc(sizeof(rdpRpchHTTP));
//rpch->http_in->ntht = ntlmssp_client_new();
//rpch->http_out->ntht = ntlmssp_client_new();
rpch->http_in->state = RPCH_HTTP_DISCONNECTED;
rpch->http_out->state = RPCH_HTTP_DISCONNECTED;
rpch->read_buffer = NULL;
rpch->write_buffer = NULL;
rpch->read_buffer_len = 0;
rpch->write_buffer_len = 0;
rpch->BytesReceived = 0;
rpch->AwailableWindow = 0;
rpch->BytesSent = 0;
rpch->RecAwailableWindow = 0;
rpch->settings = settings;
//rpch->ntlmssp = ntlmssp_client_new();
rpch->call_id = 0;
return rpch;
}
boolean rpch_attach(rdpRpch* rpch, rdpTcp* tcp_in, rdpTcp* tcp_out, rdpTls* tls_in, rdpTls* tls_out)
{
rpch->tcp_in = tcp_in;
@ -70,39 +39,170 @@ boolean rpch_attach(rdpRpch* rpch, rdpTcp* tcp_in, rdpTcp* tcp_out, rdpTls* tls_
return true;
}
#define NTLM_PACKAGE_NAME _T("NTLM")
boolean ntlm_client_init(rdpNtlm* ntlm, char* user, char* domain, char* password)
{
size_t size;
SECURITY_STATUS status;
sspi_GlobalInit();
ntlm->table = InitSecurityInterface();
ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
ntlm->identity.User = (uint16*) freerdp_uniconv_out(ntlm->uniconv, user, &size);
ntlm->identity.UserLength = (uint32) size;
if (domain)
{
ntlm->identity.Domain = (uint16*) freerdp_uniconv_out(ntlm->uniconv, domain, &size);
ntlm->identity.DomainLength = (uint32) size;
}
else
{
ntlm->identity.Domain = (uint16*) NULL;
ntlm->identity.DomainLength = 0;
}
ntlm->identity.Password = (uint16*) freerdp_uniconv_out(ntlm->uniconv, (char*) password, &size);
ntlm->identity.PasswordLength = (uint32) size;
status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo);
if (status != SEC_E_OK)
{
printf("QuerySecurityPackageInfo status: 0x%08X\n", status);
return false;
}
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME,
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
{
printf("AcquireCredentialsHandle status: 0x%08X\n", status);
return false;
}
ntlm->haveContext = false;
ntlm->haveInputBuffer = false;
memset(&ntlm->inputBuffer, 0, sizeof(SecBuffer));
memset(&ntlm->outputBuffer, 0, sizeof(SecBuffer));
memset(&ntlm->ContextSizes, 0, sizeof(SecPkgContext_Sizes));
ntlm->fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE;
return true;
}
boolean ntlm_authenticate(rdpNtlm* ntlm)
{
SECURITY_STATUS status;
ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION;
ntlm->outputBufferDesc.cBuffers = 1;
ntlm->outputBufferDesc.pBuffers = &ntlm->outputBuffer;
ntlm->outputBuffer.BufferType = SECBUFFER_TOKEN;
ntlm->outputBuffer.cbBuffer = ntlm->cbMaxToken;
ntlm->outputBuffer.pvBuffer = xmalloc(ntlm->outputBuffer.cbBuffer);
status = ntlm->table->InitializeSecurityContext(&ntlm->credentials,
(ntlm->haveContext) ? &ntlm->context : NULL,
NULL, ntlm->fContextReq, 0, SECURITY_NATIVE_DREP,
(ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL,
0, &ntlm->context, &ntlm->outputBufferDesc,
&ntlm->pfContextAttr, &ntlm->expiration);
if (ntlm->inputBuffer.pvBuffer != NULL)
{
xfree(ntlm->inputBuffer.pvBuffer);
ntlm->inputBuffer.pvBuffer = NULL;
}
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK))
{
if (ntlm->table->CompleteAuthToken != NULL)
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
{
printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n");
return 0;
}
if (status == SEC_I_COMPLETE_NEEDED)
status = SEC_E_OK;
else if (status == SEC_I_COMPLETE_AND_CONTINUE)
status = SEC_I_CONTINUE_NEEDED;
}
ntlm->haveInputBuffer = true;
ntlm->haveContext = true;
return true;
}
void ntlm_client_uninit(rdpNtlm* ntlm)
{
FreeCredentialsHandle(&ntlm->credentials);
FreeContextBuffer(ntlm->pPackageInfo);
}
rdpNtlm* ntlm_new()
{
rdpNtlm* ntlm = xnew(rdpNtlm);
if (ntlm != NULL)
{
ntlm->uniconv = freerdp_uniconv_new();
}
return ntlm;
}
void ntlm_free(rdpNtlm* ntlm)
{
if (ntlm != NULL)
{
freerdp_uniconv_free(ntlm->uniconv);
}
}
boolean rpch_out_connect_http(rdpRpch* rpch)
{
STREAM* http_stream;
STREAM* ntlm_stream;
int decoded_ntht_length;
int encoded_ntht_length;
uint8* decoded_ntht_data = NULL;
uint8* encoded_ntht_data = NULL;
rdpTls* tls_out = rpch->tls_out;
rdpSettings* settings = rpch->settings;
rdpRpchHTTP* http_out = rpch->http_out;
//NTLMSSP* http_out_ntlmssp = http_out->ntht;
rdpNtlm* http_out_ntlm = http_out->ntlm;
STREAM* ntlmssp_stream;
STREAM* http_stream;
ntlmssp_stream = stream_new(0xFFFF);
http_stream = stream_new(0xFFFF);
ntlm_stream = stream_new(0xFFFF);
uint8* decoded_ntht_data = NULL;
int decoded_ntht_length;
uint8* encoded_ntht_data = NULL;
int encoded_ntht_length;
printf("rpch_out_connect_http\n");
//ntlmssp_set_username(http_out_ntlmssp, settings->username);
//ntlmssp_set_password(http_out_ntlmssp, settings->password);
//ntlmssp_set_domain(http_out_ntlmssp, settings->domain);
//ntlmssp_set_workstation(http_out_ntlmssp, "WORKSTATION"); /* TODO insert proper w.name */
ntlm_client_init(http_out_ntlm, settings->username, settings->password, settings->domain);
//ntlmssp_send(http_out_ntlmssp, ntlmssp_stream);
ntlm_authenticate(http_out_ntlm);
ntlm_stream->size = http_out_ntlm->outputBuffer.cbBuffer;
ntlm_stream->p = ntlm_stream->data = http_out_ntlm->outputBuffer.pvBuffer;
decoded_ntht_length = ntlmssp_stream->p-ntlmssp_stream->data;
decoded_ntht_length = ntlm_stream->size;
decoded_ntht_data = xmalloc(decoded_ntht_length);
stream_read(ntlm_stream, decoded_ntht_data, decoded_ntht_length);
ntlmssp_stream->p = ntlmssp_stream->data;
stream_read(ntlmssp_stream, decoded_ntht_data, decoded_ntht_length);
stream_clear(ntlmssp_stream);
ntlmssp_stream->p = ntlmssp_stream->data;
stream_clear(ntlm_stream);
ntlm_stream->p = ntlm_stream->data;
crypto_base64_encode(decoded_ntht_data, decoded_ntht_length, &encoded_ntht_data, &encoded_ntht_length);
@ -205,25 +305,25 @@ boolean rpch_out_connect_http(rdpRpch* rpch)
crypto_base64_decode(encoded_ntht_data, encoded_ntht_length, &decoded_ntht_data, &decoded_ntht_length);
stream_write(ntlmssp_stream, decoded_ntht_data, decoded_ntht_length);
ntlmssp_stream->p = ntlmssp_stream->data;
stream_write(ntlm_stream, decoded_ntht_data, decoded_ntht_length);
ntlm_stream->p = ntlm_stream->data;
xfree(decoded_ntht_data);
xfree(encoded_ntht_data);
//ntlmssp_recv(http_out_ntlmssp, ntlmssp_stream);
stream_clear(ntlmssp_stream);
ntlmssp_stream->p = ntlmssp_stream->data;
stream_clear(ntlm_stream);
ntlm_stream->p = ntlm_stream->data;
//ntlmssp_send(http_out_ntlmssp, ntlmssp_stream);
decoded_ntht_length = ntlmssp_stream->p-ntlmssp_stream->data;
decoded_ntht_length = ntlm_stream->p-ntlm_stream->data;
decoded_ntht_data = xmalloc(decoded_ntht_length);
ntlmssp_stream->p = ntlmssp_stream->data;
stream_read(ntlmssp_stream, decoded_ntht_data, decoded_ntht_length);
ntlm_stream->p = ntlm_stream->data;
stream_read(ntlm_stream, decoded_ntht_data, decoded_ntht_length);
stream_clear(ntlmssp_stream);
ntlmssp_stream->p = ntlmssp_stream->data;
stream_clear(ntlm_stream);
ntlm_stream->p = ntlm_stream->data;
crypto_base64_encode(decoded_ntht_data, decoded_ntht_length, &encoded_ntht_data, &encoded_ntht_length);
@ -1396,3 +1496,36 @@ boolean rpch_connect(rdpRpch* rpch)
return true;
}
rdpRpch* rpch_new(rdpSettings* settings)
{
rdpRpch* rpch = (rdpRpch*) xnew(rdpRpch);
if (rpch != NULL)
{
rpch->http_in = (rdpRpchHTTP*) xnew(rdpRpchHTTP);
rpch->http_out = (rdpRpchHTTP*) xnew(rdpRpchHTTP);
rpch->http_in->ntlm = ntlm_new();
rpch->http_out->ntlm = ntlm_new();
rpch->http_in->state = RPCH_HTTP_DISCONNECTED;
rpch->http_out->state = RPCH_HTTP_DISCONNECTED;
rpch->read_buffer = NULL;
rpch->write_buffer = NULL;
rpch->read_buffer_len = 0;
rpch->write_buffer_len = 0;
rpch->BytesReceived = 0;
rpch->AwailableWindow = 0;
rpch->BytesSent = 0;
rpch->RecAwailableWindow = 0;
rpch->settings = settings;
rpch->ntlm = ntlm_new();
rpch->call_id = 0;
}
return rpch;
}

View File

@ -559,6 +559,29 @@ typedef struct {
/* end common fields */
} rpcconn_shutdown_hdr_t;
struct rdp_ntlm
{
UNICONV* uniconv;
CtxtHandle context;
uint32 cbMaxToken;
uint32 fContextReq;
uint32 pfContextAttr;
TimeStamp expiration;
PSecBuffer pBuffer;
SecBuffer inputBuffer;
SecBuffer outputBuffer;
boolean haveContext;
boolean haveInputBuffer;
SecBufferDesc inputBufferDesc;
SecBufferDesc outputBufferDesc;
CredHandle credentials;
SecPkgInfo* pPackageInfo;
SecurityFunctionTable* table;
SEC_WINNT_AUTH_IDENTITY identity;
SecPkgContext_Sizes ContextSizes;
};
typedef struct rdp_ntlm rdpNtlm;
enum _RPCH_HTTP_STATE
{
RPCH_HTTP_DISCONNECTED = 0,
@ -572,21 +595,23 @@ struct rdp_rpch_http
RPCH_HTTP_STATE state;
int contentLength;
int remContentLength;
//struct _NTLMSSP* ntht;
rdpNtlm* ntlm;
};
struct rdp_rpch
{
rdpSettings* settings;
rdpTcp* tcp_in;
rdpTcp* tcp_out;
rdpTls* tls_in;
rdpTls* tls_out;
//struct _NTLMSSP* ntlmssp;
rdpNtlm* ntlm;
rdpRpchHTTP* http_in;
rdpRpchHTTP* http_out;
UNICONV* uniconv;
rdpSettings* settings;
uint8* write_buffer;
uint32 write_buffer_len;
uint8* read_buffer;
@ -603,6 +628,14 @@ struct rdp_rpch
uint32 pipe_call_id;
};
boolean ntlm_authenticate(rdpNtlm* ntlm);
boolean ntlm_client_init(rdpNtlm* ntlm, char* user, char* domain, char* password);
void ntlm_client_uninit(rdpNtlm* ntlm);
rdpNtlm* ntlm_new();
void ntlm_free(rdpNtlm* ntlm);
boolean rpch_attach(rdpRpch* rpch, rdpTcp* tcp_in, rdpTcp* tcp_out, rdpTls* tls_in, rdpTls* tls_out);
boolean rpch_connect(rdpRpch* rpch);