added session manager and fixed disconnect problems

This commit is contained in:
jsorg71 2005-01-30 04:34:19 +00:00
parent f0c7bdb304
commit 0aff0efb52
12 changed files with 914 additions and 228 deletions

View File

@ -18,6 +18,8 @@
generic operating system calls generic operating system calls
put all the os / arch define in here you want
*/ */
#ifdef _WIN32 #ifdef _WIN32
@ -117,13 +119,17 @@ void* g_malloc(int size, int zero)
rv = (char*)malloc(size + sizeof(struct xrdp_mem)); rv = (char*)malloc(size + sizeof(struct xrdp_mem));
if (zero) if (zero)
{
memset(rv, 0, size + sizeof(struct xrdp_mem)); memset(rv, 0, size + sizeof(struct xrdp_mem));
}
g_memsize += size; g_memsize += size;
p = (struct xrdp_mem*)rv; p = (struct xrdp_mem*)rv;
p->size = size; p->size = size;
p->id = g_memid; p->id = g_memid;
if (g_memlist != 0) if (g_memlist != 0)
{
xrdp_list_add_item(g_memlist, (int)p); xrdp_list_add_item(g_memlist, (int)p);
}
g_memid++; g_memid++;
return rv + sizeof(struct xrdp_mem); return rv + sizeof(struct xrdp_mem);
#else #else
@ -131,7 +137,9 @@ void* g_malloc(int size, int zero)
rv = (char*)malloc(size); rv = (char*)malloc(size);
if (zero) if (zero)
{
memset(rv, 0, size); memset(rv, 0, size);
}
return rv; return rv;
#endif #endif
} }
@ -143,7 +151,9 @@ void* g_malloc1(int size, int zero)
rv = (char*)malloc(size); rv = (char*)malloc(size);
if (zero) if (zero)
{
memset(rv, 0, size); memset(rv, 0, size);
}
return rv; return rv;
} }
@ -160,7 +170,9 @@ void g_free(void* ptr)
g_memsize -= p->size; g_memsize -= p->size;
i = xrdp_list_index_of(g_memlist, (int)p); i = xrdp_list_index_of(g_memlist, (int)p);
if (i >= 0) if (i >= 0)
{
xrdp_list_remove_item(g_memlist, i); xrdp_list_remove_item(g_memlist, i);
}
free(p); free(p);
} }
#else #else
@ -216,14 +228,22 @@ void g_hexdump(char* p, int len)
printf("%04x ", offset); printf("%04x ", offset);
thisline = len - offset; thisline = len - offset;
if (thisline > 16) if (thisline > 16)
{
thisline = 16; thisline = 16;
}
for (i = 0; i < thisline; i++) for (i = 0; i < thisline; i++)
{
printf("%02x ", line[i]); printf("%02x ", line[i]);
}
for (; i < 16; i++) for (; i < 16; i++)
{
printf(" "); printf(" ");
}
for (i = 0; i < thisline; i++) for (i = 0; i < thisline; i++)
{
printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
printf("\n"); }
printf("\n\r");
offset += thisline; offset += thisline;
line += thisline; line += thisline;
} }
@ -247,6 +267,16 @@ int g_getchar(void)
return getchar(); 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) int g_tcp_socket(void)
{ {
@ -272,7 +302,9 @@ int g_tcp_local_socket(void)
void g_tcp_close(int sck) void g_tcp_close(int sck)
{ {
if (sck == 0) if (sck == 0)
{
return; return;
}
#ifdef _WIN32 #ifdef _WIN32
closesocket(sck); closesocket(sck);
#else #else
@ -294,10 +326,18 @@ int g_tcp_connect(int sck, char* address, char* port)
{ {
h = gethostbyname(address); h = gethostbyname(address);
if (h != 0) if (h != 0)
{
if (h->h_name != 0) if (h->h_name != 0)
{
if (h->h_addr_list != 0) if (h->h_addr_list != 0)
{
if ((*(h->h_addr_list)) != 0) if ((*(h->h_addr_list)) != 0)
{
s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
}
}
}
}
} }
return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); 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 (rcvd == -1)
{ {
if (g_tcp_last_error_would_block(sck)) if (g_tcp_last_error_would_block(sck))
{
g_sleep(1); g_sleep(1);
}
else else
{
return 1; return 1;
}
} }
else if (rcvd == 0) else if (rcvd == 0)
{
return 1; return 1;
}
else else
{ {
data += rcvd; data += rcvd;
@ -431,12 +477,18 @@ int g_tcp_force_send(int sck, char* data, int len)
if (sent == -1) if (sent == -1)
{ {
if (g_tcp_last_error_would_block(sck)) if (g_tcp_last_error_would_block(sck))
{
g_sleep(1); g_sleep(1);
}
else else
{
return 1; return 1;
}
} }
else if (sent == 0) else if (sent == 0)
{
return 1; return 1;
}
else else
{ {
data += sent; data += sent;
@ -461,15 +513,21 @@ int g_tcp_select(int sck1, int sck2)
FD_SET(((unsigned int)sck2), &rfds); FD_SET(((unsigned int)sck2), &rfds);
max = sck1; max = sck1;
if (sck2 > max) if (sck2 > max)
{
max = sck2; max = sck2;
}
rv = select(max + 1, &rfds, 0, 0, &time); rv = select(max + 1, &rfds, 0, 0, &time);
if (rv > 0) if (rv > 0)
{ {
rv = 0; rv = 0;
if (FD_ISSET(((unsigned int)sck1), &rfds)) if (FD_ISSET(((unsigned int)sck1), &rfds))
{
rv = rv | 1; rv = rv | 1;
}
if (FD_ISSET(((unsigned int)sck2), &rfds)) if (FD_ISSET(((unsigned int)sck2), &rfds))
{
rv = rv | 2; rv = rv | 2;
}
} }
return rv; return rv;
} }
@ -653,7 +711,9 @@ void g_random(char* data, int len)
memset(data, 0x44, len); memset(data, 0x44, len);
fd = open("/dev/urandom", O_RDONLY); fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) if (fd == -1)
{
fd = open("/dev/random", O_RDONLY); fd = open("/dev/random", O_RDONLY);
}
if (fd != -1) if (fd != -1)
{ {
read(fd, data, len); read(fd, data, len);
@ -703,9 +763,13 @@ int g_file_read(int fd, char* ptr, int len)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (ReadFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) if (ReadFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0))
{
return len; return len;
}
else else
{
return -1; return -1;
}
#else #else
return read(fd, ptr, len); return read(fd, ptr, len);
#endif #endif
@ -717,9 +781,13 @@ int g_file_write(int fd, char* ptr, int len)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (WriteFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) if (WriteFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0))
{
return len; return len;
}
else else
{
return -1; return -1;
}
#else #else
return write(fd, ptr, len); return write(fd, ptr, len);
#endif #endif

View File

@ -32,6 +32,7 @@ void g_free1(void* ptr);
void g_memset(void* ptr, int val, int size); void g_memset(void* ptr, int val, int size);
void g_memcpy(void* d_ptr, const void* s_ptr, int size); void g_memcpy(void* d_ptr, const void* s_ptr, int size);
int g_getchar(void); int g_getchar(void);
int g_tcp_set_no_delay(int sck);
int g_tcp_socket(void); int g_tcp_socket(void);
int g_tcp_local_socket(void); int g_tcp_local_socket(void);
void g_tcp_close(int sck); void g_tcp_close(int sck);

16
sesman/Makefile Normal file
View File

@ -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

484
sesman/sesman.c Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <security/pam_userpass.h>
#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;
}

5
sesman/sesman.ini Normal file
View File

@ -0,0 +1,5 @@
[globals]
auth=pam
xserver=Xvnc :%d -geometry %dx%d -depth %d -bs
wm=startkde

103
vnc/vnc.c
View File

@ -22,11 +22,6 @@
#include "vnc.h" #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) 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 r;
int g; int g;
int b; int b;
int data_size;
int need_size;
struct stream* s; struct stream* s;
data_size = 0;
data = 0;
Bpp = (v->mod_bpp + 7) / 8; Bpp = (v->mod_bpp + 7) / 8;
make_stream(s); make_stream(s);
init_stream(s, 8192); init_stream(s, 8192);
@ -287,7 +286,13 @@ int lib_framebuffer_update(struct vnc* v)
in_uint32_be(s, encoding); in_uint32_be(s, encoding);
if (encoding == 0) /* raw */ 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) if (g_tcp_force_recv(v->sck, data, cx * cy * Bpp) != 0)
{ {
g_free(data); g_free(data);
@ -295,13 +300,13 @@ int lib_framebuffer_update(struct vnc* v)
return 1; return 1;
} }
v->server_paint_rect(v, x, y, cx, cy, data); v->server_paint_rect(v, x, y, cx, cy, data);
g_free(data);
} }
else if (encoding == 1) /* copy rect */ else if (encoding == 1) /* copy rect */
{ {
init_stream(s, 8192); init_stream(s, 8192);
if (g_tcp_force_recv(v->sck, s->data, 4) != 0) if (g_tcp_force_recv(v->sck, s->data, 4) != 0)
{ {
g_free(data);
free_stream(s); free_stream(s);
return 1; return 1;
} }
@ -317,6 +322,7 @@ int lib_framebuffer_update(struct vnc* v)
if (g_tcp_force_recv(v->sck, s->data, if (g_tcp_force_recv(v->sck, s->data,
cx * cy * Bpp + ((cx + 7) / 8) * cy) != 0) cx * cy * Bpp + ((cx + 7) / 8) * cy) != 0)
{ {
g_free(data);
free_stream(s); free_stream(s);
return 1; return 1;
} }
@ -339,8 +345,13 @@ int lib_framebuffer_update(struct vnc* v)
} }
v->server_set_cursor(v, x, y, cursor_data, cursor_mask); 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); v->server_end_update(v);
g_free(data);
/* FrambufferUpdateRequest */ /* FrambufferUpdateRequest */
init_stream(s, 8192); init_stream(s, 8192);
@ -491,34 +502,77 @@ int lib_mod_connect(struct vnc* v)
{ {
char cursor_data[32 * (32 * 3)]; char cursor_data[32 * (32 * 3)];
char cursor_mask[32 * (32 / 8)]; char cursor_mask[32 * (32 / 8)];
char text[256];
char con_port[256]; char con_port[256];
struct stream* s; struct stream* s;
struct stream* pixel_format; struct stream* pixel_format;
int error; int error;
int i; int i;
int check_sec_result; int check_sec_result;
int sck;
int version;
int size;
int code;
int ok;
int display;
check_sec_result = 1; check_sec_result = 1;
if (g_strcmp(v->ip, "") == 0) if (g_strcmp(v->ip, "") == 0)
{ {
return 6; return 6;
} }
make_stream(s);
if (g_strcmp(v->port, "-1") == 0) if (g_strcmp(v->port, "-1") == 0)
{ {
i = 10; i = 0;
g_sprintf(text, vnc_start_command, v->username, i, v->server_bpp, error = 0;
v->server_width, v->server_height); init_stream(s, 8192);
error = g_system(text); sck = g_tcp_socket();
while (error != 0 && i < 100) if (g_tcp_connect(sck, v->ip, "3350") == 0)
{ {
i++; s_push_layer(s, channel_hdr, 8);
g_sprintf(text, vnc_start_command, v->username, i, v->server_bpp, out_uint16_be(s, 0); // code
v->server_width, v->server_height); i = g_strlen(v->username);
error = g_system(text); 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; return 5;
} }
g_sprintf(con_port, "%d", 5900 + i); 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); g_sprintf(con_port, "%s", v->port);
} }
make_stream(s);
make_stream(pixel_format); make_stream(pixel_format);
v->sck = g_tcp_socket(); v->sck = g_tcp_socket();
error = g_tcp_connect(v->sck, v->ip, con_port); 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) int lib_mod_end(struct vnc* v)
{ {
char text[256];
if (v->vnc_desktop != 0) if (v->vnc_desktop != 0)
{ {
g_sprintf(text, vnc_stop_command, v->username, v->vnc_desktop);
g_system(text);
} }
return 0; 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) int lib_mod_set_param(struct vnc* v, char* name, char* value)
{ {
if (g_strcmp(name, "username") == 0) if (g_strcmp(name, "username") == 0)
{
g_strncpy(v->username, value, 255); g_strncpy(v->username, value, 255);
}
else if (g_strcmp(name, "password") == 0) else if (g_strcmp(name, "password") == 0)
{
g_strncpy(v->password, value, 255); g_strncpy(v->password, value, 255);
}
else if (g_strcmp(name, "ip") == 0) else if (g_strcmp(name, "ip") == 0)
{
g_strncpy(v->ip, value, 255); g_strncpy(v->ip, value, 255);
}
else if (g_strcmp(name, "port") == 0) else if (g_strcmp(name, "port") == 0)
{
g_strncpy(v->port, value, 255); g_strncpy(v->port, value, 255);
}
return 0; return 0;
} }

View File

@ -4,28 +4,19 @@ bitmap_cache=yes
bitmap_compression=yes bitmap_compression=yes
[vnc1] [vnc1]
name=self:2 name=sesman
lib=../vnc/libvnc.so lib=../vnc/libvnc.so
auth=local auth=local
ip=127.0.0.1 ip=127.0.0.1
port=5902 port=-1
username=ask username=ask
password=master password=ask
[vnc2] [vnc2]
name=self:3 name=console
lib=../vnc/libvnc.so lib=../vnc/libvnc.so
auth=local auth=local
ip=127.0.0.1 ip=127.0.0.1
port=5903 port=5900
username=n/a username=ask
password=master password=ask
[vnc3]
name=playback
lib=../vnc/libvnc.so
auth=local
ip=127.0.0.1
port=5910
username=n/a
password=tucker

View File

@ -47,17 +47,31 @@ int xrdp_listen_term_processes(struct xrdp_listen* self)
/* tell all xrdp processes to end */ /* tell all xrdp processes to end */
for (i = 0; i < self->process_list_count; i++) for (i = 0; i < self->process_list_count; i++)
{
if (self->process_list[i] != 0) if (self->process_list[i] != 0)
{
self->process_list[i]->term = 1; self->process_list[i]->term = 1;
}
}
/* make sure they are done */ /* make sure they are done */
for (i = 0; i < self->process_list_count; i++) for (i = 0; i < self->process_list_count; i++)
{
if (self->process_list[i] != 0) if (self->process_list[i] != 0)
{
while (self->process_list[i]->status > 0) while (self->process_list[i]->status > 0)
{
g_sleep(10); g_sleep(10);
}
}
}
/* free them all */ /* free them all */
for (i = 0; i < self->process_list_count; i++) for (i = 0; i < self->process_list_count; i++)
{
if (self->process_list[i] != 0) if (self->process_list[i] != 0)
{
xrdp_process_delete(self->process_list[i]); xrdp_process_delete(self->process_list[i]);
}
}
return 0; return 0;
} }
@ -133,9 +147,13 @@ int xrdp_listen_main_loop(struct xrdp_listen* self)
{ {
error = g_tcp_accept(self->sck); error = g_tcp_accept(self->sck);
if (error == -1 && g_tcp_last_error_would_block(self->sck)) if (error == -1 && g_tcp_last_error_would_block(self->sck))
{
g_sleep(100); g_sleep(100);
}
else if (error == -1) else if (error == -1)
{
break; break;
}
else else
{ {
g_process = xrdp_process_create(self); g_process = xrdp_process_create(self);
@ -147,7 +165,9 @@ int xrdp_listen_main_loop(struct xrdp_listen* self)
g_sleep(100); g_sleep(100);
} }
else else
{
xrdp_process_delete(g_process); xrdp_process_delete(g_process);
}
} }
} }
} }

