/* returns error */ int APP_CC send_channel_data(int chan_id, char* data, int size) { struct stream* s; int chan_flags; int total_size; int sent; int rv; s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { log_message(&log_conf, LOG_LEVEL_DEBUG, "chansrv[send_channel_data]: " "No client RDP client"); return 1; } rv = 0; sent = 0; total_size = size; while (sent < total_size) { size = MIN(1600, total_size - sent); chan_flags = 0; if (sent == 0) { chan_flags |= 1; /* first */ } if (size + sent == total_size) { chan_flags |= 2; /* last */ } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ out_uint32_le(s, 8); /* msg id */ out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ out_uint16_le(s, chan_id); out_uint16_le(s, chan_flags); out_uint16_le(s, size); out_uint32_le(s, total_size); out_uint8a(s, data + sent, size); s_mark_end(s); rv = trans_force_write(g_con_trans); if (rv != 0) { break; } sent += size; s = trans_get_out_s(g_con_trans, 8192); } return rv; }
static int APP_CC xrdp_mm_chan_send_init(struct xrdp_mm* self) { struct stream* s = (struct stream *)NULL; s = trans_get_out_s(self->chan_trans, 8192); if (s == 0) { return 1; } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8); /* size */ out_uint32_le(s, 1); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); return trans_force_write(self->chan_trans); }
/* returns error */ static int APP_CC xrdp_mm_trans_send_channel_data_response(struct xrdp_mm* self, struct trans* trans) { struct stream* s = (struct stream *)NULL; s = trans_get_out_s(trans, 8192); if (s == 0) { return 1; } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8); /* size */ out_uint32_le(s, 7); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); return trans_force_write(trans); }
/* returns error */ static int APP_CC send_channel_data_response_message(void) { struct stream* s; log_message(&log_conf, LOG_LEVEL_DEBUG, "chansrv[send_channel_data_response_message]: "); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { return 1; } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8); /* size */ out_uint32_le(s, 6); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); return trans_force_write(g_con_trans); }
/* returns error data coming from client that need to go to channel handler */ int APP_CC xrdp_mm_process_channel_data(struct xrdp_mm* self, tbus param1, tbus param2, tbus param3, tbus param4) { struct stream* s = (struct stream *)NULL; int rv = 0; int length = 0; int total_length = 0; int flags = 0; int id = 0; char * data = (char *)NULL; rv = 0; if ((self->chan_trans != 0) && self->chan_trans_up) { s = trans_get_out_s(self->chan_trans, 8192); if (s != 0) { id = LOWORD(param1); flags = HIWORD(param1); length = param2; data = (char*)param3; total_length = param4; if (total_length < length) { g_writeln("WARNING in xrdp_mm_process_channel_data(): total_len < length"); total_length = length; } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + length); out_uint32_le(s, 5); /* msg id */ out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + length); out_uint16_le(s, id); out_uint16_le(s, flags); out_uint16_le(s, length); out_uint32_le(s, total_length); out_uint8a(s, data, length); s_mark_end(s); rv = trans_force_write(self->chan_trans); } } return rv; }
/* 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); }
/* returns error */ static int APP_CC send_channel_setup_response_message(void) { struct stream *s = (struct stream *)NULL; LOGM((LOG_LEVEL_DEBUG, "send_channel_setup_response_message:")); s = trans_get_out_s(g_con_trans, 8192); if (s == 0) { return 1; } out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8); /* size */ out_uint32_le(s, 4); /* msg id */ out_uint32_le(s, 8); /* size */ s_mark_end(s); return trans_force_write(g_con_trans); }
/* returns error */ int APP_CC send_rail_drawing_orders(char* data, int size) { LOGM((LOG_LEVEL_DEBUG, "chansrv::send_rail_drawing_orders: size %d", size)); struct stream* s; int error; s = trans_get_out_s(g_con_trans, 8192); out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8 + size); /* size */ out_uint32_le(s, 10); /* msg id */ out_uint32_le(s, 8 + size); /* size */ out_uint8a(s, data, size); s_mark_end(s); error = trans_force_write(g_con_trans); if (error != 0) { return 1; } return 0; }
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; }
/* returns error */ static int APP_CC process_message_channel_data(struct stream *s) { int chan_id = 0; int chan_flags = 0; int rv = 0; int length = 0; int total_length = 0; struct stream *ls; in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); in_uint16_le(s, length); in_uint32_le(s, total_length); LOGM((LOG_LEVEL_DEBUG, "process_message_channel_data: chan_id %d " "chan_flags %d", chan_id, chan_flags)); LOG(10, ("process_message_channel_data")); rv = send_channel_data_response_message(); if (rv == 0) { if (chan_id == g_cliprdr_chan_id) { rv = clipboard_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == g_rdpsnd_chan_id) { rv = sound_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == g_rdpdr_chan_id) { rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == g_rail_chan_id) { rv = rail_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == g_drdynvc_chan_id) { rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == ((struct xrdp_api_data *) (g_api_con_trans->callback_data))->chan_id) { LOG(10, ("process_message_channel_data length %d total_length %d " "chan_flags 0x%8.8x", length, total_length, chan_flags)); ls = g_api_con_trans->out_s; if (chan_flags & 1) /* first */ { init_stream(ls, total_length); } out_uint8a(ls, s->p, length); if (chan_flags & 2) /* last */ { s_mark_end(ls); trans_force_write(g_api_con_trans); } } } return rv; }
/* returns error */ static int APP_CC send_data_from_chan_item(struct chan_item *chan_item) { struct stream *s; struct chan_out_data *cod; int bytes_left; int size; int chan_flags; int error; if (chan_item->head == 0) { return 0; } cod = chan_item->head; bytes_left = (int)(cod->s->end - cod->s->p); size = MIN(1600, bytes_left); chan_flags = 0; if (cod->s->p == cod->s->data) { chan_flags |= 1; /* first */ } if (cod->s->p + size >= cod->s->end) { chan_flags |= 2; /* last */ } s = trans_get_out_s(g_con_trans, 8192); out_uint32_le(s, 0); /* version */ out_uint32_le(s, 8 + 8 + 2 + 2 + 2 + 4 + size); /* size */ out_uint32_le(s, 8); /* msg id */ out_uint32_le(s, 8 + 2 + 2 + 2 + 4 + size); /* size */ out_uint16_le(s, chan_item->id); out_uint16_le(s, chan_flags); out_uint16_le(s, size); out_uint32_le(s, cod->s->size); out_uint8a(s, cod->s->p, size); s_mark_end(s); LOGM((LOG_LEVEL_DEBUG, "chansrv::send_channel_data: -- " "size %d chan_flags 0x%8.8x", size, chan_flags)); error = trans_force_write(g_con_trans); if (error != 0) { return 1; } cod->s->p += size; if (cod->s->p >= cod->s->end) { free_stream(cod->s); chan_item->head = chan_item->head->next; if (chan_item->head == 0) { chan_item->tail = 0; } g_free(cod); } return 0; }