zeroc-ice 3.8.1 → 3.8.3

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 (280) hide show
  1. checksums.yaml +4 -4
  2. data/dist/IceRuby/Communicator.cpp +26 -9
  3. data/dist/IceRuby/Config.h +0 -12
  4. data/dist/IceRuby/Connection.cpp +18 -9
  5. data/dist/IceRuby/DefaultSliceLoader.h +1 -1
  6. data/dist/IceRuby/Endpoint.cpp +21 -8
  7. data/dist/IceRuby/Operation.cpp +29 -11
  8. data/dist/IceRuby/Properties.cpp +3 -4
  9. data/dist/IceRuby/Proxy.cpp +11 -19
  10. data/dist/IceRuby/RubySliceLoader.cpp +1 -1
  11. data/dist/IceRuby/RubySliceLoader.h +6 -0
  12. data/dist/IceRuby/Types.cpp +162 -138
  13. data/dist/IceRuby/Types.h +68 -28
  14. data/dist/IceRuby/Util.cpp +14 -78
  15. data/dist/IceRuby/Util.h +7 -17
  16. data/dist/ice/cpp/include/Ice/Communicator.h +31 -8
  17. data/dist/ice/cpp/include/Ice/Config.h +2 -2
  18. data/dist/ice/cpp/include/Ice/Connection.h +24 -8
  19. data/dist/ice/cpp/include/Ice/CtrlCHandler.h +1 -1
  20. data/dist/ice/cpp/include/Ice/Demangle.h +1 -1
  21. data/dist/ice/cpp/include/Ice/Endpoint.h +4 -4
  22. data/dist/ice/cpp/include/Ice/Initialize.h +4 -4
  23. data/dist/ice/cpp/include/Ice/InputStream.h +5 -5
  24. data/dist/ice/cpp/include/Ice/Instrumentation.h +13 -7
  25. data/dist/ice/cpp/include/Ice/LocalExceptions.h +26 -5
  26. data/dist/ice/cpp/include/Ice/Logger.h +7 -0
  27. data/dist/ice/cpp/include/Ice/LoggerUtil.h +1 -1
  28. data/dist/ice/cpp/include/Ice/Object.h +10 -8
  29. data/dist/ice/cpp/include/Ice/ObjectAdapter.h +1 -1
  30. data/dist/ice/cpp/include/Ice/OutgoingAsync.h +5 -2
  31. data/dist/ice/cpp/include/Ice/OutgoingResponse.h +2 -1
  32. data/dist/ice/cpp/include/Ice/OutputStream.h +14 -11
  33. data/dist/ice/cpp/include/Ice/PluginFactory.h +1 -1
  34. data/dist/ice/cpp/include/Ice/Properties.h +3 -3
  35. data/dist/ice/cpp/include/Ice/Proxy.h +192 -50
  36. data/dist/ice/cpp/include/Ice/SSL/ClientAuthenticationOptions.h +3 -3
  37. data/dist/ice/cpp/include/Ice/SSL/EndpointInfo.h +1 -1
  38. data/dist/ice/cpp/include/Ice/SSL/ServerAuthenticationOptions.h +5 -5
  39. data/dist/ice/cpp/include/Ice/ServantLocator.h +1 -1
  40. data/dist/ice/cpp/include/Ice/Service.h +2 -5
  41. data/dist/ice/cpp/include/Ice/SliceLoader.h +1 -1
  42. data/dist/ice/cpp/include/Ice/SlicedData.h +5 -3
  43. data/dist/ice/cpp/include/Ice/StreamHelpers.h +1 -1
  44. data/dist/ice/cpp/include/Ice/StreamableTraits.h +2 -2
  45. data/dist/ice/cpp/include/Ice/StringConverter.h +2 -3
  46. data/dist/ice/cpp/include/Ice/StringUtil.h +2 -7
  47. data/dist/ice/cpp/include/Ice/UUID.h +1 -0
  48. data/dist/ice/cpp/include/Ice/Value.h +2 -2
  49. data/dist/ice/cpp/include/generated/Ice/BuiltinSequences.h +2 -2
  50. data/dist/ice/cpp/include/generated/Ice/Context.h +2 -2
  51. data/dist/ice/cpp/include/generated/Ice/EndpointTypes.h +2 -2
  52. data/dist/ice/cpp/include/generated/Ice/Identity.h +2 -2
  53. data/dist/ice/cpp/include/generated/Ice/Locator.h +57 -23
  54. data/dist/ice/cpp/include/generated/Ice/LocatorRegistry.h +38 -11
  55. data/dist/ice/cpp/include/generated/Ice/Metrics.h +99 -44
  56. data/dist/ice/cpp/include/generated/Ice/OperationMode.h +2 -2
  57. data/dist/ice/cpp/include/generated/Ice/Process.h +34 -8
  58. data/dist/ice/cpp/include/generated/Ice/PropertiesAdmin.h +42 -11
  59. data/dist/ice/cpp/include/generated/Ice/PropertyDict.h +2 -2
  60. data/dist/ice/cpp/include/generated/Ice/RemoteLogger.h +93 -40
  61. data/dist/ice/cpp/include/generated/Ice/ReplyStatus.h +8 -4
  62. data/dist/ice/cpp/include/generated/Ice/Router.h +55 -19
  63. data/dist/ice/cpp/include/generated/Ice/SliceChecksumDict.h +2 -2
  64. data/dist/ice/cpp/include/generated/Ice/Version.h +2 -2
  65. data/dist/ice/cpp/include/generated/IceDiscovery/Lookup.h +66 -14
  66. data/dist/ice/cpp/include/generated/IceLocatorDiscovery/Lookup.h +34 -8
  67. data/dist/ice/cpp/src/Ice/AddDefaultPluginFactories_all.cpp +1 -1
  68. data/dist/ice/cpp/src/Ice/Base64.cpp +47 -137
  69. data/dist/ice/cpp/src/Ice/Base64.h +2 -2
  70. data/dist/ice/cpp/src/Ice/BatchRequestQueue.cpp +28 -13
  71. data/dist/ice/cpp/src/Ice/BatchRequestQueue.h +5 -1
  72. data/dist/ice/cpp/src/Ice/Buffer.cpp +1 -1
  73. data/dist/ice/cpp/src/Ice/CollocatedRequestHandler.cpp +6 -4
  74. data/dist/ice/cpp/src/Ice/CollocatedRequestHandler.h +1 -1
  75. data/dist/ice/cpp/src/Ice/Communicator.cpp +4 -3
  76. data/dist/ice/cpp/src/Ice/CommunicatorFlushBatchAsync.cpp +8 -0
  77. data/dist/ice/cpp/src/Ice/ConnectRequestHandler.cpp +5 -15
  78. data/dist/ice/cpp/src/Ice/ConnectRequestHandler.h +1 -1
  79. data/dist/ice/cpp/src/Ice/ConnectionFactory.cpp +6 -8
  80. data/dist/ice/cpp/src/Ice/ConnectionFactory.h +0 -3
  81. data/dist/ice/cpp/src/Ice/ConnectionI.cpp +121 -108
  82. data/dist/ice/cpp/src/Ice/ConnectionI.h +12 -9
  83. data/dist/ice/cpp/src/Ice/ConsoleUtil.cpp +1 -1
  84. data/dist/ice/cpp/src/Ice/DefaultsAndOverrides.cpp +10 -14
  85. data/dist/ice/cpp/src/Ice/EndpointI.h +1 -1
  86. data/dist/ice/cpp/src/Ice/FileUtil.cpp +15 -79
  87. data/dist/ice/cpp/src/Ice/FileUtil.h +0 -3
  88. data/dist/ice/cpp/src/Ice/FixedRequestHandler.cpp +1 -1
  89. data/dist/ice/cpp/src/Ice/FixedRequestHandler.h +1 -1
  90. data/dist/ice/cpp/src/Ice/HttpParser.h +0 -2
  91. data/dist/ice/cpp/src/Ice/IPEndpointI.cpp +4 -0
  92. data/dist/ice/cpp/src/Ice/IdleTimeoutTransceiverDecorator.cpp +6 -3
  93. data/dist/ice/cpp/src/Ice/IncomingRequest.cpp +2 -4
  94. data/dist/ice/cpp/src/Ice/InputStream.cpp +50 -33
  95. data/dist/ice/cpp/src/Ice/Instance.cpp +73 -50
  96. data/dist/ice/cpp/src/Ice/Instance.h +1 -6
  97. data/dist/ice/cpp/src/Ice/LocalExceptions.cpp +7 -1
  98. data/dist/ice/cpp/src/Ice/LocatorInfo.cpp +2 -2
  99. data/dist/ice/cpp/src/Ice/LoggerAdminI.cpp +13 -18
  100. data/dist/ice/cpp/src/Ice/LoggerI.cpp +1 -1
  101. data/dist/ice/cpp/src/Ice/LoggerI.h +2 -2
  102. data/dist/ice/cpp/src/Ice/MetricsAdminI.h +6 -1
  103. data/dist/ice/cpp/src/Ice/MetricsObserverI.h +22 -18
  104. data/dist/ice/cpp/src/Ice/NativePropertiesAdmin.cpp +5 -2
  105. data/dist/ice/cpp/src/Ice/Network.cpp +168 -103
  106. data/dist/ice/cpp/src/Ice/Network.h +12 -7
  107. data/dist/ice/cpp/src/Ice/NetworkProxy.cpp +17 -6
  108. data/dist/ice/cpp/src/Ice/NetworkProxy.h +2 -1
  109. data/dist/ice/cpp/src/Ice/Object.cpp +1 -1
  110. data/dist/ice/cpp/src/Ice/ObjectAdapterI.cpp +56 -19
  111. data/dist/ice/cpp/src/Ice/OpaqueEndpointI.cpp +10 -10
  112. data/dist/ice/cpp/src/Ice/Options.cpp +7 -2
  113. data/dist/ice/cpp/src/Ice/OutgoingAsync.cpp +2 -2
  114. data/dist/ice/cpp/src/Ice/OutgoingResponse.cpp +127 -127
  115. data/dist/ice/cpp/src/Ice/OutgoingResponseInternal.h +21 -0
  116. data/dist/ice/cpp/src/Ice/OutputStream.cpp +50 -65
  117. data/dist/ice/cpp/src/Ice/PluginManagerI.cpp +7 -1
  118. data/dist/ice/cpp/src/Ice/Properties.cpp +26 -16
  119. data/dist/ice/cpp/src/Ice/PropertyNames.cpp +2 -1
  120. data/dist/ice/cpp/src/Ice/PropertyUtil.cpp +1 -1
  121. data/dist/ice/cpp/src/Ice/ProtocolInstance.cpp +0 -11
  122. data/dist/ice/cpp/src/Ice/ProtocolInstance.h +1 -2
  123. data/dist/ice/cpp/src/Ice/Proxy.cpp +9 -1
  124. data/dist/ice/cpp/src/Ice/ProxyAsync.cpp +110 -13
  125. data/dist/ice/cpp/src/Ice/ProxyFunctions.cpp +4 -4
  126. data/dist/ice/cpp/src/Ice/Random.cpp +68 -7
  127. data/dist/ice/cpp/src/Ice/Random.h +6 -2
  128. data/dist/ice/cpp/src/Ice/Reference.cpp +37 -26
  129. data/dist/ice/cpp/src/Ice/Reference.h +3 -0
  130. data/dist/ice/cpp/src/Ice/ReferenceFactory.cpp +26 -13
  131. data/dist/ice/cpp/src/Ice/RequestHandler.h +3 -1
  132. data/dist/ice/cpp/src/Ice/RequestHandlerCache.cpp +1 -1
  133. data/dist/ice/cpp/src/Ice/RequestHandlerCache.h +1 -1
  134. data/dist/ice/cpp/src/Ice/ResourceConfig.h +3 -3
  135. data/dist/ice/cpp/src/Ice/RetryQueue.cpp +8 -12
  136. data/dist/ice/cpp/src/Ice/SHA1.cpp +11 -11
  137. data/dist/ice/cpp/src/Ice/SSL/DistinguishedName.cpp +0 -6
  138. data/dist/ice/cpp/src/Ice/SSL/DistinguishedName.h +0 -6
  139. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.cpp +27 -12
  140. data/dist/ice/cpp/src/Ice/SSL/OpenSSLEngine.h +1 -2
  141. data/dist/ice/cpp/src/Ice/SSL/OpenSSLTransceiverI.cpp +77 -27
  142. data/dist/ice/cpp/src/Ice/SSL/OpenSSLTransceiverI.h +2 -1
  143. data/dist/ice/cpp/src/Ice/SSL/RFC2253.cpp +2 -2
  144. data/dist/ice/cpp/src/Ice/SSL/SSLEndpointI.cpp +1 -1
  145. data/dist/ice/cpp/src/Ice/SSL/SSLEngine.h +1 -4
  146. data/dist/ice/cpp/src/Ice/SSL/SSLUtil.cpp +39 -34
  147. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.cpp +165 -80
  148. data/dist/ice/cpp/src/Ice/SSL/SchannelEngine.h +1 -5
  149. data/dist/ice/cpp/src/Ice/SSL/SchannelTransceiverI.cpp +73 -33
  150. data/dist/ice/cpp/src/Ice/SSL/SchannelTransceiverI.h +0 -1
  151. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.cpp +110 -17
  152. data/dist/ice/cpp/src/Ice/SSL/SecureTransportEngine.h +7 -2
  153. data/dist/ice/cpp/src/Ice/SSL/SecureTransportTransceiverI.cpp +9 -3
  154. data/dist/ice/cpp/src/Ice/SSL/SecureTransportUtil.cpp +73 -51
  155. data/dist/ice/cpp/src/Ice/SSL/SecureTransportUtil.h +0 -8
  156. data/dist/ice/cpp/src/Ice/Selector.cpp +13 -11
  157. data/dist/ice/cpp/src/Ice/ServantManager.cpp +3 -3
  158. data/dist/ice/cpp/src/Ice/Service.cpp +33 -115
  159. data/dist/ice/cpp/src/Ice/StreamSocket.cpp +33 -40
  160. data/dist/ice/cpp/src/Ice/StreamSocket.h +4 -4
  161. data/dist/ice/cpp/src/Ice/StringConverter.cpp +1 -1
  162. data/dist/ice/cpp/src/Ice/StringUtil.cpp +12 -21
  163. data/dist/ice/cpp/src/Ice/SysLoggerI.cpp +136 -100
  164. data/dist/ice/cpp/src/Ice/SysLoggerI.h +7 -3
  165. data/dist/ice/cpp/src/Ice/SystemdJournalI.cpp +1 -1
  166. data/dist/ice/cpp/src/Ice/TcpAcceptor.cpp +7 -7
  167. data/dist/ice/cpp/src/Ice/TcpAcceptor.h +2 -1
  168. data/dist/ice/cpp/src/Ice/TcpBufSize.h +40 -0
  169. data/dist/ice/cpp/src/Ice/TcpConnector.cpp +5 -2
  170. data/dist/ice/cpp/src/Ice/TcpConnector.h +2 -0
  171. data/dist/ice/cpp/src/Ice/TcpEndpointI.cpp +2 -2
  172. data/dist/ice/cpp/src/Ice/TcpTransceiver.cpp +6 -2
  173. data/dist/ice/cpp/src/Ice/ThreadPool.cpp +2 -8
  174. data/dist/ice/cpp/src/Ice/ThreadPool.h +0 -2
  175. data/dist/ice/cpp/src/Ice/Timer.cpp +7 -3
  176. data/dist/ice/cpp/src/Ice/UUID.cpp +1 -2
  177. data/dist/ice/cpp/src/Ice/UdpEndpointI.cpp +6 -3
  178. data/dist/ice/cpp/src/Ice/UdpTransceiver.cpp +136 -123
  179. data/dist/ice/cpp/src/Ice/UdpTransceiver.h +3 -4
  180. data/dist/ice/cpp/src/Ice/WSAcceptor.cpp +8 -3
  181. data/dist/ice/cpp/src/Ice/WSAcceptor.h +5 -1
  182. data/dist/ice/cpp/src/Ice/WSEndpoint.cpp +45 -2
  183. data/dist/ice/cpp/src/Ice/WSTransceiver.cpp +214 -34
  184. data/dist/ice/cpp/src/Ice/WSTransceiver.h +13 -2
  185. data/dist/ice/cpp/src/Ice/generated/BuiltinSequences.cpp +2 -2
  186. data/dist/ice/cpp/src/Ice/generated/Context.cpp +2 -2
  187. data/dist/ice/cpp/src/Ice/generated/EndpointTypes.cpp +2 -2
  188. data/dist/ice/cpp/src/Ice/generated/Identity.cpp +2 -2
  189. data/dist/ice/cpp/src/Ice/generated/Locator.cpp +2 -2
  190. data/dist/ice/cpp/src/Ice/generated/LocatorRegistry.cpp +2 -2
  191. data/dist/ice/cpp/src/Ice/generated/Metrics.cpp +2 -2
  192. data/dist/ice/cpp/src/Ice/generated/OperationMode.cpp +2 -2
  193. data/dist/ice/cpp/src/Ice/generated/Process.cpp +2 -2
  194. data/dist/ice/cpp/src/Ice/generated/PropertiesAdmin.cpp +2 -2
  195. data/dist/ice/cpp/src/Ice/generated/PropertyDict.cpp +2 -2
  196. data/dist/ice/cpp/src/Ice/generated/RemoteLogger.cpp +2 -2
  197. data/dist/ice/cpp/src/Ice/generated/ReplyStatus.cpp +4 -2
  198. data/dist/ice/cpp/src/Ice/generated/Router.cpp +2 -2
  199. data/dist/ice/cpp/src/Ice/generated/SliceChecksumDict.cpp +2 -2
  200. data/dist/ice/cpp/src/Ice/generated/Version.cpp +2 -2
  201. data/dist/ice/cpp/src/IceDiscovery/LookupI.cpp +47 -9
  202. data/dist/ice/cpp/src/IceDiscovery/LookupI.h +8 -3
  203. data/dist/ice/cpp/src/IceDiscovery/generated/Lookup.cpp +2 -2
  204. data/dist/ice/cpp/src/IceLocatorDiscovery/PluginI.cpp +43 -14
  205. data/dist/ice/cpp/src/IceLocatorDiscovery/generated/Lookup.cpp +2 -2
  206. data/dist/ice/cpp/src/Slice/DocCommentParser.cpp +32 -26
  207. data/dist/ice/cpp/src/Slice/DocCommentParser.h +6 -4
  208. data/dist/ice/cpp/src/Slice/FileTracker.cpp +3 -11
  209. data/dist/ice/cpp/src/Slice/FileTracker.h +0 -2
  210. data/dist/ice/cpp/src/Slice/Grammar.cpp +211 -210
  211. data/dist/ice/cpp/src/Slice/MetadataValidation.cpp +34 -14
  212. data/dist/ice/cpp/src/Slice/MetadataValidation.h +3 -2
  213. data/dist/ice/cpp/src/Slice/Parser.cpp +145 -97
  214. data/dist/ice/cpp/src/Slice/Parser.h +22 -8
  215. data/dist/ice/cpp/src/Slice/Preprocessor.cpp +77 -29
  216. data/dist/ice/cpp/src/Slice/Preprocessor.h +0 -3
  217. data/dist/ice/cpp/src/Slice/Scanner.cpp +3 -3
  218. data/dist/ice/cpp/src/Slice/SliceUtil.cpp +203 -172
  219. data/dist/ice/cpp/src/Slice/StringLiteralUtil.cpp +0 -2
  220. data/dist/ice/cpp/src/Slice/Util.h +21 -12
  221. data/dist/ice/cpp/src/slice2rb/Ruby.cpp +7 -3
  222. data/dist/ice/cpp/src/slice2rb/RubyUtil.cpp +26 -20
  223. data/dist/ice/cpp/src/slice2rb/RubyUtil.h +10 -13
  224. data/dist/ice/slice/Glacier2/Router.ice +3 -3
  225. data/dist/ice/slice/Ice/Identity.ice +3 -0
  226. data/dist/ice/slice/Ice/Locator.ice +6 -5
  227. data/dist/ice/slice/Ice/LocatorRegistry.ice +3 -0
  228. data/dist/ice/slice/Ice/Metrics.ice +7 -6
  229. data/dist/ice/slice/Ice/OperationMode.ice +8 -0
  230. data/dist/ice/slice/Ice/Process.ice +3 -0
  231. data/dist/ice/slice/Ice/RemoteLogger.ice +5 -5
  232. data/dist/ice/slice/Ice/ReplyStatus.ice +13 -0
  233. data/dist/ice/slice/IceGrid/Admin.ice +9 -9
  234. data/dist/ice/slice/IceGrid/Descriptor.ice +5 -5
  235. data/dist/ice/slice/IceStorm/Metrics.ice +1 -1
  236. data/dist/lib/Glacier2/Metrics.rb +1 -1
  237. data/dist/lib/Glacier2/PermissionsVerifier.rb +3 -3
  238. data/dist/lib/Glacier2/Router.rb +9 -9
  239. data/dist/lib/Glacier2/SSLInfo.rb +1 -1
  240. data/dist/lib/Glacier2/Session.rb +15 -15
  241. data/dist/lib/Ice/BuiltinSequences.rb +1 -1
  242. data/dist/lib/Ice/CompressBatch.rb +1 -2
  243. data/dist/lib/Ice/Context.rb +1 -1
  244. data/dist/lib/Ice/EndpointSelectionType.rb +1 -2
  245. data/dist/lib/Ice/EndpointTypes.rb +1 -1
  246. data/dist/lib/Ice/Identity.rb +1 -1
  247. data/dist/lib/Ice/IdentitySpaceship.rb +1 -0
  248. data/dist/lib/Ice/LocalExceptions.rb +3 -0
  249. data/dist/lib/Ice/Locator.rb +5 -5
  250. data/dist/lib/Ice/LocatorRegistry.rb +4 -4
  251. data/dist/lib/Ice/Metrics.rb +7 -7
  252. data/dist/lib/Ice/OperationMode.rb +2 -3
  253. data/dist/lib/Ice/Process.rb +3 -3
  254. data/dist/lib/Ice/PropertiesAdmin.rb +4 -4
  255. data/dist/lib/Ice/PropertyDict.rb +1 -1
  256. data/dist/lib/Ice/ProxyFunctions.rb +8 -4
  257. data/dist/lib/Ice/RemoteLogger.rb +7 -8
  258. data/dist/lib/Ice/ReplyStatus.rb +4 -4
  259. data/dist/lib/Ice/Router.rb +5 -5
  260. data/dist/lib/Ice/SliceChecksumDict.rb +1 -1
  261. data/dist/lib/Ice/SliceUtil.rb +2 -2
  262. data/dist/lib/Ice/Struct.rb +1 -0
  263. data/dist/lib/Ice/ToStringMode.rb +1 -2
  264. data/dist/lib/Ice/Value.rb +2 -2
  265. data/dist/lib/Ice/Version.rb +1 -1
  266. data/dist/lib/IceBox/ServiceManager.rb +8 -8
  267. data/dist/lib/IceGrid/Admin.rb +85 -86
  268. data/dist/lib/IceGrid/Descriptor.rb +1 -1
  269. data/dist/lib/IceGrid/Exception.rb +1 -1
  270. data/dist/lib/IceGrid/FileParser.rb +2 -2
  271. data/dist/lib/IceGrid/Registry.rb +14 -15
  272. data/dist/lib/IceGrid/Session.rb +7 -7
  273. data/dist/lib/IceGrid/UserAccountMapper.rb +2 -2
  274. data/dist/lib/IceStorm/IceStorm.rb +16 -16
  275. data/dist/lib/IceStorm/Metrics.rb +1 -1
  276. data/extconf.rb +1 -1
  277. data/ice.gemspec +3 -3
  278. metadata +5 -5
  279. data/dist/ice/cpp/src/Ice/DLLMain.cpp +0 -40
  280. data/dist/ice/cpp/src/Ice/UndefSysMacros.h +0 -37
