[omniORB] Feature Proposal: Support selecting the TLS protocol version

Weweler, Yves-Noel Y.Weweler at insiders-technologies.de
Tue Jan 2 13:18:30 UTC 2024


Hi,

We have certain requirements that force us to ensure that we can force specific TLS protocol versions.
First I tried doing this using an openssl configuration file. However, I noticed that within src/lib/omniORB/orbcore/ssl/sslContext.cc the TLS version configuration is overwritten.
```
void
sslContext::set_supported_versions() {
  SSL_CTX_set_options(pd_ctx,
                      SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
                      SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
}
```
Do you have any suggestions on how to force specific protocol versions?


Alternatively, I would like to propose that we add additional configuration to omniorb that behaves similar to `cipher_list`.
Essentially, I would like to be able to set the protocol version using the orb specific configurations as well as using the python interface.

According to the openssl wiki setting the version using options is deprecated. Hence, I suggest we adopt the min and max approach of configuration.

  *   https://wiki.openssl.org/index.php/List_of_SSL_OP_Flags
These options are deprecated as of 1.1.0, use SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version() instead.

Sadly, my understanding of the omniorb codebase is rather limited at the moment, hence writing appropriate tests and getting all locations correct is currently out of reach for me.
Nevertheless, I prepared a small patch as a sketch for my proposal. (I never compiled it and it does not yet cover Python. Just to show my idea!)

Do you think that my approach is worth implementing?

Best regards,
Yves-Noel Weweler



Index: include/omniORB4/sslContext.h
===================================================================
--- include/omniORB4/sslContext.h        (Revision 6674)
+++ include/omniORB4/sslContext.h     (Arbeitskopie)
@@ -101,6 +101,19 @@
   static _core_attr CORBA::Boolean full_peerdetails;
