diff --git a/.gitignore b/.gitignore
index 99a76ffaa..0dcd5daa7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,8 +14,9 @@ Makefile
*.cproject
*.settings
-# Doxygen
+# Documentation
docs/api
+client/X11/xfreerdp.1
# Mac OS X
.DS_Store
diff --git a/channels/rdpsnd/pulse/rdpsnd_pulse.c b/channels/rdpsnd/pulse/rdpsnd_pulse.c
index af316fbe7..1b2c59473 100644
--- a/channels/rdpsnd/pulse/rdpsnd_pulse.c
+++ b/channels/rdpsnd/pulse/rdpsnd_pulse.c
@@ -122,6 +122,8 @@ static void rdpsnd_pulse_stream_success_callback(pa_stream* stream, int success,
static void rdpsnd_pulse_wait_for_operation(rdpsndPulsePlugin* pulse, pa_operation* operation)
{
+ if (operation == NULL)
+ return;
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
{
pa_threaded_mainloop_wait(pulse->mainloop);
diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt
index 38364105d..2311d1250 100644
--- a/client/X11/CMakeLists.txt
+++ b/client/X11/CMakeLists.txt
@@ -17,6 +17,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+include(FindXmlto)
include_directories(${X11_INCLUDE_DIRS})
add_executable(xfreerdp
@@ -32,26 +33,41 @@ add_executable(xfreerdp
xf_window.h
xfreerdp.c
xfreerdp.h)
-
+
+if(WITH_MANPAGES)
+ if(XMLTO_FOUND)
+ add_custom_command(OUTPUT xfreerdp.1
+ COMMAND ${XMLTO_EXECUTABLE} man ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp.1.xml
+ DEPENDS xfreerdp.1.xml)
+
+ add_custom_target(xfreerdp.manpage ALL
+ DEPENDS xfreerdp.1)
+
+ install(FILES xfreerdp.1 DESTINATION share/man/man1)
+ else(XMLTO_FOUND)
+ message(WARNING "WITH_MANPAGES was set, but xmlto was not found. man-pages will not be installed")
+ endif(XMLTO_FOUND)
+endif(WITH_MANPAGES)
+
find_package(Xinerama)
if(XINERAMA_FOUND)
- add_definitions(-DWITH_XINERAMA)
+ add_definitions(-DWITH_XINERAMA -DWITH_XEXT)
include_directories(${XINERAMA_INCLUDE_DIRS})
target_link_libraries(xfreerdp ${XINERAMA_LIBRARIES})
endif()
find_package(Xext)
-if(Xext_FOUND)
+if(XEXT_FOUND)
add_definitions(-DWITH_XEXT)
- include_directories(${Xext_INCLUDE_DIRS})
- target_link_libraries(xfreerdp ${Xext_LIBRARIES})
+ include_directories(${XEXT_INCLUDE_DIRS})
+ target_link_libraries(xfreerdp ${XEXT_LIBRARIES})
endif()
find_package(Xcursor)
if(Xcursor_FOUND)
add_definitions(-DWITH_XCURSOR)
include_directories(${Xcursor_INCLUDE_DIRS})
- target_link_libraries(xfreerdp ${Xext_LIBRARIES})
+ target_link_libraries(xfreerdp ${Xcursor_LIBRARIES})
endif()
target_link_libraries(xfreerdp freerdp-core)
@@ -63,3 +79,4 @@ target_link_libraries(xfreerdp freerdp-utils)
target_link_libraries(xfreerdp ${X11_LIBRARIES})
install(TARGETS xfreerdp DESTINATION bin)
+
diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c
index 15dc8ddd8..11bc57c9d 100644
--- a/client/X11/xf_event.c
+++ b/client/X11/xf_event.c
@@ -343,7 +343,7 @@ boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
if (xfi->mouse_active && (app != True))
XGrabKeyboard(xfi->display, xfi->window->handle, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- xf_rail_send_activate(xfi, event->xany.window, True);
+ //xf_rail_send_activate(xfi, event->xany.window, True);
xf_kbd_focus_in(xfi);
return True;
@@ -359,7 +359,7 @@ boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app)
if (event->xfocus.mode == NotifyWhileGrabbed)
XUngrabKeyboard(xfi->display, CurrentTime);
- xf_rail_send_activate(xfi, event->xany.window, False);
+ //xf_rail_send_activate(xfi, event->xany.window, False);
return True;
}
@@ -476,7 +476,7 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
app = True;
}
-#if 1
+#if 0
if (event->type != MotionNotify)
printf("X11 %s Event: wnd=0x%X\n", X11_EVENT_STRINGS[event->type], (uint32)event->xany.window);
#endif
diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c
index c43f47dc9..ca815a771 100644
--- a/client/X11/xf_rail.c
+++ b/client/X11/xf_rail.c
@@ -82,6 +82,7 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
window->windowId, window->ownerWindowId);
xfparent = NULL;
+
if (window->ownerWindowId != 0)
{
rdpWindow* p = NULL;
@@ -89,7 +90,7 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
p = window_list_get_by_id(xfi->rail->list, window->ownerWindowId);
if (p != NULL)
- xfparent = (xfWindow *)p->extra;
+ xfparent = (xfWindow *) p->extra;
}
xfw = xf_CreateWindow((xfInfo*) rail->extra, xfparent,
@@ -97,10 +98,10 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
window->windowWidth, window->windowHeight,
window->windowId);
- XStoreName(xfi->display, xfw->handle, window->title);
-
xf_SetWindowStyle(xfi, xfw, window->style, window->extendedStyle);
+ XStoreName(xfi->display, xfw->handle, window->title);
+
window->extra = (void*) xfw;
window->extraId = (void*) xfw->handle;
}
@@ -165,6 +166,17 @@ void xf_rail_SetWindowRects(rdpRail* rail, rdpWindow* window)
xf_SetWindowRects(xfi, xfw, window->windowRects, window->numWindowRects);
}
+void xf_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window)
+{
+ xfInfo* xfi;
+ xfWindow* xfw;
+
+ xfi = (xfInfo*) rail->extra;
+ xfw = (xfWindow*) window->extra;
+
+ xf_SetWindowVisibilityRects(xfi, xfw, window->windowRects, window->numWindowRects);
+}
+
void xf_rail_DestroyWindow(rdpRail* rail, rdpWindow* window)
{
xfWindow* xfw;
@@ -181,6 +193,7 @@ void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail)
rail->SetWindowText = xf_rail_SetWindowText;
rail->SetWindowIcon = xf_rail_SetWindowIcon;
rail->SetWindowRects = xf_rail_SetWindowRects;
+ rail->SetWindowVisibilityRects = xf_rail_SetWindowVisibilityRects;
rail->DestroyWindow = xf_rail_DestroyWindow;
}
diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c
index 2a22bb0f7..28f9a45ee 100644
--- a/client/X11/xf_window.c
+++ b/client/X11/xf_window.c
@@ -41,9 +41,6 @@ struct _PropMotifWmHints
};
typedef struct _PropMotifWmHints PropMotifWmHints;
-void xf_ReferenceWindow(xfInfo* xfi, xfWindow* window);
-void xf_DereferenceWindow(xfInfo* xfi, xfWindow* window);
-
void xf_SendClientMessage(xfInfo* xfi, xfWindow* window, Atom atom, long msg, long d1, long d2, long d3)
{
XEvent xevent;
@@ -162,43 +159,38 @@ void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show)
window->decorations = show;
}
+void xf_SetWindowUnlisted(xfInfo* xfi, xfWindow* window)
+{
+ Atom window_state[2];
+
+ window_state[0] = xfi->_NET_WM_STATE_SKIP_PAGER;
+ window_state[1] = xfi->_NET_WM_STATE_SKIP_TASKBAR;
+
+ XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_STATE,
+ XA_ATOM, 32, PropModeReplace, (uint8*) &window_state, 2);
+}
+
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style)
{
Atom window_type;
window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
- if (((style & WS_POPUP) !=0) ||
- ((style & WS_DLGFRAME) != 0) ||
- ((ex_style & WS_EX_DLGMODALFRAME) != 0)
- )
+ if ((style & WS_POPUP) || (style & WS_DLGFRAME) || (ex_style & WS_EX_DLGMODALFRAME))
{
window_type = xfi->_NET_WM_WINDOW_TYPE_DIALOG;
}
- else if ((ex_style & WS_EX_TOOLWINDOW) != 0)
+
+ if (ex_style & WS_EX_TOOLWINDOW)
{
+ xf_SetWindowUnlisted(xfi, window);
window_type = xfi->_NET_WM_WINDOW_TYPE_UTILITY;
}
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_WINDOW_TYPE,
- xfi->_NET_WM_WINDOW_TYPE, 32, PropModeReplace, (unsigned char*)&window_type, 1);
+ XA_ATOM, 32, PropModeReplace, (uint8*) &window_type, 1);
}
-void xf_SetWindowChildState(xfInfo* xfi, xfWindow* window)
-{
- Atom window_state[2];
-
- if (window->parent != NULL)
- {
- window_state[0] = xfi->_NET_WM_STATE_SKIP_PAGER;
- window_state[1] = xfi->_NET_WM_STATE_SKIP_TASKBAR;
-
- XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_STATE,
- xfi->_NET_WM_STATE, 32, PropModeReplace, (unsigned char*)&window_state, 2);
- }
-}
-
-
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height)
{
xfWindow* window;
@@ -295,36 +287,18 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
XGCValues gcv;
int input_mask;
XClassHint* class_hints;
- Window parent_handle;
- int lx;
- int ly;
window->ref_count = 0;
window->decorations = False;
window->fullscreen = False;
window->parent = parent;
- lx = x;
- ly = y;
- parent_handle = RootWindowOfScreen(xfi->screen);
-
- if (window->parent != NULL)
- {
- lx = x - window->parent->left;
- ly = y - window->parent->top;
- parent_handle = parent->handle;
- }
-
- window->handle = XCreateWindow(xfi->display, parent_handle,
- lx, ly, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
+ window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
+ x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel, &xfi->attribs);
- xf_ReferenceWindow(xfi, window);
- xf_ReferenceWindow(xfi, window->parent);
-
xf_SetWindowDecorations(xfi, window, window->decorations);
- xf_SetWindowChildState(xfi, window);
class_hints = XAllocClassHint();
@@ -352,10 +326,6 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
window->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv);
window->surface = XCreatePixmap(xfi->display, window->handle, window->width, window->height, xfi->depth);
- printf("xf_CreateWindow: h=0x%X p=0x%X x=%d y=%d w=%d h=%d\n", (uint32)window->handle,
- (window->parent != NULL) ? (uint32)window->parent->handle : 0,
- x, y, width, height);
-
xf_MoveWindow(xfi, window, x, y, width, height);
}
@@ -364,37 +334,19 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
{
- int lx, ly;
Pixmap surface;
if ((width * height) < 1)
return;
- printf("xf_MoveWindow: BEFORE correctness h=0x%X x=%d y=%d w=%d h=%d\n",
- (uint32) window->handle, x, y, width, height);
-
xf_FixWindowCoordinates(&x, &y, &width, &height);
- if (window->parent != NULL)
- {
- lx = x - window->parent->left;
- ly = y - window->parent->top;
- }
- else
- {
- lx = x;
- ly = y;
- }
-
- printf("xf_MoveWindow: AFTER correctness h=0x%X x=%d y=%d lx=%d ly=%d w=%d h=%d \n",
- (uint32) window->handle, x, y, lx, ly, width, height);
-
if (window->width == width && window->height == height)
- XMoveWindow(xfi->display, window->handle, lx, ly);
+ XMoveWindow(xfi->display, window->handle, x, y);
else if (window->left == x && window->top == y)
XResizeWindow(xfi->display, window->handle, width, height);
else
- XMoveResizeWindow(xfi->display, window->handle, lx, ly, width, height);
+ XMoveResizeWindow(xfi->display, window->handle, x, y, width, height);
surface = XCreatePixmap(xfi->display, window->handle, width, height, xfi->depth);
XCopyArea(xfi->display, surface, window->surface, window->gc, 0, 0, window->width, window->height, 0, 0);
@@ -490,42 +442,41 @@ void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int n
xfree(xrects);
}
-void xf_ReferenceWindow(xfInfo* xfi, xfWindow* window)
+void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects)
{
- if (window == NULL) return;
- window->ref_count++;
-}
+ int i;
+ XRectangle* xrects;
-void xf_DereferenceWindow(xfInfo* xfi, xfWindow* window)
-{
- if (window == NULL) return;
+ xrects = xmalloc(sizeof(XRectangle) * nrects);
- window->ref_count--;
- if (window->ref_count == 0)
+ for (i = 0; i < nrects; i++)
{
- printf("xf_DerefrenceWindow: destroying h=0x%X p=0x%X\n", (uint32)window->handle,
- (window->parent != NULL) ? (uint32)window->parent->handle : 0);
-
- if (window->gc)
- XFreeGC(xfi->display, window->gc);
- if (window->surface)
- XFreePixmap(xfi->display, window->surface);
- if (window->handle)
- {
- XUnmapWindow(xfi->display, window->handle);
- XDestroyWindow(xfi->display, window->handle);
- }
- xfree(window);
+ xrects[i].x = rects[i].left;
+ xrects[i].y = rects[i].top;
+ xrects[i].width = rects[i].right - rects[i].left;
+ xrects[i].height = rects[i].bottom - rects[i].top;
}
+
+#ifdef WITH_XEXT
+ XShapeCombineRectangles(xfi->display, window->handle, ShapeBounding, 0, 0, xrects, nrects, ShapeSet, 0);
+#endif
+
+ xfree(xrects);
}
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window)
{
- xfWindow* parent = window->parent;
+ if (window->gc)
+ XFreeGC(xfi->display, window->gc);
- printf("xf_DestroyWindow: h=0x%X p=0x%X\n", (uint32)window->handle,
- (window->parent != NULL) ? (uint32)window->parent->handle : 0);
+ if (window->surface)
+ XFreePixmap(xfi->display, window->surface);
- xf_DereferenceWindow(xfi, window);
- xf_DereferenceWindow(xfi, parent);
+ if (window->handle)
+ {
+ XUnmapWindow(xfi->display, window->handle);
+ XDestroyWindow(xfi->display, window->handle);
+ }
+
+ xfree(window);
}
diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h
index e71eacae1..d9046d89d 100644
--- a/client/X11/xf_window.h
+++ b/client/X11/xf_window.h
@@ -52,6 +52,7 @@ boolean xf_GetWorkArea(xfInfo* xfi);
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen);
void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show);
+void xf_SetWindowUnlisted(xfInfo* xfi, xfWindow* window);
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height);
@@ -60,6 +61,7 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state);
void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon);
void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects);
+void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style);
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window);
diff --git a/client/X11/xfreerdp.1.xml b/client/X11/xfreerdp.1.xml
new file mode 100644
index 000000000..88b897dac
--- /dev/null
+++ b/client/X11/xfreerdp.1.xml
@@ -0,0 +1,389 @@
+
+
+
+ 2011-08-27
+
+ The FreeRDP-Team
+
+
+
+ xfreerdp
+ 1
+ freerdp
+ xfreerdp
+
+
+ xfreerdp
+ X11 frontend to libFreeRDP
+
+
+
+ 2011-08-27
+
+
+ xfreerdp [options] server[:port] [[options] server[:port] …]
+
+
+
+
+ 2011-08-27
+
+ DESCRIPTION
+
+ xfreerdp is a frontend to libFreeRDP,
+ which implements a client to the Remote Desktop Protocol (RDP).
+ RDP is used in a number of Microsoft products including Microsoft Windows
+ versions starting from NT Terminal Server. RDP is also implemented by xrdp and VirtualBox.
+
+
+
+ OPTIONS
+
+
+ -0
+
+
+ Attach to the admin console of the server.
+
+
+
+
+ -a bpp
+
+
+ Sets the color depth for the connection to bpp bits per pixel.
+ Valid values are 8, 15, 16, 24 and 32. The default value is the color depth of the FreeRDP-window.
+
+
+
+
+ -c dir
+
+
+ Sets the working-dir to dir.
+ This parameter is only used when an AlternateShell () is requested.
+ dir should contain the executable file specified in the AlternateShell.
+
+
+
+
+ -D
+
+
+ Removes the windows decorations.
+
+
+
+
+ -d
+
+
+ Domain used in authentication.
+
+
+
+
+ -f
+
+
+ start in full screen mode. This mode can always be en- and disabled using Ctrl-Alt-Enter.
+
+
+
+
+ -g geometry
+
+
+ Sets the size of the FreeRDP-window (and of the remote desktop, when establishing a new connection).
+ geometry can have one of the following forms:
+
+
+
+ WxH -
+ in this case the resulting window will be of
+ WxH pixels.
+
+
+
+
+ P% -
+ in this case the resulting window will be P%
+ of your screen.
+
+
+
+
+ The special keyword workarea -
+ in this case the resulting window will be of the same size as your workarea.
+
+
+
+
+
+
+
+ -k id
+
+
+ Sets the keyboard-layout-id to id.
+
+
+
+
+ -m
+
+
+ Don't send mouse motion events.
+
+
+
+
+
+ -n hostname
+
+
+ Set the reported client hostname to hostname.
+ Default is to automatically detect the hostname.
+
+
+
+
+ -o
+
+
+ Play audio on the console instead of redirecting to the client.
+
+
+
+
+ -p password
+
+
+ Password used in authentication.
+
+
+
+
+ -s shell
+
+
+ Sets the startup-shell to shell.
+ This parameter should contain a complete path to the alternate shell.
+ If the alternete shell requires a different working directory use .
+
+
+
+
+ -t port
+
+
+ Connect to port, instead of the default 3389.
+
+
+
+
+ -u username
+
+
+ Username used in authentication.
+
+
+
+
+ -x flag
+
+
+ Set the experiance performance flags.
+ flag can be one of:
+
+
+
+ m - (modem): Equivalent to 15.
+
+
+
+
+ b - (broadband): Equivalent to 1.
+
+
+
+
+ l - (lan): Equivalent to 0.
+
+
+
+
+ num - A number that represents a
+ bit-mask, were numbers mean the following
+ Taken from
+ MS-RDPBCGR Scetion 2.2.1.11.1.1.1 - Extended Info Packet:
+
+
+ 1: Disable desktop wallpaper.
+
+
+ 2: Disable full-window drag (only the window outline is displayed when the window is moved).
+
+
+ 4: Disable menu animations.
+
+
+ 8: Disable user interface themes.
+
+
+ 32: Disable mouse cursor shadows.
+
+
+ 64: Disable cursor blinking.
+
+
+ 128: Enable font smoothing.
+
+
+ 256: Enable Desktop Composition.
+
+
+
+
+
+
+
+
+
+ -z
+
+
+ Enable compression.
+
+
+
+
+ --app
+
+
+ initialize a RemoteApp connection. This implies -g workarea.
+ FIXME: How to do RemoteApp
+
+
+
+
+ --ext
+
+
+ load an extension
+ FIXME: How to do this
+
+
+
+
+ --no-auth
+
+
+ Skips authentication. This is useful e.g. for the current FreeRDP server that doesn't yet support server-side authentication.
+
+
+
+
+ --no-fastpath
+
+
+ Disables fast-path. Use slow-path packets instead, which have larger headers.
+ It might be good for debugging certain issues when you suspect it might be
+ linked to the parsing of one of the two header types.
+
+
+
+
+ --no-osb
+
+
+ Disable off screen bitmaps.
+
+
+
+
+ --plugin
+
+
+ load a plugin
+ FIXME: How to do this
+
+
+
+
+ --rfx
+
+
+ Enable RemoteFX.
+
+
+
+
+ --no-rdp
+
+
+ Disable Standard RDP encryption.
+
+
+
+
+ --no-tls
+
+
+ Disable TLS encryption.
+
+
+
+
+ --no-nla
+
+
+ Disable network level authentication.
+
+
+
+
+ --sec proto
+
+
+ force protocol security. proto can be one of rdp, tls or nla.
+
+
+
+
+ --version
+
+
+ Print version information.
+
+
+
+
+
+
+
+
+
+ LINKS
+
+ http://www.freerdp.com/
+
+
+
diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c
index 97898239c..0fb5ea9bc 100644
--- a/client/X11/xfreerdp.c
+++ b/client/X11/xfreerdp.c
@@ -718,7 +718,7 @@ int main(int argc, char* argv[])
chanman = freerdp_chanman_new();
SET_CHANMAN(instance, chanman);
- instance->settings->sw_gdi = False;
+ instance->settings->sw_gdi = True;
if (freerdp_parse_args(instance->settings, argc, argv,
xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0)
diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake
index c49541b80..295b0cd88 100644
--- a/cmake/ConfigOptions.cmake
+++ b/cmake/ConfigOptions.cmake
@@ -9,5 +9,6 @@ option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." OFF)
option(WITH_DEBUG_LICENSE "Print license debug messages." OFF)
option(WITH_DEBUG_GDI "Print graphics debug messages." OFF)
option(WITH_DEBUG_RFX "Print RemoteFX debug messages." OFF)
+option(WITH_MANPAGES "Generate manpages." ON)
option(WITH_PROFILER "Compile profiler." OFF)
option(WITH_SSE2 "Use SSE2 optimization." OFF)
diff --git a/cmake/FindXext.cmake b/cmake/FindXext.cmake
index 211de22bc..cc4bf5dbd 100644
--- a/cmake/FindXext.cmake
+++ b/cmake/FindXext.cmake
@@ -28,22 +28,22 @@
# limitations under the License.
#=============================================================================
-find_path(Xext_INCLUDE_DIR NAMES Xext.h
+find_path(XEXT_INCLUDE_DIR NAMES Xext.h
PATH_SUFFIXES X11/extensions
DOC "The Xext include directory"
)
-find_library(Xext_LIBRARY NAMES Xext
+find_library(XEXT_LIBRARY NAMES Xext
DOC "The Xext library"
)
include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Xext DEFAULT_MSG Xext_LIBRARY Xext_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(XEXT DEFAULT_MSG XEXT_LIBRARY XEXT_INCLUDE_DIR)
-if(Xext_FOUND)
- set( Xext_LIBRARIES ${Xext_LIBRARY} )
- set( Xext_INCLUDE_DIRS ${Xext_INCLUDE_DIR} )
+if(XEXT_FOUND)
+ set( XEXT_LIBRARIES ${XEXT_LIBRARY} )
+ set( XEXT_INCLUDE_DIRS ${XEXT_INCLUDE_DIR} )
endif()
-mark_as_advanced(Xext_INCLUDE_DIR Xext_LIBRARY)
+mark_as_advanced(XEXT_INCLUDE_DIR XEXT_LIBRARY)
diff --git a/cmake/FindXmlto.cmake b/cmake/FindXmlto.cmake
new file mode 100644
index 000000000..7d2107bab
--- /dev/null
+++ b/cmake/FindXmlto.cmake
@@ -0,0 +1,35 @@
+# - Find xmlto
+# Find the xmlto docbook xslt frontend
+#
+# This module defines the following variables:
+# XMLTO_FOUND - True if xmlto was found
+# XMLTO_EXECUTABLE - Path to xmlto, if xmlto was found
+#
+
+#=============================================================================
+# Copyright 2011 Nils Andresen
+#
+# 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.
+#=============================================================================
+set(XMLTO_FOUND false)
+
+find_program(XMLTO_EXECUTABLE
+ NAMES xmlto
+ DOC "docbook xslt frontend")
+
+if(XMLTO_EXECUTABLE)
+ set(XMLTO_FOUND true)
+ message(STATUS "Found XMLTO: ${XMLTO_EXECUTABLE}")
+endif()
+
+mark_as_advanced(XMLTO_EXECUTABLE)
diff --git a/cunit/CMakeLists.txt b/cunit/CMakeLists.txt
index 5b5171259..88fe5cc3f 100644
--- a/cunit/CMakeLists.txt
+++ b/cunit/CMakeLists.txt
@@ -44,6 +44,8 @@ add_executable(test_freerdp
test_list.h
test_orders.c
test_orders.h
+ test_pcap.c
+ test_pcap.h
test_license.c
test_license.h
test_stream.c
diff --git a/cunit/test_freerdp.c b/cunit/test_freerdp.c
index d07206914..d5ffa047c 100644
--- a/cunit/test_freerdp.c
+++ b/cunit/test_freerdp.c
@@ -37,6 +37,7 @@
#include "test_librfx.h"
#include "test_freerdp.h"
#include "test_rail.h"
+#include "test_pcap.h"
void dump_data(unsigned char * p, int len, int width, char* name)
{
@@ -188,6 +189,10 @@ int main(int argc, char* argv[])
{
add_per_suite();
}
+ else if (strcmp("pcap", argv[*pindex]) == 0)
+ {
+ add_pcap_suite();
+ }
else if (strcmp("ber", argv[*pindex]) == 0)
{
add_ber_suite();
diff --git a/cunit/test_pcap.c b/cunit/test_pcap.c
new file mode 100644
index 000000000..d18856f4d
--- /dev/null
+++ b/cunit/test_pcap.c
@@ -0,0 +1,99 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * pcap File Format Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+
+#include "test_pcap.h"
+
+int init_pcap_suite(void)
+{
+ return 0;
+}
+
+int clean_pcap_suite(void)
+{
+ return 0;
+}
+
+int add_pcap_suite(void)
+{
+ add_test_suite(pcap);
+
+ add_test_function(pcap);
+
+ return 0;
+}
+
+uint8 test_packet_1[16] =
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
+
+uint8 test_packet_2[32] =
+ "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"
+ "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB";
+
+uint8 test_packet_3[64] =
+ "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
+ "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
+ "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
+ "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC";
+
+typedef struct
+{
+ void* data;
+ uint32 length;
+} test_packet;
+
+void test_pcap(void)
+{
+ rdpPcap* pcap;
+ pcap_record record;
+ test_packet packets[3];
+
+ packets[0].data = test_packet_1;
+ packets[0].length = sizeof(test_packet_1);
+ packets[1].data = test_packet_2;
+ packets[1].length = sizeof(test_packet_2);
+ packets[2].data = test_packet_3;
+ packets[2].length = sizeof(test_packet_3);
+
+ pcap = pcap_open("/tmp/test.pcap", True);
+ pcap_add_record(pcap, test_packet_1, sizeof(test_packet_1));
+ pcap_flush(pcap);
+ pcap_add_record(pcap, test_packet_2, sizeof(test_packet_2));
+ pcap_flush(pcap);
+ pcap_add_record(pcap, test_packet_3, sizeof(test_packet_3));
+ pcap_close(pcap);
+
+ pcap = pcap_open("/tmp/test.pcap", False);
+
+ int i = 0;
+ while (pcap_has_next_record(pcap))
+ {
+ pcap_get_next_record(pcap, &record);
+ CU_ASSERT(record.length == packets[i].length)
+ i++;
+ }
+
+ CU_ASSERT(i == 3);
+
+ pcap_close(pcap);
+}
+
diff --git a/cunit/test_pcap.h b/cunit/test_pcap.h
new file mode 100644
index 000000000..f506edcaa
--- /dev/null
+++ b/cunit/test_pcap.h
@@ -0,0 +1,26 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * pcap File Format Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau
+ *
+ * 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.
+ */
+
+#include "test_freerdp.h"
+
+int init_pcap_suite(void);
+int clean_pcap_suite(void);
+int add_pcap_suite(void);
+
+void test_pcap(void);
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 444d227f6..463315557 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -17,5 +17,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-file(GLOB HEADERS "freerdp/*.h")
+file(GLOB HEADERS "freerdp/*")
install_files(/include/freerdp FILES ${HEADERS})
diff --git a/include/freerdp/rail/rail.h b/include/freerdp/rail/rail.h
index 9e50d28fc..00f90b5e9 100644
--- a/include/freerdp/rail/rail.h
+++ b/include/freerdp/rail/rail.h
@@ -40,6 +40,7 @@ typedef void (*railShowWindow)(rdpRail* rail, rdpWindow* window, uint8 state);
typedef void (*railSetWindowText)(rdpRail* rail, rdpWindow* window);
typedef void (*railSetWindowIcon)(rdpRail* rail, rdpWindow* window, rdpIcon* icon);
typedef void (*railSetWindowRects)(rdpRail* rail, rdpWindow* window);
+typedef void (*railSetWindowVisibilityRects)(rdpRail* rail, rdpWindow* window);
struct rdp_rail
{
@@ -56,6 +57,7 @@ struct rdp_rail
railSetWindowText SetWindowText;
railSetWindowIcon SetWindowIcon;
railSetWindowRects SetWindowRects;
+ railSetWindowVisibilityRects SetWindowVisibilityRects;
};
FREERDP_API void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update);
diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h
index 861620fc6..9adf77bb7 100644
--- a/include/freerdp/settings.h
+++ b/include/freerdp/settings.h
@@ -297,6 +297,11 @@ struct rdp_settings
uint8 rfx_codec_id;
boolean frame_acknowledge;
+ boolean dump_rfx;
+ boolean play_rfx;
+ char* dump_rfx_file;
+ char* play_rfx_file;
+
boolean remote_app;
uint8 num_icon_caches;
uint16 num_icon_cache_entries;
diff --git a/include/freerdp/update.h b/include/freerdp/update.h
index 591d5bef2..aaaf56567 100644
--- a/include/freerdp/update.h
+++ b/include/freerdp/update.h
@@ -22,6 +22,8 @@
#include
#include
+#include
+#include
/* Common */
@@ -1063,6 +1065,7 @@ typedef void (*pcMonitoredDesktop)(rdpUpdate* update, WINDOW_ORDER_INFO* orderIn
typedef void (*pcNonMonitoredDesktop)(rdpUpdate* update, WINDOW_ORDER_INFO* orderInfo);
typedef void (*pcSurfaceBits)(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command);
+typedef void (*pcSurfaceCommand)(rdpUpdate* update, STREAM* s);
struct rdp_update
{
@@ -1072,6 +1075,10 @@ struct rdp_update
void* param1;
void* param2;
+ boolean dump_rfx;
+ boolean play_rfx;
+ rdpPcap* pcap_rfx;
+
pcBeginPaint BeginPaint;
pcEndPaint EndPaint;
pcSetBounds SetBounds;
@@ -1142,6 +1149,7 @@ struct rdp_update
pcNonMonitoredDesktop NonMonitoredDesktop;
pcSurfaceBits SurfaceBits;
+ pcSurfaceCommand SurfaceCommand;
BITMAP_UPDATE bitmap_update;
PALETTE_UPDATE palette_update;
diff --git a/include/freerdp/utils/certstore.h b/include/freerdp/utils/certstore.h
new file mode 100644
index 000000000..75e8ea3ce
--- /dev/null
+++ b/include/freerdp/utils/certstore.h
@@ -0,0 +1,42 @@
+#ifndef __CERTSTORE_UTILS_H
+#define __CERTSTORE_UTILS_H
+
+typedef struct rdp_certstore rdpCertstore;
+typedef struct rdp_certdata rdpCertdata;
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct rdp_certdata
+{
+ char* thumbprint;
+ char* hostname;
+};
+
+struct rdp_certstore
+{
+ FILE* fp;
+ char* path;
+ char* file;
+ char* home;
+ int match;
+ struct rdp_certdata* certdata;
+};
+
+void certstore_create(rdpCertstore* certstore);
+void certstore_open(rdpCertstore* certstore);
+void certstore_load(rdpCertstore* certstore);
+void certstore_close(rdpCertstore* certstore);
+char* get_local_certloc();
+rdpCertdata* certdata_new(char* host_name,char* fingerprint);
+void certdata_free(rdpCertdata* certdata);
+void certstore_init(rdpCertstore* certstore);
+rdpCertstore* certstore_new(rdpCertdata* certdata);
+void certstore_free(rdpCertstore* certstore);
+int match_certdata(rdpCertstore* certstore);
+void print_certdata(rdpCertstore* certstore);
+#endif /* __CERTSTORE_UTILS_H */
diff --git a/include/freerdp/utils/pcap.h b/include/freerdp/utils/pcap.h
new file mode 100644
index 000000000..a431fbc60
--- /dev/null
+++ b/include/freerdp/utils/pcap.h
@@ -0,0 +1,83 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * pcap File Format Utils
+ *
+ * Copyright 2011 Marc-Andre Moreau
+ *
+ * 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.
+ */
+
+#ifndef __UTILS_PCAP_H
+#define __UTILS_PCAP_H
+
+#include
+#include
+#include
+
+struct _pcap_header
+{
+ uint32 magic_number; /* magic number */
+ uint16 version_major; /* major version number */
+ uint16 version_minor; /* minor version number */
+ sint32 thiszone; /* GMT to local correction */
+ uint32 sigfigs; /* accuracy of timestamps */
+ uint32 snaplen; /* max length of captured packets, in octets */
+ uint32 network; /* data link type */
+};
+typedef struct _pcap_header pcap_header;
+
+struct _pcap_record_header
+{
+ uint32 ts_sec; /* timestamp seconds */
+ uint32 ts_usec; /* timestamp microseconds */
+ uint32 incl_len; /* number of octets of packet saved in file */
+ uint32 orig_len; /* actual length of packet */
+};
+typedef struct _pcap_record_header pcap_record_header;
+
+typedef struct _pcap_record pcap_record;
+
+struct _pcap_record
+{
+ pcap_record_header header;
+ void* data;
+ uint32 length;
+ pcap_record* next;
+};
+
+struct rdp_pcap
+{
+ FILE* fp;
+ char* name;
+ STOPWATCH* sw;
+ boolean write;
+ int file_size;
+ int record_count;
+ pcap_header header;
+ pcap_record* head;
+ pcap_record* tail;
+ pcap_record* record;
+};
+typedef struct rdp_pcap rdpPcap;
+
+FREERDP_API rdpPcap* pcap_open(char* name, boolean write);
+FREERDP_API void pcap_close(rdpPcap* pcap);
+
+FREERDP_API void pcap_add_record(rdpPcap* pcap, void* data, uint32 length);
+FREERDP_API boolean pcap_has_next_record(rdpPcap* pcap);
+FREERDP_API boolean pcap_get_next_record(rdpPcap* pcap, pcap_record* record);
+FREERDP_API boolean pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record);
+FREERDP_API boolean pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record);
+FREERDP_API void pcap_flush(rdpPcap* pcap);
+
+#endif /* __UTILS_PCAP_H */
diff --git a/include/freerdp/utils/stopwatch.h b/include/freerdp/utils/stopwatch.h
index c7fa46457..58d7be5e1 100644
--- a/include/freerdp/utils/stopwatch.h
+++ b/include/freerdp/utils/stopwatch.h
@@ -22,6 +22,7 @@
#include
#include
+#include
#include
struct _STOPWATCH
@@ -40,6 +41,7 @@ FREERDP_API void stopwatch_start(STOPWATCH* stopwatch);
FREERDP_API void stopwatch_stop(STOPWATCH* stopwatch);
FREERDP_API void stopwatch_reset(STOPWATCH* stopwatch);
-double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch);
+FREERDP_API double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch);
+FREERDP_API void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, uint32* sec, uint32* usec);
#endif /* __UTILS_STOPWATCH_H */
diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c
index daa697cc9..fb0269c23 100644
--- a/libfreerdp-core/capabilities.c
+++ b/libfreerdp-core/capabilities.c
@@ -1371,6 +1371,10 @@ void rdp_read_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
*/
void rdp_write_rfx_client_capability_container(STREAM* s, rdpSettings* settings)
{
+ uint16 captureFlags;
+
+ captureFlags = settings->dump_rfx ? 0 : CARDP_CAPS_CAPTURE_NON_CAC;
+
stream_write_uint16(s, 49); /* codecPropertiesLength */
/* TS_RFX_CLNT_CAPS_CONTAINER */
diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c
index d58969ce8..27134ebb7 100644
--- a/libfreerdp-core/credssp.c
+++ b/libfreerdp-core/credssp.c
@@ -8,7 +8,7 @@
* 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
+ * 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,
@@ -25,7 +25,6 @@
#include "ntlmssp.h"
#include "credssp.h"
-
/**
* TSRequest ::= SEQUENCE {
* version [0] INTEGER,
@@ -109,7 +108,7 @@ int credssp_get_public_key(rdpCredssp* credssp)
{
int ret;
CryptoCert cert;
-
+
cert = tls_get_certificate(credssp->transport->tls);
if (cert == NULL)
@@ -117,7 +116,8 @@ int credssp_get_public_key(rdpCredssp* credssp)
printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n");
return 0;
}
-
+ if(tls_verify_certificate(cert,credssp->transport->settings->hostname))
+ tls_disconnect(credssp->transport->tls);
ret = crypto_cert_get_public_key(cert, &credssp->public_key);
crypto_cert_free(cert);
diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c
index 05a969bef..9aa65f0ab 100644
--- a/libfreerdp-core/crypto.c
+++ b/libfreerdp-core/crypto.c
@@ -8,7 +8,7 @@
* 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
+ * 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,
@@ -189,3 +189,113 @@ void crypto_nonce(uint8* nonce, int size)
{
RAND_bytes((void*) nonce, size);
}
+
+char* crypto_cert_fingerprint(X509* xcert)
+{
+ char* p;
+ int i = 0;
+ char* fp_buffer;
+ unsigned int fp_len;
+ unsigned char fp[EVP_MAX_MD_SIZE];
+
+ X509_digest(xcert, EVP_sha1(), fp, &fp_len);
+
+ fp_buffer = xzalloc(3 * fp_len);
+ p = fp_buffer;
+
+ for (i = 0; i < fp_len - 1; i++)
+ {
+ sprintf(p, "%02x:", fp[i]);
+ p = (char*) &fp_buffer[i * 3];
+ }
+ sprintf(p, "%02x", fp[i]);
+
+ return fp_buffer;
+}
+
+boolean x509_verify_cert(CryptoCert cert)
+{
+ char* cert_loc;
+ X509_STORE_CTX* csc;
+ boolean status = False;
+ X509_STORE* cert_ctx = NULL;
+ X509_LOOKUP* lookup = NULL;
+ X509* xcert = cert->px509;
+
+ cert_ctx = X509_STORE_new();
+
+ if (cert_ctx == NULL)
+ goto end;
+
+ OpenSSL_add_all_algorithms();
+ lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
+
+ if (lookup == NULL)
+ goto end;
+
+ lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
+
+ if (lookup == NULL)
+ goto end;
+
+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+ cert_loc = get_local_certloc();
+
+ if(cert_loc != NULL)
+ {
+ X509_LOOKUP_add_dir(lookup, cert_loc, X509_FILETYPE_ASN1);
+ xfree(cert_loc);
+ }
+
+ csc = X509_STORE_CTX_new();
+
+ if (csc == NULL)
+ goto end;
+
+ X509_STORE_set_flags(cert_ctx, 0);
+
+ if(!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0))
+ goto end;
+
+ if (X509_verify_cert(csc) == 1)
+ status = True;
+
+ X509_STORE_CTX_free(csc);
+ X509_STORE_free(cert_ctx);
+
+end:
+ return status;
+}
+
+rdpCertdata* crypto_get_certdata(X509* xcert, char* hostname)
+{
+ char* fp;
+ rdpCertdata* certdata;
+
+ fp = crypto_cert_fingerprint(xcert);
+ certdata = certdata_new(hostname, fp);
+ xfree(fp);
+
+ return certdata;
+}
+
+void crypto_cert_printinfo(X509* xcert)
+{
+ char* fp;
+ char* issuer;
+ char* subject;
+
+ subject = X509_NAME_oneline(X509_get_subject_name(xcert), NULL, 0);
+ issuer = X509_NAME_oneline(X509_get_issuer_name(xcert), NULL, 0);
+ fp = crypto_cert_fingerprint(xcert);
+
+ printf("Certificate details:\n");
+ printf("\tSubject: %s\n", subject);
+ printf("\tIssuer: %s\n", issuer);
+ printf("\tThumbprint: %s\n", fp);
+ printf("The above X.509 certificate could not be verified, possibly because you do not have "
+ "the CA certificate in your certificate store, or the certificate has expired."
+ "Please look at the documentation on how to create local certificate store for a private CA.\n");
+
+ xfree(fp);
+}
diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h
index 5a8746790..b63ff16c4 100644
--- a/libfreerdp-core/crypto.h
+++ b/libfreerdp-core/crypto.h
@@ -45,6 +45,7 @@
#include
#include
#include
+#include
struct crypto_sha1_struct
{
@@ -83,8 +84,12 @@ void crypto_rc4_free(CryptoRc4 rc4);
typedef struct crypto_cert_struct* CryptoCert;
CryptoCert crypto_cert_read(uint8* data, uint32 length);
+char* cypto_cert_fingerprint(X509* xcert);
+void crypto_cert_printinfo(X509* xcert);
void crypto_cert_free(CryptoCert cert);
+boolean x509_verify_cert(CryptoCert cert);
boolean crypto_cert_verify(CryptoCert server_cert, CryptoCert cacert);
+rdpCertdata* crypto_get_certdata(X509* xcert, char* hostname);
boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key);
void crypto_rsa_encrypt(uint8* input, int length, uint32 key_length, uint8* modulus, uint8* exponent, uint8* output);
diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c
index e48e4a2ae..b5bf10653 100644
--- a/libfreerdp-core/fastpath.c
+++ b/libfreerdp-core/fastpath.c
@@ -73,6 +73,26 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
return length;
}
+inline void fastpath_read_update_header(STREAM* s, uint8* updateCode, uint8* fragmentation, uint8* compression)
+{
+ uint8 updateHeader;
+
+ stream_read_uint8(s, updateHeader);
+ *updateCode = updateHeader & 0x0F;
+ *fragmentation = (updateHeader >> 4) & 0x03;
+ *compression = (updateHeader >> 6) & 0x03;
+}
+
+inline void fastpath_write_update_header(STREAM* s, uint8 updateCode, uint8 fragmentation, uint8 compression)
+{
+ uint8 updateHeader = 0;
+
+ updateHeader |= updateCode & 0x0F;
+ updateHeader |= (fragmentation & 0x03) << 4;
+ updateHeader |= (compression & 0x03) << 6;
+ stream_write_uint8(s, updateHeader);
+}
+
boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s)
{
/* TODO: fipsInformation */
@@ -122,7 +142,7 @@ static void fastpath_recv_update_common(rdpFastPath* fastpath, STREAM* s)
}
}
-static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint16 size, STREAM* s)
+static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint32 size, STREAM* s)
{
switch (updateCode)
{
@@ -175,19 +195,16 @@ static void fastpath_recv_update(rdpFastPath* fastpath, uint8 updateCode, uint16
static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
{
- uint8 updateHeader;
+ uint16 size;
+ int next_pos;
+ uint32 totalSize;
uint8 updateCode;
uint8 fragmentation;
uint8 compression;
uint8 compressionFlags;
- uint16 size;
STREAM* update_stream;
- int next_pos;
- stream_read_uint8(s, updateHeader);
- updateCode = updateHeader & 0x0F;
- fragmentation = (updateHeader >> 4) & 0x03;
- compression = (updateHeader >> 6) & 0x03;
+ fastpath_read_update_header(s, &updateCode, &fragmentation, &compression);
if (compression == FASTPATH_OUTPUT_COMPRESSION_USED)
stream_read_uint8(s, compressionFlags);
@@ -207,6 +224,7 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
update_stream = NULL;
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
{
+ totalSize = size;
update_stream = s;
}
else
@@ -220,13 +238,13 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
if (fragmentation == FASTPATH_FRAGMENT_LAST)
{
update_stream = fastpath->updateData;
- size = stream_get_length(update_stream);
+ totalSize = stream_get_length(update_stream);
stream_set_pos(update_stream, 0);
}
}
if (update_stream)
- fastpath_recv_update(fastpath, updateCode, size, update_stream);
+ fastpath_recv_update(fastpath, updateCode, totalSize, update_stream);
stream_set_pos(s, next_pos);
}
@@ -394,7 +412,7 @@ boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
{
/**
* If numberEvents is not provided in fpInputHeader, it will be provided
- * as onee additional byte here.
+ * as one additional byte here.
*/
if (stream_get_left(s) < 1)
@@ -457,9 +475,10 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
uint16 length;
length = stream_get_length(s);
+
if (length > FASTPATH_MAX_PACKET_SIZE)
{
- printf("Maximum FastPath Update PDU length is %d\n", FASTPATH_MAX_PACKET_SIZE);
+ printf("Maximum FastPath Update PDU length is %d (actual:%d)\n", FASTPATH_MAX_PACKET_SIZE, length);
return False;
}
@@ -475,6 +494,41 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
return True;
}
+boolean fastpath_send_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s)
+{
+ int fragment;
+ uint16 length;
+ uint16 maxLength;
+ uint32 totalLength;
+ uint8 fragmentation;
+ STREAM* update;
+
+ maxLength = FASTPATH_MAX_PACKET_SIZE - 6;
+ totalLength = stream_get_length(s);
+ stream_set_pos(s, 0);
+
+ for (fragment = 0; totalLength > 0; fragment++)
+ {
+ update = fastpath_update_pdu_init(fastpath);
+ length = MIN(maxLength, totalLength);
+ totalLength -= length;
+
+ if (totalLength == 0)
+ fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST;
+ else
+ fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT;
+
+ fastpath_write_update_header(update, FASTPATH_UPDATETYPE_SURFCMDS, fragmentation, 0);
+ stream_write_uint16(update, length);
+ stream_write(update, s->p, length);
+ stream_seek(s, length);
+
+ fastpath_send_update_pdu(fastpath, update);
+ }
+
+ return True;
+}
+
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId)
{
STREAM* s;
@@ -520,19 +574,17 @@ boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_C
}
fragment_size = MIN(FASTPATH_MAX_PACKET_SIZE - stream_get_length(s), bitmapDataLength);
+
if (fragment_size == bitmapDataLength)
- {
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST);
- }
else
- {
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT);
- }
+
size += fragment_size;
ep = stream_get_pos(s);
stream_set_pos(s, bp);
- stream_write_uint8(s, FASTPATH_UPDATETYPE_SURFCMDS | (fragmentation << 4));
+ fastpath_write_update_header(s, FASTPATH_UPDATETYPE_SURFCMDS, fragmentation, 0);
stream_write_uint16(s, size);
stream_set_pos(s, ep);
diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h
index 5a6166aef..25899b3ba 100644
--- a/libfreerdp-core/fastpath.h
+++ b/libfreerdp-core/fastpath.h
@@ -100,6 +100,7 @@ boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s);
STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath);
boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s);
+boolean fastpath_send_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId);
boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);
diff --git a/libfreerdp-core/freerdp.c b/libfreerdp-core/freerdp.c
index 504079fc9..bd88f449d 100644
--- a/libfreerdp-core/freerdp.c
+++ b/libfreerdp-core/freerdp.c
@@ -20,6 +20,7 @@
#include "rdp.h"
#include "input.h"
#include "update.h"
+#include "surface.h"
#include "transport.h"
#include "connection.h"
@@ -34,10 +35,51 @@ boolean freerdp_connect(freerdp* instance)
rdp = (rdpRdp*) instance->rdp;
IFCALL(instance->PreConnect, instance);
+
status = rdp_client_connect((rdpRdp*) instance->rdp);
+
if (status)
+ {
+ if (instance->settings->dump_rfx)
+ {
+ instance->update->dump_rfx = instance->settings->dump_rfx;
+ instance->update->pcap_rfx = pcap_open(instance->settings->dump_rfx_file, True);
+ }
+
IFCALL(instance->PostConnect, instance);
+ if (instance->settings->play_rfx)
+ {
+ STREAM* s;
+ rdpUpdate* update;
+ pcap_record record;
+
+ s = stream_new(1024);
+ instance->update->play_rfx = instance->settings->play_rfx;
+ instance->update->pcap_rfx = pcap_open(instance->settings->play_rfx_file, False);
+ update = instance->update;
+
+ while (pcap_has_next_record(update->pcap_rfx))
+ {
+ pcap_get_next_record_header(update->pcap_rfx, &record);
+
+ s->data = xrealloc(s->data, record.length);
+ record.data = s->data;
+ s->size = record.length;
+
+ pcap_get_next_record_content(update->pcap_rfx, &record);
+ stream_set_pos(s, 0);
+
+ update->BeginPaint(update);
+ update_recv_surfcmds(update, s->size, s);
+ update->EndPaint(update);
+ }
+
+ xfree(s->data);
+ return True;
+ }
+ }
+
return status;
}
diff --git a/libfreerdp-core/surface.c b/libfreerdp-core/surface.c
index 6c17e310c..b0bc45411 100644
--- a/libfreerdp-core/surface.c
+++ b/libfreerdp-core/surface.c
@@ -17,12 +17,14 @@
* limitations under the License.
*/
+#include
+
#include "surface.h"
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s)
{
- SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
int pos;
+ SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
stream_read_uint16(s, cmd->destLeft);
stream_read_uint16(s, cmd->destTop);
@@ -56,12 +58,16 @@ static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s)
return 6;
}
-boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
+boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s)
{
+ uint8* mark;
uint16 cmdType;
+ uint32 cmdLength;
while (size > 2)
{
+ stream_get_mark(s, mark);
+
stream_read_uint16(s, cmdType);
size -= 2;
@@ -69,17 +75,25 @@ boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
{
case CMDTYPE_SET_SURFACE_BITS:
case CMDTYPE_STREAM_SURFACE_BITS:
- size -= update_recv_surfcmd_surface_bits(update, s);
+ cmdLength = update_recv_surfcmd_surface_bits(update, s);
break;
case CMDTYPE_FRAME_MARKER:
- size -= update_recv_surfcmd_frame_marker(update, s);
+ cmdLength = update_recv_surfcmd_frame_marker(update, s);
break;
default:
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
return False;
}
+
+ size -= cmdLength;
+
+ if (update->dump_rfx)
+ {
+ pcap_add_record(update->pcap_rfx, mark, cmdLength + 2);
+ pcap_flush(update->pcap_rfx);
+ }
}
return True;
}
diff --git a/libfreerdp-core/surface.h b/libfreerdp-core/surface.h
index 1c18adf39..c19ed0d57 100644
--- a/libfreerdp-core/surface.h
+++ b/libfreerdp-core/surface.h
@@ -39,7 +39,7 @@ enum SURFCMD_FRAMEACTION
SURFACECMD_FRAMEACTION_END = 0x0001
};
-boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s);
+boolean update_recv_surfcmds(rdpUpdate* update, uint32 size, STREAM* s);
void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);
diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c
index e6d3c3ea2..c5760f0bd 100644
--- a/libfreerdp-core/tls.c
+++ b/libfreerdp-core/tls.c
@@ -8,7 +8,7 @@
* 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
+ * 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,
@@ -240,7 +240,7 @@ rdpTls* tls_new()
tls->connect = tls_connect;
tls->accept = tls_accept;
tls->disconnect = tls_disconnect;
-
+
SSL_load_error_strings();
SSL_library_init();
}
@@ -248,6 +248,69 @@ rdpTls* tls_new()
return tls;
}
+int tls_verify_certificate(CryptoCert cert, char* hostname)
+{
+ boolean ret;
+ ret = x509_verify_cert(cert);
+
+ if (!ret)
+ {
+ rdpCertdata* certdata;
+ certdata = crypto_get_certdata(cert->px509, hostname);
+ rdpCertstore* certstore = certstore_new(certdata);
+
+ if (match_certdata(certstore) == 0)
+ goto end;
+
+ if (certstore->match == 1)
+ {
+ char answer;
+ crypto_cert_printinfo(cert->px509);
+
+ while(1)
+ {
+ printf("Do you trust the above certificate? (Y/N) ");
+ answer=fgetc(stdin);
+
+ if(answer=='y' || answer =='Y')
+ {
+ print_certdata(certstore);
+ break;
+ }
+ else if(answer=='n' || answer=='N')
+ {
+ certstore_free(certstore);
+ return 1;
+ }
+ }
+ }
+ else if (certstore->match == -1)
+ {
+ tls_print_cert_error();
+ certstore_free(certstore);
+ return 1;
+ }
+
+end:
+ certstore_free(certstore);
+ }
+
+ return 0;
+}
+
+void tls_print_cert_error()
+{
+ printf("#####################################\n");
+ printf("##############WARNING################\n");
+ printf("#####################################\n");
+ printf("The thumbprint of certificate received\n");
+ printf("did not match the stored thumbprint.You\n");
+ printf("might be a victim of MAN in the MIDDLE\n");
+ printf("ATTACK.It is also possible that server's\n");
+ printf("certificate have been changed.In that case\n");
+ printf("contact your server administrator\n");
+}
+
void tls_free(rdpTls* tls)
{
if (tls != NULL)
diff --git a/libfreerdp-core/tls.h b/libfreerdp-core/tls.h
index 9a7da598a..52b301c40 100644
--- a/libfreerdp-core/tls.h
+++ b/libfreerdp-core/tls.h
@@ -49,8 +49,9 @@ boolean tls_disconnect(rdpTls* tls);
int tls_read(rdpTls* tls, uint8* data, int length);
int tls_write(rdpTls* tls, uint8* data, int length);
CryptoCert tls_get_certificate(rdpTls* tls);
+int tls_verify_certificate(CryptoCert cert,char* hostname);
+void tls_print_cert_error();
boolean tls_print_error(char* func, SSL* connection, int value);
-
rdpTls* tls_new();
void tls_free(rdpTls* tls);
diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c
index ffc1e3c49..b63e4b8a0 100644
--- a/libfreerdp-core/update.c
+++ b/libfreerdp-core/update.c
@@ -322,10 +322,15 @@ static void update_end_paint(rdpUpdate* update)
{
}
+static void update_send_surface_command(rdpUpdate* update, STREAM* s)
+{
+ rdpRdp* rdp = (rdpRdp*) update->rdp;
+ fastpath_send_fragmented_update_pdu(rdp->fastpath, s);
+}
+
static void update_send_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command)
{
rdpRdp* rdp = (rdpRdp*)update->rdp;
-
fastpath_send_surfcmd_surface_bits(rdp->fastpath, surface_bits_command);
}
@@ -362,6 +367,7 @@ void update_register_server_callbacks(rdpUpdate* update)
update->Synchronize = update_send_synchronize;
update->PointerSystem = update_send_pointer_system;
update->SurfaceBits = update_send_surface_bits;
+ update->SurfaceCommand = update_send_surface_command;
}
rdpUpdate* update_new(rdpRdp* rdp)
diff --git a/libfreerdp-rail/window.c b/libfreerdp-rail/window.c
index 51fb6ef0e..9a55e01c0 100644
--- a/libfreerdp-rail/window.c
+++ b/libfreerdp-rail/window.c
@@ -284,6 +284,10 @@ void rail_CreateWindow(rdpRail* rail, rdpWindow* window)
{
IFCALL(rail->SetWindowRects, rail, window);
}
+ if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
+ {
+ IFCALL(rail->SetWindowVisibilityRects, rail, window);
+ }
}
void rail_UpdateWindow(rdpRail* rail, rdpWindow* window)
@@ -356,7 +360,7 @@ void rail_UpdateWindow(rdpRail* rail, rdpWindow* window)
if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
{
-
+ IFCALL(rail->SetWindowVisibilityRects, rail, window);
}
}
diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt
index a0b6037dd..71a9eda63 100644
--- a/libfreerdp-utils/CMakeLists.txt
+++ b/libfreerdp-utils/CMakeLists.txt
@@ -30,9 +30,11 @@ set(FREERDP_UTILS_SRCS
load_plugin.c
memory.c
mutex.c
+ pcap.c
profiler.c
rail.c
registry.c
+ certstore.c
semaphore.c
sleep.c
stopwatch.c
diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c
index 00e189e96..522543648 100644
--- a/libfreerdp-utils/args.c
+++ b/libfreerdp-utils/args.c
@@ -51,7 +51,47 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
while (index < argc)
{
- if (strcmp("-a", argv[index]) == 0)
+ if ((strcmp("-h", argv[index]) == 0 ) || (strcmp("--help", argv[index]) == 0 ))
+ {
+ printf("\n"
+ "FreeRDP - A Free Remote Desktop Protocol Client\n"
+ "See http://www.freerdp.com for more information\n"
+ "\n"
+ "Usage: %s [options] server:port\n"
+ " -0: connect to console session\n"
+ " -a: set color depth in bit, default is 16\n"
+ " -c: initial working directory\n"
+ " -D: hide window decorations\n"
+ " -d: domain\n"
+ " -f: fullscreen mode\n"
+ " -g: set geometry, using format WxH or X%% or 'workarea', default is 1024x768\n"
+ " -h: print this help\n"
+ " -k: set keyboard layout ID\n"
+ " -m: don't send mouse motion events\n"
+ " -n: hostname\n"
+ " -o: console audio\n"
+ " -p: password\n"
+ " -s: set startup-shell\n"
+ " -t: alternative port number, default is 3389\n"
+ " -u: username\n"
+ " -x: performance flags (m[odem], b[roadband] or l[an])\n"
+ " -z: enable compression\n"
+ " --app: RemoteApp connection. This implies -g workarea\n"
+ " --ext: load an extension\n"
+ " --no-auth: disable authentication\n"
+ " --no-fastpath: disable fast-path\n"
+ " --no-osb: disable off screen bitmaps, default on\n"
+ " --plugin: load a virtual channel plugin\n"
+ " --rfx: enable RemoteFX\n"
+ " --no-rdp: disable Standard RDP encryption\n"
+ " --no-tls: disable TLS encryption\n"
+ " --no-nla: disable network level authentication\n"
+ " --sec: force protocol security (rdp, tls or nla)\n"
+ " --version: print version information\n"
+ "\n", argv[0]);
+ return -1; //TODO: What is the correct return
+ }
+ else if (strcmp("-a", argv[index]) == 0)
{
index++;
if (index == argc)
@@ -242,6 +282,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
settings->performance_flags = PERF_FLAG_NONE;
settings->large_pointer = True;
}
+ else if (strcmp("--dump-rfx", argv[index]) == 0)
+ {
+ index++;
+ if (index == argc)
+ {
+ printf("missing file name\n");
+ return -1;
+ }
+ settings->dump_rfx_file = xstrdup(argv[index]);
+ settings->dump_rfx = True;
+ }
+ else if (strcmp("--play-rfx", argv[index]) == 0)
+ {
+ index++;
+ if (index == argc)
+ {
+ printf("missing file name\n");
+ return -1;
+ }
+ settings->play_rfx_file = xstrdup(argv[index]);
+ settings->play_rfx = True;
+ }
else if (strcmp("-m", argv[index]) == 0)
{
settings->mouse_motion = True;
diff --git a/libfreerdp-utils/certstore.c b/libfreerdp-utils/certstore.c
new file mode 100644
index 000000000..b784d33a3
--- /dev/null
+++ b/libfreerdp-utils/certstore.c
@@ -0,0 +1,213 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * certstore Utils
+ *
+ * Copyright 2011 Jiten Pathy
+ *
+ * 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.
+ */
+
+#include
+
+#ifdef _WIN32
+#include
+#endif
+
+static char cert_dir[] = "freerdp";
+static char cert_loc[] = "cacert";
+static char certstore_file[] = "known_hosts";
+
+void certstore_create(rdpCertstore* certstore)
+{
+ certstore->fp = fopen((char*)certstore->file, "w+");
+
+ if (certstore->fp == NULL)
+ {
+ printf("certstore_create: error opening [%s] for writing\n", certstore->file);
+ return;
+ }
+ fflush(certstore->fp);
+}
+
+void certstore_load(rdpCertstore* certstore)
+{
+ certstore->fp = fopen((char*)certstore->file, "r+");
+}
+
+void certstore_open(rdpCertstore* certstore)
+{
+ struct stat stat_info;
+
+ if (stat((char*)certstore->file, &stat_info) != 0)
+ certstore_create(certstore);
+ else
+ certstore_load(certstore);
+}
+
+void certstore_close(rdpCertstore* certstore)
+{
+ if (certstore->fp != NULL)
+ fclose(certstore->fp);
+}
+
+char* get_local_certloc()
+{
+ char *home_path;
+ char *certloc;
+ struct stat stat_info;
+ home_path=getenv("HOME");
+ certloc=(char*)xmalloc(strlen(home_path)+strlen("/.")+strlen(cert_dir)+strlen("/")+strlen(cert_loc)+1);
+ sprintf(certloc,"%s/.%s/%s",home_path,cert_dir,cert_loc);
+ if(stat((char*)certloc, &stat_info) != 0)
+ mkdir(certloc, S_IRUSR | S_IWUSR | S_IXUSR);
+ return certloc;
+}
+
+void certstore_init(rdpCertstore* certstore)
+{
+ int length;
+ char* home_path;
+ struct stat stat_info;
+
+ certstore->match=1;
+ home_path = getenv("HOME");
+
+ if (home_path == NULL)
+ {
+ printf("could not get home path\n");
+ return;
+ }
+
+ certstore->home = (char*) xstrdup(home_path);
+ printf("home path: %s\n", certstore->home);
+
+ certstore->path = (char*) xmalloc(strlen(certstore->home) + strlen("/.") + strlen(cert_dir) + 1);
+ sprintf(certstore->path, "%s/.%s", certstore->home, cert_dir);
+ printf("certstore path: %s\n", certstore->path);
+
+ if (stat(certstore->path, &stat_info) != 0)
+ {
+#ifndef _WIN32
+ mkdir(certstore->path, S_IRUSR | S_IWUSR | S_IXUSR);
+#else
+ CreateDirectory(certstore->path, 0);
+#endif
+ printf("creating directory %s\n", certstore->path);
+ }
+
+ length = strlen(certstore->path);
+ certstore->file = (char*) xmalloc(strlen(certstore->path) + strlen("/") + strlen(certstore_file) + 1);
+ sprintf(certstore->file, "%s/%s", certstore->path, certstore_file);
+ printf("certstore file: %s\n", certstore->file);
+
+ certstore_open(certstore);
+}
+
+rdpCertdata* certdata_new(char* host_name,char* fingerprint)
+{
+ rdpCertdata* certdata=(rdpCertdata*)xzalloc(sizeof(rdpCertdata));
+ if(certdata !=NULL)
+ {
+ certdata->hostname=xzalloc(strlen(host_name)+1);
+ certdata->thumbprint=xzalloc(strlen(fingerprint)+1);
+ sprintf(certdata->hostname,"%s",host_name);
+ sprintf(certdata->thumbprint,"%s",fingerprint);
+ }
+ return certdata;
+}
+
+void certdata_free(rdpCertdata* certdata)
+{
+ if(certdata != NULL)
+ {
+ xfree(certdata->hostname);
+ xfree(certdata->thumbprint);
+ xfree(certdata);
+ }
+}
+
+rdpCertstore* certstore_new(rdpCertdata* certdata)
+{
+ rdpCertstore* certstore = (rdpCertstore*) xzalloc(sizeof(rdpCertstore));
+
+ if (certstore != NULL)
+ {
+ certstore->certdata = certdata;
+ certstore_init(certstore);
+ }
+
+ return certstore;
+}
+
+void certstore_free(rdpCertstore* certstore)
+{
+ if (certstore != NULL)
+ {
+ certstore_close(certstore);
+ xfree(certstore->path);
+ xfree(certstore->file);
+ xfree(certstore->home);
+ certdata_free(certstore->certdata);
+ xfree(certstore);
+ }
+}
+
+int match_certdata(rdpCertstore* certstore)
+{
+ char *host;
+ char *p;
+ char *thumb_print;
+ int length;
+ unsigned char c;
+ FILE* cfp;
+ cfp=certstore->fp;
+ rdpCertdata* cert_data=certstore->certdata;
+ length=strlen(cert_data->thumbprint);
+ host=xzalloc(strlen(cert_data->hostname)+1);
+ for(;;)
+ {
+ if((int)fread(host,sizeof(char),strlen(cert_data->hostname),cfp) < strlen(cert_data->hostname))
+ break;
+ if((!strcmp(host,cert_data->hostname)) && ((c=fgetc(cfp))==' ' || c=='\t') )
+ {
+ ungetc(c,cfp);
+ while((c=fgetc(cfp))==' ' || c=='\t');
+ if(c==EOF)
+ break;
+ ungetc(c,cfp);
+ thumb_print=xzalloc(length+1);
+ p=thumb_print;
+ while((p-thumb_print) < length && (*p=fgetc(cfp))!=EOF && *p!='\n' && *p==*(cert_data->thumbprint+(p-thumb_print)))
+ p++;
+ if(p-thumb_print==length)
+ certstore->match=0;
+ else
+ certstore->match=-1;
+ break;
+ }
+ else
+ {
+ while(c!='\n' && c!=EOF)
+ c=fgetc(cfp);
+ if(c==EOF)
+ break;
+ }
+ }
+ xfree(host);
+ return certstore->match;
+}
+void print_certdata(rdpCertstore* certstore)
+{
+ fseek(certstore->fp,0,SEEK_END);
+ fprintf(certstore->fp,"%s %s\n",certstore->certdata->hostname,certstore->certdata->thumbprint);
+}
diff --git a/libfreerdp-utils/pcap.c b/libfreerdp-utils/pcap.c
new file mode 100644
index 000000000..48f2a711d
--- /dev/null
+++ b/libfreerdp-utils/pcap.c
@@ -0,0 +1,193 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * pcap File Format Utils
+ *
+ * Copyright 2011 Marc-Andre Moreau
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#define PCAP_MAGIC 0xA1B2C3D4
+
+void pcap_read_header(rdpPcap* pcap, pcap_header* header)
+{
+ fread((void*) header, sizeof(pcap_header), 1, pcap->fp);
+}
+
+void pcap_write_header(rdpPcap* pcap, pcap_header* header)
+{
+ fwrite((void*) header, sizeof(pcap_header), 1, pcap->fp);
+}
+
+void pcap_read_record_header(rdpPcap* pcap, pcap_record_header* record)
+{
+ fread((void*) record, sizeof(pcap_record_header), 1, pcap->fp);
+}
+
+void pcap_write_record_header(rdpPcap* pcap, pcap_record_header* record)
+{
+ fwrite((void*) record, sizeof(pcap_record_header), 1, pcap->fp);
+}
+
+void pcap_read_record(rdpPcap* pcap, pcap_record* record)
+{
+ pcap_read_record_header(pcap, &record->header);
+ record->length = record->header.incl_len;
+ record->data = xmalloc(record->length);
+ fread(record->data, record->length, 1, pcap->fp);
+}
+
+void pcap_write_record(rdpPcap* pcap, pcap_record* record)
+{
+ pcap_write_record_header(pcap, &record->header);
+ fwrite(record->data, record->length, 1, pcap->fp);
+}
+
+void pcap_add_record(rdpPcap* pcap, void* data, uint32 length)
+{
+ pcap_record* record;
+
+ if (pcap->tail == NULL)
+ {
+ pcap->tail = (pcap_record*) xzalloc(sizeof(pcap_record));
+ pcap->head = pcap->tail;
+ pcap->record = pcap->head;
+ record = pcap->tail;
+ }
+ else
+ {
+ record = (pcap_record*) xzalloc(sizeof(pcap_record));
+ pcap->tail->next = record;
+ pcap->tail = record;
+ }
+
+ if (pcap->record == NULL)
+ pcap->record = record;
+
+ record->data = data;
+ record->length = length;
+ record->header.incl_len = length;
+ record->header.orig_len = length;
+
+ stopwatch_stop(pcap->sw);
+ stopwatch_get_elapsed_time_in_useconds(pcap->sw, &record->header.ts_sec, &record->header.ts_usec);
+ stopwatch_start(pcap->sw);
+}
+
+boolean pcap_has_next_record(rdpPcap* pcap)
+{
+ if (pcap->file_size - (ftell(pcap->fp)) <= 16)
+ return False;
+
+ return True;
+}
+
+boolean pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record)
+{
+ if (pcap_has_next_record(pcap) != True)
+ return False;
+
+ pcap_read_record_header(pcap, &record->header);
+ record->length = record->header.incl_len;
+ record->data = xmalloc(record->length);
+
+ return True;
+}
+
+boolean pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record)
+{
+ fread(record->data, record->length, 1, pcap->fp);
+ return True;
+}
+
+boolean pcap_get_next_record(rdpPcap* pcap, pcap_record* record)
+{
+ if (pcap_has_next_record(pcap) != True)
+ return False;
+
+ pcap_read_record(pcap, record);
+
+ return True;
+}
+
+rdpPcap* pcap_open(char* name, boolean write)
+{
+ rdpPcap* pcap;
+
+ pcap = (rdpPcap*) xzalloc(sizeof(rdpPcap));
+
+ if (pcap != NULL)
+ {
+ pcap->name = name;
+ pcap->write = write;
+ pcap->record_count = 0;
+
+ if (write)
+ {
+ pcap->fp = fopen(name, "w+");
+ pcap->header.magic_number = 0xA1B2C3D4;
+ pcap->header.version_major = 2;
+ pcap->header.version_minor = 4;
+ pcap->header.thiszone = 0;
+ pcap->header.sigfigs = 0;
+ pcap->header.snaplen = 0xFFFFFFFF;
+ pcap->header.network = 0;
+ pcap_write_header(pcap, &pcap->header);
+ }
+ else
+ {
+ pcap->fp = fopen(name, "r");
+ fseek(pcap->fp, 0, SEEK_END);
+ pcap->file_size = (int) ftell(pcap->fp);
+ fseek(pcap->fp, 0, SEEK_SET);
+ pcap_read_header(pcap, &pcap->header);
+ }
+
+ pcap->sw = stopwatch_create();
+ stopwatch_start(pcap->sw);
+ }
+
+ return pcap;
+}
+
+void pcap_flush(rdpPcap* pcap)
+{
+ while (pcap->record != NULL)
+ {
+ pcap_write_record(pcap, pcap->record);
+ pcap->record = pcap->record->next;
+ }
+
+ if (pcap->fp != NULL)
+ fflush(pcap->fp);
+}
+
+void pcap_close(rdpPcap* pcap)
+{
+ pcap_flush(pcap);
+
+ if (pcap->fp != NULL)
+ fclose(pcap->fp);
+
+ stopwatch_stop(pcap->sw);
+ stopwatch_free(pcap->sw);
+}
diff --git a/libfreerdp-utils/stopwatch.c b/libfreerdp-utils/stopwatch.c
index 55b814f06..e74c1d909 100644
--- a/libfreerdp-utils/stopwatch.c
+++ b/libfreerdp-utils/stopwatch.c
@@ -56,5 +56,15 @@ void stopwatch_reset(STOPWATCH* stopwatch)
double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch)
{
- return ((double)stopwatch->elapsed) / CLOCKS_PER_SEC;
+ return ((double) stopwatch->elapsed) / CLOCKS_PER_SEC;
}
+
+void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, uint32* sec, uint32* usec)
+{
+ double uelapsed;
+
+ *sec = ((uint32) stopwatch->elapsed) / CLOCKS_PER_SEC;
+ uelapsed = stopwatch->elapsed - ((double)(*sec) * CLOCKS_PER_SEC);
+ *usec = (uelapsed / (CLOCKS_PER_SEC / 1000000));
+}
+
diff --git a/server/test/freerdp_server.c b/server/test/freerdp_server.c
index 00d07da47..c926363c6 100644
--- a/server/test/freerdp_server.c
+++ b/server/test/freerdp_server.c
@@ -30,6 +30,8 @@
#include
#include
+static char* test_pcap_file = NULL;
+
/* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */
static const unsigned int test_quantization_values[] =
{
@@ -183,6 +185,8 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
RFX_RECT rect;
STREAM* s;
+ if (client->update->dump_rfx)
+ return;
if (!client->settings->rfx_codec || !info)
return;
if (info->icon_width < 1)
@@ -232,6 +236,33 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
info->icon_y = y;
}
+void test_peer_dump_rfx(freerdp_peer* client)
+{
+ STREAM* s;
+ rdpUpdate* update;
+ rdpPcap* pcap_rfx;
+ pcap_record record;
+
+ s = stream_new(512);
+ update = client->update;
+ client->update->pcap_rfx = pcap_open(test_pcap_file, False);
+ pcap_rfx = client->update->pcap_rfx;
+
+ while (pcap_has_next_record(pcap_rfx))
+ {
+ pcap_get_next_record_header(pcap_rfx, &record);
+
+ s->data = xrealloc(s->data, record.length);
+ record.data = s->data;
+ s->size = record.length;
+
+ pcap_get_next_record_content(pcap_rfx, &record);
+ s->p = s->data + s->size;
+
+ update->SurfaceCommand(update, s);
+ }
+}
+
boolean test_peer_post_connect(freerdp_peer* client)
{
/**
@@ -256,9 +287,18 @@ boolean test_peer_post_connect(freerdp_peer* client)
/* A real server should tag the peer as activated here and start sending updates in mainloop. */
test_peer_init(client);
- test_peer_draw_background(client);
test_peer_load_icon(client);
+ if (test_pcap_file != NULL)
+ {
+ client->update->dump_rfx = True;
+ test_peer_dump_rfx(client);
+ }
+ else
+ {
+ test_peer_draw_background(client);
+ }
+
/* Return False here would stop the execution of the peer mainloop. */
return True;
}
@@ -292,13 +332,13 @@ void test_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uin
static void* test_peer_mainloop(void* arg)
{
- freerdp_peer* client = (freerdp_peer*)arg;
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
+ freerdp_peer* client = (freerdp_peer*) arg;
memset(rfds, 0, sizeof(rfds));
@@ -452,8 +492,11 @@ int main(int argc, char* argv[])
instance->PeerAccepted = test_peer_accepted;
+ if (argc > 1)
+ test_pcap_file = argv[1];
+
/* Open the server socket and start listening. */
- if (instance->Open(instance, (argc > 1 ? argv[1] : NULL), 3389))
+ if (instance->Open(instance, NULL, 3389))
{
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
test_server_mainloop(instance);
diff --git a/server/test/rfx_test.pcap b/server/test/rfx_test.pcap
new file mode 100644
index 000000000..c830e10b5
Binary files /dev/null and b/server/test/rfx_test.pcap differ