diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/IceSSL/.depend | 2 | ||||
-rw-r--r-- | cpp/src/IceSSL/Certificate.cpp | 1 | ||||
-rw-r--r-- | cpp/src/IceSSL/Instance.cpp | 154 |
3 files changed, 84 insertions, 73 deletions
diff --git a/cpp/src/IceSSL/.depend b/cpp/src/IceSSL/.depend index e3f69e69e02..207cb3e7805 100644 --- a/cpp/src/IceSSL/.depend +++ b/cpp/src/IceSSL/.depend @@ -1,5 +1,5 @@ AcceptorI$(OBJEXT): AcceptorI.cpp ../IceSSL/AcceptorI.h $(includedir)/Ice/LoggerF.h $(includedir)/Ice/LocalObjectF.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/Ice/Handle.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/UndefSysMacros.h ../Ice/TransceiverF.h ../Ice/Acceptor.h ../Ice/AcceptorF.h $(includedir)/Ice/Protocol.h ../IceSSL/InstanceF.h ../IceSSL/Instance.h ../IceSSL/UtilF.h $(includedir)/Ice/CommunicatorF.h ../Ice/Network.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Proxy.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/ProtocolPluginFacadeF.h $(includedir)/IceSSL/Plugin.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/BuiltinSequences.h ../IceSSL/TrustManagerF.h ../IceSSL/TransceiverI.h $(includedir)/Ice/StatsF.h ../Ice/Transceiver.h ../Ice/SelectorF.h ../IceSSL/Util.h $(includedir)/Ice/Communicator.h $(includedir)/Ice/ObjectFactoryF.h $(includedir)/Ice/RouterF.h $(includedir)/Ice/LocatorF.h $(includedir)/Ice/PluginF.h $(includedir)/Ice/ImplicitContextF.h $(includedir)/Ice/LocalException.h $(includedir)/Ice/LoggerUtil.h $(includedir)/Ice/Properties.h $(includedir)/Ice/Outgoing.h $(includedir)/IceUtil/Monitor.h $(includedir)/IceUtil/Cond.h $(includedir)/Ice/InstanceF.h $(includedir)/Ice/BasicStream.h $(includedir)/Ice/Buffer.h $(includedir)/Ice/StringConverter.h $(includedir)/IceUtil/Unicode.h $(includedir)/Ice/OutgoingAsync.h $(includedir)/IceUtil/Timer.h $(includedir)/IceUtil/Thread.h $(includedir)/Ice/Incoming.h $(includedir)/Ice/ServantLocatorF.h $(includedir)/Ice/ServantManagerF.h $(includedir)/Ice/Direct.h -Certificate$(OBJEXT): Certificate.cpp $(includedir)/IceUtil/DisableWarnings.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/IceUtil/MutexPtrLock.h $(includedir)/IceSSL/Plugin.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/LocalObjectF.h $(includedir)/IceUtil/Shared.h $(includedir)/Ice/Handle.h $(includedir)/IceUtil/Handle.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/Proxy.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/UndefSysMacros.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/CommunicatorF.h $(includedir)/Ice/LoggerF.h $(includedir)/Ice/BuiltinSequences.h ../IceSSL/Util.h ../IceSSL/UtilF.h ../Ice/Network.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/Protocol.h ../IceSSL/RFC2253.h +Certificate$(OBJEXT): Certificate.cpp $(includedir)/IceUtil/DisableWarnings.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/IceUtil/MutexPtrLock.h $(includedir)/IceUtil/StringUtil.h $(includedir)/IceSSL/Plugin.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/LocalObjectF.h $(includedir)/IceUtil/Shared.h $(includedir)/Ice/Handle.h $(includedir)/IceUtil/Handle.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/Proxy.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/UndefSysMacros.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/CommunicatorF.h $(includedir)/Ice/LoggerF.h $(includedir)/Ice/BuiltinSequences.h ../IceSSL/Util.h ../IceSSL/UtilF.h ../Ice/Network.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/Protocol.h ../IceSSL/RFC2253.h ConnectorI$(OBJEXT): ConnectorI.cpp ../IceSSL/ConnectorI.h $(includedir)/Ice/LoggerF.h $(includedir)/Ice/LocalObjectF.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/Ice/Handle.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/UndefSysMacros.h ../Ice/TransceiverF.h ../Ice/Connector.h ../Ice/ConnectorF.h ../IceSSL/InstanceF.h ../IceSSL/Instance.h ../IceSSL/UtilF.h $(includedir)/Ice/CommunicatorF.h ../Ice/Network.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Proxy.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/Protocol.h $(includedir)/Ice/ProtocolPluginFacadeF.h $(includedir)/IceSSL/Plugin.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/BuiltinSequences.h ../IceSSL/TrustManagerF.h ../IceSSL/TransceiverI.h $(includedir)/Ice/StatsF.h ../Ice/Transceiver.h ../Ice/SelectorF.h ../IceSSL/EndpointI.h ../Ice/EndpointI.h $(includedir)/IceUtil/Thread.h $(includedir)/IceUtil/Monitor.h $(includedir)/IceUtil/Cond.h $(includedir)/Ice/Endpoint.h $(includedir)/Ice/InstanceF.h ../Ice/AcceptorF.h $(includedir)/Ice/EndpointFactory.h $(includedir)/Ice/EndpointFactoryF.h $(includedir)/IceSSL/Endpoint.h ../IceSSL/Util.h $(includedir)/Ice/Communicator.h $(includedir)/Ice/ObjectFactoryF.h $(includedir)/Ice/RouterF.h $(includedir)/Ice/LocatorF.h $(includedir)/Ice/PluginF.h $(includedir)/Ice/ImplicitContextF.h $(includedir)/Ice/LocalException.h $(includedir)/Ice/LoggerUtil.h Endpoint$(OBJEXT): Endpoint.cpp $(includedir)/IceSSL/Endpoint.h $(includedir)/Ice/LocalObjectF.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/Ice/Handle.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/Proxy.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/UndefSysMacros.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/CommunicatorF.h $(includedir)/Ice/Endpoint.h $(includedir)/Ice/BuiltinSequences.h $(includedir)/Ice/BasicStream.h $(includedir)/Ice/InstanceF.h $(includedir)/Ice/ObjectFactoryF.h $(includedir)/Ice/Buffer.h $(includedir)/Ice/Protocol.h $(includedir)/Ice/StringConverter.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/LoggerF.h $(includedir)/IceUtil/Unicode.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/IceUtil/Iterator.h $(includedir)/IceUtil/ScopedArray.h $(includedir)/IceUtil/DisableWarnings.h EndpointI$(OBJEXT): EndpointI.cpp ../IceSSL/EndpointI.h ../Ice/EndpointI.h $(includedir)/IceUtil/Shared.h $(includedir)/IceUtil/Config.h $(includedir)/IceUtil/Thread.h $(includedir)/IceUtil/Handle.h $(includedir)/IceUtil/Exception.h $(includedir)/IceUtil/Mutex.h $(includedir)/IceUtil/Lock.h $(includedir)/IceUtil/ThreadException.h $(includedir)/IceUtil/Time.h $(includedir)/IceUtil/MutexProtocol.h $(includedir)/IceUtil/Monitor.h $(includedir)/IceUtil/Cond.h $(includedir)/Ice/Endpoint.h $(includedir)/Ice/LocalObjectF.h $(includedir)/Ice/Handle.h $(includedir)/Ice/Config.h $(includedir)/Ice/ProxyHandle.h $(includedir)/Ice/ProxyF.h $(includedir)/Ice/ObjectF.h $(includedir)/Ice/GCCountMap.h $(includedir)/Ice/GCShared.h $(includedir)/Ice/Exception.h $(includedir)/Ice/LocalObject.h $(includedir)/Ice/Proxy.h $(includedir)/Ice/ProxyFactoryF.h $(includedir)/Ice/ConnectionIF.h $(includedir)/Ice/RequestHandlerF.h $(includedir)/Ice/EndpointIF.h $(includedir)/Ice/EndpointF.h $(includedir)/Ice/UndefSysMacros.h $(includedir)/Ice/EndpointTypes.h $(includedir)/Ice/ObjectAdapterF.h $(includedir)/Ice/ReferenceF.h $(includedir)/Ice/OutgoingAsyncF.h $(includedir)/Ice/Current.h $(includedir)/Ice/ConnectionF.h $(includedir)/Ice/Identity.h $(includedir)/Ice/StreamF.h $(includedir)/Ice/CommunicatorF.h $(includedir)/Ice/BuiltinSequences.h $(includedir)/Ice/InstanceF.h ../Ice/TransceiverF.h ../Ice/ConnectorF.h ../Ice/AcceptorF.h $(includedir)/Ice/Protocol.h $(includedir)/Ice/EndpointFactory.h $(includedir)/Ice/EndpointFactoryF.h $(includedir)/IceSSL/Endpoint.h ../IceSSL/InstanceF.h ../IceSSL/AcceptorI.h $(includedir)/Ice/LoggerF.h ../Ice/Acceptor.h ../IceSSL/ConnectorI.h ../Ice/Connector.h ../IceSSL/TransceiverI.h $(includedir)/IceSSL/Plugin.h $(includedir)/Ice/Plugin.h $(includedir)/Ice/StatsF.h ../Ice/Transceiver.h ../Ice/SelectorF.h ../IceSSL/Instance.h ../IceSSL/UtilF.h ../Ice/Network.h $(includedir)/Ice/PropertiesF.h $(includedir)/Ice/Object.h $(includedir)/Ice/IncomingAsyncF.h $(includedir)/Ice/ProtocolPluginFacadeF.h ../IceSSL/TrustManagerF.h $(includedir)/Ice/BasicStream.h $(includedir)/Ice/ObjectFactoryF.h $(includedir)/Ice/Buffer.h $(includedir)/Ice/StringConverter.h $(includedir)/IceUtil/Unicode.h $(includedir)/Ice/LocalException.h ../Ice/DefaultsAndOverrides.h ../Ice/DefaultsAndOverridesF.h diff --git a/cpp/src/IceSSL/Certificate.cpp b/cpp/src/IceSSL/Certificate.cpp index dc9e0f940fa..5f12222c89f 100644 --- a/cpp/src/IceSSL/Certificate.cpp +++ b/cpp/src/IceSSL/Certificate.cpp @@ -10,6 +10,7 @@ #include <IceUtil/DisableWarnings.h> #include <IceUtil/Mutex.h> #include <IceUtil/MutexPtrLock.h> +#include <IceUtil/StringUtil.h> #include <IceSSL/Plugin.h> #include <IceSSL/Util.h> #include <IceSSL/RFC2253.h> diff --git a/cpp/src/IceSSL/Instance.cpp b/cpp/src/IceSSL/Instance.cpp index 6983eda8c97..704fdb118ee 100644 --- a/cpp/src/IceSSL/Instance.cpp +++ b/cpp/src/IceSSL/Instance.cpp @@ -389,7 +389,7 @@ IceSSL::Instance::initialize() { ERR_clear_error(); err = SSL_CTX_load_verify_locations(_ctx, file, dir); - if(err || !passwordError()) + if(err) { break; } @@ -459,7 +459,7 @@ IceSSL::Instance::initialize() { ERR_clear_error(); err = SSL_CTX_use_certificate_chain_file(_ctx, file.c_str()); - if(err || !passwordError()) + if(err) { break; } @@ -524,7 +524,7 @@ IceSSL::Instance::initialize() { ERR_clear_error(); err = SSL_CTX_use_PrivateKey_file(_ctx, file.c_str(), SSL_FILETYPE_PEM); - if(err || !passwordError()) + if(err) { break; } @@ -789,11 +789,15 @@ IceSSL::Instance::verifyPeer(SSL* ssl, SOCKET fd, const string& address, const s } // - // Extract the IP addresses and the DNS names from the subject - // alternative names. + // For an outgoing connection, we compare the proxy address (if any) against + // fields in the server's certificate (if any). // - if(cert) + if(cert && !address.empty()) { + // + // Extract the IP addresses and the DNS names from the subject + // alternative names. + // vector<pair<int, string> > subjectAltNames = cert->getSubjectAlternativeNames(); vector<string> ipAddresses; vector<string> dnsNames; @@ -801,95 +805,101 @@ IceSSL::Instance::verifyPeer(SSL* ssl, SOCKET fd, const string& address, const s { if(p->first == 7) { - ipAddresses.push_back(p->second); + ipAddresses.push_back(IceUtilInternal::toLower(p->second)); } else if(p->first == 2) { - dnsNames.push_back(p->second); + dnsNames.push_back(IceUtilInternal::toLower(p->second)); } } // - // Compare the peer's address against the dnsName and ipAddress values. - // This is only relevant for an outgoing connection. + // Compare the peer's address against the common name. // - if(!address.empty()) + bool certNameOK = false; + string dn; + string addrLower = IceUtilInternal::toLower(address); { - bool certNameOK = false; - - for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end() && !certNameOK; ++p) + DistinguishedName d = cert->getSubjectDN(); + dn = IceUtilInternal::toLower(string(d)); + string cn = "cn=" + addrLower; + string::size_type pos = dn.find(cn); + if(pos != string::npos) { - if(address == *p) - { - certNameOK = true; - break; - } + // + // Ensure we match the entire common name. + // + certNameOK = (pos + cn.size() == dn.size()) || (dn[pos + cn.size()] == ','); } + } - if(!certNameOK && !dnsNames.empty()) + // + // Compare the peer's address against the the dnsName and ipAddress + // values in the subject alternative name. + // + if(!certNameOK) + { + certNameOK = find(ipAddresses.begin(), ipAddresses.end(), addrLower) != ipAddresses.end(); + } + if(!certNameOK) + { + certNameOK = find(dnsNames.begin(), dnsNames.end(), addrLower) != dnsNames.end(); + } + + // + // Log a message if the name comparison fails. If CheckCertName is defined, + // we also raise an exception to abort the connection. Don't log a message if + // CheckCertName is not defined and a verifier is present. + // + if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && !_verifier))) + { + ostringstream ostr; + ostr << "IceSSL: "; + if(!_checkCertName) { - string host = IceUtilInternal::toLower(address); - for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end() && !certNameOK; ++p) - { - string s = IceUtilInternal::toLower(*p); - if(host == s) - { - certNameOK = true; - } - } + ostr << "ignoring "; } - - // - // Log a message if the name comparison fails. If CheckCertName is defined, - // we also raise an exception to abort the connection. Don't log a message if - // CheckCertName is not defined and a verifier is present. - // - if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && !_verifier))) + ostr << "certificate validation failure:\npeer certificate does not have `" << address + << "' as its commonName or in its subjectAltName extension"; + if(!dn.empty()) { - ostringstream ostr; - ostr << "IceSSL: "; - if(!_checkCertName) - { - ostr << "ignoring "; - } - ostr << "certificate validation failure:\npeer certificate does not contain `" - << address << "' in its subjectAltName extension"; - if(!dnsNames.empty()) + ostr << "\nSubject DN: " << dn; + } + if(!dnsNames.empty()) + { + ostr << "\nDNS names found in certificate: "; + for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end(); ++p) { - ostr << "\nDNS names found in certificate: "; - for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end(); ++p) + if(p != dnsNames.begin()) { - if(p != dnsNames.begin()) - { - ostr << ", "; - } - ostr << *p; + ostr << ", "; } + ostr << *p; } - if(!ipAddresses.empty()) + } + if(!ipAddresses.empty()) + { + ostr << "\nIP addresses found in certificate: "; + for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end(); ++p) { - ostr << "\nIP addresses found in certificate: "; - for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end(); ++p) + if(p != ipAddresses.begin()) { - if(p != ipAddresses.begin()) - { - ostr << ", "; - } - ostr << *p; + ostr << ", "; } + ostr << *p; } - string msg = ostr.str(); - if(_securityTraceLevel >= 1) - { - Trace out(_logger, _securityTraceCategory); - out << msg; - } - if(_checkCertName) - { - SecurityException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; - } + } + string msg = ostr.str(); + if(_securityTraceLevel >= 1) + { + Trace out(_logger, _securityTraceCategory); + out << msg; + } + if(_checkCertName) + { + SecurityException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } } } |