TLSServerSocket.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /* vim:set ts=2 sw=2 et cindent: */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "TLSServerSocket.h"
  6. #include "mozilla/net/DNS.h"
  7. #include "nsAutoPtr.h"
  8. #include "nsComponentManagerUtils.h"
  9. #include "nsIServerSocket.h"
  10. #include "nsITimer.h"
  11. #include "nsIX509Cert.h"
  12. #include "nsIX509CertDB.h"
  13. #include "nsNetCID.h"
  14. #include "nsProxyRelease.h"
  15. #include "nsServiceManagerUtils.h"
  16. #include "nsSocketTransport2.h"
  17. #include "nsThreadUtils.h"
  18. #include "ScopedNSSTypes.h"
  19. #include "ssl.h"
  20. namespace mozilla {
  21. namespace net {
  22. //-----------------------------------------------------------------------------
  23. // TLSServerSocket
  24. //-----------------------------------------------------------------------------
  25. TLSServerSocket::TLSServerSocket()
  26. : mServerCert(nullptr)
  27. {
  28. }
  29. TLSServerSocket::~TLSServerSocket()
  30. {
  31. }
  32. NS_IMPL_ISUPPORTS_INHERITED(TLSServerSocket,
  33. nsServerSocket,
  34. nsITLSServerSocket)
  35. nsresult
  36. TLSServerSocket::SetSocketDefaults()
  37. {
  38. // Set TLS options on the listening socket
  39. mFD = SSL_ImportFD(nullptr, mFD);
  40. if (NS_WARN_IF(!mFD)) {
  41. return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  42. }
  43. SSL_OptionSet(mFD, SSL_SECURITY, true);
  44. SSL_OptionSet(mFD, SSL_HANDSHAKE_AS_CLIENT, false);
  45. SSL_OptionSet(mFD, SSL_HANDSHAKE_AS_SERVER, true);
  46. SSL_OptionSet(mFD, SSL_NO_CACHE, true);
  47. // We don't currently notify the server API consumer of renegotiation events
  48. // (to revalidate peer certs, etc.), so disable it for now.
  49. SSL_OptionSet(mFD, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER);
  50. SetSessionTickets(true);
  51. SetRequestClientCertificate(REQUEST_NEVER);
  52. return NS_OK;
  53. }
  54. void
  55. TLSServerSocket::CreateClientTransport(PRFileDesc* aClientFD,
  56. const NetAddr& aClientAddr)
  57. {
  58. MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
  59. nsresult rv;
  60. RefPtr<nsSocketTransport> trans = new nsSocketTransport;
  61. if (NS_WARN_IF(!trans)) {
  62. mCondition = NS_ERROR_OUT_OF_MEMORY;
  63. return;
  64. }
  65. RefPtr<TLSServerConnectionInfo> info = new TLSServerConnectionInfo();
  66. info->mServerSocket = this;
  67. info->mTransport = trans;
  68. nsCOMPtr<nsISupports> infoSupports =
  69. NS_ISUPPORTS_CAST(nsITLSServerConnectionInfo*, info);
  70. rv = trans->InitWithConnectedSocket(aClientFD, &aClientAddr, infoSupports);
  71. if (NS_WARN_IF(NS_FAILED(rv))) {
  72. mCondition = rv;
  73. return;
  74. }
  75. // Override the default peer certificate validation, so that server consumers
  76. // can make their own choice after the handshake completes.
  77. SSL_AuthCertificateHook(aClientFD, AuthCertificateHook, nullptr);
  78. // Once the TLS handshake has completed, the server consumer is notified and
  79. // has access to various TLS state details.
  80. // It's safe to pass info here because the socket transport holds it as
  81. // |mSecInfo| which keeps it alive for the lifetime of the socket.
  82. SSL_HandshakeCallback(aClientFD, TLSServerConnectionInfo::HandshakeCallback,
  83. info);
  84. // Notify the consumer of the new client so it can manage the streams.
  85. // Security details aren't known yet. The security observer will be notified
  86. // later when they are ready.
  87. nsCOMPtr<nsIServerSocket> serverSocket =
  88. do_QueryInterface(NS_ISUPPORTS_CAST(nsITLSServerSocket*, this));
  89. mListener->OnSocketAccepted(serverSocket, trans);
  90. }
  91. nsresult
  92. TLSServerSocket::OnSocketListen()
  93. {
  94. if (NS_WARN_IF(!mServerCert)) {
  95. return NS_ERROR_NOT_INITIALIZED;
  96. }
  97. UniqueCERTCertificate cert(mServerCert->GetCert());
  98. if (NS_WARN_IF(!cert)) {
  99. return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  100. }
  101. UniqueSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert.get(), nullptr));
  102. if (NS_WARN_IF(!key)) {
  103. return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  104. }
  105. SSLKEAType certKEA = NSS_FindCertKEAType(cert.get());
  106. nsresult rv = MapSECStatus(SSL_ConfigSecureServer(mFD, cert.get(), key.get(),
  107. certKEA));
  108. if (NS_WARN_IF(NS_FAILED(rv))) {
  109. return rv;
  110. }
  111. return NS_OK;
  112. }
  113. // static
  114. SECStatus
  115. TLSServerSocket::AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig,
  116. PRBool isServer)
  117. {
  118. // Allow any client cert here, server consumer code can decide whether it's
  119. // okay after being notified of the new client socket.
  120. return SECSuccess;
  121. }
  122. //-----------------------------------------------------------------------------
  123. // TLSServerSocket::nsITLSServerSocket
  124. //-----------------------------------------------------------------------------
  125. NS_IMETHODIMP
  126. TLSServerSocket::GetServerCert(nsIX509Cert** aCert)
  127. {
  128. if (NS_WARN_IF(!aCert)) {
  129. return NS_ERROR_INVALID_POINTER;
  130. }
  131. *aCert = mServerCert;
  132. NS_IF_ADDREF(*aCert);
  133. return NS_OK;
  134. }
  135. NS_IMETHODIMP
  136. TLSServerSocket::SetServerCert(nsIX509Cert* aCert)
  137. {
  138. // If AsyncListen was already called (and set mListener), it's too late to set
  139. // this.
  140. if (NS_WARN_IF(mListener)) {
  141. return NS_ERROR_IN_PROGRESS;
  142. }
  143. mServerCert = aCert;
  144. return NS_OK;
  145. }
  146. NS_IMETHODIMP
  147. TLSServerSocket::SetSessionTickets(bool aEnabled)
  148. {
  149. // If AsyncListen was already called (and set mListener), it's too late to set
  150. // this.
  151. if (NS_WARN_IF(mListener)) {
  152. return NS_ERROR_IN_PROGRESS;
  153. }
  154. SSL_OptionSet(mFD, SSL_ENABLE_SESSION_TICKETS, aEnabled);
  155. return NS_OK;
  156. }
  157. NS_IMETHODIMP
  158. TLSServerSocket::SetRequestClientCertificate(uint32_t aMode)
  159. {
  160. // If AsyncListen was already called (and set mListener), it's too late to set
  161. // this.
  162. if (NS_WARN_IF(mListener)) {
  163. return NS_ERROR_IN_PROGRESS;
  164. }
  165. SSL_OptionSet(mFD, SSL_REQUEST_CERTIFICATE, aMode != REQUEST_NEVER);
  166. switch (aMode) {
  167. case REQUEST_ALWAYS:
  168. SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NO_ERROR);
  169. break;
  170. case REQUIRE_FIRST_HANDSHAKE:
  171. SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_FIRST_HANDSHAKE);
  172. break;
  173. case REQUIRE_ALWAYS:
  174. SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_ALWAYS);
  175. break;
  176. default:
  177. SSL_OptionSet(mFD, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER);
  178. }
  179. return NS_OK;
  180. }
  181. NS_IMETHODIMP
  182. TLSServerSocket::SetCipherSuites(uint16_t* aCipherSuites, uint32_t aLength)
  183. {
  184. // If AsyncListen was already called (and set mListener), it's too late to set
  185. // this.
  186. if (NS_WARN_IF(mListener)) {
  187. return NS_ERROR_IN_PROGRESS;
  188. }
  189. for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
  190. uint16_t cipher_id = SSL_ImplementedCiphers[i];
  191. if (SSL_CipherPrefSet(mFD, cipher_id, false) != SECSuccess) {
  192. return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  193. }
  194. }
  195. for (uint32_t i = 0; i < aLength; ++i) {
  196. if (SSL_CipherPrefSet(mFD, aCipherSuites[i], true) != SECSuccess) {
  197. return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  198. }
  199. }
  200. return NS_OK;
  201. }
  202. NS_IMETHODIMP
  203. TLSServerSocket::SetVersionRange(uint16_t aMinVersion, uint16_t aMaxVersion)
  204. {
  205. // If AsyncListen was already called (and set mListener), it's too late to set
  206. // this.
  207. if (NS_WARN_IF(mListener)) {
  208. return NS_ERROR_IN_PROGRESS;
  209. }
  210. SSLVersionRange range = {aMinVersion, aMaxVersion};
  211. if (SSL_VersionRangeSet(mFD, &range) != SECSuccess) {
  212. return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  213. }
  214. return NS_OK;
  215. }
  216. //-----------------------------------------------------------------------------
  217. // TLSServerConnectionInfo
  218. //-----------------------------------------------------------------------------
  219. namespace {
  220. class TLSServerSecurityObserverProxy final : public nsITLSServerSecurityObserver
  221. {
  222. ~TLSServerSecurityObserverProxy() {}
  223. public:
  224. explicit TLSServerSecurityObserverProxy(nsITLSServerSecurityObserver* aListener)
  225. : mListener(new nsMainThreadPtrHolder<nsITLSServerSecurityObserver>(aListener))
  226. { }
  227. NS_DECL_THREADSAFE_ISUPPORTS
  228. NS_DECL_NSITLSSERVERSECURITYOBSERVER
  229. class OnHandshakeDoneRunnable : public Runnable
  230. {
  231. public:
  232. OnHandshakeDoneRunnable(const nsMainThreadPtrHandle<nsITLSServerSecurityObserver>& aListener,
  233. nsITLSServerSocket* aServer,
  234. nsITLSClientStatus* aStatus)
  235. : mListener(aListener)
  236. , mServer(aServer)
  237. , mStatus(aStatus)
  238. { }
  239. NS_DECL_NSIRUNNABLE
  240. private:
  241. nsMainThreadPtrHandle<nsITLSServerSecurityObserver> mListener;
  242. nsCOMPtr<nsITLSServerSocket> mServer;
  243. nsCOMPtr<nsITLSClientStatus> mStatus;
  244. };
  245. private:
  246. nsMainThreadPtrHandle<nsITLSServerSecurityObserver> mListener;
  247. };
  248. NS_IMPL_ISUPPORTS(TLSServerSecurityObserverProxy,
  249. nsITLSServerSecurityObserver)
  250. NS_IMETHODIMP
  251. TLSServerSecurityObserverProxy::OnHandshakeDone(nsITLSServerSocket* aServer,
  252. nsITLSClientStatus* aStatus)
  253. {
  254. RefPtr<OnHandshakeDoneRunnable> r =
  255. new OnHandshakeDoneRunnable(mListener, aServer, aStatus);
  256. return NS_DispatchToMainThread(r);
  257. }
  258. NS_IMETHODIMP
  259. TLSServerSecurityObserverProxy::OnHandshakeDoneRunnable::Run()
  260. {
  261. mListener->OnHandshakeDone(mServer, mStatus);
  262. return NS_OK;
  263. }
  264. } // namespace
  265. NS_IMPL_ISUPPORTS(TLSServerConnectionInfo,
  266. nsITLSServerConnectionInfo,
  267. nsITLSClientStatus)
  268. TLSServerConnectionInfo::TLSServerConnectionInfo()
  269. : mServerSocket(nullptr)
  270. , mTransport(nullptr)
  271. , mPeerCert(nullptr)
  272. , mTlsVersionUsed(TLS_VERSION_UNKNOWN)
  273. , mKeyLength(0)
  274. , mMacLength(0)
  275. , mLock("TLSServerConnectionInfo.mLock")
  276. , mSecurityObserver(nullptr)
  277. {
  278. }
  279. TLSServerConnectionInfo::~TLSServerConnectionInfo()
  280. {
  281. if (!mSecurityObserver) {
  282. return;
  283. }
  284. RefPtr<nsITLSServerSecurityObserver> observer;
  285. {
  286. MutexAutoLock lock(mLock);
  287. observer = mSecurityObserver.forget();
  288. }
  289. if (observer) {
  290. NS_ReleaseOnMainThread(observer.forget());
  291. }
  292. }
  293. NS_IMETHODIMP
  294. TLSServerConnectionInfo::SetSecurityObserver(nsITLSServerSecurityObserver* aObserver)
  295. {
  296. {
  297. MutexAutoLock lock(mLock);
  298. mSecurityObserver = new TLSServerSecurityObserverProxy(aObserver);
  299. }
  300. return NS_OK;
  301. }
  302. NS_IMETHODIMP
  303. TLSServerConnectionInfo::GetServerSocket(nsITLSServerSocket** aSocket)
  304. {
  305. if (NS_WARN_IF(!aSocket)) {
  306. return NS_ERROR_INVALID_POINTER;
  307. }
  308. *aSocket = mServerSocket;
  309. NS_IF_ADDREF(*aSocket);
  310. return NS_OK;
  311. }
  312. NS_IMETHODIMP
  313. TLSServerConnectionInfo::GetStatus(nsITLSClientStatus** aStatus)
  314. {
  315. if (NS_WARN_IF(!aStatus)) {
  316. return NS_ERROR_INVALID_POINTER;
  317. }
  318. *aStatus = this;
  319. NS_IF_ADDREF(*aStatus);
  320. return NS_OK;
  321. }
  322. NS_IMETHODIMP
  323. TLSServerConnectionInfo::GetPeerCert(nsIX509Cert** aCert)
  324. {
  325. if (NS_WARN_IF(!aCert)) {
  326. return NS_ERROR_INVALID_POINTER;
  327. }
  328. *aCert = mPeerCert;
  329. NS_IF_ADDREF(*aCert);
  330. return NS_OK;
  331. }
  332. NS_IMETHODIMP
  333. TLSServerConnectionInfo::GetTlsVersionUsed(int16_t* aTlsVersionUsed)
  334. {
  335. if (NS_WARN_IF(!aTlsVersionUsed)) {
  336. return NS_ERROR_INVALID_POINTER;
  337. }
  338. *aTlsVersionUsed = mTlsVersionUsed;
  339. return NS_OK;
  340. }
  341. NS_IMETHODIMP
  342. TLSServerConnectionInfo::GetCipherName(nsACString& aCipherName)
  343. {
  344. aCipherName.Assign(mCipherName);
  345. return NS_OK;
  346. }
  347. NS_IMETHODIMP
  348. TLSServerConnectionInfo::GetCipherSuite(nsACString& aCipherSuite)
  349. {
  350. aCipherSuite.Assign(mCipherSuite);
  351. return NS_OK;
  352. }
  353. NS_IMETHODIMP
  354. TLSServerConnectionInfo::GetKeyLength(uint32_t* aKeyLength)
  355. {
  356. if (NS_WARN_IF(!aKeyLength)) {
  357. return NS_ERROR_INVALID_POINTER;
  358. }
  359. *aKeyLength = mKeyLength;
  360. return NS_OK;
  361. }
  362. NS_IMETHODIMP
  363. TLSServerConnectionInfo::GetMacLength(uint32_t* aMacLength)
  364. {
  365. if (NS_WARN_IF(!aMacLength)) {
  366. return NS_ERROR_INVALID_POINTER;
  367. }
  368. *aMacLength = mMacLength;
  369. return NS_OK;
  370. }
  371. // static
  372. void
  373. TLSServerConnectionInfo::HandshakeCallback(PRFileDesc* aFD, void* aArg)
  374. {
  375. RefPtr<TLSServerConnectionInfo> info =
  376. static_cast<TLSServerConnectionInfo*>(aArg);
  377. nsISocketTransport* transport = info->mTransport;
  378. // No longer needed outside this function, so clear the weak ref
  379. info->mTransport = nullptr;
  380. nsresult rv = info->HandshakeCallback(aFD);
  381. if (NS_WARN_IF(NS_FAILED(rv))) {
  382. transport->Close(rv);
  383. }
  384. }
  385. nsresult
  386. TLSServerConnectionInfo::HandshakeCallback(PRFileDesc* aFD)
  387. {
  388. nsresult rv;
  389. UniqueCERTCertificate clientCert(SSL_PeerCertificate(aFD));
  390. if (clientCert) {
  391. nsCOMPtr<nsIX509CertDB> certDB =
  392. do_GetService(NS_X509CERTDB_CONTRACTID, &rv);
  393. if (NS_FAILED(rv)) {
  394. return rv;
  395. }
  396. nsCOMPtr<nsIX509Cert> clientCertPSM;
  397. rv = certDB->ConstructX509(reinterpret_cast<char*>(clientCert->derCert.data),
  398. clientCert->derCert.len,
  399. getter_AddRefs(clientCertPSM));
  400. if (NS_FAILED(rv)) {
  401. return rv;
  402. }
  403. mPeerCert = clientCertPSM;
  404. }
  405. SSLChannelInfo channelInfo;
  406. rv = MapSECStatus(SSL_GetChannelInfo(aFD, &channelInfo, sizeof(channelInfo)));
  407. if (NS_FAILED(rv)) {
  408. return rv;
  409. }
  410. mTlsVersionUsed = channelInfo.protocolVersion;
  411. SSLCipherSuiteInfo cipherInfo;
  412. rv = MapSECStatus(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
  413. sizeof(cipherInfo)));
  414. if (NS_FAILED(rv)) {
  415. return rv;
  416. }
  417. mCipherName.Assign(cipherInfo.symCipherName);
  418. mCipherSuite.Assign(cipherInfo.cipherSuiteName);
  419. mKeyLength = cipherInfo.effectiveKeyBits;
  420. mMacLength = cipherInfo.macBits;
  421. if (!mSecurityObserver) {
  422. return NS_OK;
  423. }
  424. // Notify consumer code that handshake is complete
  425. nsCOMPtr<nsITLSServerSecurityObserver> observer;
  426. {
  427. MutexAutoLock lock(mLock);
  428. mSecurityObserver.swap(observer);
  429. }
  430. nsCOMPtr<nsITLSServerSocket> serverSocket;
  431. GetServerSocket(getter_AddRefs(serverSocket));
  432. observer->OnHandshakeDone(serverSocket, this);
  433. return NS_OK;
  434. }
  435. } // namespace net
  436. } // namespace mozilla