Smartcard support by Alexi Volkov <alexi@pravex.kiev.ua> and additional

patches for smartcard-support by Jennings Jared <jared.jennings.ctr@eglin.af.mil>


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1308 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Michael Gernoth 2006-11-01 20:52:01 +00:00
parent 082031280a
commit f37c871e8b
12 changed files with 3075 additions and 15 deletions

View File

@ -24,6 +24,7 @@ VNCINC = @VNCINC@
LDVNC = @LDVNC@
VNCLINK = @VNCLINK@
SOUNDOBJ = @SOUNDOBJ@
SCARDOBJ = @SCARDOBJ@
RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o lspci.o seamless.o
X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o
@ -32,11 +33,11 @@ VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
.PHONY: all
all: $(TARGETS)
rdesktop: $(X11OBJ) $(SOUNDOBJ) $(RDPOBJ)
$(CC) $(CFLAGS) -o rdesktop $(X11OBJ) $(SOUNDOBJ) $(RDPOBJ) $(LDFLAGS) -lX11
rdesktop: $(X11OBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ)
$(CC) $(CFLAGS) -o rdesktop $(X11OBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ) $(LDFLAGS) -lX11
rdp2vnc: $(VNCOBJ) $(SOUNDOBJ) $(RDPOBJ)
$(VNCLINK) $(CFLAGS) -o rdp2vnc $(VNCOBJ) $(SOUNDOBJ) $(RDPOBJ) $(LDFLAGS) $(LDVNC)
rdp2vnc: $(VNCOBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ)
$(VNCLINK) $(CFLAGS) -o rdp2vnc $(VNCOBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ) $(LDFLAGS) $(LDVNC)
vnc/rdp2vnc.o: rdesktop.c
$(CC) $(CFLAGS) $(VNCINC) -DRDP2VNC -o vnc/rdp2vnc.o -c rdesktop.c
@ -82,7 +83,8 @@ proto:
bitmap.c cache.c channels.c cliprdr.c disk.c mppc.c ewmhints.c \
iso.c licence.c mcs.c orders.c parallel.c printer.c printercache.c \
pstcache.c rdesktop.c rdp5.c rdp.c rdpdr.c rdpsnd.c \
secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c lspci.c seamless.c >> proto.h
secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c lspci.c seamless.c \
scard.c >> proto.h
cat proto.tail >> proto.h
.PHONY: clean

10
README
View File

@ -30,3 +30,13 @@ Terminal Services enabled, or there is a firewall blocking access.
The rdesktop manual page lists the possible options ("man rdesktop").
Smart-card support notes
------------------------
Smart-card support module uses PCSC-lite. You should use PCSC-lite 1.2.9 or
later.
To enable smart-card support in the rdesktop just run "./configure" with the
"--enable-smartcard" option. Also you can enable smart-card debug with
additional "--with-debug-smartcard" option.

View File

@ -79,6 +79,22 @@ LIBS="$LIBS -L$ssldir/lib -lcrypto"
rpath="$rpath:$ssldir/lib"
])
AC_ARG_ENABLE(smartcard,
[ --enable-smartcard Enables smart-card support.
],
[
if test -n "$PKG_CONFIG"; then
PKG_CHECK_MODULES(PCSCLITE, libpcsclite, [WITH_SCARD=1], [WITH_SCARD=0])
if test x"$WITH_SCARD" = "x1"; then
SCARDOBJ="scard.o"
CFLAGS="$CFLAGS $PCSCLITE_CFLAGS"
LIBS="$LIBS $PCSCLITE_LIBS"
AC_DEFINE(WITH_SCARD)
fi
fi
])
AC_SUBST(SCARDOBJ)
#
# Alignment
@ -785,6 +801,17 @@ AC_ARG_WITH(debug-channel,
])
AC_ARG_WITH(debug-smartcard,
[ --with-debug-smartcard enable debugging of smart-card code],
[
if test $withval != "no";
then
if test x"$WITH_SCARD" = "x1"; then
AC_DEFINE(WITH_SCARD_DEBUG,1)
fi
fi
])
#
# target-specific stuff
#

