Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: net/socket/ssl_client_socket_nss.cc

Issue 12025040: When reading from an SSL socket, attempt to fully fill the caller's buffer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comment update Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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.
wtc 2013/02/15 23:14:49 It'd be nice to point out this constant can be any
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
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
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
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
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) {
wtc 2013/02/15 23:14:49 I believe rv cannot be 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 pending_read_nss_error_ = 0;
2045 if (rv > 0) {
2046 // If at least some data was read from PR_Read(), do not treat
2047 // insufficient data as an error to return in the next call to
2048 // DoPayloadRead() - instead, let the call fall through to check
2049 // PR_Read() again. This is because DoTransportIO() may complete
2050 // in between the next call to DoPayloadRead(), and thus it is
2051 // important to check PR_Read() on subsequent invocations to see
2052 // if a complete record may now be read.
2053 pending_read_result_ = kNoPendingReadResult;
2054 } else {
2055 *next_result = ERR_IO_PENDING;
wtc 2013/02/15 23:14:49 I think it's clearer to use |rv| here: rv = ER
2056 }
2057 } else {
2058 *next_result = HandleNSSError(pending_read_nss_error_, false);
wtc 2013/02/15 23:14:49 HandleNSSError maps PR_WOULD_BLOCK_ERROR to ERR_IO
2059 }
2060 }
2061 }
2062
wtc 2013/02/15 23:14:49 Here you can CHECK or DCHECK that we never set pen
1967 if (rv >= 0) { 2063 if (rv >= 0) {
1968 PostOrRunCallback( 2064 PostOrRunCallback(
1969 FROM_HERE, 2065 FROM_HERE,
1970 base::Bind(&LogByteTransferEvent, weak_net_log_, 2066 base::Bind(&LogByteTransferEvent, weak_net_log_,
1971 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, 2067 NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1972 scoped_refptr<IOBuffer>(user_read_buf_))); 2068 scoped_refptr<IOBuffer>(user_read_buf_)));
1973 return rv; 2069 } else if (rv != ERR_IO_PENDING) {
2070 PostOrRunCallback(
2071 FROM_HERE,
2072 base::Bind(&AddLogEventWithCallback, weak_net_log_,
2073 NetLog::TYPE_SSL_READ_ERROR,
2074 CreateNetLogSSLErrorCallback(rv, pending_read_nss_error_)));
2075 pending_read_nss_error_ = 0;
1974 } 2076 }
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; 2077 return rv;
1986 } 2078 }
1987 2079
1988 int SSLClientSocketNSS::Core::DoPayloadWrite() { 2080 int SSLClientSocketNSS::Core::DoPayloadWrite() {
1989 DCHECK(OnNSSTaskRunner()); 2081 DCHECK(OnNSSTaskRunner());
1990 2082
1991 DCHECK(user_write_buf_); 2083 DCHECK(user_write_buf_);
1992 2084
1993 int old_amount_in_read_buffer = memio_GetReadableBufferSize(nss_bufs_); 2085 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_); 2086 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
3439 EnsureThreadIdAssigned(); 3531 EnsureThreadIdAssigned();
3440 base::AutoLock auto_lock(lock_); 3532 base::AutoLock auto_lock(lock_);
3441 return valid_thread_id_ == base::PlatformThread::CurrentId(); 3533 return valid_thread_id_ == base::PlatformThread::CurrentId();
3442 } 3534 }
3443 3535
3444 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { 3536 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const {
3445 return server_bound_cert_service_; 3537 return server_bound_cert_service_;
3446 } 3538 }
3447 3539
3448 } // namespace net 3540 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/socket/ssl_client_socket_openssl.h » ('j') | net/socket/ssl_client_socket_openssl.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698