Ejemplo n.º 1
0
  /**
   * Intialise a packet at the Secure layer
   *
   * @param flags Encryption flags
   * @param length Length of packet
   * @return Intialised packet
   * @throws RdesktopException
   */
  public RdpPacket_Localised init(int flags, int length) throws RdesktopException {
    int headerlength = 0;
    RdpPacket_Localised buffer;

    if (!this.licenceIssued) headerlength = ((flags & SEC_ENCRYPT) != 0) ? 12 : 4;
    else headerlength = ((flags & SEC_ENCRYPT) != 0) ? 12 : 0;

    buffer = McsLayer.init(length + headerlength);
    buffer.pushLayer(RdpPacket.SECURE_HEADER, headerlength);
    // buffer.setHeader(RdpPacket_Localised.SECURE_HEADER);
    // buffer.incrementPosition(headerlength);
    // buffer.setStart(buffer.getPosition());
    return buffer;
  }
Ejemplo n.º 2
0
  /**
   * Handle MCS info from server (server info, encryption info and channel information)
   *
   * @param mcs_data Data received from server
   */
  public void processMcsData(RdpPacket_Localised mcs_data)
      throws RdesktopException, CryptoException {
    logger.debug("Secure.processMcsData");
    int tag = 0, len = 0, length = 0, nexttag = 0;

    mcs_data.incrementPosition(21); // header (T.124 stuff, probably)
    len = mcs_data.get8();

    if ((len & 0x00000080) != 0) {
      len = mcs_data.get8();
    }

    while (mcs_data.getPosition() < mcs_data.getEnd()) {
      tag = mcs_data.getLittleEndian16();
      length = mcs_data.getLittleEndian16();

      if (length <= 4) return;

      nexttag = mcs_data.getPosition() + length - 4;

      switch (tag) {
        case (Secure.SEC_TAG_SRV_INFO):
          processSrvInfo(mcs_data);
          break;
        case (Secure.SEC_TAG_SRV_CRYPT):
          this.processCryptInfo(mcs_data);
          break;
        case (Secure.SEC_TAG_SRV_CHANNELS):
          /*
           * FIXME: We should parse this information and use it to map
           * RDP5 channels to MCS channels
           */
          break;

        default:
          throw new RdesktopException("Not implemented! Tag:" + tag + "not recognized!");
      }

      mcs_data.setPosition(nexttag);
    }
  }
Ejemplo n.º 3
0
  /**
   * Read in a public key from a provided Secure layer PDU, and store in this.exponent and
   * this.modulus
   *
   * @param data Secure layer PDU containing key data
   * @return True if key successfully read
   * @throws RdesktopException
   */
  public boolean parsePublicKey(RdpPacket_Localised data) throws RdesktopException {
    int magic = 0, modulus_length = 0;

    magic = data.getLittleEndian32();

    if (magic != SEC_RSA_MAGIC) {
      throw new RdesktopException("Wrong magic! Expected" + SEC_RSA_MAGIC + "got:" + magic);
    }

    modulus_length = data.getLittleEndian32() - SEC_PADDING_SIZE;

    if (modulus_length < 64 || modulus_length > SEC_MAX_MODULUS_SIZE) {
      throw new RdesktopException(
          "Bad server public key size (" + (modulus_length * 8) + " bites)");
    }

    data.incrementPosition(8); // unknown modulus bits
    this.exponent = new byte[SEC_EXPONENT_SIZE];
    data.copyToByteArray(this.exponent, 0, data.getPosition(), SEC_EXPONENT_SIZE);
    data.incrementPosition(SEC_EXPONENT_SIZE);
    this.modulus = new byte[modulus_length];
    data.copyToByteArray(this.modulus, 0, data.getPosition(), modulus_length);
    data.incrementPosition(modulus_length);
    data.incrementPosition(SEC_PADDING_SIZE);
    this.server_public_key_len = modulus_length;

    if (data.getPosition() <= data.getEnd()) {
      return true;
    } else {
      return false;
    }
  }