@@ -459,21 +459,28 @@ namespace
459
459
  throw InitializationException(
460
460
  __FILE__,
461
461
  __LINE__,
462
- "SSL transport: invalid value '" + value + "' for `IceSSL.FindCert' property:\n" +
462
+ "SSL transport: invalid value '" + value + "' for 'IceSSL.FindCert' property:\n" +
463
463
  IceInternal::lastErrorToString());
464
464
  }
465
465
 
466
466
  vector<BYTE> buffer(length);
467
- if (!CertStrToNameW(X509_ASN_ENCODING, argW.c_str(), flags[i], 0, &buffer[0], &length, 0))
467
+ if (!CertStrToNameW(
468
+ X509_ASN_ENCODING,
469
+ argW.c_str(),
470
+ flags[i],
471
+ 0,
472
+ buffer.data(),
473
+ &length,
474
+ 0))
468
475
  {
469
476
  throw InitializationException(
470
477
  __FILE__,
471
478
  __LINE__,
472
- "SSL transport: invalid value '" + value + "' for `IceSSL.FindCert' property:\n" +
479
+ "SSL transport: invalid value '" + value + "' for 'IceSSL.FindCert' property:\n" +
473
480
  IceInternal::lastErrorToString());
474
481
  }
475
482
 
476
- CERT_NAME_BLOB name = {length, &buffer[0]};
483
+ CERT_NAME_BLOB name = {length, buffer.data()};
477
484
 
