Merge pull request #2346 from awakecoding/gateway

Win32 Gateway Fix
This commit is contained in:
Marc-André Moreau 2015-01-29 15:00:37 -05:00
commit 77b6a20223
25 changed files with 1047 additions and 984 deletions

1
.gitignore vendored
View File

@ -79,6 +79,7 @@ RelWithDebInfo
*.resource.txt
*.embed.manifest*
*.intermediate.manifest*
version.rc
# Binaries
*.a

View File

@ -23,10 +23,6 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/smartcard.h>
#include <winpr/environment.h>
@ -385,7 +381,7 @@ void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
}
else
{
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
irp->MajorFunction, irp->MinorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
@ -521,8 +517,6 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
smartcard->name = name;
}
smartcard->log = WLog_Get("com.freerdp.channel.smartcard.client");
smartcard->IrpQueue = MessageQueue_New(NULL);
smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1);

View File

@ -108,8 +108,6 @@ struct _SMARTCARD_DEVICE
{
DEVICE device;
wLog* log;
char* name;
char* path;

View File

@ -23,9 +23,6 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <winpr/crt.h>
@ -1033,9 +1030,8 @@ static UINT32 smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
if (ret.ReturnCode)
{
WLog_Print(smartcard->log, WLOG_WARN,
"SCardGetAttrib: %s (0x%08X) cbAttrLen: %d",
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
WLog_WARN(TAG, "SCardGetAttrib: %s (0x%08X) cbAttrLen: %d",
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
Stream_Zero(irp->output, 256);
free(ret.pbAttr);
@ -1060,7 +1056,7 @@ static UINT32 smartcard_AccessStartedEvent_Decode(SMARTCARD_DEVICE* smartcard, S
if (Stream_GetRemainingLength(irp->input) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "AccessStartedEvent is too short: %d",
WLog_WARN(TAG, "AccessStartedEvent is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
@ -1207,7 +1203,7 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
if (Stream_GetRemainingLength(irp->input) < 32)
{
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
WLog_WARN(TAG, "Device Control Request is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
@ -1220,18 +1216,14 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
{
WLog_Print(smartcard->log, WLOG_WARN,
"InputBufferLength mismatch: Actual: %d Expected: %d",
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %d Expected: %d",
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
return SCARD_F_INTERNAL_ERROR;
}
WLog_Print(smartcard->log, WLOG_DEBUG, "%s (0x%08X) FileId: %d CompletionId: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
#if 0
WLog_DBG(TAG, "%s (0x%08X) FileId: %d CompletionId: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
#endif
smartcard_get_ioctl_string(ioControlCode, TRUE),
ioControlCode, irp->FileId, irp->CompletionId);
if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
(ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT))
@ -1482,10 +1474,9 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
{
UINT32 difference;
difference = (int)(Stream_Length(irp->input) - Stream_GetPosition(irp->input));
WLog_Print(smartcard->log, WLOG_WARN,
"IRP was not fully parsed %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
WLog_WARN(TAG, "IRP was not fully parsed %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
winpr_HexDump(TAG, WLOG_WARN, Stream_Pointer(irp->input), difference);
}
@ -1493,10 +1484,9 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
{
UINT32 difference;
difference = (int)(Stream_GetPosition(irp->input) - Stream_Length(irp->input));
WLog_Print(smartcard->log, WLOG_WARN,
"IRP was parsed beyond its end %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
WLog_WARN(TAG, "IRP was parsed beyond its end %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
}
if (status != SCARD_S_SUCCESS)
@ -1756,10 +1746,9 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
(result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE))
{
WLog_Print(smartcard->log, WLOG_WARN,
"IRP failure: %s (0x%08X), status: %s (0x%08X)",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
SCardGetErrorString(result), result);
WLog_WARN(TAG, "IRP failure: %s (0x%08X), status: %s (0x%08X)",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
SCardGetErrorString(result), result);
}
irp->IoStatus = 0;
@ -1769,9 +1758,8 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
/* NTSTATUS error */
irp->IoStatus = result;
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
WLog_Print(smartcard->log, WLOG_WARN,
"IRP failure: %s (0x%08X), ntstatus: 0x%08X",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
WLog_WARN(TAG, "IRP failure: %s (0x%08X), ntstatus: 0x%08X",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
}
Stream_SealLength(irp->output);

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" },
{ "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" },
{ "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, NULL, "Gateway usage method" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" },
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" },
{ "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" },
{ "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" },
@ -1464,7 +1464,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->GatewayEnabled = TRUE;
settings->GatewayUseSameCredentials = TRUE;
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DETECT);
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DIRECT);
}
CommandLineSwitchCase(arg, "gu")
{

View File

@ -44,29 +44,10 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
{
SECURITY_STATUS status;
sspi_GlobalInit();
ntlm->http = http;
ntlm->Bindings = Bindings;
#ifdef WITH_NATIVE_SSPI
{
HMODULE hSSPI;
INIT_SECURITY_INTERFACE InitSecurityInterface;
PSecurityFunctionTable pSecurityInterface = NULL;
hSSPI = LoadLibrary(_T("secur32.dll"));
#ifdef UNICODE
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
#else
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
#endif
ntlm->table = (*InitSecurityInterface)();
}
#else
ntlm->table = InitSecurityInterface();
#endif
ntlm->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR);
sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password);
@ -74,18 +55,19 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
if (status != SEC_E_OK)
{
WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", status);
WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", status);
return FALSE;
}
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration);
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL,
&ntlm->credentials, &ntlm->expiration);
if (status != SEC_E_OK)
{
WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", status);
WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", status);
return FALSE;
}
@ -121,45 +103,41 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname)
{
int length;
DWORD status;
DWORD SpnLength;
LPTSTR hostnameX;
length = 0;
DWORD SpnLength = 0;
LPTSTR hostnameX = NULL;
#ifdef UNICODE
length = strlen(hostname);
hostnameX = (LPWSTR) malloc((length + 1)* sizeof(TCHAR));
MultiByteToWideChar(CP_UTF8, 0, hostname, length, hostnameX, length);
hostnameX[length] = 0;
ConvertToUnicode(CP_UTF8, 0, hostname, -1, (LPWSTR*) &hostnameX, 0);
#else
hostnameX = hostname;
hostnameX = _strdup(hostname);
#endif
if (!hostnameX)
return FALSE;
if (!ServiceClass)
{
ntlm->ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX);
if (!ntlm->ServicePrincipalName)
return FALSE;
return TRUE;
}
SpnLength = 0;
status = DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, NULL);
if (status != ERROR_BUFFER_OVERFLOW)
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, NULL) != ERROR_BUFFER_OVERFLOW)
return FALSE;
ntlm->ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR));
if (!ntlm->ServicePrincipalName)
return FALSE;
status = DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName);
if (status != ERROR_SUCCESS)
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName) != ERROR_SUCCESS)
return FALSE;
free(hostnameX);
return TRUE;
}
@ -239,7 +217,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
if ((!ntlm) || (!ntlm->table))
{
WLog_ERR(TAG, "ntlm_authenticate: invalid ntlm context");
WLog_ERR(TAG, "ntlm_authenticate: invalid ntlm context");
return FALSE;
}
@ -253,12 +231,12 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK))
{
if (ntlm->table->CompleteAuthToken != NULL)
if (ntlm->table->CompleteAuthToken)
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
{
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
return FALSE;
}
@ -271,6 +249,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
if (ntlm->haveInputBuffer)
{
free(ntlm->inputBuffer[0].pvBuffer);
ntlm->inputBuffer[0].pvBuffer = NULL;
}
ntlm->haveInputBuffer = TRUE;
@ -282,9 +261,16 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
void ntlm_client_uninit(rdpNtlm* ntlm)
{
free(ntlm->identity.User);
ntlm->identity.User = NULL;
free(ntlm->identity.Domain);
ntlm->identity.Domain = NULL;
free(ntlm->identity.Password);
ntlm->identity.Password = NULL;
free(ntlm->ServicePrincipalName);
ntlm->ServicePrincipalName = NULL;
if (ntlm->table)
{

View File

@ -310,9 +310,9 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
{
int status;
BYTE* buffer;
UINT32 offset;
UINT32 length;
RpcClientCall* clientCall;
rpcconn_rpc_auth_3_hdr_t* auth_3_pdu;
@ -360,17 +360,17 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, auth_3_pdu->auth_length);
offset += (8 + auth_3_pdu->auth_length);
length = auth_3_pdu->frag_length;
status = (int) auth_3_pdu->frag_length;
clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0);
ArrayList_Add(rpc->client->ClientCallList, clientCall);
if (rpc_send_enqueue_pdu(rpc, buffer, length) != 0)
length = -1;
if (rpc_send_enqueue_pdu(rpc, buffer, (UINT32) status) != 0)
status = -1;
free(auth_3_pdu);
return length;
return status;
}
/**

View File

@ -64,7 +64,7 @@ RPC_PDU* rpc_client_receive_pool_take(rdpRpc* rpc)
if (!pdu)
{
pdu = (RPC_PDU*)malloc(sizeof(RPC_PDU));
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
if (!pdu)
return NULL;
@ -311,9 +311,10 @@ RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
{
int index;
int count;
RpcClientCall* clientCall;
RpcClientCall* clientCall = NULL;
ArrayList_Lock(rpc->client->ClientCallList);
clientCall = NULL;
count = ArrayList_Count(rpc->client->ClientCallList);
for (index = 0; index < count; index++)
@ -325,13 +326,15 @@ RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
}
ArrayList_Unlock(rpc->client->ClientCallList);
return clientCall;
}
RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
{
RpcClientCall* clientCall;
clientCall = (RpcClientCall*) malloc(sizeof(RpcClientCall));
clientCall = (RpcClientCall*) calloc(1, sizeof(RpcClientCall));
if (!clientCall)
return NULL;
@ -339,6 +342,7 @@ RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
clientCall->CallId = CallId;
clientCall->OpNum = OpNum;
clientCall->State = RPC_CLIENT_CALL_STATE_SEND_PDUS;
return clientCall;
}
@ -349,8 +353,9 @@ void rpc_client_call_free(RpcClientCall* clientCall)
int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
RPC_PDU* pdu;
int status;
RPC_PDU* pdu;
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
if (!pdu)
@ -385,6 +390,7 @@ out_free_stream:
Stream_Free(pdu->s, TRUE);
out_free:
free(pdu);
WLog_ERR(TAG, "rpc_send_enqueue_pdu failure");
return -1;
}
@ -434,19 +440,20 @@ int rpc_send_dequeue_pdu(rdpRpc* rpc)
RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc)
{
RPC_PDU* pdu;
DWORD waitStatus;
DWORD dwMilliseconds;
DWORD result;
dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT * 4 : 0;
result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
if (result == WAIT_TIMEOUT)
waitStatus = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
if (waitStatus == WAIT_TIMEOUT)
{
WLog_ERR(TAG, "timed out waiting for receive event");
return NULL;
}
if (result != WAIT_OBJECT_0)
if (waitStatus != WAIT_OBJECT_0)
return NULL;
pdu = (RPC_PDU*) Queue_Dequeue(rpc->client->ReceiveQueue);
@ -456,52 +463,37 @@ RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc)
RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc)
{
DWORD waitStatus;
DWORD dwMilliseconds;
DWORD result;
dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT : 0;
result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
if (result != WAIT_OBJECT_0)
waitStatus = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
if (waitStatus != WAIT_OBJECT_0)
return NULL;
return (RPC_PDU*)Queue_Peek(rpc->client->ReceiveQueue);
return (RPC_PDU*) Queue_Peek(rpc->client->ReceiveQueue);
}
static void* rpc_client_thread(void* arg)
{
int fd;
DWORD status;
DWORD nCount;
HANDLE events[3];
HANDLE ReadEvent;
HANDLE events[8];
DWORD waitStatus;
HANDLE ReadEvent = NULL;
rdpRpc* rpc = (rdpRpc*) arg;
fd = BIO_get_fd(rpc->TlsOut->bio, NULL);
ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, fd);
BIO_get_event(rpc->TlsOut->bio, &ReadEvent);
nCount = 0;
events[nCount++] = rpc->client->StopEvent;
events[nCount++] = Queue_Event(rpc->client->SendQueue);
events[nCount++] = ReadEvent;
/* Do a first free run in case some bytes were set from the HTTP headers.
* We also have to do it because most of the time the underlying socket has notified,
* and the ssl layer has eaten all bytes, so we won't be notified any more even if the
* bytes are buffered locally
*/
if (rpc_client_on_read_event(rpc) < 0)
{
WLog_ERR(TAG, "an error occurred when treating first packet");
goto out;
}
while (rpc->transport->layer != TRANSPORT_LAYER_CLOSED)
{
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
if (status == WAIT_TIMEOUT)
continue;
waitStatus = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0)
break;
@ -521,8 +513,6 @@ static void* rpc_client_thread(void* arg)
}
}
out:
CloseHandle(ReadEvent);
return NULL;
}