View File

@ -1,6 +1,7 @@
rdesktop (1.?.?)
* ALSA-driver added
* sound-drivers can now be selected at runtime
* Smartcard support by Alexi Volkov <alexi@pravex.kiev.ua>
rdesktop (1.5.0)
* SeamlessRDP - seamless windows support

View File

@ -202,6 +202,14 @@ Activates the lspci channel, which allows the server to enumerate the
clients PCI devices. See the file lspci-channel.txt in the
documentation for more information.
.TP
.BR "-r scard[:<Scard Name>=<Alias Name>[;<Vendor Name>][,...]]"
Enables redirection of one or more smart-cards. You can provide
static name binding between linux and windows. To do this you
can use optional parameters as described: <Scard Name> - device name in
Linux/Unix enviroment, <Alias Name> - device name shown in Windows enviroment
<Vendor Name> - optional device vendor name. For list of examples run
rdesktop without parameters.
.TP
.BR "-0"
Attach to the console of the server (requires Windows Server 2003
or newer).

10
proto.h
View File

@ -157,6 +157,8 @@ void rdp_disconnect(void);
/* rdpdr.c */
int get_device_index(NTHANDLE handle);
void convert_to_unix_filename(char *filename);
void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
uint32 length);
BOOL rdpdr_init(void);
void rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout);
struct async_iorequest *rdpdr_remove_iorequest(struct async_iorequest *prev,
@ -302,6 +304,14 @@ unsigned int seamless_send_position(unsigned long id, int x, int y, int width, i
void seamless_select_timeout(struct timeval *tv);
unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags);
unsigned int seamless_send_focus(unsigned long id, unsigned long flags);
/* scard.c */
void scardSetInfo(uint32 device, uint32 id, uint32 bytes_out);
int scard_enum_devices(uint32 * id, char *optarg);
void scard_tcp_lock(void);
void scard_tcp_unlock(void);
STREAM scard_tcp_init(void);
void scard_tcp_connect(void);
void scard_tcp_reset_state(void);
/* *INDENT-OFF* */
#ifdef __cplusplus

View File

@ -193,6 +193,21 @@ usage(char *program)
" 'PRIMARYCLIPBOARD' looks at both PRIMARY and CLIPBOARD\n");
fprintf(stderr, " when sending data to server.\n");
fprintf(stderr, " 'CLIPBOARD' looks at only CLIPBOARD.\n");
#ifdef WITH_SCARD
fprintf(stderr, " '-r scard[:\"Scard Name\"=\"Alias Name[;Vendor Name]\"[,...]]\n");
fprintf(stderr, " example: -r scard:\"eToken PRO 00 00\"=\"AKS ifdh 0\"\n");
fprintf(stderr,
" \"eToken PRO 00 00\" -> Device in Linux/Unix enviroment\n");
fprintf(stderr,
" \"AKS ifdh 0\" -> Device shown in Windows enviroment \n");
fprintf(stderr, " example: -r scard:\"eToken PRO 00 00\"=\"AKS ifdh 0;AKS\"\n");
fprintf(stderr,
" \"eToken PRO 00 00\" -> Device in Linux/Unix enviroment\n");
fprintf(stderr,
" \"AKS ifdh 0\" -> Device shown in Windows enviroment \n");
fprintf(stderr,
" \"AKS\" -> Device vendor name \n");
#endif
fprintf(stderr, " -0: attach to console\n");
fprintf(stderr, " -4: use RDP version 4\n");
fprintf(stderr, " -5: use RDP version 5 (default)\n");
@ -740,9 +755,17 @@ main(int argc, char *argv[])
else
g_rdpclip = True;
}
else if (strncmp("scard", optarg, 5) == 0)
{
#ifdef WITH_SCARD
scard_enum_devices(&g_num_devices, optarg + 5);
#else
warning("Not compiled with smartcard support\n");
#endif
}
else
{
warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard\n");
warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n");
}
break;

