/* return error */ static int APP_CC send_paint_rect_ack(struct mod *mod, int flags, int x, int y, int cx, int cy, int frame_id) { int len; struct stream *s; make_stream(s); init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 105); out_uint32_le(s, flags); out_uint32_le(s, frame_id); out_uint32_le(s, x); out_uint32_le(s, y); out_uint32_le(s, cx); out_uint32_le(s, cy); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); free_stream(s); return 0; }
/* returns error */ int APP_CC xrdp_iso_init(struct xrdp_iso* self, struct stream* s) { xrdp_tcp_init(self->tcp_layer, s); s_push_layer(s, iso_hdr, 7); return 0; }
/* return error */ int DEFAULT_CC lib_mod_event(struct mod* mod, int msg, tbus param1, tbus param2, tbus param3, tbus param4) { struct stream* s; int len; int rv; LIB_DEBUG(mod, "in lib_mod_event"); make_stream(s); init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, msg); out_uint32_le(s, param1); out_uint32_le(s, param2); out_uint32_le(s, param3); out_uint32_le(s, param4); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); rv = lib_send(mod, s->data, len); free_stream(s); LIB_DEBUG(mod, "out lib_mod_event"); return rv; }
/* Initialize fast path data packet */ STREAM iso_fp_init(rdpIso * iso, int length) { STREAM s; s = tcp_init(iso->tcp, length + 3); s_push_layer(s, iso_hdr, 3); return s; }
/* Initialise an RDP data packet */ static STREAM rdp_init_data(int maxlen) { STREAM s; s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18); s_push_layer(s, rdp_hdr, 18); return s; }
STREAM channel_init(VCHANNEL * channel, uint32 length) { STREAM s; s = sec_init(g_encryption ? SEC_ENCRYPT : 0, length + 8); s_push_layer(s, channel_hdr, 8); return s; }
/* returns error send a list of channels to the channel handler */ static int APP_CC xrdp_mm_trans_send_channel_setup(struct xrdp_mm* self, struct trans* trans) { int index = 0; int chan_id = 0; int chan_flags = 0; int size = 0; struct stream* s = (struct stream *)NULL; char chan_name[256]; g_memset(chan_name,0,sizeof(char) * 256); s = trans_get_out_s(trans, 8192); if (s == 0) { return 1; } s_push_layer(s, iso_hdr, 8); s_push_layer(s, mcs_hdr, 8); s_push_layer(s, sec_hdr, 2); index = 0; while (libxrdp_query_channel(self->wm->session, index, chan_name, &chan_flags) == 0) { chan_id = libxrdp_get_channel_id(self->wm->session, chan_name); out_uint8a(s, chan_name, 8); out_uint16_le(s, chan_id); out_uint16_le(s, chan_flags); index++; } s_mark_end(s); s_pop_layer(s, sec_hdr); out_uint16_le(s, index); s_pop_layer(s, mcs_hdr); size = (int)(s->end - s->p); out_uint32_le(s, 3); /* msg id */ out_uint32_le(s, size); /* msg size */ s_pop_layer(s, iso_hdr); size = (int)(s->end - s->p); out_uint32_le(s, 0); /* version */ out_uint32_le(s, size); /* block size */ return trans_force_write(trans); }
/* Initialise ISO transport data packet */ STREAM iso_init(int length) { STREAM s; s = tcp_init(length + 7); s_push_layer(s, iso_hdr, 7); return s; }
/* Initialise an RDP data packet */ static STREAM rdp_init_data(RDPCLIENT * This, int maxlen) { STREAM s; s = sec_init(This, This->encryption ? SEC_ENCRYPT : 0, maxlen + 18); if(s == NULL) return NULL; s_push_layer(s, rdp_hdr, 18); return s; }
/* Initialise ISO transport data packet */ STREAM iso_init(RDPCLIENT * This, int length) { STREAM s; s = tcp_init(This, length + 7); if(s == NULL) return NULL; s_push_layer(s, iso_hdr, 7); return s; }
/* return error */ static int APP_CC lib_send_client_info(struct mod *mod) { struct stream *s; int len; make_stream(s); init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 104); g_memcpy(s->p, &(mod->client_info), sizeof(mod->client_info)); s->p += sizeof(mod->client_info); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); free_stream(s); return 0; }
/* 006 */ enum SCP_SERVER_STATES_E scp_v1s_mng_list_sessions(struct SCP_CONNECTION *c, struct SCP_SESSION *s, int sescnt, struct SCP_DISCONNECTED_SESSION *ds) { tui32 version = 1; tui32 size = 12; tui16 cmd = SCP_CMD_MNG_LIST; int pktcnt; int idx; int sidx; int pidx; struct SCP_DISCONNECTED_SESSION *cds; /* 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; idx < pktcnt; idx++) { /* ok, we send session session list */ init_stream(c->out_s, c->out_s->size); /* size: ver+size+cmdset+cmd+sescnt+continue+count */ size = 4 + 4 + 2 + 2 + 4 + 1 + 1; /* header */ s_push_layer(c->out_s, channel_hdr, 8); out_uint16_be(c->out_s, SCP_COMMAND_SET_MANAGE); 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; sidx < pidx; sidx++) { /* shortcut to the current session to send */ cds = ds + ((idx) * SCP_SERVER_MAX_LIST_SIZE) + sidx; /* session data */ out_uint32_be(c->out_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 += 13; out_uint16_be(c->out_s, cds->conn_year); out_uint8(c->out_s, cds->conn_month); out_uint8(c->out_s, cds->conn_day); out_uint8(c->out_s, cds->conn_hour); out_uint8(c->out_s, cds->conn_minute); out_uint8(c->out_s, cds->addr_type); size += 7; if (cds->addr_type == SCP_ADDRESS_TYPE_IPV4) { in_uint32_be(c->out_s, cds->ipv4addr); size += 4; } else if (cds->addr_type == SCP_ADDRESS_TYPE_IPV6) { in_uint8a(c->out_s, cds->ipv6addr, 16); size += 16; } } s_pop_layer(c->out_s, channel_hdr); out_uint32_be(c->out_s, version); out_uint32_be(c->out_s, size); if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { log_message(LOG_LEVEL_WARNING, "[v1s_mng:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } return _scp_v1s_mng_check_response(c, s); }
int DEFAULT_CC main(int argc, char** argv) { int sck; int code; int i; int size; int version; int width; int height; int bpp; int keylayout; int display; struct stream* in_s; struct stream* out_s; char* username; char* password; char* exec; long data; if (0 != config_read(&g_cfg)) { g_printf("sesrun: error reading config. quitting.\n"); return 1; } g_pid = g_getpid(); if (argc == 1) { g_printf("xrdp session starter v0.2\n"); g_printf("\nusage:\n"); g_printf("sesrun <server> <username> <password> <exec> <width> <height> <bpp> <keylayout>\n"); } else if (argc == 9) { username = argv[2]; password = argv[3]; exec = argv[4]; width = g_atoi(argv[5]); height = g_atoi(argv[6]); bpp = g_atoi(argv[7]); keylayout = g_atoi(argv[8]); 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, 20); /* 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); i = g_strlen(exec); out_uint16_be(out_s, i); out_uint8a(out_s, exec, i); out_uint16_be(out_s, width); out_uint16_be(out_s, height); out_uint16_be(out_s, bpp); out_uint16_be(out_s, keylayout); 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 */ tcp_force_send(sck, out_s->data, out_s->end - out_s->data); if (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 (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, data); in_uint16_be(in_s, display); g_printf("ok %d display %d\n", data, display); } } } } } else { g_printf("connect error\n"); } g_tcp_close(sck); free_stream(in_s); free_stream(out_s); } return 0; }
int EXPORT_CC libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, int bpp, char *data, int x, int y, int cx, int cy) { int line_size = 0; int i = 0; int j = 0; int total_lines = 0; int lines_sending = 0; int Bpp = 0; int e = 0; int bufsize = 0; int total_bufsize = 0; int num_updates = 0; char *p_num_updates = (char *)NULL; char *p = (char *)NULL; char *q = (char *)NULL; struct stream *s = (struct stream *)NULL; struct stream *temp_s = (struct stream *)NULL; DEBUG(("libxrdp_send_bitmap sending bitmap")); Bpp = (bpp + 7) / 8; e = width % 4; if (e != 0) { e = 4 - e; } line_size = width * Bpp; make_stream(s); init_stream(s, 8192); if (session->client_info->use_bitmap_comp) { make_stream(temp_s); init_stream(temp_s, 65536); i = 0; if (cy <= height) { i = cy; } while (i > 0) { total_bufsize = 0; num_updates = 0; xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); out_uint16_le(s, RDP_UPDATE_BITMAP); p_num_updates = s->p; out_uint8s(s, 2); /* num_updates set later */ do { if (session->client_info->op1) { s_push_layer(s, channel_hdr, 18); } else { s_push_layer(s, channel_hdr, 26); } p = s->p; lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 4096 - total_bufsize, i - 1, temp_s, e); if (lines_sending == 0) { break; } num_updates++; bufsize = s->p - p; total_bufsize += bufsize; i = i - lines_sending; s_mark_end(s); s_pop_layer(s, channel_hdr); out_uint16_le(s, x); /* left */ out_uint16_le(s, y + i); /* top */ out_uint16_le(s, (x + cx) - 1); /* right */ out_uint16_le(s, (y + i + lines_sending) - 1); /* bottom */ out_uint16_le(s, width + e); /* width */ out_uint16_le(s, lines_sending); /* height */ out_uint16_le(s, bpp); /* bpp */ if (session->client_info->op1) { out_uint16_le(s, 0x401); /* compress */ out_uint16_le(s, bufsize); /* compressed size */ j = (width + e) * Bpp; j = j * lines_sending; } else { out_uint16_le(s, 0x1); /* compress */ out_uint16_le(s, bufsize + 8); out_uint8s(s, 2); /* pad */ out_uint16_le(s, bufsize); /* compressed size */ j = (width + e) * Bpp; out_uint16_le(s, j); /* line size */ j = j * lines_sending; out_uint16_le(s, j); /* final size */ } if (j > 32768) { g_writeln("error, decompressed size too big, its %d", j); } if (bufsize > 8192) { g_writeln("error, compressed size too big, its %d", bufsize); } s->p = s->end; } while (total_bufsize < 4096 && i > 0); p_num_updates[0] = num_updates; p_num_updates[1] = num_updates >> 8; xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); if (total_bufsize > 8192) { g_writeln("error, total compressed size too big, its %d", total_bufsize); } } free_stream(temp_s); }
static int APP_CC xrdp_mm_send_login(struct xrdp_mm* self) { struct stream * s = (struct stream *)NULL; int rv = 0; int index = 0; int count = 0; char * username = (char *)NULL; char * password = (char *)NULL; char * name = (char *)NULL; char * value = (char *)NULL; xrdp_wm_log_msg(self->wm, "sending login info to session manager, " "please wait..."); username = 0; password = 0; self->code = 0; count = self->login_names->count; for (index = 0; index < count; index++) { name = (char*)list_get_item(self->login_names, index); value = (char*)list_get_item(self->login_values, index); if (g_strcasecmp(name, "username") == 0) { username = value; } else if (g_strcasecmp(name, "password") == 0) { password = value; } else if (g_strcasecmp(name, "lib") == 0) { if ((g_strcasecmp(value, "libxup.so") == 0) || (g_strcasecmp(value, "xup.dll") == 0)) { self->code = 10; } } } if ((username == 0) || (password == 0)) { xrdp_wm_log_msg(self->wm, "Error finding username and password"); return 1; } s = trans_get_out_s(self->sesman_trans, 8192); s_push_layer(s, channel_hdr, 8); /* this code is either 0 for Xvnc or 10 for X11rdp */ out_uint16_be(s, self->code); index = g_strlen(username); out_uint16_be(s, index); out_uint8a(s, username, index); index = g_strlen(password); out_uint16_be(s, index); out_uint8a(s, password, index); out_uint16_be(s, self->wm->screen->width); out_uint16_be(s, self->wm->screen->height); out_uint16_be(s, self->wm->screen->bpp); /* send domain */ index = g_strlen(self->wm->client_info->domain); out_uint16_be(s, index); out_uint8a(s, self->wm->client_info->domain, index); /* send program / shell */ index = g_strlen(self->wm->client_info->program); out_uint16_be(s, index); out_uint8a(s, self->wm->client_info->program, index); /* send directory */ index = g_strlen(self->wm->client_info->directory); out_uint16_be(s, index); out_uint8a(s, self->wm->client_info->directory, index); /* send client ip */ index = g_strlen(self->wm->client_info->client_ip); out_uint16_be(s, index); out_uint8a(s, self->wm->client_info->client_ip, index); s_mark_end(s); s_pop_layer(s, channel_hdr); out_uint32_be(s, 0); /* version */ index = (int)(s->end - s->data); out_uint32_be(s, index); /* size */ rv = trans_force_write(self->sesman_trans); if (rv != 0) { xrdp_wm_log_msg(self->wm, "xrdp_mm_send_login: xrdp_mm_send_login failed"); } return rv; }
int EXPORT_CC libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, int bpp, char *data, int x, int y, int cx, int cy) { int line_bytes = 0; int i = 0; int j = 0; int k; int total_lines = 0; int lines_sending = 0; int Bpp = 0; int e = 0; int bufsize = 0; int total_bufsize = 0; int num_updates = 0; int line_pad_bytes; int server_line_bytes; char *p_num_updates = (char *)NULL; char *p = (char *)NULL; char *q = (char *)NULL; struct stream *s = (struct stream *)NULL; struct stream *temp_s = (struct stream *)NULL; tui32 pixel; LLOGLN(10, ("libxrdp_send_bitmap: sending bitmap")); Bpp = (bpp + 7) / 8; e = (4 - width) & 3; switch (bpp) { case 15: case 16: server_line_bytes = width * 2; break; case 24: case 32: server_line_bytes = width * 4; break; default: /* 8 bpp */ server_line_bytes = width; break; } line_bytes = width * Bpp; line_pad_bytes = line_bytes + e * Bpp; LLOGLN(10, ("libxrdp_send_bitmap: bpp %d Bpp %d line_bytes %d " "server_line_bytes %d", bpp, Bpp, line_bytes, server_line_bytes)); make_stream(s); init_stream(s, MAX_BITMAP_BUF_SIZE); if (session->client_info->use_bitmap_comp) { LLOGLN(10, ("libxrdp_send_bitmap: compression")); make_stream(temp_s); init_stream(temp_s, 65536); i = 0; if (cy <= height) { i = cy; } while (i > 0) { LLOGLN(10, ("libxrdp_send_bitmap: i %d", i)); total_bufsize = 0; num_updates = 0; xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); out_uint16_le(s, RDP_UPDATE_BITMAP); p_num_updates = s->p; out_uint8s(s, 2); /* num_updates set later */ do { if (session->client_info->op1) { s_push_layer(s, channel_hdr, 18); } else { s_push_layer(s, channel_hdr, 26); } p = s->p; if (bpp > 24) { LLOGLN(10, ("libxrdp_send_bitmap: 32 bpp")); lines_sending = xrdp_bitmap32_compress(data, width, height, s, 32, (MAX_BITMAP_BUF_SIZE - 100) - total_bufsize, i - 1, temp_s, e, 0x10); LLOGLN(10, ("libxrdp_send_bitmap: i %d lines_sending %d", i, lines_sending)); } else { lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, (MAX_BITMAP_BUF_SIZE - 100) - total_bufsize, i - 1, temp_s, e); LLOGLN(10, ("libxrdp_send_bitmap: i %d lines_sending %d", i, lines_sending)); } if (lines_sending == 0) { break; } num_updates++; bufsize = s->p - p; total_bufsize += bufsize; i = i - lines_sending; s_mark_end(s); s_pop_layer(s, channel_hdr); out_uint16_le(s, x); /* left */ out_uint16_le(s, y + i); /* top */ out_uint16_le(s, (x + cx) - 1); /* right */ out_uint16_le(s, (y + i + lines_sending) - 1); /* bottom */ out_uint16_le(s, width + e); /* width */ out_uint16_le(s, lines_sending); /* height */ out_uint16_le(s, bpp); /* bpp */ if (session->client_info->op1) { out_uint16_le(s, 0x401); /* compress */ out_uint16_le(s, bufsize); /* compressed size */ j = (width + e) * Bpp; j = j * lines_sending; total_bufsize += 18; /* bytes since pop layer */ } else { out_uint16_le(s, 0x1); /* compress */ out_uint16_le(s, bufsize + 8); out_uint8s(s, 2); /* pad */ out_uint16_le(s, bufsize); /* compressed size */ j = (width + e) * Bpp; out_uint16_le(s, j); /* line size */ j = j * lines_sending; out_uint16_le(s, j); /* final size */ total_bufsize += 26; /* bytes since pop layer */ } LLOGLN(10, ("libxrdp_send_bitmap: decompressed pixels %d " "decompressed bytes %d compressed bytes %d", lines_sending * (width + e), line_pad_bytes * lines_sending, bufsize)); if (j > MAX_BITMAP_BUF_SIZE) { LLOGLN(0, ("libxrdp_send_bitmap: error, decompressed " "size too big: %d bytes", j)); } if (bufsize > MAX_BITMAP_BUF_SIZE) { LLOGLN(0, ("libxrdp_send_bitmap: error, compressed size " "too big: %d bytes", bufsize)); } s->p = s->end; } while (total_bufsize < MAX_BITMAP_BUF_SIZE && i > 0); LLOGLN(10, ("libxrdp_send_bitmap: num_updates %d total_bufsize %d", num_updates, total_bufsize)); p_num_updates[0] = num_updates; p_num_updates[1] = num_updates >> 8; xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); if (total_bufsize > MAX_BITMAP_BUF_SIZE) { LLOGLN(0, ("libxrdp_send_bitmap: error, total compressed " "size too big: %d bytes", total_bufsize)); } } free_stream(temp_s); }
/* 040 */ enum SCP_SERVER_STATES_E scp_v1s_list_sessions(struct SCP_CONNECTION* c, int sescnt, struct SCP_DISCONNECTED_SESSION* ds, SCP_SID* sid) { tui32 version=1; tui32 size=12; tui16 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 */ 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)) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); 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 server side or client side 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(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version!=1) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size<12) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_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(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_DEFAULT) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != 41) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); 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; idx<pktcnt; idx++) { /* ok, we send session session list */ init_stream(c->out_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; sidx<pidx; sidx++) { /* shortcut to the current session to send */ cds=ds+((idx)*SCP_SERVER_MAX_LIST_SIZE)+sidx; /* session data */ out_uint32_be(c->out_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 += 13; out_uint16_be(c->out_s, cds->conn_year); out_uint8(c->out_s, cds->conn_month); out_uint8(c->out_s, cds->conn_day); out_uint8(c->out_s, cds->conn_hour); out_uint8(c->out_s, cds->conn_minute); out_uint8(c->out_s, cds->addr_type); size += 7; if (cds->addr_type == SCP_ADDRESS_TYPE_IPV4) { in_uint32_be(c->out_s, cds->ipv4addr); size += 4; } else if (cds->addr_type == SCP_ADDRESS_TYPE_IPV6) { in_uint8a(c->out_s, cds->ipv6addr, 16); size += 16; } } s_pop_layer(c->out_s, channel_hdr); out_uint32_be(c->out_s, version); out_uint32_be(c->out_s, size); if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size)) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } } /* we get the 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(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (version != 1) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__); return SCP_SERVER_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 12) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__); return SCP_SERVER_STATE_SIZE_ERR; } /* rest of the packet */ 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(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__); return SCP_SERVER_STATE_NETWORK_ERR; } in_uint16_be(c->in_s, cmd); if (cmd != SCP_COMMAND_SET_DEFAULT) { log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); 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; idx<sescnt; idx++) { /* the sid is valid */ if (ds[idx].SID==(*sid)) { /* ok, session selected */ return SCP_SERVER_STATE_OK; } } /* if we got here, the requested sid wasn't one from the list we sent */ /* we should kill the connection */ log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } else if (cmd == 44) { /* cancel connection */ return SCP_SERVER_STATE_SELECTION_CANCEL; } // else if (cmd == 45) // { // /* force new connection */ // return SCP_SERVER_STATE_FORCE_NEW; // } else { /* wrong response */ log_message(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__); return SCP_SERVER_STATE_SEQUENCE_ERR; } return SCP_SERVER_STATE_OK; }
/* return error */ int DEFAULT_CC lib_mod_connect(struct mod* mod) { int error; int len; int i; int index; int use_uds; struct stream* s; char con_port[256]; LIB_DEBUG(mod, "in lib_mod_connect"); /* clear screen */ mod->server_begin_update(mod); mod->server_set_fgcolor(mod, 0); mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); mod->server_end_update(mod); mod->server_msg(mod, "started connecting", 0); /* only support 8, 15, 16, and 24 bpp connections from rdp client */ if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24) { mod->server_msg(mod, "error - only supporting 8, 15, 16, and 24 bpp rdp connections", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } if (g_strcmp(mod->ip, "") == 0) { mod->server_msg(mod, "error - no ip set", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } make_stream(s); g_sprintf(con_port, "%s", mod->port); use_uds = 0; if (con_port[0] == '/') { use_uds = 1; } mod->sck_closed = 0; i = 0; while (1) { if (use_uds) { mod->sck = g_tcp_local_socket(); } else { mod->sck = g_tcp_socket(); } g_tcp_set_non_blocking(mod->sck); g_tcp_set_no_delay(mod->sck); mod->server_msg(mod, "connecting...", 0); if (use_uds) { error = g_tcp_local_connect(mod->sck, con_port); } else { error = g_tcp_connect(mod->sck, mod->ip, con_port); } if (error == -1) { if (g_tcp_last_error_would_block(mod->sck)) { error = 0; index = 0; while (!g_tcp_can_send(mod->sck, 100)) { index++; if ((index >= 30) || mod->server_is_term(mod)) { mod->server_msg(mod, "connect timeout", 0); error = 1; break; } } } else { mod->server_msg(mod, "connect error", 0); } } if (error == 0) { break; } g_tcp_close(mod->sck); mod->sck = 0; i++; if (i >= 4) { mod->server_msg(mod, "connection problem, giving up", 0); break; } g_sleep(250); } if (error == 0) { init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 300); out_uint32_le(s, mod->width); out_uint32_le(s, mod->height); out_uint32_le(s, mod->bpp); out_uint32_le(s, mod->rfx); /* send rfx flag */ s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } if (error == 0) { init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 200); /* x and y */ i = 0; out_uint32_le(s, i); /* width and height */ i = ((mod->width & 0xffff) << 16) | mod->height; out_uint32_le(s, i); out_uint32_le(s, 0); out_uint32_le(s, 0); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } free_stream(s); if (error != 0) { mod->server_msg(mod, "some problem", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } else { mod->server_msg(mod, "connected ok", 0); mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0); } LIB_DEBUG(mod, "out lib_mod_connect"); return 0; }
enum SCP_CLIENT_STATES_E scp_v0c_connect(struct SCP_CONNECTION *c, struct SCP_SESSION *s) { tui32 version; tui32 size; tui16 sz; init_stream(c->in_s, c->in_s->size); init_stream(c->out_s, c->in_s->size); LOG_DBG("[v0:%d] starting connection", __LINE__); g_tcp_set_non_blocking(c->in_sck); g_tcp_set_no_delay(c->in_sck); s_push_layer(c->out_s, channel_hdr, 8); /* code */ if (s->type == SCP_SESSION_TYPE_XVNC) { out_uint16_be(c->out_s, 0); } else if (s->type == SCP_SESSION_TYPE_XRDP) { out_uint16_be(c->out_s, 10); } else if (s->type == SCP_SESSION_TYPE_XORG) { out_uint16_be(c->out_s, 20); } else { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_INTERNAL_ERR; } sz = g_strlen(s->username); out_uint16_be(c->out_s, sz); out_uint8a(c->out_s, s->username, sz); sz = g_strlen(s->password); out_uint16_be(c->out_s, sz); out_uint8a(c->out_s, s->password, sz); out_uint16_be(c->out_s, s->width); out_uint16_be(c->out_s, s->height); out_uint16_be(c->out_s, s->bpp); s_mark_end(c->out_s); s_pop_layer(c->out_s, channel_hdr); /* version */ out_uint32_be(c->out_s, 0); /* size */ out_uint32_be(c->out_s, c->out_s->end - c->out_s->data); if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data)) { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8)) { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } in_uint32_be(c->in_s, version); if (0 != version) { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: version error", __LINE__); return SCP_CLIENT_STATE_VERSION_ERR; } in_uint32_be(c->in_s, size); if (size < 14) { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: packet size error", __LINE__); return SCP_CLIENT_STATE_SIZE_ERR; } /* getting payload */ 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(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); return SCP_CLIENT_STATE_NETWORK_ERR; } /* check code */ in_uint16_be(c->in_s, sz); if (3 != sz) { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__); return SCP_CLIENT_STATE_SEQUENCE_ERR; } /* message payload */ in_uint16_be(c->in_s, sz); if (1 != sz) { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: connection denied", __LINE__); return SCP_CLIENT_STATE_CONNECTION_DENIED; } in_uint16_be(c->in_s, sz); s->display = sz; LOG_DBG("[v0:%d] connection terminated", __LINE__); return SCP_CLIENT_STATE_END; }
/* return error */ int DEFAULT_CC lib_mod_event(struct mod *mod, int msg, tbus param1, tbus param2, tbus param3, tbus param4) { struct stream *s; int len; int key; int rv; LIB_DEBUG(mod, "in lib_mod_event"); make_stream(s); if ((msg >= 15) && (msg <= 16)) /* key events */ { key = param2; if (key > 0) { if (key == 65027) /* altgr */ { if (mod->shift_state) { g_writeln("special"); /* fix for mstsc sending left control down with altgr */ /* control down / up msg param1 param2 param3 param4 15 0 65507 29 0 16 0 65507 29 49152 */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 16); /* key up */ out_uint32_le(s, 0); out_uint32_le(s, 65507); /* left control */ out_uint32_le(s, 29); /* RDP scan code */ out_uint32_le(s, 0xc000); /* flags */ s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } } if (key == 65507) /* left control */ { mod->shift_state = msg == 15; } } } init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, msg); out_uint32_le(s, param1); out_uint32_le(s, param2); out_uint32_le(s, param3); out_uint32_le(s, param4); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); rv = lib_send(mod, s->data, len); free_stream(s); LIB_DEBUG(mod, "out lib_mod_event"); return rv; }
/* return error */ int DEFAULT_CC lib_mod_connect(struct mod *mod) { int error; int len; int i; int index; int use_uds; struct stream *s; char con_port[256]; int retry = 0; int send_error = 0; int rc = 0; unsigned int nbytes; char pidfile[128]; char ip[16]; char cookie[33]; char sessionid[128]; char sessiontoken[128]; struct passwd pwd; struct passwd *pwdresult; char pwdbuffer[16384]; char message[256]; char reply[256]; int sock; struct sockaddr_in server; json_t *request; json_t *response; json_t *display; json_error_t js_error; mod->server_msg(mod, "GoPCNX started connection", 0); sock = socket(AF_INET , SOCK_STREAM , 0); if (sock == -1) { mod->server_msg(mod, "Socket creation failed", 0); return 1; } server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons(9999); if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) { mod->server_msg(mod, "Server connection failed", 0); return 1; } request = json_object(); json_object_set(request, "username", json_string(mod->username)); json_object_set(request, "password", json_string(mod->password)); json_object_set(request, "ip", json_string("127.0.0.1")); json_object_set(request, "link", json_string("lan")); display = json_object(); json_object_set(display, "width", json_integer(mod->width)); json_object_set(display, "height", json_integer(mod->height)); json_object_set(request, "display", display); json_decref(display); g_snprintf(message, sizeof(message)-1, "%s\n", json_dumps(request, 0)); json_decref(request); if (send(sock, message, strlen(message), 0) < 0) { mod->server_msg(mod, "Server request failed", 0); return 1; } if (recv(sock, reply, sizeof(reply), 0) < 0) { mod->server_msg(mod, "Server reply failed", 0); return 1; } response = json_loads(reply, 0, &js_error); if (response == NULL) { mod->server_msg(mod, "Decoding response failed", 0); return 1; } else { json_t *nxsession = json_object_get(response, "session"); json_t *err = json_object_get(response, "err"); int resume = json_is_true(json_object_get(response, "resume")); if (err) { mod->server_msg(mod, json_string_value(err), 0); return 1; } else if (resume) { resize_nxproxy(mod); } else { char sessionstash[512]; const char *cookie = json_string_value(json_object_get(nxsession, "cookie")); const char *host = json_string_value(json_object_get(nxsession, "host")); json_int_t port = json_integer_value(json_object_get(nxsession, "port")); getpwnam_r(mod->username, &pwd, pwdbuffer, sizeof(pwdbuffer), &pwdresult); if (pwdresult == NULL) { mod->server_msg(mod, "Uid lookup failed", 0); return 1; } if (!start_nxproxy(mod, cookie, (int)port)) { mod->server_msg(mod, "nxproxy failed to start", 0); return 1; } json_decref(nxsession); } } json_decref(response); LIB_DEBUG(mod, "in lib_mod_connect"); /* clear screen */ mod->server_begin_update(mod); mod->server_set_fgcolor(mod, 0); mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); mod->server_end_update(mod); mod->server_msg(mod, "started connecting", 0); /* only support 8, 15, 16, and 24 bpp connections from rdp client */ if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24) { mod->server_msg(mod, "error - only supporting 8, 15, 16, and 24 bpp rdp connections", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } if (g_strcmp(mod->ip, "") == 0) { mod->server_msg(mod, "error - no ip set", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } make_stream(s); g_snprintf(con_port, 255, "%s", mod->port); use_uds = 0; if (con_port[0] == '/') { use_uds = 1; } mod->sck_closed = 0; i = 0; RECONNECT: while (1) { if (use_uds) { mod->sck = g_tcp_local_socket(); } else { mod->sck = g_tcp_socket(); g_tcp_set_non_blocking(mod->sck); g_tcp_set_no_delay(mod->sck); } /* mod->server_msg(mod, "connecting...", 0); */ if (use_uds) { error = g_tcp_local_connect(mod->sck, con_port); } else { error = g_tcp_connect(mod->sck, mod->ip, con_port); } if (error == -1) { if (g_tcp_last_error_would_block(mod->sck)) { error = 0; index = 0; while (!g_tcp_can_send(mod->sck, 100)) { index++; if ((index >= 30) || mod->server_is_term(mod)) { mod->server_msg(mod, "connect timeout", 0); error = 1; break; } } } else { /* mod->server_msg(mod, "connect error", 0); */ } } if (error == 0) { break; } g_tcp_close(mod->sck); mod->sck = 0; i++; if (i >= 20) { mod->server_msg(mod, "connection problem, giving up", 0); break; } g_sleep(500); } if (error == 0) { if (use_uds) { lib_mod_log_peer(mod); } } if (error == 0) { /* send version message */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 301); out_uint32_le(s, 0); out_uint32_le(s, 0); out_uint32_le(s, 0); out_uint32_le(s, 1); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } if (error == 0) { /* send screen size message */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 300); out_uint32_le(s, mod->width); out_uint32_le(s, mod->height); out_uint32_le(s, mod->bpp); out_uint32_le(s, 0); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); lib_send(mod, s->data, len); } if (error == 0) { /* send invalidate message */ init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 103); out_uint32_le(s, 200); /* x and y */ i = 0; out_uint32_le(s, i); /* width and height */ i = ((mod->width & 0xffff) << 16) | mod->height; out_uint32_le(s, i); out_uint32_le(s, 0); out_uint32_le(s, 0); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); out_uint32_le(s, len); send_error = lib_send(mod, s->data, len); } if (send_error) { if (retry < 50) { g_tcp_close(mod->sck); mod->server_msg(mod, "Doing a retry", 0); retry++; g_sleep(1000); goto RECONNECT; } error = send_error; } free_stream(s); if (error != 0) { mod->server_msg(mod, "some problem", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } else { mod->server_msg(mod, "connected ok", 0); mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0); } LIB_DEBUG(mod, "out lib_mod_connect"); return 0; }