| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 }; | 73 }; |
| 74 | 74 |
| 75 scoped_refptr<URLRequestContext> OCSPInitSingleton::request_context_; | 75 scoped_refptr<URLRequestContext> OCSPInitSingleton::request_context_; |
| 76 | 76 |
| 77 // Concrete class for SEC_HTTP_REQUEST_SESSION. | 77 // Concrete class for SEC_HTTP_REQUEST_SESSION. |
| 78 class OCSPRequestSession { | 78 class OCSPRequestSession { |
| 79 public: | 79 public: |
| 80 OCSPRequestSession(const GURL& url, | 80 OCSPRequestSession(const GURL& url, |
| 81 const char* http_request_method, | 81 const char* http_request_method, |
| 82 base::TimeDelta timeout); | 82 base::TimeDelta timeout); |
| 83 ~OCSPRequestSession() {} | 83 ~OCSPRequestSession(); |
| 84 | 84 |
| 85 void SetPostData(const char* http_data, | 85 void SetPostData(const char* http_data, |
| 86 const PRUint32 http_data_len, | 86 const PRUint32 http_data_len, |
| 87 const char* http_content_type); | 87 const char* http_content_type); |
| 88 | 88 |
| 89 void AddHeader(const char* http_header_name, | 89 void AddHeader(const char* http_header_name, |
| 90 const char* http_header_value); | 90 const char* http_header_value); |
| 91 | 91 |
| 92 void Start(); | 92 void Start(); |
| 93 bool Started() const; | 93 bool Started() const; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 // This class is the real guts of OCSP handlers. | 130 // This class is the real guts of OCSP handlers. |
| 131 // Public methods except virtual methods of URLRequest::Delegate (On* methods) | 131 // Public methods except virtual methods of URLRequest::Delegate (On* methods) |
| 132 // run on certificate verifier thread (worker thread). | 132 // run on certificate verifier thread (worker thread). |
| 133 // Virtual methods of URLRequest::Delegate and private methods run | 133 // Virtual methods of URLRequest::Delegate and private methods run |
| 134 // on IO thread. | 134 // on IO thread. |
| 135 class OCSPRequestSession::Core | 135 class OCSPRequestSession::Core |
| 136 : public base::RefCountedThreadSafe<OCSPRequestSession::Core>, | 136 : public base::RefCountedThreadSafe<OCSPRequestSession::Core>, |
| 137 public URLRequest::Delegate { | 137 public URLRequest::Delegate { |
| 138 public: | 138 public: |
| 139 explicit Core(OCSPRequestSession* req) | 139 explicit Core(OCSPRequestSession* req) |
| 140 : ocsp_req_(req), | 140 : url_(req->url()), |
| 141 url_(ocsp_req_->url()), | 141 http_request_method_(req->http_request_method()), |
| 142 timeout_(req->timeout()), |
| 142 io_loop_(Singleton<OCSPInitSingleton>::get()->io_thread()), | 143 io_loop_(Singleton<OCSPInitSingleton>::get()->io_thread()), |
| 143 request_(NULL), | 144 request_(NULL), |
| 144 buffer_(new net::IOBuffer(kRecvBufferSize)), | 145 buffer_(new net::IOBuffer(kRecvBufferSize)), |
| 145 response_code_(-1), | 146 response_code_(-1), |
| 146 cv_(&lock_), | 147 cv_(&lock_), |
| 147 finished_(false) {} | 148 finished_(false) {} |
| 148 virtual ~Core() {} | 149 virtual ~Core() { |
| 150 DCHECK(!request_); |
| 151 } |
| 149 | 152 |
| 150 void SetPostData(const char* http_data, PRUint32 http_data_len, | 153 void SetPostData(const char* http_data, PRUint32 http_data_len, |
| 151 const char* http_content_type) { | 154 const char* http_content_type) { |
| 152 upload_content_.assign(http_data, http_data_len); | 155 upload_content_.assign(http_data, http_data_len); |
| 153 upload_content_type_.assign(http_content_type); | 156 upload_content_type_.assign(http_content_type); |
| 154 } | 157 } |
| 155 | 158 |
| 156 void AddHeader(const char* http_header_name, const char* http_header_value) { | 159 void AddHeader(const char* http_header_name, const char* http_header_value) { |
| 157 if (!extra_request_headers_.empty()) | 160 if (!extra_request_headers_.empty()) |
| 158 extra_request_headers_ += "\r\n"; | 161 extra_request_headers_ += "\r\n"; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 174 AutoLock autolock(lock_); | 177 AutoLock autolock(lock_); |
| 175 return finished_; | 178 return finished_; |
| 176 } | 179 } |
| 177 | 180 |
| 178 void Cancel() { | 181 void Cancel() { |
| 179 io_loop_->PostTask(FROM_HERE, | 182 io_loop_->PostTask(FROM_HERE, |
| 180 NewRunnableMethod(this, &Core::CancelURLRequest)); | 183 NewRunnableMethod(this, &Core::CancelURLRequest)); |
| 181 } | 184 } |
| 182 | 185 |
| 183 bool Wait() { | 186 bool Wait() { |
| 184 base::TimeDelta timeout = ocsp_req_->timeout(); | 187 base::TimeDelta timeout = timeout_; |
| 185 AutoLock autolock(lock_); | 188 AutoLock autolock(lock_); |
| 186 while (!finished_) { | 189 while (!finished_) { |
| 187 base::TimeTicks last_time = base::TimeTicks::Now(); | 190 base::TimeTicks last_time = base::TimeTicks::Now(); |
| 188 cv_.TimedWait(timeout); | 191 cv_.TimedWait(timeout); |
| 189 // Check elapsed time | 192 // Check elapsed time |
| 190 base::TimeDelta elapsed_time = base::TimeTicks::Now() - last_time; | 193 base::TimeDelta elapsed_time = base::TimeTicks::Now() - last_time; |
| 191 timeout -= elapsed_time; | 194 timeout -= elapsed_time; |
| 192 if (timeout < base::TimeDelta()) { | 195 if (timeout < base::TimeDelta()) { |
| 193 LOG(INFO) << "OCSP Timed out"; | 196 LOG(INFO) << "OCSP Timed out"; |
| 194 if (!finished_) | 197 if (!finished_) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 219 return data_; | 222 return data_; |
| 220 } | 223 } |
| 221 | 224 |
| 222 // Follow rediect. | 225 // Follow rediect. |
| 223 virtual void OnReceivedRedirect(URLRequest* request, | 226 virtual void OnReceivedRedirect(URLRequest* request, |
| 224 const GURL& new_url) {} | 227 const GURL& new_url) {} |
| 225 | 228 |
| 226 virtual void OnResponseStarted(URLRequest* request) { | 229 virtual void OnResponseStarted(URLRequest* request) { |
| 227 DCHECK(request == request_); | 230 DCHECK(request == request_); |
| 228 DCHECK(MessageLoopForIO::current() == io_loop_); | 231 DCHECK(MessageLoopForIO::current() == io_loop_); |
| 232 |
| 229 int bytes_read = 0; | 233 int bytes_read = 0; |
| 230 if (request->status().is_success()) { | 234 if (request->status().is_success()) { |
| 231 response_code_ = request_->GetResponseCode(); | 235 response_code_ = request_->GetResponseCode(); |
| 232 response_headers_ = request_->response_headers(); | 236 response_headers_ = request_->response_headers(); |
| 233 response_headers_->GetMimeType(&response_content_type_); | 237 response_headers_->GetMimeType(&response_content_type_); |
| 234 request_->Read(buffer_, kRecvBufferSize, &bytes_read); | 238 request_->Read(buffer_, kRecvBufferSize, &bytes_read); |
| 235 } | 239 } |
| 236 OnReadCompleted(request_, bytes_read); | 240 OnReadCompleted(request_, bytes_read); |
| 237 } | 241 } |
| 238 | 242 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 262 DCHECK(MessageLoopForIO::current() == io_loop_); | 266 DCHECK(MessageLoopForIO::current() == io_loop_); |
| 263 DCHECK(!request_); | 267 DCHECK(!request_); |
| 264 | 268 |
| 265 request_ = new URLRequest(url_, this); | 269 request_ = new URLRequest(url_, this); |
| 266 request_->set_context( | 270 request_->set_context( |
| 267 Singleton<OCSPInitSingleton>::get()->url_request_context()); | 271 Singleton<OCSPInitSingleton>::get()->url_request_context()); |
| 268 // To meet the privacy requirements of off-the-record mode. | 272 // To meet the privacy requirements of off-the-record mode. |
| 269 request_->set_load_flags( | 273 request_->set_load_flags( |
| 270 net::LOAD_DISABLE_CACHE|net::LOAD_DO_NOT_SAVE_COOKIES); | 274 net::LOAD_DISABLE_CACHE|net::LOAD_DO_NOT_SAVE_COOKIES); |
| 271 | 275 |
| 272 if (ocsp_req_->http_request_method() == "POST") { | 276 if (http_request_method_ == "POST") { |
| 273 DCHECK(!upload_content_.empty()); | 277 DCHECK(!upload_content_.empty()); |
| 274 DCHECK(!upload_content_type_.empty()); | 278 DCHECK(!upload_content_type_.empty()); |
| 275 | 279 |
| 276 request_->set_method("POST"); | 280 request_->set_method("POST"); |
| 277 if (!extra_request_headers_.empty()) | 281 if (!extra_request_headers_.empty()) |
| 278 extra_request_headers_ += "\r\n"; | 282 extra_request_headers_ += "\r\n"; |
| 279 StringAppendF(&extra_request_headers_, | 283 StringAppendF(&extra_request_headers_, |
| 280 "Content-Type: %s", upload_content_type_.c_str()); | 284 "Content-Type: %s", upload_content_type_.c_str()); |
| 281 request_->AppendBytesToUpload(upload_content_.data(), | 285 request_->AppendBytesToUpload(upload_content_.data(), |
| 282 static_cast<int>(upload_content_.size())); | 286 static_cast<int>(upload_content_.size())); |
| 283 } | 287 } |
| 284 if (!extra_request_headers_.empty()) | 288 if (!extra_request_headers_.empty()) |
| 285 request_->SetExtraRequestHeaders(extra_request_headers_); | 289 request_->SetExtraRequestHeaders(extra_request_headers_); |
| 286 | 290 |
| 287 request_->Start(); | 291 request_->Start(); |
| 288 } | 292 } |
| 289 | 293 |
| 290 void CancelURLRequest() { | 294 void CancelURLRequest() { |
| 291 DCHECK(MessageLoopForIO::current() == io_loop_); | 295 DCHECK(MessageLoopForIO::current() == io_loop_); |
| 292 if (request_) { | 296 if (request_) { |
| 297 request_->Cancel(); |
| 293 delete request_; | 298 delete request_; |
| 294 request_ = NULL; | 299 request_ = NULL; |
| 295 } | 300 } |
| 296 } | 301 } |
| 297 | 302 |
| 298 OCSPRequestSession* ocsp_req_; // corresponding OCSP session | |
| 299 GURL url_; // The URL we eventually wound up at | 303 GURL url_; // The URL we eventually wound up at |
| 304 std::string http_request_method_; |
| 305 base::TimeDelta timeout_; // The timeout for OCSP |
| 300 MessageLoop* io_loop_; // Message loop of the IO thread | 306 MessageLoop* io_loop_; // Message loop of the IO thread |
| 301 URLRequest* request_; // The actual request this wraps | 307 URLRequest* request_; // The actual request this wraps |
| 302 scoped_refptr<net::IOBuffer> buffer_; // Read buffer | 308 scoped_refptr<net::IOBuffer> buffer_; // Read buffer |
| 303 std::string extra_request_headers_; // Extra headers for the request, if any | 309 std::string extra_request_headers_; // Extra headers for the request, if any |
| 304 std::string upload_content_; // HTTP POST payload | 310 std::string upload_content_; // HTTP POST payload |
| 305 std::string upload_content_type_; // MIME type of POST payload | 311 std::string upload_content_type_; // MIME type of POST payload |
| 306 | 312 |
| 307 int response_code_; // HTTP status code for the request | 313 int response_code_; // HTTP status code for the request |
| 308 std::string response_content_type_; | 314 std::string response_content_type_; |
| 309 scoped_refptr<net::HttpResponseHeaders> response_headers_; | 315 scoped_refptr<net::HttpResponseHeaders> response_headers_; |
| 310 std::string data_; // Results of the requst | 316 std::string data_; // Results of the requst |
| 311 | 317 |
| 312 // |lock_| protects |finished_| only. | 318 // |lock_| protects |finished_| only. |
| 313 mutable Lock lock_; | 319 mutable Lock lock_; |
| 314 ConditionVariable cv_; | 320 ConditionVariable cv_; |
| 315 | 321 |
| 316 bool finished_; | 322 bool finished_; |
| 317 | 323 |
| 318 DISALLOW_COPY_AND_ASSIGN(Core); | 324 DISALLOW_COPY_AND_ASSIGN(Core); |
| 319 }; | 325 }; |
| 320 | 326 |
| 321 OCSPRequestSession::OCSPRequestSession(const GURL& url, | 327 OCSPRequestSession::OCSPRequestSession(const GURL& url, |
| 322 const char* http_request_method, | 328 const char* http_request_method, |
| 323 base::TimeDelta timeout) | 329 base::TimeDelta timeout) |
| 324 : url_(url), http_request_method_(http_request_method), | 330 : url_(url), http_request_method_(http_request_method), |
| 325 timeout_(timeout), | 331 timeout_(timeout), |
| 326 ALLOW_THIS_IN_INITIALIZER_LIST(core_(new Core(this))) { | 332 ALLOW_THIS_IN_INITIALIZER_LIST(core_(new Core(this))) { |
| 327 } | 333 } |
| 328 | 334 |
| 335 OCSPRequestSession::~OCSPRequestSession() { |
| 336 core_->Cancel(); |
| 337 } |
| 338 |
| 329 void OCSPRequestSession::SetPostData(const char* http_data, | 339 void OCSPRequestSession::SetPostData(const char* http_data, |
| 330 const PRUint32 http_data_len, | 340 const PRUint32 http_data_len, |
| 331 const char* http_content_type) { | 341 const char* http_content_type) { |
| 332 core_->SetPostData(http_data, http_data_len, http_content_type); | 342 core_->SetPostData(http_data, http_data_len, http_content_type); |
| 333 } | 343 } |
| 334 | 344 |
| 335 void OCSPRequestSession::AddHeader(const char* http_header_name, | 345 void OCSPRequestSession::AddHeader(const char* http_header_name, |
| 336 const char* http_header_value) { | 346 const char* http_header_value) { |
| 337 core_->AddHeader(http_header_name, http_header_value); | 347 core_->AddHeader(http_header_name, http_header_value); |
| 338 } | 348 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 DCHECK(req->Finished()); | 511 DCHECK(req->Finished()); |
| 502 const std::string& data = req->http_response_data(); | 512 const std::string& data = req->http_response_data(); |
| 503 if (http_response_data_len && *http_response_data_len) { | 513 if (http_response_data_len && *http_response_data_len) { |
| 504 if (*http_response_data_len < data.size()) { | 514 if (*http_response_data_len < data.size()) { |
| 505 LOG(ERROR) << "data size too large: " << *http_response_data_len | 515 LOG(ERROR) << "data size too large: " << *http_response_data_len |
| 506 << " < " << data.size(); | 516 << " < " << data.size(); |
| 507 *http_response_data_len = 1; | 517 *http_response_data_len = 1; |
| 508 return false; | 518 return false; |
| 509 } | 519 } |
| 510 } | 520 } |
| 511 LOG(INFO) << "OSCP response " | 521 LOG(INFO) << "OCSP response " |
| 512 << " response_code=" << req->http_response_code() | 522 << " response_code=" << req->http_response_code() |
| 513 << " content_type=" << req->http_response_content_type() | 523 << " content_type=" << req->http_response_content_type() |
| 514 << " header=" << req->http_response_headers() | 524 << " header=" << req->http_response_headers() |
| 515 << " data_len=" << data.size(); | 525 << " data_len=" << data.size(); |
| 516 if (http_response_code) | 526 if (http_response_code) |
| 517 *http_response_code = req->http_response_code(); | 527 *http_response_code = req->http_response_code(); |
| 518 if (http_response_content_type) | 528 if (http_response_content_type) |
| 519 *http_response_content_type = req->http_response_content_type().c_str(); | 529 *http_response_content_type = req->http_response_content_type().c_str(); |
| 520 if (http_response_headers) | 530 if (http_response_headers) |
| 521 *http_response_headers = req->http_response_headers().c_str(); | 531 *http_response_headers = req->http_response_headers().c_str(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 void EnsureOCSPInit() { | 601 void EnsureOCSPInit() { |
| 592 Singleton<OCSPInitSingleton>::get(); | 602 Singleton<OCSPInitSingleton>::get(); |
| 593 } | 603 } |
| 594 | 604 |
| 595 // This function would be called before NSS initialization. | 605 // This function would be called before NSS initialization. |
| 596 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { | 606 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { |
| 597 OCSPInitSingleton::set_url_request_context(request_context); | 607 OCSPInitSingleton::set_url_request_context(request_context); |
| 598 } | 608 } |
| 599 | 609 |
| 600 } // namespace net | 610 } // namespace net |
| OLD | NEW |