View File

@ -1413,6 +1413,9 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port)
rpc->client->SynchronousSend = TRUE;
rpc->client->SynchronousReceive = TRUE;
tsg->bio = BIO_new(BIO_s_tsg());
tsg->bio->ptr = tsg;
WLog_INFO(TAG, "TS Gateway Connection Success");
return TRUE;
@ -1602,9 +1605,121 @@ void tsg_free(rdpTsg* tsg)
{
if (tsg)
{
if (tsg->bio)
{
BIO_free(tsg->bio);
tsg->bio = NULL;
}
rpc_free(tsg->rpc);
free(tsg->Hostname);
free(tsg->MachineName);
free(tsg);
}
}
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
{
return 1;
}
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
status = tsg_write(tsg, (BYTE*) buf, num);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_WRITE);
}
return status >= 0 ? status : -1;
}
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = tsg_read(tsg, (BYTE*) buf, size);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_READ);
}
return status > 0 ? status : -1;
}
static int transport_bio_tsg_puts(BIO* bio, const char* str)
{
return 1;
}
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
{
return 1;
}
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
if (cmd == BIO_CTRL_FLUSH)
{
return 1;
}
return 0;
}
static int transport_bio_tsg_new(BIO* bio)
{
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
return 1;
}
static int transport_bio_tsg_free(BIO* bio)
{
return 1;
}
static BIO_METHOD transport_bio_tsg_methods =
{
BIO_TYPE_TSG,
"TSGateway",
transport_bio_tsg_write,
transport_bio_tsg_read,
transport_bio_tsg_puts,
transport_bio_tsg_gets,
transport_bio_tsg_ctrl,
transport_bio_tsg_new,
transport_bio_tsg_free,
NULL,
};
BIO_METHOD* BIO_s_tsg(void)
{
return &transport_bio_tsg_methods;
}

