| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived | 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived |
| 6 // from AuthCertificateCallback() in | 6 // from AuthCertificateCallback() in |
| 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. |
| 8 | 8 |
| 9 /* ***** BEGIN LICENSE BLOCK ***** | 9 /* ***** BEGIN LICENSE BLOCK ***** |
| 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 #include <wincrypt.h> | 110 #include <wincrypt.h> |
| 111 #elif defined(OS_MACOSX) | 111 #elif defined(OS_MACOSX) |
| 112 #include <Security/SecBase.h> | 112 #include <Security/SecBase.h> |
| 113 #include <Security/SecCertificate.h> | 113 #include <Security/SecCertificate.h> |
| 114 #include <Security/SecIdentity.h> | 114 #include <Security/SecIdentity.h> |
| 115 #include "base/mac/mac_logging.h" | 115 #include "base/mac/mac_logging.h" |
| 116 #elif defined(USE_NSS) | 116 #elif defined(USE_NSS) |
| 117 #include <dlfcn.h> | 117 #include <dlfcn.h> |
| 118 #endif | 118 #endif |
| 119 | 119 |
| 120 namespace net { |
| 121 |
| 122 // State machines are easier to debug if you log state transitions. |
| 123 // Enable these if you want to see what's going on. |
| 124 #if 1 |
| 125 #define EnterFunction(x) |
| 126 #define LeaveFunction(x) |
| 127 #define GotoState(s) next_handshake_state_ = s |
| 128 #else |
| 129 #define EnterFunction(x)\ |
| 130 VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\ |
| 131 << "; next_handshake_state " << next_handshake_state_ |
| 132 #define LeaveFunction(x)\ |
| 133 VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\ |
| 134 << "; next_handshake_state " << next_handshake_state_ |
| 135 #define GotoState(s)\ |
| 136 do {\ |
| 137 VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\ |
| 138 next_handshake_state_ = s;\ |
| 139 } while (0) |
| 140 #endif |
| 141 |
| 142 namespace { |
| 143 |
| 120 // SSL plaintext fragments are shorter than 16KB. Although the record layer | 144 // SSL plaintext fragments are shorter than 16KB. Although the record layer |
| 121 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much | 145 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much |
| 122 // smaller than 1KB. So a 17KB buffer should be large enough to hold an | 146 // smaller than 1KB. So a 17KB buffer should be large enough to hold an |
| 123 // entire SSL record. | 147 // entire SSL record. |
| 124 static const int kRecvBufferSize = 17 * 1024; | 148 const int kRecvBufferSize = 17 * 1024; |
| 125 static const int kSendBufferSize = 17 * 1024; | 149 const int kSendBufferSize = 17 * 1024; |
| 150 |
| 151 // Used by SSLClientSocketNSS::Core to indicate there is no read result |
| 152 // obtained by a previous operation waiting to be returned to the caller. |
| 153 const int kNoPendingReadResult = 1; |
| 126 | 154 |
| 127 #if defined(OS_WIN) | 155 #if defined(OS_WIN) |
| 128 // CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be | 156 // CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be |
| 129 // set on Windows XP without error. There is some overhead from the server | 157 // set on Windows XP without error. There is some overhead from the server |
| 130 // sending the OCSP response if it supports the extension, for the subset of | 158 // sending the OCSP response if it supports the extension, for the subset of |
| 131 // XP clients who will request it but be unable to use it, but this is an | 159 // XP clients who will request it but be unable to use it, but this is an |
| 132 // acceptable trade-off for simplicity of implementation. | 160 // acceptable trade-off for simplicity of implementation. |
| 133 static bool IsOCSPStaplingSupported() { | 161 bool IsOCSPStaplingSupported() { |
| 134 return true; | 162 return true; |
| 135 } | 163 } |
| 136 #elif defined(USE_NSS) | 164 #elif defined(USE_NSS) |
| 137 typedef SECStatus | 165 typedef SECStatus |
| 138 (*CacheOCSPResponseFromSideChannelFunction)( | 166 (*CacheOCSPResponseFromSideChannelFunction)( |
| 139 CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, | 167 CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, |
| 140 SECItem *encodedResponse, void *pwArg); | 168 SECItem *encodedResponse, void *pwArg); |
| 141 | 169 |
| 142 // On Linux, we dynamically link against the system version of libnss3.so. In | 170 // On Linux, we dynamically link against the system version of libnss3.so. In |
| 143 // order to continue working on systems without up-to-date versions of NSS we | 171 // order to continue working on systems without up-to-date versions of NSS we |
| (...skipping 18 matching lines...) Expand all Loading... |
| 162 RuntimeLibNSSFunctionPointers() { | 190 RuntimeLibNSSFunctionPointers() { |
| 163 cache_ocsp_response_from_side_channel_ = | 191 cache_ocsp_response_from_side_channel_ = |
| 164 (CacheOCSPResponseFromSideChannelFunction) | 192 (CacheOCSPResponseFromSideChannelFunction) |
| 165 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"); | 193 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"); |
| 166 } | 194 } |
| 167 | 195 |
| 168 CacheOCSPResponseFromSideChannelFunction | 196 CacheOCSPResponseFromSideChannelFunction |
| 169 cache_ocsp_response_from_side_channel_; | 197 cache_ocsp_response_from_side_channel_; |
| 170 }; | 198 }; |
| 171 | 199 |
| 172 static CacheOCSPResponseFromSideChannelFunction | 200 CacheOCSPResponseFromSideChannelFunction |
| 173 GetCacheOCSPResponseFromSideChannelFunction() { | 201 GetCacheOCSPResponseFromSideChannelFunction() { |
| 174 return RuntimeLibNSSFunctionPointers::GetInstance() | 202 return RuntimeLibNSSFunctionPointers::GetInstance() |
| 175 ->GetCacheOCSPResponseFromSideChannelFunction(); | 203 ->GetCacheOCSPResponseFromSideChannelFunction(); |
| 176 } | 204 } |
| 177 | 205 |
| 178 static bool IsOCSPStaplingSupported() { | 206 bool IsOCSPStaplingSupported() { |
| 179 return GetCacheOCSPResponseFromSideChannelFunction() != NULL; | 207 return GetCacheOCSPResponseFromSideChannelFunction() != NULL; |
| 180 } | 208 } |
| 181 #else | 209 #else |
| 182 // TODO(agl): Figure out if we can plumb the OCSP response into Mac's system | 210 // TODO(agl): Figure out if we can plumb the OCSP response into Mac's system |
| 183 // certificate validation functions. | 211 // certificate validation functions. |
| 184 static bool IsOCSPStaplingSupported() { | 212 bool IsOCSPStaplingSupported() { |
| 185 return false; | 213 return false; |
| 186 } | 214 } |
| 187 #endif | 215 #endif |
| 188 | 216 |
| 189 namespace net { | |
| 190 | |
| 191 // State machines are easier to debug if you log state transitions. | |
| 192 // Enable these if you want to see what's going on. | |
| 193 #if 1 | |
| 194 #define EnterFunction(x) | |
| 195 #define LeaveFunction(x) | |
| 196 #define GotoState(s) next_handshake_state_ = s | |
| 197 #else | |
| 198 #define EnterFunction(x)\ | |
| 199 VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\ | |
| 200 << "; next_handshake_state " << next_handshake_state_ | |
| 201 #define LeaveFunction(x)\ | |
| 202 VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\ | |
| 203 << "; next_handshake_state " << next_handshake_state_ | |
| 204 #define GotoState(s)\ | |
| 205 do {\ | |
| 206 VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\ | |
| 207 next_handshake_state_ = s;\ | |
| 208 } while (0) | |
| 209 #endif | |
| 210 | |
| 211 namespace { | |
| 212 | |
| 213 class FreeCERTCertificate { | 217 class FreeCERTCertificate { |
| 214 public: | 218 public: |
| 215 inline void operator()(CERTCertificate* x) const { | 219 inline void operator()(CERTCertificate* x) const { |
| 216 CERT_DestroyCertificate(x); | 220 CERT_DestroyCertificate(x); |
| 217 } | 221 } |
| 218 }; | 222 }; |
| 219 typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate> | 223 typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate> |
| 220 ScopedCERTCertificate; | 224 ScopedCERTCertificate; |
| 221 | 225 |
| 222 #if defined(OS_WIN) | 226 #if defined(OS_WIN) |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 //////////////////////////////////////////////////////////////////////////// | 834 //////////////////////////////////////////////////////////////////////////// |
| 831 HostPortPair host_and_port_; | 835 HostPortPair host_and_port_; |
| 832 SSLConfig ssl_config_; | 836 SSLConfig ssl_config_; |
| 833 | 837 |
| 834 // NSS SSL socket. | 838 // NSS SSL socket. |
| 835 PRFileDesc* nss_fd_; | 839 PRFileDesc* nss_fd_; |
| 836 | 840 |
| 837 // Buffers for the network end of the SSL state machine | 841 // Buffers for the network end of the SSL state machine |
| 838 memio_Private* nss_bufs_; | 842 memio_Private* nss_bufs_; |
| 839 | 843 |
| 844 // Used by DoPayloadRead() when attempting to fill the caller's buffer with |
| 845 // as much data as possible, without blocking. |
| 846 // If DoPayloadRead() encounters an error after having read some data, stores |
| 847 // the results to return on the *next* call to DoPayloadRead(). A value of |
| 848 // kNoPendingReadResult indicates there is no pending result, otherwise 0 |
| 849 // indicates EOF and < 0 indicates an error. |
| 850 int pending_read_result_; |
| 851 // Contains the previously observed NSS error. Only valid when |
| 852 // pending_read_result_ != kNoPendingReadResult. |
| 853 PRErrorCode pending_read_nss_error_; |
| 854 |
| 840 // The certificate chain, in DER form, that is expected to be received from | 855 // The certificate chain, in DER form, that is expected to be received from |
| 841 // the server. | 856 // the server. |
| 842 std::vector<std::string> predicted_certs_; | 857 std::vector<std::string> predicted_certs_; |
| 843 | 858 |
| 844 State next_handshake_state_; | 859 State next_handshake_state_; |
| 845 | 860 |
| 846 // True if channel ID extension was negotiated. | 861 // True if channel ID extension was negotiated. |
| 847 bool channel_id_xtn_negotiated_; | 862 bool channel_id_xtn_negotiated_; |
| 848 // True if the handshake state machine was interrupted for channel ID. | 863 // True if the handshake state machine was interrupted for channel ID. |
| 849 bool channel_id_needed_; | 864 bool channel_id_needed_; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 weak_net_log_factory_(net_log), | 920 weak_net_log_factory_(net_log), |
| 906 server_bound_cert_service_(server_bound_cert_service), | 921 server_bound_cert_service_(server_bound_cert_service), |
| 907 unhandled_buffer_size_(0), | 922 unhandled_buffer_size_(0), |
| 908 nss_waiting_read_(false), | 923 nss_waiting_read_(false), |
| 909 nss_waiting_write_(false), | 924 nss_waiting_write_(false), |
| 910 nss_is_closed_(false), | 925 nss_is_closed_(false), |
| 911 host_and_port_(host_and_port), | 926 host_and_port_(host_and_port), |
| 912 ssl_config_(ssl_config), | 927 ssl_config_(ssl_config), |
| 913 nss_fd_(NULL), | 928 nss_fd_(NULL), |
| 914 nss_bufs_(NULL), | 929 nss_bufs_(NULL), |
| 930 pending_read_result_(kNoPendingReadResult), |
| 931 pending_read_nss_error_(0), |
| 915 next_handshake_state_(STATE_NONE), | 932 next_handshake_state_(STATE_NONE), |
| 916 channel_id_xtn_negotiated_(false), | 933 channel_id_xtn_negotiated_(false), |
| 917 channel_id_needed_(false), | 934 channel_id_needed_(false), |
| 918 client_auth_cert_needed_(false), | 935 client_auth_cert_needed_(false), |
| 919 handshake_callback_called_(false), | 936 handshake_callback_called_(false), |
| 920 transport_recv_busy_(false), | 937 transport_recv_busy_(false), |
| 921 transport_recv_eof_(false), | 938 transport_recv_eof_(false), |
| 922 transport_send_busy_(false), | 939 transport_send_busy_(false), |
| 923 user_read_buf_len_(0), | 940 user_read_buf_len_(0), |
| 924 user_write_buf_len_(0), | 941 user_write_buf_len_(0), |
| (...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1938 SetChannelIDProvided(); | 1955 SetChannelIDProvided(); |
| 1939 GotoState(STATE_HANDSHAKE); | 1956 GotoState(STATE_HANDSHAKE); |
| 1940 return OK; | 1957 return OK; |
| 1941 } | 1958 } |
| 1942 | 1959 |
| 1943 int SSLClientSocketNSS::Core::DoPayloadRead() { | 1960 int SSLClientSocketNSS::Core::DoPayloadRead() { |
| 1944 DCHECK(OnNSSTaskRunner()); | 1961 DCHECK(OnNSSTaskRunner()); |
| 1945 DCHECK(user_read_buf_); | 1962 DCHECK(user_read_buf_); |
| 1946 DCHECK_GT(user_read_buf_len_, 0); | 1963 DCHECK_GT(user_read_buf_len_, 0); |
| 1947 | 1964 |
| 1948 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); | 1965 int rv; |
| 1949 // Update NSSTaskRunner status because PR_Read may consume |nss_bufs_|, then | 1966 // If a previous greedy read resulted in an error that was not consumed (eg: |
| 1950 // following |amount_in_read_buffer| may be changed here. | 1967 // due to the caller having read some data successfully), then return that |
| 1951 int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); | 1968 // pending error now. |
| 1952 PostOrRunCallback( | 1969 if (pending_read_result_ != kNoPendingReadResult) { |
| 1953 FROM_HERE, | 1970 rv = pending_read_result_; |
| 1954 base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer)); | 1971 PRErrorCode prerr = pending_read_nss_error_; |
| 1972 pending_read_result_ = kNoPendingReadResult; |
| 1973 pending_read_nss_error_ = 0; |
| 1955 | 1974 |
| 1956 if (client_auth_cert_needed_) { | 1975 if (rv == 0) { |
| 1957 // We don't need to invalidate the non-client-authenticated SSL session | 1976 PostOrRunCallback( |
| 1958 // because the server will renegotiate anyway. | 1977 FROM_HERE, |
| 1959 rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1978 base::Bind(&LogByteTransferEvent, weak_net_log_, |
| 1960 PostOrRunCallback( | 1979 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, |
| 1961 FROM_HERE, | 1980 scoped_refptr<IOBuffer>(user_read_buf_))); |
| 1962 base::Bind(&AddLogEventWithCallback, weak_net_log_, | 1981 } else if (rv != ERR_IO_PENDING) { |
| 1963 NetLog::TYPE_SSL_READ_ERROR, | 1982 PostOrRunCallback( |
| 1964 CreateNetLogSSLErrorCallback(rv, 0))); | 1983 FROM_HERE, |
| 1984 base::Bind(&AddLogEventWithCallback, weak_net_log_, |
| 1985 NetLog::TYPE_SSL_READ_ERROR, |
| 1986 CreateNetLogSSLErrorCallback(rv, prerr))); |
| 1987 } |
| 1965 return rv; | 1988 return rv; |
| 1966 } | 1989 } |
| 1990 |
| 1991 // Perform a greedy read, attempting to read as much as the caller has |
| 1992 // requested. In the current NSS implementation, PR_Read will return |
| 1993 // exactly one SSL application data record's worth of data per invocation. |
| 1994 // The record size is dictated by the server, and may be noticeably smaller |
| 1995 // than the caller's buffer. This may be as little as a single byte, if the |
| 1996 // server is performing 1/n-1 record splitting. |
| 1997 // |
| 1998 // However, this greedy read may result in renegotiations/re-handshakes |
| 1999 // happening or may lead to some data being read, followed by an EOF (such as |
| 2000 // a TLS close-notify). If at least some data was read, then that result |
| 2001 // should be deferred until the next call to DoPayloadRead(). Otherwise, if no |
| 2002 // data was read, it's safe to return the error or EOF immediately. |
| 2003 int total_bytes_read = 0; |
| 2004 do { |
| 2005 rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read, |
| 2006 user_read_buf_len_ - total_bytes_read); |
| 2007 if (rv > 0) |
| 2008 total_bytes_read += rv; |
| 2009 } while (total_bytes_read < user_read_buf_len_ && rv > 0); |
| 2010 int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); |
| 2011 PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this, |
| 2012 amount_in_read_buffer)); |
| 2013 |
| 2014 if (total_bytes_read == user_read_buf_len_) { |
| 2015 // The caller's entire request was satisfied without error. No further |
| 2016 // processing needed. |
| 2017 rv = total_bytes_read; |
| 2018 } else { |
| 2019 // Otherwise, an error occurred (rv <= 0). The error needs to be handled |
| 2020 // immediately, while the NSPR/NSS errors are still available in |
| 2021 // thread-local storage. However, the handled/remapped error code should |
| 2022 // only be returned if no application data was already read; if it was, the |
| 2023 // error code should be deferred until the next call of DoPayloadRead. |
| 2024 // |
| 2025 // If no data was read, |*next_result| will point to the return value of |
| 2026 // this function. If at least some data was read, |*next_result| will point |
| 2027 // to |pending_read_error_|, to be returned in a future call to |
| 2028 // DoPayloadRead() (e.g.: after the current data is handled). |
| 2029 int* next_result = &rv; |
| 2030 if (total_bytes_read > 0) { |
| 2031 pending_read_result_ = rv; |
| 2032 rv = total_bytes_read; |
| 2033 next_result = &pending_read_result_; |
| 2034 } |
| 2035 |
| 2036 if (client_auth_cert_needed_) { |
| 2037 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 2038 pending_read_nss_error_ = 0; |
| 2039 } else if (*next_result < 0) { |
| 2040 // If *next_result == 0, then that indicates EOF, and no special error |
| 2041 // handling is needed. |
| 2042 pending_read_nss_error_ = PR_GetError(); |
| 2043 if (pending_read_nss_error_ == PR_WOULD_BLOCK_ERROR) { |
| 2044 *next_result = ERR_IO_PENDING; |
| 2045 pending_read_nss_error_ = 0; |
| 2046 } else { |
| 2047 *next_result = HandleNSSError(pending_read_nss_error_, false); |
| 2048 } |
| 2049 } |
| 2050 } |
| 2051 |
| 1967 if (rv >= 0) { | 2052 if (rv >= 0) { |
| 1968 PostOrRunCallback( | 2053 PostOrRunCallback( |
| 1969 FROM_HERE, | 2054 FROM_HERE, |
| 1970 base::Bind(&LogByteTransferEvent, weak_net_log_, | 2055 base::Bind(&LogByteTransferEvent, weak_net_log_, |
| 1971 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, | 2056 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, |
| 1972 scoped_refptr<IOBuffer>(user_read_buf_))); | 2057 scoped_refptr<IOBuffer>(user_read_buf_))); |
| 1973 return rv; | 2058 } else if (rv != ERR_IO_PENDING) { |
| 2059 PostOrRunCallback( |
| 2060 FROM_HERE, |
| 2061 base::Bind(&AddLogEventWithCallback, weak_net_log_, |
| 2062 NetLog::TYPE_SSL_READ_ERROR, |
| 2063 CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_))); |
| 2064 pending_read_nss_error_ = 0; |
| 1974 } | 2065 } |
| 1975 PRErrorCode prerr = PR_GetError(); | |
| 1976 if (prerr == PR_WOULD_BLOCK_ERROR) | |
| 1977 return ERR_IO_PENDING; | |
| 1978 | |
| 1979 rv = HandleNSSError(prerr, false); | |
| 1980 PostOrRunCallback( | |
| 1981 FROM_HERE, | |
| 1982 base::Bind(&AddLogEventWithCallback, weak_net_log_, | |
| 1983 NetLog::TYPE_SSL_READ_ERROR, | |
| 1984 CreateNetLogSSLErrorCallback(rv, prerr))); | |
| 1985 return rv; | 2066 return rv; |
| 1986 } | 2067 } |
| 1987 | 2068 |
| 1988 int SSLClientSocketNSS::Core::DoPayloadWrite() { | 2069 int SSLClientSocketNSS::Core::DoPayloadWrite() { |
| 1989 DCHECK(OnNSSTaskRunner()); | 2070 DCHECK(OnNSSTaskRunner()); |
| 1990 | 2071 |
| 1991 DCHECK(user_write_buf_); | 2072 DCHECK(user_write_buf_); |
| 1992 | 2073 |
| 1993 int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); | 2074 int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); |
| 1994 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); | 2075 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); |
| (...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3439 EnsureThreadIdAssigned(); | 3520 EnsureThreadIdAssigned(); |
| 3440 base::AutoLock auto_lock(lock_); | 3521 base::AutoLock auto_lock(lock_); |
| 3441 return valid_thread_id_ == base::PlatformThread::CurrentId(); | 3522 return valid_thread_id_ == base::PlatformThread::CurrentId(); |
| 3442 } | 3523 } |
| 3443 | 3524 |
| 3444 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { | 3525 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { |
| 3445 return server_bound_cert_service_; | 3526 return server_bound_cert_service_; |
| 3446 } | 3527 } |
| 3447 | 3528 |
| 3448 } // namespace net | 3529 } // namespace net |
| OLD | NEW |