From ae9faad218563b46c0a4a00fc584454dbd566825 Mon Sep 17 00:00:00 2001 From: ilsimo Date: Sat, 17 Mar 2007 16:41:21 +0000 Subject: [PATCH] more work on scp v1 --- sesman/libscp_types.h | 24 ++-- sesman/libscp_v1c.c | 234 ++++++++++++++++++++++++++++-- sesman/libscp_v1c.h | 38 +++-- sesman/libscp_v1s.c | 313 +++++++++++++++++++++++++++++------------ sesman/libscp_v1s.h | 52 +++---- sesman/scp_v1.c | 137 ++++++++++-------- sesman/tools/Makefile | 7 +- sesman/tools/sestest.c | 73 ++++++---- 8 files changed, 643 insertions(+), 235 deletions(-) diff --git a/sesman/libscp_types.h b/sesman/libscp_types.h index 5c835522..4aa16753 100644 --- a/sesman/libscp_types.h +++ b/sesman/libscp_types.h @@ -22,7 +22,7 @@ * @file libscp_types.h * @brief libscp data types definitions * @author Simone Fedele - * + * */ #ifndef LIBSCP_TYPES_H @@ -36,7 +36,7 @@ #include "arch.h" #include "log.h" -//#warning sesman requires its own tcp streaming functions for threading safety +//sesman requires its own tcp streaming functions for threading safety #include "tcp.h" #define SCP_SID uint32_t @@ -58,6 +58,8 @@ #define SCP_COMMAND_SET_MANAGE 0x0001 #define SCP_COMMAND_SET_RSR 0x0002 +#define SCP_SERVER_MAX_LIST_SIZE 100 + #define free_session(s) {g_free((s)->username); g_free((s)->password); g_free((s)->hostname); g_free(s);} struct SCP_CONNECTION @@ -89,13 +91,13 @@ struct SCP_SESSION struct SCP_DISCONNECTED_SESSION { uint32_t SID; - unsigned char type; + uint8_t type; uint16_t height; uint16_t width; - unsigned char bpp; - unsigned char idle_days; - unsigned char idle_hours; - unsigned char idle_minutes; + uint8_t bpp; + uint8_t idle_days; + uint8_t idle_hours; + uint8_t idle_minutes; }; enum SCP_CLIENT_STATES_E @@ -104,12 +106,16 @@ enum SCP_CLIENT_STATES_E SCP_CLIENT_STATE_NETWORK_ERR, SCP_CLIENT_STATE_VERSION_ERR, SCP_CLIENT_STATE_SEQUENCE_ERR, + SCP_CLIENT_STATE_SIZE_ERR, SCP_CLIENT_STATE_INTERNAL_ERR, SCP_CLIENT_STATE_SESSION_LIST, + SCP_CLIENT_STATE_LIST_OK, SCP_CLIENT_STATE_RESEND_CREDENTIALS, SCP_CLIENT_STATE_CONNECTION_DENIED, SCP_CLIENT_STATE_PWD_CHANGE_REQ, - SCP_CLIENT_STATE_RECONNECT + SCP_CLIENT_STATE_RECONNECT_SINGLE, + SCP_CLIENT_STATE_SELECTION_CANCEL, + SCP_CLIENT_STATE_END }; enum SCP_SERVER_STATES_E @@ -121,6 +127,8 @@ enum SCP_SERVER_STATES_E SCP_SERVER_STATE_INTERNAL_ERR, SCP_SERVER_STATE_SESSION_TYPE_ERR, SCP_SERVER_STATE_SIZE_ERR, + SCP_SERVER_STATE_SELECTION_CANCEL, + /*SCP_SERVER_STATE_FORCE_NEW,*/ SCP_SERVER_STATE_START_MANAGE, SCP_SERVER_STATE_END }; diff --git a/sesman/libscp_v1c.c b/sesman/libscp_v1c.c index 736a451a..17bfb0e0 100644 --- a/sesman/libscp_v1c.c +++ b/sesman/libscp_v1c.c @@ -18,19 +18,22 @@ */ /** - * + * * @file libscp_v1c.c * @brief libscp version 1 client api code * @author Simone Fedele - * + * */ #include "libscp_v1c.h" +#include +#include + static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s); /* client API */ -/* 001 */ +/* 001 */ enum SCP_CLIENT_STATES_E scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) { unsigned char sz; @@ -93,11 +96,11 @@ enum SCP_CLIENT_STATES_E scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SE return SCP_CLIENT_STATE_NETWORK_ERR; } - /* wait for response */ + /* wait for response */ return _scp_v1c_check_response(c, s); } -/* 004 */ +/* 004 */ enum SCP_CLIENT_STATES_E scp_v1c_resend_credentials(struct SCP_CONNECTION* c, struct SCP_SESSION* s) { unsigned char sz; @@ -138,11 +141,208 @@ enum SCP_CLIENT_STATES_E scp_v1c_resend_credentials(struct SCP_CONNECTION* c, st /* 021 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change(struct SCP_CONNECTION* c, char* newpass); /* 022 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change_cancel(struct SCP_CONNECTION* c); -/* ... */ enum SCP_CLIENT_STATES_E scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, struct SCP_DISCONNECTED_SESSION** s); -/* 041 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session(struct SCP_CONNECTION* c, SCP_SID sid); -/* 042 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session_cancel(struct SCP_CONNECTION* c); +/* 041 */ +enum SCP_CLIENT_STATES_E +scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, struct SCP_DISCONNECTED_SESSION** s) +{ + uint32_t version=1; + uint32_t size=12; + uint16_t cmd=41; + uint32_t sescnt=0; /* total session number */ + uint32_t sestmp=0; /* additional total session number */ + uint8_t pktcnt=0; /* packet session count */ + uint32_t totalcnt=0; /* session counter */ + uint8_t continued=0; /* continue flag */ + int firstpkt=1; /* "first packet" flag */ + int idx; + struct SCP_DISCONNECTED_SESSION* ds=0; + + init_stream(c->out_s, c->out_s->size); + + /* we request session list */ + out_uint32_be(c->out_s, version); /* version */ + out_uint32_be(c->out_s, size); /* size */ + out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */ + out_uint16_be(c->out_s, cmd); /* cmd */ + + if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + do + { + /* then we wait for server response */ + init_stream(c->in_s, c->in_s->size); + if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint32_be(c->in_s, version); + if (version!=1) + { + return SCP_CLIENT_STATE_VERSION_ERR; + } + + in_uint32_be(c->in_s, size); + if (size<12) + { + return SCP_CLIENT_STATE_SIZE_ERR; + } + + init_stream(c->in_s, c->in_s->size); + if (0!=tcp_force_recv(c->in_sck, c->in_s->data, size-8)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd!=SCP_COMMAND_SET_DEFAULT) + { + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd!=42) + { + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + if (firstpkt) + { + firstpkt = 0; + in_uint32_be(c->in_s, sescnt); + sestmp = sescnt; + + ds = g_malloc(sizeof(struct SCP_DISCONNECTED_SESSION)*sescnt, 0); + if (ds == 0) + { + return SCP_CLIENT_STATE_INTERNAL_ERR; + } + } + else + { + in_uint32_be(c->in_s, sestmp); + } + in_uint8(c->in_s, continued); + in_uint8(c->in_s, pktcnt); + + for (idx=0; idxin_s, (ds[totalcnt]).SID); /* session id */ + in_uint8(c->in_s, (ds[totalcnt]).type); + in_uint16_be(c->in_s, (ds[totalcnt]).height); + in_uint16_be(c->in_s, (ds[totalcnt]).width); + in_uint8(c->in_s, (ds[totalcnt]).bpp); + in_uint8(c->in_s, (ds[totalcnt]).idle_days); + in_uint8(c->in_s, (ds[totalcnt]).idle_hours); + in_uint8(c->in_s, (ds[totalcnt]).idle_minutes); + totalcnt++; + } + } + while (continued); + + printf("fine\n"); + /* return data... */ + (*scount) = sescnt; + (*s) = ds; + + return SCP_CLIENT_STATE_LIST_OK; +} + +/* 043 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s, SCP_SID sid) +{ + uint32_t version = 1; + uint32_t size = 16; + uint16_t cmd = 43; + + init_stream(c->out_s, c->out_s->size); + + /* sending our selection */ + out_uint32_be(c->out_s, version); /* version */ + out_uint32_be(c->out_s, size); /* size */ + out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */ + out_uint16_be(c->out_s, cmd); /* cmd */ + + out_uint32_be(c->out_s, sid); + + if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + /* waiting for response.... */ + init_stream(c->in_s, c->in_s->size); + if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint32_be(c->in_s, version); + if (version!=1) + { + return SCP_CLIENT_STATE_VERSION_ERR; + } + + in_uint32_be(c->in_s, size); + if (size<12) + { + return SCP_CLIENT_STATE_SIZE_ERR; + } -/* 03x */ enum SCP_CLIENT_STATES_E scp_v1c_retrieve_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s, struct SCP_DISCONNECTED_SESSION* ds); + init_stream(c->in_s, c->in_s->size); + /* read the rest of the packet */ + if (0!=tcp_force_recv(c->in_sck, c->in_s->data, size-8)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd != SCP_COMMAND_SET_DEFAULT) + { + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd != 46) + { + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + /* session display */ + in_uint16_be(c->in_s, (s->display)); + /*we don't need to return any data other than the display */ + /*because we already sent that */ + + return SCP_CLIENT_STATE_OK; +} + +/* 044 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session_cancel(struct SCP_CONNECTION* c) +{ + uint32_t version = 1; + uint32_t size = 12; + uint16_t cmd = 44; + + init_stream(c->out_s, c->out_s->size); + + /* sending our selection */ + out_uint32_be(c->out_s, version); /* version */ + out_uint32_be(c->out_s, size); /* size */ + out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */ + out_uint16_be(c->out_s, cmd); /* cmd */ + + if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) + { + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + return SCP_CLIENT_STATE_END; +} static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) { @@ -156,7 +356,7 @@ static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c { return SCP_CLIENT_STATE_NETWORK_ERR; } - + in_uint32_be(c->in_s, version); if (version!=1) { @@ -166,7 +366,7 @@ static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c in_uint32_be(c->in_s, size); init_stream(c->in_s, c->in_s->size); - /* read the rest of the packet */ + /* read the rest of the packet */ if (0!=tcp_force_recv(c->in_sck, c->in_s->data, size-8)) { return SCP_CLIENT_STATE_NETWORK_ERR; @@ -236,10 +436,14 @@ static enum SCP_CLIENT_STATES_E _scp_v1c_check_response(struct SCP_CONNECTION* c return SCP_CLIENT_STATE_OK; } - else if (cmd==32) /* display of a disconnected session */ - { - return SCP_CLIENT_STATE_RECONNECT; - } + //else if (cmd==31) /* there's a disconnected session */ + //{ + // return SCP_CLIENT_STATE_RECONNECT_SINGLE; + //} + //else if (cmd==33) /* display of a disconnected session */ + //{ + // return SCP_CLIENT_STATE_RECONNECT; + //} else if (cmd==40) /* session list */ { return SCP_CLIENT_STATE_SESSION_LIST; diff --git a/sesman/libscp_v1c.h b/sesman/libscp_v1c.h index 66464f45..c8be8445 100644 --- a/sesman/libscp_v1c.h +++ b/sesman/libscp_v1c.h @@ -18,11 +18,11 @@ */ /** - * + * * @file libscp_v1c.h * @brief libscp version 1 client api declarations * @author Simone Fedele - * + * */ #ifndef LIBSCP_V1C_H @@ -31,14 +31,34 @@ #include "libscp_types.h" /* client API */ -/* 001 */ enum SCP_CLIENT_STATES_E scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s); -/* 004 */ enum SCP_CLIENT_STATES_E scp_v1c_resend_credentials(struct SCP_CONNECTION* c, struct SCP_SESSION* s); +/* 001 */ +enum SCP_CLIENT_STATES_E +scp_v1c_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s); -/* 021 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change(struct SCP_CONNECTION* c, char* newpass); -/* 022 */ enum SCP_CLIENT_STATES_E scp_v1c_pwd_change_cancel(struct SCP_CONNECTION* c); +/* 004 */ +enum SCP_CLIENT_STATES_E +scp_v1c_resend_credentials(struct SCP_CONNECTION* c, struct SCP_SESSION* s); -/* ... */ enum SCP_CLIENT_STATES_E scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, struct SCP_DISCONNECTED_SESSION** s); -/* 041 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session(struct SCP_CONNECTION* c, SCP_SID sid); -/* 042 */ enum SCP_CLIENT_STATES_E scp_v1c_select_session_cancel(struct SCP_CONNECTION* c); +/* 021 */ +enum SCP_CLIENT_STATES_E +scp_v1c_pwd_change(struct SCP_CONNECTION* c, char* newpass); + +/* 022 */ +enum SCP_CLIENT_STATES_E +scp_v1c_pwd_change_cancel(struct SCP_CONNECTION* c); + +/* 041 */ +enum SCP_CLIENT_STATES_E +scp_v1c_get_session_list(struct SCP_CONNECTION* c, int* scount, + struct SCP_DISCONNECTED_SESSION** s); + +/* 043 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s, + SCP_SID sid); + +/* 044 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session_cancel(struct SCP_CONNECTION* c); #endif diff --git a/sesman/libscp_v1s.c b/sesman/libscp_v1s.c index 37932198..9a3e2df6 100644 --- a/sesman/libscp_v1s.c +++ b/sesman/libscp_v1s.c @@ -18,11 +18,11 @@ */ /** - * + * * @file libscp_v1s.c * @brief libscp version 1 server api code * @author Simone Fedele - * + * */ #ifndef LIBSCP_V1S_C @@ -39,7 +39,7 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES uint16_t cmdset; uint16_t cmd; unsigned char sz; - + if (!skipVchk) { @@ -60,14 +60,13 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES { version=1; } - + in_uint32_be(c->in_s, size); - LOG_DBG("size: %d",size); - if (size<12) + if (size<12) { return SCP_SERVER_STATE_SIZE_ERR; } - + init_stream(c->in_s, c->in_s->size); if (0!=tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) { @@ -76,14 +75,13 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES /* reading command set */ in_uint16_be(c->in_s, cmdset); - LOG_DBG("command set: %d",cmdset); - + /* if we are starting a management session */ if (cmdset==SCP_COMMAND_SET_MANAGE) { return SCP_SERVER_STATE_START_MANAGE; } - + /* if we started with resource sharing... */ if (cmdset==SCP_COMMAND_SET_RSR) { @@ -92,7 +90,6 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES /* reading command */ in_uint16_be(c->in_s, cmd); - LOG_DBG("command: %d",cmd); if (cmd != 1) { return SCP_SERVER_STATE_SEQUENCE_ERR; @@ -117,10 +114,8 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES in_uint8(c->in_s, session->bpp); in_uint8(c->in_s, session->rsr); in_uint8a(c->in_s, session->locale, 17); - session->locale[17]='\0'; + session->locale[17]='\0'; - LOG_DBG("locale: %s\n", session->locale); - in_uint8(c->in_s, session->addr_type); if (session->addr_type==SCP_ADDRESS_TYPE_IPV4) { @@ -131,11 +126,8 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES #warning how to handle ipv6 addresses? } - LOG_DBG("rest: %d\n",(unsigned char)*((c->in_s->p)+2)); - - /* reading hostname */ + /* reading hostname */ in_uint8(c->in_s, sz); - LOG_DBG("size read: %d", sz); session->hostname=g_malloc(sz+1,1); if (0==session->hostname) { @@ -156,43 +148,40 @@ enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SES } session->username[sz]='\0'; in_uint8a(c->in_s, session->username, sz); - + /* reading password */ in_uint8(c->in_s, sz); - LOG_DBG("size read: %d", sz); session->password=g_malloc(sz+1,1); - if (0==session->password) + if (0==session->password) { g_free(session->username); g_free(session->hostname); - g_free(session); + g_free(session); return SCP_SERVER_STATE_INTERNAL_ERR; } session->password[sz]='\0'; in_uint8a(c->in_s, session->password, sz); - LOG_DBG("password: %s - size: %d - pointer: %x", session->password, sz, session->password); - /* returning the struct */ (*s)=session; - + return SCP_SERVER_STATE_OK; } -enum SCP_SERVER_STATES_E +enum SCP_SERVER_STATES_E scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason) { int rlen; - + init_stream(c->out_s,c->out_s->size); - + /* forcing message not to exceed 64k */ rlen = g_strlen(reason); if (rlen > 65535) { rlen = 65535; } - + out_uint32_be(c->out_s, 1); /* packet size: 4 + 4 + 2 + 2 + 2 + strlen(reason)*/ /* version + size + cmdset + cmd + msglen + msg */ @@ -210,7 +199,7 @@ scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason) return SCP_SERVER_STATE_END; } -enum SCP_SERVER_STATES_E +enum SCP_SERVER_STATES_E scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* reason) { unsigned char sz; @@ -231,7 +220,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* { rlen = 65535; } - + /* send password request */ version=1; size=12; @@ -250,24 +239,22 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* { return SCP_SERVER_STATE_NETWORK_ERR; } - + /* receive password & username */ if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8)) { return SCP_SERVER_STATE_NETWORK_ERR; } - + in_uint32_be(c->in_s, version); - if (version!=1) + if (version!=1) { - LOG_DBG("version: %d",version); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); - if (size<12) + if (size<12) { - LOG_DBG("size: %d",size); return SCP_SERVER_STATE_SIZE_ERR; } @@ -277,9 +264,17 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* return SCP_SERVER_STATE_NETWORK_ERR; } -#warning check cmd seq in_uint16_be(c->in_s, cmdset); + if (cmdset != SCP_COMMAND_SET_DEFAULT) + { + return SCP_SERVER_STATE_SEQUENCE_ERR; + } + in_uint16_be(c->in_s, cmd); + if (cmd != 4) + { + return SCP_SERVER_STATE_SEQUENCE_ERR; + } /* reading username */ in_uint8(c->in_s, sz); @@ -290,7 +285,7 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* } ubuf[sz]='\0'; in_uint8a(c->in_s, ubuf, sz); - + /* reading password */ in_uint8(c->in_s, sz); pbuf=g_malloc(sz+1,1); @@ -311,22 +306,22 @@ scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* return SCP_SERVER_STATE_OK; } -/* 020 */ -enum SCP_SERVER_STATES_E +/* 020 */ +enum SCP_SERVER_STATES_E scp_v1s_request_pwd_change(struct SCP_CONNECTION* c, char* reason, char* npw) { return SCP_SERVER_STATE_INTERNAL_ERR; } -/* 023 */ -enum SCP_SERVER_STATES_E +/* 023 */ +enum SCP_SERVER_STATES_E scp_v1s_pwd_change_error(struct SCP_CONNECTION* c, char* error, int retry, char* npw) { return SCP_SERVER_STATE_INTERNAL_ERR; } -/* 030 */ -enum SCP_SERVER_STATES_E +/* 030 */ +enum SCP_SERVER_STATES_E scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) { /* send password request */ @@ -346,22 +341,33 @@ scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d) if (0!=tcp_force_send(c->in_sck, c->out_s->data, 14)) { return SCP_SERVER_STATE_NETWORK_ERR; - } - + } + return SCP_SERVER_STATE_OK; } -/* 031 */ -enum SCP_SERVER_STATES_E -scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESSION* ds, - SCP_DISPLAY d) +/* 032 */ +enum SCP_SERVER_STATES_E +scp_v1s_connection_error(struct SCP_CONNECTION* c, char* error) +{ + return SCP_SERVER_STATE_INTERNAL_ERR; + return SCP_SERVER_STATE_END; +} + +/* 040 */ +enum SCP_SERVER_STATES_E +scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid) { uint32_t version=1; uint32_t size=12; - uint16_t cmd=32; -#warning FIXME check this command code - - /* first we send a notice that we're reconnecting to an existing session */ + uint16_t cmd=40; + int pktcnt; + int idx; + int sidx; + int pidx; + struct SCP_DISCONNECTED_SESSION* cds; + + /* first we send a notice that we have some disconnected sessions */ init_stream(c->out_s, c->out_s->size); out_uint32_be(c->out_s, version); /* version */ @@ -369,27 +375,28 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESS out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */ out_uint16_be(c->out_s, cmd); /* cmd */ - if (0!=tcp_force_send(c->in_sck, c->out_s->data, 14)) + if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) { return SCP_SERVER_STATE_NETWORK_ERR; - } + } /* then we wait for client ack */ -#warning maybe this message could say if the session should be resized on +#warning maybe this message could say if the session should be resized on #warning server side or client side + init_stream(c->in_s, c->in_s->size); if (0!=tcp_force_recv(c->in_sck, c->in_s->data, 8)) { return SCP_SERVER_STATE_NETWORK_ERR; } - + in_uint32_be(c->in_s, version); - if (version!=1) + if (version!=1) { return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); - if (size<12) + if (size<12) { return SCP_SERVER_STATE_SIZE_ERR; } @@ -407,58 +414,186 @@ scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESS } in_uint16_be(c->in_s, cmd); -#warning FIXME check this command code - if (cmd != 33) + if (cmd != 41) { return SCP_SERVER_STATE_SEQUENCE_ERR; } + /* calculating the number of packets to send */ + pktcnt=sescnt/SCP_SERVER_MAX_LIST_SIZE; + if ((sescnt%SCP_SERVER_MAX_LIST_SIZE)!=0) + { + pktcnt++; + } + + for (idx=0; idxout_s, c->out_s->size); + + /* size: ver+size+cmdset+cmd+sescnt+continue+count */ + size=4+4+2+2+4+1+1; + + /* header */ + cmd=42; + s_push_layer(c->out_s, channel_hdr, 8); + out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); + out_uint16_be(c->out_s, cmd); + + /* session count */ + out_uint32_be(c->out_s, sescnt); + + /* setting the continue flag */ + if ((idx+1)*SCP_SERVER_MAX_LIST_SIZE >= sescnt) + { + out_uint8(c->out_s, 0); + /* setting session count for this packet */ + pidx=sescnt-(idx*SCP_SERVER_MAX_LIST_SIZE); + out_uint8(c->out_s, pidx); + } + else + { + out_uint8(c->out_s, 1); + /* setting session count for this packet */ + pidx=SCP_SERVER_MAX_LIST_SIZE; + out_uint8(c->out_s, pidx); + } + + /* adding session descriptors */ + for (sidx=0; sidxout_s, cds->SID); /* session id */ + out_uint8(c->out_s, cds->type); + out_uint16_be(c->out_s, cds->height); + out_uint16_be(c->out_s, cds->width); + out_uint8(c->out_s, cds->bpp); + out_uint8(c->out_s, cds->idle_days); + out_uint8(c->out_s, cds->idle_hours); + out_uint8(c->out_s, cds->idle_minutes); + + size = size + 13; + } + + s_pop_layer(c->out_s, channel_hdr); + out_uint32_be(c->out_s, version); + out_uint32_be(c->out_s, size); + + if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) + { + return SCP_SERVER_STATE_NETWORK_ERR; + } + } + + /* we get the response */ + init_stream(c->in_s, c->in_s->size); + if (0!=tcp_force_recv(c->in_sck, c->in_s->data, (8))) + { + return SCP_SERVER_STATE_NETWORK_ERR; + } + + in_uint32_be(c->in_s, version); + if (version!=1) + { + return SCP_SERVER_STATE_VERSION_ERR; + } + + in_uint32_be(c->in_s, size); + if (size<12) + { + return SCP_SERVER_STATE_SIZE_ERR; + } + + /* rest of the packet */ + init_stream(c->in_s, c->in_s->size); + if (0!=tcp_force_recv(c->in_sck, c->in_s->data, (size-8))) + { + return SCP_SERVER_STATE_NETWORK_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd != SCP_COMMAND_SET_DEFAULT) + { + return SCP_SERVER_STATE_SEQUENCE_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd == 43) + { + /* select session */ + in_uint32_be(c->in_s, (*sid)); + + /* checking sid value */ + for (idx=0; idxout_s, c->out_s->size); - /* size */ - size=4+4+2+2+ \ - 2+1+2+2+1+1+1+1; - /* header */ - cmd=31; out_uint32_be(c->out_s, version); out_uint32_be(c->out_s, size); out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); out_uint16_be(c->out_s, cmd); - + /* session data */ out_uint16_be(c->out_s, d); /* session display */ - out_uint8(c->out_s, ds->type); + /*out_uint8(c->out_s, ds->type); out_uint16_be(c->out_s, ds->height); out_uint16_be(c->out_s, ds->width); out_uint8(c->out_s, ds->bpp); out_uint8(c->out_s, ds->idle_days); out_uint8(c->out_s, ds->idle_hours); - out_uint8(c->out_s, ds->idle_minutes); + out_uint8(c->out_s, ds->idle_minutes);*/ /* these last three are not really needed... */ - + if (0!=tcp_force_send(c->in_sck, c->out_s->data, size)) { return SCP_SERVER_STATE_NETWORK_ERR; - } - - return SCP_SERVER_STATE_OK; -} - -/* 032 */ -enum SCP_SERVER_STATES_E -scp_v1s_connection_error(struct SCP_CONNECTION* c, char* error) -{ - return SCP_SERVER_STATE_INTERNAL_ERR; - return SCP_SERVER_STATE_END; -} + } -/* 040 */ -enum SCP_SERVER_STATES_E -scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid) -{ - return SCP_SERVER_STATE_INTERNAL_ERR; + return SCP_SERVER_STATE_OK; } #endif diff --git a/sesman/libscp_v1s.h b/sesman/libscp_v1s.h index 34650920..6ea12fd8 100644 --- a/sesman/libscp_v1s.h +++ b/sesman/libscp_v1s.h @@ -18,11 +18,11 @@ */ /** - * + * * @file libscp_v1s.h * @brief libscp version 1 server api declarations * @author Simone Fedele - * + * */ #ifndef LIBSCP_V1S_H @@ -36,52 +36,52 @@ * @brief processes the stream using scp version 1 * @param c connection descriptor * @param s pointer to session descriptor pointer - * @param skipVchk if set to !0 skips the version control (to be used after + * @param skipVchk if set to !0 skips the version control (to be used after * scp_vXs_accept() ) * * this function places in *s the address of a newely allocated SCP_SESSION structure * that should be free()d */ -enum SCP_SERVER_STATES_E -scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk); +enum SCP_SERVER_STATES_E +scp_v1s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk); /** * * @brief denies connection to sesman * @param c connection descriptor * @param reason pointer to a string containinge the reason for denying connection + * */ -/* 002 */ -enum SCP_SERVER_STATES_E +/* 002 */ +enum SCP_SERVER_STATES_E scp_v1s_deny_connection(struct SCP_CONNECTION* c, char* reason); -enum SCP_SERVER_STATES_E +enum SCP_SERVER_STATES_E scp_v1s_request_password(struct SCP_CONNECTION* c, struct SCP_SESSION* s, char* reason); - -/* 020 */ -enum SCP_SERVER_STATES_E + +/* 020 */ +enum SCP_SERVER_STATES_E scp_v1s_request_pwd_change(struct SCP_CONNECTION* c, char* reason, char* npw); -/* 023 */ -enum SCP_SERVER_STATES_E +/* 023 */ +enum SCP_SERVER_STATES_E scp_v1s_pwd_change_error(struct SCP_CONNECTION* c, char* error, int retry, char* npw); -/* 030 */ -enum SCP_SERVER_STATES_E +/* 030 */ +enum SCP_SERVER_STATES_E scp_v1s_connect_new_session(struct SCP_CONNECTION* c, SCP_DISPLAY d); -/* 031 */ -enum SCP_SERVER_STATES_E -scp_v1s_reconnect_session(struct SCP_CONNECTION* c, struct SCP_DISCONNECTED_SESSION* ds, - SCP_DISPLAY d); - -/* 032 */ -enum SCP_SERVER_STATES_E +/* 032 */ +enum SCP_SERVER_STATES_E scp_v1s_connection_error(struct SCP_CONNECTION* c, char* error); -/* 040 */ -enum SCP_SERVER_STATES_E -scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, - SCP_SID* sid); +/* 040 */ +enum SCP_SERVER_STATES_E +scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, + struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid); + +/* 046 was: 031 struct SCP_DISCONNECTED_SESSION* ds, */ +enum SCP_SERVER_STATES_E +scp_v1s_reconnect_session(struct SCP_CONNECTION* c, SCP_DISPLAY d); #endif diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c index d2018da5..ed6dcde4 100644 --- a/sesman/scp_v1.c +++ b/sesman/scp_v1.c @@ -22,7 +22,7 @@ * @file scp_v1.c * @brief scp version 1 implementation * @author Jay Sorg, Simone Fedele - * + * */ #include "sesman.h" @@ -32,6 +32,8 @@ extern struct config_sesman g_cfg; +static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f); + /******************************************************************************/ void DEFAULT_CC scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) @@ -50,50 +52,31 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) current_try = retries; data = auth_userpass(s->username, s->password); - LOG_DBG("user: %s\npass: %s", s->username, s->password); + /*LOG_DBG("user: %s\npass: %s", s->username, s->password);*/ while ((!data) && ((retries == 0) || (current_try > 0))) { - LOG_DBG("data %d - retry %d - currenttry %d - expr %d", data, retries, - current_try, ((!data) && ((retries == 0) || (current_try > 0)))); + LOG_DBG("data %d - retry %d - currenttry %d - expr %d", data, retries, current_try, ((!data) && ((retries==0) || (current_try>0)))); - e = scp_v1s_request_password(c, s, "Wrong username and/or password"); + e=scp_v1s_request_password(c,s,"Wrong username and/or password"); switch (e) { case SCP_SERVER_STATE_OK: /* all ok, we got new username and password */ data = auth_userpass(s->username, s->password); - /* one try less */ + /* one try less */ if (current_try > 0) { current_try--; } break; - case SCP_SERVER_STATE_VERSION_ERR: - LOG_DBG("version error", 0) - case SCP_SERVER_STATE_SIZE_ERR: - /* an unknown scp version was requested, so we shut down the */ - /* connection (and log the fact) */ - log_message(LOG_LEVEL_WARNING, - "protocol violation. connection closed."); - return; - case SCP_SERVER_STATE_NETWORK_ERR: - log_message(LOG_LEVEL_WARNING, "libscp network error."); - return; - case SCP_SERVER_STATE_SEQUENCE_ERR: - log_message(LOG_LEVEL_WARNING, "libscp sequence error."); - return; - case SCP_SERVER_STATE_INTERNAL_ERR: - /* internal error occurred (eg. malloc() error, ecc.) */ - log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); - return; default: - /* dummy: scp_v1s_request_password won't generate any other */ - /* error other than the ones before */ - log_message(LOG_LEVEL_ALWAYS, - "unknown return from scp_v1s_request_password()"); + /* we check the other errors */ + parseCommonStates(e, "scp_v1s_list_sessions()"); + free_session(s); return; + //break; } } @@ -106,7 +89,7 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) return; } - /* testing if login is allowed*/ + /* testing if login is allowed*/ if (0 == access_login_allowed(s->username)) { scp_v1s_deny_connection(c, "Access to Terminal Server not allowed."); @@ -123,7 +106,6 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) if (scount == 0) { -#warning FIXME we should check for MaxSessions /* no disconnected sessions - start a new one */ log_message(LOG_LEVEL_INFO, "granted TS access to user %s", s->username); if (SCP_SESSION_TYPE_XVNC == s->type) @@ -145,42 +127,48 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) case SCP_SERVER_STATE_OK: /* all ok, we got new username and password */ break; - case SCP_SERVER_STATE_NETWORK_ERR: - log_message(LOG_LEVEL_WARNING, "libscp network error."); - return; default: - return; + /* we check the other errors */ + parseCommonStates(e, "scp_v1s_connect_new_session()"); + break; } } - else if (scount == 1) + else { - /* there's only one session - returning that */ - sitem = session_get_bypid(slist->SID); #warning FIXME session_get_by*() should return a malloc()ated struct #warning FIXME or at least lock the chain - if (0 == sitem) - { - e = scp_v1s_connection_error(c, "Internal error"); - log_message(LOG_LEVEL_INFO, "Cannot find session item on the chain"); - } - else - { - display = sitem->display; - e = scp_v1s_reconnect_session(c, slist, display); - log_message(LOG_LEVEL_INFO, - "User %s reconnected to session %d on port %d", - s->username, sitem->pid, display); - } - g_free(slist); - } - else - { - /* 2 or more disconnected sessions - listing */ - //max session x packet = 100 => pkt size = 1300 (13x100) + /* one or more disconnected sessions - listing */ e = scp_v1s_list_sessions(c, scount, slist, &sid); - //CHECK RETURN - + switch (e) + { + /*case SCP_SERVER_STATE_FORCE_NEW:*/ + /* we should check for MaxSessions */ + case SCP_SERVER_STATE_SELECTION_CANCEL: + log_message(LOG_LEVEL_INFO, "Connection cancelled after session listing"); + break; + case SCP_SERVER_STATE_OK: + /* ok, reconnecting... */ + sitem=session_get_bypid(sid); + if (0==sitem) + { + e=scp_v1s_connection_error(c, "Internal error"); + log_message(LOG_LEVEL_INFO, "Cannot find session item on the chain"); + } + else + { + display=sitem->display; + /*e=scp_v1s_reconnect_session(c, sitem, display);*/ + e=scp_v1s_reconnect_session(c, display); + log_message(LOG_LEVEL_INFO, "User %s reconnected to session %d on port %d", \ + s->username, sitem->pid, display); + } + break; + default: + /* we check the other errors */ + parseCommonStates(e, "scp_v1s_list_sessions()"); + break; + } g_free(slist); } @@ -190,8 +178,37 @@ scp_v1_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s) /* here goes scp resource sharing code */ } - /* cleanup */ + /* cleanup */ free_session(s); - auth_end(data); + auth_end(data); } +static void parseCommonStates(enum SCP_SERVER_STATES_E e, char* f) +{ + switch (e) + { + case SCP_SERVER_STATE_VERSION_ERR: + LOG_DBG("version error", 0) + case SCP_SERVER_STATE_SIZE_ERR: + /* an unknown scp version was requested, so we shut down the */ + /* connection (and log the fact) */ + log_message(LOG_LEVEL_WARNING, + "protocol violation. connection closed."); + break; + case SCP_SERVER_STATE_NETWORK_ERR: + log_message(LOG_LEVEL_WARNING, "libscp network error."); + break; + case SCP_SERVER_STATE_SEQUENCE_ERR: + log_message(LOG_LEVEL_WARNING, "libscp sequence error."); + break; + case SCP_SERVER_STATE_INTERNAL_ERR: + /* internal error occurred (eg. malloc() error, ecc.) */ + log_message(LOG_LEVEL_ERROR, "libscp internal error occurred."); + break; + default: + /* dummy: scp_v1s_request_password won't generate any other */ + /* error other than the ones before */ + log_message(LOG_LEVEL_ALWAYS, "unknown return from %s", f); + break; + } +} diff --git a/sesman/tools/Makefile b/sesman/tools/Makefile index b4902ad5..51eda709 100644 --- a/sesman/tools/Makefile +++ b/sesman/tools/Makefile @@ -6,8 +6,9 @@ SESTESTOBJ = sestest.o tcp.o \ DEFINES = -DLIBSCP_CLIENT CFLAGS = -Wall -O2 -I../../common -I../ -I/usr/include/nptl $(DEFINES) -LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES) -C_OS_FLAGS = $(CFLAGS) -c +#LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES) +LDFLAGS = -L /usr/gnu/lib -ldl $(DEFINES) +C_OS_FLAGS = $(CFLAGS) -c -g CC = gcc all: sestest @@ -37,4 +38,4 @@ clean: rm $(SESTESTOBJ) sestest install: - #install:wq + #install diff --git a/sesman/tools/sestest.c b/sesman/tools/sestest.c index 62629f3a..ae23f616 100644 --- a/sesman/tools/sestest.c +++ b/sesman/tools/sestest.c @@ -14,9 +14,14 @@ int main(int argc, char** argv) { struct SCP_SESSION s; struct SCP_CONNECTION c; + /*struct SCP_DISCONNECTED_SESSION ds;*/ + struct SCP_DISCONNECTED_SESSION* dsl; enum SCP_CLIENT_STATES_E e; int end; - + int scnt; + int idx; + int sel; + make_stream(c.in_s); init_stream(c.in_s, 8192); make_stream(c.out_s); @@ -28,7 +33,7 @@ int main(int argc, char** argv) g_printf("error connecting"); return 1; } - + g_printf("001 - send connect request\n"); /*struct SCP_SESSION @@ -36,7 +41,7 @@ int main(int argc, char** argv) uint16_t display; char* errstr; };*/ - + s.type=SCP_SESSION_TYPE_XVNC; s.version=1; s.height=600; @@ -44,18 +49,18 @@ int main(int argc, char** argv) s.bpp=8; s.rsr=0; g_strncpy(s.locale,"it_IT 0123456789",18); - + s.username=g_malloc(256, 1); g_strncpy(s.username,"prog",255); - + s.password=g_malloc(256,1); g_strncpy(s.password, "prog", 255); g_printf("%s - %s\n", s.username, s.password); - - + + s.hostname=g_malloc(256,1); g_strncpy(s.hostname, "odin", 255); - + s.addr_type=SCP_ADDRESS_TYPE_IPV4; s.ipv4addr=0; s.errstr=0; @@ -68,34 +73,52 @@ int main(int argc, char** argv) switch (e) { case SCP_CLIENT_STATE_OK: - g_printf("OK : display is %d\n", (int)s.display); - end=1; + g_printf("OK : display is %d\n", (short int)s.display); + end=1; break; case SCP_CLIENT_STATE_SESSION_LIST: g_printf("OK : session list needed\n"); + e=scp_v1c_get_session_list(&c, &scnt, &dsl); + printf("Sessions: %d\n", scnt); + for (idx=0; idx username); g_printf("password:"); scanf("%255s", s->password); g_printf("hostname:"); scanf("%255s", s->hostname); - + g_printf("session type:\n"); g_printf("0: Xvnc\n", SCP_SESSION_TYPE_XVNC); g_printf("1: x11rdp\n", SCP_SESSION_TYPE_XRDP); @@ -125,7 +148,7 @@ int inputSession(struct SCP_SESSION* s) { s->type=SCP_SESSION_TYPE_XVNC; } - + s->version=1; s->height=600; s->width=800; @@ -134,7 +157,7 @@ int inputSession(struct SCP_SESSION* s) /* fixed for now */ s->rsr=0; g_strncpy(s->locale,"it_IT 0123456789",18); - + return 0; } @@ -142,9 +165,9 @@ unsigned int menuSelect(unsigned int choices) { unsigned int sel; int ret; - + ret=scanf("%u", &sel); - + while ((ret==0) || (sel > choices)) { g_printf("invalid choice.");