View File

@ -55,6 +55,7 @@ typedef enum _TSG_STATE TSG_STATE;
struct rdp_tsg
{
BIO* bio;
rdpRpc* rpc;
UINT16 Port;
RPC_PDU* pdu;
@ -317,4 +318,6 @@ BOOL tsg_set_blocking_mode(rdpTsg* tsg, BOOL blocking);
rdpTsg* tsg_new(rdpTransport* transport);
void tsg_free(rdpTsg* tsg);
BIO_METHOD* BIO_s_tsg(void);
#endif /* FREERDP_CORE_TSG_H */

View File

@ -149,7 +149,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
if (status != 0)
{
#ifdef _WIN32
WLog_ERR("bind() failed with error: %u", WSAGetLastError());
WLog_ERR(TAG, "bind() failed with error: %d", (int) WSAGetLastError());
WSACleanup();
#else
WLog_ERR(TAG, "bind");

View File

@ -394,7 +394,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->MultifragMaxRequestSize = 0xFFFF;
settings->GatewayUseSameCredentials = FALSE;
settings->GatewayBypassLocal = TRUE;
settings->GatewayBypassLocal = FALSE;
settings->FastPathInput = TRUE;
settings->FastPathOutput = TRUE;

View File

@ -87,8 +87,30 @@
/* Simple Socket BIO */
static int transport_bio_simple_new(BIO* bio);
static int transport_bio_simple_free(BIO* bio);
struct _WINPR_BIO_SIMPLE_SOCKET
{
BOOL win32;
SOCKET socket;
HANDLE hEvent;
};
typedef struct _WINPR_BIO_SIMPLE_SOCKET WINPR_BIO_SIMPLE_SOCKET;
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown);
static int transport_bio_simple_uninit(BIO* bio);
static void transport_bio_simple_check_reset_event(BIO* bio)
{
u_long nbytes = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (!ptr->win32)
return;
_ioctlsocket(ptr->socket, FIONREAD, &nbytes);
if (nbytes < 1)
WSAResetEvent(ptr->hEvent);
}
long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
{
@ -99,13 +121,14 @@ static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
{
int error;
int status = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (!buf)
return 0;
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
status = _send((SOCKET) bio->num, buf, size, 0);
status = _send(ptr->socket, buf, size, 0);
if (status <= 0)
{
@ -129,15 +152,20 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
{
int error;
int status = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (!buf)
return 0;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = _recv((SOCKET) bio->num, buf, size, 0);
status = _recv(ptr->socket, buf, size, 0);
if (status > 0)
{
transport_bio_simple_check_reset_event(bio);
return status;
}
if (status == 0)
{
@ -157,6 +185,8 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
transport_bio_simple_check_reset_event(bio);
return -1;
}
@ -173,17 +203,59 @@ static int transport_bio_simple_gets(BIO* bio, char* str, int size)
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
int status = -1;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (cmd == BIO_C_SET_SOCKET)
{
transport_bio_simple_uninit(bio);
transport_bio_simple_init(bio, (SOCKET) arg2, (int) arg1);
return 1;
}
else if (cmd == BIO_C_GET_SOCKET)
{
if (!bio->init || !arg2)
return 0;
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->socket;
return 1;
}
else if (cmd == BIO_C_GET_EVENT)
{
if (!bio->init || !arg2)
return 0;
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->hEvent;
return 1;
}
else if (cmd == BIO_C_SET_NONBLOCK)
{
#ifndef _WIN32
int flags;
flags = fcntl((int) ptr->socket, F_GETFL);
if (flags == -1)
return 0;
if (arg1)
fcntl((int) ptr->socket, F_SETFL, flags | O_NONBLOCK);
else
fcntl((int) ptr->socket, F_SETFL, flags & ~(O_NONBLOCK));
#else
/* the internal socket is always non-blocking */
#endif
return 1;
}
switch (cmd)
{
case BIO_C_SET_FD:
if (arg2)
{
transport_bio_simple_free(bio);
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->num = *((int*) arg2);
bio->shutdown = (int) arg1;
bio->init = 1;
transport_bio_simple_uninit(bio);
transport_bio_simple_init(bio, (SOCKET) *((int*) arg2), (int) arg1);
status = 1;
}
break;
@ -192,8 +264,8 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
if (bio->init)
{
if (arg2)
*((int*) arg2) = bio->num;
status = bio->num;
*((int*) arg2) = (int) ptr->socket;
status = (int) ptr->socket;
}
break;
@ -222,12 +294,81 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
return status;
}
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
{
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
ptr->socket = socket;
bio->shutdown = shutdown;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->init = 1;
if (ptr->win32)
{
ptr->hEvent = WSACreateEvent(); /* creates a manual reset event */
if (!ptr->hEvent)
return 0;
/* WSAEventSelect automatically sets the socket in non-blocking mode */
WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_CLOSE);
}
else
{
ptr->hEvent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, (int) ptr->socket);
if (!ptr->hEvent)
return 0;
}
return 1;
}
static int transport_bio_simple_uninit(BIO* bio)
{
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (bio->shutdown)
{
if (bio->init)
{
closesocket(ptr->socket);
ptr->socket = 0;
}
}
if (ptr->hEvent)
{
CloseHandle(ptr->hEvent);
ptr->hEvent = NULL;
}
bio->init = 0;
bio->flags = 0;
return 1;
}
static int transport_bio_simple_new(BIO* bio)
{
WINPR_BIO_SIMPLE_SOCKET* ptr;
bio->init = 0;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
ptr = (WINPR_BIO_SIMPLE_SOCKET*) calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
if (!ptr)
return 0;
bio->ptr = ptr;
#ifdef _WIN32
ptr->win32 = TRUE;
#endif
return 1;
}
@ -236,13 +377,12 @@ static int transport_bio_simple_free(BIO* bio)
if (!bio)
return 0;
if (bio->shutdown)
{
if (bio->init)
closesocket((SOCKET) bio->num);
transport_bio_simple_uninit(bio);
bio->init = 0;
bio->flags = 0;
if (bio->ptr)
{
free(bio->ptr);
bio->ptr = NULL;
}
return 1;
@ -931,7 +1071,7 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE);
}
SetEventFileDescriptor(tcp->event, tcp->sockfd);
BIO_get_event(tcp->socketBio, &tcp->event);
freerdp_tcp_get_ip_address(tcp);
freerdp_tcp_get_mac_address(tcp);
@ -994,49 +1134,7 @@ BOOL freerdp_tcp_disconnect(rdpTcp* tcp)
BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking)
{
#ifndef _WIN32
int flags;
flags = fcntl(tcp->sockfd, F_GETFL);
if (flags == -1)
{
WLog_ERR(TAG, "fcntl failed, %s.", strerror(errno));
return FALSE;
}
if (blocking == TRUE)
fcntl(tcp->sockfd, F_SETFL, flags & ~(O_NONBLOCK));
else
fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK);
#else
/**
* ioctlsocket function:
* msdn.microsoft.com/en-ca/library/windows/desktop/ms738573/
*
* The WSAAsyncSelect and WSAEventSelect functions automatically set a socket to nonblocking mode.
* If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use
* ioctlsocket to set the socket back to blocking mode will fail with WSAEINVAL.
*
* To set the socket back to blocking mode, an application must first disable WSAAsyncSelect
* by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect
* by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.
*/
if (blocking == TRUE)
{
if (tcp->event)
WSAEventSelect(tcp->sockfd, tcp->event, 0);
}
else
{
if (!tcp->event)
tcp->event = WSACreateEvent();
WSAEventSelect(tcp->sockfd, tcp->event, FD_READ);
}
#endif
return TRUE;
return BIO_set_nonblock(tcp->socketBio, blocking ? 0 : 1) ? TRUE : FALSE;
}
BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
@ -1102,13 +1200,12 @@ BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
{
tcp->sockfd = sockfd;
SetEventFileDescriptor(tcp->event, tcp->sockfd);
ringbuffer_commit_read_bytes(&tcp->xmitBuffer, ringbuffer_used(&tcp->xmitBuffer));
if (tcp->socketBio)
{
if (BIO_set_fd(tcp->socketBio, sockfd, 1) < 0)
if (BIO_set_fd(tcp->socketBio, sockfd, BIO_CLOSE) < 0)
return -1;
}
else
@ -1133,7 +1230,9 @@ int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
}
return 0;
BIO_get_event(tcp->socketBio, &tcp->event);
return 1;
}
HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp)
@ -1235,19 +1334,8 @@ rdpTcp* freerdp_tcp_new(rdpSettings* settings)
tcp->sockfd = -1;
tcp->settings = settings;
if (0)
goto out_ringbuffer; /* avoid unreferenced label warning on Windows */
#ifndef _WIN32
tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd);
if (!tcp->event || tcp->event == INVALID_HANDLE_VALUE)
goto out_ringbuffer;
#endif
return tcp;
out_ringbuffer:
ringbuffer_destroy(&tcp->xmitBuffer);
out_free:
free(tcp);
return NULL;
@ -1259,6 +1347,18 @@ void freerdp_tcp_free(rdpTcp* tcp)
return;
ringbuffer_destroy(&tcp->xmitBuffer);
CloseHandle(tcp->event);
if (tcp->socketBio)
{
BIO_free(tcp->socketBio);
tcp->socketBio = NULL;
}
if (tcp->bufferedBio)
{
BIO_free(tcp->bufferedBio);
tcp->bufferedBio = NULL;
}
free(tcp);
}

