Commit 923452dc authored by YannGarcia's avatar YannGarcia
Browse files

Enhance security support

parent b3e32ae4
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -371,17 +371,17 @@ public:
   * \param[in] p_value The buffer value
   * \return The Base64 encoded buffert
   */
  std::vector<unsigned char> buffer_to_base64(const std::vector<unsigned char> &p_value);
  std::vector<unsigned char> buffer_to_base64(const std::vector<unsigned char> &p_value, const bool p_is_url = false);

  /*!
   * \brief Convert the provided Base64 buffer
   * \param[in] p_value The buffer value
   * \return The Base64 encoded buffert
   */
  std::vector<unsigned char> base64_to_buffer(const std::vector<unsigned char> &p_value);
  std::vector<unsigned char> base64_to_buffer(const std::vector<unsigned char> &p_value, const bool p_remove_crlf = true);

  static const std::string lut_u;
  static const std::string lut_l;
  static const std::string base64_enc_map;
  static const std::string base64_enc_map[2];

}; // End of class converter
+104 −39
Original line number Diff line number Diff line
#include "converter.hh"

#include <stdexcept>

converter *converter::instance = NULL;

uint16_t converter::swap(const uint16_t p_value) {
@@ -40,22 +42,22 @@ std::string converter::string_to_hexa(const std::string& p_value, const bo
}

std::string converter::bytes_to_hexa(const std::vector<uint8_t> &p_value, const bool p_uppercase) {
  std::string ret;
  ret.assign(p_value.size() * 2, ' ');
  std::string out;
  out.assign(p_value.size() * 2, ' ');
  if (p_uppercase) { // TODO Use pointer to reduce code size
    for (size_t i = 0; i < p_value.size(); i++) {
      uint8_t c      = p_value[i];
      ret[i * 2]     = lut_u[c >> 4];
      ret[i * 2 + 1] = lut_u[c & 0xF];
      out[i * 2]     = lut_u[c >> 4];
      out[i * 2 + 1] = lut_u[c & 0xF];
    }
  } else {
    for (size_t i = 0; i < p_value.size(); i++) {
      uint8_t c      = p_value[i];
      ret[i * 2]     = lut_l[c >> 4];
      ret[i * 2 + 1] = lut_l[c & 0xF];
      out[i * 2]     = lut_l[c >> 4];
      out[i * 2 + 1] = lut_l[c & 0xF];
    }
  }
  return ret;
  return out;
}

inline uint8_t char2byte(const char p_ch) {
@@ -147,49 +149,112 @@ std::vector<std::string> converter::split_arguments_line(const std::string& p_va
  return output;
}

const std::string converter::base64_enc_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const std::string converter::base64_enc_map[2] = {
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
  };

/**
 * @brief Return the position of chr within base64_encode()
 * @param[in] chr 
 * @return Return the position of chr within base64_encode()
 */
static unsigned char pos_of_char(const unsigned char chr) {
  if ((chr >= 'A' && chr <= 'Z')) {
    return static_cast<unsigned char>(chr - 'A');
  } else if ((chr >= 'a' && chr <= 'z')) {
    return static_cast<unsigned char>(chr - 'a' + ('Z' - 'A') + 1);
  } else if ((chr >= '0' && chr <= '9')) {
    return static_cast<unsigned char>(chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2);
  } else if ((chr == '+' || chr == '-')) {
    return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
  } else if ((chr == '/' || chr == '_')) {
    return 63; // Idem for '/' and '_'
  } else {
    throw std::runtime_error("Input is not valid base64-encoded data.");
  }
}

static std::string insert_linebreaks(std::string str, size_t distance) {
    if (!str.length()) {
        return "";
    }
    size_t pos = distance;
    while (pos < str.size()) {
        str.insert(pos, "\n");
        pos += distance + 1;
    }
    return str;
}

std::vector<unsigned char> converter::buffer_to_base64(const std::vector<unsigned char> &p_value, const bool p_is_url) {
  const std::string& base64_enc_map_ = converter::base64_enc_map[(p_is_url) ? 1 : 0];
  const unsigned char trailing_char = (p_is_url) ? '.' : '=';

std::vector<unsigned char> converter::buffer_to_base64(const std::vector<unsigned char> &p_value) {
  std::vector<unsigned char> out;
  //out.resize((p_value.size() + 2) / 3 * 4);

  int val = 0, valb = -6;
  for (unsigned char c : p_value) {
    val = (val << 8) + c;
    valb += 8;
    while (valb >= 0) {
      out.push_back(converter::base64_enc_map[(val >> valb) & 0x3F]);
      valb -= 6;
    } // End of 'while' statement
  }   // End of 'for' statement
  if (valb > -6) {
    out.push_back(converter::base64_enc_map[((val << 8) >> (valb + 8)) & 0x3F]);
  unsigned int pos = 0;
  while (pos < p_value.size()) {
      out.push_back(base64_enc_map_[(p_value[pos + 0] & 0xfc) >> 2]);

      if (pos+1 < p_value.size()) {
          out.push_back(base64_enc_map_[((p_value[pos + 0] & 0x03) << 4) + ((p_value[pos + 1] & 0xf0) >> 4)]);

          if (pos+2 < p_value.size()) {
            out.push_back(base64_enc_map_[((p_value[pos + 1] & 0x0f) << 2) + ((p_value[pos + 2] & 0xc0) >> 6)]);
            out.push_back(base64_enc_map_[  p_value[pos + 2] & 0x3f]);
          } else {
            out.push_back(base64_enc_map_[(p_value[pos + 1] & 0x0f) << 2]);
            out.push_back(trailing_char);
          }
      } else {
          out.push_back(base64_enc_map_[(p_value[pos + 0] & 0x03) << 4]);
          out.push_back(trailing_char);
          out.push_back(trailing_char);
      }
  while (out.size() % 4) {
    out.push_back('=');
      pos += 3;
    } // End of 'while' statement

  return out;
}

std::vector<unsigned char> converter::base64_to_buffer(const std::vector<unsigned char> &p_value) {
  std::vector<unsigned char> out;
std::vector<unsigned char> converter::base64_to_buffer(const std::vector<unsigned char> &p_value, const bool p_remove_crlf) {

  std::vector<int> T(256, -1);
  for (int i = 0; i < 64; i++) {
    T[converter::base64_enc_map[i]] = i;
  if (p_value.size() == 0) {
    return std::vector<unsigned char>();
  }

  int val = 0, valb = -8;
  for (unsigned char c : p_value) {
    if (T[c] == -1) {
      break;
  std::vector<unsigned char> value(p_value);
  if (p_remove_crlf) {
    value.erase(std::remove(value.begin(), value.end(), '\r'), value.end());
    value.erase(std::remove(value.begin(), value.end(), '\n'), value.end());
  }
    val = (val << 6) + T[c];
    valb += 6;
    if (valb >= 0) {
      out.push_back((unsigned char)char((val >> valb) & 0xFF));
      valb -= 8;

  std::vector<unsigned char> out;
  //out.resize(value.size() / 4 * 3);

  size_t pos = 0;
  while (pos < value.size()) {
    size_t pos_of_char_1 = pos_of_char(value[pos + 1]);
    out.push_back(((pos_of_char(value[pos])) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4));

    if ((pos + 2 < value.size()) &&  // Check for data that is not padded with equal signs (which is allowed by RFC 2045)
        value[pos + 2] != '=' &&
        value[pos + 2] != '.' // accept URL-safe base 64 strings, too, so check for '.' also.
        ) {
      //Emit a chunk's second byte (which might not be produced in the last chunk).
      unsigned int pos_of_char_2 = pos_of_char(value[pos + 2]);
      out.push_back(((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2));

      if ((pos + 3 < value.size()) && value[pos + 3] != '='  && value[pos + 3] != '.' ) {
        // Emit a chunk's third byte (which might not be produced in the last chunk).
        out.push_back(((pos_of_char_2 & 0x03 ) << 6) + pos_of_char(value[pos + 3]));
      }
  } // End of 'for' statement
    }

    pos += 4;
  } // End of 'while' statement

  return out;
}
+2 −2
Original line number Diff line number Diff line
@@ -449,8 +449,8 @@ int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_
    }
  } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_xml__body)) {
    const LibHttp__XmlMessageBodyTypes::XmlBody &xml_body = p_message_body.xml__body();
    if (xml_body.ischosen(LibHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) {
      p_encoding_buffer = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char *)static_cast<const char *>(xml_body.raw()));
    if (xml_body.msg().ischosen(LibHttp__XmlMessageBodyTypes::XmlBodyMsg::ALT_raw)) {
      p_encoding_buffer = OCTETSTRING(xml_body.msg().raw().lengthof(), (unsigned char *)static_cast<const char *>(xml_body.msg().raw()));
    } else {
      encode_body_xml(xml_body, p_encoding_buffer, p_content_type);
    }
+3 −1
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ void tcp_layer::init() {
  it = _params.find(std::string("tcp_fragmented"));
  if (it == _params.cend()) {
    _params.insert(std::pair<std::string, std::string>(std::string("tcp_fragmented"), "0"));
  } else {
    _params.insert(std::pair<std::string, std::string>(std::string("tcp_fragmented"), "1"));
  }
  bool server_mode = false;
  it = _params.find(params::server_mode);
@@ -257,7 +259,7 @@ int tcp_layer::receive_message_on_fd(int p_client_id)

  loggers::get_instance().log("tcp_layer::receive_message_on_fd: Non secured mode");
  if (_params[std::string("tcp_fragmented")].compare("1") == 0) {
    sleep(5); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution
    sleep(4); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution
  }
  return Abstract_Socket::receive_message_on_fd(p_client_id);
}
+10 −6
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ class certs_cache {
protected: /*! \protectedsection */
  // TODO Enforce with const security_cache_record, and const std::string
  std::map<std::string, const std::string> _certificates_idx; //! List of the certificate names indexed by the certificate identifier, i.e. the SH1 of the certificate name
  std::map<std::string, const std::string> _certificates_subject; //! List of the certificates indexed by the certificate subject name
  std::map<std::string, std::unique_ptr<const certs_db_record>> _certificates; //! List of the certificates indexed by the certificate identifier

public: /*! \publicsection */
@@ -42,7 +43,7 @@ public: /*! \publicsection */
   */
  virtual ~certs_cache();

  int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate);
  int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const X509** p_certificate);
  /*!
   * \fn int get_certificate(const std::string& p_hashed_id8, const X509** p_certificate);
   * \brief Retrive the specified certificate either from memory
@@ -51,6 +52,8 @@ public: /*! \publicsection */
   * \return 0 on success, -1 otherwise
   */
  int get_certificate(const std::string& p_certificate_id, const X509** p_certificate);

  int get_certificate_by_subject_name(const std::string& p_certificate_subject_name, const X509** p_certificate);
/*!
   * \fn int get_private_key(const std::string& p_certificate_id, const EVP_PKEY** p_private_key);
   * \brief Retrive the private key of the specified certificate
@@ -70,7 +73,7 @@ public: /*! \publicsection */

  int get_certificate_pem(const std::string& p_certificate_id, std::string& p_certificate_pem);

  virtual int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key);
  int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, std::string& p_certificate_id, const certs_db_record** p_record);

  /*!
   * \fn int int clear();
@@ -84,14 +87,15 @@ public: /*! \publicsection */

private: /*! \privatesection */
  /*!
   * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record);
   * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const certs_db_record** p_record);
   * \brief Retrive the specified certificate either from memory of from storage location
   * \param[in] p_certificate_name The certificate name
   * \param[in] p_private_key_name The certificate's private key name
   * \param[in] p_private_key_name The certificate's private key name, in PKCS#8 format
   * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption
   * \param[out] p_record A reference to the certificate record
   * \return 0 on success, -1 otherwise
   */
  int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record);
  int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const certs_db_record** p_record);
  /*!
   * \fn int load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record);
   * \brief Retrive the specified certificate either from memory of from storage location
Loading