Ejemplo n.º 4
0
  /**
   * Read encryption information from a Secure layer PDU, obtaining and storing level of encryption
   * and any keys received
   *
   * @param data Packet to read encryption information from
   * @return Size of RC4 key
   * @throws RdesktopException
   */
  public int parseCryptInfo(RdpPacket_Localised data) throws RdesktopException {
    logger.debug("Secure.parseCryptInfo");
    int encryption_level = 0, random_length = 0, RSA_info_length = 0;
    int tag = 0, length = 0;
    int next_tag = 0, end = 0;
    int rc4_key_size = 0;

    rc4_key_size = data.getLittleEndian32(); // 1 = 40-Bit 2 = 128 Bit
    encryption_level = data.getLittleEndian32(); // 1 = low, 2 = medium,
    // 3 = high
    if (encryption_level == 0) { // no encryption
      return 0;
    }
    random_length = data.getLittleEndian32();
    RSA_info_length = data.getLittleEndian32();

    if (random_length != SEC_RANDOM_SIZE) {
      throw new RdesktopException(
          "Wrong Size of Random! Got" + random_length + "expected" + SEC_RANDOM_SIZE);
    }
    this.server_random = new byte[random_length];
    data.copyToByteArray(this.server_random, 0, data.getPosition(), random_length);
    data.incrementPosition(random_length);

    end = data.getPosition() + RSA_info_length;

    if (end > data.getEnd()) {
      logger.debug("Reached end of crypt info prematurely ");
      return 0;
    }

    // data.incrementPosition(12); // unknown bytes
    int flags = data.getLittleEndian32(); // in_uint32_le(s, flags); // 1
    // = RDP4-style, 0x80000002 =
    // X.509
    logger.debug("Flags = 0x" + Integer.toHexString(flags));
    if ((flags & 1) != 0) {
      logger.debug(("We're going for the RDP4-style encryption"));
      data.incrementPosition(8); // in_uint8s(s, 8); // unknown

      while (data.getPosition() < data.getEnd()) {
        tag = data.getLittleEndian16();
        length = data.getLittleEndian16();

        next_tag = data.getPosition() + length;

        switch (tag) {
          case (Secure.SEC_TAG_PUBKEY):
            if (!parsePublicKey(data)) {
              return 0;
            }

            break;
          case (Secure.SEC_TAG_KEYSIG):
            // Microsoft issued a key but we don't care
            break;

          default:
            throw new RdesktopException("Unimplemented decrypt tag " + tag);
        }
        data.setPosition(next_tag);
      }

      if (data.getPosition() == data.getEnd()) {
        return rc4_key_size;
      } else {
        logger.warn("End not reached!");
        return 0;
      }

    } else {
      logger.debug(("We're going for the RDP5-style encryption"));
      // data.incrementPosition(4); // number of certificates
      int num_certs = data.getLittleEndian32();

      int cacert_len = data.getLittleEndian32();
      data.incrementPosition(cacert_len);
      int cert_len = data.getLittleEndian32();
      data.incrementPosition(cert_len);

      readCert = true;

      return rc4_key_size;
    }
  }
Ejemplo n.º 5
0
  /**
   * Prepare data as a Secure PDU and pass down to the MCS layer
   *
   * @param sec_data Data to send
   * @param flags Encryption flags
   * @param channel Channel over which to send data
   * @throws RdesktopException
   * @throws IOException
   * @throws CryptoException
   */
  public void send_to_channel(RdpPacket_Localised sec_data, int flags, int channel)
      throws RdesktopException, IOException, CryptoException {
    int datalength = 0;
    byte[] signature = null;
    byte[] data;
    byte[] buffer;

    sec_data.setPosition(sec_data.getHeader(RdpPacket.SECURE_HEADER));

    if (this.licenceIssued == false || (flags & SEC_ENCRYPT) != 0) {
      sec_data.setLittleEndian32(flags);
    }

    if (Options.debug_hexdump) {
      int length = sec_data.getEnd() - sec_data.getPosition();
      byte[] packet = new byte[length];
      sec_data.copyToByteArray(
          packet, 0, sec_data.getPosition(), sec_data.getEnd() - sec_data.getPosition());
      System.out.println("Sending packet:");
      System.out.println(net.propero.rdp.tools.HexDump.dumpHexString(packet));
    }

    if ((flags & SEC_ENCRYPT) != 0) {
      flags &= ~SEC_ENCRYPT;
      datalength = sec_data.getEnd() - sec_data.getPosition() - 8;
      data = new byte[datalength];
      buffer = null;
      sec_data.copyToByteArray(data, 0, sec_data.getPosition() + 8, datalength);
      signature = this.sign(this.sec_sign_key, 8, this.keylength, data, datalength);

      buffer = this.encrypt(data, datalength);

      sec_data.copyFromByteArray(signature, 0, sec_data.getPosition(), 8);
      sec_data.copyFromByteArray(buffer, 0, sec_data.getPosition() + 8, datalength);
    }
    // McsLayer.send(sec_data);
    McsLayer.send_to_channel(sec_data, channel);
  }
