Merge remote-tracking branch 'upstream/master' into rail
This commit is contained in:
commit
585b436915
3
.gitignore
vendored
3
.gitignore
vendored
@ -14,8 +14,9 @@ Makefile
|
|||||||
*.cproject
|
*.cproject
|
||||||
*.settings
|
*.settings
|
||||||
|
|
||||||
# Doxygen
|
# Documentation
|
||||||
docs/api
|
docs/api
|
||||||
|
client/X11/xfreerdp.1
|
||||||
|
|
||||||
# Mac OS X
|
# Mac OS X
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
@ -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)
|
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)
|
while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING)
|
||||||
{
|
{
|
||||||
pa_threaded_mainloop_wait(pulse->mainloop);
|
pa_threaded_mainloop_wait(pulse->mainloop);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
include(FindXmlto)
|
||||||
include_directories(${X11_INCLUDE_DIRS})
|
include_directories(${X11_INCLUDE_DIRS})
|
||||||
|
|
||||||
add_executable(xfreerdp
|
add_executable(xfreerdp
|
||||||
@ -32,26 +33,41 @@ add_executable(xfreerdp
|
|||||||
xf_window.h
|
xf_window.h
|
||||||
xfreerdp.c
|
xfreerdp.c
|
||||||
xfreerdp.h)
|
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)
|
find_package(Xinerama)
|
||||||
if(XINERAMA_FOUND)
|
if(XINERAMA_FOUND)
|
||||||
add_definitions(-DWITH_XINERAMA)
|
add_definitions(-DWITH_XINERAMA -DWITH_XEXT)
|
||||||
include_directories(${XINERAMA_INCLUDE_DIRS})
|
include_directories(${XINERAMA_INCLUDE_DIRS})
|
||||||
target_link_libraries(xfreerdp ${XINERAMA_LIBRARIES})
|
target_link_libraries(xfreerdp ${XINERAMA_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Xext)
|
find_package(Xext)
|
||||||
if(Xext_FOUND)
|
if(XEXT_FOUND)
|
||||||
add_definitions(-DWITH_XEXT)
|
add_definitions(-DWITH_XEXT)
|
||||||
include_directories(${Xext_INCLUDE_DIRS})
|
include_directories(${XEXT_INCLUDE_DIRS})
|
||||||
target_link_libraries(xfreerdp ${Xext_LIBRARIES})
|
target_link_libraries(xfreerdp ${XEXT_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Xcursor)
|
find_package(Xcursor)
|
||||||
if(Xcursor_FOUND)
|
if(Xcursor_FOUND)
|
||||||
add_definitions(-DWITH_XCURSOR)
|
add_definitions(-DWITH_XCURSOR)
|
||||||
include_directories(${Xcursor_INCLUDE_DIRS})
|
include_directories(${Xcursor_INCLUDE_DIRS})
|
||||||
target_link_libraries(xfreerdp ${Xext_LIBRARIES})
|
target_link_libraries(xfreerdp ${Xcursor_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(xfreerdp freerdp-core)
|
target_link_libraries(xfreerdp freerdp-core)
|
||||||
@ -63,3 +79,4 @@ target_link_libraries(xfreerdp freerdp-utils)
|
|||||||
target_link_libraries(xfreerdp ${X11_LIBRARIES})
|
target_link_libraries(xfreerdp ${X11_LIBRARIES})
|
||||||
|
|
||||||
install(TARGETS xfreerdp DESTINATION bin)
|
install(TARGETS xfreerdp DESTINATION bin)
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
|
|||||||
if (xfi->mouse_active && (app != True))
|
if (xfi->mouse_active && (app != True))
|
||||||
XGrabKeyboard(xfi->display, xfi->window->handle, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
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);
|
xf_kbd_focus_in(xfi);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
@ -359,7 +359,7 @@ boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app)
|
|||||||
if (event->xfocus.mode == NotifyWhileGrabbed)
|
if (event->xfocus.mode == NotifyWhileGrabbed)
|
||||||
XUngrabKeyboard(xfi->display, CurrentTime);
|
XUngrabKeyboard(xfi->display, CurrentTime);
|
||||||
|
|
||||||
xf_rail_send_activate(xfi, event->xany.window, False);
|
//xf_rail_send_activate(xfi, event->xany.window, False);
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
@ -476,7 +476,7 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
|
|||||||
app = True;
|
app = True;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
if (event->type != MotionNotify)
|
if (event->type != MotionNotify)
|
||||||
printf("X11 %s Event: wnd=0x%X\n", X11_EVENT_STRINGS[event->type], (uint32)event->xany.window);
|
printf("X11 %s Event: wnd=0x%X\n", X11_EVENT_STRINGS[event->type], (uint32)event->xany.window);
|
||||||
#endif
|
#endif
|
||||||
|
@ -82,6 +82,7 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
|
|||||||
window->windowId, window->ownerWindowId);
|
window->windowId, window->ownerWindowId);
|
||||||
|
|
||||||
xfparent = NULL;
|
xfparent = NULL;
|
||||||
|
|
||||||
if (window->ownerWindowId != 0)
|
if (window->ownerWindowId != 0)
|
||||||
{
|
{
|
||||||
rdpWindow* p = NULL;
|
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);
|
p = window_list_get_by_id(xfi->rail->list, window->ownerWindowId);
|
||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
xfparent = (xfWindow *)p->extra;
|
xfparent = (xfWindow *) p->extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfw = xf_CreateWindow((xfInfo*) rail->extra, xfparent,
|
xfw = xf_CreateWindow((xfInfo*) rail->extra, xfparent,
|
||||||
@ -97,10 +98,10 @@ void xf_rail_CreateWindow(rdpRail* rail, rdpWindow* window)
|
|||||||
window->windowWidth, window->windowHeight,
|
window->windowWidth, window->windowHeight,
|
||||||
window->windowId);
|
window->windowId);
|
||||||
|
|
||||||
XStoreName(xfi->display, xfw->handle, window->title);
|
|
||||||
|
|
||||||
xf_SetWindowStyle(xfi, xfw, window->style, window->extendedStyle);
|
xf_SetWindowStyle(xfi, xfw, window->style, window->extendedStyle);
|
||||||
|
|
||||||
|
XStoreName(xfi->display, xfw->handle, window->title);
|
||||||
|
|
||||||
window->extra = (void*) xfw;
|
window->extra = (void*) xfw;
|
||||||
window->extraId = (void*) xfw->handle;
|
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);
|
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)
|
void xf_rail_DestroyWindow(rdpRail* rail, rdpWindow* window)
|
||||||
{
|
{
|
||||||
xfWindow* xfw;
|
xfWindow* xfw;
|
||||||
@ -181,6 +193,7 @@ void xf_rail_register_callbacks(xfInfo* xfi, rdpRail* rail)
|
|||||||
rail->SetWindowText = xf_rail_SetWindowText;
|
rail->SetWindowText = xf_rail_SetWindowText;
|
||||||
rail->SetWindowIcon = xf_rail_SetWindowIcon;
|
rail->SetWindowIcon = xf_rail_SetWindowIcon;
|
||||||
rail->SetWindowRects = xf_rail_SetWindowRects;
|
rail->SetWindowRects = xf_rail_SetWindowRects;
|
||||||
|
rail->SetWindowVisibilityRects = xf_rail_SetWindowVisibilityRects;
|
||||||
rail->DestroyWindow = xf_rail_DestroyWindow;
|
rail->DestroyWindow = xf_rail_DestroyWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,6 @@ struct _PropMotifWmHints
|
|||||||
};
|
};
|
||||||
typedef struct _PropMotifWmHints 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)
|
void xf_SendClientMessage(xfInfo* xfi, xfWindow* window, Atom atom, long msg, long d1, long d2, long d3)
|
||||||
{
|
{
|
||||||
XEvent xevent;
|
XEvent xevent;
|
||||||
@ -162,43 +159,38 @@ void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show)
|
|||||||
window->decorations = 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)
|
void xf_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style)
|
||||||
{
|
{
|
||||||
Atom window_type;
|
Atom window_type;
|
||||||
|
|
||||||
window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
|
window_type = xfi->_NET_WM_WINDOW_TYPE_NORMAL;
|
||||||
|
|
||||||
if (((style & WS_POPUP) !=0) ||
|
if ((style & WS_POPUP) || (style & WS_DLGFRAME) || (ex_style & WS_EX_DLGMODALFRAME))
|
||||||
((style & WS_DLGFRAME) != 0) ||
|
|
||||||
((ex_style & WS_EX_DLGMODALFRAME) != 0)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
window_type = xfi->_NET_WM_WINDOW_TYPE_DIALOG;
|
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;
|
window_type = xfi->_NET_WM_WINDOW_TYPE_UTILITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_WINDOW_TYPE,
|
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* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height)
|
||||||
{
|
{
|
||||||
xfWindow* window;
|
xfWindow* window;
|
||||||
@ -295,36 +287,18 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, xfWindow* parent, int x, int y, int width
|
|||||||
XGCValues gcv;
|
XGCValues gcv;
|
||||||
int input_mask;
|
int input_mask;
|
||||||
XClassHint* class_hints;
|
XClassHint* class_hints;
|
||||||
Window parent_handle;
|
|
||||||
int lx;
|
|
||||||
int ly;
|
|
||||||
|
|
||||||
window->ref_count = 0;
|
window->ref_count = 0;
|
||||||
window->decorations = False;
|
window->decorations = False;
|
||||||
window->fullscreen = False;
|
window->fullscreen = False;
|
||||||
window->parent = parent;
|
window->parent = parent;
|
||||||
|
|
||||||
lx = x;
|
window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
|
||||||
ly = y;
|
x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
|
||||||
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,
|
|
||||||
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
|
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
|
||||||
CWBorderPixel, &xfi->attribs);
|
CWBorderPixel, &xfi->attribs);
|
||||||
|
|
||||||
xf_ReferenceWindow(xfi, window);
|
|
||||||
xf_ReferenceWindow(xfi, window->parent);
|
|
||||||
|
|
||||||
xf_SetWindowDecorations(xfi, window, window->decorations);
|
xf_SetWindowDecorations(xfi, window, window->decorations);
|
||||||
xf_SetWindowChildState(xfi, window);
|
|
||||||
|
|
||||||
class_hints = XAllocClassHint();
|
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->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv);
|
||||||
window->surface = XCreatePixmap(xfi->display, window->handle, window->width, window->height, xfi->depth);
|
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);
|
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)
|
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int lx, ly;
|
|
||||||
Pixmap surface;
|
Pixmap surface;
|
||||||
|
|
||||||
if ((width * height) < 1)
|
if ((width * height) < 1)
|
||||||
return;
|
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);
|
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)
|
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)
|
else if (window->left == x && window->top == y)
|
||||||
XResizeWindow(xfi->display, window->handle, width, height);
|
XResizeWindow(xfi->display, window->handle, width, height);
|
||||||
else
|
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);
|
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);
|
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);
|
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;
|
int i;
|
||||||
window->ref_count++;
|
XRectangle* xrects;
|
||||||
}
|
|
||||||
|
|
||||||
void xf_DereferenceWindow(xfInfo* xfi, xfWindow* window)
|
xrects = xmalloc(sizeof(XRectangle) * nrects);
|
||||||
{
|
|
||||||
if (window == NULL) return;
|
|
||||||
|
|
||||||
window->ref_count--;
|
for (i = 0; i < nrects; i++)
|
||||||
if (window->ref_count == 0)
|
|
||||||
{
|
{
|
||||||
printf("xf_DerefrenceWindow: destroying h=0x%X p=0x%X\n", (uint32)window->handle,
|
xrects[i].x = rects[i].left;
|
||||||
(window->parent != NULL) ? (uint32)window->parent->handle : 0);
|
xrects[i].y = rects[i].top;
|
||||||
|
xrects[i].width = rects[i].right - rects[i].left;
|
||||||
if (window->gc)
|
xrects[i].height = rects[i].bottom - rects[i].top;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)
|
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,
|
if (window->surface)
|
||||||
(window->parent != NULL) ? (uint32)window->parent->handle : 0);
|
XFreePixmap(xfi->display, window->surface);
|
||||||
|
|
||||||
xf_DereferenceWindow(xfi, window);
|
if (window->handle)
|
||||||
xf_DereferenceWindow(xfi, parent);
|
{
|
||||||
|
XUnmapWindow(xfi->display, window->handle);
|
||||||
|
XDestroyWindow(xfi->display, window->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(window);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ boolean xf_GetWorkArea(xfInfo* xfi);
|
|||||||
|
|
||||||
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen);
|
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen);
|
||||||
void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show);
|
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);
|
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_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state);
|
||||||
void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon);
|
void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon);
|
||||||
void xf_SetWindowRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects);
|
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_SetWindowStyle(xfInfo* xfi, xfWindow* window, uint32 style, uint32 ex_style);
|
||||||
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window);
|
void xf_DestroyWindow(xfInfo* xfi, xfWindow* window);
|
||||||
|
|
||||||
|
389
client/X11/xfreerdp.1.xml
Normal file
389
client/X11/xfreerdp.1.xml
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
|
||||||
|
<refentry>
|
||||||
|
<refentryinfo>
|
||||||
|
<date>2011-08-27</date>
|
||||||
|
<author>
|
||||||
|
<authorblurb><para>The FreeRDP-Team</para></authorblurb>
|
||||||
|
</author>
|
||||||
|
</refentryinfo>
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>xfreerdp</refentrytitle>
|
||||||
|
<manvolnum>1</manvolnum>
|
||||||
|
<refmiscinfo class="source">freerdp</refmiscinfo>
|
||||||
|
<refmiscinfo class="manual">xfreerdp</refmiscinfo>
|
||||||
|
</refmeta>
|
||||||
|
<refnamediv>
|
||||||
|
<refname><application>xfreerdp</application></refname>
|
||||||
|
<refpurpose>X11 frontend to libFreeRDP</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<refsynopsisdivinfo>
|
||||||
|
<date>2011-08-27</date>
|
||||||
|
</refsynopsisdivinfo>
|
||||||
|
<para>
|
||||||
|
<command>xfreerdp</command> [options] server[:port] [[options] server[:port] …]
|
||||||
|
</para>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
<refsect1>
|
||||||
|
<refsect1info>
|
||||||
|
<date>2011-08-27</date>
|
||||||
|
</refsect1info>
|
||||||
|
<title>DESCRIPTION</title>
|
||||||
|
<para>
|
||||||
|
<command>xfreerdp</command> 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.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
<refsect1>
|
||||||
|
<title>OPTIONS</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-0</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Attach to the admin console of the server.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-a <replaceable class="parameter">bpp</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets the color depth for the connection to <replaceable class="parameter">bpp</replaceable> bits per pixel.
|
||||||
|
Valid values are 8, 15, 16, 24 and 32. The default value is the color depth of the FreeRDP-window.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry id="WorkingDir">
|
||||||
|
<term>-c <replaceable class="parameter">dir</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets the working-dir to <replaceable class="parameter">dir</replaceable>.
|
||||||
|
This parameter is only used when an AlternateShell (<xref linkend="AlternateShell"/>) is requested.
|
||||||
|
<replaceable class="parameter">dir</replaceable> should contain the executable file specified in the AlternateShell.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-D</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Removes the windows decorations.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-d</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Domain used in authentication.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-f</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
start in full screen mode. This mode can always be en- and disabled using Ctrl-Alt-Enter.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-g <replaceable class="parameter">geometry</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets the size of the FreeRDP-window (and of the remote desktop, when establishing a new connection).
|
||||||
|
<replaceable class="parameter">geometry</replaceable> can have one of the following forms:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<replaceable class="parameter">W</replaceable>x<replaceable class="parameter">H</replaceable> -
|
||||||
|
in this case the resulting window will be of
|
||||||
|
<replaceable class="parameter">W</replaceable>x<replaceable class="parameter">H</replaceable> pixels.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<replaceable class="parameter">P</replaceable>% -
|
||||||
|
in this case the resulting window will be <replaceable class="parameter">P</replaceable>%
|
||||||
|
of your screen.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The special keyword <emphasis>workarea</emphasis> -
|
||||||
|
in this case the resulting window will be of the same size as your workarea.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-k <replaceable class="parameter">id</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets the keyboard-layout-id to <replaceable class="parameter">id</replaceable>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-m</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Don't send mouse motion events.
|
||||||
|
<!-- TODO: what is this good for? -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-n <replaceable class="parameter">hostname</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the reported client hostname to <replaceable class="parameter">hostname</replaceable>.
|
||||||
|
Default is to automatically detect the hostname.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-o</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Play audio on the console instead of redirecting to the client.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-p <replaceable class="parameter">password</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Password used in authentication.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry id="AlternateShell">
|
||||||
|
<term>-s <replaceable class="parameter">shell</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Sets the startup-shell to <replaceable class="parameter">shell</replaceable>.
|
||||||
|
This parameter should contain a complete path to the alternate shell.
|
||||||
|
If the alternete shell requires a different working directory use <xref linkend="WorkingDir"/>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-t <replaceable class="parameter">port</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Connect to <replaceable class="parameter">port</replaceable>, instead of the default 3389.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-u <replaceable class="parameter">username</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Username used in authentication.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-x <replaceable class="parameter">flag</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Set the experiance performance flags.
|
||||||
|
<replaceable class="parameter">flag</replaceable> can be one of:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
m - (modem): Equivalent to 15.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
b - (broadband): Equivalent to 1.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
l - (lan): Equivalent to 0.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<replaceable class="parameter">num</replaceable> - A number that represents a
|
||||||
|
bit-mask, were numbers mean the following
|
||||||
|
<footnote><para>Taken from <ulink url="http://msdn.microsoft.com/en-us/library/cc240476%28v=prot.10%29.aspx">
|
||||||
|
MS-RDPBCGR Scetion 2.2.1.11.1.1.1 - Extended Info Packet</ulink></para></footnote>:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>1: Disable desktop wallpaper.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>2: Disable full-window drag (only the window outline is displayed when the window is moved).</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>4: Disable menu animations.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>8: Disable user interface themes.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>32: Disable mouse cursor shadows.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>64: Disable cursor blinking.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>128: Enable font smoothing.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>256: Enable Desktop Composition.</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>-z</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Enable compression.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--app</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
initialize a RemoteApp connection. This implies -g workarea.
|
||||||
|
FIXME: How to do RemoteApp
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--ext</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
load an extension
|
||||||
|
FIXME: How to do this
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--no-auth</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Skips authentication. This is useful e.g. for the current FreeRDP server that doesn't yet support server-side authentication.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--no-fastpath</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--no-osb</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Disable off screen bitmaps.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--plugin</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
load a plugin
|
||||||
|
FIXME: How to do this
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--rfx</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Enable RemoteFX.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--no-rdp</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Disable Standard RDP encryption.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--no-tls</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Disable TLS encryption.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--no-nla</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Disable network level authentication.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--sec <replaceable class="parameter">proto</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
force protocol security. <replaceable class="parameter">proto</replaceable> can be one of rdp, tls or nla.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>--version</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Print version information.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
<!-- refsect1>
|
||||||
|
<title>USAGE</title>
|
||||||
|
<para>
|
||||||
|
<command>foo</command> -f foo.conf -d2 foodata.foo
|
||||||
|
</para>
|
||||||
|
</refsect1 -->
|
||||||
|
<!-- refsect1>
|
||||||
|
<title>CAVEATS</title>
|
||||||
|
<para>
|
||||||
|
Other programs named <command>foo</command> may exist and actually
|
||||||
|
do something!
|
||||||
|
</para>
|
||||||
|
</refsect1 -->
|
||||||
|
<!-- refsect1>
|
||||||
|
<title>BUGS</title>
|
||||||
|
<para>
|
||||||
|
None. Program does nothing.
|
||||||
|
</para>
|
||||||
|
</refsect1 -->
|
||||||
|
<refsect1>
|
||||||
|
<title>LINKS</title>
|
||||||
|
<para>
|
||||||
|
<ulink url="http://www.freerdp.com/">http://www.freerdp.com/</ulink>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
@ -718,7 +718,7 @@ int main(int argc, char* argv[])
|
|||||||
chanman = freerdp_chanman_new();
|
chanman = freerdp_chanman_new();
|
||||||
SET_CHANMAN(instance, chanman);
|
SET_CHANMAN(instance, chanman);
|
||||||
|
|
||||||
instance->settings->sw_gdi = False;
|
instance->settings->sw_gdi = True;
|
||||||
|
|
||||||
if (freerdp_parse_args(instance->settings, argc, argv,
|
if (freerdp_parse_args(instance->settings, argc, argv,
|
||||||
xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0)
|
xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0)
|
||||||
|
@ -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_LICENSE "Print license debug messages." OFF)
|
||||||
option(WITH_DEBUG_GDI "Print graphics debug messages." OFF)
|
option(WITH_DEBUG_GDI "Print graphics debug messages." OFF)
|
||||||
option(WITH_DEBUG_RFX "Print RemoteFX 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_PROFILER "Compile profiler." OFF)
|
||||||
option(WITH_SSE2 "Use SSE2 optimization." OFF)
|
option(WITH_SSE2 "Use SSE2 optimization." OFF)
|
||||||
|
@ -28,22 +28,22 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
|
|
||||||
find_path(Xext_INCLUDE_DIR NAMES Xext.h
|
find_path(XEXT_INCLUDE_DIR NAMES Xext.h
|
||||||
PATH_SUFFIXES X11/extensions
|
PATH_SUFFIXES X11/extensions
|
||||||
DOC "The Xext include directory"
|
DOC "The Xext include directory"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(Xext_LIBRARY NAMES Xext
|
find_library(XEXT_LIBRARY NAMES Xext
|
||||||
DOC "The Xext library"
|
DOC "The Xext library"
|
||||||
)
|
)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
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)
|
if(XEXT_FOUND)
|
||||||
set( Xext_LIBRARIES ${Xext_LIBRARY} )
|
set( XEXT_LIBRARIES ${XEXT_LIBRARY} )
|
||||||
set( Xext_INCLUDE_DIRS ${Xext_INCLUDE_DIR} )
|
set( XEXT_INCLUDE_DIRS ${XEXT_INCLUDE_DIR} )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
mark_as_advanced(Xext_INCLUDE_DIR Xext_LIBRARY)
|
mark_as_advanced(XEXT_INCLUDE_DIR XEXT_LIBRARY)
|
||||||
|
|
||||||
|
35
cmake/FindXmlto.cmake
Normal file
35
cmake/FindXmlto.cmake
Normal file
@ -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 <nils@nils-andresen.de>
|
||||||
|
#
|
||||||
|
# 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)
|
@ -44,6 +44,8 @@ add_executable(test_freerdp
|
|||||||
test_list.h
|
test_list.h
|
||||||
test_orders.c
|
test_orders.c
|
||||||
test_orders.h
|
test_orders.h
|
||||||
|
test_pcap.c
|
||||||
|
test_pcap.h
|
||||||
test_license.c
|
test_license.c
|
||||||
test_license.h
|
test_license.h
|
||||||
test_stream.c
|
test_stream.c
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "test_librfx.h"
|
#include "test_librfx.h"
|
||||||
#include "test_freerdp.h"
|
#include "test_freerdp.h"
|
||||||
#include "test_rail.h"
|
#include "test_rail.h"
|
||||||
|
#include "test_pcap.h"
|
||||||
|
|
||||||
void dump_data(unsigned char * p, int len, int width, char* name)
|
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();
|
add_per_suite();
|
||||||
}
|
}
|
||||||
|
else if (strcmp("pcap", argv[*pindex]) == 0)
|
||||||
|
{
|
||||||
|
add_pcap_suite();
|
||||||
|
}
|
||||||
else if (strcmp("ber", argv[*pindex]) == 0)
|
else if (strcmp("ber", argv[*pindex]) == 0)
|
||||||
{
|
{
|
||||||
add_ber_suite();
|
add_ber_suite();
|
||||||
|
99
cunit/test_pcap.c
Normal file
99
cunit/test_pcap.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
* pcap File Format Unit Tests
|
||||||
|
*
|
||||||
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
#include <freerdp/utils/hexdump.h>
|
||||||
|
#include <freerdp/utils/pcap.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
26
cunit/test_pcap.h
Normal file
26
cunit/test_pcap.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
* pcap File Format Unit Tests
|
||||||
|
*
|
||||||
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_freerdp.h"
|
||||||
|
|
||||||
|
int init_pcap_suite(void);
|
||||||
|
int clean_pcap_suite(void);
|
||||||
|
int add_pcap_suite(void);
|
||||||
|
|
||||||
|
void test_pcap(void);
|
@ -17,5 +17,5 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
file(GLOB HEADERS "freerdp/*.h")
|
file(GLOB HEADERS "freerdp/*")
|
||||||
install_files(/include/freerdp FILES ${HEADERS})
|
install_files(/include/freerdp FILES ${HEADERS})
|
||||||
|
@ -40,6 +40,7 @@ typedef void (*railShowWindow)(rdpRail* rail, rdpWindow* window, uint8 state);
|
|||||||
typedef void (*railSetWindowText)(rdpRail* rail, rdpWindow* window);
|
typedef void (*railSetWindowText)(rdpRail* rail, rdpWindow* window);
|
||||||
typedef void (*railSetWindowIcon)(rdpRail* rail, rdpWindow* window, rdpIcon* icon);
|
typedef void (*railSetWindowIcon)(rdpRail* rail, rdpWindow* window, rdpIcon* icon);
|
||||||
typedef void (*railSetWindowRects)(rdpRail* rail, rdpWindow* window);
|
typedef void (*railSetWindowRects)(rdpRail* rail, rdpWindow* window);
|
||||||
|
typedef void (*railSetWindowVisibilityRects)(rdpRail* rail, rdpWindow* window);
|
||||||
|
|
||||||
struct rdp_rail
|
struct rdp_rail
|
||||||
{
|
{
|
||||||
@ -56,6 +57,7 @@ struct rdp_rail
|
|||||||
railSetWindowText SetWindowText;
|
railSetWindowText SetWindowText;
|
||||||
railSetWindowIcon SetWindowIcon;
|
railSetWindowIcon SetWindowIcon;
|
||||||
railSetWindowRects SetWindowRects;
|
railSetWindowRects SetWindowRects;
|
||||||
|
railSetWindowVisibilityRects SetWindowVisibilityRects;
|
||||||
};
|
};
|
||||||
|
|
||||||
FREERDP_API void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update);
|
FREERDP_API void rail_register_update_callbacks(rdpRail* rail, rdpUpdate* update);
|
||||||
|
@ -297,6 +297,11 @@ struct rdp_settings
|
|||||||
uint8 rfx_codec_id;
|
uint8 rfx_codec_id;
|
||||||
boolean frame_acknowledge;
|
boolean frame_acknowledge;
|
||||||
|
|
||||||
|
boolean dump_rfx;
|
||||||
|
boolean play_rfx;
|
||||||
|
char* dump_rfx_file;
|
||||||
|
char* play_rfx_file;
|
||||||
|
|
||||||
boolean remote_app;
|
boolean remote_app;
|
||||||
uint8 num_icon_caches;
|
uint8 num_icon_caches;
|
||||||
uint16 num_icon_cache_entries;
|
uint16 num_icon_cache_entries;
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <freerdp/rail.h>
|
#include <freerdp/rail.h>
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/utils/pcap.h>
|
||||||
|
#include <freerdp/utils/stream.h>
|
||||||
|
|
||||||
/* Common */
|
/* 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 (*pcNonMonitoredDesktop)(rdpUpdate* update, WINDOW_ORDER_INFO* orderInfo);
|
||||||
|
|
||||||
typedef void (*pcSurfaceBits)(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command);
|
typedef void (*pcSurfaceBits)(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command);
|
||||||
|
typedef void (*pcSurfaceCommand)(rdpUpdate* update, STREAM* s);
|
||||||
|
|
||||||
struct rdp_update
|
struct rdp_update
|
||||||
{
|
{
|
||||||
@ -1072,6 +1075,10 @@ struct rdp_update
|
|||||||
void* param1;
|
void* param1;
|
||||||
void* param2;
|
void* param2;
|
||||||
|
|
||||||
|
boolean dump_rfx;
|
||||||
|
boolean play_rfx;
|
||||||
|
rdpPcap* pcap_rfx;
|
||||||
|
|
||||||
pcBeginPaint BeginPaint;
|
pcBeginPaint BeginPaint;
|
||||||
pcEndPaint EndPaint;
|
pcEndPaint EndPaint;
|
||||||
pcSetBounds SetBounds;
|
pcSetBounds SetBounds;
|
||||||
@ -1142,6 +1149,7 @@ struct rdp_update
|
|||||||
pcNonMonitoredDesktop NonMonitoredDesktop;
|
pcNonMonitoredDesktop NonMonitoredDesktop;
|
||||||
|
|
||||||
pcSurfaceBits SurfaceBits;
|
pcSurfaceBits SurfaceBits;
|
||||||
|
pcSurfaceCommand SurfaceCommand;
|
||||||
|
|
||||||
BITMAP_UPDATE bitmap_update;
|
BITMAP_UPDATE bitmap_update;
|
||||||
PALETTE_UPDATE palette_update;
|
PALETTE_UPDATE palette_update;
|
||||||
|
42
include/freerdp/utils/certstore.h
Normal file
42
include/freerdp/utils/certstore.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef __CERTSTORE_UTILS_H
|
||||||
|
#define __CERTSTORE_UTILS_H
|
||||||
|
|
||||||
|
typedef struct rdp_certstore rdpCertstore;
|
||||||
|
typedef struct rdp_certdata rdpCertdata;
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <freerdp/api.h>
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
#include <freerdp/utils/memory.h>
|
||||||
|
|
||||||
|
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 */
|
83
include/freerdp/utils/pcap.h
Normal file
83
include/freerdp/utils/pcap.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
* pcap File Format Utils
|
||||||
|
*
|
||||||
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTILS_PCAP_H
|
||||||
|
#define __UTILS_PCAP_H
|
||||||
|
|
||||||
|
#include <freerdp/api.h>
|
||||||
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/utils/stopwatch.h>
|
||||||
|
|
||||||
|
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 */
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <freerdp/api.h>
|
#include <freerdp/api.h>
|
||||||
|
#include <freerdp/types.h>
|
||||||
#include <freerdp/utils/memory.h>
|
#include <freerdp/utils/memory.h>
|
||||||
|
|
||||||
struct _STOPWATCH
|
struct _STOPWATCH
|
||||||
@ -40,6 +41,7 @@ FREERDP_API void stopwatch_start(STOPWATCH* stopwatch);
|
|||||||
FREERDP_API void stopwatch_stop(STOPWATCH* stopwatch);
|
FREERDP_API void stopwatch_stop(STOPWATCH* stopwatch);
|
||||||
FREERDP_API void stopwatch_reset(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 */
|
#endif /* __UTILS_STOPWATCH_H */
|
||||||
|
@ -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)
|
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 */
|
stream_write_uint16(s, 49); /* codecPropertiesLength */
|
||||||
|
|
||||||
/* TS_RFX_CLNT_CAPS_CONTAINER */
|
/* TS_RFX_CLNT_CAPS_CONTAINER */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -25,7 +25,6 @@
|
|||||||
#include "ntlmssp.h"
|
#include "ntlmssp.h"
|
||||||
|
|
||||||
#include "credssp.h"
|
#include "credssp.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TSRequest ::= SEQUENCE {
|
* TSRequest ::= SEQUENCE {
|
||||||
* version [0] INTEGER,
|
* version [0] INTEGER,
|
||||||
@ -109,7 +108,7 @@ int credssp_get_public_key(rdpCredssp* credssp)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
CryptoCert cert;
|
CryptoCert cert;
|
||||||
|
|
||||||
cert = tls_get_certificate(credssp->transport->tls);
|
cert = tls_get_certificate(credssp->transport->tls);
|
||||||
|
|
||||||
if (cert == NULL)
|
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");
|
printf("credssp_get_public_key: tls_get_certificate failed to return the server certificate.\n");
|
||||||
return 0;
|
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);
|
ret = crypto_cert_get_public_key(cert, &credssp->public_key);
|
||||||
crypto_cert_free(cert);
|
crypto_cert_free(cert);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* 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);
|
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);
|
||||||
|
}
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
#include <freerdp/utils/blob.h>
|
#include <freerdp/utils/blob.h>
|
||||||
#include <freerdp/utils/memory.h>
|
#include <freerdp/utils/memory.h>
|
||||||
|
#include <freerdp/utils/certstore.h>
|
||||||
|
|
||||||
struct crypto_sha1_struct
|
struct crypto_sha1_struct
|
||||||
{
|
{
|
||||||
@ -83,8 +84,12 @@ void crypto_rc4_free(CryptoRc4 rc4);
|
|||||||
|
|
||||||
typedef struct crypto_cert_struct* CryptoCert;
|
typedef struct crypto_cert_struct* CryptoCert;
|
||||||
CryptoCert crypto_cert_read(uint8* data, uint32 length);
|
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);
|
void crypto_cert_free(CryptoCert cert);
|
||||||
|
boolean x509_verify_cert(CryptoCert cert);
|
||||||
boolean crypto_cert_verify(CryptoCert server_cert, CryptoCert cacert);
|
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);
|
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);
|
void crypto_rsa_encrypt(uint8* input, int length, uint32 key_length, uint8* modulus, uint8* exponent, uint8* output);
|
||||||
|
@ -73,6 +73,26 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
|
|||||||
return length;
|
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)
|
boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s)
|
||||||
{
|
{
|
||||||
/* TODO: fipsInformation */
|
/* 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)
|
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)
|
static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
|
||||||
{
|
{
|
||||||
uint8 updateHeader;
|
uint16 size;
|
||||||
|
int next_pos;
|
||||||
|
uint32 totalSize;
|
||||||
uint8 updateCode;
|
uint8 updateCode;
|
||||||
uint8 fragmentation;
|
uint8 fragmentation;
|
||||||
uint8 compression;
|
uint8 compression;
|
||||||
uint8 compressionFlags;
|
uint8 compressionFlags;
|
||||||
uint16 size;
|
|
||||||
STREAM* update_stream;
|
STREAM* update_stream;
|
||||||
int next_pos;
|
|
||||||
|
|
||||||
stream_read_uint8(s, updateHeader);
|
fastpath_read_update_header(s, &updateCode, &fragmentation, &compression);
|
||||||
updateCode = updateHeader & 0x0F;
|
|
||||||
fragmentation = (updateHeader >> 4) & 0x03;
|
|
||||||
compression = (updateHeader >> 6) & 0x03;
|
|
||||||
|
|
||||||
if (compression == FASTPATH_OUTPUT_COMPRESSION_USED)
|
if (compression == FASTPATH_OUTPUT_COMPRESSION_USED)
|
||||||
stream_read_uint8(s, compressionFlags);
|
stream_read_uint8(s, compressionFlags);
|
||||||
@ -207,6 +224,7 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
|
|||||||
update_stream = NULL;
|
update_stream = NULL;
|
||||||
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
|
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
|
||||||
{
|
{
|
||||||
|
totalSize = size;
|
||||||
update_stream = s;
|
update_stream = s;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -220,13 +238,13 @@ static void fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s)
|
|||||||
if (fragmentation == FASTPATH_FRAGMENT_LAST)
|
if (fragmentation == FASTPATH_FRAGMENT_LAST)
|
||||||
{
|
{
|
||||||
update_stream = fastpath->updateData;
|
update_stream = fastpath->updateData;
|
||||||
size = stream_get_length(update_stream);
|
totalSize = stream_get_length(update_stream);
|
||||||
stream_set_pos(update_stream, 0);
|
stream_set_pos(update_stream, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_stream)
|
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);
|
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
|
* 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)
|
if (stream_get_left(s) < 1)
|
||||||
@ -457,9 +475,10 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
|
|||||||
uint16 length;
|
uint16 length;
|
||||||
|
|
||||||
length = stream_get_length(s);
|
length = stream_get_length(s);
|
||||||
|
|
||||||
if (length > FASTPATH_MAX_PACKET_SIZE)
|
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;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,6 +494,41 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
|
|||||||
return True;
|
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)
|
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId)
|
||||||
{
|
{
|
||||||
STREAM* s;
|
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);
|
fragment_size = MIN(FASTPATH_MAX_PACKET_SIZE - stream_get_length(s), bitmapDataLength);
|
||||||
|
|
||||||
if (fragment_size == bitmapDataLength)
|
if (fragment_size == bitmapDataLength)
|
||||||
{
|
|
||||||
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST);
|
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT);
|
fragmentation = (i == 0 ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT);
|
||||||
}
|
|
||||||
size += fragment_size;
|
size += fragment_size;
|
||||||
|
|
||||||
ep = stream_get_pos(s);
|
ep = stream_get_pos(s);
|
||||||
stream_set_pos(s, bp);
|
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_write_uint16(s, size);
|
||||||
stream_set_pos(s, ep);
|
stream_set_pos(s, ep);
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s);
|
|||||||
|
|
||||||
STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath);
|
STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath);
|
||||||
boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s);
|
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_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId);
|
||||||
boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);
|
boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
|
#include "surface.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
@ -34,10 +35,51 @@ boolean freerdp_connect(freerdp* instance)
|
|||||||
rdp = (rdpRdp*) instance->rdp;
|
rdp = (rdpRdp*) instance->rdp;
|
||||||
|
|
||||||
IFCALL(instance->PreConnect, instance);
|
IFCALL(instance->PreConnect, instance);
|
||||||
|
|
||||||
status = rdp_client_connect((rdpRdp*) instance->rdp);
|
status = rdp_client_connect((rdpRdp*) instance->rdp);
|
||||||
|
|
||||||
if (status)
|
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);
|
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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <freerdp/utils/pcap.h>
|
||||||
|
|
||||||
#include "surface.h"
|
#include "surface.h"
|
||||||
|
|
||||||
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s)
|
static int update_recv_surfcmd_surface_bits(rdpUpdate* update, STREAM* s)
|
||||||
{
|
{
|
||||||
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
|
|
||||||
int pos;
|
int pos;
|
||||||
|
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
|
||||||
|
|
||||||
stream_read_uint16(s, cmd->destLeft);
|
stream_read_uint16(s, cmd->destLeft);
|
||||||
stream_read_uint16(s, cmd->destTop);
|
stream_read_uint16(s, cmd->destTop);
|
||||||
@ -56,12 +58,16 @@ static int update_recv_surfcmd_frame_marker(rdpUpdate* update, STREAM* s)
|
|||||||
return 6;
|
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;
|
uint16 cmdType;
|
||||||
|
uint32 cmdLength;
|
||||||
|
|
||||||
while (size > 2)
|
while (size > 2)
|
||||||
{
|
{
|
||||||
|
stream_get_mark(s, mark);
|
||||||
|
|
||||||
stream_read_uint16(s, cmdType);
|
stream_read_uint16(s, cmdType);
|
||||||
size -= 2;
|
size -= 2;
|
||||||
|
|
||||||
@ -69,17 +75,25 @@ boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
|
|||||||
{
|
{
|
||||||
case CMDTYPE_SET_SURFACE_BITS:
|
case CMDTYPE_SET_SURFACE_BITS:
|
||||||
case CMDTYPE_STREAM_SURFACE_BITS:
|
case CMDTYPE_STREAM_SURFACE_BITS:
|
||||||
size -= update_recv_surfcmd_surface_bits(update, s);
|
cmdLength = update_recv_surfcmd_surface_bits(update, s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMDTYPE_FRAME_MARKER:
|
case CMDTYPE_FRAME_MARKER:
|
||||||
size -= update_recv_surfcmd_frame_marker(update, s);
|
cmdLength = update_recv_surfcmd_frame_marker(update, s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
|
DEBUG_WARN("unknown cmdType 0x%X", cmdType);
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size -= cmdLength;
|
||||||
|
|
||||||
|
if (update->dump_rfx)
|
||||||
|
{
|
||||||
|
pcap_add_record(update->pcap_rfx, mark, cmdLength + 2);
|
||||||
|
pcap_flush(update->pcap_rfx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ enum SURFCMD_FRAMEACTION
|
|||||||
SURFACECMD_FRAMEACTION_END = 0x0001
|
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_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
|
||||||
void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);
|
void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* 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
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -240,7 +240,7 @@ rdpTls* tls_new()
|
|||||||
tls->connect = tls_connect;
|
tls->connect = tls_connect;
|
||||||
tls->accept = tls_accept;
|
tls->accept = tls_accept;
|
||||||
tls->disconnect = tls_disconnect;
|
tls->disconnect = tls_disconnect;
|
||||||
|
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
}
|
}
|
||||||
@ -248,6 +248,69 @@ rdpTls* tls_new()
|
|||||||
return tls;
|
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)
|
void tls_free(rdpTls* tls)
|
||||||
{
|
{
|
||||||
if (tls != NULL)
|
if (tls != NULL)
|
||||||
|
@ -49,8 +49,9 @@ boolean tls_disconnect(rdpTls* tls);
|
|||||||
int tls_read(rdpTls* tls, uint8* data, int length);
|
int tls_read(rdpTls* tls, uint8* data, int length);
|
||||||
int tls_write(rdpTls* tls, uint8* data, int length);
|
int tls_write(rdpTls* tls, uint8* data, int length);
|
||||||
CryptoCert tls_get_certificate(rdpTls* tls);
|
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);
|
boolean tls_print_error(char* func, SSL* connection, int value);
|
||||||
|
|
||||||
rdpTls* tls_new();
|
rdpTls* tls_new();
|
||||||
void tls_free(rdpTls* tls);
|
void tls_free(rdpTls* tls);
|
||||||
|
|
||||||
|
@ -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)
|
static void update_send_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command)
|
||||||
{
|
{
|
||||||
rdpRdp* rdp = (rdpRdp*)update->rdp;
|
rdpRdp* rdp = (rdpRdp*)update->rdp;
|
||||||
|
|
||||||
fastpath_send_surfcmd_surface_bits(rdp->fastpath, surface_bits_command);
|
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->Synchronize = update_send_synchronize;
|
||||||
update->PointerSystem = update_send_pointer_system;
|
update->PointerSystem = update_send_pointer_system;
|
||||||
update->SurfaceBits = update_send_surface_bits;
|
update->SurfaceBits = update_send_surface_bits;
|
||||||
|
update->SurfaceCommand = update_send_surface_command;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpUpdate* update_new(rdpRdp* rdp)
|
rdpUpdate* update_new(rdpRdp* rdp)
|
||||||
|
@ -284,6 +284,10 @@ void rail_CreateWindow(rdpRail* rail, rdpWindow* window)
|
|||||||
{
|
{
|
||||||
IFCALL(rail->SetWindowRects, rail, 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)
|
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)
|
if (window->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||||
{
|
{
|
||||||
|
IFCALL(rail->SetWindowVisibilityRects, rail, window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,9 +30,11 @@ set(FREERDP_UTILS_SRCS
|
|||||||
load_plugin.c
|
load_plugin.c
|
||||||
memory.c
|
memory.c
|
||||||
mutex.c
|
mutex.c
|
||||||
|
pcap.c
|
||||||
profiler.c
|
profiler.c
|
||||||
rail.c
|
rail.c
|
||||||
registry.c
|
registry.c
|
||||||
|
certstore.c
|
||||||
semaphore.c
|
semaphore.c
|
||||||
sleep.c
|
sleep.c
|
||||||
stopwatch.c
|
stopwatch.c
|
||||||
|
@ -51,7 +51,47 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
|||||||
|
|
||||||
while (index < argc)
|
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++;
|
index++;
|
||||||
if (index == argc)
|
if (index == argc)
|
||||||
@ -242,6 +282,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
|||||||
settings->performance_flags = PERF_FLAG_NONE;
|
settings->performance_flags = PERF_FLAG_NONE;
|
||||||
settings->large_pointer = True;
|
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)
|
else if (strcmp("-m", argv[index]) == 0)
|
||||||
{
|
{
|
||||||
settings->mouse_motion = True;
|
settings->mouse_motion = True;
|
||||||
|
213
libfreerdp-utils/certstore.c
Normal file
213
libfreerdp-utils/certstore.c
Normal file
@ -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 <freerdp/utils/certstore.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#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);
|
||||||
|
}
|
193
libfreerdp-utils/pcap.c
Normal file
193
libfreerdp-utils/pcap.c
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Client
|
||||||
|
* pcap File Format Utils
|
||||||
|
*
|
||||||
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/utils/memory.h>
|
||||||
|
|
||||||
|
#include <freerdp/utils/pcap.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
@ -56,5 +56,15 @@ void stopwatch_reset(STOPWATCH* stopwatch)
|
|||||||
|
|
||||||
double stopwatch_get_elapsed_time_in_seconds(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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <freerdp/rfx/rfx.h>
|
#include <freerdp/rfx/rfx.h>
|
||||||
#include <freerdp/listener.h>
|
#include <freerdp/listener.h>
|
||||||
|
|
||||||
|
static char* test_pcap_file = NULL;
|
||||||
|
|
||||||
/* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */
|
/* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */
|
||||||
static const unsigned int test_quantization_values[] =
|
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;
|
RFX_RECT rect;
|
||||||
STREAM* s;
|
STREAM* s;
|
||||||
|
|
||||||
|
if (client->update->dump_rfx)
|
||||||
|
return;
|
||||||
if (!client->settings->rfx_codec || !info)
|
if (!client->settings->rfx_codec || !info)
|
||||||
return;
|
return;
|
||||||
if (info->icon_width < 1)
|
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;
|
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)
|
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. */
|
/* A real server should tag the peer as activated here and start sending updates in mainloop. */
|
||||||
test_peer_init(client);
|
test_peer_init(client);
|
||||||
test_peer_draw_background(client);
|
|
||||||
test_peer_load_icon(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 False here would stop the execution of the peer mainloop. */
|
||||||
return True;
|
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)
|
static void* test_peer_mainloop(void* arg)
|
||||||
{
|
{
|
||||||
freerdp_peer* client = (freerdp_peer*)arg;
|
|
||||||
int i;
|
int i;
|
||||||
int fds;
|
int fds;
|
||||||
int max_fds;
|
int max_fds;
|
||||||
int rcount;
|
int rcount;
|
||||||
void* rfds[32];
|
void* rfds[32];
|
||||||
fd_set rfds_set;
|
fd_set rfds_set;
|
||||||
|
freerdp_peer* client = (freerdp_peer*) arg;
|
||||||
|
|
||||||
memset(rfds, 0, sizeof(rfds));
|
memset(rfds, 0, sizeof(rfds));
|
||||||
|
|
||||||
@ -452,8 +492,11 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
instance->PeerAccepted = test_peer_accepted;
|
instance->PeerAccepted = test_peer_accepted;
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
test_pcap_file = argv[1];
|
||||||
|
|
||||||
/* Open the server socket and start listening. */
|
/* 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. */
|
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
|
||||||
test_server_mainloop(instance);
|
test_server_mainloop(instance);
|
||||||
|
BIN
server/test/rfx_test.pcap
Normal file
BIN
server/test/rfx_test.pcap
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user