mirror of https://github.com/neutrinolabs/xrdp
Update smartcard code to use new UTF-8 calls
This commit is contained in:
parent
1b286a0469
commit
d722ffe357
|
@ -34,10 +34,6 @@
|
|||
* Section 14 : Describes the NDR
|
||||
*/
|
||||
|
||||
/*
|
||||
* smartcard redirection support
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
@ -1094,6 +1090,17 @@ scard_send_IsContextValid(IRP *irp, char *context, int context_bytes)
|
|||
free_stream(s);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
align_s(struct stream *s, unsigned int boundary)
|
||||
{
|
||||
unsigned int over = (unsigned int)(s->p - s->data) % boundary;
|
||||
if (over != 0)
|
||||
{
|
||||
out_uint8s(s, boundary - over);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
@ -1144,13 +1151,10 @@ scard_send_ListReaders(IRP *irp, char *context, int context_bytes,
|
|||
SMARTCARD *sc;
|
||||
struct stream *s;
|
||||
int bytes;
|
||||
int bytes_groups; // Length of NDR for groups + 2 terminators
|
||||
int val; // Referent Id for mszGroups (assume NULL)
|
||||
int index;
|
||||
int num_chars;
|
||||
int bytes_groups = 0; // Length of NDR for groups + 2 terminators
|
||||
int val = 0; // Referent Id for mszGroups (assume NULL)
|
||||
int groups_len = 0; // strlen(groups)
|
||||
tui32 ioctl;
|
||||
twchar w_groups[100];
|
||||
|
||||
|
||||
if ((sc = smartcards[irp->scard_index]) == NULL)
|
||||
{
|
||||
|
@ -1167,18 +1171,18 @@ scard_send_ListReaders(IRP *irp, char *context, int context_bytes,
|
|||
return;
|
||||
}
|
||||
|
||||
num_chars = 0;
|
||||
bytes_groups = 0;
|
||||
w_groups[0] = 0;
|
||||
val = 0;
|
||||
if (groups != 0)
|
||||
if (groups != NULL && *groups != '\0')
|
||||
{
|
||||
if (groups[0] != 0)
|
||||
groups_len = g_strlen(groups);
|
||||
if (wide)
|
||||
{
|
||||
num_chars = g_mbstowcs(w_groups, groups, 99);
|
||||
bytes_groups = wide ? (num_chars + 2) * 2 : num_chars + 2;
|
||||
val = 0x00020004;
|
||||
bytes_groups = (utf8_as_utf16_word_count(groups, groups_len) + 2) * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_groups = groups_len + 2;
|
||||
}
|
||||
val = 0x00020004;
|
||||
}
|
||||
|
||||
s_push_layer(s, mcs_hdr, 4); /* bytes, set later */
|
||||
|
@ -1204,25 +1208,19 @@ scard_send_ListReaders(IRP *irp, char *context, int context_bytes,
|
|||
// mszGroups is also a Uni-dimensional conformant array of bytes
|
||||
if (bytes_groups > 0)
|
||||
{
|
||||
align_s(s, 4);
|
||||
out_uint32_le(s, bytes_groups);
|
||||
if (wide)
|
||||
{
|
||||
out_uint32_le(s, bytes_groups);
|
||||
for (index = 0; index < num_chars; index++)
|
||||
{
|
||||
out_uint16_le(s, w_groups[index]);
|
||||
}
|
||||
out_utf8_as_utf16_le(s, groups, groups_len);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint32_le(s, bytes_groups);
|
||||
for (index = 0; index < num_chars; index++)
|
||||
{
|
||||
out_uint8(s, w_groups[index]);
|
||||
}
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint8p(s, groups, groups_len);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1249,18 +1247,46 @@ scard_send_ListReaders(IRP *irp, char *context, int context_bytes,
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
align_s(struct stream *s, int bytes)
|
||||
/**
|
||||
* Outputs the pointed-to-data for one of these IDL pointer types:-
|
||||
* [string] const wchar_t* str; (wide != 0)
|
||||
* [string] const char* str; (wide == 0)
|
||||
*
|
||||
* It is assumed that the referent identifier for the string has already
|
||||
* been sent
|
||||
*
|
||||
* @param s Output stream
|
||||
* @param str UTF-8 string to output
|
||||
* @param wide Whether to output as a wide string or ASCII
|
||||
*
|
||||
* Note that wchar_t on Windows is 16-bit
|
||||
* TODO: These strings have two terminators. Is this necessary?
|
||||
*/
|
||||
static void
|
||||
out_conformant_and_varying_string(struct stream *s, const char *str, int wide)
|
||||
{
|
||||
int i32;
|
||||
|
||||
i32 = (int) (s->p - s->data);
|
||||
while ((i32 % bytes) != 0)
|
||||
align_s(s, 4);
|
||||
unsigned int len = strlen(str);
|
||||
if (wide)
|
||||
{
|
||||
out_uint8s(s, 1);
|
||||
i32 = (int) (s->p - s->data);
|
||||
unsigned int num_chars = utf8_as_utf16_word_count(str, len);
|
||||
// Max number, offset and actual count
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
out_utf8_as_utf16_le(s, str, len);
|
||||
out_uint16_le(s, 0); // Terminate string
|
||||
out_uint16_le(s, 0); // ?
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint32_le(s, len + 2);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, len + 2);
|
||||
out_uint8p(s, str, len);
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1347,9 +1373,6 @@ scard_send_GetStatusChange(IRP *irp, char *context, int context_bytes,
|
|||
tui32 ioctl;
|
||||
int bytes;
|
||||
unsigned int i;
|
||||
int num_chars;
|
||||
int index;
|
||||
twchar w_reader_name[100];
|
||||
|
||||
if ((sc = smartcards[irp->scard_index]) == NULL)
|
||||
{
|
||||
|
@ -1386,6 +1409,7 @@ scard_send_GetStatusChange(IRP *irp, char *context, int context_bytes,
|
|||
out_uint8a(s, context, context_bytes);
|
||||
|
||||
// rgReaderState is a Uni-dimensional conformant array
|
||||
align_s(s, 4);
|
||||
out_uint32_le(s, num_readers);
|
||||
|
||||
/* insert card reader state */
|
||||
|
@ -1406,43 +1430,11 @@ scard_send_GetStatusChange(IRP *irp, char *context, int context_bytes,
|
|||
out_uint8s(s, 3);
|
||||
}
|
||||
|
||||
if (wide)
|
||||
/* insert card reader names */
|
||||
for (i = 0; i < num_readers; i++)
|
||||
{
|
||||
/* insert card reader names */
|
||||
for (i = 0; i < num_readers; i++)
|
||||
{
|
||||
rs = &rsa[i];
|
||||
num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
for (index = 0; index < num_chars; index++)
|
||||
{
|
||||
out_uint16_le(s, w_reader_name[index]);
|
||||
}
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
align_s(s, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* insert card reader names */
|
||||
for (i = 0; i < num_readers; i++)
|
||||
{
|
||||
rs = &rsa[i];
|
||||
num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
for (index = 0; index < num_chars; index++)
|
||||
{
|
||||
out_uint8(s, w_reader_name[index]);
|
||||
}
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
align_s(s, 4);
|
||||
}
|
||||
rs = &rsa[i];
|
||||
out_conformant_and_varying_string(s, rs->reader_name, wide);
|
||||
}
|
||||
|
||||
s_mark_end(s);
|
||||
|
@ -1525,14 +1517,10 @@ scard_send_Connect(IRP *irp, char *context, int context_bytes,
|
|||
* ?? Conformant Array pointed to by pbContext
|
||||
*
|
||||
*/
|
||||
|
||||
SMARTCARD *sc;
|
||||
struct stream *s;
|
||||
tui32 ioctl;
|
||||
int bytes;
|
||||
int num_chars;
|
||||
int index;
|
||||
twchar w_reader_name[100];
|
||||
|
||||
if ((sc = smartcards[irp->scard_index]) == NULL)
|
||||
{
|
||||
|
@ -1564,34 +1552,13 @@ scard_send_Connect(IRP *irp, char *context, int context_bytes,
|
|||
out_uint32_le(s, rs->dwPreferredProtocols);
|
||||
|
||||
/* insert card reader name */
|
||||
num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
out_uint32_le(s, 0x00000000);
|
||||
out_uint32_le(s, num_chars + 2);
|
||||
if (wide)
|
||||
{
|
||||
for (index = 0; index < num_chars; index++)
|
||||
{
|
||||
out_uint16_le(s, w_reader_name[index]);
|
||||
}
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < num_chars; index++)
|
||||
{
|
||||
out_uint8(s, w_reader_name[index]);
|
||||
}
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0);
|
||||
}
|
||||
align_s(s, 4);
|
||||
out_conformant_and_varying_string(s, rs->reader_name, wide);
|
||||
|
||||
/* insert context */
|
||||
align_s(s, 4);
|
||||
out_uint32_le(s, context_bytes);
|
||||
out_uint8a(s, context, context_bytes);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, 0); // ?
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* @file sesman/chansrv/smartcard_pcsc.c
|
||||
*
|
||||
* smartcard redirection support, PCSC daemon standin
|
||||
* this will act like pcsc daemon
|
||||
* pcsc lib and daemon write struct on unix domain socket for communication
|
||||
|
@ -653,6 +651,44 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Counts the number of non-NULL strings in a multistring
|
||||
*
|
||||
* [MS-RDPESC] A multistring is "A series of null-terminated character
|
||||
* strings terminated by a final null character stored in a contiguous
|
||||
* block of memory."
|
||||
*
|
||||
* The string is guaranteed to have at least the returned number of NULL
|
||||
* characters in it
|
||||
*/
|
||||
unsigned int
|
||||
count_multistring_elements(const char *str, unsigned int len)
|
||||
{
|
||||
unsigned int rv = 0;
|
||||
|
||||
if (str != NULL)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
// Look for a terminator
|
||||
const char *p = (const char *)memchr(str, '\0', len);
|
||||
if (!p || p == str)
|
||||
{
|
||||
// No terminator, or an empty string encountered */
|
||||
break;
|
||||
}
|
||||
|
||||
++rv;
|
||||
++p; // Skip terminator
|
||||
len -= (p - str);
|
||||
str = p;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scard_function_list_readers_return(void *user_data,
|
||||
|
@ -685,19 +721,16 @@ scard_function_list_readers_return(void *user_data,
|
|||
* 16 Multistring data
|
||||
*/
|
||||
struct stream *out_s;
|
||||
int chr;
|
||||
int readers;
|
||||
int rn_index;
|
||||
int index;
|
||||
int bytes;
|
||||
int cchReaders;
|
||||
int llen;
|
||||
int uds_client_id;
|
||||
twchar reader_name[100];
|
||||
char lreader_name[16][100];
|
||||
struct pcsc_uds_client *uds_client;
|
||||
struct trans *con;
|
||||
struct pcsc_list_readers *pcscListReaders;
|
||||
char *msz_readers = NULL;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_list_readers_return:");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " status 0x%8.8x", status);
|
||||
|
@ -721,9 +754,6 @@ scard_function_list_readers_return(void *user_data,
|
|||
return 1;
|
||||
}
|
||||
con = uds_client->con;
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
g_memset(lreader_name, 0, sizeof(lreader_name));
|
||||
rn_index = 0;
|
||||
readers = 0;
|
||||
llen = 0;
|
||||
if (status == 0)
|
||||
|
@ -733,39 +763,23 @@ scard_function_list_readers_return(void *user_data,
|
|||
// Move to length of multistring in bytes
|
||||
in_uint8s(in_s, 12);
|
||||
|
||||
in_uint32_le(in_s, len);
|
||||
llen = len;
|
||||
in_uint32_le(in_s, llen);
|
||||
if (cchReaders > 0)
|
||||
{
|
||||
while (len > 0)
|
||||
// Convert the wide multistring to a UTF-8 multistring
|
||||
unsigned int u8len;
|
||||
u8len = in_utf16_le_fixed_as_utf8_length(in_s, len / 2);
|
||||
msz_readers = (char *)malloc(u8len);
|
||||
if (msz_readers == NULL)
|
||||
{
|
||||
in_uint16_le(in_s, chr);
|
||||
len -= 2;
|
||||
if (chr == 0)
|
||||
{
|
||||
if (reader_name[0] != 0)
|
||||
{
|
||||
g_wcstombs(lreader_name[readers], reader_name, 99);
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
readers++;
|
||||
}
|
||||
reader_name[0] = 0;
|
||||
rn_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
reader_name[rn_index] = chr;
|
||||
rn_index++;
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR, "scard_function_list_readers_return: "
|
||||
"Can't allocate %u bytes of memory", u8len);
|
||||
readers = 0;
|
||||
}
|
||||
}
|
||||
if (rn_index > 0)
|
||||
{
|
||||
if (reader_name[0] != 0)
|
||||
else
|
||||
{
|
||||
g_wcstombs(lreader_name[readers], reader_name, 99);
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
readers++;
|
||||
in_utf16_le_fixed_as_utf8(in_s, len / 2, msz_readers, u8len);
|
||||
readers = count_multistring_elements(msz_readers, u8len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -778,10 +792,25 @@ scard_function_list_readers_return(void *user_data,
|
|||
s_push_layer(out_s, iso_hdr, 8);
|
||||
out_uint32_le(out_s, llen);
|
||||
out_uint32_le(out_s, readers);
|
||||
for (index = 0; index < readers; index++)
|
||||
{
|
||||
out_uint8a(out_s, lreader_name[index], 100);
|
||||
const char *p = msz_readers;
|
||||
for (index = 0; index < readers; index++)
|
||||
{
|
||||
unsigned int slen = strlen(p);
|
||||
if (slen < 100)
|
||||
{
|
||||
out_uint8a(out_s, p, slen);
|
||||
out_uint8s(out_s, 100 - slen);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint8a(out_s, p, 99);
|
||||
out_uint8s(out_s, 1);
|
||||
}
|
||||
p += (slen + 1);
|
||||
}
|
||||
}
|
||||
free(msz_readers);
|
||||
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
|
||||
s_mark_end(out_s);
|
||||
bytes = (int) (out_s->end - out_s->data);
|
||||
|
@ -1466,14 +1495,12 @@ scard_function_status_return(void *user_data,
|
|||
* 60 Multistring data
|
||||
*/
|
||||
struct stream *out_s;
|
||||
int index;
|
||||
int bytes;
|
||||
int dwReaderLen;
|
||||
int dwState;
|
||||
int dwProtocol;
|
||||
int dwAtrLen;
|
||||
char attr[32];
|
||||
twchar reader_name[100];
|
||||
char lreader_name[100];
|
||||
int uds_client_id;
|
||||
struct pcsc_uds_client *uds_client;
|
||||
|
@ -1519,33 +1546,20 @@ scard_function_status_return(void *user_data,
|
|||
in_uint32_le(in_s, dwProtocol);
|
||||
in_uint8a(in_s, attr, 32);
|
||||
in_uint32_le(in_s, dwAtrLen);
|
||||
if (dwReaderLen > 0)
|
||||
|
||||
// Length of multistring and multistring data
|
||||
if (dwReaderLen <= 0)
|
||||
{
|
||||
in_uint32_le(in_s, dwReaderLen);
|
||||
dwReaderLen /= 2;
|
||||
lreader_name[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
dwReaderLen = 1;
|
||||
in_uint8s(in_s, 4); // Skip length of msz in bytes
|
||||
|
||||
// TODO: why are we just returning the first name of the card?
|
||||
in_utf16_le_terminated_as_utf8(in_s, lreader_name,
|
||||
sizeof(lreader_name));
|
||||
}
|
||||
if (dwReaderLen < 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "scard_function_status_return: dwReaderLen < 1");
|
||||
dwReaderLen = 1;
|
||||
}
|
||||
if (dwReaderLen > 99)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "scard_function_status_return: dwReaderLen too big "
|
||||
"0x%8.8x", dwReaderLen);
|
||||
dwReaderLen = 99;
|
||||
}
|
||||
g_memset(reader_name, 0, sizeof(reader_name));
|
||||
g_memset(lreader_name, 0, sizeof(lreader_name));
|
||||
for (index = 0; index < dwReaderLen - 1; index++)
|
||||
{
|
||||
in_uint16_le(in_s, reader_name[index]);
|
||||
}
|
||||
g_wcstombs(lreader_name, reader_name, 99);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_status_return: dwAtrLen %d dwReaderLen %d "
|
||||
"dwProtocol %d dwState %d name %s",
|
||||
|
|
Loading…
Reference in New Issue