478
485
  DWORD findType = field == "SUBJECTDN" ? CERT_FIND_SUBJECT_NAME : CERT_FIND_ISSUER_NAME;
479
486
  addMatchingCertificates(store, tmpStore, findType, &name);
@@ -487,10 +494,10 @@ namespace
487
494
  throw InitializationException(
488
495
  __FILE__,
489
496
  __LINE__,
490
- "SSL transport: invalid 'IceSSL.FindCert' property: can't decode the value");
497
+ "SSL transport: invalid 'IceSSL.FindCert' property: cannot decode the value");
491
498
  }
492
499
 
493
- CRYPT_HASH_BLOB hash = {static_cast<DWORD>(buffer.size()), &buffer[0]};
500
+ CRYPT_HASH_BLOB hash = {static_cast<DWORD>(buffer.size()), buffer.data()};
494
501
  DWORD findType = field == "THUMBPRINT" ? CERT_FIND_HASH : CERT_FIND_KEY_IDENTIFIER;
495
502
  addMatchingCertificates(store, tmpStore, findType, &hash);
496
503
  }
@@ -502,7 +509,7 @@ namespace
502
509
  throw InitializationException(
503
510
  __FILE__,
504
511
  __LINE__,
505
- "SSL transport: invalid value '" + value + "' for `IceSSL.FindCert' property");
512
+ "SSL transport: invalid value '" + value + "' for 'IceSSL.FindCert' property");
506
513
  }
507
514
 
508
515
  // CRYPT_INTEGER_BLOB stores serial data in little-endian format, parseBytes returns big-endian
@@ -510,7 +517,7 @@ namespace
510
517
  std::vector<BYTE> serialData(buffer.size());
511
518
  std::reverse_copy(std::begin(buffer), std::end(buffer), std::begin(serialData));
512
519
 
513
- CRYPT_INTEGER_BLOB serial = {static_cast<DWORD>(serialData.size()), &serialData[0]};
520
+ CRYPT_INTEGER_BLOB serial = {static_cast<DWORD>(serialData.size()), serialData.data()};
514
521
  PCCERT_CONTEXT next = nullptr;
515
522
  do
516
523
  {
@@ -568,9 +575,12 @@ namespace
568
575
  0,
569
576
  CERT_FIND_ANY,
570
577
  0,
571
- next)) != 0)
578
+ next)) != nullptr)
572
579
  {
573
- certs.push_back(next);
580
+ // CertFindCertificateInStore frees the context passed as pPrevCertContext on the next iteration
581
+ // (and frees the last one when it returns null). Duplicate the context to keep an owned reference
582
+ // that remains valid after enumeration; these duplicates are released in the destructor.
583
+ certs.push_back(CertDuplicateCertificateContext(next));
574
584
  }
575
585
  } while (next);
576
586
  stores.push_back(store);
@@ -598,7 +608,13 @@ namespace
598
608
  if (startpos != string::npos)
599
609
  {
600
610
  endpos = strbuf.find("-----END CERTIFICATE-----", startpos);
601
- size = endpos - startpos + sizeof("-----END CERTIFICATE-----");
611
+ if (endpos == string::npos)
612
+ {
613
+ ostringstream os;
614
+ os << "SSL transport: malformed PEM certificate (missing END marker): '" << file << "'";
615
+ throw InitializationException(__FILE__, __LINE__, os.str());
616
+ }
617
+ size = endpos - startpos + strlen("-----END CERTIFICATE-----");
602
618
  }
