diff --git a/common/os_calls.c b/common/os_calls.c index 9b3a9e31..6d6acaef 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -18,6 +18,8 @@ generic operating system calls + put all the os / arch define in here you want + */ #ifdef _WIN32 @@ -117,13 +119,17 @@ void* g_malloc(int size, int zero) rv = (char*)malloc(size + sizeof(struct xrdp_mem)); if (zero) + { memset(rv, 0, size + sizeof(struct xrdp_mem)); + } g_memsize += size; p = (struct xrdp_mem*)rv; p->size = size; p->id = g_memid; if (g_memlist != 0) + { xrdp_list_add_item(g_memlist, (int)p); + } g_memid++; return rv + sizeof(struct xrdp_mem); #else @@ -131,7 +137,9 @@ void* g_malloc(int size, int zero) rv = (char*)malloc(size); if (zero) + { memset(rv, 0, size); + } return rv; #endif } @@ -143,7 +151,9 @@ void* g_malloc1(int size, int zero) rv = (char*)malloc(size); if (zero) + { memset(rv, 0, size); + } return rv; } @@ -160,7 +170,9 @@ void g_free(void* ptr) g_memsize -= p->size; i = xrdp_list_index_of(g_memlist, (int)p); if (i >= 0) + { xrdp_list_remove_item(g_memlist, i); + } free(p); } #else @@ -216,14 +228,22 @@ void g_hexdump(char* p, int len) printf("%04x ", offset); thisline = len - offset; if (thisline > 16) + { thisline = 16; + } for (i = 0; i < thisline; i++) + { printf("%02x ", line[i]); + } for (; i < 16; i++) + { printf(" "); + } for (i = 0; i < thisline; i++) + { printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); - printf("\n"); + } + printf("\n\r"); offset += thisline; line += thisline; } @@ -247,6 +267,16 @@ int g_getchar(void) return getchar(); } +/*****************************************************************************/ +int g_tcp_set_no_delay(int sck) +{ + int i; + + i = 1; + setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i)); + return 0; +} + /*****************************************************************************/ int g_tcp_socket(void) { @@ -272,7 +302,9 @@ int g_tcp_local_socket(void) void g_tcp_close(int sck) { if (sck == 0) + { return; + } #ifdef _WIN32 closesocket(sck); #else @@ -294,10 +326,18 @@ int g_tcp_connect(int sck, char* address, char* port) { h = gethostbyname(address); if (h != 0) + { if (h->h_name != 0) + { if (h->h_addr_list != 0) + { if ((*(h->h_addr_list)) != 0) + { s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); + } + } + } + } } return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); } @@ -399,12 +439,18 @@ int g_tcp_force_recv(int sck, char* data, int len) if (rcvd == -1) { if (g_tcp_last_error_would_block(sck)) + { g_sleep(1); + } else + { return 1; + } } else if (rcvd == 0) + { return 1; + } else { data += rcvd; @@ -431,12 +477,18 @@ int g_tcp_force_send(int sck, char* data, int len) if (sent == -1) { if (g_tcp_last_error_would_block(sck)) + { g_sleep(1); + } else + { return 1; + } } else if (sent == 0) + { return 1; + } else { data += sent; @@ -461,15 +513,21 @@ int g_tcp_select(int sck1, int sck2) FD_SET(((unsigned int)sck2), &rfds); max = sck1; if (sck2 > max) + { max = sck2; + } rv = select(max + 1, &rfds, 0, 0, &time); if (rv > 0) { rv = 0; if (FD_ISSET(((unsigned int)sck1), &rfds)) + { rv = rv | 1; + } if (FD_ISSET(((unsigned int)sck2), &rfds)) + { rv = rv | 2; + } } return rv; } @@ -653,7 +711,9 @@ void g_random(char* data, int len) memset(data, 0x44, len); fd = open("/dev/urandom", O_RDONLY); if (fd == -1) + { fd = open("/dev/random", O_RDONLY); + } if (fd != -1) { read(fd, data, len); @@ -703,9 +763,13 @@ int g_file_read(int fd, char* ptr, int len) { #ifdef _WIN32 if (ReadFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) + { return len; + } else + { return -1; + } #else return read(fd, ptr, len); #endif @@ -717,9 +781,13 @@ int g_file_write(int fd, char* ptr, int len) { #ifdef _WIN32 if (WriteFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) + { return len; + } else + { return -1; + } #else return write(fd, ptr, len); #endif diff --git a/common/os_calls.h b/common/os_calls.h index 7766563d..009ed4a4 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -32,6 +32,7 @@ void g_free1(void* ptr); void g_memset(void* ptr, int val, int size); void g_memcpy(void* d_ptr, const void* s_ptr, int size); int g_getchar(void); +int g_tcp_set_no_delay(int sck); int g_tcp_socket(void); int g_tcp_local_socket(void); void g_tcp_close(int sck); diff --git a/sesman/Makefile b/sesman/Makefile new file mode 100644 index 00000000..7844495d --- /dev/null +++ b/sesman/Makefile @@ -0,0 +1,16 @@ + +SESMANOBJ = sesman.o ../common/os_calls.o + +CFLAGS = -Wall -O2 -I../common +LDFLAGS = -L /usr/gnu/lib +LIBS = -lpam_userpass -lcrypto -lpthread +PAMLIB = /lib/libpam.so.0 +CC = gcc + +all: sesman + +sesman: $(SESMANOBJ) + $(CC) $(LDFLAGS) -o sesman $(PAMLIB) $(SESMANOBJ) $(LIBS) + +clean: + rm -f $(SESMANOBJ) sesman diff --git a/sesman/sesman.c b/sesman/sesman.c new file mode 100644 index 00000000..d18096bb --- /dev/null +++ b/sesman/sesman.c @@ -0,0 +1,484 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2005 + + session manager + linux only + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "arch.h" +#include "parse.h" +#include "os_calls.h" + +#define SERVICE "xrdp" + +struct session_item +{ + char name[256]; + int pid; // pid of sesman waiting for wm to end + int display; + int width; + int height; + int bpp; +}; + +struct session_item session_items[100]; + +/******************************************************************************/ +struct session_item* find_session_item(char* name, int width, + int height, int bpp) +{ + int i; + + for (i = 0; i < 100; i++) + { + if (g_strcmp(name, session_items[i].name) == 0 && + session_items[i].width == width && + session_items[i].height == height && + session_items[i].bpp == bpp) + { + return session_items + i; + } + } + return 0; +} + +/******************************************************************************/ +struct session_item* find_session_item_by_name(char* name) +{ + int i; + + for (i = 0; i < 100; i++) + { + if (g_strcmp(name, session_items[i].name) == 0) + { + return session_items + i; + } + } + return 0; +} + +/******************************************************************************/ +struct session_item* find_session_item_by_display(int display) +{ + int i; + + for (i = 0; i < 100; i++) + { + if (session_items[i].display == display) + { + return session_items + i; + } + } + return 0; +} + +/******************************************************************************/ +int x_server_running(int display) +{ + char text[256]; + + g_sprintf(text, "/tmp/.X11-unix/X%d", display); + return access(text, F_OK) == 0; +} + +/******************************************************************************/ +/* returns boolean */ +int auth_pam_userpass(const char* user, const char* pass) +{ + pam_handle_t* pamh; + pam_userpass_t userpass; + struct pam_conv conv = {pam_userpass_conv, &userpass}; + const void* template1; + int status; + + userpass.user = user; + userpass.pass = pass; + if (pam_start(SERVICE, user, &conv, &pamh) != PAM_SUCCESS) + { + return 0; + } + status = pam_authenticate(pamh, 0); + if (status != PAM_SUCCESS) + { + pam_end(pamh, status); + return 0; + } + status = pam_acct_mgmt(pamh, 0); + if (status != PAM_SUCCESS) + { + pam_end(pamh, status); + return 0; + } + status = pam_get_item(pamh, PAM_USER, &template1); + if (status != PAM_SUCCESS) + { + pam_end(pamh, status); + return 0; + } + if (pam_end(pamh, PAM_SUCCESS) != PAM_SUCCESS) + { + return 0; + } + return 1; +} + +/******************************************************************************/ +void cterm(int s) +{ + int i; + int pid; + int wstat; + + pid = waitpid(0, &wstat, WNOHANG); + if (pid > 0) + { + for (i = 0; i < 100; i++) + { + if (session_items[i].pid == pid) + { + g_memset(session_items + i, 0, sizeof(struct session_item)); + } + } + } +} + +/******************************************************************************/ +/* ge the next available X display */ +int get_next_display(void) +{ + int i; + + for (i = 10; i < 100; i++) + { + if (!x_server_running(i)) + { + return i; + } + } + return -1; +} + +/******************************************************************************/ +int start_session(int width, int height, int bpp, char* username) +{ + int display; + int pid; + int uid; + int wmpid; + int xpid; + struct passwd* pwd_1; + char text[256]; + char geometry[32]; + char depth[32]; + char screen[32]; + + display = 10; + while (x_server_running(display) && display < 50) + { + display++; + } + if (display >= 50) + { + return 0; + } + wmpid = 0; + pid = fork(); + if (pid == -1) + { + } + else if (pid == 0) // child + { + pwd_1 = getpwnam(username); + if (pwd_1 != 0) + { + uid = pwd_1->pw_uid; + if (setuid(uid) == 0) + { + setenv("USER", username, 1); + g_sprintf(text, "%d", uid); + setenv("UID", text, 1); + setenv("HOME", pwd_1->pw_dir, 1); + chdir(pwd_1->pw_dir); + if (access(".bash_profile", F_OK) == 0) + { + system("sh .bash_profile"); + } + g_sprintf(text, ":%d.0", display); + setenv("DISPLAY", text, 1); + g_sprintf(geometry, "%dx%d", width, height); + g_sprintf(depth, "%d", bpp); + g_sprintf(screen, ":%d", display); + wmpid = fork(); + if (wmpid == -1) + { + } + else if (wmpid == 0) // child + { + // give X a bit to start + g_sleep(500); + if (x_server_running(display)) + { + execlp("startkde", NULL); + // should not get here + } + g_printf("error\n"); + _exit(0); + } + else // parent + { + xpid = fork(); + if (xpid == -1) + { + } + else if (xpid == 0) // child + { + g_sprintf(text, "%s/.vnc/passwd", pwd_1->pw_dir); + if (access(text, F_OK) == 0) + { + execlp("Xvnc", "Xvnc", screen, "-geometry", geometry, + "-depth", depth, "-bs", "-rfbauth", text, NULL); + } + else + { + execlp("Xvnc", "Xvnc", screen, "-geometry", geometry, + "-depth", depth, "-bs", NULL); + } + // should not get here + g_printf("error\n"); + _exit(0); + } + else // parent + { + waitpid(wmpid, 0, 0); + kill(xpid, SIGTERM); + kill(wmpid, SIGTERM); + _exit(0); + } + } + } + } + } + else // parent + { + signal(SIGCHLD, cterm); + session_items[display].pid = pid; + g_strcpy(session_items[display].name, username); + session_items[display].display = display; + session_items[display].width = width; + session_items[display].height = height; + session_items[display].bpp = bpp; + g_sleep(1000); + } + return display; +} + +/******************************************************************************/ +int main(int argc, char** argv) +{ + int sck; + int in_sck; + int code; + int i; + int size; + int version; + int ok; + int width; + int height; + int bpp; + int display; + struct stream* in_s; + struct stream* out_s; + char* username; + char* password; + char user[256]; + char pass[256]; + struct session_item* s_item; + + g_memset(&session_items, 0, sizeof(session_items)); + if (argc == 1) + { + g_printf("xrdp session manager v0.1\n"); + g_printf("usage\n"); + g_printf("sesman wait - wait for connection\n"); + g_printf("sesman server username password width height bpp - \ +start session\n"); + } + else if (argc == 2 && g_strcmp(argv[1], "wait") == 0) + { + make_stream(in_s); + init_stream(in_s, 8192); + make_stream(out_s); + init_stream(out_s, 8192); + g_printf("listening\n"); + sck = g_tcp_socket(); + if (g_tcp_bind(sck, "3350") == 0) + { + if (g_tcp_listen(sck) == 0) + { + in_sck = g_tcp_accept(sck); + while (in_sck > 0) + { + init_stream(in_s, 8192); + if (g_tcp_force_recv(in_sck, in_s->data, 8) == 0) + { + in_uint32_be(in_s, version); + in_uint32_be(in_s, size); + init_stream(in_s, 8192); + if (g_tcp_force_recv(in_sck, in_s->data, size - 8) == 0) + { + if (version == 0) + { + in_uint16_be(in_s, code); + if (code == 0) // check username - password, start session + { + in_uint16_be(in_s, i); + in_uint8a(in_s, user, i); + user[i] = 0; + //g_printf("%s\n", user); + in_uint16_be(in_s, i); + in_uint8a(in_s, pass, i); + pass[i] = 0; + //g_printf("%s\n", pass); + in_uint16_be(in_s, width); + in_uint16_be(in_s, height); + in_uint16_be(in_s, bpp); + //g_printf("%d %d %d\n", width, height, bpp); + ok = auth_pam_userpass(user, pass); + display = 0; + if (ok) + { + s_item = find_session_item(user, width, height, bpp); + if (s_item != 0) + { + display = s_item->display; + } + else + { + display = start_session(width, height, bpp, user); + } + if (display == 0) + { + ok = 0; + } + } + init_stream(out_s, 8192); + out_uint32_be(out_s, 0); // version + out_uint32_be(out_s, 14); // size + out_uint16_be(out_s, 3); // cmd + out_uint16_be(out_s, ok); // data + out_uint16_be(out_s, display); // data + s_mark_end(out_s); + g_tcp_force_send(in_sck, out_s->data, + out_s->end - out_s->data); + } + } + } + } + close(in_sck); + in_sck = g_tcp_accept(sck); + } + } + else + { + g_printf("listen error\n"); + } + } + else + { + g_printf("bind error\n"); + } + g_tcp_close(sck); + free_stream(in_s); + free_stream(out_s); + } + else if (argc == 7) + { + username = argv[2]; + password = argv[3]; + width = atoi(argv[4]); + height = atoi(argv[5]); + bpp = atoi(argv[6]); + make_stream(in_s); + init_stream(in_s, 8192); + make_stream(out_s); + init_stream(out_s, 8192); + sck = g_tcp_socket(); + if (g_tcp_connect(sck, argv[1], "3350") == 0) + { + s_push_layer(out_s, channel_hdr, 8); + out_uint16_be(out_s, 0); // code + i = g_strlen(username); + out_uint16_be(out_s, i); + out_uint8a(out_s, username, i); + i = g_strlen(password); + out_uint16_be(out_s, i); + out_uint8a(out_s, password, i); + //g_printf("%d\n", width); + out_uint16_be(out_s, width); + out_uint16_be(out_s, height); + out_uint16_be(out_s, bpp); + s_mark_end(out_s); + s_pop_layer(out_s, channel_hdr); + out_uint32_be(out_s, 0); // version + out_uint32_be(out_s, out_s->end - out_s->data); // size + g_tcp_force_send(sck, out_s->data, out_s->end - out_s->data); + if (g_tcp_force_recv(sck, in_s->data, 8) == 0) + { + in_uint32_be(in_s, version); + in_uint32_be(in_s, size); + init_stream(in_s, 8192); + if (g_tcp_force_recv(sck, in_s->data, size - 8) == 0) + { + if (version == 0) + { + in_uint16_be(in_s, code); + if (code == 3) + { + in_uint16_be(in_s, ok); + in_uint16_be(in_s, display); + g_printf("ok %d display %d\n", ok, display); + } + } + } + } + } + else + { + g_printf("connect error\n"); + } + g_tcp_close(sck); + free_stream(in_s); + free_stream(out_s); + } + return 0; +} diff --git a/sesman/sesman.ini b/sesman/sesman.ini new file mode 100644 index 00000000..d01e8d2f --- /dev/null +++ b/sesman/sesman.ini @@ -0,0 +1,5 @@ + +[globals] +auth=pam +xserver=Xvnc :%d -geometry %dx%d -depth %d -bs +wm=startkde diff --git a/vnc/vnc.c b/vnc/vnc.c index a8514c7b..94c39ae8 100644 --- a/vnc/vnc.c +++ b/vnc/vnc.c @@ -22,11 +22,6 @@ #include "vnc.h" -char* vnc_start_command = -"su %s -c \"sh ../vnc/startvnc.sh :%d %d %d %d\""; -char* vnc_stop_command = -""; - /******************************************************************************/ int lib_mod_event(struct vnc* v, int msg, int param1, int param2) { @@ -258,8 +253,12 @@ int lib_framebuffer_update(struct vnc* v) int r; int g; int b; + int data_size; + int need_size; struct stream* s; + data_size = 0; + data = 0; Bpp = (v->mod_bpp + 7) / 8; make_stream(s); init_stream(s, 8192); @@ -287,7 +286,13 @@ int lib_framebuffer_update(struct vnc* v) in_uint32_be(s, encoding); if (encoding == 0) /* raw */ { - data = (char*)g_malloc(cx * cy * Bpp, 0); + need_size = cx * cy * Bpp; + if (need_size > data_size) + { + g_free(data); + data = (char*)g_malloc(need_size, 0); + data_size = need_size; + } if (g_tcp_force_recv(v->sck, data, cx * cy * Bpp) != 0) { g_free(data); @@ -295,13 +300,13 @@ int lib_framebuffer_update(struct vnc* v) return 1; } v->server_paint_rect(v, x, y, cx, cy, data); - g_free(data); } else if (encoding == 1) /* copy rect */ { init_stream(s, 8192); if (g_tcp_force_recv(v->sck, s->data, 4) != 0) { + g_free(data); free_stream(s); return 1; } @@ -317,6 +322,7 @@ int lib_framebuffer_update(struct vnc* v) if (g_tcp_force_recv(v->sck, s->data, cx * cy * Bpp + ((cx + 7) / 8) * cy) != 0) { + g_free(data); free_stream(s); return 1; } @@ -339,8 +345,13 @@ int lib_framebuffer_update(struct vnc* v) } v->server_set_cursor(v, x, y, cursor_data, cursor_mask); } + else + { + g_printf("error in lib_framebuffer_update\n\r"); + } } v->server_end_update(v); + g_free(data); /* FrambufferUpdateRequest */ init_stream(s, 8192); @@ -491,34 +502,77 @@ int lib_mod_connect(struct vnc* v) { char cursor_data[32 * (32 * 3)]; char cursor_mask[32 * (32 / 8)]; - char text[256]; char con_port[256]; struct stream* s; struct stream* pixel_format; int error; int i; int check_sec_result; + int sck; + int version; + int size; + int code; + int ok; + int display; check_sec_result = 1; if (g_strcmp(v->ip, "") == 0) { return 6; } + make_stream(s); if (g_strcmp(v->port, "-1") == 0) { - i = 10; - g_sprintf(text, vnc_start_command, v->username, i, v->server_bpp, - v->server_width, v->server_height); - error = g_system(text); - while (error != 0 && i < 100) + i = 0; + error = 0; + init_stream(s, 8192); + sck = g_tcp_socket(); + if (g_tcp_connect(sck, v->ip, "3350") == 0) { - i++; - g_sprintf(text, vnc_start_command, v->username, i, v->server_bpp, - v->server_width, v->server_height); - error = g_system(text); + s_push_layer(s, channel_hdr, 8); + out_uint16_be(s, 0); // code + i = g_strlen(v->username); + out_uint16_be(s, i); + out_uint8a(s, v->username, i); + i = g_strlen(v->password); + out_uint16_be(s, i); + out_uint8a(s, v->password, i); + out_uint16_be(s, v->server_width); + out_uint16_be(s, v->server_height); + out_uint16_be(s, v->server_bpp); + s_mark_end(s); + s_pop_layer(s, channel_hdr); + out_uint32_be(s, 0); // version + out_uint32_be(s, s->end - s->data); // size + g_tcp_force_send(sck, s->data, s->end - s->data); + init_stream(s, 8192); + if (g_tcp_force_recv(sck, s->data, 8) == 0) + { + in_uint32_be(s, version); + in_uint32_be(s, size); + init_stream(s, 8192); + if (g_tcp_force_recv(sck, s->data, size - 8) == 0) + { + if (version == 0) + { + in_uint16_be(s, code); + if (code == 3) + { + in_uint16_be(s, ok); + in_uint16_be(s, display); + if (ok) + { + i = display; + } + } + } + } + } } - if (error != 0) + g_tcp_close(sck); + if (error != 0 || i == 0) { + free_stream(s); return 5; } g_sprintf(con_port, "%d", 5900 + i); @@ -528,7 +582,6 @@ int lib_mod_connect(struct vnc* v) { g_sprintf(con_port, "%s", v->port); } - make_stream(s); make_stream(pixel_format); v->sck = g_tcp_socket(); error = g_tcp_connect(v->sck, v->ip, con_port); @@ -681,12 +734,8 @@ int lib_mod_invalidate(struct vnc* v, int x, int y, int cx, int cy) /******************************************************************************/ int lib_mod_end(struct vnc* v) { - char text[256]; - if (v->vnc_desktop != 0) { - g_sprintf(text, vnc_stop_command, v->username, v->vnc_desktop); - g_system(text); } return 0; } @@ -695,13 +744,21 @@ int lib_mod_end(struct vnc* v) int lib_mod_set_param(struct vnc* v, char* name, char* value) { if (g_strcmp(name, "username") == 0) + { g_strncpy(v->username, value, 255); + } else if (g_strcmp(name, "password") == 0) + { g_strncpy(v->password, value, 255); + } else if (g_strcmp(name, "ip") == 0) + { g_strncpy(v->ip, value, 255); + } else if (g_strcmp(name, "port") == 0) + { g_strncpy(v->port, value, 255); + } return 0; } diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index f46acb9c..9a682181 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -4,28 +4,19 @@ bitmap_cache=yes bitmap_compression=yes [vnc1] -name=self:2 +name=sesman lib=../vnc/libvnc.so auth=local ip=127.0.0.1 -port=5902 +port=-1 username=ask -password=master +password=ask [vnc2] -name=self:3 +name=console lib=../vnc/libvnc.so auth=local ip=127.0.0.1 -port=5903 -username=n/a -password=master - -[vnc3] -name=playback -lib=../vnc/libvnc.so -auth=local -ip=127.0.0.1 -port=5910 -username=n/a -password=tucker +port=5900 +username=ask +password=ask diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c index 492466ee..f46cb187 100644 --- a/xrdp/xrdp_listen.c +++ b/xrdp/xrdp_listen.c @@ -47,17 +47,31 @@ int xrdp_listen_term_processes(struct xrdp_listen* self) /* tell all xrdp processes to end */ for (i = 0; i < self->process_list_count; i++) + { if (self->process_list[i] != 0) + { self->process_list[i]->term = 1; + } + } /* make sure they are done */ for (i = 0; i < self->process_list_count; i++) + { if (self->process_list[i] != 0) + { while (self->process_list[i]->status > 0) + { g_sleep(10); + } + } + } /* free them all */ for (i = 0; i < self->process_list_count; i++) + { if (self->process_list[i] != 0) + { xrdp_process_delete(self->process_list[i]); + } + } return 0; } @@ -133,9 +147,13 @@ int xrdp_listen_main_loop(struct xrdp_listen* self) { error = g_tcp_accept(self->sck); if (error == -1 && g_tcp_last_error_would_block(self->sck)) + { g_sleep(100); + } else if (error == -1) + { break; + } else { g_process = xrdp_process_create(self); @@ -147,7 +165,9 @@ int xrdp_listen_main_loop(struct xrdp_listen* self) g_sleep(100); } else + { xrdp_process_delete(g_process); + } } } } diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index 38b58d99..b6fa0d19 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -187,10 +187,10 @@ int xrdp_wm_login_notify(struct xrdp_bitmap* wnd, } else if (sender->id == 2) /* cancel button */ { - /*if (wnd != 0) + if (wnd != 0) if (wnd->wm != 0) if (wnd->wm->pro_layer != 0) - wnd->wm->pro_layer->term = 1;*/ + wnd->wm->pro_layer->term = 1; } else if (sender->id == 3) /* ok button */ { diff --git a/xrdp/xrdp_mcs.c b/xrdp/xrdp_mcs.c index 82eeff0f..41197cfa 100644 --- a/xrdp/xrdp_mcs.c +++ b/xrdp/xrdp_mcs.c @@ -584,25 +584,18 @@ int xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s) /* returns error */ int xrdp_mcs_disconnect(struct xrdp_mcs* self) { - int len; struct stream* s; make_stream(s); init_stream(s, 8192); - if (xrdp_mcs_init(self, s) != 0) + if (xrdp_iso_init(self->iso_layer, s) != 0) { free_stream(s); return 1; } + out_uint8(s, (MCS_DPUM << 2) | 1); + out_uint8(s, 0x80); s_mark_end(s); - s_pop_layer(s, mcs_hdr); - len = (s->end - s->p) - 8; - len = len | 0x8000; - out_uint8(s, MCS_DPUM << 2); - out_uint16_be(s, self->userid); - out_uint16_be(s, MCS_GLOBAL_CHANNEL); - out_uint8(s, 0x70); - out_uint16_be(s, len); if (xrdp_iso_send(self->iso_layer, s) != 0) { free_stream(s); diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index aa9acfa1..91531688 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -1,169 +1,171 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2004-2005 - - main rdp process - -*/ - -#include "xrdp.h" - -/*****************************************************************************/ -struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner) -{ - struct xrdp_process* self; - - self = (struct xrdp_process*)g_malloc(sizeof(struct xrdp_process), 1); - self->lis_layer = owner; - return self; -} - -/*****************************************************************************/ -void xrdp_process_delete(struct xrdp_process* self) -{ - if (self == 0) - { - return; - } - xrdp_rdp_delete(self->rdp_layer); - xrdp_orders_delete(self->orders); - xrdp_wm_delete(self->wm); - g_free(self); -} - -/*****************************************************************************/ -int xrdp_process_loop(struct xrdp_process* self, struct stream* s) -{ - int cont; - int rv; - int code; - - code = 0; - rv = 0; - cont = 1; - while (cont && !self->term) - { - if (xrdp_rdp_recv(self->rdp_layer, s, &code) != 0) - { - rv = 1; - break; - } - DEBUG(("xrdp_process_main_loop code %d\n\r", code)); - switch (code) - { - case -1: - xrdp_rdp_send_demand_active(self->rdp_layer); - break; - case 0: - break; - case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active(self->rdp_layer, s); - break; - case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data(self->rdp_layer, s) != 0) - { - DEBUG(("xrdp_rdp_process_data returned non zero\n\r")); - cont = 0; - self->term = 1; - } - break; - default: - g_printf("unknown in xrdp_process_main_loop\n\r"); - break; - } - if (cont) - { - cont = s->next_packet < s->end; - } - } - if (self->rdp_layer->up_and_running && self->wm == 0 && rv == 0) - { - /* only do this once */ - DEBUG(("xrdp_process_main_loop up and running\n\r")); - self->orders = xrdp_orders_create(self, self->rdp_layer); - self->wm = xrdp_wm_create(self, &self->rdp_layer->client_info); - xrdp_wm_init(self->wm); - } - return rv; -} - -/*****************************************************************************/ -int xrdp_process_main_loop(struct xrdp_process* self) -{ -#ifndef XRDP_LIB - int i; - struct stream* s; - - make_stream(s); - self->status = 1; - self->rdp_layer = xrdp_rdp_create(self, self->sck); - g_tcp_set_non_blocking(self->sck); - if (xrdp_rdp_incoming(self->rdp_layer) == 0) - { - while (!g_is_term() && !self->term) - { - i = g_tcp_select(self->sck, self->app_sck); - if (i & 1) - { - init_stream(s, 8192); - if (xrdp_process_loop(self, s) != 0) - { - break; - } - } - if (i & 2) /* mod socket fired */ - { - if (self->wm->mod == 0) - { - break; - } - if (self->wm->mod->mod_signal == 0) - { - break; - } - if (self->wm->mod->mod_signal(self->wm->mod) != 0) - { - break; - } - } - if (i == 0) /* no data on any stream */ - { - g_sleep(10); - } - else if (i < 0) - { - break; - } - } - } - if (self->wm->mod != 0) - { - if (self->wm->mod->mod_end != 0) - { - self->wm->mod->mod_end(self->wm->mod); - } - } - xrdp_rdp_disconnect(self->rdp_layer); - xrdp_rdp_delete(self->rdp_layer); - self->rdp_layer = 0; - g_tcp_close(self->sck); - self->status = -1; - xrdp_listen_delete_pro(self->lis_layer, self); - free_stream(s); -#endif - return 0; -} +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2004-2005 + + main rdp process + +*/ + +#include "xrdp.h" + +/*****************************************************************************/ +struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner) +{ + struct xrdp_process* self; + + self = (struct xrdp_process*)g_malloc(sizeof(struct xrdp_process), 1); + self->lis_layer = owner; + return self; +} + +/*****************************************************************************/ +void xrdp_process_delete(struct xrdp_process* self) +{ + if (self == 0) + { + return; + } + xrdp_rdp_delete(self->rdp_layer); + xrdp_orders_delete(self->orders); + xrdp_wm_delete(self->wm); + g_free(self); +} + +/*****************************************************************************/ +int xrdp_process_loop(struct xrdp_process* self, struct stream* s) +{ + int cont; + int rv; + int code; + + code = 0; + rv = 0; + cont = 1; + while (cont && !self->term) + { + if (xrdp_rdp_recv(self->rdp_layer, s, &code) != 0) + { + rv = 1; + break; + } + DEBUG(("xrdp_process_main_loop code %d\n\r", code)); + switch (code) + { + case -1: + xrdp_rdp_send_demand_active(self->rdp_layer); + break; + case 0: + break; + case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ + xrdp_rdp_process_confirm_active(self->rdp_layer, s); + break; + case RDP_PDU_DATA: /* 7 */ + if (xrdp_rdp_process_data(self->rdp_layer, s) != 0) + { + DEBUG(("xrdp_rdp_process_data returned non zero\n\r")); + cont = 0; + self->term = 1; + } + break; + default: + g_printf("unknown in xrdp_process_main_loop\n\r"); + break; + } + if (cont) + { + cont = s->next_packet < s->end; + } + } + if (self->rdp_layer->up_and_running && self->wm == 0 && rv == 0) + { + /* only do this once */ + DEBUG(("xrdp_process_main_loop up and running\n\r")); + self->orders = xrdp_orders_create(self, self->rdp_layer); + self->wm = xrdp_wm_create(self, &self->rdp_layer->client_info); + xrdp_wm_init(self->wm); + } + return rv; +} + +/*****************************************************************************/ +int xrdp_process_main_loop(struct xrdp_process* self) +{ +#ifndef XRDP_LIB + int i; + struct stream* s; + + make_stream(s); + self->status = 1; + self->rdp_layer = xrdp_rdp_create(self, self->sck); + g_tcp_set_non_blocking(self->sck); + g_tcp_set_no_delay(self->sck); + if (xrdp_rdp_incoming(self->rdp_layer) == 0) + { + while (!g_is_term() && !self->term) + { + i = g_tcp_select(self->sck, self->app_sck); + if (i & 1) + { + init_stream(s, 8192); + if (xrdp_process_loop(self, s) != 0) + { + break; + } + } + if (i & 2) /* mod socket fired */ + { + if (self->wm->mod == 0) + { + break; + } + if (self->wm->mod->mod_signal == 0) + { + break; + } + if (self->wm->mod->mod_signal(self->wm->mod) != 0) + { + break; + } + } + if (i == 0) /* no data on any stream */ + { + g_sleep(10); + } + else if (i < 0) + { + break; + } + } + } + if (self->wm->mod != 0) + { + if (self->wm->mod->mod_end != 0) + { + self->wm->mod->mod_end(self->wm->mod); + } + } + xrdp_rdp_disconnect(self->rdp_layer); + g_sleep(500); + xrdp_rdp_delete(self->rdp_layer); + self->rdp_layer = 0; + g_tcp_close(self->sck); + self->status = -1; + xrdp_listen_delete_pro(self->lis_layer, self); + free_stream(s); +#endif + return 0; +} diff --git a/xrdp/xrdp_rdp.c b/xrdp/xrdp_rdp.c index bed3e833..a36aeac6 100644 --- a/xrdp/xrdp_rdp.c +++ b/xrdp/xrdp_rdp.c @@ -777,6 +777,53 @@ int xrdp_rdp_process_data_font(struct xrdp_rdp* self, struct stream* s) return 0; } +/*****************************************************************************/ +/* sent 37 pdu */ +int xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp* self) +{ + struct stream* s; + + make_stream(s); + init_stream(s, 8192); + if (xrdp_rdp_init_data(self, s) != 0) + { + free_stream(s); + return 1; + } + s_mark_end(s); + if (xrdp_rdp_send_data(self, s, 37) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} + +/*****************************************************************************/ +/* sent RDP_DATA_PDU_DISCONNECT 47 pdu */ +int xrdp_rdp_send_disconnect_reason(struct xrdp_rdp* self, int reason) +{ + struct stream* s; + + make_stream(s); + init_stream(s, 8192); + if (xrdp_rdp_init_data(self, s) != 0) + { + free_stream(s); + return 1; + } + out_uint32_le(s, reason); + s_mark_end(s); + if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_DISCONNECT) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} + /*****************************************************************************/ /* RDP_PDU_DATA */ int xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s) @@ -806,18 +853,20 @@ int xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s) case RDP_DATA_PDU_SYNCHRONISE: /* 31 */ xrdp_rdp_process_data_sync(self); break; - case 33: /* 33 ?? */ + case 33: /* 33 ?? Invalidate an area I think */ xrdp_rdp_process_screen_update(self, s); break; - - /*case 35:*/ + case 35: /* 35 ?? this comes when minimuzing a full screen mstsc.exe 2600 */ /* I think this is saying the client no longer wants screen */ /* updates and it will issue a 33 above to catch up */ - /* so minumized apps don't take bandwidth */ - - case 36: /* 36 ?? disconnect? */ - return 1; + /* so minimized apps don't take bandwidth */ + break; + case 36: /* 36 ?? disconnect query? */ + /* when this message comes, send a 37 back so the client */ + /* is sure the connection is alive and it can ask if user */ + /* really wants to disconnect */ + xrdp_rdp_send_disconnect_query_response(self); /* send a 37 back */ break; case RDP_DATA_PDU_FONT2: /* 39 */ xrdp_rdp_process_data_font(self, s);