15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/ocsp/nss_ocsp.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <certt.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <certdb.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ocsp.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nspr.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secerr.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
275e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
285e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_checker.h"
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/base/request_priority.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_headers.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/url_request/redirect_info.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protects |g_request_context|.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pthread_mutex_t g_request_context_lock = PTHREAD_MUTEX_INITIALIZER;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestContext* g_request_context = NULL;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The default timeout for network fetches in NSS is 60 seconds. Choose a
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// saner upper limit for OCSP/CRL/AIA fetches.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNetworkFetchTimeoutInSecs = 15;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OCSPRequestSession;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OCSPIOLoop {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartUsing() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    used_ = true;
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    io_loop_ = base::MessageLoopForIO::current();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(io_loop_);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on IO loop.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Shutdown();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool used() const {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return used_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called from worker thread.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PostTaskToIOLoop(const tracked_objects::Location& from_here,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const base::Closure& task);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EnsureIOLoop();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddRequest(OCSPRequestSession* request);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveRequest(OCSPRequestSession* request);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clears internal state and calls |StartUsing()|. Should be called only in
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the context of testing.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReuseForTesting() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock autolock(lock_);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DCHECK(base::MessageLoopForIO::current());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_checker_.DetachFromThread();
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // CalledOnValidThread is the only available API to reassociate
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // thread_checker_ with the current thread. Result ignored intentionally.
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ignore_result(thread_checker_.CalledOnValidThread());
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_ = false;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      used_ = false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartUsing();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct base::DefaultLazyInstanceTraits<OCSPIOLoop>;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPIOLoop();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~OCSPIOLoop();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelAllRequests();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock lock_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool shutdown_;  // Protected by |lock_|.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<OCSPRequestSession*> requests_;  // Protected by |lock_|.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool used_;  // Protected by |lock_|.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should not be modified after |used_|.
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO* io_loop_;  // Protected by |lock_|.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadChecker thread_checker_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OCSPIOLoop);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<OCSPIOLoop>::Leaky
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_ocsp_io_loop = LAZY_INSTANCE_INITIALIZER;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kRecvBufferSize = 4096;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All OCSP handlers should be called in the context of
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CertVerifier's thread (i.e. worker pool, not on the I/O thread).
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It supports blocking mode only.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPCreateSession(const char* host, PRUint16 portnum,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SEC_HTTP_SERVER_SESSION* pSession);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PRPollDesc **pPollDesc);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPFreeSession(SEC_HTTP_SERVER_SESSION session);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPCreate(SEC_HTTP_SERVER_SESSION session,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* http_protocol_variant,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* path_and_query_string,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* http_request_method,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const PRIntervalTime timeout,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SEC_HTTP_REQUEST_SESSION* pRequest);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPSetPostData(SEC_HTTP_REQUEST_SESSION request,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* http_data,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const PRUint32 http_data_len,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* http_content_type);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPAddHeader(SEC_HTTP_REQUEST_SESSION request,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* http_header_name,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* http_header_value);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPTrySendAndReceive(SEC_HTTP_REQUEST_SESSION request,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PRPollDesc** pPollDesc,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PRUint16* http_response_code,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char** http_response_content_type,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char** http_response_headers,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char** http_response_data,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PRUint32* http_response_data_len);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* GetAlternateOCSPAIAInfo(CERTCertificate *cert);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OCSPNSSInitialization {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct base::DefaultLazyInstanceTraits<OCSPNSSInitialization>;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPNSSInitialization();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~OCSPNSSInitialization();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SEC_HttpClientFcn client_fcn_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OCSPNSSInitialization);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<OCSPNSSInitialization> g_ocsp_nss_initialization =
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Concrete class for SEC_HTTP_REQUEST_SESSION.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Public methods except virtual methods of URLRequest::Delegate
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (On* methods) run on certificate verifier thread (worker thread).
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Virtual methods of URLRequest::Delegate and private methods run
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on IO thread.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OCSPRequestSession
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<OCSPRequestSession>,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public URLRequest::Delegate {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession(const GURL& url,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* http_request_method,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::TimeDelta timeout)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : url_(url),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        http_request_method_(http_request_method),
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        timeout_(timeout),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buffer_(new IOBuffer(kRecvBufferSize)),
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_code_(-1),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cv_(&lock_),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_loop_(NULL),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        finished_(false) {}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPostData(const char* http_data, PRUint32 http_data_len,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const char* http_content_type) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |upload_content_| should not be modified if |request_| is active.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!request_);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    upload_content_.assign(http_data, http_data_len);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    upload_content_type_.assign(http_content_type);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddHeader(const char* http_header_name, const char* http_header_value) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_request_headers_.SetHeader(http_header_name,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     http_header_value);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Start() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At this point, it runs on worker thread.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |io_loop_| was initialized to be NULL in constructor, and
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // set only in StartURLRequest, so no need to lock |lock_| here.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!io_loop_);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_ocsp_io_loop.Get().PostTaskToIOLoop(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&OCSPRequestSession::StartURLRequest, this));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Started() const {
22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return request_.get() != NULL;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IO thread may set |io_loop_| to NULL, so protect by |lock_|.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelLocked();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Finished() const {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return finished_;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Wait() {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta timeout = timeout_;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!finished_) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeTicks last_time = base::TimeTicks::Now();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cv_.TimedWait(timeout);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check elapsed time
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta elapsed_time = base::TimeTicks::Now() - last_time;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timeout -= elapsed_time;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (timeout < base::TimeDelta()) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VLOG(1) << "OCSP Timed out";
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!finished_)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CancelLocked();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return finished_;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url() const {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return url_;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& http_request_method() const {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return http_request_method_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta timeout() const {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return timeout_;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRUint16 http_response_code() const {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(finished_);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return response_code_;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& http_response_content_type() const {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(finished_);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return response_content_type_;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& http_response_headers() const {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(finished_);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return response_headers_->raw_headers();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& http_response_data() const {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(finished_);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnReceivedRedirect(URLRequest* request,
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  const RedirectInfo& redirect_info,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool* defer_redirect) OVERRIDE {
28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK_EQ(request_.get(), request);
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK_EQ(base::MessageLoopForIO::current(), io_loop_);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!redirect_info.new_url.SchemeIs("http")) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Prevent redirects to non-HTTP schemes, including HTTPS. This matches
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the initial check in OCSPServerSession::CreateRequest().
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CancelURLRequest();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnResponseStarted(URLRequest* request) OVERRIDE {
30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK_EQ(request_.get(), request);
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK_EQ(base::MessageLoopForIO::current(), io_loop_);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes_read = 0;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request->status().is_success()) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_code_ = request_->GetResponseCode();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_headers_ = request_->response_headers();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_headers_->GetMimeType(&response_content_type_);
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      request_->Read(buffer_.get(), kRecvBufferSize, &bytes_read);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    OnReadCompleted(request_.get(), bytes_read);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnReadCompleted(URLRequest* request,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int bytes_read) OVERRIDE {
31503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK_EQ(request_.get(), request);
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK_EQ(base::MessageLoopForIO::current(), io_loop_);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!request_->status().is_success() || bytes_read <= 0)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_.append(buffer_->data(), bytes_read);
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } while (request_->Read(buffer_.get(), kRecvBufferSize, &bytes_read));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!request_->status().is_io_pending()) {
32503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      request_.reset();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_ocsp_io_loop.Get().RemoveRequest(this);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::AutoLock autolock(lock_);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        finished_ = true;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_loop_ = NULL;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cv_.Signal();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Release();  // Balanced with StartURLRequest().
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must be called on the IO loop thread.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelURLRequest() {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock autolock(lock_);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (io_loop_)
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        DCHECK_EQ(base::MessageLoopForIO::current(), io_loop_);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request_) {
34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      request_.reset();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_ocsp_io_loop.Get().RemoveRequest(this);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::AutoLock autolock(lock_);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        finished_ = true;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_loop_ = NULL;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cv_.Signal();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Release();  // Balanced with StartURLRequest().
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<OCSPRequestSession>;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~OCSPRequestSession() {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When this destructor is called, there should be only one thread that has
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a reference to this object, and so that thread doesn't need to lock
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |lock_| here.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!request_);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!io_loop_);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must call this method while holding |lock_|.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelLocked() {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock_.AssertAcquired();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (io_loop_) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_loop_->PostTask(
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&OCSPRequestSession::CancelURLRequest, this));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Runs on |g_ocsp_io_loop|'s IO loop.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartURLRequest() {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!request_);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pthread_mutex_lock(&g_request_context_lock);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLRequestContext* url_request_context = g_request_context;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pthread_mutex_unlock(&g_request_context_lock);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url_request_context == NULL)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock autolock(lock_);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!io_loop_);
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      io_loop_ = base::MessageLoopForIO::current();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_ocsp_io_loop.Get().AddRequest(this);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    request_ = url_request_context->CreateRequest(
39903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        url_, DEFAULT_PRIORITY, this, NULL);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // To meet the privacy requirements of incognito mode.
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    request_->SetLoadFlags(LOAD_DISABLE_CACHE | LOAD_DO_NOT_SAVE_COOKIES |
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           LOAD_DO_NOT_SEND_COOKIES);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (http_request_method_ == "POST") {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!upload_content_.empty());
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!upload_content_type_.empty());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_->set_method("POST");
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extra_request_headers_.SetHeader(
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpRequestHeaders::kContentType, upload_content_type_);
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<UploadElementReader> reader(new UploadBytesElementReader(
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          upload_content_.data(), upload_content_.size()));
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_->set_upload(make_scoped_ptr(
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UploadDataStream::CreateWithReader(reader.Pass(), 0)));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!extra_request_headers_.IsEmpty())
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_->SetExtraRequestHeaders(extra_request_headers_);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->Start();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddRef();  // Release after |request_| deleted.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  GURL url_;                        // The URL we eventually wound up at
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string http_request_method_;
42603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::TimeDelta timeout_;         // The timeout for OCSP
42703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<URLRequest> request_;  // The actual request this wraps
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buffer_;  // Read buffer
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestHeaders extra_request_headers_;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // HTTP POST payload. |request_| reads bytes from this.
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string upload_content_;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string upload_content_type_;  // MIME type of POST payload
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_code_;             // HTTP status code for the request
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_content_type_;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HttpResponseHeaders> response_headers_;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data_;              // Results of the request
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |lock_| protects |finished_| and |io_loop_|.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock lock_;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ConditionVariable cv_;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop* io_loop_;  // Message loop of the IO thread
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool finished_;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OCSPRequestSession);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Concrete class for SEC_HTTP_SERVER_SESSION.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OCSPServerSession {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPServerSession(const char* host, PRUint16 port)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : host_and_port_(host, port) {}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~OCSPServerSession() {}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession* CreateRequest(const char* http_protocol_variant,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const char* path_and_query_string,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const char* http_request_method,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const PRIntervalTime timeout) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We dont' support "https" because we haven't thought about
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // whether it's safe to re-enter this code from talking to an OCSP
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // responder over SSL.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (strcmp(http_protocol_variant, "http") != 0) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string url_string(base::StringPrintf(
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "%s://%s%s",
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        http_protocol_variant,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        host_and_port_.ToString().c_str(),
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path_and_query_string));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "URL [" << url_string << "]";
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL url(url_string);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NSS does not expose public functions to adjust the fetch timeout when
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // using libpkix, so hardcode the upper limit for network fetches.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta actual_timeout = std::min(
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(kNetworkFetchTimeoutInSecs),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(PR_IntervalToMilliseconds(timeout)));
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new OCSPRequestSession(url, http_request_method, actual_timeout);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_and_port_;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OCSPServerSession);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OCSPIOLoop::OCSPIOLoop()
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : shutdown_(false),
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      used_(false),
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_loop_(NULL) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OCSPIOLoop::~OCSPIOLoop() {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO thread was already deleted before the singleton is deleted
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in AtExitManager.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!io_loop_);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!used_);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(shutdown_);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_lock(&g_request_context_lock);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!g_request_context);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_unlock(&g_request_context_lock);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OCSPIOLoop::Shutdown() {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Safe to read outside lock since we only write on IO thread anyway.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent the worker thread from trying to access |io_loop_|.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock autolock(lock_);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_loop_ = NULL;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    used_ = false;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shutdown_ = true;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelAllRequests();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_lock(&g_request_context_lock);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_request_context = NULL;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_unlock(&g_request_context_lock);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OCSPIOLoop::PostTaskToIOLoop(
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here, const base::Closure& task) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock autolock(lock_);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (io_loop_)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_loop_->PostTask(from_here, task);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OCSPIOLoop::EnsureIOLoop() {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock autolock(lock_);
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(base::MessageLoopForIO::current(), io_loop_);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OCSPIOLoop::AddRequest(OCSPRequestSession* request) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ContainsKey(requests_, request));
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  requests_.insert(request);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OCSPIOLoop::RemoveRequest(OCSPRequestSession* request) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ContainsKey(requests_, request));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  requests_.erase(request);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OCSPIOLoop::CancelAllRequests() {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CancelURLRequest() always removes the request from the requests_
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set synchronously.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!requests_.empty())
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*requests_.begin())->CancelURLRequest();
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OCSPNSSInitialization::OCSPNSSInitialization() {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NSS calls the functions in the function table to download certificates
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or CRLs or talk to OCSP responders over HTTP.  These functions must
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set an NSS/NSPR error code when they fail.  Otherwise NSS will get the
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // residual error code from an earlier failed function call.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_fcn_.version = 1;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->createSessionFcn = OCSPCreateSession;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->keepAliveSessionFcn = OCSPKeepAliveSession;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->freeSessionFcn = OCSPFreeSession;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->createFcn = OCSPCreate;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->setPostDataFcn = OCSPSetPostData;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->addHeaderFcn = OCSPAddHeader;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->trySendAndReceiveFcn = OCSPTrySendAndReceive;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->cancelFcn = NULL;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ft->freeFcn = OCSPFree;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != SECSuccess) {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Work around NSS bugs 524013 and 564334.  NSS incorrectly thinks the
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CRLs for Network Solutions Certificate Authority have bad signatures,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which causes certificates issued by that CA to be reported as revoked.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By using OCSP for those certificates, which don't have AIA extensions,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we can work around these bugs.  See http://crbug.com/41730.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_StringFromCertFcn old_callback = NULL;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = CERT_RegisterAlternateOCSPAIAInfoCallBack(
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAlternateOCSPAIAInfo, &old_callback);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status == SECSuccess) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!old_callback);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OCSPNSSInitialization::~OCSPNSSInitialization() {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus status = CERT_RegisterAlternateOCSPAIAInfoCallBack(NULL, NULL);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != SECSuccess) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error unregistering OCSP: " << PR_GetError();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OCSP Http Client functions.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Our Http Client functions operate in blocking mode.
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPCreateSession(const char* host, PRUint16 portnum,
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SEC_HTTP_SERVER_SESSION* pSession) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP create session: host=" << host << " port=" << portnum;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_lock(&g_request_context_lock);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLRequestContext* request_context = g_request_context;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_unlock(&g_request_context_lock);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_context == NULL) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "No URLRequestContext for NSS HTTP handler. host: " << host;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The application failed to call SetURLRequestContextForNSSHttpIO or
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has already called ShutdownNSSHttpIO, so we can't create and use
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // URLRequest.  PR_NOT_IMPLEMENTED_ERROR is not an accurate error
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // code for these error conditions, but is close enough.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pSession = new OCSPServerSession(host, portnum);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PRPollDesc **pPollDesc) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP keep alive";
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pPollDesc)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pPollDesc = NULL;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPFreeSession(SEC_HTTP_SERVER_SESSION session) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP free session";
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete reinterpret_cast<OCSPServerSession*>(session);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPCreate(SEC_HTTP_SERVER_SESSION session,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* http_protocol_variant,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* path_and_query_string,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const char* http_request_method,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const PRIntervalTime timeout,
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SEC_HTTP_REQUEST_SESSION* pRequest) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP create protocol=" << http_protocol_variant
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " path_and_query=" << path_and_query_string
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " http_request_method=" << http_request_method
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " timeout=" << timeout;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPServerSession* ocsp_session =
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<OCSPServerSession*>(session);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession* req = ocsp_session->CreateRequest(http_protocol_variant,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        path_and_query_string,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        http_request_method,
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        timeout);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SECFailure;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (req) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    req->AddRef();  // Release in OCSPFree().
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = SECSuccess;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pRequest = req;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPSetPostData(SEC_HTTP_REQUEST_SESSION request,
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* http_data,
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const PRUint32 http_data_len,
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char* http_content_type) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP set post data len=" << http_data_len;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->SetPostData(http_data, http_data_len, http_content_type);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPAddHeader(SEC_HTTP_REQUEST_SESSION request,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* http_header_name,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* http_header_value) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP add header name=" << http_header_name
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " value=" << http_header_value;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->AddHeader(http_header_name, http_header_value);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets response of |req| in the output parameters.
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is helper routine for OCSP trySendAndReceiveFcn.
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |http_response_data_len| could be used as input parameter.  If it has
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-zero value, it is considered as maximum size of |http_response_data|.
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPSetResponse(OCSPRequestSession* req,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          PRUint16* http_response_code,
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char** http_response_content_type,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char** http_response_headers,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const char** http_response_data,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          PRUint32* http_response_data_len) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(req->Finished());
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& data = req->http_response_data();
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_data_len && *http_response_data_len) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*http_response_data_len < data.size()) {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "response body too large: " << *http_response_data_len
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << " < " << data.size();
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *http_response_data_len = data.size();
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE);
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SECFailure;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP response "
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " response_code=" << req->http_response_code()
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " content_type=" << req->http_response_content_type()
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " header=" << req->http_response_headers()
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " data_len=" << data.size();
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_code)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_response_code = req->http_response_code();
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_content_type)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_response_content_type = req->http_response_content_type().c_str();
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_headers)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_response_headers = req->http_response_headers().c_str();
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_data)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_response_data = data.data();
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_data_len)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_response_data_len = data.size();
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPTrySendAndReceive(SEC_HTTP_REQUEST_SESSION request,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PRPollDesc** pPollDesc,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PRUint16* http_response_code,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char** http_response_content_type,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char** http_response_headers,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char** http_response_data,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PRUint32* http_response_data_len) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_response_data_len) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We must always set an output value, even on failure.  The output value 0
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // means the failure was unrelated to the acceptable response data length.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *http_response_data_len = 0;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP try send and receive";
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We support blocking mode only.
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pPollDesc)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pPollDesc = NULL;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (req->Started() || req->Finished()) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We support blocking mode only, so this function shouldn't be called
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // again when req has stareted or finished.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE);  // Simple approximation.
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Time start_time = base::Time::Now();
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool request_ok = true;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->Start();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!req->Wait() || req->http_response_code() == static_cast<PRUint16>(-1)) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the response code is -1, the request failed and there is no response.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_ok = false;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta duration = base::Time::Now() - start_time;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For metrics, we want to know if the request was 'successful' or not.
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |request_ok| determines if we'll pass the response back to NSS and |ok|
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keep track of if we think the response was good.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = true;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_ok ||
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (req->http_response_code() >= 400 && req->http_response_code() < 600) ||
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->http_response_data().size() == 0 ||
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 0x30 is the ASN.1 DER encoding of a SEQUENCE. All valid OCSP/CRL/CRT
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // responses must start with this. If we didn't check for this then a
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // captive portal could provide an HTML reply that we would count as a
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 'success' (although it wouldn't count in NSS, of course).
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->http_response_data().data()[0] != 0x30) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = false;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to know if this was:
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   1) An OCSP request
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   2) A CRL request
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   3) A request for a missing intermediate certificate
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There's no sure way to do this, so we use heuristics like MIME type and
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URL.
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* mime_type = "";
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mime_type = req->http_response_content_type().c_str();
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_ocsp =
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcasecmp(mime_type, "application/ocsp-response") == 0;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_crl = strcasecmp(mime_type, "application/x-pkcs7-crl") == 0 ||
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                strcasecmp(mime_type, "application/x-x509-crl") == 0 ||
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                strcasecmp(mime_type, "application/pkix-crl") == 0;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_cert =
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcasecmp(mime_type, "application/x-x509-ca-cert") == 0 ||
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcasecmp(mime_type, "application/x-x509-server-cert") == 0 ||
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcasecmp(mime_type, "application/pkix-cert") == 0 ||
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcasecmp(mime_type, "application/pkcs7-mime") == 0;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_cert && !is_crl && !is_ocsp) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We didn't get a hint from the MIME type, so do the best that we can.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string path = req->url().path();
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string host = req->url().host();
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_crl = strcasestr(path.c_str(), ".crl") != NULL;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_cert = strcasestr(path.c_str(), ".crt") != NULL ||
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              strcasestr(path.c_str(), ".p7c") != NULL ||
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              strcasestr(path.c_str(), ".cer") != NULL;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_ocsp = strcasestr(host.c_str(), "ocsp") != NULL ||
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              req->http_request_method() == "POST";
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_ocsp) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok) {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("Net.OCSPRequestTimeMs", duration);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("Net.OCSPRequestSuccess", true);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("Net.OCSPRequestFailedTimeMs", duration);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("Net.OCSPRequestSuccess", false);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_crl) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("Net.CRLRequestTimeMs", duration);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("Net.CRLRequestSuccess", true);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("Net.CRLRequestFailedTimeMs", duration);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("Net.CRLRequestSuccess", false);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_cert) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("Net.CRTRequestTimeMs", duration);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_TIMES("Net.UnknownTypeRequestTimeMs", duration);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_ok) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_SetError(SEC_ERROR_BAD_HTTP_RESPONSE);  // Simple approximation.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OCSPSetResponse(
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req, http_response_code,
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_response_content_type,
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_response_headers,
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_response_data,
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_response_data_len);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OCSP free";
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OCSPRequestSession* req = reinterpret_cast<OCSPRequestSession*>(request);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->Cancel();
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->Release();
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Data for GetAlternateOCSPAIAInfo.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There are two CAs with this name.  Their key IDs are listed next.
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char network_solutions_ca_name[] = {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x30, 0x62, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1f, 0x06,
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x4e, 0x65, 0x74, 0x77,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x72, 0x6b, 0x20, 0x53, 0x6f, 0x6c, 0x75, 0x74, 0x69,
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x6e, 0x73, 0x20, 0x4c, 0x2e, 0x4c, 0x2e, 0x43, 0x2e,
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x27, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x53,
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x43,
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int network_solutions_ca_name_len = 100;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This CA is an intermediate CA, subordinate to UTN-USERFirst-Hardware.
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char network_solutions_ca_key_id[] = {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x3c, 0x41, 0xe2, 0x8f, 0x08, 0x08, 0xa9, 0x4c, 0x25, 0x89,
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x8d, 0x6d, 0xc5, 0x38, 0xd0, 0xfc, 0x85, 0x8c, 0x62, 0x17
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int network_solutions_ca_key_id_len = 20;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This CA is a root CA.  It is also cross-certified by
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// UTN-USERFirst-Hardware.
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char network_solutions_ca_key_id2[] = {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x21, 0x30, 0xc9, 0xfb, 0x00, 0xd7, 0x4e, 0x98, 0xda, 0x87,
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0xaa, 0x2a, 0xd0, 0xa7, 0x2e, 0xb1, 0x40, 0x31, 0xa7, 0x4c
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int network_solutions_ca_key_id2_len = 20;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An entry in our OCSP responder table.  |issuer| and |issuer_key_id| are
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the key.  |ocsp_url| is the value.
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OCSPResponderTableEntry {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem issuer;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem issuer_key_id;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *ocsp_url;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const OCSPResponderTableEntry g_ocsp_responder_table[] = {
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      siBuffer,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<unsigned char*>(network_solutions_ca_name),
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_solutions_ca_name_len
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      siBuffer,
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<unsigned char*>(network_solutions_ca_key_id),
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_solutions_ca_key_id_len
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://ocsp.netsolssl.com"
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      siBuffer,
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<unsigned char*>(network_solutions_ca_name),
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_solutions_ca_name_len
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      siBuffer,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<unsigned char*>(network_solutions_ca_key_id2),
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_solutions_ca_key_id2_len
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://ocsp.netsolssl.com"
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* GetAlternateOCSPAIAInfo(CERTCertificate *cert) {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert && !cert->isRoot && cert->authKeyID) {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i=0; i < arraysize(g_ocsp_responder_table); i++) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (SECITEM_CompareItem(&g_ocsp_responder_table[i].issuer,
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &cert->derIssuer) == SECEqual &&
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SECITEM_CompareItem(&g_ocsp_responder_table[i].issuer_key_id,
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &cert->authKeyID->keyID) == SECEqual) {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return PORT_Strdup(g_ocsp_responder_table[i].ocsp_url);
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetMessageLoopForNSSHttpIO() {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must have a MessageLoopForIO.
94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(base::MessageLoopForIO::current());
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool used = g_ocsp_io_loop.Get().used();
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should not be called when g_ocsp_io_loop has already been used.
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!used);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnsureNSSHttpIOInit() {
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_ocsp_io_loop.Get().StartUsing();
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_ocsp_nss_initialization.Get();
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShutdownNSSHttpIO() {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_ocsp_io_loop.Get().Shutdown();
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResetNSSHttpIOForTesting() {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_ocsp_io_loop.Get().ReuseForTesting();
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function would be called before NSS initialization.
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetURLRequestContextForNSSHttpIO(URLRequestContext* request_context) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_lock(&g_request_context_lock);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_context) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!g_request_context);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_request_context = request_context;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_unlock(&g_request_context_lock);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
978