+  // Map of string to OpenSSL version enumerators
+  static std::map<std::string, int> ssl_version_string_to_enum_mapping = {
+      {"SSL3_VERSION", SSL3_VERSION},
+      {"TLS1_VERSION", TLS1_VERSION},
+      {"TLS1_1_VERSION", TLS1_1_VERSION},
+      {"TLS1_2_VERSION", TLS1_2_VERSION},
+      {"TLS1_3_VERSION", TLS1_3_VERSION},
+      {"DTLS1_VERSION", DTLS1_VERSION},
+      {"DTLS1_2_VERSION", DTLS1_2_VERSION}
+  };
+  static int convert_ssl_version_string_to_enum(CORBA::String_var versionString);
+  static CORBA::String_var convert_enum_to_ssl_version_string(int enum);
+
   class PeerDetails {
   public:
     inline PeerDetails(SSL* s, X509* c, CORBA::Boolean v)
@@ -150,6 +163,8 @@
   void update_CA(const char* cafile, const char* capath);
   void update_key(const char* keyfile, const char* password);
   void update_cipher_list(const char* cipher_list);
+  void update_min_protocol_version(int version);
+  void update_max_protocol_version(int version);
   void update_verify_mode(int mode, int mode_incoming, omni_verify_cb callback);
   void update_info_cb(omni_info_cb callback);
@@ -179,7 +194,7 @@

   //
   // Virtual functions that populate the SSL_CTX in pd_ctx. Subclasses
-  // may override these if required. Thse are called while holding
+  // may override these if required. These are called while holding
   // pd_ctx_lock.
   SSL_CTX* get_SSL_CTX() const
@@ -193,12 +208,8 @@
   virtual SSL_METHOD* set_method();
   // Method to pass to SSL_CTX_new. Defaults to return TLS_method().
-  virtual void set_supported_versions();
-  // Default to
-  //   SSL_CTX_set_options(ssl_ctx,
-  //                       SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
-  //                       SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
-  // That is, only accept TLS 1.2 or later.
+  virtual void set_min_protocol_version(int version);
+  virtual void set_max_protocol_version(int version);
   virtual void set_CA();
   // Set CA details. Calls both SSL_CTX_load_verify_locations and
@@ -239,6 +250,8 @@
   CORBA::String_var pd_password;
   CORBA::String_var pd_password_in_ctx;
   CORBA::String_var pd_cipher_list;
+  int               pd_min_protocol_version;
+  int               pd_max_protocol_version;
   int               pd_verify_mode;
   int               pd_verify_mode_incoming;
   omni_verify_cb    pd_verify_cb;
Index: sample.cfg
===================================================================
--- sample.cfg    (Revision 6674)
+++ sample.cfg (Arbeitskopie)
@@ -326,6 +326,8 @@
# sslCAFile
# sslCAPath
# sslCipherList
+# sslMinProtocolVersion
+# sslMaxProtocolVersion
# sslKeyFile
# sslKeyPassword
# sslVerifyMode
@@ -349,6 +351,16 @@
#   sslCipherList specifies the string form of acceptable ciphers. See
#   the OpenSSL ciphers(1) manual page for details.
#
+#   sslMinProtocolVersion specifies the minimum protocol version to use.
+#   Currently supported versions are SSL3_VERSION, TLS1_VERSION,
+#   TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION for TLS and
+#   DTLS1_VERSION, DTLS1_2_VERSION for DTLS.
+#
+#   sslMaxProtocolVersion specifies the maximum protocol version to use.
+#   Currently supported versions are SSL3_VERSION, TLS1_VERSION,
+#   TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION for TLS and
+#   DTLS1_VERSION, DTLS1_2_VERSION for DTLS.
+#
#   sslKeyFile specifies the file containing the SSL key.
#
#   sslKeyPassword specifies the password to unlock the key.
Index: src/lib/omniORB/orbcore/ssl/sslContext.cc
===================================================================
--- src/lib/omniORB/orbcore/ssl/sslContext.cc   (Revision 6674)
+++ src/lib/omniORB/orbcore/ssl/sslContext.cc (Arbeitskopie)
@@ -53,6 +53,8 @@
const char*    sslContext::key_file                    = 0;
const char*    sslContext::key_file_password           = 0;
const char*    sslContext::cipher_list                 = 0;
+int            sslContext::min_protocol_version       = TLS1_2_VERSION;
+int            sslContext::max_protocol_version       = TLS1_3_VERSION;
int            sslContext::verify_mode                 =
                             (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
int            sslContext::verify_mode_incoming        = -1;
@@ -136,6 +138,21 @@
 /////////////////////////////////////////////////////////////////////////
void
+sslContext::update_min_protocol_version(int version)
+{
+  omni_tracedmutex_lock sync(pd_ctx_lock);
+  pd_min_protocol_version = version;
+}
+
+/////////////////////////////////////////////////////////////////////////
+void
+sslContext::update_max_protocol_version(int version)
+{
+  omni_tracedmutex_lock sync(pd_ctx_lock);
+  pd_max_protocol_version = version;
+}
+/////////////////////////////////////////////////////////////////////////
+void
sslContext::update_verify_mode(int mode, int mode_incoming,
                                omni_verify_cb callback)
{
@@ -178,7 +195,8 @@
                     CORBA::COMPLETED_NO);
     }
-    set_supported_versions();
+    set_min_protocol_version();
+    set_max_protocol_version();
     set_certificate();
     set_privatekey();
     set_CA();
@@ -208,7 +226,7 @@
   SSL_CTX_set_default_passwd_cb_userdata(pd_ctx, 0);
   SSL_CTX_free(pd_ctx);
   pd_password_in_ctx = (const char*)0;
-
+
   create_ctx();
}
@@ -222,7 +240,7 @@
     // not free it yet.
     if (!(const char*)pd_password_in_ctx)
       pd_password_in_ctx = pd_password._retn();
-
+
     pd_cafile   = certificate_authority_file;
     pd_capath   = certificate_authority_path;
     pd_keyfile  = key_file;
@@ -229,6 +247,8 @@
     pd_password = key_file_password;
   }
   pd_cipher_list          = cipher_list;
+  pd_min_protocol_version   = min_protocol_version;
+  pd_max_protocol_version   = max_protocol_version;
   pd_verify_mode          = verify_mode;
   pd_verify_mode_incoming = verify_mode_incoming;
   pd_verify_cb            = verify_callback;
@@ -276,14 +296,24 @@
 /////////////////////////////////////////////////////////////////////////
