예제 #1
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;
    }
  }
예제 #2
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);
  }
예제 #3
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;
    }
  }
예제 #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;
    }
  }