summaryrefslogtreecommitdiffstats
path: root/sesman
diff options
context:
space:
mode:
authorLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-09-25 18:54:16 -0700
committerLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-09-25 18:54:16 -0700
commit5e005bf26ce965350cac7f942678031d5482d867 (patch)
tree705b0caeda414ad90ecda9f1d0de00251036b939 /sesman
parent52fb1f9854eec37d57f9a7a91dfce48ae9774dd5 (diff)
parent1afb67850157392e2d8c35857388d515ddcdf0b4 (diff)
downloadxrdp-proprietary-5e005bf26ce965350cac7f942678031d5482d867.tar.gz
xrdp-proprietary-5e005bf26ce965350cac7f942678031d5482d867.zip
Merge branch 'master' of github.com:neutrinolabs/xrdp
Diffstat (limited to 'sesman')
-rw-r--r--sesman/chansrv/Makefile.am6
-rw-r--r--sesman/chansrv/chansrv.c21
-rw-r--r--sesman/chansrv/chansrv_fuse.c218
-rw-r--r--sesman/chansrv/devredir.c6
-rw-r--r--sesman/chansrv/fifo.c255
-rw-r--r--sesman/chansrv/fifo.h35
-rw-r--r--sesman/chansrv/mlog.h112
-rw-r--r--sesman/chansrv/pcsc/xrdp_pcsc.c52
-rw-r--r--sesman/chansrv/smartcard.c8
-rw-r--r--sesman/chansrv/smartcard_pcsc.c57
-rw-r--r--sesman/chansrv/smartcard_pcsc.h3
11 files changed, 676 insertions, 97 deletions
diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am
index 7cecdb1e..29ef902b 100644
--- a/sesman/chansrv/Makefile.am
+++ b/sesman/chansrv/Makefile.am
@@ -8,7 +8,8 @@ EXTRA_DIST = \
drdynvc.h \
rail.h \
sound.h \
- xcommon.h
+ xcommon.h \
+ mlog.h
EXTRA_DEFINES =
EXTRA_INCLUDES =
@@ -51,7 +52,8 @@ xrdp_chansrv_SOURCES = \
xcommon.c \
drdynvc.c \
chansrv_fuse.c \
- irp.c
+ irp.c \
+ fifo.c
xrdp_chansrv_LDFLAGS = \
$(EXTRA_FLAGS)
diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c
index c3d1aa79..86c50960 100644
--- a/sesman/chansrv/chansrv.c
+++ b/sesman/chansrv/chansrv.c
@@ -293,11 +293,11 @@ send_data_from_chan_item(struct chan_item *chan_item)
out_uint32_le(s, cod->s->size);
out_uint8a(s, cod->s->p, size);
s_mark_end(s);
- LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- "
+ LOGM((LOG_LEVEL_DEBUG, "chansrv::send_data_from_chan_item: -- "
"size %d chan_flags 0x%8.8x", size, chan_flags));
g_sent = 1;
- error = trans_force_write(g_con_trans);
+ error = trans_write_copy(g_con_trans);
if (error != 0)
{
return 1;
@@ -392,7 +392,7 @@ send_init_response_message(void)
out_uint32_le(s, 2); /* msg id */
out_uint32_le(s, 8); /* size */
s_mark_end(s);
- return trans_force_write(g_con_trans);
+ return trans_write_copy(g_con_trans);
}
/*****************************************************************************/
@@ -415,7 +415,7 @@ send_channel_setup_response_message(void)
out_uint32_le(s, 4); /* msg id */
out_uint32_le(s, 8); /* size */
s_mark_end(s);
- return trans_force_write(g_con_trans);
+ return trans_write_copy(g_con_trans);
}
/*****************************************************************************/
@@ -438,7 +438,7 @@ send_channel_data_response_message(void)
out_uint32_le(s, 6); /* msg id */
out_uint32_le(s, 8); /* size */
s_mark_end(s);
- return trans_force_write(g_con_trans);
+ return trans_write_copy(g_con_trans);
}
/*****************************************************************************/
@@ -637,7 +637,7 @@ process_message_channel_data(struct stream *s)
if (chan_flags & 2) /* last */
{
s_mark_end(ls);
- trans_force_write(g_api_con_trans);
+ trans_write_copy(g_api_con_trans);
}
}
}
@@ -1041,7 +1041,9 @@ THREAD_RV THREAD_CC
channel_thread_loop(void *in_val)
{
tbus objs[32];
+ tbus wobjs[32];
int num_objs;
+ int num_wobjs;
int timeout;
int error;
THREAD_RV rv;
@@ -1055,12 +1057,13 @@ channel_thread_loop(void *in_val)
{
timeout = -1;
num_objs = 0;
+ num_wobjs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
- while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0)
+ while (g_obj_wait(objs, num_objs, wobjs, num_wobjs, timeout) == 0)
{
check_timeout();
if (g_is_wait_obj_set(g_term_event))
@@ -1135,10 +1138,12 @@ channel_thread_loop(void *in_val)
xfuse_check_wait_objs();
timeout = -1;
num_objs = 0;
+ num_wobjs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
- trans_get_wait_objs(g_con_trans, objs, &num_objs);
+ trans_get_wait_objs_rw(g_con_trans, objs, &num_objs,
+ wobjs, &num_wobjs);
trans_get_wait_objs(g_api_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_api_con_trans, objs, &num_objs);
xcommon_get_wait_objs(objs, &num_objs, &timeout);
diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c
index 572679eb..2eb78ea0 100644
--- a/sesman/chansrv/chansrv_fuse.c
+++ b/sesman/chansrv/chansrv_fuse.c
@@ -102,6 +102,7 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#include "os_calls.h"
#include "chansrv_fuse.h"
#include "list.h"
+#include "fifo.h"
#define min(x, y) ((x) < (y) ? (x) : (y))
@@ -223,6 +224,16 @@ struct dir_info
int index;
};
+/* queue FUSE opendir commands so we run only one at a time */
+struct opendir_req
+{
+ fuse_req_t req;
+ fuse_ino_t ino;
+ struct fuse_file_info *fi;
+};
+
+FIFO g_fifo_opendir;
+
static struct list *g_req_list = 0;
static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */
static char *g_mount_point = 0; /* our FUSE mount point */
@@ -338,19 +349,22 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
static void xfuse_cb_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi);
-/* clipboard calls */
-int clipboard_request_file_data(int stream_id, int lindex, int offset,
- int request_bytes);
-
static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int to_set, struct fuse_file_info *fi);
static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi);
+static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
+ struct fuse_file_info *fi);
+
static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi);
+/* clipboard calls */
+int clipboard_request_file_data(int stream_id, int lindex, int offset,
+ int request_bytes);
+
/* misc calls */
static void xfuse_mark_as_stale(int pinode);
static void xfuse_delete_stale_entries(int pinode);
@@ -403,6 +417,9 @@ int xfuse_init()
if (xfuse_init_xrdp_fs())
return -1;
+ /* setup FIFOs */
+ fifo_init(&g_fifo_opendir, 30);
+
/* setup FUSE callbacks */
g_memset(&g_xfuse_ops, 0, sizeof(g_xfuse_ops));
g_xfuse_ops.lookup = xfuse_cb_lookup;
@@ -424,6 +441,8 @@ int xfuse_init()
fuse_opt_add_arg(&args, "xrdp-chansrv");
fuse_opt_add_arg(&args, g_fuse_root_path);
+ //fuse_opt_add_arg(&args, "-s"); /* single threaded mode */
+ //fuse_opt_add_arg(&args, "-d"); /* debug mode */
if (xfuse_init_lib(&args))
{
@@ -444,6 +463,7 @@ int xfuse_init()
int xfuse_deinit()
{
xfuse_deinit_xrdp_fs();
+ fifo_deinit(&g_fifo_opendir);
if (g_ch != 0)
{
@@ -901,12 +921,11 @@ static int xfuse_deinit_xrdp_fs()
static int xfuse_is_inode_valid(int ino)
{
- /* our lowest ino is FIRST_INODE */
- if (ino < FIRST_INODE)
+ /* is ino present in our table? */
+ if ((ino < FIRST_INODE) || (ino >= g_xrdp_fs.next_node))
return 0;
- /* is ino present in our table? */
- if (ino >= g_xrdp_fs.next_node)
+ if (g_xrdp_fs.inode_table[ino] == NULL)
return 0;
return 1;
@@ -989,6 +1008,11 @@ static void xfuse_dump_fs()
log_debug("found %d entries", g_xrdp_fs.num_entries - FIRST_INODE);
+#if 0
+ log_debug("not dumping xrdp fs");
+ return;
+#endif
+
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
{
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
@@ -1229,6 +1253,9 @@ static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode)
if ((xinode == NULL) || (xinode->mode & S_IFDIR))
return -1;
+ log_always("deleting: inode=%d name=%s", xinode->inode, xinode->name);
+ log_debug("deleting: inode=%d name=%s", xinode->inode, xinode->name);
+
g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
g_xrdp_fs.inode_table[xinode->inode] = NULL;
free(xinode);
@@ -1281,6 +1308,12 @@ static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode)
if ((xinode == NULL) || (xinode->mode & S_IFREG))
return -1;
+ log_always("recursively deleting dir with inode=%d name=%s",
+ xinode->inode, xinode->name);
+
+ log_debug("recursively deleting dir with inode=%d name=%s",
+ xinode->inode, xinode->name);
+
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
{
if ((xip = g_xrdp_fs.inode_table[i]) == NULL)
@@ -1342,60 +1375,6 @@ static void xfuse_update_xrdpfs_size()
g_xrdp_fs.inode_table = vp;
}
-/* LK_TODO do we still need this function */
-#if 0
-static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size,
- off_t off, struct fuse_file_info *fi)
-{
- XRDP_INODE *xinode;
- XRDP_INODE *xinode1;
- struct dirbuf b;
- int first_time = 1;
- int i;
-
- memset(&b, 0, sizeof(struct dirbuf));
-
- for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
- {
- if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
- continue;
-
- /* match parent inode */
- if (xinode->parent_inode != ino)
- continue;
-
- if (first_time)
- {
- first_time = 0;
- if (ino == 1)
- {
- xfuse_dirbuf_add(req, &b, ".", 1);
- xfuse_dirbuf_add(req, &b, "..", 1);
- }
- else
- {
- xinode1 = g_xrdp_fs.inode_table[ino];
- xfuse_dirbuf_add(req, &b, ".", ino);
- xfuse_dirbuf_add(req, &b, "..", xinode1->parent_inode);
- }
- }
-
- xfuse_dirbuf_add(req, &b, xinode->name, xinode->inode);
- }
-
- if (!first_time)
- {
- if (off < b.size)
- fuse_reply_buf(req, b.p + off, min(b.size - off, size));
- else
- fuse_reply_buf(req, NULL, 0);
- }
-
- if (b.p)
- free(b.p);
-}
-#endif
-
/******************************************************************************
** **
** callbacks for devredir **
@@ -1464,8 +1443,9 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
{
- XFUSE_INFO *fip;
- struct dir_info *di;
+ XFUSE_INFO *fip;
+ struct dir_info *di;
+ struct opendir_req *odreq;
log_debug("vp=%p IoStatus=0x%x", vp, IoStatus);
@@ -1473,7 +1453,7 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
if (fip == NULL)
{
log_debug("fip is NULL");
- return;
+ goto done;
}
if (IoStatus != 0)
@@ -1506,6 +1486,22 @@ done:
if (fip)
free(fip);
+
+ /* remove current request */
+ g_free(fifo_remove(&g_fifo_opendir));
+
+ while (1)
+ {
+ /* process next request */
+ odreq = fifo_peek(&g_fifo_opendir);
+ if (!odreq)
+ return;
+
+ if (xfuse_proc_opendir_req(odreq->req, odreq->ino, odreq->fi))
+ g_free(fifo_remove(&g_fifo_opendir)); /* req failed */
+ else
+ break; /* req has been queued */
+ }
}
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
@@ -1903,15 +1899,19 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
}
xino = g_xrdp_fs.inode_table[ino];
+ if (!xino)
+ {
+ log_debug("****** invalid ino=%d", (int) ino);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_ino = ino;
stbuf.st_mode = xino->mode;
stbuf.st_nlink = xino->nlink;
stbuf.st_size = xino->size;
-
fuse_reply_attr(req, &stbuf, 1.0);
- log_debug("exiting");
}
/**
@@ -1977,8 +1977,7 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
int i;
int first_time;
- log_debug("req=%p inode=%d name=%s size=%d offset=%d", req, ino,
- g_xrdp_fs.inode_table[ino]->name, size, off);
+ log_debug("req=%p inode=%d size=%d offset=%d", req, ino, size, off);
/* do we have a valid inode? */
if (!xfuse_is_inode_valid(ino))
@@ -2014,6 +2013,12 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
{
first_time = 0;
ti = g_xrdp_fs.inode_table[ino];
+ if (!ti)
+ {
+ log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_buf(req, NULL, 0);
+ return;
+ }
xfuse_dirbuf_add1(req, &b, ".", ino);
xfuse_dirbuf_add1(req, &b, "..", ti->parent_inode);
}
@@ -2451,6 +2456,12 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
/* if ino points to a dir, fail the open request */
xinode = g_xrdp_fs.inode_table[ino];
+ if (!xinode)
+ {
+ log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
if (xinode->mode & S_IFDIR)
{
log_debug("reading a dir not allowed!");
@@ -2491,8 +2502,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
fip->name[1023] = 0;
fip->reply_type = RT_FUSE_REPLY_OPEN;
- /* LK_TODO need to handle open permissions */
-
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
@@ -2532,6 +2541,12 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
}
XRDP_INODE *xinode = g_xrdp_fs.inode_table[ino];
+ if (!xinode)
+ {
+ log_debug("****** g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, 0);
+ return;
+ }
if (xinode->is_loc_resource)
{
/* specified file is a local resource */
@@ -2748,7 +2763,12 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
return;
}
- xinode = g_xrdp_fs.inode_table[ino];
+ if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
+ {
+ log_debug("g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
if (to_set & FUSE_SET_ATTR_MODE)
{
@@ -2813,9 +2833,40 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
fuse_reply_attr(req, &st, 1.0); /* LK_TODO just faking for now */
}
+/**
+ * Get dir listing
+ *****************************************************************************/
static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
+ struct opendir_req *odreq;
+
+ /* save request */
+ odreq = malloc(sizeof(struct opendir_req));
+ odreq->req = req;
+ odreq->ino = ino;
+ odreq->fi = fi;
+
+ if (fifo_is_empty(&g_fifo_opendir))
+ {
+ fifo_insert(&g_fifo_opendir, odreq);
+ xfuse_proc_opendir_req(req, ino, fi);
+ }
+ else
+ {
+ /* place req in FIFO; xfuse_devredir_cb_enum_dir_done() will handle it */
+ fifo_insert(&g_fifo_opendir, odreq);
+ }
+}
+
+/**
+ * Process the next opendir req
+ *
+ * @return 0 of the request was sent for remote lookup, -1 otherwise
+ *****************************************************************************/
+static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
+ struct fuse_file_info *fi)
+{
struct dir_info *di;
XRDP_INODE *xinode;
XFUSE_INFO *fip;
@@ -2823,19 +2874,26 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
char full_path[4096];
char *cptr;
- log_debug("inode=%d name=%s", ino, g_xrdp_fs.inode_table[ino]->name);
+ log_debug("inode=%d", ino);
if (!xfuse_is_inode_valid(ino))
{
log_error("inode %d is not valid", ino);
fuse_reply_err(req, EBADF);
- return;
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
if (ino == 1)
goto done; /* special case; enumerate top level dir */
- xinode = g_xrdp_fs.inode_table[ino];
+ if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
+ {
+ log_debug("g_xrdp_fs.inode_table[%d] is NULL", ino);
+ fuse_reply_err(req, EBADF);
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
+ }
if (xinode->is_loc_resource)
goto done;
@@ -2846,7 +2904,8 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
if (xinode->is_synced)
{
xfuse_enum_dir(req, ino, size, off, fi);
- return;
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
else
{
@@ -2867,7 +2926,8 @@ do_remote_lookup:
{
log_error("system out of memory");
fuse_reply_err(req, ENOMEM);
- return;
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
fip->req = req;
@@ -2900,7 +2960,7 @@ do_remote_lookup:
}
}
- return;
+ return 0;
done:
@@ -2908,6 +2968,8 @@ done:
di->index = FIRST_INODE;
fi->fh = (long) di;
fuse_reply_open(req, fi);
+ g_free(fifo_remove(&g_fifo_opendir));
+ return -1;
}
/**
diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c
index 05fd3302..cdcc9e94 100644
--- a/sesman/chansrv/devredir.c
+++ b/sesman/chansrv/devredir.c
@@ -1098,7 +1098,11 @@ dev_redir_file_open(void *fusep, tui32 device_id, char *path,
#if 1
/* without the 0x00000010 rdesktop opens files in */
/* O_RDONLY instead of O_RDWR mode */
- DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
+ if (mode & O_RDWR)
+ DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
+ else
+ DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
+
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
CreateDisposition = CD_FILE_OPEN; // WAS 1
#else
diff --git a/sesman/chansrv/fifo.c b/sesman/chansrv/fifo.c
new file mode 100644
index 00000000..630df3cd
--- /dev/null
+++ b/sesman/chansrv/fifo.c
@@ -0,0 +1,255 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@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.
+ */
+
+ /* FIFO implementation to store a pointer to a user struct */
+
+/* module based logging */
+#define MODULE_NAME "FIFO "
+#define LOCAL_DEBUG
+
+#include "fifo.h"
+#include "mlog.h"
+
+/**
+ * Initialize a FIFO that grows as required
+ *
+ * @param fp pointer to a FIFO
+ * @param num_entries initial size
+ *
+ * @return 0 on success, -1 on failure
+ *****************************************************************************/
+int
+fifo_init(FIFO* fp, int num_entries)
+{
+ log_debug_high("entered");
+
+ /* validate params */
+ if (!fp)
+ {
+ log_debug_high("invalid parameters");
+ return -1;
+ }
+
+ if (num_entries < 1)
+ num_entries = 10;
+
+ fp->rd_ptr = 0;
+ fp->wr_ptr = 0;
+ fp->user_data = (long *) g_malloc(sizeof(long) * num_entries);
+
+ if (fp->user_data)
+ {
+ fp->entries = num_entries;
+ log_debug_low("FIFO created; rd_ptr=%d wr_ptr=%d entries=%d",
+ fp->rd_ptr, fp->wr_ptr, fp->entries);
+ return 0;
+ }
+ else
+ {
+ log_error("FIFO create error; system out of memory");
+ fp->entries = 0;
+ return -1;
+ }
+}
+
+/**
+ * Deinit FIFO and release resources
+ *
+ * @param fp FIFO to deinit
+ *
+ * @return 0 on success, -1 on error
+ *****************************************************************************/
+int
+fifo_deinit(FIFO* fp)
+{
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return -1;
+ }
+
+ if (fp->user_data)
+ {
+ g_free(fp->user_data);
+ fp->user_data = 0;
+ }
+
+ fp->rd_ptr = 0;
+ fp->wr_ptr = 0;
+ fp->entries = 0;
+}
+
+/**
+ * Check if FIFO is empty
+ *
+ * @param fp FIFO
+ *
+ * @return 1 if FIFO is empty, 0 otherwise
+ *****************************************************************************/
+int
+fifo_is_empty(FIFO* fp)
+{
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return 0;
+ }
+
+ return (fp->rd_ptr == fp->wr_ptr) ? 1 : 0;
+}
+
+/**
+ * Insert an item at the end
+ *
+ * @param fp FIFO
+ * @param data data to insert into FIFO
+ *
+ * @param 0 on success, -1 on error
+ *****************************************************************************/
+
+int
+fifo_insert(FIFO* fp, void* data)
+{
+ long* lp;
+ int next_val; /* next value for wr_ptr */
+ int i;
+
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return -1;
+ }
+
+ next_val = fp->wr_ptr + 1;
+ if (next_val >= fp->entries)
+ next_val = 0;
+
+ if (next_val == fp->rd_ptr)
+ {
+ /* FIFO is full, expand it by 10 entries */
+ lp = (long *) g_malloc(sizeof(long) * (fp->entries + 10));
+ if (!lp)
+ {
+ log_debug_low("FIFO full; cannot expand, no memory");
+ return -1;
+ }
+
+ log_debug_low("FIFO full, expanding by 10 entries");
+
+ /* copy old data new location */
+ for (i = 0; i < (fp->entries - 1); i++)
+ {
+ lp[i] = fp->user_data[fp->rd_ptr++];
+ if (fp->rd_ptr >= fp->entries)
+ fp->rd_ptr = 0;
+ }
+
+ /* update pointers */
+ fp->rd_ptr = 0;
+ fp->wr_ptr = fp->entries - 1;
+ next_val = fp->entries;
+ fp->entries += 10;
+
+ /* free old data */
+ g_free(fp->user_data);
+ fp->user_data = lp;
+ }
+
+ log_debug_low("inserting data at index %d", fp->wr_ptr);
+
+ fp->user_data[fp->wr_ptr] = (long) data;
+ fp->wr_ptr = next_val;
+
+ return 0;
+}
+
+/**
+ * Remove an item from the head
+ *
+ * @param fp FIFO
+ *
+ * @param data on success, NULL on error
+ *****************************************************************************/
+void*
+fifo_remove(FIFO* fp)
+{
+ long data;
+
+ log_debug_high("entered");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null");
+ return 0;
+ }
+
+ if (fp->rd_ptr == fp->wr_ptr)
+ {
+ log_debug_high("FIFO is empty");
+ return 0;
+ }
+
+ log_debug_low("removing data at index %d", fp->rd_ptr);
+
+ data = fp->user_data[fp->rd_ptr++];
+
+ if (fp->rd_ptr >= fp->entries)
+ {
+ log_debug_high("FIFO rd_ptr wrapped around");
+ fp->rd_ptr = 0;
+ }
+
+ return (void *) data;
+}
+
+/**
+ * Return item from head, but do not remove it
+ *
+ * @param fp FIFO
+ *
+ * @param data on success, NULL on error
+ *****************************************************************************/
+void*
+fifo_peek(FIFO* fp)
+{
+ long data;
+
+ log_debug_high("entered\n");
+
+ if (!fp)
+ {
+ log_debug_high("FIFO is null\n");
+ return 0;
+ }
+
+ if (fp->rd_ptr == fp->wr_ptr)
+ {
+ log_debug_high("FIFO is empty\n");
+ return 0;
+ }
+
+ log_debug_low("peeking data at index %d\n", fp->rd_ptr);
+
+ return (void *) fp->user_data[fp->rd_ptr];
+}
diff --git a/sesman/chansrv/fifo.h b/sesman/chansrv/fifo.h
new file mode 100644
index 00000000..0a23592c
--- /dev/null
+++ b/sesman/chansrv/fifo.h
@@ -0,0 +1,35 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@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.
+ */
+
+ /* FIFO implementation to store a pointer to a user struct */
+
+typedef struct fifo
+{
+ long* user_data;
+ int rd_ptr;
+ int wr_ptr;
+ int entries;
+} FIFO;
+
+int fifo_init(FIFO* fp, int num_entries);
+int fifo_deinit(FIFO* fp);
+int fifo_is_empty(FIFO* fp);
+int fifo_insert(FIFO* fp, void* data);
+void* fifo_remove(FIFO* fp);
+void* fifo_peek(FIFO* fp);
+
diff --git a/sesman/chansrv/mlog.h b/sesman/chansrv/mlog.h
new file mode 100644
index 00000000..866c9692
--- /dev/null
+++ b/sesman/chansrv/mlog.h
@@ -0,0 +1,112 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@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.
+ */
+
+ /* module based logging */
+
+#ifndef _MLOG_H
+#define _MLOG_H
+
+/*
+ * Note1: to enable debug messages, in your .c file, #define LOCAL_DEBUG
+ * BEFORE including this file
+ *
+ * Note2: in your .c file, #define MODULE_NAME, 8 chars long, to print each
+ * log entry with your module name
+ */
+
+#define LOG_ERROR 0
+#define LOG_INFO 1
+#define LOG_DEBUG_LOW 2
+#define LOG_DEBUG_HIGH 3
+#define LOG_LEVEL LOG_ERROR
+
+/*
+ * print always
+ */
+
+#define log_error(_params...) \
+do \
+{ \
+ g_write("[%10.10u]: %s %s: %d: ERROR: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+} \
+while(0)
+
+#define log_always(_params...) \
+do \
+{ \
+ g_write("[%10.10u]: %s %s: %d: ALWAYS: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+} \
+while(0)
+
+/*
+ * print conditionally
+ */
+
+#ifdef LOCAL_DEBUG
+#define log_info(_params...) \
+do \
+{ \
+ if (LOG_INFO <= LOG_LEVEL) \
+ { \
+ g_write("[%10.10u]: %s %s: %d: INFO: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+ } \
+} \
+while(0)
+#else
+#define log_info(_params...)
+#endif
+
+#ifdef LOCAL_DEBUG
+#define log_debug_low(_params...) \
+do \
+{ \
+ if (LOG_DEBUG_LOW <= LOG_LEVEL) \
+ { \
+ g_write("[%10.10u]: %s %s: %d: DEBUG: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+ } \
+} \
+while(0)
+#else
+#define log_debug_low(_params...)
+#endif
+
+#ifdef LOCAL_DEBUG
+#define log_debug_high(_params...) \
+do \
+{ \
+ if (LOG_DEBUG_HIGH <= LOG_LEVEL) \
+ { \
+ g_write("[%10.10u]: %s %s: %d: DEBUG: ", g_time3(), \
+ MODULE_NAME, __func__, __LINE__); \
+ g_writeln (_params); \
+ } \
+} \
+while(0)
+#else
+#define log_debug_high(_params...)
+#endif
+
+#endif /* #ifndef _MLOG_H */
diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c
index 520c9971..b93dba12 100644
--- a/sesman/chansrv/pcsc/xrdp_pcsc.c
+++ b/sesman/chansrv/pcsc/xrdp_pcsc.c
@@ -52,11 +52,22 @@ typedef struct _SCARD_IO_REQUEST
#define LLOGLN(_level, _args) \
do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
-#define SCARD_ESTABLISH_CONTEXT 0x01
-#define SCARD_RELEASE_CONTEXT 0x02
-#define SCARD_LIST_READERS 0x03
-#define SCARD_CONNECT 0x04
-#define SCARD_GET_STATUS_CHANGE 0x0C
+#define SCARD_ESTABLISH_CONTEXT 0x01
+#define SCARD_RELEASE_CONTEXT 0x02
+#define SCARD_LIST_READERS 0x03
+#define SCARD_CONNECT 0x04
+#define SCARD_RECONNECT 0x05
+#define SCARD_DISCONNECT 0x06
+#define SCARD_BEGIN_TRANSACTION 0x07
+#define SCARD_END_TRANSACTION 0x08
+#define SCARD_TRANSMIT 0x09
+#define SCARD_CONTROL 0x0A
+#define SCARD_STATUS 0x0B
+#define SCARD_GET_STATUS_CHANGE 0x0C
+#define SCARD_CANCEL 0x0D
+#define SCARD_CANCEL_TRANSACTION 0x0E
+#define SCARD_GET_ATTRIB 0x0F
+#define SCARD_SET_ATTRIB 0x10
#define SCARD_S_SUCCESS 0x00000000
#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001)
@@ -417,7 +428,7 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
pthread_mutex_unlock(&g_mutex);
return SCARD_F_INTERNAL_ERROR;
}
- if (code != SCARD_RELEASE_CONTEXT)
+ if (code != SCARD_CONNECT)
{
LLOGLN(0, ("SCardConnect: error, bad code"));
pthread_mutex_unlock(&g_mutex);
@@ -467,6 +478,11 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
PCSC_API LONG
SCardBeginTransaction(SCARDHANDLE hCard)
{
+ char msg[256];
+ int code;
+ int bytes;
+ int status;
+
LLOGLN(0, ("SCardBeginTransaction:"));
if (g_sck == -1)
{
@@ -474,8 +490,30 @@ SCardBeginTransaction(SCARDHANDLE hCard)
return SCARD_F_INTERNAL_ERROR;
}
pthread_mutex_lock(&g_mutex);
+ SET_UINT32(msg, 0, hCard);
+ if (send_message(SCARD_BEGIN_TRANSACTION, msg, 4) != 0)
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, send_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ bytes = 256;
+ if (get_message(&code, msg, &bytes) != 0)
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, get_message"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
+ if ((code != SCARD_BEGIN_TRANSACTION) || (bytes != 4))
+ {
+ LLOGLN(0, ("SCardBeginTransaction: error, bad code"));
+ pthread_mutex_unlock(&g_mutex);
+ return SCARD_F_INTERNAL_ERROR;
+ }
pthread_mutex_unlock(&g_mutex);
- return SCARD_S_SUCCESS;
+ status = GET_UINT32(msg, 0);
+ LLOGLN(10, ("SCardBeginTransaction: got status 0x%8.8x", status));
+ return status;
}
/*****************************************************************************/
diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c
index d5ebea2c..9d55807d 100644
--- a/sesman/chansrv/smartcard.c
+++ b/sesman/chansrv/smartcard.c
@@ -1307,6 +1307,8 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs)
/* insert reader name */
num_chars = g_mbstowcs(w_reader_name, rs->reader_name, 99);
+ xstream_wr_u32_le(s, 0);
+ xstream_wr_u32_le(s, 0);
xstream_wr_u32_le(s, num_chars);
if (wide)
{
@@ -1322,6 +1324,7 @@ scard_send_Connect(IRP* irp, tui32 context, int wide, READER_STATE* rs)
xstream_wr_u8(s, w_reader_name[index]);
}
}
+ align_s(s, 4);
/* insert context */
xstream_wr_u32_le(s, 4);
@@ -2058,6 +2061,7 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp,
tui32 IoStatus)
{
tui32 len;
+ struct trans *con;
log_debug("entered");
@@ -2077,7 +2081,9 @@ scard_handle_Connect_Return(struct stream *s, IRP *irp,
/* get OutputBufferLen */
xstream_rd_u32_le(s, len);
-
+ con = (struct trans *) (irp->user_data);
+ scard_function_connect_return(con, s, len);
+ devredir_irp_delete(irp);
log_debug("leaving");
}
diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c
index a9c5f3e4..62b3b722 100644
--- a/sesman/chansrv/smartcard_pcsc.c
+++ b/sesman/chansrv/smartcard_pcsc.c
@@ -56,6 +56,7 @@
#define XRDP_PCSC_STATE_GOT_RC (1 << 2) /* release context */
#define XRDP_PCSC_STATE_GOT_GSC (1 << 3) /* get status change */
#define XRDP_PCSC_STATE_GOT_C (1 << 4) /* connect */
+#define XRDP_PCSC_STATE_GOT_BT (1 << 5) /* begin transaction */
/* TODO: put this in con */
static int g_xrdp_pcsc_state = XRDP_PCSC_STATE_NONE;
@@ -348,6 +349,61 @@ scard_process_connect(struct trans *con, struct stream *in_s)
}
/*****************************************************************************/
+int APP_CC
+scard_function_connect_return(struct trans *con,
+ struct stream *in_s,
+ int len)
+{
+ int dwActiveProtocol;
+ int hCard;
+ int bytes;
+ struct stream *out_s;
+
+ g_hexdump(in_s->p, len);
+ if ((g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_C) == 0)
+ {
+ LLOGLN(0, ("scard_function_connect_return: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state &= ~XRDP_PCSC_STATE_GOT_C;
+ in_uint8s(in_s, 36);
+ in_uint32_le(in_s, dwActiveProtocol);
+ in_uint8s(in_s, 36);
+ in_uint32_le(in_s, hCard);
+ out_s = trans_get_out_s(con, 8192);
+ s_push_layer(out_s, iso_hdr, 8);
+ out_uint32_le(out_s, hCard);
+ out_uint32_le(out_s, dwActiveProtocol);
+ out_uint32_le(out_s, 0); /* SCARD_S_SUCCESS status */
+ s_mark_end(out_s);
+ bytes = (int) (out_s->end - out_s->data);
+ s_pop_layer(out_s, iso_hdr);
+ out_uint32_le(out_s, bytes - 8);
+ out_uint32_le(out_s, 0x04); /* SCARD_CONNECT 0x04 */
+ return trans_force_write(con);
+}
+
+/*****************************************************************************/
+/* returns error */
+int APP_CC
+scard_process_begin_transaction(struct trans *con, struct stream *in_s)
+{
+ int hCard;
+
+ LLOGLN(0, ("scard_process_begin_transaction:"));
+ if (g_xrdp_pcsc_state & XRDP_PCSC_STATE_GOT_BT)
+ {
+ LLOGLN(0, ("scard_process_begin_transaction: opps"));
+ return 1;
+ }
+ g_xrdp_pcsc_state |= XRDP_PCSC_STATE_GOT_BT;
+ in_uint32_le(in_s, hCard);
+ LLOGLN(0, ("scard_process_begin_transaction: hCard 0x%8.8x", hCard));
+ scard_send_begin_transaction(con, hCard);
+ return 0;
+}
+
+/*****************************************************************************/
/* returns error */
int APP_CC
scard_process_get_status_change(struct trans *con, struct stream *in_s)
@@ -495,6 +551,7 @@ scard_process_msg(struct trans *con, struct stream *in_s, int command)
case 0x07: /* SCARD_BEGIN_TRANSACTION */
LLOGLN(0, ("scard_process_msg: SCARD_BEGIN_TRANSACTION"));
+ rv = scard_process_begin_transaction(con, in_s);
break;
case 0x08: /* SCARD_END_TRANSACTION */
diff --git a/sesman/chansrv/smartcard_pcsc.h b/sesman/chansrv/smartcard_pcsc.h
index 81bf5046..94effea9 100644
--- a/sesman/chansrv/smartcard_pcsc.h
+++ b/sesman/chansrv/smartcard_pcsc.h
@@ -41,5 +41,8 @@ int APP_CC scard_function_list_readers_return(struct trans *con,
int APP_CC scard_function_get_status_change_return(struct trans *con,
struct stream *in_s,
int len);
+int APP_CC scard_function_connect_return(struct trans *con,
+ struct stream *in_s,
+ int len);
#endif /* end #ifndef _SMARTCARD_PCSC_H */