Ejemplo n.º 6
0
  public void establishKey() throws RdesktopException, IOException, CryptoException {
    RdpPacket_Localised buffer;
    int flags = SEC_CLIENT_RANDOM;
    if (readCert) {
      // RDP5-style encryption, use old code for now
      int length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
      buffer = this.init(flags, 76);

      buffer.setLittleEndian32(length);

      buffer.copyFromByteArray(this.sec_crypted_random, 0, buffer.getPosition(), SEC_MODULUS_SIZE);
      buffer.incrementPosition(SEC_MODULUS_SIZE);
    } else {
      int length = server_public_key_len + SEC_PADDING_SIZE;
      buffer = this.init(flags, length + 4);

      buffer.setLittleEndian32(length);

      buffer.copyFromByteArray(
          this.sec_crypted_random, 0, buffer.getPosition(), server_public_key_len);
      buffer.incrementPosition(server_public_key_len);
    }
    buffer.incrementPosition(SEC_PADDING_SIZE);
    buffer.markEnd();
    this.send(buffer, flags);
  }
Ejemplo n.º 7
0
 /**
  * Read server info from packet, specifically the RDP version of the server
  *
  * @param mcs_data Packet to read
  */
 private void processSrvInfo(RdpPacket_Localised mcs_data) {
   Options.server_rdp_version = mcs_data.getLittleEndian16(); // in_uint16_le(s,
   // g_server_rdp_version);
   logger.debug(("Server RDP version is " + Options.server_rdp_version));
   if (1 == Options.server_rdp_version) Options.use_rdp5 = false;
 }
