zeroc-ice 3.8.0 → 3.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/dist/IceRuby/Operation.cpp +22 -6
  3. data/dist/IceRuby/Slice.cpp +1 -1
  4. data/dist/ice/cpp/include/Ice/Communicator.h +4 -4
  5. data/dist/ice/cpp/include/Ice/Config.h +2 -2
  6. data/dist/ice/cpp/include/Ice/Connection.h +3 -3
  7. data/dist/ice/cpp/include/Ice/Endpoint.h +2 -2
  8. data/dist/ice/cpp/include/Ice/Exception.h +1 -1
  9. data/dist/ice/cpp/include/Ice/Initialize.h +1 -1
  10. data/dist/ice/cpp/include/Ice/LocalExceptions.h +22 -1
  11. data/dist/ice/cpp/include/Ice/Logger.h +3 -3
  12. data/dist/ice/cpp/include/Ice/NativePropertiesAdmin.h +2 -0
  13. data/dist/ice/cpp/include/Ice/ObjectAdapter.h +3 -3
  14. data/dist/ice/cpp/include/Ice/ObserverHelper.h +1 -0
  15. data/dist/ice/cpp/include/Ice/OutputStream.h +27 -5
  16. data/dist/ice/cpp/include/Ice/Properties.h +3 -3
  17. data/dist/ice/cpp/include/Ice/Proxy.h +1 -1
  18. data/dist/ice/cpp/include/Ice/SSL/ClientAuthenticationOptions.h +10 -2
  19. data/dist/ice/cpp/include/Ice/SSL/ServerAuthenticationOptions.h +10 -2
  20. data/dist/ice/cpp/include/generated/Ice/BuiltinSequences.h +2 -2
  21. data/dist/ice/cpp/include/generated/Ice/Context.h +2 -2
  22. data/dist/ice/cpp/include/generated/Ice/EndpointTypes.h +2 -2
  23. data/dist/ice/cpp/include/generated/Ice/Identity.h +2 -2
  24. data/dist/ice/cpp/include/generated/Ice/Locator.h +9 -11
  25. data/dist/ice/cpp/include/generated/Ice/LocatorRegistry.h +2 -2
  26. data/dist/ice/cpp/include/generated/Ice/Metrics.h +7 -7
  27. data/dist/ice/cpp/include/generated/Ice/OperationMode.h +2 -2
  28. data/dist/ice/cpp/include/generated/Ice/Process.h +2 -2
  29. data/dist/ice/cpp/include/generated/Ice/PropertiesAdmin.h +2 -2
  30. data/dist/ice/cpp/include/generated/Ice/PropertyDict.h +2 -2
  31. data/dist/ice/cpp/include/generated/Ice/RemoteLogger.h +2 -2
  32. data/dist/ice/cpp/include/generated/Ice/ReplyStatus.h +8 -4
  33. data/dist/ice/cpp/include/generated/Ice/Router.h +7 -7
  34. data/dist/ice/cpp/include/generated/Ice/SliceChecksumDict.h +2 -2
  35. data/dist/ice/cpp/include/generated/Ice/Version.h +2 -2
  36. data/dist/ice/cpp/include/generated/IceDiscovery/Lookup.h +2 -2
  37. data/dist/ice/cpp/include/generated/IceLocatorDiscovery/Lookup.h +2 -2
  38. data/dist/ice/cpp/src/Ice/CollocatedRequestHandler.cpp +5 -3
  39. data/dist/ice/cpp/src/Ice/ConnectionFactory.h +8 -8
  40. data/dist/ice/cpp/src/Ice/ConnectionI.cpp +28 -11
  41. data/dist/ice/cpp/src/Ice/ConnectionI.h +1 -1
  42. data/dist/ice/cpp/src/Ice/Demangle.cpp +1 -0
  43. data/dist/ice/cpp/src/Ice/FileUtil.cpp +3 -67
  44. data/dist/ice/cpp/src/Ice/FileUtil.h +0 -3
  45. data/dist/ice/cpp/src/Ice/IPEndpointI.cpp +4 -0
  46. data/dist/ice/cpp/src/Ice/IncomingRequest.cpp +1 -1
  47. data/dist/ice/cpp/src/Ice/InputStream.cpp +28 -17
  48. data/dist/ice/cpp/src/Ice/LocalException.cpp +1 -1
  49. data/dist/ice/cpp/src/Ice/LocalExceptions.cpp +6 -0
  50. data/dist/ice/cpp/src/Ice/OutgoingAsync.cpp +1 -1
  51. data/dist/ice/cpp/src/Ice/OutgoingResponse.cpp +127 -127
  52. data/dist/ice/cpp/src/Ice/OutgoingResponseInternal.h +21 -0
  53. data/dist/ice/cpp/src/Ice/OutputStream.cpp +80 -115
  54. data/dist/ice/cpp/src/Ice/PropertyNames.cpp +3 -2
  55. data/dist/ice/cpp/src/Ice/ProxyFunctions.cpp +4 -4
  56. data/dist/ice/cpp/src/Ice/Reference.cpp +15 -15
  57. data/dist/ice/cpp/src/Ice/ReferenceFactory.cpp +16 -13
  58. data/dist/ice/cpp/src/Ice/ResourceConfig.h +2 -2
  59. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.cpp +29 -20
  60. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.h +1 -2
  61. data/dist/ice/cpp/src/Ice/SSL/OpenSSLTransceiverI.cpp +14 -3
  62. data/dist/ice/cpp/src/Ice/SSL/RFC2253.cpp +3 -3
  63. data/dist/ice/cpp/src/Ice/SSL/SSLEndpointI.cpp +1 -1
  64. data/dist/ice/cpp/src/Ice/SSL/SSLEngine.h +4 -10
  65. data/dist/ice/cpp/src/Ice/SSL/SSLUtil.cpp +21 -2
  66. data/dist/ice/cpp/src/Ice/SSL/SSLUtil.h +15 -1
  67. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.cpp +67 -48
  68. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.h +1 -5
  69. data/dist/ice/cpp/src/Ice/SSL/SchannelTransceiverI.cpp +14 -2
  70. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.cpp +111 -15
  71. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.h +7 -2
  72. data/dist/ice/cpp/src/Ice/SSL/SecureTransportTransceiverI.h +1 -1
  73. data/dist/ice/cpp/src/Ice/SSL/SecureTransportUtil.cpp +3 -16
  74. data/dist/ice/cpp/src/Ice/SSL/TrustManager.cpp +12 -1
  75. data/dist/ice/cpp/src/Ice/ServantManager.h +1 -1
  76. data/dist/ice/cpp/src/Ice/StringConverter.cpp +4 -0
  77. data/dist/ice/cpp/src/Ice/TcpEndpointI.cpp +2 -2
  78. data/dist/ice/cpp/src/Ice/UdpEndpointI.cpp +2 -2
  79. data/dist/ice/cpp/src/Ice/WSAcceptor.cpp +8 -3
  80. data/dist/ice/cpp/src/Ice/WSAcceptor.h +5 -1
  81. data/dist/ice/cpp/src/Ice/WSEndpoint.cpp +45 -2
  82. data/dist/ice/cpp/src/Ice/WSTransceiver.cpp +118 -7
  83. data/dist/ice/cpp/src/Ice/WSTransceiver.h +12 -1
  84. data/dist/ice/cpp/src/Ice/generated/BuiltinSequences.cpp +2 -2
  85. data/dist/ice/cpp/src/Ice/generated/Context.cpp +2 -2
  86. data/dist/ice/cpp/src/Ice/generated/EndpointTypes.cpp +2 -2
  87. data/dist/ice/cpp/src/Ice/generated/Identity.cpp +2 -2
  88. data/dist/ice/cpp/src/Ice/generated/Locator.cpp +2 -2
  89. data/dist/ice/cpp/src/Ice/generated/LocatorRegistry.cpp +2 -2
  90. data/dist/ice/cpp/src/Ice/generated/Metrics.cpp +2 -2
  91. data/dist/ice/cpp/src/Ice/generated/OperationMode.cpp +2 -2
  92. data/dist/ice/cpp/src/Ice/generated/Process.cpp +2 -2
  93. data/dist/ice/cpp/src/Ice/generated/PropertiesAdmin.cpp +2 -2
  94. data/dist/ice/cpp/src/Ice/generated/PropertyDict.cpp +2 -2
  95. data/dist/ice/cpp/src/Ice/generated/RemoteLogger.cpp +2 -2
  96. data/dist/ice/cpp/src/Ice/generated/ReplyStatus.cpp +4 -2
  97. data/dist/ice/cpp/src/Ice/generated/Router.cpp +2 -2
  98. data/dist/ice/cpp/src/Ice/generated/SliceChecksumDict.cpp +2 -2
  99. data/dist/ice/cpp/src/Ice/generated/Version.cpp +2 -2
  100. data/dist/ice/cpp/src/IceDiscovery/LocatorI.cpp +2 -2
  101. data/dist/ice/cpp/src/IceDiscovery/LookupI.cpp +4 -3
  102. data/dist/ice/cpp/src/IceDiscovery/LookupI.h +2 -1
  103. data/dist/ice/cpp/src/IceDiscovery/generated/Lookup.cpp +2 -2
  104. data/dist/ice/cpp/src/IceLocatorDiscovery/PluginI.cpp +6 -18
  105. data/dist/ice/cpp/src/IceLocatorDiscovery/generated/Lookup.cpp +2 -2
  106. data/dist/ice/cpp/src/Slice/DocCommentParser.cpp +6 -6
  107. data/dist/ice/cpp/src/Slice/DocCommentParser.h +4 -2
  108. data/dist/ice/cpp/src/Slice/FileTracker.h +1 -0
  109. data/dist/ice/cpp/src/Slice/Grammar.cpp +261 -264
  110. data/dist/ice/cpp/src/Slice/MetadataValidation.cpp +39 -7
  111. data/dist/ice/cpp/src/Slice/MetadataValidation.h +3 -2
  112. data/dist/ice/cpp/src/Slice/Parser.cpp +192 -155
  113. data/dist/ice/cpp/src/Slice/Parser.h +44 -9
  114. data/dist/ice/cpp/src/Slice/Preprocessor.cpp +76 -20
  115. data/dist/ice/cpp/src/Slice/Preprocessor.h +0 -1
  116. data/dist/ice/cpp/src/Slice/Scanner.cpp +1 -1
  117. data/dist/ice/cpp/src/Slice/SliceUtil.cpp +44 -58
  118. data/dist/ice/cpp/src/Slice/StringLiteralUtil.cpp +3 -10
  119. data/dist/ice/cpp/src/Slice/Util.h +7 -3
  120. data/dist/ice/cpp/src/slice2rb/Main.cpp +2 -2
  121. data/dist/ice/cpp/src/slice2rb/Ruby.cpp +1 -1
  122. data/dist/ice/cpp/src/slice2rb/RubyUtil.cpp +10 -8
  123. data/dist/ice/cpp/src/slice2rb/RubyUtil.h +10 -13
  124. data/dist/ice/mcpp/directive.c +5 -2
  125. data/dist/ice/mcpp/mcpp_main.c +1 -1
  126. data/dist/ice/mcpp/support.c +6 -6
  127. data/dist/ice/mcpp/system.c +5 -5
  128. data/dist/ice/slice/Ice/Identity.ice +3 -0
  129. data/dist/ice/slice/Ice/Locator.ice +6 -5
  130. data/dist/ice/slice/Ice/LocatorRegistry.ice +3 -0
  131. data/dist/ice/slice/Ice/Metrics.ice +1 -1
  132. data/dist/ice/slice/Ice/OperationMode.ice +8 -0
  133. data/dist/ice/slice/Ice/Process.ice +3 -0
  134. data/dist/ice/slice/Ice/ReplyStatus.ice +13 -0
  135. data/dist/lib/Glacier2/Metrics.rb +1 -1
  136. data/dist/lib/Glacier2/PermissionsVerifier.rb +3 -3
  137. data/dist/lib/Glacier2/Router.rb +8 -8
  138. data/dist/lib/Glacier2/SSLInfo.rb +1 -1
  139. data/dist/lib/Glacier2/Session.rb +15 -15
  140. data/dist/lib/Ice/BuiltinSequences.rb +1 -1
  141. data/dist/lib/Ice/Context.rb +1 -1
  142. data/dist/lib/Ice/EndpointTypes.rb +1 -1
  143. data/dist/lib/Ice/Identity.rb +1 -1
  144. data/dist/lib/Ice/LocalExceptions.rb +3 -0
  145. data/dist/lib/Ice/Locator.rb +5 -5
  146. data/dist/lib/Ice/LocatorRegistry.rb +4 -4
  147. data/dist/lib/Ice/Metrics.rb +7 -7
  148. data/dist/lib/Ice/OperationMode.rb +1 -1
  149. data/dist/lib/Ice/Process.rb +3 -3
  150. data/dist/lib/Ice/PropertiesAdmin.rb +4 -4
  151. data/dist/lib/Ice/PropertyDict.rb +1 -1
  152. data/dist/lib/Ice/ProxyFunctions.rb +8 -4
  153. data/dist/lib/Ice/RemoteLogger.rb +6 -6
  154. data/dist/lib/Ice/ReplyStatus.rb +3 -2
  155. data/dist/lib/Ice/Router.rb +5 -5
  156. data/dist/lib/Ice/SliceChecksumDict.rb +1 -1
  157. data/dist/lib/Ice/Version.rb +1 -1
  158. data/dist/lib/IceBox/ServiceManager.rb +8 -8
  159. data/dist/lib/IceGrid/Admin.rb +83 -83
  160. data/dist/lib/IceGrid/Descriptor.rb +1 -1
  161. data/dist/lib/IceGrid/Exception.rb +1 -1
  162. data/dist/lib/IceGrid/FileParser.rb +2 -2
  163. data/dist/lib/IceGrid/Registry.rb +13 -13
  164. data/dist/lib/IceGrid/Session.rb +6 -6
  165. data/dist/lib/IceGrid/UserAccountMapper.rb +2 -2
  166. data/dist/lib/IceStorm/IceStorm.rb +16 -16
  167. data/dist/lib/IceStorm/Metrics.rb +1 -1
  168. data/ice.gemspec +1 -1
  169. metadata +2 -1
