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 // This constant can be any non-negative/non-zero value (eg: it does not |
| 154 // overlap with any value of the net::Error range, including net::OK). |
| 155 const int kNoPendingReadResult = 1; |
126 | 156 |
127 #if defined(OS_WIN) | 157 #if defined(OS_WIN) |
128 // CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be | 158 // 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 | 159 // 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 | 160 // 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 | 161 // XP clients who will request it but be unable to use it, but this is an |
132 // acceptable trade-off for simplicity of implementation. | 162 // acceptable trade-off for simplicity of implementation. |
133 static bool IsOCSPStaplingSupported() { | 163 bool IsOCSPStaplingSupported() { |
134 return true; | 164 return true; |
135 } | 165 } |
136 #elif defined(USE_NSS) | 166 #elif defined(USE_NSS) |
137 typedef SECStatus | 167 typedef SECStatus |
138 (*CacheOCSPResponseFromSideChannelFunction)( | 168 (*CacheOCSPResponseFromSideChannelFunction)( |
139 CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, | 169 CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, |
140 SECItem *encodedResponse, void *pwArg); | 170 SECItem *encodedResponse, void *pwArg); |
141 | 171 |
142 // On Linux, we dynamically link against the system version of libnss3.so. In | 172 // 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 | 173 // order to continue working on systems without up-to-date versions of NSS we |
(...skipping 18 matching lines...) Expand all Loading... |
162 RuntimeLibNSSFunctionPointers() { | 192 RuntimeLibNSSFunctionPointers() { |
163 cache_ocsp_response_from_side_channel_ = | 193 cache_ocsp_response_from_side_channel_ = |
164 (CacheOCSPResponseFromSideChannelFunction) | 194 (CacheOCSPResponseFromSideChannelFunction) |
165 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"); | 195 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"); |
166 } | 196 } |
167 | 197 |
168 CacheOCSPResponseFromSideChannelFunction | 198 CacheOCSPResponseFromSideChannelFunction |
169 cache_ocsp_response_from_side_channel_; | 199 cache_ocsp_response_from_side_channel_; |
170 }; | 200 }; |
171 | 201 |
172 static CacheOCSPResponseFromSideChannelFunction | 202 CacheOCSPResponseFromSideChannelFunction |
173 GetCacheOCSPResponseFromSideChannelFunction() { | 203 GetCacheOCSPResponseFromSideChannelFunction() { |
174 return RuntimeLibNSSFunctionPointers::GetInstance() | 204 return RuntimeLibNSSFunctionPointers::GetInstance() |
175 ->GetCacheOCSPResponseFromSideChannelFunction(); | 205 ->GetCacheOCSPResponseFromSideChannelFunction(); |
176 } | 206 } |
177 | 207 |
178 static bool IsOCSPStaplingSupported() { | 208 bool IsOCSPStaplingSupported() { |
179 return GetCacheOCSPResponseFromSideChannelFunction() != NULL; | 209 return GetCacheOCSPResponseFromSideChannelFunction() != NULL; |
180 } | 210 } |
181 #else | 211 #else |
182 // TODO(agl): Figure out if we can plumb the OCSP response into Mac's system | 212 // TODO(agl): Figure out if we can plumb the OCSP response into Mac's system |
183 // certificate validation functions. | 213 // certificate validation functions. |
184 static bool IsOCSPStaplingSupported() { | 214 bool IsOCSPStaplingSupported() { |
185 return false; | 215 return false; |
186 } | 216 } |
187 #endif | 217 #endif |
188 | 218 |
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 { | 219 class FreeCERTCertificate { |
214 public: | 220 public: |
215 inline void operator()(CERTCertificate* x) const { | 221 inline void operator()(CERTCertificate* x) const { |
216 CERT_DestroyCertificate(x); | 222 CERT_DestroyCertificate(x); |
217 } | 223 } |
218 }; | 224 }; |
219 typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate> | 225 typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate> |
220 ScopedCERTCertificate; | 226 ScopedCERTCertificate; |
221 | 227 |
222 #if defined(OS_WIN) | 228 #if defined(OS_WIN) |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 //////////////////////////////////////////////////////////////////////////// | 836 //////////////////////////////////////////////////////////////////////////// |
831 HostPortPair host_and_port_; | 837 HostPortPair host_and_port_; |
832 SSLConfig ssl_config_; | 838 SSLConfig ssl_config_; |
833 | 839 |
834 // NSS SSL socket. | 840 // NSS SSL socket. |
835 PRFileDesc* nss_fd_; | 841 PRFileDesc* nss_fd_; |
836 | 842 |
837 // Buffers for the network end of the SSL state machine | 843 // Buffers for the network end of the SSL state machine |
838 memio_Private* nss_bufs_; | 844 memio_Private* nss_bufs_; |
839 | 845 |
| 846 // Used by DoPayloadRead() when attempting to fill the caller's buffer with |
| 847 // as much data as possible, without blocking. |
| 848 // If DoPayloadRead() encounters an error after having read some data, stores |
| 849 // the results to return on the *next* call to DoPayloadRead(). A value of |
| 850 // kNoPendingReadResult indicates there is no pending result, otherwise 0 |
| 851 // indicates EOF and < 0 indicates an error. |
| 852 int pending_read_result_; |
| 853 // Contains the previously observed NSS error. Only valid when |
| 854 // pending_read_result_ != kNoPendingReadResult. |
| 855 PRErrorCode pending_read_nss_error_; |
| 856 |
840 // The certificate chain, in DER form, that is expected to be received from | 857 // The certificate chain, in DER form, that is expected to be received from |
841 // the server. | 858 // the server. |
842 std::vector<std::string> predicted_certs_; | 859 std::vector<std::string> predicted_certs_; |
843 | 860 |
844 State next_handshake_state_; | 861 State next_handshake_state_; |
845 | 862 |
846 // True if channel ID extension was negotiated. | 863 // True if channel ID extension was negotiated. |
847 bool channel_id_xtn_negotiated_; | 864 bool channel_id_xtn_negotiated_; |
848 // True if the handshake state machine was interrupted for channel ID. | 865 // True if the handshake state machine was interrupted for channel ID. |
849 bool channel_id_needed_; | 866 bool channel_id_needed_; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 weak_net_log_factory_(net_log), | 922 weak_net_log_factory_(net_log), |
906 server_bound_cert_service_(server_bound_cert_service), | 923 server_bound_cert_service_(server_bound_cert_service), |
907 unhandled_buffer_size_(0), | 924 unhandled_buffer_size_(0), |
908 nss_waiting_read_(false), | 925 nss_waiting_read_(false), |
909 nss_waiting_write_(false), | 926 nss_waiting_write_(false), |
910 nss_is_closed_(false), | 927 nss_is_closed_(false), |
911 host_and_port_(host_and_port), | 928 host_and_port_(host_and_port), |
912 ssl_config_(ssl_config), | 929 ssl_config_(ssl_config), |
913 nss_fd_(NULL), | 930 nss_fd_(NULL), |
914 nss_bufs_(NULL), | 931 nss_bufs_(NULL), |
| 932 pending_read_result_(kNoPendingReadResult), |
| 933 pending_read_nss_error_(0), |
915 next_handshake_state_(STATE_NONE), | 934 next_handshake_state_(STATE_NONE), |
916 channel_id_xtn_negotiated_(false), | 935 channel_id_xtn_negotiated_(false), |
917 channel_id_needed_(false), | 936 channel_id_needed_(false), |
918 client_auth_cert_needed_(false), | 937 client_auth_cert_needed_(false), |
919 handshake_callback_called_(false), | 938 handshake_callback_called_(false), |
920 transport_recv_busy_(false), | 939 transport_recv_busy_(false), |
921 transport_recv_eof_(false), | 940 transport_recv_eof_(false), |
922 transport_send_busy_(false), | 941 transport_send_busy_(false), |
923 user_read_buf_len_(0), | 942 user_read_buf_len_(0), |
924 user_write_buf_len_(0), | 943 user_write_buf_len_(0), |
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 SetChannelIDProvided(); | 1957 SetChannelIDProvided(); |
1939 GotoState(STATE_HANDSHAKE); | 1958 GotoState(STATE_HANDSHAKE); |
1940 return OK; | 1959 return OK; |
1941 } | 1960 } |
1942 | 1961 |
1943 int SSLClientSocketNSS::Core::DoPayloadRead() { | 1962 int SSLClientSocketNSS::Core::DoPayloadRead() { |
1944 DCHECK(OnNSSTaskRunner()); | 1963 DCHECK(OnNSSTaskRunner()); |
1945 DCHECK(user_read_buf_); | 1964 DCHECK(user_read_buf_); |
1946 DCHECK_GT(user_read_buf_len_, 0); | 1965 DCHECK_GT(user_read_buf_len_, 0); |
1947 | 1966 |
1948 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); | 1967 int rv; |
1949 // Update NSSTaskRunner status because PR_Read may consume |nss_bufs_|, then | 1968 // If a previous greedy read resulted in an error that was not consumed (eg: |
1950 // following |amount_in_read_buffer| may be changed here. | 1969 // due to the caller having read some data successfully), then return that |
1951 int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); | 1970 // pending error now. |
1952 PostOrRunCallback( | 1971 if (pending_read_result_ != kNoPendingReadResult) { |
1953 FROM_HERE, | 1972 rv = pending_read_result_; |
1954 base::Bind(&Core::OnNSSBufferUpdated, this, amount_in_read_buffer)); | 1973 PRErrorCode prerr = pending_read_nss_error_; |
| 1974 pending_read_result_ = kNoPendingReadResult; |
| 1975 pending_read_nss_error_ = 0; |
1955 | 1976 |
1956 if (client_auth_cert_needed_) { | 1977 if (rv == 0) { |
1957 // We don't need to invalidate the non-client-authenticated SSL session | 1978 PostOrRunCallback( |
1958 // because the server will renegotiate anyway. | 1979 FROM_HERE, |
1959 rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1980 base::Bind(&LogByteTransferEvent, weak_net_log_, |
1960 PostOrRunCallback( | 1981 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, |
1961 FROM_HERE, | 1982 scoped_refptr<IOBuffer>(user_read_buf_))); |
1962 base::Bind(&AddLogEventWithCallback, weak_net_log_, | 1983 } else { |
1963 NetLog::TYPE_SSL_READ_ERROR, | 1984 PostOrRunCallback( |
1964 CreateNetLogSSLErrorCallback(rv, 0))); | 1985 FROM_HERE, |
| 1986 base::Bind(&AddLogEventWithCallback, weak_net_log_, |
| 1987 NetLog::TYPE_SSL_READ_ERROR, |
| 1988 CreateNetLogSSLErrorCallback(rv, prerr))); |
| 1989 } |
1965 return rv; | 1990 return rv; |
1966 } | 1991 } |
| 1992 |
| 1993 // Perform a greedy read, attempting to read as much as the caller has |
| 1994 // requested. In the current NSS implementation, PR_Read will return |
| 1995 // exactly one SSL application data record's worth of data per invocation. |
| 1996 // The record size is dictated by the server, and may be noticeably smaller |
| 1997 // than the caller's buffer. This may be as little as a single byte, if the |
| 1998 // server is performing 1/n-1 record splitting. |
| 1999 // |
| 2000 // However, this greedy read may result in renegotiations/re-handshakes |
| 2001 // happening or may lead to some data being read, followed by an EOF (such as |
| 2002 // a TLS close-notify). If at least some data was read, then that result |
| 2003 // should be deferred until the next call to DoPayloadRead(). Otherwise, if no |
| 2004 // data was read, it's safe to return the error or EOF immediately. |
| 2005 int total_bytes_read = 0; |
| 2006 do { |
| 2007 rv = PR_Read(nss_fd_, user_read_buf_->data() + total_bytes_read, |
| 2008 user_read_buf_len_ - total_bytes_read); |
| 2009 if (rv > 0) |
| 2010 total_bytes_read += rv; |
| 2011 } while (total_bytes_read < user_read_buf_len_ && rv > 0); |
| 2012 int amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); |
| 2013 PostOrRunCallback(FROM_HERE, base::Bind(&Core::OnNSSBufferUpdated, this, |
| 2014 amount_in_read_buffer)); |
| 2015 |
| 2016 if (total_bytes_read == user_read_buf_len_) { |
| 2017 // The caller's entire request was satisfied without error. No further |
| 2018 // processing needed. |
| 2019 rv = total_bytes_read; |
| 2020 } else { |
| 2021 // Otherwise, an error occurred (rv <= 0). The error needs to be handled |
| 2022 // immediately, while the NSPR/NSS errors are still available in |
| 2023 // thread-local storage. However, the handled/remapped error code should |
| 2024 // only be returned if no application data was already read; if it was, the |
| 2025 // error code should be deferred until the next call of DoPayloadRead. |
| 2026 // |
| 2027 // If no data was read, |*next_result| will point to the return value of |
| 2028 // this function. If at least some data was read, |*next_result| will point |
| 2029 // to |pending_read_error_|, to be returned in a future call to |
| 2030 // DoPayloadRead() (e.g.: after the current data is handled). |
| 2031 int* next_result = &rv; |
| 2032 if (total_bytes_read > 0) { |
| 2033 pending_read_result_ = rv; |
| 2034 rv = total_bytes_read; |
| 2035 next_result = &pending_read_result_; |
| 2036 } |
| 2037 |
| 2038 if (client_auth_cert_needed_) { |
| 2039 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 2040 pending_read_nss_error_ = 0; |
| 2041 } else if (*next_result < 0) { |
| 2042 // If *next_result == 0, then that indicates EOF, and no special error |
| 2043 // handling is needed. |
| 2044 pending_read_nss_error_ = PR_GetError(); |
| 2045 *next_result = HandleNSSError(pending_read_nss_error_, false); |
| 2046 if (rv > 0 && *next_result == ERR_IO_PENDING) { |
| 2047 // If at least some data was read from PR_Read(), do not treat |
| 2048 // insufficient data as an error to return in the next call to |
| 2049 // DoPayloadRead() - instead, let the call fall through to check |
| 2050 // PR_Read() again. This is because DoTransportIO() may complete |
| 2051 // in between the next call to DoPayloadRead(), and thus it is |
| 2052 // important to check PR_Read() on subsequent invocations to see |
| 2053 // if a complete record may now be read. |
| 2054 pending_read_nss_error_ = 0; |
| 2055 pending_read_result_ = kNoPendingReadResult; |
| 2056 } |
| 2057 } |
| 2058 } |
| 2059 |
| 2060 DCHECK_NE(ERR_IO_PENDING, pending_read_result_); |
| 2061 |
1967 if (rv >= 0) { | 2062 if (rv >= 0) { |
1968 PostOrRunCallback( | 2063 PostOrRunCallback( |
1969 FROM_HERE, | 2064 FROM_HERE, |
1970 base::Bind(&LogByteTransferEvent, weak_net_log_, | 2065 base::Bind(&LogByteTransferEvent, weak_net_log_, |
1971 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, | 2066 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, |
1972 scoped_refptr<IOBuffer>(user_read_buf_))); | 2067 scoped_refptr<IOBuffer>(user_read_buf_))); |
1973 return rv; | 2068 } else if (rv != ERR_IO_PENDING) { |
| 2069 PostOrRunCallback( |
| 2070 FROM_HERE, |
| 2071 base::Bind(&AddLogEventWithCallback, weak_net_log_, |
| 2072 NetLog::TYPE_SSL_READ_ERROR, |
| 2073 CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_))); |
| 2074 pending_read_nss_error_ = 0; |
1974 } | 2075 } |
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; | 2076 return rv; |
1986 } | 2077 } |
1987 | 2078 |
1988 int SSLClientSocketNSS::Core::DoPayloadWrite() { | 2079 int SSLClientSocketNSS::Core::DoPayloadWrite() { |
1989 DCHECK(OnNSSTaskRunner()); | 2080 DCHECK(OnNSSTaskRunner()); |
1990 | 2081 |
1991 DCHECK(user_write_buf_); | 2082 DCHECK(user_write_buf_); |
1992 | 2083 |
1993 int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); | 2084 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_); | 2085 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(); | 3530 EnsureThreadIdAssigned(); |
3440 base::AutoLock auto_lock(lock_); | 3531 base::AutoLock auto_lock(lock_); |
3441 return valid_thread_id_ == base::PlatformThread::CurrentId(); | 3532 return valid_thread_id_ == base::PlatformThread::CurrentId(); |
3442 } | 3533 } |
3443 | 3534 |
3444 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { | 3535 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { |
3445 return server_bound_cert_service_; | 3536 return server_bound_cert_service_; |
3446 } | 3537 } |
3447 | 3538 |
3448 } // namespace net | 3539 } // namespace net |
OLD | NEW |