OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/socket/ssl_client_socket_mac.h" | 5 #include "net/socket/ssl_client_socket_mac.h" |
6 | 6 |
7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> |
8 #include <netdb.h> | 8 #include <netdb.h> |
9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 hostname_.length()); | 795 hostname_.length()); |
796 if (status) | 796 if (status) |
797 return NetErrorFromOSStatus(status); | 797 return NetErrorFromOSStatus(status); |
798 | 798 |
799 // Disable certificate verification within Secure Transport; we'll | 799 // Disable certificate verification within Secure Transport; we'll |
800 // be handling that ourselves. | 800 // be handling that ourselves. |
801 status = SSLSetEnableCertVerify(ssl_context_, false); | 801 status = SSLSetEnableCertVerify(ssl_context_, false); |
802 if (status) | 802 if (status) |
803 return NetErrorFromOSStatus(status); | 803 return NetErrorFromOSStatus(status); |
804 | 804 |
| 805 // It is tricky to handle client cert request over renegotiation due to bugs |
| 806 // in Secure Transport. From Ken McLeod on apple-cdsa: |
| 807 // http://lists.apple.com/archives/apple-cdsa/2010/Feb/msg00058.html |
| 808 // A possible workaround would be to set the |
| 809 // kSSLSessionOptionBreakOnCertRequested option initially, then if you get |
| 810 // that status, ask for a client cert, abort the connection yourself and |
| 811 // retry it (this time calling SSLSetCertificate before the handshake |
| 812 // starts, and *not* setting the kSSLSessionOptionBreakOnCertRequested |
| 813 // option.) |
805 if (ssl_config_.send_client_cert) { | 814 if (ssl_config_.send_client_cert) { |
806 // Provide the client cert up-front if we have one, even though we'll get | |
807 // notified later when the server requests it, and set it again; this is | |
808 // seemingly redundant but works around a problem with SecureTransport | |
809 // and provides correct behavior on both 10.5 and 10.6: | |
810 // http://lists.apple.com/archives/apple-cdsa/2010/Feb/msg00058.html | |
811 // http://code.google.com/p/chromium/issues/detail?id=38905 | |
812 SSL_LOG << "Setting client cert in advance because send_client_cert is set"; | 815 SSL_LOG << "Setting client cert in advance because send_client_cert is set"; |
813 status = SetClientCert(); | 816 status = SetClientCert(); |
814 if (status) | 817 if (status) |
815 return NetErrorFromOSStatus(status); | 818 return NetErrorFromOSStatus(status); |
| 819 return OK; |
816 } | 820 } |
817 | 821 |
818 status = EnableBreakOnAuth(true); | 822 status = EnableBreakOnAuth(true); |
819 if (status == noErr) { | 823 if (status == noErr) { |
820 // Only enable session resumption if break-on-auth is available, | 824 // Only enable session resumption if break-on-auth is available, |
821 // because without break-on-auth we are verifying the server's certificate | 825 // because without break-on-auth we are verifying the server's certificate |
822 // after the handshake completes (but before any application data is | 826 // after the handshake completes (but before any application data is |
823 // exchanged). If we were to enable session resumption in this situation, | 827 // exchanged). If we were to enable session resumption in this situation, |
824 // the session would be cached before we verified the certificate, leaving | 828 // the session would be cached before we verified the certificate, leaving |
825 // the potential for a session in which the certificate failed to validate | 829 // the potential for a session in which the certificate failed to validate |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 | 1106 |
1103 int SSLClientSocketMac::DoHandshakeFinish() { | 1107 int SSLClientSocketMac::DoHandshakeFinish() { |
1104 OSStatus status = SSLHandshake(ssl_context_); | 1108 OSStatus status = SSLHandshake(ssl_context_); |
1105 | 1109 |
1106 switch (status) { | 1110 switch (status) { |
1107 case errSSLWouldBlock: | 1111 case errSSLWouldBlock: |
1108 next_handshake_state_ = STATE_HANDSHAKE_FINISH; | 1112 next_handshake_state_ = STATE_HANDSHAKE_FINISH; |
1109 break; | 1113 break; |
1110 case errSSLClientCertRequested: | 1114 case errSSLClientCertRequested: |
1111 SSL_LOG << "Server requested client cert (DoHandshakeFinish)"; | 1115 SSL_LOG << "Server requested client cert (DoHandshakeFinish)"; |
1112 if (!ssl_config_.send_client_cert) | 1116 DCHECK(!ssl_config_.send_client_cert); |
1113 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1117 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
1114 // (We already called SetClientCert during InitializeSSLContext.) | |
1115 status = noErr; | |
1116 next_handshake_state_ = STATE_HANDSHAKE_FINISH; | |
1117 break; | 1118 break; |
1118 case errSSLClosedGraceful: | 1119 case errSSLClosedGraceful: |
1119 return ERR_SSL_PROTOCOL_ERROR; | 1120 return ERR_SSL_PROTOCOL_ERROR; |
1120 case errSSLClosedAbort: | 1121 case errSSLClosedAbort: |
1121 case errSSLPeerHandshakeFail: { | 1122 case errSSLPeerHandshakeFail: { |
1122 // See if the server aborted due to client cert checking. | 1123 // See if the server aborted due to client cert checking. |
1123 SSLClientCertificateState client_state; | 1124 SSLClientCertificateState client_state; |
1124 if (SSLGetClientCertificateState(ssl_context_, &client_state) == noErr && | 1125 if (SSLGetClientCertificateState(ssl_context_, &client_state) == noErr && |
1125 client_state > kSSLClientCertNone) { | 1126 client_state > kSSLClientCertNone) { |
1126 if (client_state == kSSLClientCertRequested && | 1127 if (client_state == kSSLClientCertRequested && |
(...skipping 14 matching lines...) Expand all Loading... |
1141 DCHECK(next_handshake_state_ == STATE_NONE); | 1142 DCHECK(next_handshake_state_ == STATE_NONE); |
1142 break; | 1143 break; |
1143 default: | 1144 default: |
1144 break; | 1145 break; |
1145 } | 1146 } |
1146 | 1147 |
1147 return NetErrorFromOSStatus(status); | 1148 return NetErrorFromOSStatus(status); |
1148 } | 1149 } |
1149 | 1150 |
1150 void SSLClientSocketMac::HandshakeFinished() { | 1151 void SSLClientSocketMac::HandshakeFinished() { |
1151 // After the handshake's finished, disable breaking on server or client | |
1152 // auth. Otherwise it might be triggered during a subsequent renegotiation, | |
1153 // and SecureTransport doesn't handle that very well (there's usually no way | |
1154 // to proceed without aborting the connection, at least not on 10.5.) | |
1155 SSL_LOG << "HandshakeFinished()"; | 1152 SSL_LOG << "HandshakeFinished()"; |
1156 OSStatus status = EnableBreakOnAuth(false); | |
1157 if (status != noErr) | |
1158 SSL_LOG << "EnableBreakOnAuth failed: " << status; | |
1159 // Note- this will actually always return an error, up through OS 10.6.3, | |
1160 // because the option can't be changed after the context opens. | |
1161 } | 1153 } |
1162 | 1154 |
1163 int SSLClientSocketMac::DoPayloadRead() { | 1155 int SSLClientSocketMac::DoPayloadRead() { |
1164 size_t processed = 0; | 1156 size_t processed = 0; |
1165 OSStatus status = SSLRead(ssl_context_, | 1157 OSStatus status = SSLRead(ssl_context_, |
1166 user_read_buf_->data(), | 1158 user_read_buf_->data(), |
1167 user_read_buf_len_, | 1159 user_read_buf_len_, |
1168 &processed); | 1160 &processed); |
1169 | 1161 |
1170 // There's a subtle difference here in semantics of the "would block" errors. | 1162 // There's a subtle difference here in semantics of the "would block" errors. |
1171 // In our code, ERR_IO_PENDING means the whole operation is async, while | 1163 // In our code, ERR_IO_PENDING means the whole operation is async, while |
1172 // errSSLWouldBlock means that the stream isn't ending (and is often returned | 1164 // errSSLWouldBlock means that the stream isn't ending (and is often returned |
1173 // along with partial data). So even though "would block" is returned, if we | 1165 // along with partial data). So even though "would block" is returned, if we |
1174 // have data, let's just return it. | 1166 // have data, let's just return it. |
1175 | 1167 |
1176 if (processed > 0) | 1168 if (processed > 0) |
1177 return processed; | 1169 return processed; |
1178 | 1170 |
1179 switch (status) { | 1171 switch (status) { |
1180 case errSSLClosedNoNotify: | 1172 case errSSLClosedNoNotify: |
1181 // TODO(wtc): Unless we have received the close_notify alert, we need to | 1173 // TODO(wtc): Unless we have received the close_notify alert, we need to |
1182 // return an error code indicating that the SSL connection ended | 1174 // return an error code indicating that the SSL connection ended |
1183 // uncleanly, a potential truncation attack. See http://crbug.com/18586. | 1175 // uncleanly, a potential truncation attack. See http://crbug.com/18586. |
1184 return OK; | 1176 return OK; |
1185 | 1177 |
1186 case errSSLServerAuthCompleted: | 1178 case errSSLServerAuthCompleted: |
1187 case errSSLClientCertRequested: | 1179 case errSSLClientCertRequested: |
1188 // Server wants to renegotiate, probably to ask for a client cert, | 1180 // Server wants to renegotiate, probably to ask for a client cert, |
1189 // but SecureTransport doesn't support renegotiation so we have to close. | 1181 // but SecureTransport doesn't support renegotiation so we have to close. |
1190 if (ssl_config_.send_client_cert) { | 1182 DCHECK(!ssl_config_.send_client_cert); |
1191 // We already gave SecureTransport a client cert. At this point there's | |
1192 // nothing we can do; the renegotiation will fail regardless, due to | |
1193 // bugs in Apple's SecureTransport library. | |
1194 SSL_LOG << "Server renegotiating (status=" << status | |
1195 << "), but I've already set a client cert. Fatal error."; | |
1196 return ERR_SSL_PROTOCOL_ERROR; | |
1197 } | |
1198 // Tell my caller the server wants a client cert so it can reconnect. | 1183 // Tell my caller the server wants a client cert so it can reconnect. |
1199 SSL_LOG << "Server renegotiating; assuming it wants a client cert..."; | 1184 SSL_LOG << "Server renegotiating; assuming it wants a client cert..."; |
1200 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1185 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
1201 | 1186 |
1202 default: | 1187 default: |
1203 return NetErrorFromOSStatus(status); | 1188 return NetErrorFromOSStatus(status); |
1204 } | 1189 } |
1205 } | 1190 } |
1206 | 1191 |
1207 int SSLClientSocketMac::DoPayloadWrite() { | 1192 int SSLClientSocketMac::DoPayloadWrite() { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 if (rv < 0 && rv != ERR_IO_PENDING) { | 1303 if (rv < 0 && rv != ERR_IO_PENDING) { |
1319 us->write_io_buf_ = NULL; | 1304 us->write_io_buf_ = NULL; |
1320 return OSStatusFromNetError(rv); | 1305 return OSStatusFromNetError(rv); |
1321 } | 1306 } |
1322 | 1307 |
1323 // always lie to our caller | 1308 // always lie to our caller |
1324 return noErr; | 1309 return noErr; |
1325 } | 1310 } |
1326 | 1311 |
1327 } // namespace net | 1312 } // namespace net |
OLD | NEW |