27
rdpdr.c
View File

@ -60,6 +60,9 @@ extern DEVICE_FNS serial_fns;
extern DEVICE_FNS printer_fns;
extern DEVICE_FNS parallel_fns;
extern DEVICE_FNS disk_fns;
#ifdef WITH_SCARD
extern DEVICE_FNS scard_fns;
#endif
extern FILEINFO g_fileinfo[];
extern BOOL g_notify_stamp;
@ -309,7 +312,7 @@ rdpdr_send_available(void)
channel_send(s, rdpdr_channel);
}
static void
void
rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
uint32 length)
{
@ -395,6 +398,11 @@ rdpdr_process_irp(STREAM s)
break;
case DEVICE_TYPE_SCARD:
#ifdef WITH_SCARD
fns = &scard_fns;
rw_blocking = False;
break;
#endif
default:
error("IRP for bad device %ld\n", device);
@ -671,9 +679,20 @@ rdpdr_process_irp(STREAM s)
out.data = out.p = buffer;
out.size = sizeof(buffer);
#ifdef WITH_SCARD_DEBUG
printf("[SMART-CARD TRACE]\n");
printf("device 0x%.8x\n", device);
printf("file 0x%.8x\n", file);
printf("id 0x%.8x\n", id);
#endif
#ifdef WITH_SCARD
scardSetInfo(device, id, bytes_out + 0x14);
#endif
status = fns->device_control(file, request, s, &out);
result = buffer_len = out.p - out.data;
#ifdef WITH_SCARD_DEBUG
printf("[SMART-CARD TRACE] OUT 0x%.8x\n", status);
#endif
/* Serial SERIAL_WAIT_ON_MASK */
if (status == STATUS_PENDING)
{
@ -684,6 +703,10 @@ rdpdr_process_irp(STREAM s)
break;
}
}
#ifdef WITH_SCARD
else if (status == (STATUS_PENDING | 0xC0000000))
status = STATUS_PENDING;
#endif
break;

2765
scard.c Normal file

File diff suppressed because it is too large Load Diff

159
scard.h Normal file
View File