void
-sslContext::set_supported_versions() {
-  SSL_CTX_set_options(pd_ctx,
-                      SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
-                      SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
+sslContext::set_min_protocol_version(int version) {
+  if (!int SSL_CTX_set_min_proto_version(pd_ctx, version)) {
+    report_error();
+    OMNIORB_THROW(INITIALIZE, INITIALIZE_TransportError, CORBA::COMPLETED_NO);
+  }
}
 /////////////////////////////////////////////////////////////////////////
void
+sslContext::set_max_protocol_version(int version) {
+  if (!int SSL_CTX_set_max_proto_version(pd_ctx, version)) {
+    report_error();
+    OMNIORB_THROW(INITIALIZE, INITIALIZE_TransportError, CORBA::COMPLETED_NO);
+  }
+}
+
+/////////////////////////////////////////////////////////////////////////
+void
sslContext::set_CA() {
   if (pd_cafile.in() || pd_capath.in()) {
@@ -492,3 +522,19 @@
     log << "OpenSSL: " << (const char*) buf << "\n";
   }
}
+
+static int convert_ssl_version_string_to_enum(CORBA::String_var versionString) {
+  auto it = versionMap.find(versionStr);
+  int version = (it != versionMap.end()) ? it->second : -1;
+  return version;
+}
+
+static CORBA::String_var convert_enum_to_ssl_version_string(int enumerator) {
+  std::map<int, std::string> reversedMap;
+  for (const auto& pair : originalMap) {
+      reversedMap[pair.second] = pair.first;
+  }
+  auto it = reversedMap.find(enumerator);
+  std::string versionString = (it != reversedMap.end()) ? it->second : 'UNKNOWN';
+  return CORBA::string_dup(versionString);
+}
Index: src/lib/omniORB/orbcore/ssl/sslTransportImpl.cc
===================================================================
--- src/lib/omniORB/orbcore/ssl/sslTransportImpl.cc      (Revision 6674)
+++ src/lib/omniORB/orbcore/ssl/sslTransportImpl.cc   (Arbeitskopie)
@@ -272,6 +272,57 @@

 /////////////////////////////////////////////////////////////////////////////
+class sslMinTlsVersionHandler : public orbOptions::Handler {
+public:
+
+  sslMinTlsVersionHandler() :
+    orbOptions::Handler("sslMinTlsVersion",
+                                             "sslMinTlsVersion = <min. protocol version>",
+                                             1,
+                                             "-ORBsslMinTlsVersion <min. protocol version>") {}
+
+  void visit(const char* value, orbOptions::Source)
+  {
+    sslContext::min_protocol_version = SSLContext::ssl_version_string_to_enum(value);
+  }
+
+  void dump(orbOptions::sequenceString& result)
+  {
+    orbOptions::addKVString(key(),
+                                                 sslContext::convert_enum_to_ssl_version_string(sslContext::min_protocol_version),
+                                                 result);
+  }
+};
+
+static sslMinTlsVersionHandler sslMinTlsVersionHandler_;
+
+
+/////////////////////////////////////////////////////////////////////////////
+class sslMaxTlsVersionHandler : public orbOptions::Handler {
+public:
+
+  sslMaxTlsVersionHandler() :
+    orbOptions::Handler("sslMaxTlsVersion",
+                                             "sslMaxTlsVersion = <max. protocol version>",
+                                             1,
+                                             "-ORBsslMaxTlsVersion <max. protocol version>") {}
+
+  void visit(const char* value, orbOptions::Source)
+  {
+    sslContext::max_protocol_version = SSLContext::ssl_version_string_to_enum(value);
+  }
+
+  void dump(orbOptions::sequenceString& result)
+  {
+    orbOptions::addKVString(key(),
+                                                 sslContext::convert_enum_to_ssl_version_string(sslContext::max_protocol_version),
+                                                 result);
+  }
+};
+
+static sslMaxTlsVersionHandler sslMaxTlsVersionHandler_;
+
+/////////////////////////////////////////////////////////////////////////////
static int
verifyModeValue(const char* key, const char* value, CORBA::Boolean unset_ok)
{
@@ -455,6 +506,8 @@
     orbOptions::singleton().registerHandler(sslKeyFileHandler_);
     orbOptions::singleton().registerHandler(sslKeyPasswordHandler_);
     orbOptions::singleton().registerHandler(sslCipherListHandler_);
+    orbOptions::singleton().registerHandler(sslMinTlsVersionHandler_);
+    orbOptions::singleton().registerHandler(sslMaxTlsVersionHandler_);
     orbOptions::singleton().registerHandler(sslVerifyModeHandler_);
     orbOptions::singleton().registerHandler(sslVerifyModeIncomingHandler_);
     orbOptions::singleton().registerHandler(sslAcceptTimeOutHandler_);


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.omniorb-support.com/pipermail/omniorb-list/attachments/20240102/99e8d0ac/attachment-0001.html>


More information about the omniORB-list mailing list