View File

@ -187,10 +187,10 @@ int xrdp_wm_login_notify(struct xrdp_bitmap* wnd,
} }
else if (sender->id == 2) /* cancel button */ else if (sender->id == 2) /* cancel button */
{ {
/*if (wnd != 0) if (wnd != 0)
if (wnd->wm != 0) if (wnd->wm != 0)
if (wnd->wm->pro_layer != 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 */ else if (sender->id == 3) /* ok button */
{ {

View File

@ -584,25 +584,18 @@ int xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s)
/* returns error */ /* returns error */
int xrdp_mcs_disconnect(struct xrdp_mcs* self) int xrdp_mcs_disconnect(struct xrdp_mcs* self)
{ {
int len;
struct stream* s; struct stream* s;
make_stream(s); make_stream(s);
init_stream(s, 8192); init_stream(s, 8192);
if (xrdp_mcs_init(self, s) != 0) if (xrdp_iso_init(self->iso_layer, s) != 0)
{ {
free_stream(s); free_stream(s);
return 1; return 1;
} }
out_uint8(s, (MCS_DPUM << 2) | 1);
out_uint8(s, 0x80);
s_mark_end(s); 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) if (xrdp_iso_send(self->iso_layer, s) != 0)
{ {
free_stream(s); free_stream(s);

View File

@ -1,169 +1,171 @@
/* /*
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server. xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2004-2005 Copyright (C) Jay Sorg 2004-2005
main rdp process main rdp process
*/ */
#include "xrdp.h" #include "xrdp.h"
/*****************************************************************************/ /*****************************************************************************/
struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner) struct xrdp_process* xrdp_process_create(struct xrdp_listen* owner)
{ {
struct xrdp_process* self; struct xrdp_process* self;
self = (struct xrdp_process*)g_malloc(sizeof(struct xrdp_process), 1); self = (struct xrdp_process*)g_malloc(sizeof(struct xrdp_process), 1);
self->lis_layer = owner; self->lis_layer = owner;
return self; return self;
} }
/*****************************************************************************/ /*****************************************************************************/
void xrdp_process_delete(struct xrdp_process* self) void xrdp_process_delete(struct xrdp_process* self)
{ {
if (self == 0) if (self == 0)
{ {
return; return;
} }
xrdp_rdp_delete(self->rdp_layer); xrdp_rdp_delete(self->rdp_layer);
xrdp_orders_delete(self->orders); xrdp_orders_delete(self->orders);
xrdp_wm_delete(self->wm); xrdp_wm_delete(self->wm);
g_free(self); g_free(self);
} }
/*****************************************************************************/ /*****************************************************************************/
int xrdp_process_loop(struct xrdp_process* self, struct stream* s) int xrdp_process_loop(struct xrdp_process* self, struct stream* s)
{ {
int cont; int cont;
int rv; int rv;
int code; int code;
code = 0; code = 0;
rv = 0; rv = 0;
cont = 1; cont = 1;
while (cont && !self->term) while (cont && !self->term)
{ {
if (xrdp_rdp_recv(self->rdp_layer, s, &code) != 0) if (xrdp_rdp_recv(self->rdp_layer, s, &code) != 0)
{ {
rv = 1; rv = 1;
break; break;
} }
DEBUG(("xrdp_process_main_loop code %d\n\r", code)); DEBUG(("xrdp_process_main_loop code %d\n\r", code));
switch (code) switch (code)
{ {
case -1: case -1:
xrdp_rdp_send_demand_active(self->rdp_layer); xrdp_rdp_send_demand_active(self->rdp_layer);
break; break;
case 0: case 0:
break; break;
case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ case RDP_PDU_CONFIRM_ACTIVE: /* 3 */
xrdp_rdp_process_confirm_active(self->rdp_layer, s); xrdp_rdp_process_confirm_active(self->rdp_layer, s);
break; break;
case RDP_PDU_DATA: /* 7 */ case RDP_PDU_DATA: /* 7 */
if (xrdp_rdp_process_data(self->rdp_layer, s) != 0) if (xrdp_rdp_process_data(self->rdp_layer, s) != 0)
{ {
DEBUG(("xrdp_rdp_process_data returned non zero\n\r")); DEBUG(("xrdp_rdp_process_data returned non zero\n\r"));
cont = 0; cont = 0;
self->term = 1; self->term = 1;
} }
break; break;
default: default:
g_printf("unknown in xrdp_process_main_loop\n\r"); g_printf("unknown in xrdp_process_main_loop\n\r");
break; break;
} }
if (cont) if (cont)
{ {
cont = s->next_packet < s->end; cont = s->next_packet < s->end;
} }
} }
if (self->rdp_layer->up_and_running && self->wm == 0 && rv == 0) if (self->rdp_layer->up_and_running && self->wm == 0 && rv == 0)
{ {
/* only do this once */ /* only do this once */
DEBUG(("xrdp_process_main_loop up and running\n\r")); DEBUG(("xrdp_process_main_loop up and running\n\r"));
self->orders = xrdp_orders_create(self, self->rdp_layer); self->orders = xrdp_orders_create(self, self->rdp_layer);
self->wm = xrdp_wm_create(self, &self->rdp_layer->client_info); self->wm = xrdp_wm_create(self, &self->rdp_layer->client_info);
xrdp_wm_init(self->wm); xrdp_wm_init(self->wm);
} }
return rv; return rv;
} }
/*****************************************************************************/ /*****************************************************************************/
int xrdp_process_main_loop(struct xrdp_process* self) int xrdp_process_main_loop(struct xrdp_process* self)
{ {
#ifndef XRDP_LIB #ifndef XRDP_LIB
int i; int i;
struct stream* s; struct stream* s;
make_stream(s); make_stream(s);
self->status = 1; self->status = 1;
self->rdp_layer = xrdp_rdp_create(self, self->sck); self->rdp_layer = xrdp_rdp_create(self, self->sck);
g_tcp_set_non_blocking(self->sck); g_tcp_set_non_blocking(self->sck);
if (xrdp_rdp_incoming(self->rdp_layer) == 0) g_tcp_set_no_delay(self->sck);
{ if (xrdp_rdp_incoming(self->rdp_layer) == 0)
while (!g_is_term() && !self->term) {
{ while (!g_is_term() && !self->term)
i = g_tcp_select(self->sck, self->app_sck); {
if (i & 1) i = g_tcp_select(self->sck, self->app_sck);
{ if (i & 1)
init_stream(s, 8192); {
if (xrdp_process_loop(self, s) != 0) init_stream(s, 8192);
{ if (xrdp_process_loop(self, s) != 0)
break; {
} break;
} }
if (i & 2) /* mod socket fired */ }
{ if (i & 2) /* mod socket fired */
if (self->wm->mod == 0) {
{ if (self->wm->mod == 0)
break; {
} break;
if (self->wm->mod->mod_signal == 0) }
{ if (self->wm->mod->mod_signal == 0)
break; {
} break;
if (self->wm->mod->mod_signal(self->wm->mod) != 0) }
{ if (self->wm->mod->mod_signal(self->wm->mod) != 0)
break; {
} break;
} }
if (i == 0) /* no data on any stream */ }
{ if (i == 0) /* no data on any stream */
g_sleep(10); {
} g_sleep(10);
else if (i < 0) }
{ else if (i < 0)
break; {
} break;
} }
} }
if (self->wm->mod != 0) }
{ if (self->wm->mod != 0)
if (self->wm->mod->mod_end != 0) {
{ if (self->wm->mod->mod_end != 0)
self->wm->mod->mod_end(self->wm->mod); {
} self->wm->mod->mod_end(self->wm->mod);
} }
xrdp_rdp_disconnect(self->rdp_layer); }
xrdp_rdp_delete(self->rdp_layer); xrdp_rdp_disconnect(self->rdp_layer);
self->rdp_layer = 0; g_sleep(500);
g_tcp_close(self->sck); xrdp_rdp_delete(self->rdp_layer);
self->status = -1; self->rdp_layer = 0;
xrdp_listen_delete_pro(self->lis_layer, self); g_tcp_close(self->sck);
free_stream(s); self->status = -1;
#endif xrdp_listen_delete_pro(self->lis_layer, self);
return 0; free_stream(s);
} #endif
return 0;
}

View File

@ -777,6 +777,53 @@ int xrdp_rdp_process_data_font(struct xrdp_rdp* self, struct stream* s)
return 0; 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 */ /* RDP_PDU_DATA */
int xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s) 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 */ case RDP_DATA_PDU_SYNCHRONISE: /* 31 */
xrdp_rdp_process_data_sync(self); xrdp_rdp_process_data_sync(self);
break; break;
case 33: /* 33 ?? */ case 33: /* 33 ?? Invalidate an area I think */
xrdp_rdp_process_screen_update(self, s); xrdp_rdp_process_screen_update(self, s);
break; break;
case 35:
/*case 35:*/
/* 35 ?? this comes when minimuzing a full screen mstsc.exe 2600 */ /* 35 ?? this comes when minimuzing a full screen mstsc.exe 2600 */
/* I think this is saying the client no longer wants screen */ /* I think this is saying the client no longer wants screen */
/* updates and it will issue a 33 above to catch up */ /* updates and it will issue a 33 above to catch up */
/* so minumized apps don't take bandwidth */ /* so minimized apps don't take bandwidth */
break;
case 36: /* 36 ?? disconnect? */ case 36: /* 36 ?? disconnect query? */
return 1; /* 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; break;
case RDP_DATA_PDU_FONT2: /* 39 */ case RDP_DATA_PDU_FONT2: /* 39 */
xrdp_rdp_process_data_font(self, s); xrdp_rdp_process_data_font(self, s);