View File

@ -38,8 +38,19 @@
#define MSG_NOSIGNAL 0
#endif
#define BIO_TYPE_SIMPLE 66
#define BIO_TYPE_BUFFERED 67
#define BIO_TYPE_TSG 65
#define BIO_TYPE_SIMPLE 66
#define BIO_TYPE_BUFFERED 67
#define BIO_C_SET_SOCKET 1101
#define BIO_C_GET_SOCKET 1102
#define BIO_C_GET_EVENT 1103
#define BIO_C_SET_NONBLOCK 1104
#define BIO_set_socket(b, s, c) BIO_ctrl(b, BIO_C_SET_SOCKET, c, s);
#define BIO_get_socket(b, c) BIO_ctrl(b, BIO_C_GET_SOCKET, 0, (char*) c)
#define BIO_get_event(b, c) BIO_ctrl(b, BIO_C_GET_EVENT, 0, (char*) c)
#define BIO_set_nonblock(b, c) BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL)
typedef struct rdp_tcp rdpTcp;

View File

@ -103,12 +103,6 @@ BOOL transport_disconnect(rdpTransport* transport)
transport_stop(transport);
if (transport->frontBio)
{
BIO_free_all(transport->frontBio);
transport->frontBio = NULL;
}
if (transport->TlsIn)
tls_free(transport->TlsIn);
@ -145,114 +139,6 @@ BOOL transport_connect_rdp(rdpTransport* transport)
return TRUE;
}
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
{
return 1;
}
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
status = tsg_write(tsg, (BYTE*) buf, num);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_WRITE);
}
return status >= 0 ? status : -1;
}
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = tsg_read(tsg, (BYTE*) buf, size);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_READ);
}
return status > 0 ? status : -1;
}
static int transport_bio_tsg_puts(BIO* bio, const char* str)
{
return 1;
}
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
{
return 1;
}
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
if (cmd == BIO_CTRL_FLUSH)
{
return 1;
}
return 0;
}
static int transport_bio_tsg_new(BIO* bio)
{
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
return 1;
}
static int transport_bio_tsg_free(BIO* bio)
{
return 1;
}
#define BIO_TYPE_TSG 65
static BIO_METHOD transport_bio_tsg_methods =
{
BIO_TYPE_TSG,
"TSGateway",
transport_bio_tsg_write,
transport_bio_tsg_read,
transport_bio_tsg_puts,
transport_bio_tsg_gets,
transport_bio_tsg_ctrl,
transport_bio_tsg_new,
transport_bio_tsg_free,
NULL,
};
BIO_METHOD* BIO_s_tsg(void)
{
return &transport_bio_tsg_methods;
}
BOOL transport_connect_tls(rdpTransport* transport)
{
rdpSettings* settings = transport->settings;
@ -391,8 +277,10 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
freerdp* instance;
rdpContext* context;
rdpSettings* settings = transport->settings;
instance = (freerdp*) transport->settings->instance;
context = instance->context;
tsg = tsg_new(transport);
if (!tsg)
@ -424,6 +312,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
transport->TlsIn->hostname = transport->TlsOut->hostname = settings->GatewayHostname;
transport->TlsIn->port = transport->TlsOut->port = settings->GatewayPort;
transport->TlsIn->isGatewayTransport = TRUE;
tls_status = tls_connect(transport->TlsIn, transport->TcpIn->bufferedBio);
@ -465,8 +354,8 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
if (!tsg_connect(tsg, hostname, port))
return FALSE;
transport->frontBio = BIO_new(BIO_s_tsg());
transport->frontBio->ptr = tsg;
transport->frontBio = tsg->bio;
return TRUE;
}
@ -509,7 +398,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
{
transport->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
transport->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
}
}
@ -838,7 +727,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
#endif
if (Stream_GetPosition(s) >= pduLength)
WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
Stream_SealLength(s);
Stream_SetPosition(s, 0);
@ -866,7 +755,7 @@ int transport_write(rdpTransport* transport, wStream* s)
if (length > 0)
{
WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
}
while (length > 0)
@ -1138,20 +1027,23 @@ static void* transport_client_thread(void* arg)
rdpTransport* transport = (rdpTransport*) arg;
rdpContext* context = transport->context;
freerdp* instance = context->instance;
WLog_Print(transport->log, WLOG_DEBUG, "Starting transport thread");
WLog_DBG(TAG, "Starting transport thread");
nCount = 0;
handles[nCount++] = transport->stopEvent;
handles[nCount++] = transport->connectedEvent;
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
{
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
WLog_DBG(TAG, "Terminating transport thread");
ExitThread(0);
return NULL;
}
WLog_Print(transport->log, WLOG_DEBUG, "Asynchronous transport activated");
WLog_DBG(TAG, "Asynchronous transport activated");
while (1)
{
@ -1177,7 +1069,7 @@ static void* transport_client_thread(void* arg)
}
}
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
WLog_DBG(TAG, "Terminating transport thread");
ExitThread(0);
return NULL;
}
@ -1185,6 +1077,7 @@ static void* transport_client_thread(void* arg)
rdpTransport* transport_new(rdpContext* context)
{
rdpTransport* transport;
transport = (rdpTransport*) calloc(1, sizeof(rdpTransport));
if (!transport)
@ -1192,11 +1085,6 @@ rdpTransport* transport_new(rdpContext* context)
transport->context = context;
transport->settings = context->settings;
WLog_Init();
transport->log = WLog_Get(TAG);
if (!transport->log)
goto out_free;
transport->TcpIn = freerdp_tcp_new(context->settings);

View File

@ -55,7 +55,7 @@ typedef int (*TransportRecv) (rdpTransport* transport, wStream* stream, void* ex
struct rdp_transport
{
TRANSPORT_LAYER layer;
BIO *frontBio;
BIO* frontBio;
rdpTsg* tsg;
rdpTcp* TcpIn;
rdpTcp* TcpOut;
@ -82,7 +82,6 @@ struct rdp_transport
BOOL GatewayEnabled;
CRITICAL_SECTION ReadLock;
CRITICAL_SECTION WriteLock;
wLog* log;
void* rdp;
};

View File

@ -74,9 +74,15 @@ PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize);
#include <netinet/tcp.h>
#include <net/if.h>
#include <winpr/io.h>
#include <winpr/error.h>
#include <winpr/platform.h>
#define WSAEVENT HANDLE
#define LPWSAEVENT LPHANDLE
#define WSAOVERLAPPED OVERLAPPED
typedef OVERLAPPED* LPWSAOVERLAPPED;
typedef UINT_PTR SOCKET;
typedef struct sockaddr_storage SOCKADDR_STORAGE;
@ -87,6 +93,39 @@ typedef struct sockaddr_storage SOCKADDR_STORAGE;
#define WSADESCRIPTION_LEN 256
#define WSASYS_STATUS_LEN 128
#define FD_READ_BIT 0
#define FD_READ (1 << FD_READ_BIT)
#define FD_WRITE_BIT 1
#define FD_WRITE (1 << FD_WRITE_BIT)
#define FD_OOB_BIT 2
#define FD_OOB (1 << FD_OOB_BIT)
#define FD_ACCEPT_BIT 3
#define FD_ACCEPT (1 << FD_ACCEPT_BIT)
#define FD_CONNECT_BIT 4
#define FD_CONNECT (1 << FD_CONNECT_BIT)
#define FD_CLOSE_BIT 5
#define FD_CLOSE (1 << FD_CLOSE_BIT)
#define FD_QOS_BIT 6
#define FD_QOS (1 << FD_QOS_BIT)
#define FD_GROUP_QOS_BIT 7
#define FD_GROUP_QOS (1 << FD_GROUP_QOS_BIT)
#define FD_ROUTING_INTERFACE_CHANGE_BIT 8
#define FD_ROUTING_INTERFACE_CHANGE (1 << FD_ROUTING_INTERFACE_CHANGE_BIT)
#define FD_ADDRESS_LIST_CHANGE_BIT 9
#define FD_ADDRESS_LIST_CHANGE (1 << FD_ADDRESS_LIST_CHANGE_BIT)
#define FD_MAX_EVENTS 10
#define FD_ALL_EVENTS ((1 << FD_MAX_EVENTS) - 1)
#define SD_RECEIVE 0
#define SD_SEND 1
#define SD_BOTH 2
@ -126,6 +165,16 @@ WINPR_API int WSACleanup(void);
WINPR_API void WSASetLastError(int iError);
WINPR_API int WSAGetLastError(void);
WINPR_API HANDLE WSACreateEvent(void);
WINPR_API BOOL WSASetEvent(HANDLE hEvent);
WINPR_API BOOL WSAResetEvent(HANDLE hEvent);
WINPR_API BOOL WSACloseEvent(HANDLE hEvent);
WINPR_API int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents);
WINPR_API DWORD WSAWaitForMultipleEvents(DWORD cEvents,
const HANDLE* lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable);
WINPR_API SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen);
WINPR_API int _bind(SOCKET s, const struct sockaddr* addr, int namelen);
WINPR_API int closesocket(SOCKET s);

