diff --git a/sesman/libscp/libscp_v1c_mng.c b/sesman/libscp/libscp_v1c_mng.c new file mode 100644 index 00000000..e18a3004 --- /dev/null +++ b/sesman/libscp/libscp_v1c_mng.c @@ -0,0 +1,400 @@ +/* + 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-2008 +*/ + +/** + * + * @file libscp_v1c_mng.c + * @brief libscp version 1 client api code - session management + * @author Simone Fedele + * + */ + +#include "libscp_v1c_mng.h" + +#include +#include + +extern struct log_config* s_log; + +static enum SCP_CLIENT_STATES_E +_scp_v1c_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s); + +/* client API */ +/* 001 */ +enum SCP_CLIENT_STATES_E +scp_v1c_mng_connect(struct SCP_CONNECTION* c, struct SCP_SESSION* s) +{ + tui8 sz; + tui32 size; + + init_stream(c->out_s, c->out_s->size); + init_stream(c->in_s, c->in_s->size); + + size = 12 + 4 + g_strlen(s->hostname) + g_strlen(s->username) + + g_strlen(s->password); + if (s->addr_type == SCP_ADDRESS_TYPE_IPV4) + { + size = size + 4; + } + else + { + size = size + 16; + } + + /* sending request */ + + /* header */ + out_uint32_be(c->out_s, 1); /* version */ + out_uint32_be(c->out_s, size); + out_uint16_be(c->out_s, SCP_COMMAND_SET_MANAGE); + out_uint16_be(c->out_s, SCP_CMD_MNG_LOGIN); + + /* data */ + sz = g_strlen(s->username); + out_uint8(c->out_s, sz); + out_uint8p(c->out_s, s->username, sz); + sz = g_strlen(s->password); + out_uint8(c->out_s, sz); + out_uint8p(c->out_s, s->password, sz); + + /* address */ + out_uint8(c->out_s, s->addr_type); + if (s->addr_type == SCP_ADDRESS_TYPE_IPV4) + { + out_uint32_be(c->out_s, s->ipv4addr); + } + else + { + out_uint8p(c->out_s, s->ipv6addr, 16); + } + + /* hostname */ + sz = g_strlen(s->hostname); + out_uint8(c->out_s, sz); + out_uint8p(c->out_s, s->hostname, sz); + + if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + /* wait for response */ + return _scp_v1c_mng_check_response(c, s); +} + +/* 004 */ +enum SCP_CLIENT_STATES_E +scp_v1c_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, + struct SCP_DISCONNECTED_SESSION** s) +{ + tui32 version = 1; + tui32 size = 12; + tui16 cmd = SCP_CMD_MNG_LIST_REQ; /* request session list */ + tui32 sescnt = 0; /* total session number */ + tui32 sestmp = 0; /* additional total session number */ + tui8 pktcnt = 0; /* packet session count */ + tui32 totalcnt = 0; /* session counter */ + tui8 continued = 0; /* continue flag */ + int firstpkt = 1; /* "first packet" flag */ + int idx; + struct SCP_DISCONNECTED_SESSION* ds = 0; +// tui8 addr[16]; + + 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_MANAGE); /* cmdset */ + out_uint16_be(c->out_s, cmd); /* cmd */ + + if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + do + { + /* then we wait for server response */ + init_stream(c->in_s, c->in_s->size); + if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint32_be(c->in_s, version); + if (version != 1) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); + return SCP_CLIENT_STATE_VERSION_ERR; + } + + in_uint32_be(c->in_s, size); + if (size < 12) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: size error", __LINE__); + return SCP_CLIENT_STATE_SIZE_ERR; + } + + init_stream(c->in_s, c->in_s->size); + if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd != SCP_COMMAND_SET_MANAGE) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd != SCP_CMD_MNG_LIST) /* session list */ + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + if (firstpkt) + { + firstpkt = 0; + in_uint32_be(c->in_s, sescnt); + sestmp = sescnt; + + if (0 == sescnt) + { + /* return data... */ + (*scount) = sescnt; + (*s) = NULL; + + LOG_DBG(s_log, "[v1c_mng] end list - no session on TS"); + return SCP_CLIENT_STATE_LIST_OK; + } + + ds = g_malloc(sizeof(struct SCP_DISCONNECTED_SESSION) * sescnt, 0); + if (ds == 0) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: internal error", __LINE__); + 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; idx < pktcnt; idx++) + { + in_uint32_be(c->in_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); + + in_uint16_be(c->in_s, (ds[totalcnt]).conn_year); + in_uint8(c->in_s, (ds[totalcnt]).conn_month); + in_uint8(c->in_s, (ds[totalcnt]).conn_day); + in_uint8(c->in_s, (ds[totalcnt]).conn_hour); + in_uint8(c->in_s, (ds[totalcnt]).conn_minute); + in_uint8(c->in_s, (ds[totalcnt]).addr_type); + if ((ds[totalcnt]).addr_type == SCP_ADDRESS_TYPE_IPV4) + { + in_uint32_be(c->in_s, (ds[totalcnt]).ipv4addr); + } + if ((ds[totalcnt]).addr_type == SCP_ADDRESS_TYPE_IPV6) + { + in_uint8a(c->in_s, (ds[totalcnt]).ipv6addr, 16); + } + totalcnt++; + } + } + while (continued); + + /* return data... */ + (*scount) = sescnt; + (*s) = ds; + + LOG_DBG(s_log, "[v1c_mng] end list"); + 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) +{ + tui32 version = 1; + tui32 size = 16; + tui16 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 != scp_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 != scp_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); + / * read the rest of the packet * / + if (0 != scp_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) +{ + tui32 version = 1; + tui32 size = 12; + tui16 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 != scp_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_mng_check_response(struct SCP_CONNECTION* c, struct SCP_SESSION* s) +{ + tui32 version; + tui32 size; + tui16 cmd; + tui8 dim; + char buf[257]; + + init_stream(c->in_s, c->in_s->size); + if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint32_be(c->in_s, version); + if (version != 1) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__); + return SCP_CLIENT_STATE_VERSION_ERR; + } + + in_uint32_be(c->in_s, size); + + init_stream(c->in_s, c->in_s->size); + /* read the rest of the packet */ + if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8)) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__); + return SCP_CLIENT_STATE_NETWORK_ERR; + } + + in_uint16_be(c->in_s, cmd); + if (cmd != SCP_COMMAND_SET_MANAGE) + { + log_message(s_log, LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__); + return SCP_CLIENT_STATE_SEQUENCE_ERR; + } + + in_uint16_be(c->in_s, cmd) + if (cmd == SCP_CMD_MNG_LOGIN_ALLOW) /* connection ok */ + { + log_message(s_log, LOG_LEVEL_INFO, "[v1c_mng:%d] connection ok", __LINE__); + return SCP_CLIENT_STATE_OK; + } + else if (cmd == SCP_CMD_MNG_LOGIN_DENY) /* connection denied */ + { + in_uint8(c->in_s, dim); + buf[dim]='\0'; + in_uint8a(c->in_s, buf, dim); + scp_session_set_errstr(s, buf); + + log_message(s_log, LOG_LEVEL_INFO, "[v1c_mng:%d] connection denied: %s", __LINE__ , s->errstr); + return SCP_CLIENT_STATE_CONNECTION_DENIED; + } + + log_message(s_log, LOG_LEVEL_WARNING, "[v1c-mng:%d] connection aborted: sequence error", __LINE__); + return SCP_CLIENT_STATE_SEQUENCE_ERR; +} diff --git a/sesman/libscp/libscp_v1c_mng.h b/sesman/libscp/libscp_v1c_mng.h new file mode 100644 index 00000000..e72e6c64 --- /dev/null +++ b/sesman/libscp/libscp_v1c_mng.h @@ -0,0 +1,60 @@ +/* + 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-2008 +*/ + +/** + * + * @file libscp_v1c_mng.h + * @brief libscp version 1 client api declarations - session management + * @author Simone Fedele + * + */ + +#ifndef LIBSCP_V1C_MNG_H +#define LIBSCP_V1C_MNG_H + +#include "libscp.h" + +/* client API */ +/* 001 */ +enum SCP_CLIENT_STATES_E +scp_v1c_mng_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); + +/ * 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_mng_get_session_list(struct SCP_CONNECTION* c, int* scount, + struct SCP_DISCONNECTED_SESSION** s); + +/* 044 */ +enum SCP_CLIENT_STATES_E +scp_v1c_select_session_cancel(struct SCP_CONNECTION* c); + +#endif