@ -0,0 +1,159 @@
/************************************/
/* Smart Card support for RDesktop. */
/* Copyright (C) by Alexi Volkov */
/* e-mail: alexi@myrealbox.com */
/* ICQ: 264679502 */
/************************************/
#include <pthread.h>
#include <pcsclite.h>
#include "proto.h"
/*************************************************************************/
/* these are the additional types needed to split out 64-vs-32-bit APIs */
/* */
/* The point of all of this is to avoid patching the existing smartcard
* infrastructure (PC/SC Lite, libmusclecard+libmusclepkcs11 or CoolKey, any
* other apps linking against any of these) because the need for patches
* spreads without limit. The alternative is to patch the heck out of rdesktop,
* which is already being done anyway.
*
* - jared.jennings@eglin.af.mil, 2 Aug 2006
*/
#include <stdint.h>
/* A DWORD when dealing with the smartcard stuff. Could be 32 bits or 64. */
typedef DWORD MYPCSC_DWORD;
/* A DWORD when talking to the server. Must be exactly 32 bits all the time.*/
typedef uint32_t SERVER_DWORD;
typedef SCARDCONTEXT MYPCSC_SCARDCONTEXT;
typedef SCARDHANDLE MYPCSC_SCARDHANDLE;
typedef uint32_t SERVER_SCARDCONTEXT;
typedef uint32_t SERVER_SCARDHANDLE;
typedef SCARD_READERSTATE_A MYPCSC_SCARD_READERSTATE_A;
typedef LPSCARD_READERSTATE_A MYPCSC_LPSCARD_READERSTATE_A;
typedef struct
{
const char *szReader;
void *pvUserData;
SERVER_DWORD dwCurrentState;
SERVER_DWORD dwEventState;
SERVER_DWORD cbAtr;
unsigned char rgbAtr[MAX_ATR_SIZE];
}
SERVER_SCARD_READERSTATE_A;
typedef SERVER_SCARD_READERSTATE_A *SERVER_LPSCARD_READERSTATE_A;
#define SERVER_SCARDSTATESIZE (sizeof(SERVER_SCARD_READERSTATE_A) - sizeof(const char *) - sizeof(void *))
#define MYPCSC_SCARDSTATESIZE (sizeof(MYPCSC_SCARD_READERSTATE_A) - sizeof(const char *) - sizeof(void *))
typedef struct _SERVER_SCARD_IO_REQUEST
{
SERVER_DWORD dwProtocol; /* Protocol identifier */
SERVER_DWORD cbPciLength; /* Protocol Control Inf Length */
}
SERVER_SCARD_IO_REQUEST, *SERVER_LPSCARD_IO_REQUEST;
typedef SCARD_IO_REQUEST MYPCSC_SCARD_IO_REQUEST;
typedef LPSCARD_IO_REQUEST MYPCSC_LPSCARD_IO_REQUEST;
/* */
/* */
/*************************************************************************/
#define SC_TRUE 1
#define SC_FALSE 0
#define SC_ESTABLISH_CONTEXT 0x00090014 /* EstablishContext */
#define SC_RELEASE_CONTEXT 0x00090018 /* ReleaseContext */
#define SC_IS_VALID_CONTEXT 0x0009001C /* IsValidContext */
#define SC_LIST_READER_GROUPS 0x00090020 /* ListReaderGroups */
#define SC_LIST_READERS 0x00090028 /* ListReadersA */
#define SC_INTRODUCE_READER_GROUP 0x00090050 /* IntroduceReaderGroup */
#define SC_FORGET_READER_GROUP 0x00090058 /* ForgetReader */
#define SC_INTRODUCE_READER 0x00090060 /* IntroduceReader */
#define SC_FORGET_READER 0x00090068 /* IntroduceReader */
#define SC_ADD_READER_TO_GROUP 0x00090070 /* AddReaderToGroup */
#define SC_REMOVE_READER_FROM_GROUP 0x00090078 /* RemoveReaderFromGroup */
#define SC_CONNECT 0x000900AC /* ConnectA */
#define SC_RECONNECT 0x000900B4 /* Reconnect */
#define SC_DISCONNECT 0x000900B8 /* Disconnect */
#define SC_GET_STATUS_CHANGE 0x000900A0 /* GetStatusChangeA */
#define SC_CANCEL 0x000900A8 /* Cancel */
#define SC_BEGIN_TRANSACTION 0x000900BC /* BeginTransaction */
#define SC_END_TRANSACTION 0x000900C0 /* EndTransaction */
#define SC_STATE 0x000900C4 /* State */
#define SC_STATUS 0x000900C8 /* StatusA */
#define SC_TRANSMIT 0x000900D0 /* Transmit */
#define SC_CONTROL 0x000900D4 /* Control */
#define SC_GETATTRIB 0x000900D8 /* GetAttrib */
#define SC_SETATTRIB 0x000900DC /* SetAttrib */
#define SC_ACCESS_STARTED_EVENT 0x000900E0 /* SCardAccessStartedEvent */
#define SC_LOCATE_CARDS_BY_ATR 0x000900E8 /* LocateCardsByATR */
/* #define INPUT_LINKED 0x00020000 */
#define INPUT_LINKED 0xFFFFFFFF
#define SC_THREAD_FUNCTION(f) void *(*f)(void *)
extern RDPDR_DEVICE g_rdpdr_device[];
typedef struct _MEM_HANDLE
{
struct _MEM_HANDLE *prevHandle;
struct _MEM_HANDLE *nextHandle;
int dataSize;
} MEM_HANDLE, *PMEM_HANDLE;
typedef struct _SCARD_ATRMASK_L
{
unsigned int cbAtr;
unsigned char rgbAtr[36];
unsigned char rgbMask[36];
} SCARD_ATRMASK_L, *PSCARD_ATRMASK_L, *LPSCARD_ATRMASK_L;
typedef struct _TSCNameMapRec
{
char alias[128];
char name[128];
char vendor[128];
} TSCNameMapRec, *PSCNameMapRec;
typedef struct _TSCHCardRec
{
DWORD hCard;
char *vendor;
struct _TSCHCardRec *next;
struct _TSCHCardRec *prev;
} TSCHCardRec, *PSCHCardRec;
typedef struct _TSCThreadData
{
uint32 device;
uint32 id;
NTHANDLE handle;
uint32 request;
STREAM in;
STREAM out;
PMEM_HANDLE memHandle;
struct _TSCThreadData *next;
} TSCThreadData, *PSCThreadData;
typedef struct _TThreadListElement
{
pthread_t thread;
pthread_mutex_t busy;
pthread_mutex_t nodata;
PSCThreadData data;
struct _TThreadListElement *next;
} TThreadListElement, *PThreadListElement;
int scard_enum_devices(uint32 * id, char *optarg);