View File

@ -28,7 +28,6 @@ endif()
set(${MODULE_PREFIX}_SRCS
smartcard.c
smartcard.h
smartcard_link.c
smartcard_pcsc.c
smartcard_pcsc.h
smartcard_inspect.c

View File

@ -1,202 +0,0 @@
/**
* WinPR: Windows Portable Runtime
* Smart Card API
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef _WIN32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DISABLE_PCSC_WINPR
/**
* PCSC-WinPR (optional for Mac OS X):
*
* PCSC-WinPR is a static build of libpcsclite with
* minor modifications meant to avoid an ABI conflict.
*
* At this point, it is only a work in progress, as I was not
* yet able to make it work properly. However, if we could make it
* work, we might be able to build against a version of pcsc-lite
* that doesn't have issues present in Apple's SmartCard Services.
*
* Patch pcsc-lite/src/PCSC/wintypes.h:
* Change "unsigned long" to "unsigned int" for
*
* typedef unsigned int ULONG;
* typedef unsigned int DWORD;
*
* This is important as ULONG and DWORD are supposed to be 32-bit,
* but unsigned long on 64-bit OS X is 64-bit, not 32-bit.
* More importantly, Apple's SmartCard Services uses unsigned int,
* while vanilla pcsc-lite still uses unsigned long.
*
* Patch pcsc-lite/src/PCSC/pcsclite.h.in:
*
* Add the WinPR_PCSC_* definitions that follow "#define WinPR_PCSC"
* in this source file at the beginning of the pcsclite.h.in.
*
* Change "unsigned long" to "unsigned int" in the definition
* of the SCARD_IO_REQUEST structure:
*
* unsigned int dwProtocol;
* unsigned int cbPciLength;
*
* Configure pcsc-lite with the following options (Mac OS X):
*
* ./configure --enable-static --prefix=/usr --program-suffix=winpr
* --enable-usbdropdir=/usr/libexec/SmartCardServices/drivers
* --enable-confdir=/etc --enable-ipcdir=/var/run
*
* Build pcsc-lite, and then copy libpcsclite.a to libpcsc-winpr.a:
*
* make
* cp ./src/.libs/libpcsclite.a libpcsc-winpr.a
*
* Validate that libpcsc-winpr.a has a modified ABI:
*
* nm libpcsc-winpr.a | grep " T " | grep WinPR
*
* If the ABI has been successfully modified, you should
* see pcsc-lite functions prefixed with "WinPR_PCSC_".
*
* You can keep this custom pcsc-lite build for later.
* To install the library, copy it to /usr/lib or /usr/local/lib.
*
* The FreeRDP build system will then automatically pick it up
* as long as it is present on the system. To ensure PCSC-WinPR
* is properly detected at cmake generation time, look for the
* following debug output:
*
* -- Found PCSC-WinPR: /usr/lib/libpcsc-winpr.a
*/
#if 0
#define WinPR_PCSC
#define SCardEstablishContext WinPR_PCSC_SCardEstablishContext
#define SCardReleaseContext WinPR_PCSC_SCardReleaseContext
#define SCardIsValidContext WinPR_PCSC_SCardIsValidContext
#define SCardConnect WinPR_PCSC_SCardConnect
#define SCardReconnect WinPR_PCSC_SCardReconnect
#define SCardDisconnect WinPR_PCSC_SCardDisconnect
#define SCardBeginTransaction WinPR_PCSC_SCardBeginTransaction
#define SCardEndTransaction WinPR_PCSC_SCardEndTransaction
#define SCardStatus WinPR_PCSC_SCardStatus
#define SCardGetStatusChange WinPR_PCSC_SCardGetStatusChange
#define SCardControl WinPR_PCSC_SCardControl
#define SCardTransmit WinPR_PCSC_SCardTransmit
#define SCardListReaderGroups WinPR_PCSC_SCardListReaderGroups
#define SCardListReaders WinPR_PCSC_SCardListReaders
#define SCardFreeMemory WinPR_PCSC_SCardFreeMemory
#define SCardCancel WinPR_PCSC_SCardCancel
#define SCardGetAttrib WinPR_PCSC_SCardGetAttrib
#define SCardSetAttrib WinPR_PCSC_SCardSetAttrib
#define g_rgSCardT0Pci WinPR_PCSC_g_rgSCardT0Pci
#define g_rgSCardT1Pci WinPR_PCSC_g_rgSCardT1Pci
#define g_rgSCardRawPci WinPR_PCSC_g_rgSCardRawPci
#endif
#ifdef WITH_WINPR_PCSC
extern void* WinPR_PCSC_SCardEstablishContext();
extern void* WinPR_PCSC_SCardReleaseContext();
extern void* WinPR_PCSC_SCardIsValidContext();
extern void* WinPR_PCSC_SCardConnect();
extern void* WinPR_PCSC_SCardReconnect();
extern void* WinPR_PCSC_SCardDisconnect();
extern void* WinPR_PCSC_SCardBeginTransaction();
extern void* WinPR_PCSC_SCardEndTransaction();
extern void* WinPR_PCSC_SCardStatus();
extern void* WinPR_PCSC_SCardGetStatusChange();
extern void* WinPR_PCSC_SCardControl();
extern void* WinPR_PCSC_SCardTransmit();
extern void* WinPR_PCSC_SCardListReaderGroups();
extern void* WinPR_PCSC_SCardListReaders();
extern void* WinPR_PCSC_SCardFreeMemory();
extern void* WinPR_PCSC_SCardCancel();
extern void* WinPR_PCSC_SCardGetAttrib();
extern void* WinPR_PCSC_SCardSetAttrib();
#endif
struct _PCSCFunctionTable
{
void* pfnSCardEstablishContext;
void* pfnSCardReleaseContext;
void* pfnSCardIsValidContext;
void* pfnSCardConnect;
void* pfnSCardReconnect;
void* pfnSCardDisconnect;
void* pfnSCardBeginTransaction;
void* pfnSCardEndTransaction;
void* pfnSCardStatus;
void* pfnSCardGetStatusChange;
void* pfnSCardControl;
void* pfnSCardTransmit;
void* pfnSCardListReaderGroups;
void* pfnSCardListReaders;
void* pfnSCardFreeMemory;
void* pfnSCardCancel;
void* pfnSCardGetAttrib;
void* pfnSCardSetAttrib;
};
typedef struct _PCSCFunctionTable PCSCFunctionTable;
PCSCFunctionTable g_PCSC_Link = { 0 };
int PCSC_InitializeSCardApi_Link(void)
{
int status = -1;
#ifdef DISABLE_PCSC_WINPR
return -1;
#endif
#ifdef WITH_WINPR_PCSC
g_PCSC_Link.pfnSCardEstablishContext = (void*) WinPR_PCSC_SCardEstablishContext;
g_PCSC_Link.pfnSCardReleaseContext = (void*) WinPR_PCSC_SCardReleaseContext;
g_PCSC_Link.pfnSCardIsValidContext = (void*) WinPR_PCSC_SCardIsValidContext;
g_PCSC_Link.pfnSCardConnect = (void*) WinPR_PCSC_SCardConnect;
g_PCSC_Link.pfnSCardReconnect = (void*) WinPR_PCSC_SCardReconnect;
g_PCSC_Link.pfnSCardDisconnect = (void*) WinPR_PCSC_SCardDisconnect;
g_PCSC_Link.pfnSCardBeginTransaction = (void*) WinPR_PCSC_SCardBeginTransaction;
g_PCSC_Link.pfnSCardEndTransaction = (void*) WinPR_PCSC_SCardEndTransaction;
g_PCSC_Link.pfnSCardStatus = (void*) WinPR_PCSC_SCardStatus;
g_PCSC_Link.pfnSCardGetStatusChange = (void*) WinPR_PCSC_SCardGetStatusChange;
g_PCSC_Link.pfnSCardControl = (void*) WinPR_PCSC_SCardControl;
g_PCSC_Link.pfnSCardTransmit = (void*) WinPR_PCSC_SCardTransmit;
g_PCSC_Link.pfnSCardListReaderGroups = (void*) WinPR_PCSC_SCardListReaderGroups;
g_PCSC_Link.pfnSCardListReaders = (void*) WinPR_PCSC_SCardListReaders;
//g_PCSC_Link.pfnSCardFreeMemory = (void*) WinPR_PCSC_SCardFreeMemory;
g_PCSC_Link.pfnSCardFreeMemory = (void*) NULL;
g_PCSC_Link.pfnSCardCancel = (void*) WinPR_PCSC_SCardCancel;
g_PCSC_Link.pfnSCardGetAttrib = (void*) WinPR_PCSC_SCardGetAttrib;
g_PCSC_Link.pfnSCardSetAttrib = (void*) WinPR_PCSC_SCardSetAttrib;
status = 1;
#endif
return status;
}
#endif

View File

@ -111,22 +111,24 @@
//#define DISABLE_PCSC_SCARD_AUTOALLOCATE
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
struct _PCSC_SCARDCONTEXT
{
SCARDHANDLE owner;
CRITICAL_SECTION lock;
SCARDCONTEXT hContext;
DWORD dwCardHandleCount;
BOOL isTransactionLocked;
};
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
struct _PCSC_SCARDHANDLE
{
CRITICAL_SECTION lock;
BOOL shared;
SCARDCONTEXT hSharedContext;
SCARDCONTEXT hPrivateContext;
};
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
struct _PCSC_READER
{
@ -143,6 +145,7 @@ static int g_StartedEventRefCount = 0;
static BOOL g_SCardAutoAllocate = FALSE;
static BOOL g_PnP_Notification = TRUE;
#ifdef __MACOSX__
static unsigned int OSXVersion = 0;
#endif
@ -425,6 +428,117 @@ SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
return pCard->hPrivateContext;
}
BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
{
BOOL status = TRUE;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_SCARDCONTEXT* pContext = NULL;
if (!hCard)
{
/* SCardConnect */
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
return FALSE;
if (!pContext->owner)
return TRUE;
/* wait for card ownership */
return TRUE;
}
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return FALSE;
shared = pCard->shared;
hContext = pCard->hSharedContext;
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
return FALSE;
if (!pContext->owner)
{
/* card is not owned */
if (!shared)
pContext->owner = hCard;
return TRUE;
}
if (pContext->owner == hCard)
{
/* already card owner */
}
else
{
/* wait for card ownership */
}
return status;
}
BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_SCARDCONTEXT* pContext = NULL;
if (!hCard)
{
/* release current owner */
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
return FALSE;
hCard = pContext->owner;
if (!hCard)
return TRUE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return FALSE;
/* release card ownership */
pContext->owner = 0;
return TRUE;
}
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return FALSE;
hContext = pCard->hSharedContext;
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
return FALSE;
if (pContext->owner == hCard)
{
/* release card ownership */
pContext->owner = 0;
}
return TRUE;
}
PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTEXT hPrivateContext, SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
@ -444,13 +558,13 @@ PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTE
pCard->hSharedContext = hSharedContext;
pCard->hPrivateContext = hPrivateContext;
InitializeCriticalSectionAndSpinCount(&(pCard->lock), 4000);
pContext->dwCardHandleCount++;
if (!g_CardHandles)
g_CardHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_CardHandles, (void*) hCard, (void*) pCard);
return pCard;
}
@ -458,12 +572,12 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
PCSC_SCARDCONTEXT* pContext;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return;
DeleteCriticalSection(&(pCard->lock));
pContext = PCSC_GetCardContextData(pCard->hSharedContext);
PCSC_SCardReleaseContext_Internal(pCard->hPrivateContext);
free(pCard);
@ -482,68 +596,6 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
pContext->dwCardHandleCount--;
}
BOOL PCSC_LockCardHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
WLog_ERR(TAG, "PCSC_LockCardHandle: invalid handle (%p)", (void*) hCard);
return FALSE;
}
EnterCriticalSection(&(pCard->lock));
return TRUE;
}
BOOL PCSC_UnlockCardHandle(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
WLog_ERR(TAG, "PCSC_UnlockCardHandle: invalid handle (%p)", (void*) hCard);
return FALSE;
}
LeaveCriticalSection(&(pCard->lock));
return TRUE;
}
BOOL PCSC_LockCardTransaction(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
return TRUE; /* disable for now because it deadlocks */
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
WLog_ERR(TAG, "PCSC_LockCardTransaction: invalid handle (%p)", (void*) hCard);
return FALSE;
}
EnterCriticalSection(&(pCard->lock));
return TRUE;
}
BOOL PCSC_UnlockCardTransaction(SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
return TRUE; /* disable for now because it deadlocks */
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
{
WLog_ERR(TAG, "PCSC_UnlockCardTransaction: invalid handle (%p)", (void*) hCard);
return FALSE;
}
LeaveCriticalSection(&(pCard->lock));
return TRUE;
}
char* PCSC_GetReaderNameFromAlias(char* nameWinSCard)
{
int index;
@ -1605,8 +1657,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
BOOL shared;
BOOL access;
char* szReaderPCSC;
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
SCARDCONTEXT hPrivateContext = 0;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
@ -1615,6 +1670,10 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
if (!g_PCSC.pfnSCardConnect)
return SCARD_E_NO_SERVICE;
shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
access = PCSC_WaitForCardAccess(hContext, 0, shared);
status = PCSC_SCardEstablishContext_Internal(SCARD_SCOPE_SYSTEM, NULL, NULL, &hPrivateContext);
if (status != SCARD_S_SUCCESS)
@ -1642,8 +1701,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
if (status == SCARD_S_SUCCESS)
{
PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
pCard = PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
pCard->shared = shared;
PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
}
else
{
@ -1697,6 +1759,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
{
BOOL shared;
BOOL access;
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
@ -1706,11 +1770,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
if (!g_PCSC.pfnSCardReconnect)
return SCARD_E_NO_SERVICE;
shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
access = PCSC_WaitForCardAccess(0, hCard, shared);
pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
status = (LONG) g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode,
pcsc_dwPreferredProtocols, pcsc_dwInitialization, &pcsc_dwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
return status;
}
@ -1730,6 +1799,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposit
PCSC_DisconnectCardHandle(hCard);
}
PCSC_ReleaseCardAccess(0, hCard);
return status;
}
@ -1785,6 +1856,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisp
if (!pContext)
return SCARD_E_INVALID_HANDLE;
PCSC_ReleaseCardAccess(0, hCard);
if (!pContext->isTransactionLocked)
return SCARD_S_SUCCESS; /* disable nested transactions */
@ -1795,21 +1868,23 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisp
}
pContext->isTransactionLocked = FALSE;
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
{
return 0;
return SCARD_S_SUCCESS;
}
WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
PCSC_DWORD cchReaderLen;
SCARDCONTEXT hContext = 0;
LPSTR mszReaderNames = NULL;
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwState = 0;
PCSC_DWORD pcsc_dwProtocol = 0;
PCSC_DWORD pcsc_cbAtrLen = (PCSC_DWORD) *pcbAtrLen;
@ -1817,6 +1892,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
if (!g_PCSC.pfnSCardStatus)
return SCARD_E_NO_SERVICE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
@ -1824,7 +1906,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
cchReaderLen = SCARD_AUTOALLOCATE;
status = (LONG) g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
if (mszReaderNames)
@ -1833,6 +1915,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
*pdwState = (DWORD) pcsc_dwState;
*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
return status;
}
@ -1847,6 +1930,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
LPBYTE* pPbAtr = (LPBYTE*) pbAtr;
LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames;
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_cchReaderLen = 0;
PCSC_DWORD pcsc_dwState = 0;
PCSC_DWORD pcsc_dwProtocol = 0;
@ -1855,6 +1939,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
if (!g_PCSC.pfnSCardStatus)
return SCARD_E_NO_SERVICE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext || !pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen)
@ -1879,9 +1970,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
pcsc_cbAtrLen = 0;
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
(pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol,
(pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
(pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol,
(pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
@ -1909,9 +2000,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
}
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
*pMszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol,
pbAtr, &pcsc_cbAtrLen);
*pMszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol,
pbAtr, &pcsc_cbAtrLen);
if (status != SCARD_S_SUCCESS)
{
@ -1940,7 +2031,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
else
{
status = (LONG) g_PCSC.pfnSCardStatus(hCard, mszReaderNames, &pcsc_cchReaderLen,
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
}
status = PCSC_MapErrorCodeToWinSCard(status);
@ -2003,6 +2094,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD cbExtraBytes = 0;
BYTE* pbExtraBytes = NULL;
BYTE* pcsc_pbExtraBytes = NULL;
@ -2014,6 +2106,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
if (!g_PCSC.pfnSCardTransmit)
return SCARD_E_NO_SERVICE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
if (!pcbRecvLength)
return SCARD_E_INVALID_PARAMETER;
@ -2094,7 +2193,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
{
return 0;
PCSC_SCARDHANDLE* pCard = NULL;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
return SCARD_S_SUCCESS;
}
WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
@ -2107,6 +2215,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
DWORD IoCtlDeviceType = 0;
BOOL getFeatureRequest = FALSE;
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwControlCode = 0;
PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD) cbInBufferSize;
PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD) cbOutBufferSize;
@ -2115,6 +2224,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
if (!g_PCSC.pfnSCardControl)
return SCARD_E_NO_SERVICE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
/**
* PCSCv2 Part 10:
* http://www.pcscworkgroup.com/specifications/files/pcsc10_v2.02.09.pdf
@ -2173,12 +2289,20 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dw
BOOL pcbAttrLenAlloc = FALSE;
LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
PCSC_DWORD pcsc_cbAttrLen = 0;
if (!g_PCSC.pfnSCardGetAttrib)
return SCARD_E_NO_SERVICE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
@ -2516,14 +2640,23 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L
WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
{
LONG status = SCARD_S_SUCCESS;
PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD) cbAttrLen;
if (!g_PCSC.pfnSCardSetAttrib)
return SCARD_E_NO_SERVICE;
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return SCARD_E_INVALID_VALUE;
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
status = (LONG) g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
@ -2806,48 +2939,37 @@ PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void)
return &PCSC_SCardApiFunctionTable;
}
extern PCSCFunctionTable g_PCSC_Link;
extern int PCSC_InitializeSCardApi_Link(void);
int PCSC_InitializeSCardApi(void)
{
/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
#ifndef DISABLE_PCSC_LINK
DWORD nSize;
char* env = NULL;
if (PCSC_InitializeSCardApi_Link() >= 0)
nSize = GetEnvironmentVariableA("WINPR_WINSCARD_LOCK_TRANSACTIONS", NULL, 0);
if (nSize)
{
g_PCSC.pfnSCardEstablishContext = g_PCSC_Link.pfnSCardEstablishContext;
g_PCSC.pfnSCardReleaseContext = g_PCSC_Link.pfnSCardReleaseContext;
g_PCSC.pfnSCardIsValidContext = g_PCSC_Link.pfnSCardIsValidContext;
g_PCSC.pfnSCardConnect = g_PCSC_Link.pfnSCardConnect;
g_PCSC.pfnSCardReconnect = g_PCSC_Link.pfnSCardReconnect;
g_PCSC.pfnSCardDisconnect = g_PCSC_Link.pfnSCardDisconnect;
g_PCSC.pfnSCardBeginTransaction = g_PCSC_Link.pfnSCardBeginTransaction;
g_PCSC.pfnSCardEndTransaction = g_PCSC_Link.pfnSCardEndTransaction;
g_PCSC.pfnSCardStatus = g_PCSC_Link.pfnSCardStatus;
g_PCSC.pfnSCardGetStatusChange = g_PCSC_Link.pfnSCardGetStatusChange;
g_PCSC.pfnSCardControl = g_PCSC_Link.pfnSCardControl;
g_PCSC.pfnSCardTransmit = g_PCSC_Link.pfnSCardTransmit;
g_PCSC.pfnSCardListReaderGroups = g_PCSC_Link.pfnSCardListReaderGroups;
g_PCSC.pfnSCardListReaders = g_PCSC_Link.pfnSCardListReaders;
g_PCSC.pfnSCardFreeMemory = g_PCSC_Link.pfnSCardFreeMemory;
g_PCSC.pfnSCardCancel = g_PCSC_Link.pfnSCardCancel;
g_PCSC.pfnSCardGetAttrib = g_PCSC_Link.pfnSCardGetAttrib;
g_PCSC.pfnSCardSetAttrib = g_PCSC_Link.pfnSCardSetAttrib;
return 1;
env = (LPSTR) malloc(nSize);
nSize = GetEnvironmentVariableA("WINPR_WINSCARD_LOCK_TRANSACTIONS", env, nSize);
if (strcmp(env, "1") == 0)
g_LockTransactions = TRUE;
else if (strcmp(env, "0") == 0)
g_LockTransactions = FALSE;
free(env);
}
#endif
/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
#ifdef __MACOSX__
g_PCSCModule = LoadLibraryA("/System/Library/Frameworks/PCSC.framework/PCSC");
OSXVersion = determineMacOSXVersion();
OSXVersion = determineMacOSXVersion();
#else
g_PCSCModule = LoadLibraryA("libpcsclite.so.1");
if (!g_PCSCModule)
g_PCSCModule = LoadLibraryA("libpcsclite.so");
#endif
if (!g_PCSCModule)
@ -2863,6 +2985,7 @@ int PCSC_InitializeSCardApi(void)
g_PCSC.pfnSCardEndTransaction = (void*) GetProcAddress(g_PCSCModule, "SCardEndTransaction");
g_PCSC.pfnSCardStatus = (void*) GetProcAddress(g_PCSCModule, "SCardStatus");
g_PCSC.pfnSCardGetStatusChange = (void*) GetProcAddress(g_PCSCModule, "SCardGetStatusChange");
#ifdef __MACOSX__
if (OSXVersion >= 0x10050600)
g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl132");
@ -2871,12 +2994,14 @@ int PCSC_InitializeSCardApi(void)
#else
g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl");
#endif
g_PCSC.pfnSCardTransmit = (void*) GetProcAddress(g_PCSCModule, "SCardTransmit");
g_PCSC.pfnSCardListReaderGroups = (void*) GetProcAddress(g_PCSCModule, "SCardListReaderGroups");
g_PCSC.pfnSCardListReaders = (void*) GetProcAddress(g_PCSCModule, "SCardListReaders");
g_PCSC.pfnSCardCancel = (void*) GetProcAddress(g_PCSCModule, "SCardCancel");
g_PCSC.pfnSCardGetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardGetAttrib");
g_PCSC.pfnSCardSetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardSetAttrib");
g_PCSC.pfnSCardFreeMemory = NULL;
#ifndef __APPLE__
g_PCSC.pfnSCardFreeMemory = (void*) GetProcAddress(g_PCSCModule, "SCardFreeMemory");
@ -2889,9 +3014,11 @@ int PCSC_InitializeSCardApi(void)
g_PCSC.pfnSCardFreeMemory = NULL;
g_SCardAutoAllocate = FALSE;
#endif
#ifdef __APPLE__
g_PnP_Notification = FALSE;
#endif
return 1;
}

View File

@ -740,9 +740,7 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
{
WLog_ERR(TAG, "[ERROR] %s: Function not implemented.");
assert(0);
return 0;
return WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);
}
DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)

View File

@ -36,8 +36,10 @@
#endif
#if defined(_WIN32) || defined(_WIN64)
#include <io.h>
#include <Windows.h>
#include <Dbghelp.h>
#define write _write
#endif
#include <winpr/crt.h>
@ -421,16 +423,18 @@ void winpr_backtrace_symbols_fd(void *buffer, int fd)
assert(data);
backtrace_symbols_fd(data->buffer, data->used, fd);
#elif defined(_WIN32) || defined(_WIN64) || defined(ANDROID)
{
size_t used;
char **lines = winpr_backtrace_symbols(buffer, &used);
{
DWORD i;
size_t used;
char** lines;
lines = winpr_backtrace_symbols(buffer, &used);
if (lines)
{
DWORD i;
for (i=0; i<used; i++)
write(fd, lines[i], strlen(lines[i]));
}
if (lines)
{
for (i = 0; i < used; i++)
write(fd, lines[i], strlen(lines[i]));
}
}
#else
LOGF(support_msg);

View File

@ -65,7 +65,6 @@ void winpr_HexDump(const char* tag, int level, const BYTE* data, int length)
pos += trio_snprintf(&buffer[pos], blen - pos, "%c",
(p[i] >= 0x20 && p[i] < 0x7F) ? p[i] : '.');
pos += trio_snprintf(&buffer[pos], blen - pos, "\n");
WLog_LVL(tag, level, "%s", buffer);
offset += line;
p += line;

View File

@ -22,6 +22,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/winsock.h>
@ -596,6 +597,43 @@ int WSAGetLastError(void)
return iError;
}
HANDLE WSACreateEvent(void)
{
return CreateEvent(NULL, TRUE, FALSE, NULL);
}
BOOL WSASetEvent(HANDLE hEvent)
{
return SetEvent(hEvent);
}
BOOL WSAResetEvent(HANDLE hEvent)
{
return ResetEvent(hEvent);
}
BOOL WSACloseEvent(HANDLE hEvent)
{
BOOL status;
status = CloseHandle(hEvent);
if (!status)
SetLastError(6);
return status;
}
int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents)
{
return 0;
}
DWORD WSAWaitForMultipleEvents(DWORD cEvents, const HANDLE* lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable)
{
return WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
}
SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
{
int status;