603
619
  else if (first)
604
620
  {
@@ -618,7 +634,7 @@ namespace
618
634
  &buffer[startpos],
619
635
  static_cast<DWORD>(size),
620
636
  CRYPT_STRING_ANY,
621
- &outBuffer[0],
637
+ outBuffer.data(),
622
638
  &outLength,
623
639
  0,
624
640
  0))
@@ -633,7 +649,7 @@ namespace
633
649
  if (!CertAddEncodedCertificateToStore(
634
650
  store,
635
651
  X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
636
- &outBuffer[0],
652
+ outBuffer.data(),
637
653
  outLength,
638
654
  CERT_STORE_ADD_NEW,
639
655
  first ? cert : 0))
@@ -688,7 +704,7 @@ namespace
688
704
  }
689
705
  else
690
706
  {
691
- // If subjectAlt is empty compare it to the subject CN, otherwise compare it to the to the subject alt
707
+ // If subjectAlt is empty compare it to the subject CN, otherwise compare it to the subject alt
692
708
  // name dnsNames.
693
709
  if (dnsNames.empty())
694
710
  {
@@ -734,6 +750,34 @@ namespace
734
750
  throw SecurityException(__FILE__, __LINE__, msg);
735
751
  }
736
752
  }
753
+
754
+ // Deletes the key container referenced by the certificate's CERT_KEY_PROV_INFO property, if it has one.
755
+ // With CRYPT_DELETEKEYSET, CryptAcquireContextW deletes the key container; the returned handle is undefined
756
+ // and must not be released. Machine key containers live in a separate store, so CRYPT_MACHINE_KEYSET must be
757
+ // carried over from the provider info or the container is not found.
758
+ void deleteKeyContainer(PCCERT_CONTEXT cert)
759
+ {
760
+ DWORD length = 0;
761
+ if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, nullptr, &length))
762
+ {
763
+ return;
764
+ }
765
+
766
+ vector<char> buf(length);
767
+ if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, buf.data(), &length))
768
+ {
769
+ return;
770
+ }
771
+
772
+ const CRYPT_KEY_PROV_INFO* keyProvInfo = reinterpret_cast<const CRYPT_KEY_PROV_INFO*>(buf.data());
773
+ HCRYPTPROV prov = 0;
774
+ CryptAcquireContextW(
775
+ &prov,
776
+ keyProvInfo->pwszContainerName,
777
+ keyProvInfo->pwszProvName,
778
+ keyProvInfo->dwProvType,
779
+ (keyProvInfo->dwFlags & CRYPT_MACHINE_KEYSET) | CRYPT_DELETEKEYSET);
780
+ }
737
781
  }
738
782
 
739
783
  Schannel::SSLEngine::SSLEngine(const IceInternal::InstancePtr& instance)
@@ -743,14 +787,57 @@ Schannel::SSLEngine::SSLEngine(const IceInternal::InstancePtr& instance)
743
787
  {
744
788
  }
745
789
 
790
+ Schannel::SSLEngine::~SSLEngine()
791
+ {
792
+ // Best-effort cleanup. We catch every exception (e.g. std::bad_alloc from the per-cert vector
793
+ // allocation below) so nothing escapes the destructor and triggers std::terminate.
794
+ try
795
+ {
796
+ if (_chainEngine && _chainEngine != HCCE_CURRENT_USER && _chainEngine != HCCE_LOCAL_MACHINE)
797
+ {
798
+ CertFreeCertificateChainEngine(_chainEngine);
799
+ }
800
+
801
+ if (_rootStore)
802
+ {
803
+ CertCloseStore(_rootStore, 0);
804
+ }
805
+
806
+ // Remove the key containers created for the certificates Ice imported. Certificates found in a system store
807
+ // are not listed in _importedCerts: their key containers belong to the user or the machine and must be kept.
808
+ for (vector<PCCERT_CONTEXT>::const_iterator i = _importedCerts.begin(); i != _importedCerts.end(); ++i)
809
+ {
810
+ deleteKeyContainer(*i);
811
+ }
812
+
813
+ for (vector<PCCERT_CONTEXT>::const_iterator i = _allCerts.begin(); i != _allCerts.end(); ++i)
814
+ {
815
+ CertFreeCertificateContext(*i);
816
+ }
817
+
818
+ for (vector<HCERTSTORE>::const_iterator i = _stores.begin(); i != _stores.end(); ++i)
819
+ {
820
+ #ifdef NDEBUG
821
+ CertCloseStore(*i, 0);
822
+ #else
823
+ // In debug builds, close the store with CERT_CLOSE_STORE_CHECK_FLAG to assert that every certificate
824
+ // context obtained from it was freed. The call returns false (last error CRYPT_E_PENDING_CLOSE) if any
825
+ // context is still outstanding, which catches certificate-reference leaks early.
826
+ const BOOL allContextsFreed = CertCloseStore(*i, CERT_CLOSE_STORE_CHECK_FLAG);
827
+ assert(allContextsFreed && "SSL transport: certificate context leaked (store closed with live contexts)");
828
+ #endif
829
+ }
830
+ }
831
+ catch (...)
832
+ {
833
+ }
834
+ }
835
+
746
836
  void
747
837
  Schannel::SSLEngine::initialize()
748
838
  {
749
- //
750
- // BUGFIX: we use a global mutex for the initialization of Schannel to
751
- // avoid crashes occurring with last Schannel updates see:
752
- // https://github.com/zeroc-ice/ice/issues/242
753
- //
839
+ // We use a global mutex for the initialization of Schannel to avoid crashes observed with some Schannel
840
+ // updates.
754
841
  lock_guard globalLock(globalMutex);
755
842
 
756
843
  Ice::SSL::SSLEngine::initialize();
@@ -856,7 +943,7 @@ Schannel::SSLEngine::initialize()
856
943
 
857
944
  CRYPT_DATA_BLOB pfxBlob;
858
945
  pfxBlob.cbData = static_cast<DWORD>(buffer.size());
859
- pfxBlob.pbData = reinterpret_cast<BYTE*>(&buffer[0]);
946
+ pfxBlob.pbData = reinterpret_cast<BYTE*>(buffer.data());
860
947
 
861
948
  PCCERT_CONTEXT cert = nullptr;
862
949
  DWORD importFlags = (certStoreLocation == "LocalMachine") ? CRYPT_MACHINE_KEYSET : CRYPT_USER_KEYSET;
@@ -902,10 +989,10 @@ Schannel::SSLEngine::initialize()
902
989
  }
903
990
  if (!cert)
904
991
  {
905
- throw InitializationException(
906
- __FILE__,
907
- __LINE__,
908
- "SSL transport: certificate error:\n" + lastErrorToString());
992
+ // Read the error before closing the store, otherwise it reports the close instead of the lookup.
993
+ const string error = lastErrorToString();
994
+ CertCloseStore(store, 0);
995
+ throw InitializationException(__FILE__, __LINE__, "SSL transport: certificate error:\n" + error);
909
996
  }
910
997
  _allCerts.push_back(cert);
911
998
  _stores.push_back(store);
@@ -946,10 +1033,10 @@ Schannel::SSLEngine::initialize()
946
1033
 
947
1034
  // Convert the PEM encoded buffer to DER binary format.
