| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/ocsp/nss_ocsp.h" | 5 #include "net/ocsp/nss_ocsp.h" |
| 6 | 6 |
| 7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 | 7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 |
| 8 // until NSS 3.12.2 comes out and we update to it. | 8 // until NSS 3.12.2 comes out and we update to it. |
| 9 #define Lock FOO_NSS_Lock | 9 #define Lock FOO_NSS_Lock |
| 10 #include <certt.h> | 10 #include <certt.h> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "net/url_request/url_request_context.h" | 31 #include "net/url_request/url_request_context.h" |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 static const int kRecvBufferSize = 4096; | 35 static const int kRecvBufferSize = 4096; |
| 36 | 36 |
| 37 // All OCSP handlers should be called in the context of | 37 // All OCSP handlers should be called in the context of |
| 38 // CertVerifier's thread (i.e. worker pool, not on the I/O thread). | 38 // CertVerifier's thread (i.e. worker pool, not on the I/O thread). |
| 39 // It supports blocking mode only. | 39 // It supports blocking mode only. |
| 40 | 40 |
| 41 class OCSPInitSingleton { | 41 class OCSPInitSingleton : public MessageLoop::DestructionObserver { |
| 42 public: | 42 public: |
| 43 virtual void WillDestroyCurrentMessageLoop() { |
| 44 io_loop_ = NULL; |
| 45 }; |
| 46 |
| 43 MessageLoop* io_thread() const { | 47 MessageLoop* io_thread() const { |
| 44 DCHECK(io_loop_); | |
| 45 return io_loop_; | 48 return io_loop_; |
| 46 } | 49 } |
| 47 | 50 |
| 48 // This is static method because it is called before NSS initialization, | 51 // This is static method because it is called before NSS initialization, |
| 49 // that is, before OCSPInitSingleton is initialized. | 52 // that is, before OCSPInitSingleton is initialized. |
| 50 static void set_url_request_context(URLRequestContext* request_context) { | 53 static void set_url_request_context(URLRequestContext* request_context) { |
| 51 request_context_ = request_context; | 54 request_context_ = request_context; |
| 52 } | 55 } |
| 53 URLRequestContext* url_request_context() const { | 56 URLRequestContext* url_request_context() const { |
| 54 return request_context_.get(); | 57 return request_context_.get(); |
| 55 } | 58 } |
| 56 | 59 |
| 57 private: | 60 private: |
| 58 friend struct DefaultSingletonTraits<OCSPInitSingleton>; | 61 friend struct DefaultSingletonTraits<OCSPInitSingleton>; |
| 59 OCSPInitSingleton(); | 62 OCSPInitSingleton(); |
| 60 ~OCSPInitSingleton() { | 63 virtual ~OCSPInitSingleton() { |
| 61 request_context_ = NULL; | 64 request_context_ = NULL; |
| 62 } | 65 } |
| 63 | 66 |
| 64 SEC_HttpClientFcn client_fcn_; | 67 SEC_HttpClientFcn client_fcn_; |
| 65 | 68 |
| 66 // I/O thread. | 69 // I/O thread. |
| 67 MessageLoop* io_loop_; // I/O thread | 70 MessageLoop* io_loop_; // I/O thread |
| 68 | 71 |
| 69 // URLRequestContext for OCSP handlers. | 72 // URLRequestContext for OCSP handlers. |
| 70 static scoped_refptr<URLRequestContext> request_context_; | 73 static scoped_refptr<URLRequestContext> request_context_; |
| 71 | 74 |
| 72 DISALLOW_COPY_AND_ASSIGN(OCSPInitSingleton); | 75 DISALLOW_COPY_AND_ASSIGN(OCSPInitSingleton); |
| 73 }; | 76 }; |
| 74 | 77 |
| 75 scoped_refptr<URLRequestContext> OCSPInitSingleton::request_context_; | 78 scoped_refptr<URLRequestContext> OCSPInitSingleton::request_context_; |
| 76 | 79 |
| 77 // Concrete class for SEC_HTTP_REQUEST_SESSION. | 80 // Concrete class for SEC_HTTP_REQUEST_SESSION. |
| 78 // Public methods except virtual methods of URLRequest::Delegate (On* methods) | 81 // Public methods except virtual methods of URLRequest::Delegate (On* methods) |
| 79 // run on certificate verifier thread (worker thread). | 82 // run on certificate verifier thread (worker thread). |
| 80 // Virtual methods of URLRequest::Delegate and private methods run | 83 // Virtual methods of URLRequest::Delegate and private methods run |
| 81 // on IO thread. | 84 // on IO thread. |
| 82 class OCSPRequestSession | 85 class OCSPRequestSession |
| 83 : public base::RefCountedThreadSafe<OCSPRequestSession>, | 86 : public base::RefCountedThreadSafe<OCSPRequestSession>, |
| 84 public URLRequest::Delegate { | 87 public URLRequest::Delegate, |
| 88 public MessageLoop::DestructionObserver { |
| 85 public: | 89 public: |
| 86 OCSPRequestSession(const GURL& url, | 90 OCSPRequestSession(const GURL& url, |
| 87 const char* http_request_method, | 91 const char* http_request_method, |
| 88 base::TimeDelta timeout) | 92 base::TimeDelta timeout) |
| 89 : url_(url), | 93 : url_(url), |
| 90 http_request_method_(http_request_method), | 94 http_request_method_(http_request_method), |
| 91 timeout_(timeout), | 95 timeout_(timeout), |
| 92 io_loop_(Singleton<OCSPInitSingleton>::get()->io_thread()), | 96 io_loop_(Singleton<OCSPInitSingleton>::get()->io_thread()), |
| 93 request_(NULL), | 97 request_(NULL), |
| 94 buffer_(new net::IOBuffer(kRecvBufferSize)), | 98 buffer_(new net::IOBuffer(kRecvBufferSize)), |
| 95 response_code_(-1), | 99 response_code_(-1), |
| 96 cv_(&lock_), | 100 cv_(&lock_), |
| 97 finished_(false) {} | 101 finished_(false) {} |
| 98 | 102 |
| 99 void SetPostData(const char* http_data, PRUint32 http_data_len, | 103 void SetPostData(const char* http_data, PRUint32 http_data_len, |
| 100 const char* http_content_type) { | 104 const char* http_content_type) { |
| 101 upload_content_.assign(http_data, http_data_len); | 105 upload_content_.assign(http_data, http_data_len); |
| 102 upload_content_type_.assign(http_content_type); | 106 upload_content_type_.assign(http_content_type); |
| 103 } | 107 } |
| 104 | 108 |
| 105 void AddHeader(const char* http_header_name, const char* http_header_value) { | 109 void AddHeader(const char* http_header_name, const char* http_header_value) { |
| 106 if (!extra_request_headers_.empty()) | 110 if (!extra_request_headers_.empty()) |
| 107 extra_request_headers_ += "\r\n"; | 111 extra_request_headers_ += "\r\n"; |
| 108 StringAppendF(&extra_request_headers_, | 112 StringAppendF(&extra_request_headers_, |
| 109 "%s: %s", http_header_name, http_header_value); | 113 "%s: %s", http_header_name, http_header_value); |
| 110 } | 114 } |
| 111 | 115 |
| 112 void Start() { | 116 void Start() { |
| 113 DCHECK(io_loop_); | 117 if (io_loop_) { |
| 114 io_loop_->PostTask( | 118 io_loop_->PostTask( |
| 115 FROM_HERE, | 119 FROM_HERE, |
| 116 NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest)); | 120 NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest)); |
| 121 } |
| 117 } | 122 } |
| 118 | 123 |
| 119 bool Started() const { | 124 bool Started() const { |
| 120 return request_ != NULL; | 125 return request_ != NULL; |
| 121 } | 126 } |
| 122 | 127 |
| 123 void Cancel() { | 128 void Cancel() { |
| 124 io_loop_->PostTask( | 129 if (io_loop_) { |
| 125 FROM_HERE, | 130 io_loop_->PostTask( |
| 126 NewRunnableMethod(this, &OCSPRequestSession::CancelURLRequest)); | 131 FROM_HERE, |
| 132 NewRunnableMethod(this, &OCSPRequestSession::CancelURLRequest)); |
| 133 } |
| 127 } | 134 } |
| 128 | 135 |
| 129 bool Finished() const { | 136 bool Finished() const { |
| 130 AutoLock autolock(lock_); | 137 AutoLock autolock(lock_); |
| 131 return finished_; | 138 return finished_; |
| 132 } | 139 } |
| 133 | 140 |
| 134 bool Wait() { | 141 bool Wait() { |
| 135 base::TimeDelta timeout = timeout_; | 142 base::TimeDelta timeout = timeout_; |
| 136 AutoLock autolock(lock_); | 143 AutoLock autolock(lock_); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 } while (request_->Read(buffer_, kRecvBufferSize, &bytes_read)); | 214 } while (request_->Read(buffer_, kRecvBufferSize, &bytes_read)); |
| 208 | 215 |
| 209 if (!request_->status().is_io_pending()) { | 216 if (!request_->status().is_io_pending()) { |
| 210 { | 217 { |
| 211 AutoLock autolock(lock_); | 218 AutoLock autolock(lock_); |
| 212 finished_ = true; | 219 finished_ = true; |
| 213 } | 220 } |
| 214 cv_.Signal(); | 221 cv_.Signal(); |
| 215 delete request_; | 222 delete request_; |
| 216 request_ = NULL; | 223 request_ = NULL; |
| 224 io_loop_->RemoveDestructionObserver(this); |
| 225 io_loop_ = NULL; |
| 217 } | 226 } |
| 218 } | 227 } |
| 219 | 228 |
| 229 virtual void WillDestroyCurrentMessageLoop() { |
| 230 DCHECK(MessageLoopForIO::current() == io_loop_); |
| 231 if (request_) { |
| 232 request_->Cancel(); |
| 233 delete request_; |
| 234 request_ = NULL; |
| 235 } |
| 236 io_loop_ = NULL; |
| 237 } |
| 238 |
| 220 private: | 239 private: |
| 221 friend class base::RefCountedThreadSafe<OCSPRequestSession>; | 240 friend class base::RefCountedThreadSafe<OCSPRequestSession>; |
| 222 | 241 |
| 223 virtual ~OCSPRequestSession() { | 242 virtual ~OCSPRequestSession() { |
| 224 DCHECK(!request_); | 243 DCHECK(!request_); |
| 244 if (io_loop_) |
| 245 io_loop_->RemoveDestructionObserver(this); |
| 246 io_loop_ = NULL; |
| 225 } | 247 } |
| 226 | 248 |
| 227 void StartURLRequest() { | 249 void StartURLRequest() { |
| 228 DCHECK(MessageLoopForIO::current() == io_loop_); | 250 DCHECK(MessageLoopForIO::current() == io_loop_); |
| 229 DCHECK(!request_); | 251 DCHECK(!request_); |
| 230 | 252 |
| 253 io_loop_->AddDestructionObserver(this); |
| 254 |
| 231 request_ = new URLRequest(url_, this); | 255 request_ = new URLRequest(url_, this); |
| 232 request_->set_context( | 256 request_->set_context( |
| 233 Singleton<OCSPInitSingleton>::get()->url_request_context()); | 257 Singleton<OCSPInitSingleton>::get()->url_request_context()); |
| 234 // To meet the privacy requirements of off-the-record mode. | 258 // To meet the privacy requirements of off-the-record mode. |
| 235 request_->set_load_flags( | 259 request_->set_load_flags( |
| 236 net::LOAD_DISABLE_CACHE|net::LOAD_DO_NOT_SAVE_COOKIES); | 260 net::LOAD_DISABLE_CACHE|net::LOAD_DO_NOT_SAVE_COOKIES); |
| 237 | 261 |
| 238 if (http_request_method_ == "POST") { | 262 if (http_request_method_ == "POST") { |
| 239 DCHECK(!upload_content_.empty()); | 263 DCHECK(!upload_content_.empty()); |
| 240 DCHECK(!upload_content_type_.empty()); | 264 DCHECK(!upload_content_type_.empty()); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 LOG(INFO) << "OCSP free"; | 517 LOG(INFO) << "OCSP free"; |
| 494 DCHECK(!MessageLoop::current()); | 518 DCHECK(!MessageLoop::current()); |
| 495 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); | 519 OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request); |
| 496 req->Cancel(); | 520 req->Cancel(); |
| 497 req->Release(); | 521 req->Release(); |
| 498 return SECSuccess; | 522 return SECSuccess; |
| 499 } | 523 } |
| 500 | 524 |
| 501 OCSPInitSingleton::OCSPInitSingleton() | 525 OCSPInitSingleton::OCSPInitSingleton() |
| 502 : io_loop_(MessageLoopForIO::current()) { | 526 : io_loop_(MessageLoopForIO::current()) { |
| 527 io_loop_->AddDestructionObserver(this); |
| 503 client_fcn_.version = 1; | 528 client_fcn_.version = 1; |
| 504 SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1; | 529 SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1; |
| 505 ft->createSessionFcn = OCSPCreateSession; | 530 ft->createSessionFcn = OCSPCreateSession; |
| 506 ft->keepAliveSessionFcn = OCSPKeepAliveSession; | 531 ft->keepAliveSessionFcn = OCSPKeepAliveSession; |
| 507 ft->freeSessionFcn = OCSPFreeSession; | 532 ft->freeSessionFcn = OCSPFreeSession; |
| 508 ft->createFcn = OCSPCreate; | 533 ft->createFcn = OCSPCreate; |
| 509 ft->setPostDataFcn = OCSPSetPostData; | 534 ft->setPostDataFcn = OCSPSetPostData; |
| 510 ft->addHeaderFcn = OCSPAddHeader; | 535 ft->addHeaderFcn = OCSPAddHeader; |
| 511 ft->trySendAndReceiveFcn = OCSPTrySendAndReceive; | 536 ft->trySendAndReceiveFcn = OCSPTrySendAndReceive; |
| 512 ft->cancelFcn = NULL; | 537 ft->cancelFcn = NULL; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 524 void EnsureOCSPInit() { | 549 void EnsureOCSPInit() { |
| 525 Singleton<OCSPInitSingleton>::get(); | 550 Singleton<OCSPInitSingleton>::get(); |
| 526 } | 551 } |
| 527 | 552 |
| 528 // This function would be called before NSS initialization. | 553 // This function would be called before NSS initialization. |
| 529 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { | 554 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { |
| 530 OCSPInitSingleton::set_url_request_context(request_context); | 555 OCSPInitSingleton::set_url_request_context(request_context); |
| 531 } | 556 } |
| 532 | 557 |
| 533 } // namespace net | 558 } // namespace net |
| OLD | NEW |