42
tcp.c
View File

@ -34,22 +34,36 @@
static int sock;
static struct stream in;
#ifndef WITH_SCARD
static struct stream out;
#endif
int g_tcp_port_rdp = TCP_PORT_RDP;
/* Initialise TCP transport data packet */
STREAM
tcp_init(uint32 maxlen)
{
if (maxlen > out.size)
STREAM result = NULL;
#ifdef WITH_SCARD
scard_tcp_lock();
result = scard_tcp_init();
#else
result = &out;
#endif
if (maxlen > result->size)
{
out.data = (uint8 *) xrealloc(out.data, maxlen);
out.size = maxlen;
result->data = (uint8 *) xrealloc(result->data, maxlen);
result->size = maxlen;
}
out.p = out.data;
out.end = out.data + out.size;
return &out;
result->p = result->data;
result->end = result->data + result->size;
#ifdef WITH_SCARD
scard_tcp_unlock();
#endif
return result;
}
/* Send TCP transport data packet */
@ -59,6 +73,9 @@ tcp_send(STREAM s)
int length = s->end - s->data;
int sent, total = 0;
#ifdef WITH_SCARD
scard_tcp_lock();
#endif
while (total < length)
{
sent = send(sock, s->data + total, length - total, 0);
@ -70,6 +87,9 @@ tcp_send(STREAM s)
total += sent;
}
#ifdef WITH_SCARD
scard_tcp_unlock();
#endif
}
/* Receive a message on the TCP layer */
@ -214,8 +234,12 @@ tcp_connect(char *server)
in.size = 4096;
in.data = (uint8 *) xmalloc(in.size);
#ifdef WITH_SCARD
scard_tcp_connect();
#else
out.size = 4096;
out.data = (uint8 *) xmalloc(out.size);
#endif
return True;
}
@ -263,7 +287,10 @@ tcp_reset_state(void)
in.rdp_hdr = NULL;
in.channel_hdr = NULL;
/* Clear the outgoing stream */
/* Clear the outgoing stream(s) */
#ifdef WITH_SCARD
scard_tcp_reset_state();
#else
if (out.data != NULL)
xfree(out.data);
out.p = NULL;
@ -275,4 +302,5 @@ tcp_reset_state(void)
out.sec_hdr = NULL;
out.rdp_hdr = NULL;
out.channel_hdr = NULL;
#endif
}

View File

@ -18,7 +18,11 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef WITH_SCARD
#include <wintypes.h>
#else
typedef int BOOL;
#endif
#ifndef True
#define True (1)