948
1035
  if (!CryptStringToBinary(
949
- &buffer[0],
1036
+ buffer.data(),
950
1037
  static_cast<DWORD>(buffer.size()),
951
1038
  CRYPT_STRING_BASE64HEADER,
952
- &outBuffer[0],
1039
+ outBuffer.data(),
953
1040
  &outLength,
954
1041
  0,
955
1042
  0))
@@ -962,6 +1049,10 @@ Schannel::SSLEngine::initialize()
962
1049
  PCRYPT_PRIVATE_KEY_INFO keyInfo = nullptr;
963
1050
  BYTE* key = nullptr;
964
1051
  HCRYPTKEY hKey = 0;
1052
+ HCRYPTPROV cryptProv = 0;
1053
+ wstring keySetName;
1054
+ DWORD contextFlags = 0;
1055
+ bool keySetCreated = false;
965
1056
  try
966
1057
  {
967
1058
  // First try to decode as a PKCS#8 key, if that fails try PKCS#1.
@@ -969,7 +1060,7 @@ Schannel::SSLEngine::initialize()
969
1060
  if (CryptDecodeObjectEx(
970
1061
  X509_ASN_ENCODING,
971
1062
  PKCS_PRIVATE_KEY_INFO,
972
- &outBuffer[0],
1063
+ outBuffer.data(),
973
1064
  outLength,
974
1065
  CRYPT_DECODE_ALLOC_FLAG,
975
1066
  0,
@@ -1008,7 +1099,7 @@ Schannel::SSLEngine::initialize()
1008
1099
  if (!CryptDecodeObjectEx(
1009
1100
  X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1010
1101
  PKCS_RSA_PRIVATE_KEY,
1011
- &outBuffer[0],
1102
+ outBuffer.data(),
1012
1103
  outLength,
1013
1104
  CRYPT_DECODE_ALLOC_FLAG,
1014
1105
  0,
@@ -1022,10 +1113,9 @@ Schannel::SSLEngine::initialize()
1022
1113
  }
1023
1114
 
1024
1115
  // Create a new RSA key set to store our key.
1025
- const wstring keySetName = Ice::stringToWstring(generateUUID());
1026
- HCRYPTPROV cryptProv = 0;
1116
+ keySetName = Ice::stringToWstring(generateUUID());
1027
1117
 
1028
- DWORD contextFlags = CRYPT_NEWKEYSET;
1118
+ contextFlags = CRYPT_NEWKEYSET;
1029
1119
  if (certStoreLocation == "LocalMachine")
1030
1120
  {
1031
1121
  contextFlags |= CRYPT_MACHINE_KEYSET;
@@ -1043,6 +1133,7 @@ Schannel::SSLEngine::initialize()
1043
1133
  __LINE__,
1044
1134
  "SSL transport: error acquiring cryptographic context:\n" + lastErrorToString());
1045
1135
  }
1136
+ keySetCreated = true;
1046
1137
 
1047
1138
  // Import the private key.
1048
1139
  if (!CryptImportKey(cryptProv, key, outLength, 0, 0, &hKey))
@@ -1056,6 +1147,8 @@ Schannel::SSLEngine::initialize()
1056
1147
 
1057
1148
  CryptDestroyKey(hKey);
1058
1149
  hKey = 0;
1150
+ CryptReleaseContext(cryptProv, 0);
1151
+ cryptProv = 0;
1059
1152
 
1060
1153
  // Create a new memory store to place the certificate.
1061
1154
  store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, 0);
@@ -1073,8 +1166,11 @@ Schannel::SSLEngine::initialize()
1073
1166
  CRYPT_KEY_PROV_INFO keyProvInfo;
1074
1167
  memset(&keyProvInfo, 0, sizeof(keyProvInfo));
1075
1168
  keyProvInfo.pwszContainerName = const_cast<wchar_t*>(keySetName.c_str());
1076
- keyProvInfo.pwszProvName = const_cast<wchar_t*>(MS_DEF_PROV_W);
1169
+ // The provider name and flags must match the ones the container was created with above, otherwise
1170
+ // neither the private key nor the container can be found again.
1171
+ keyProvInfo.pwszProvName = const_cast<wchar_t*>(MS_ENHANCED_PROV_W);
1077
1172
  keyProvInfo.dwProvType = PROV_RSA_FULL;
1173
+ keyProvInfo.dwFlags = contextFlags & CRYPT_MACHINE_KEYSET;
1078
1174
  keyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
1079
1175
  if (!CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo))
1080
1176
  {
@@ -1105,6 +1201,24 @@ Schannel::SSLEngine::initialize()
1105
1201
  CryptDestroyKey(hKey);
1106
1202
  }
1107
1203
 
1204
+ if (cryptProv)
1205
+ {
1206
+ CryptReleaseContext(cryptProv, 0);
1207
+ }
1208
+
1209
+ if (keySetCreated)
1210
+ {
1211
+ // With CRYPT_DELETEKEYSET, CryptAcquireContextW deletes the key container; the returned
1212
+ // handle is undefined and must not be released.
1213
+ HCRYPTPROV prov = 0;
1214
+ CryptAcquireContextW(
1215
+ &prov,
1216
+ keySetName.c_str(),
1217
+ MS_ENHANCED_PROV_W,
1218
+ PROV_RSA_FULL,
1219
+ (contextFlags & CRYPT_MACHINE_KEYSET) | CRYPT_DELETEKEYSET);
1220
+ }
1221
+
1108
1222
  if (cert)
1109
1223
  {
1110
1224
  CertFreeCertificateContext(cert);
@@ -1210,49 +1324,6 @@ Schannel::SSLEngine::getCipherName(ALG_ID cipher) const
1210
1324
  }
1211
1325
  }
1212
1326
 
1213
- void
1214
- Schannel::SSLEngine::destroy()
1215
- {
1216
- if (_chainEngine && _chainEngine != HCCE_CURRENT_USER && _chainEngine != HCCE_LOCAL_MACHINE)
1217
- {
1218
- CertFreeCertificateChainEngine(_chainEngine);
1219
- }
1220
-
1221
- if (_rootStore)
1222
- {
1223
- CertCloseStore(_rootStore, 0);
1224
- }
1225
-
1226
- for (vector<PCCERT_CONTEXT>::const_iterator i = _importedCerts.begin(); i != _importedCerts.end(); ++i)
1227
- {
1228
- // Retrieve the certificate CERT_KEY_PROV_INFO_PROP_ID property, we use the CRYPT_KEY_PROV_INFO data to remove
1229
- // the key set associated with the certificate.
1230
- DWORD length = 0;
1231
- if (!CertGetCertificateContextProperty(*i, CERT_KEY_PROV_INFO_PROP_ID, 0, &length))
1232
- {
1233
- continue;
1234
- }
1235
- vector<char> buf(length);
1236
- if (!CertGetCertificateContextProperty(*i, CERT_KEY_PROV_INFO_PROP_ID, &buf[0], &length))
1237
- {
1238
- continue;
1239
- }
1240
- CRYPT_KEY_PROV_INFO* key = reinterpret_cast<CRYPT_KEY_PROV_INFO*>(&buf[0]);
1241
- HCRYPTPROV prov = 0;
1242
- CryptAcquireContextW(&prov, key->pwszContainerName, key->pwszProvName, key->dwProvType, CRYPT_DELETEKEYSET);
1243
- }
1244
-
1245
- for (vector<PCCERT_CONTEXT>::const_iterator i = _allCerts.begin(); i != _allCerts.end(); ++i)
1246
- {
1247
- CertFreeCertificateContext(*i);
1248
- }
1249
-
1250
- for (vector<HCERTSTORE>::const_iterator i = _stores.begin(); i != _stores.end(); ++i)
1251
- {
1252
- CertCloseStore(*i, 0);
1253
- }
1254
- }
1255
-
1256
1327
  Ice::SSL::ClientAuthenticationOptions