@@ -20,7 +20,6 @@
20
20
  #include <openssl/err.h>
21
21
  #include <openssl/ssl.h>
22
22
 
23
- #include <iostream>
24
23
  #include <mutex>
25
24
 
26
25
  using namespace std;
@@ -41,10 +40,14 @@ namespace
41
40
  {
42
41
  bool defaultVerificationCallback(bool ok, X509_STORE_CTX*, const Ice::SSL::ConnectionInfoPtr&) { return ok; }
43
42
 
43
+ /// Returns nullptr if SSL_CTX_new fails; the caller is responsible for checking the return value.
44
44
  SSL_CTX* defaultSSLContextSelectionCallback(const string&)
45
45
  {
46
46
  SSL_CTX* defaultSSLContext = SSL_CTX_new(TLS_method());
47
- SSL_CTX_set_default_verify_paths(defaultSSLContext);
47
+ if (defaultSSLContext)
48
+ {
49
+ SSL_CTX_set_default_verify_paths(defaultSSLContext);
50
+ }
48
51
  return defaultSSLContext;
49
52
  }
50
53
  }
@@ -90,7 +93,13 @@ OpenSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::
90
93
  }
91
94
  SSL_set_bio(_ssl, bio, bio);
92
95
 
93
- SSL_set_ex_data(_ssl, 0, this);
96
+ if (!SSL_set_ex_data(_ssl, 0, this))
97
+ {
98
+ throw SecurityException(
99
+ __FILE__,
100
+ __LINE__,
101
+ "SSL transport: error setting ex data:\n" + _engine->sslErrors());
102
+ }
94
103
  SSL_set_verify(_ssl, SSL_get_verify_mode(_ssl), Ice_SSL_opensslVerifyCallback);