Ejemplo n.º 8
0
  /**
   * Construct MCS data, including channel, encryption and display options
   *
   * @return Packet populated with MCS data
   */
  public RdpPacket_Localised sendMcsData() {
    logger.debug("Secure.sendMcsData");

    RdpPacket_Localised buffer = new RdpPacket_Localised(512);

    int hostlen = 2 * (Options.hostname == null ? 0 : Options.hostname.length());

    if (hostlen > 30) {
      hostlen = 30;
    }

    int length = 162 + 76 + 12 + 4;

    if (Options.use_rdp5 && (channels.num_channels() > 0))
      length += channels.num_channels() * 12 + 8;

    buffer.setBigEndian16(5); /* unknown */
    buffer.setBigEndian16(0x14);
    buffer.set8(0x7c);
    buffer.setBigEndian16(1);

    buffer.setBigEndian16(length | 0x8000); // remaining length

    buffer.setBigEndian16(8); // length?
    buffer.setBigEndian16(16);
    buffer.set8(0);
    buffer.setLittleEndian16(0xc001);
    buffer.set8(0);

    buffer.setLittleEndian32(0x61637544); // "Duca" ?!
    buffer.setBigEndian16(length - 14 | 0x8000); // remaining length

    // Client information
    buffer.setLittleEndian16(SEC_TAG_CLI_INFO);
    buffer.setLittleEndian16(216); // length
    buffer.setLittleEndian16(Options.use_rdp5 ? 4 : 1);
    buffer.setLittleEndian16(8);
    buffer.setLittleEndian16(Options.width);
    buffer.setLittleEndian16(Options.height);
    buffer.setLittleEndian16(0xca01);
    buffer.setLittleEndian16(0xaa03);
    buffer.setLittleEndian32(Options.keylayout);
    buffer.setLittleEndian32(2600); // or 0ece
    // // client
    // build? we
    // are 2600
    // compatible
    // :-)

    /* Unicode name of client, padded to 32 bytes */
    buffer.outUnicodeString(Options.hostname, hostlen);
    buffer.incrementPosition(30 - hostlen);

    buffer.setLittleEndian32(4);
    buffer.setLittleEndian32(0);
    buffer.setLittleEndian32(12);
    buffer.incrementPosition(64); /* reserved? 4 + 12 doublewords */

    buffer.setLittleEndian16(0xca01); // out_uint16_le(s, 0xca01);
    buffer.setLittleEndian16(1);

    buffer.setLittleEndian32(0); // out_uint32(s, 0);
    buffer.set8(Options.server_bpp); // out_uint8(s, g_server_bpp);
    buffer.setLittleEndian16(0x0700); // out_uint16_le(s, 0x0700);
    buffer.set8(0); // out_uint8(s, 0);
    buffer.setLittleEndian32(1); // out_uint32_le(s, 1);
    buffer.incrementPosition(64);
    buffer.setLittleEndian32(0); // selected_protocol /* End of client info */

    buffer.setLittleEndian16(SEC_TAG_CLI_4); // out_uint16_le(s, SEC_TAG_CLI_4);
    buffer.setLittleEndian16(12); // out_uint16_le(s, 12);

    int cluster_flags = 0;
    cluster_flags |= SEC_CC_REDIRECTION_SUPPORTED;
    cluster_flags |= (SEC_CC_REDIRECT_VERSION_3 << 2);
    if (Options.console_session) {
      cluster_flags |= SEC_CC_REDIRECT_SESSIONID_FIELD_VALID;
    }
    buffer.setLittleEndian32(cluster_flags); // out_uint32_le(s,
    buffer.setLittleEndian32(0); // redirect session id?

    // Client encryption settings //
    buffer.setLittleEndian16(SEC_TAG_CLI_CRYPT);
    buffer.setLittleEndian16(12); // length
    buffer.setLittleEndian32(Options.encryption ? 0x3 : 0);
    buffer.setLittleEndian32(0); // unknown

    if (Options.use_rdp5 && (channels.num_channels() > 0)) {
      logger.debug(("num_channels is " + channels.num_channels()));
      buffer.setLittleEndian16(SEC_TAG_CLI_CHANNELS); // out_uint16_le(s,
      // SEC_TAG_CLI_CHANNELS);
      buffer.setLittleEndian16(channels.num_channels() * 12 + 8); // out_uint16_le(s,
      buffer.setLittleEndian32(channels.num_channels()); // out_uint32_le(s,
      // g_num_channels);
      // // number of
      // virtual
      // channels
      for (int i = 0; i < channels.num_channels(); i++) {
        logger.debug(("Requesting channel " + channels.channel(i).name()));
        buffer.out_uint8p(channels.channel(i).name(), 8); // out_uint8a(s,
        // g_channels[i].name,
        // 8);
        buffer.setBigEndian32(channels.channel(i).flags()); // out_uint32_be(s,
        // g_channels[i].flags);
      }
    }

    buffer.markEnd();
    return buffer;
  }
Ejemplo n.º 9
0
  /**
   * Receive a Secure layer PDU from the MCS layer
   *
   * @return Packet representing received Secure PDU
   * @throws RdesktopException
   * @throws IOException
   * @throws CryptoException
   * @throws OrderException
   */
  public RdpPacket_Localised receive()
      throws RdesktopException, IOException, CryptoException, OrderException {
    int sec_flags = 0;
    RdpPacket_Localised buffer = null;
    while (true) {
      int[] channel = new int[1];
      buffer = McsLayer.receive(channel);
      if (buffer == null) return null;
      buffer.setHeader(RdpPacket.SECURE_HEADER);
      if (Constants.encryption || (!this.licenceIssued)) {

        sec_flags = buffer.getLittleEndian32();

        if ((sec_flags & SEC_LICENCE_NEG) != 0) {
          licence.process(buffer);
          continue;
        }
        if ((sec_flags & SEC_ENCRYPT) != 0) {
          buffer.incrementPosition(8); // signature
          byte[] data = new byte[buffer.size() - buffer.getPosition()];
          buffer.copyToByteArray(data, 0, buffer.getPosition(), data.length);
          byte[] packet = this.decrypt(data);

          buffer.copyFromByteArray(packet, 0, buffer.getPosition(), packet.length);

          // buffer.setStart(buffer.getPosition());
          // return buffer;
        }
      }

      if (channel[0] != MCS.MCS_GLOBAL_CHANNEL) {
        channels.channel_process(buffer, channel[0]);
        continue;
      }

      buffer.setStart(buffer.getPosition());
      return buffer;
    }
  }