1257
1328
  Schannel::SSLEngine::createClientAuthenticationOptions(const string& host) const
1258
1329
  {
@@ -1260,15 +1331,22 @@ Schannel::SSLEngine::createClientAuthenticationOptions(const string& host) const
1260
1331
  .clientCredentialsSelectionCallback =
1261
1332
  [this](const string&)
1262
1333
  {
1334
+ // The transport takes ownership of the returned paCred contexts and releases them when the connection
1335
+ // is closed (see ClientAuthenticationOptions). Bump the reference count of each certificate so the
1336
+ // reference handed to the transport is independent of the engine's _allCerts, which outlives the
1337
+ // individual connections.
1263
1338
  for (const auto& cert : _allCerts)
1264
1339
  {
1265
- CertDuplicateCertificateContext(cert);
1340
+ // CertDuplicateCertificateContext returns the same pointer with an incremented reference count and
1341
+ // cannot fail for a non-null context; the assert guards that invariant.
1342
+ [[maybe_unused]] PCCERT_CONTEXT duplicate = CertDuplicateCertificateContext(cert);
1343
+ assert(duplicate == cert);
1266
1344
  }
1267
1345
 
1268
1346
  return SCH_CREDENTIALS{
1269
1347
  .dwVersion = SCH_CREDENTIALS_VERSION,
1270
1348
  .cCreds = static_cast<DWORD>(_allCerts.size()),
1271
- .paCred = const_cast<PCCERT_CONTEXT*>(_allCerts.size() > 0 ? &_allCerts[0] : nullptr),
1349
+ .paCred = const_cast<PCCERT_CONTEXT*>(_allCerts.data()),
1272
1350
  .dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SERVERNAME_CHECK | SCH_USE_STRONG_CRYPTO};
1273
1351
  },
1274
1352
  .trustedRootCertificates = _rootStore,
@@ -1305,17 +1383,24 @@ Schannel::SSLEngine::createServerAuthenticationOptions() const
1305
1383
  [this](const string&)
1306
1384
  {
1307
1385
  {
1386
+ // The transport takes ownership of the returned paCred contexts and releases them when the
1387
+ // connection is closed (see ServerAuthenticationOptions). Bump the reference count of each
1388
+ // certificate so the reference handed to the transport is independent of the engine's _allCerts,
1389
+ // which outlives the individual connections.
1308
1390
  for (const auto& cert : _allCerts)
1309
1391
  {
1310
- CertDuplicateCertificateContext(cert);
1392
+ // CertDuplicateCertificateContext returns the same pointer with an incremented reference count
1393
+ // and cannot fail for a non-null context; the assert guards that invariant.
1394
+ [[maybe_unused]] PCCERT_CONTEXT duplicate = CertDuplicateCertificateContext(cert);
1395
+ assert(duplicate == cert);
1311
1396
  }
1312
1397
 
1313
1398
  return SCH_CREDENTIALS{
1314
1399
  .dwVersion = SCH_CREDENTIALS_VERSION,
1315
1400
  .cCreds = static_cast<DWORD>(_allCerts.size()),
1316
- .paCred = const_cast<PCCERT_CONTEXT*>(_allCerts.size() > 0 ? &_allCerts[0] : nullptr),
1401
+ .paCred = const_cast<PCCERT_CONTEXT*>(_allCerts.data()),
1317
1402
  // Don't set SCH_SEND_ROOT_CERT as it seems to cause problems with Java certificate validation and
1318
- // Schannel doesn't seems to send the root certificate either way.
1403
+ // Schannel doesn't seem to send the root certificate either way.
1319
1404
  .dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_USE_STRONG_CRYPTO};
1320
1405
  }
1321
1406
  },
@@ -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
@@ -93,7 +93,7 @@ namespace
93
93
  return SCH_CREDENTIALS{
94
94
  .dwVersion = SCH_CREDENTIALS_VERSION,
95
95
  // Don't set SCH_SEND_ROOT_CERT as it seems to cause problems with Java certificate validation and
96
- // Schannel doesn't seems to send the root certificate either way.
96
+ // Schannel doesn't seem to send the root certificate either way.
97
97
  .dwFlags = SCH_CRED_NO_SYSTEM_MAPPER | SCH_USE_STRONG_CRYPTO};
98
98
  }
99
99
  }
@@ -136,18 +136,31 @@ Schannel::TransceiverI::sslHandshake(SecBuffer* initialBuffer)
136
136
 
137
137
  if (_credentials.cCreds > 0)
138
138
  {
139
- for (DWORD i = 0; i < _credentials.cCreds; ++i)
139
+ if (!_credentials.paCred)
140
140
  {
141
- if (!_credentials.paCred[i])
141
+ throw SecurityException(
142
+ __FILE__,
143
+ __LINE__,
144
+ "SSL transport: the provided SCH_CREDENTIALS sets cCreds but paCred is null.");
145
+ }
146
+
147
+ // The credentials callback transfers ownership of the paCred contexts to the transport (see
148
+ // ClientAuthenticationOptions / ServerAuthenticationOptions). Record ownership of every context
149
+ // before validating below, so close() releases the full transferred set even if validation throws
150
+ // (CertFreeCertificateContext(nullptr) is a no-op). They are released in close().
151
+ _allCerts.assign(_credentials.paCred, _credentials.paCred + _credentials.cCreds);
152
+ _credentials.paCred = _allCerts.data();
153
+
154
+ for (PCCERT_CONTEXT certificate : _allCerts)
155
+ {
156
+ if (!certificate)
142
157
  {
143
158
  throw SecurityException(
144
159
  __FILE__,
145
160
  __LINE__,
146
161
  "SSL transport: invalid null certificate in the provided SCH_CREDENTIALS.");
147
162
  }
148
- _allCerts.push_back(CertDuplicateCertificateContext(_credentials.paCred[i]));
149
163
  }
150
- _credentials.paCred = &_allCerts[0];
151
164
  }
152
165
 
153
166
  err = AcquireCredentialsHandle(
@@ -197,6 +210,10 @@ Schannel::TransceiverI::sslHandshake(SecBuffer* initialBuffer)
197
210
  0);
198
211
  if (err != SEC_E_OK && err != SEC_I_CONTINUE_NEEDED)
199
212
  {
213
+ if (outBuffer.pvBuffer)
214
+ {
215
+ FreeContextBuffer(outBuffer.pvBuffer);
216
+ }
200
217
  ostringstream os;
201
218
  os << "SSL transport: handshake failure:\n" << IceInternal::errorToString(err);
202
219
  throw SecurityException(__FILE__, __LINE__, os.str());
@@ -295,6 +312,15 @@ Schannel::TransceiverI::sslHandshake(SecBuffer* initialBuffer)
295
312
  }
296
313
  else if (err != SEC_I_CONTINUE_NEEDED && err != SEC_E_OK)