95
104
  // Enable SNI by default for outgoing connections. The SNI host name is always empty for incoming connections.
96
105
  if (!_host.empty() && !IceInternal::isIpAddress(_host) && !SSL_set_tlsext_host_name(_ssl, _host.c_str()))
@@ -108,6 +117,8 @@ OpenSSL::TransceiverI::initialize(IceInternal::Buffer& readBuffer, IceInternal::
108
117
 
109
118
  while (!SSL_is_init_finished(_ssl))
110
119
  {
120
+ // Clear the error queue before the TLS I/O operation; SSL_get_error requires an empty queue to work reliably.
121
+ ERR_clear_error();
111
122
  int ret = _incoming ? SSL_accept(_ssl) : SSL_connect(_ssl);
112
123
 
113
124
  if (ret <= 0)
@@ -146,7 +146,7 @@ RFC2253::unescape(const string& data)
146
146
  {
147
147
  throw ParseException(__FILE__, __LINE__, "unescape: invalid escape sequence");
148
148
  }
149
- if (special.find(data[pos]) != string::npos || data[pos] != '\\' || data[pos] != '"')
149
+ if (special.find(data[pos]) != string::npos || data[pos] == '\\' || data[pos] == '"')
150
150
  {
151
151
  result += data[pos];
152
152
  ++pos;
@@ -185,7 +185,7 @@ static char
185
185
  unescapeHex(const string& data, size_t pos)
186
186
  {
187
187
  assert(pos < data.size());
188
- if (pos + 2 >= data.size())
188
+ if (pos + 2 > data.size())
189
189
  {
190
190
  throw Ice::ParseException(__FILE__, __LINE__, "unescape: invalid hex pair");
191
191
  }
@@ -431,7 +431,7 @@ parsePair(const string& data, size_t& pos)
431
431
  throw Ice::ParseException(__FILE__, __LINE__, "invalid escape format (unexpected end of data)");
432
432
  }
433
433
 
434
- if (special.find(data[pos]) != string::npos || data[pos] != '\\' || data[pos] != '"')
434
+ if (special.find(data[pos]) != string::npos || data[pos] == '\\' || data[pos] == '"')
435
435
  {
436
436
  result += data[pos];
437
437
  ++pos;
@@ -232,7 +232,7 @@ Ice::SSL::EndpointI::endpoint(const IceInternal::EndpointIPtr& delEndp) const
232
232
  {
233
233
  if (delEndp.get() == _delegate.get())
234
234
  {
235
- return dynamic_pointer_cast<EndpointI>(const_cast<EndpointI*>(this)->shared_from_this());
235
+ return static_pointer_cast<EndpointI>(const_cast<EndpointI*>(this)->shared_from_this());
236
236
  }
237
237
  else
238
238
  {
@@ -23,7 +23,7 @@ namespace Ice::SSL
23
23
  {
24
24
  public:
25
25
  SSLEngine(const IceInternal::InstancePtr&);
26
- ~SSLEngine();
26
+ virtual ~SSLEngine();
27
27
 
28
28
  [[nodiscard]] Ice::LoggerPtr getLogger() const;
29
29
  [[nodiscard]] Ice::PropertiesPtr getProperties() const;
@@ -34,9 +34,6 @@ namespace Ice::SSL
34
34
  // Setup the engine.
35
35
  virtual void initialize() = 0;
36
36
 
37
- // Destroy the engine.
38
- virtual void destroy() = 0;
39
-
40
37
  // Verify peer certificate.
41
38
  virtual void verifyPeer(const ConnectionInfoPtr&) const;
42
39
 
@@ -57,12 +54,9 @@ namespace Ice::SSL
57
54
  private:
58
55
  const IceInternal::InstancePtr _instance;
59
56
  const TrustManagerPtr _trustManager;
60
-
61
- std::string _password;
62
-
63
- bool _checkCertName;
64
- int _verifyPeer;
65
- int _securityTraceLevel;
57
+ bool _checkCertName{false};
58
+ int _verifyPeer{0};
59
+ int _securityTraceLevel{0};
66
60
  std::string _securityTraceCategory;
67
61
  const bool _revocationCheckCacheOnly{false};
68
62
  const int _revocationCheck{0};
@@ -67,6 +67,12 @@ Ice::SSL::parseBytes(const string& arg, vector<unsigned char>& buffer)
67
67
  }
68
68
  v = s.str();
69
69
 
70
+ // Each byte requires exactly two hex digits; reject odd-length strings.
71
+ if (v.size() % 2 != 0)
72
+ {
73
+ return false;
74
+ }
75
+
70
76
  // Convert the bytes.
71
77
  for (size_t i = 0, length = v.size(); i + 2 <= length;)
72
78
  {
@@ -86,7 +92,12 @@ Ice::SSL::readFile(const string& file, vector<char>& buffer)
86
92
  }
87
93
 
88
94
  is.seekg(0, is.end);
89
- buffer.resize(static_cast<size_t>(is.tellg()));
95
+ streampos size = is.tellg();
96
+ if (size == streampos{-1})
97
+ {
98
+ throw CertificateReadException(__FILE__, __LINE__, "error determining file size: " + file);
99
+ }
100
+ buffer.resize(static_cast<size_t>(size));
90
101
  is.seekg(0, is.beg);
91
102
 
92
103
  if (!buffer.empty())
@@ -345,7 +356,7 @@ Ice::SSL::getSubjectAltNames(PCCERT_CONTEXT cert)
345
356
  os << ".";
346
357
  }
347
358
  }
348
- altNames.push_back(make_pair(AltNAmeIP, os.str()));
359
+ altNames.push_back(make_pair(AltNameIP, os.str()));
349
360
  }
350
361
  //
351
362
  // TODO IPv6 Address support.
@@ -473,6 +484,10 @@ namespace
473
484
  string convertX509NameToString(X509_name_st* name)
474
485
  {
475
486
  BIO* out = BIO_new(BIO_s_mem());
487
+ if (!out)
488
+ {
489
+ throw CertificateEncodingException(__FILE__, __LINE__, "SSL transport: error allocating BIO");
490
+ }
476
491
  X509_NAME_print_ex(out, name, 0, XN_FLAG_RFC2253);
477
492
  BUF_MEM* p;
478
493
  BIO_get_mem_ptr(out, &p);
@@ -621,6 +636,10 @@ string
621
636
  Ice::SSL::encodeCertificate(X509* certificate)
622
637
  {
623
638
  BIO* out = BIO_new(BIO_s_mem());
639
+ if (!out)
640
+ {
641
+ throw CertificateEncodingException(__FILE__, __LINE__, "SSL transport: error allocating BIO");
642
+ }
624
643
  int i = PEM_write_bio_X509(out, certificate);
625
644
  if (i <= 0)
626
645
  {
@@ -34,7 +34,7 @@ namespace Ice::SSL
34
34
  const int AltNameDirectory = 4;
35
35
  // const int AltNameEDIPartyName = 5;
36
36
  const int AltNameURL = 6;
37
- const int AltNAmeIP = 7;
37
+ const int AltNameIP = 7;
38
38
  // const AltNameObjectIdentifier = 8;
39
39
 
40
40
  // Read a file into memory buffer.
@@ -46,6 +46,8 @@ namespace Ice::SSL
46
46
  // Determine if a directory exists, with an optional parent directory.
47
47
  std::optional<std::string> resolveDirPath(const std::string& path, const std::string& parentDir = "");
48
48
 
49
+ /// Parse a hex string (e.g., "AB:CD:EF" or "ABCDEF") into a byte buffer. Spaces and colons are ignored.
50
+ /// @return `false` if the string contains invalid characters or has an odd number of hex digits.
49
51
  bool parseBytes(const std::string&, std::vector<unsigned char>&);
50
52
 
51
53
  #if defined(ICE_USE_SCHANNEL)
@@ -57,6 +59,10 @@ namespace Ice::SSL
57
59
  {
58
60
  public:
59
61
  ScopedCertificate(PCCERT_CONTEXT certificate) : _certificate(certificate) {}
62
+ ScopedCertificate(const ScopedCertificate&) = delete;
63
+ ScopedCertificate& operator=(const ScopedCertificate&) = delete;
64
+ ScopedCertificate(ScopedCertificate&&) = delete;
65
+ ScopedCertificate& operator=(ScopedCertificate&&) = delete;
60
66
  ~ScopedCertificate();
61
67
  PCCERT_CONTEXT get() const { return _certificate; }
62
68
 
@@ -74,6 +80,10 @@ namespace Ice::SSL
74
80
  {
75
81
  public:
76
82
  ScopedCertificate(SecCertificateRef certificate) : _certificate(certificate) {}
83
+ ScopedCertificate(const ScopedCertificate&) = delete;
84
+ ScopedCertificate& operator=(const ScopedCertificate&) = delete;
85
+ ScopedCertificate(ScopedCertificate&&) = delete;
86
+ ScopedCertificate& operator=(ScopedCertificate&&) = delete;
77
87
  ~ScopedCertificate();
78
88
  [[nodiscard]] SecCertificateRef get() const { return _certificate; }
79
89
 
@@ -91,6 +101,10 @@ namespace Ice::SSL
91
101
  {
92
102
  public:
93
103
  ScopedCertificate(X509* certificate) : _certificate(certificate) {}
104
+ ScopedCertificate(const ScopedCertificate&) = delete;
105
+ ScopedCertificate& operator=(const ScopedCertificate&) = delete;
106
+ ScopedCertificate(ScopedCertificate&&) = delete;
107
+ ScopedCertificate& operator=(ScopedCertificate&&) = delete;
94
108
  ~ScopedCertificate();
95
109
  [[nodiscard]] X509* get() const { return _certificate; }
96
110
 
@@ -14,7 +14,6 @@
14
14
 
15
15
  #include <wincrypt.h>
16
16
 
17
- #include <iostream>
18
17
  #include <mutex>
19
18
 
20
19
  #ifndef SECURITY_FLAG_IGNORE_CERT_CN_INVALID
@@ -668,7 +667,7 @@ namespace
668
667
  vector<string> dnsNames;
669
668
  for (vector<pair<int, string>>::const_iterator p = subjectAltNames.begin(); p != subjectAltNames.end(); ++p)
670
669
  {
671
- if (p->first == AltNAmeIP)
670
+ if (p->first == AltNameIP)
672
671
  {
673
672
  ipAddresses.push_back(IceInternal::toLower(p->second));
674
673
  }
@@ -693,7 +692,19 @@ namespace
693
692
  // name dnsNames.
694
693
  if (dnsNames.empty())
695
694
  {
696
- auto d = DistinguishedName(getSubjectName(cert));
695
+ DistinguishedName d{list<pair<string, string>>{}};
696
+ try
697
+ {
698
+ d = DistinguishedName(getSubjectName(cert));
699
+ }
700
+ catch (const Ice::ParseException& ex)
701
+ {
702
+ throw SecurityException(
703
+ __FILE__,
704
+ __LINE__,
705
+ "SSL transport: certificate verification failure:\nunable to parse certificate DN:\n" +
706
+ string{ex.what()});
707
+ }
697
708
  string dn = IceInternal::toLower(string(d));
698
709
  string cn = "cn=" + addrLower;
699
710
  string::size_type pos = dn.find(cn);
@@ -732,6 +743,56 @@ Schannel::SSLEngine::SSLEngine(const IceInternal::InstancePtr& instance)
732
743
  {
733
744
  }
734
745
 
746
+ Schannel::SSLEngine::~SSLEngine()
747
+ {
748
+ // Best-effort cleanup. We catch every exception (e.g. std::bad_alloc from the per-cert vector
749
+ // allocation below) so nothing escapes the destructor and triggers std::terminate.
750
+ try
751
+ {
752
+ if (_chainEngine && _chainEngine != HCCE_CURRENT_USER && _chainEngine != HCCE_LOCAL_MACHINE)
753
+ {
754
+ CertFreeCertificateChainEngine(_chainEngine);
755
+ }
756
+
757
+ if (_rootStore)
758
+ {
759
+ CertCloseStore(_rootStore, 0);
760
+ }
761
+
762
+ for (vector<PCCERT_CONTEXT>::const_iterator i = _importedCerts.begin(); i != _importedCerts.end(); ++i)
763
+ {
764
+ // Retrieve the certificate CERT_KEY_PROV_INFO_PROP_ID property, we use the CRYPT_KEY_PROV_INFO data to
765
+ // remove the key set associated with the certificate.
766
+ DWORD length = 0;
767
+ if (!CertGetCertificateContextProperty(*i, CERT_KEY_PROV_INFO_PROP_ID, 0, &length))
768
+ {
769
+ continue;
770
+ }
771
+ vector<char> buf(length);
772
+ if (!CertGetCertificateContextProperty(*i, CERT_KEY_PROV_INFO_PROP_ID, &buf[0], &length))
773
+ {
774
+ continue;
775
+ }
776
+ CRYPT_KEY_PROV_INFO* key = reinterpret_cast<CRYPT_KEY_PROV_INFO*>(&buf[0]);
777
+ HCRYPTPROV prov = 0;
778
+ CryptAcquireContextW(&prov, key->pwszContainerName, key->pwszProvName, key->dwProvType, CRYPT_DELETEKEYSET);
779
+ }
780
+
781
+ for (vector<PCCERT_CONTEXT>::const_iterator i = _allCerts.begin(); i != _allCerts.end(); ++i)
782
+ {
783
+ CertFreeCertificateContext(*i);
784
+ }
785
+
786
+ for (vector<HCERTSTORE>::const_iterator i = _stores.begin(); i != _stores.end(); ++i)
787
+ {
788
+ CertCloseStore(*i, 0);
789
+ }
790
+ }
791
+ catch (...)
792
+ {
793
+ }
794
+ }
795
+
735
796
  void
736
797
  Schannel::SSLEngine::initialize()
737
798
  {
@@ -969,7 +1030,7 @@ Schannel::SSLEngine::initialize()
969
1030
  if (strcmp(keyInfo->Algorithm.pszObjId, szOID_RSA_RSA))
970
1031
  {
971
1032
  ostringstream os;
972
- os << "SSL transport: error unknow key algorithm: '" << keyInfo->Algorithm.pszObjId << "'";
1033
+ os << "SSL transport: unknown key algorithm: '" << keyInfo->Algorithm.pszObjId << "'";
973
1034
  throw InitializationException(__FILE__, __LINE__, os.str());
974
1035
  }
975
1036
 
@@ -1199,49 +1260,6 @@ Schannel::SSLEngine::getCipherName(ALG_ID cipher) const
1199
1260
  }
1200
1261
  }
1201
1262
 
1202
- void
1203
- Schannel::SSLEngine::destroy()
1204
- {
1205
- if (_chainEngine && _chainEngine != HCCE_CURRENT_USER && _chainEngine != HCCE_LOCAL_MACHINE)
1206
- {
1207
- CertFreeCertificateChainEngine(_chainEngine);
1208
- }
1209
-
1210
- if (_rootStore)
1211
- {
1212
- CertCloseStore(_rootStore, 0);
1213
- }
1214
-
1215
- for (vector<PCCERT_CONTEXT>::const_iterator i = _importedCerts.begin(); i != _importedCerts.end(); ++i)
1216
- {
1217
- // Retrieve the certificate CERT_KEY_PROV_INFO_PROP_ID property, we use the CRYPT_KEY_PROV_INFO data to remove
1218
- // the key set associated with the certificate.
1219
- DWORD length = 0;
1220
- if (!CertGetCertificateContextProperty(*i, CERT_KEY_PROV_INFO_PROP_ID, 0, &length))
1221
- {
1222
- continue;
1223
- }
1224
- vector<char> buf(length);
1225
- if (!CertGetCertificateContextProperty(*i, CERT_KEY_PROV_INFO_PROP_ID, &buf[0], &length))
1226
- {
1227
- continue;
1228
- }
1229
- CRYPT_KEY_PROV_INFO* key = reinterpret_cast<CRYPT_KEY_PROV_INFO*>(&buf[0]);
1230
- HCRYPTPROV prov = 0;
1231
- CryptAcquireContextW(&prov, key->pwszContainerName, key->pwszProvName, key->dwProvType, CRYPT_DELETEKEYSET);
1232
- }
1233
-
1234
- for (vector<PCCERT_CONTEXT>::const_iterator i = _allCerts.begin(); i != _allCerts.end(); ++i)
1235
- {
1236
- CertFreeCertificateContext(*i);
1237
- }
1238
-
1239
- for (vector<HCERTSTORE>::const_iterator i = _stores.begin(); i != _stores.end(); ++i)
1240
- {
1241
- CertCloseStore(*i, 0);
1242
- }
1243
- }
1244
-
1245
1263
  Ice::SSL::ClientAuthenticationOptions
1246
1264
  Schannel::SSLEngine::createClientAuthenticationOptions(const string& host) const
1247
1265
  {
@@ -1408,7 +1426,8 @@ Schannel::SSLEngine::validationCallback(
1408
1426
  extraPolicyPara.dwAuthType = incoming ? AUTHTYPE_CLIENT : AUTHTYPE_SERVER;
1409
1427
  // Disable because the policy only matches the CN of the certificate, not the SAN.
1410
1428
  extraPolicyPara.fdwChecks = SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
1411
- extraPolicyPara.pwszServerName = const_cast<wchar_t*>(Ice::stringToWstring(host).c_str());
1429
+ wstring hostW = Ice::stringToWstring(host);
1430
+ extraPolicyPara.pwszServerName = const_cast<wchar_t*>(hostW.c_str());
1412
1431
 
1413
1432
  CERT_CHAIN_POLICY_PARA policyPara;
1414
1433
  memset(&policyPara, 0, sizeof(policyPara));
@@ -22,17 +22,13 @@ namespace Ice::SSL::Schannel
22
22
  {
23
23
  public:
24
24
  SSLEngine(const IceInternal::InstancePtr&);
25
+ ~SSLEngine() override;
25
26
 
26
27
  //
27
28
  // Setup the engine.
28
29
  //
29
30
  void initialize() final;
30
31
 
31
- //
32
- // Destroy the engine.
33
- //
34
- void destroy() final;
35
-
36
32
  [[nodiscard]] std::string getCipherName(ALG_ID) const;
37
33
 
38
34
  [[nodiscard]] Ice::SSL::ClientAuthenticationOptions
@@ -124,6 +124,11 @@ Schannel::TransceiverI::sslHandshake(SecBuffer* initialBuffer)
124
124
  {
125
125
  assert(!initialBuffer); // Always null for the initial handshake.
126
126
  _credentials = _localCredentialsSelectionCallback(_incoming ? _adapterName : _host);
127
+
128
+ // Set hRootStore for AcquireCredentialsHandle. Schannel uses hRootStore on the server side to specify
129
+ // the CAs trusted for client authentication (sent in the CertificateRequest message). This is not used
130
+ // for certificate validation — the transport handles validation separately using the chain engine.
131
+ // If the callback already provided an hRootStore, keep it; otherwise fall back to trustedRootCertificates.
127
132
  if (_rootStore && !_credentials.hRootStore)
128
133
  {
129
134
  _credentials.hRootStore = CertDuplicateStore(_rootStore);
@@ -145,8 +150,6 @@ Schannel::TransceiverI::sslHandshake(SecBuffer* initialBuffer)
145
150
  _credentials.paCred = &_allCerts[0];
146
151
  }
147
152
 
148
- _credentials.hRootStore = _rootStore;
149
-
150
153
  err = AcquireCredentialsHandle(
151
154
  0,
152
155
  const_cast<char*>(UNISP_NAME),
@@ -549,6 +552,15 @@ Schannel::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
549
552
  }
550
553
  else if (err == SEC_I_RENEGOTIATE)
551
554
  {
555
+ if (_incoming)
556
+ {
557
+ // Reject peer-initiated TLS renegotiation on the server side: it is a CPU-asymmetric
558
+ // denial-of-service primitive on TLS 1.2 and is removed entirely in TLS 1.3.
559
+ throw ProtocolException(
560
+ __FILE__,
561
+ __LINE__,
562
+ "SSL transport: peer-initiated TLS renegotiation is not supported on the server side.");
563
+ }
552
564
  if (_sslConnectionRenegotiating)
553
565
  {
554
566
  throw ProtocolException(
@@ -9,10 +9,17 @@
9
9
  #include "Ice/Logger.h"
10
10
  #include "Ice/Properties.h"
11
11
  #include "Ice/SSL/SSLException.h"
12
+ #include "Ice/UUID.h"
12
13
  #include "SSLEngine.h"
13
14
  #include "SSLUtil.h"
14
15
  #include "SecureTransportUtil.h"
15
16
 
17
+ #include <cerrno>
18
+ #include <climits>
19
+ #include <cstring>
20
+ #include <unistd.h>
21
+ #include <vector>
22
+
16
23
  // Disable deprecation warnings from SecureTransport APIs
17
24
  #include "../DisableWarnings.h"
18
25
 
@@ -547,6 +554,43 @@ namespace
547
554
  }
548
555
  }
549
556
  }
557
+
558
+ #if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
559
+ // Creates a private temporary directory to hold a short-lived keychain, and returns its path.
560
+ // Uses confstr(_CS_DARWIN_USER_TEMP_DIR) rather than $TMPDIR so the location can't be
561
+ // redirected through the process environment.
562
+ string createTemporaryKeychainDirectory()
563
+ {
564
+ char base[PATH_MAX];
565
+ size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, base, sizeof(base));
566
+ if (len == 0 || len > sizeof(base))
567
+ {
568
+ int error = errno;
569
+
570
+ ostringstream os;
571
+ os << "SSL transport: confstr(_CS_DARWIN_USER_TEMP_DIR) failed";
572
+ if (error != 0)
573
+ {
574
+ os << ": " << strerror(error);
575
+ }
576
+ throw InitializationException(__FILE__, __LINE__, os.str());
577
+ }
578
+
579
+ string tmpl = string{base} + "ice-keychain-XXXXXX";
580
+ vector<char> buffer(tmpl.begin(), tmpl.end());
581
+ buffer.push_back('\0');
582
+
583
+ char* dir = mkdtemp(buffer.data());
584
+ if (dir == nullptr)
585
+ {
586
+ int error = errno;
587
+ ostringstream os;
588
+ os << "SSL transport: mkdtemp failed: " << strerror(error);
589
+ throw InitializationException(__FILE__, __LINE__, os.str());
590
+ }
591
+ return dir;
592
+ }
593
+ #endif
550
594
  }
551
595
 
552
596
  SecureTransport::SSLEngine::SSLEngine(const IceInternal::InstancePtr& instance)
@@ -556,7 +600,25 @@ SecureTransport::SSLEngine::SSLEngine(const IceInternal::InstancePtr& instance)
556
600
  {
557
601
  }
558
602
 
559
- SecureTransport::SSLEngine::~SSLEngine() = default;
603
+ SecureTransport::SSLEngine::~SSLEngine()
604
+ {
605
+ #if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
606
+ if (!_temporaryKeychainDir.empty())
607
+ {
608
+ // Remove the temporary keychain and its enclosing directory created by initialize().
609
+ // The cleanup lives in the destructor (not destroy()) so it also runs when initialize()
610
+ // throws after the directory has been created.
611
+ _chain.reset();
612
+ const string keychainPath = _temporaryKeychainDir + "/ice.keychain";
613
+ UniqueRef<SecKeychainRef> keychain;
614
+ if (SecKeychainOpen(keychainPath.c_str(), &keychain.get()) == noErr && keychain.get())
615
+ {
616
+ SecKeychainDelete(keychain.get());
617
+ }
618
+ rmdir(_temporaryKeychainDir.c_str());
619
+ }
620
+ #endif
621
+ }
560
622
 
561
623
  //
562
624
  // Setup the engine.
@@ -636,6 +698,18 @@ SecureTransport::SSLEngine::initialize()
636
698
  keyFile = *resolved;
637
699
  }
638
700
 
701
+ #if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
702
+ if (keychain.empty())
703
+ {
704
+ // Import the certificate into a temporary keychain rather than the user's login keychain.
705
+ // A private key in the login keychain cannot complete a forward-secret (ECDHE) handshake
706
+ // on the server side. The keychain and its enclosing directory are removed by the destructor.
707
+ _temporaryKeychainDir = createTemporaryKeychainDirectory();
708
+ keychain = _temporaryKeychainDir + "/ice.keychain";
709
+ keychainPassword = Ice::generateUUID();
710
+ }
711
+ #endif
712
+
639
713
  try
640
714
  {
641
715
  _chain.reset(loadCertificateChain(certFile, keyFile, keychain, keychainPassword, password));
@@ -651,14 +725,6 @@ SecureTransport::SSLEngine::initialize()
651
725
  }
652
726
  }
653
727
 
654
- //
655
- // Destroy the engine.
656
- //
657
- void
658
- SecureTransport::SSLEngine::destroy()
659
- {
660
- }
661
-
662
728
  ClientAuthenticationOptions
663
729
  SecureTransport::SSLEngine::createClientAuthenticationOptions(const string& host) const
664
730
  {
@@ -721,15 +787,15 @@ SecureTransport::SSLEngine::createServerAuthenticationOptions() const
721
787
  SSLContextRef
722
788
  SecureTransport::SSLEngine::newContext(bool incoming) const
723
789
  {
724
- SSLContextRef ssl =
725
- SSLCreateContext(kCFAllocatorDefault, incoming ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
726
- if (!ssl)
790
+ UniqueRef<SSLContextRef> ssl(
791
+ SSLCreateContext(kCFAllocatorDefault, incoming ? kSSLServerSide : kSSLClientSide, kSSLStreamType));
792
+ if (!ssl.get())
727
793
  {
728
794
  throw SecurityException(__FILE__, __LINE__, "SSL transport: unable to create SSL context");
729
795
  }
730
796
 
731
797
  OSStatus err = SSLSetSessionOption(
732
- ssl,
798
+ ssl.get(),
733
799
  incoming ? kSSLSessionOptionBreakOnClientAuth : kSSLSessionOptionBreakOnServerAuth,
734
800
  true);
735
801
 
@@ -741,7 +807,34 @@ SecureTransport::SSLEngine::newContext(bool incoming) const
741
807
  "SSL transport: error while setting SSL option:\n" + sslErrorToString(err));
742
808
  }
743
809
 
744
- return ssl;
810
+ // Require TLS 1.2 or later. SecureTransport otherwise negotiates down to TLS 1.0 on macOS.
811
+ err = SSLSetProtocolVersionMin(ssl.get(), kTLSProtocol12);
812
+ if (err != noErr)
813
+ {
814
+ throw SecurityException(
815
+ __FILE__,
816
+ __LINE__,
817
+ "SSL transport: error while setting the minimum protocol version:\n" + sslErrorToString(err));
818
+ }
819
+
820
+ // Enable only forward-secret cipher suites: the Mozilla "Intermediate" recommendation for TLS 1.2
821
+ // intersected with what SecureTransport can negotiate — ECDHE key exchange with AES-GCM.
822
+ // SecureTransport's own default set also includes static-RSA suites (no forward secrecy) and 3DES.
823
+ const SSLCipherSuite ciphers[] = {
824
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
825
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
826
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
827
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384};
828
+ err = SSLSetEnabledCiphers(ssl.get(), ciphers, sizeof(ciphers) / sizeof(SSLCipherSuite));
829
+ if (err != noErr)
830
+ {
831
+ throw SecurityException(
832
+ __FILE__,
833
+ __LINE__,
834
+ "SSL transport: error while setting ciphers:\n" + sslErrorToString(err));
835
+ }
836
+
837
+ return ssl.release();
745
838
  }
746
839
 
747
840
  bool
@@ -750,7 +843,10 @@ SecureTransport::SSLEngine::validationCallback(SecTrustRef trust, const Connecti
750
843
  {
751
844
  OSStatus err = noErr;
752
845
  UniqueRef<CFErrorRef> trustErr;
753
- assert(trust);
846
+ if (!trust)
847
+ {
848
+ throw SecurityException(__FILE__, __LINE__, "SSL transport: peer trust is null");
849
+ }
754
850
 
755
851
  // Do not allow to fetch missing intermediate certificates from the network.
756
852
  if ((err = SecTrustSetNetworkFetchAllowed(trust, false)))
@@ -20,10 +20,9 @@ namespace Ice::SSL::SecureTransport
20
20
  {
21
21
  public:
22
22
  SSLEngine(const IceInternal::InstancePtr&);
23
- ~SSLEngine();
23
+ ~SSLEngine() override;
24
24
 
25
25
  void initialize() final;
26
- void destroy() final;
27
26
 
28
27
  [[nodiscard]] Ice::SSL::ClientAuthenticationOptions
29
28
  createClientAuthenticationOptions(const std::string& host) const final;
@@ -37,6 +36,12 @@ namespace Ice::SSL::SecureTransport
37
36
  private:
38
37
  IceInternal::UniqueRef<CFArrayRef> _certificateAuthorities;
39
38
  IceInternal::UniqueRef<CFArrayRef> _chain;
39
+
40
+ # if defined(ICE_USE_SECURE_TRANSPORT_MACOS)
41
+ // Path of the temporary directory holding the imported certificate's keychain, removed by the destructor.
42
+ // Empty when IceSSL.Keychain is set or no certificate is configured.
43
+ std::string _temporaryKeychainDir;
44
+ # endif
40
45
  };
41
46
  }
42
47
  #endif
@@ -72,7 +72,7 @@ namespace Ice::SSL::SecureTransport
72
72
  SSLWantWrite = 0x2
73
73
  };
74
74
 
75
- mutable std::uint8_t _tflags;
75
+ mutable std::uint8_t _tflags{0};
76
76
  IceInternal::UniqueRef<SecCertificateRef> _peerCertificate;
77
77
  size_t _buffered;
78
78
  std::function<void(SSLContextRef, const std::string&)> _sslNewSessionCallback;