diff options
| -rw-r--r-- | libxrdp/libxrdp.h | 14 | ||||
| -rw-r--r-- | libxrdp/xrdp_fastpath.c | 20 | ||||
| -rw-r--r-- | libxrdp/xrdp_orders.c | 124 | ||||
| -rw-r--r-- | libxrdp/xrdp_rdp.c | 68 | ||||
| -rw-r--r-- | libxrdp/xrdp_sec.c | 88 | 
5 files changed, 262 insertions, 52 deletions
| diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 7a4342db..da8ebc3f 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -346,6 +346,10 @@ xrdp_sec_delete(struct xrdp_sec* self);  int APP_CC  xrdp_sec_init(struct xrdp_sec* self, struct stream* s);  int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s); +int APP_CC +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s); +int APP_CC  xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s);  int APP_CC  xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan); @@ -370,6 +374,8 @@ xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s);  int APP_CC  xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s);  int APP_CC +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s); +int APP_CC  xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code);  int APP_CC  xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type); @@ -377,6 +383,9 @@ int APP_CC  xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s,                     int data_pdu_type);  int APP_CC +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, +                       int data_pdu_type); +int APP_CC  xrdp_rdp_send_data_update_sync(struct xrdp_rdp* self);  int APP_CC  xrdp_rdp_incoming(struct xrdp_rdp* self); @@ -554,4 +563,9 @@ int APP_CC  xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s);  int APP_CC  xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s); +  #endif diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 927f9407..681d5424 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -97,13 +97,28 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)  }  /*****************************************************************************/ +/* no fragmenation */  int APP_CC -xrdp_fastpath_init(struct xrdp_fastpath *self) +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s)  { +    init_stream(s, 32 * 1024);      return 0;  }  /*****************************************************************************/ +/* no fragmenation */ +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) +{ +    if (trans_force_write_s(self->trans, s) != 0) +    { +        return 1; +    } +    return 0; +} + +#if 0 +/*****************************************************************************/  int APP_CC  xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode,                                struct stream *s) @@ -165,6 +180,7 @@ xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode,      return 0;  } +#endif  /*****************************************************************************/  int @@ -194,6 +210,7 @@ xrdp_fastpath_process_update(struct xrdp_fastpath *self, tui8 updateCode,      return 0;  } +#if 0  /*****************************************************************************/  int APP_CC  xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s, @@ -249,6 +266,7 @@ xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s,      in_uint16_le(s, size);      return xrdp_fastpath_process_update(self, updateCode, size, s);  } +#endif  /*****************************************************************************/  /* FASTPATH_INPUT_EVENT_SCANCODE */ diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 317e1135..819c3d06 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -64,7 +64,6 @@ xrdp_orders_delete(struct xrdp_orders *self)      {          return;      } -      xrdp_jpeg_deinit(self->jpeg_han);      free_stream(self->out_s);      g_free(self->orders_state.text_data); @@ -81,7 +80,6 @@ xrdp_orders_reset(struct xrdp_orders *self)      {          return 1;      } -      g_free(self->orders_state.text_data);      g_memset(&(self->orders_state), 0, sizeof(self->orders_state));      self->order_count_ptr = 0; @@ -98,24 +96,33 @@ int APP_CC  xrdp_orders_init(struct xrdp_orders *self)  {      self->order_level++; -      if (self->order_level == 1)      {          self->order_count = 0; - -        /* is this big enough */ -        if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) +        if (self->rdp_layer->client_info.use_fast_path & 1)          { -            return 1; +            LLOGLN(10, ("xrdp_orders_init: fastpath")); +            if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0) +            { +                return 1; +            } +            self->order_count_ptr = self->out_s->p; +            out_uint8s(self->out_s, 2); /* number of orders, set later */ +        } +        else +        { +            LLOGLN(10, ("xrdp_orders_init: slowpath")); +            if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) +            { +                return 1; +            } +            out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); +            out_uint8s(self->out_s, 2); /* pad */ +            self->order_count_ptr = self->out_s->p; +            out_uint8s(self->out_s, 2); /* number of orders, set later */ +            out_uint8s(self->out_s, 2); /* pad */          } - -        out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); -        out_uint8s(self->out_s, 2); /* pad */ -        self->order_count_ptr = self->out_s->p; -        out_uint8s(self->out_s, 2); /* number of orders, set later */ -        out_uint8s(self->out_s, 2); /* pad */      } -      return 0;  } @@ -127,11 +134,9 @@ xrdp_orders_send(struct xrdp_orders *self)      int rv;      rv = 0; -      if (self->order_level > 0)      {          self->order_level--; -          if ((self->order_level == 0) && (self->order_count > 0))          {              s_mark_end(self->out_s); @@ -139,15 +144,24 @@ xrdp_orders_send(struct xrdp_orders *self)              self->order_count_ptr[0] = self->order_count;              self->order_count_ptr[1] = self->order_count >> 8;              self->order_count = 0; - -            if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, -                                   RDP_DATA_PDU_UPDATE) != 0) +            if (self->rdp_layer->client_info.use_fast_path & 1) +            { +                if (xrdp_rdp_send_fastpath(self->rdp_layer, +                                           self->out_s, 0) != 0) +                { +                    rv = 1; +                } +            } +            else              { -                rv = 1; +                if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, +                                       RDP_DATA_PDU_UPDATE) != 0) +                { +                    rv = 1; +                }              }          }      } -      return rv;  } @@ -160,21 +174,29 @@ xrdp_orders_force_send(struct xrdp_orders *self)      {          return 1;      } -      if ((self->order_level > 0) && (self->order_count > 0))      {          s_mark_end(self->out_s);          DEBUG(("xrdp_orders_force_send sending %d orders", self->order_count));          self->order_count_ptr[0] = self->order_count;          self->order_count_ptr[1] = self->order_count >> 8; - -        if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, -                               RDP_DATA_PDU_UPDATE) != 0) +        if (self->rdp_layer->client_info.use_fast_path & 1)          { -            return 1; +            if (xrdp_rdp_send_fastpath(self->rdp_layer, +                                       self->out_s, 0) != 0) +            { +                return 1; +            } +        } +        else +        { +            if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, +                                   RDP_DATA_PDU_UPDATE) != 0) +            { +                return 1; +            }          }      } -      self->order_count = 0;      self->order_level = 0;      return 0; @@ -1632,7 +1654,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,      int present;      char* present_ptr;      char* order_flags_ptr; -     +      if (xrdp_orders_check(self, 80) != 0)      {          return 1; @@ -1653,9 +1675,9 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,              order_flags |= RDP_ORDER_BOUNDS;              if (xrdp_orders_last_bounds(self, rect))              { -                 +                  order_flags |= RDP_ORDER_LASTBOUNDS; -                 +              }          }      } @@ -1699,21 +1721,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,      {          xrdp_orders_out_bounds(self, rect);      } -     +      if (srcidx != self->orders_state.com_blt_srcidx)      {          present |= 0x000001;          out_uint16_le(self->out_s, srcidx);          self->orders_state.com_blt_srcidx = srcidx;      } -     +      if (srcformat != self->orders_state.com_blt_srcformat)      {          present |= 0x000002;          out_uint32_le(self->out_s, srcformat);          self->orders_state.com_blt_srcformat = srcformat;      } -     +      if (srcwidth != self->orders_state.com_blt_srcwidth)      {          present |= 0x000004; @@ -1727,14 +1749,14 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_srcwidth = srcwidth;      } -     +      if (srcrepeat != self->orders_state.com_blt_srcrepeat)      {          present |= 0x000008;          out_uint8(self->out_s, srcrepeat);          self->orders_state.com_blt_srcrepeat = srcrepeat;      } -     +      if (srctransform != 0)      {          if (srctransform[0] != self->orders_state.com_blt_srctransform[0]) @@ -1768,21 +1790,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,              self->orders_state.com_blt_srctransform[0] = 0;          }      } -     +      if (mskflags != self->orders_state.com_blt_mskflags)      {          present |= 0x000040;          out_uint8(self->out_s, mskflags);          self->orders_state.com_blt_mskflags = mskflags;      } -     +      if (mskidx != self->orders_state.com_blt_mskidx)      {          present |= 0x000080;          out_uint16_le(self->out_s, mskidx);          self->orders_state.com_blt_mskidx = mskidx;      } -     +      if (mskformat != self->orders_state.com_blt_mskformat)      {          present |= 0x000100; @@ -1803,21 +1825,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_mskwidth = mskwidth;      } -     +      if (mskrepeat != self->orders_state.com_blt_mskrepeat)      {          present |= 0x000400;          out_uint8(self->out_s, mskrepeat);          self->orders_state.com_blt_mskrepeat = mskrepeat;      } -     +      if (op != self->orders_state.com_blt_op)      {          present |= 0x000800;          out_uint8(self->out_s, op);          self->orders_state.com_blt_op = op;      } -     +      if (srcx != self->orders_state.com_blt_srcx)      {          present |= 0x001000; @@ -1831,7 +1853,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_srcx = srcx;      } -     +      if (srcy != self->orders_state.com_blt_srcy)      {          present |= 0x002000; @@ -1845,7 +1867,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_srcy = srcy;      } -     +      if (mskx != self->orders_state.com_blt_mskx)      {          present |= 0x004000; @@ -1859,7 +1881,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_mskx = mskx;      } -     +      if (msky != self->orders_state.com_blt_msky)      {          present |= 0x008000; @@ -1873,7 +1895,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_msky = msky;      } -     +      if (dstx != self->orders_state.com_blt_dstx)      {          present |= 0x010000; @@ -1887,7 +1909,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_dstx = dstx;      } -     +      if (dsty != self->orders_state.com_blt_dsty)      {          present |= 0x020000; @@ -1901,7 +1923,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_dsty = dsty;      } -     +      if (width != self->orders_state.com_blt_width)      {          present |= 0x040000; @@ -1915,7 +1937,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          }          self->orders_state.com_blt_width = width;      } -     +      if (height != self->orders_state.com_blt_height)      {          present |= 0x080000; @@ -1936,11 +1958,11 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat,          out_uint32_le(self->out_s, dstformat);          self->orders_state.com_blt_dstformat = dstformat;      } -     +      xrdp_order_pack_small_or_tiny(self, order_flags_ptr, order_flags, -                                   +                                    present_ptr, present, 3); -     +      return 0;  } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 26e5c453..43daa874 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -26,6 +26,12 @@  #include <freerdp/constants.h>  #endif +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ +    do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ +    do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) +  /*****************************************************************************/  static int APP_CC  xrdp_rdp_read_config(struct xrdp_client_info *client_info) @@ -289,6 +295,7 @@ xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s)      s_push_layer(s, rdp_hdr, 18);      return 0;  } +  /*****************************************************************************/  /* returns error */  int APP_CC @@ -500,6 +507,65 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,  /*****************************************************************************/  int APP_CC +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s) +{ +    if (xrdp_sec_init_fastpath(self->sec_layer, s) != 0) +    { +        return 1; +    } +    if (self->client_info.rdp_compression) +    { +        s_push_layer(s, rdp_hdr, 4); +    } +    else +    { +        s_push_layer(s, rdp_hdr, 3); +    } +    return 0; +} + +/*****************************************************************************/ +/* TODO: compression */ +int APP_CC +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, +                       int data_pdu_type) +{ +    int updateHeader; +    int ctype; +    int len; + +    LLOGLN(10, ("xrdp_rdp_send_fastpath:")); +    s_pop_layer(s, rdp_hdr); +    len = (int)(s->end - s->p); +    if (self->client_info.rdp_compression) +    { +        /* TODO: finish compression */ +        LLOGLN(10, ("xrdp_rdp_send_fastpath: compress")); +        updateHeader = data_pdu_type & 15; +        updateHeader |= 2 << 6; /* FASTPATH_OUTPUT_COMPRESSION_USED */ +        out_uint8(s, updateHeader); +        ctype = 0; +        out_uint8(s, ctype); +        len -= 4; +    } +    else +    { +        LLOGLN(10, ("xrdp_rdp_send_fastpath: no compress")); +        updateHeader = data_pdu_type & 15; +        out_uint8(s, updateHeader); +        len -= 3; +    } +    out_uint16_le(s, len); +    if (xrdp_sec_send_fastpath(self->sec_layer, s) != 0) +    { +        LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed")); +        return 1; +    } +    return 0; +} + +/*****************************************************************************/ +int APP_CC  xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self)  {      struct stream *s = (struct stream *)NULL; @@ -1581,6 +1647,7 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self)      free_stream(s);      return 0;  } +  /*****************************************************************************/  int APP_CC  xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self) @@ -1620,6 +1687,7 @@ xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self)      free_stream(s);      return 0;  } +  /*****************************************************************************/  static int APP_CC  xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 626fc91e..9db0594f 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1245,6 +1245,94 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)      DEBUG((" out xrdp_sec_send"));      return 0;  } + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s) +{ +    if (xrdp_fastpath_init(self->fastpath_layer, s) != 0) +    { +        return 1; +    } +    if (self->crypt_level == CRYPT_LEVEL_FIPS) +    { +        s_push_layer(s, sec_hdr, 3 + 4 + 8); +    } +    else if (self->crypt_level > CRYPT_LEVEL_LOW) +    { +        s_push_layer(s, sec_hdr, 3 + 8); +    } +    else +    { +        s_push_layer(s, sec_hdr, 3); +    } +    return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) +{ +    int secFlags; +    int fpOutputHeader; +    int datalen; +    int pdulen; +    int pad; + +    LLOGLN(10, ("xrdp_sec_send_fastpath:")); +    s_pop_layer(s, sec_hdr); +    if (self->crypt_level == CRYPT_LEVEL_FIPS) +    { +        LLOGLN(10, ("xrdp_sec_send_fastpath: fips")); +        pdulen = (int)(s->end - s->p); +        datalen = pdulen - 15; +        secFlags = 0x2; +        fpOutputHeader = secFlags << 6; +        out_uint8(s, fpOutputHeader); +        pdulen |= 0x8000; +        out_uint16_be(s, pdulen); +        out_uint16_le(s, 16); /* crypto header size */ +        out_uint8(s, 1); /* fips version */ +        pad = (8 - (datalen % 8)) & 7; +        g_memset(s->end, 0, pad); +        s->end += pad; +        out_uint8(s, pad); /* fips pad */ +        xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); +        xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); +    } +    else if (self->crypt_level > CRYPT_LEVEL_LOW) +    { +        LLOGLN(10, ("xrdp_sec_send_fastpath: crypt")); +        pdulen = (int)(s->end - s->p); +        datalen = pdulen - 11; +        secFlags = 0x2; +        fpOutputHeader = secFlags << 6; +        out_uint8(s, fpOutputHeader); +        pdulen |= 0x8000; +        out_uint16_be(s, pdulen); +        xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen); +        xrdp_sec_encrypt(self, s->p + 8, datalen); +    } +    else +    { +        LLOGLN(10, ("xrdp_sec_send_fastpath: no crypt")); +        pdulen = (int)(s->end - s->p); +        LLOGLN(10, ("xrdp_sec_send_fastpath: pdulen %d", pdulen)); +        secFlags = 0x0; +        fpOutputHeader = secFlags << 6; +        out_uint8(s, fpOutputHeader); +        pdulen |= 0x8000; +        out_uint16_be(s, pdulen); +    } +    if (xrdp_fastpath_send(self->fastpath_layer, s) != 0) +    { +        return 1; +    } +    return 0; +} +  /*****************************************************************************/  /* http://msdn.microsoft.com/en-us/library/cc240510.aspx     2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */ | 