297
314
  {
315
+ if (outBuffers[0].pvBuffer) // token
316
+ {
317
+ FreeContextBuffer(outBuffers[0].pvBuffer);
318
+ }
319
+ if (outBuffers[1].pvBuffer) // alert
320
+ {
321
+ FreeContextBuffer(outBuffers[1].pvBuffer);
322
+ }
323
+
298
324
  ostringstream os;
299
325
  os << "SSL handshake failure:\n" << IceInternal::errorToString(err);
300
326
  throw SecurityException(__FILE__, __LINE__, os.str());
@@ -552,6 +578,15 @@ Schannel::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
552
578
  }
553
579
  else if (err == SEC_I_RENEGOTIATE)
554
580
  {
581
+ if (_incoming)
582
+ {
583
+ // Reject peer-initiated TLS renegotiation on the server side: it is a CPU-asymmetric
584
+ // denial-of-service primitive on TLS 1.2 and is removed entirely in TLS 1.3.
585
+ throw ProtocolException(
586
+ __FILE__,
587
+ __LINE__,
588
+ "SSL transport: peer-initiated TLS renegotiation is not supported on the server side.");
589
+ }
555
590
  if (_sslConnectionRenegotiating)
556
591
  {
557
592
  throw ProtocolException(
@@ -570,7 +605,15 @@ Schannel::TransceiverI::decryptMessage(IceInternal::Buffer& buffer)
570
605
  memcpy(_extraBuffer.i, extraBuffer->pvBuffer, extraBuffer->cbBuffer);
571
606
  _extraBuffer.i += extraBuffer->cbBuffer;
572
607
  }
573
- return 0;
608
+ // Unlike the SEC_E_OK path below, we deliberately leave _readBuffer untouched here: sslHandshake resumes
609
+ // the handshake from the data still buffered in _readBuffer and moves the trailing post-renegotiation
610
+ // records back to its front, which is how the application data following the renegotiation is recovered.
611
+ // Resetting _readBuffer.i here would underflow that memmove.
612
+ // Return the application data already copied into the caller's buffer during this call (it may be non-zero
613
+ // because earlier records in the same batch were decrypted before this renegotiation request). The caller
614
+ // must advance buf.i by this amount before performing the re-handshake, otherwise the next decryptMessage
615
+ // overwrites these bytes and the plaintext is silently lost.
616
+ return i - buffer.i;
574
617
  }
575
618
  else if (err == SEC_I_CONTEXT_EXPIRED)
576
619
  {
@@ -794,6 +837,9 @@ Schannel::TransceiverI::read(IceInternal::Buffer& buf)
794
837
  }
795
838
 
796
839
  size_t decrypted = decryptMessage(buf);
840
+ // Account for the bytes decryptMessage copied into buf right away, so a renegotiation in the middle of the
841
+ // batch does not drop the plaintext already extracted before it.
842
+ buf.i += decrypted;
797
843
  if (_sslConnectionRenegotiating)
798
844
  {
799
845
  // The peer has requested a renegotiation.
@@ -819,8 +865,6 @@ Schannel::TransceiverI::read(IceInternal::Buffer& buf)
819
865
  }
820
866
  continue;
821
867
  }
822
-
823
- buf.i += decrypted;
824
868
  }
825
869
  _delegate->getNativeInfo()->ready(
826
870
  IceInternal::SocketOperationRead,
@@ -890,10 +934,14 @@ Schannel::TransceiverI::finishRead(IceInternal::Buffer& buf)
890
934
  _delegate->finishRead(_readBuffer);
891
935
  if (_state == StateHandshakeComplete)
892
936
  {
893
- size_t decrypted;
894
- while (true)
937
+ std::byte* const start = buf.i;
938
+ // Decrypt the buffered data into buf, advancing buf.i as we go so that a renegotiation in the middle of the
939
+ // batch does not drop or overwrite the plaintext already extracted. The loop guard matches decryptMessage's
940
+ // precondition: there is buffered (_readBuffer) or unprocessed data left to decrypt.
941
+ while (buf.i != buf.b.end() && (_readBuffer.i != _readBuffer.b.begin() || !_readUnprocessed.b.empty()))
895
942
  {
896
- decrypted = decryptMessage(buf);
943
+ size_t decrypted = decryptMessage(buf);
944
+ buf.i += decrypted;
897
945
  if (_sslConnectionRenegotiating)
898
946
  {
899
947
  // The peer has requested a renegotiation.
@@ -903,31 +951,23 @@ Schannel::TransceiverI::finishRead(IceInternal::Buffer& buf)
903
951
  _extraBuffer.b.begin()};
904
952
  IceInternal::SocketOperation op = sslHandshake(&extraBuffer);
905
953
  _extraBuffer.b.clear();
906
- if (op == IceInternal::SocketOperationNone)
954
+ if (op != IceInternal::SocketOperationNone)
907
955
  {
908
- _sslConnectionRenegotiating = false;
909
- if (buf.i != buf.b.begin())
910
- {
911
- continue;
912
- }
913
- break;
956
+ throw ConnectionLostException(__FILE__, __LINE__);
914
957
  }
915
- throw ConnectionLostException(__FILE__, __LINE__);
958
+ _sslConnectionRenegotiating = false;
959
+ continue;
960
+ }
961
+ if (decrypted == 0)
962
+ {
963
+ // Not enough buffered data to decrypt a complete record; wait for the next read.
964
+ break;
916
965
  }
917
- break;
918
966
  }
919
967
 
920
- if (decrypted > 0)
921
- {
922
- buf.i += decrypted;
923
- _delegate->getNativeInfo()->ready(
924
- IceInternal::SocketOperationRead,
925
- !_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin());
926
- }
927
- else
928
- {
929
- _delegate->getNativeInfo()->ready(IceInternal::SocketOperationRead, false);
930
- }
968
+ _delegate->getNativeInfo()->ready(
969
+ IceInternal::SocketOperationRead,
970
+ buf.i != start && (!_readUnprocessed.b.empty() || _readBuffer.i != _readBuffer.b.begin()));
931
971
  }
932
972
  }
933
973
 
@@ -1065,8 +1105,8 @@ Schannel::TransceiverI::TransceiverI(
1065
1105
  false); // Whether or not revocation checks only uses cached information.
1066
1106
  };
1067
1107
  }
1068
- // If the user provides a validation callback is up to the callback to validate the certificate chain.
1069
- // If the user doesn't set the trusted root certificates, we use Schannel default behavior, with uses the system
1108
+ // If the user provides a validation callback, it is up to the callback to validate the certificate chain.
1109
+ // If the user doesn't set the trusted root certificates, we use Schannel default behavior, which uses the system
1070
1110
  // trusted root certificates.
1071
1111
  }
1072
1112
 
@@ -95,7 +95,6 @@ namespace Ice::SSL::Schannel
95
95
  std::function<SCH_CREDENTIALS(const std::string&)> _localCredentialsSelectionCallback;
96
96
  std::function<void(CtxtHandle context, const std::string& host)> _sslNewSessionCallback;
97
97
  SecPkgContext_StreamSizes _sizes;
98
- std::string _cipher;
99
98
  PCCERT_CONTEXT _peerCertificate;
100
99
  std::function<bool(CtxtHandle, const Ice::SSL::ConnectionInfoPtr&)> _remoteCertificateValidationCallback;
101
100
  bool _clientCertificateRequired;