1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_SSL_CLIENT_SOCKET_WIN_H_
#define NET_BASE_SSL_CLIENT_SOCKET_WIN_H_
#define SECURITY_WIN32 // Needs to be defined before including security.h
#include <windows.h>
#include <wincrypt.h>
#include <security.h>
#include <string>
#include "base/scoped_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/ssl_client_socket.h"
#include "net/base/ssl_config_service.h"
namespace net {
// An SSL client socket implemented with the Windows Schannel.
class SSLClientSocketWin : public SSLClientSocket {
public:
// Takes ownership of the transport_socket, which may already be connected.
// The given hostname will be compared with the name(s) in the server's
// certificate during the SSL handshake. ssl_config specifies the SSL
// settings.
SSLClientSocketWin(ClientSocket* transport_socket,
const std::string& hostname,
const SSLConfig& ssl_config);
~SSLClientSocketWin();
// SSLClientSocket methods:
virtual void GetSSLInfo(SSLInfo* ssl_info);
// ClientSocket methods:
virtual int Connect(CompletionCallback* callback);
virtual int ReconnectIgnoringLastError(CompletionCallback* callback);
virtual void Disconnect();
virtual bool IsConnected() const;
// Socket methods:
virtual int Read(char* buf, int buf_len, CompletionCallback* callback);
virtual int Write(const char* buf, int buf_len, CompletionCallback* callback);
private:
void DoCallback(int result);
void OnIOComplete(int result);
int DoLoop(int last_io_result);
int DoConnect();
int DoConnectComplete(int result);
int DoHandshakeRead();
int DoHandshakeReadComplete(int result);
int DoHandshakeWrite();
int DoHandshakeWriteComplete(int result);
int DoPayloadRead();
int DoPayloadReadComplete(int result);
int DoPayloadEncrypt();
int DoPayloadWrite();
int DoPayloadWriteComplete(int result);
int DidCompleteHandshake();
int VerifyServerCert();
CompletionCallbackImpl<SSLClientSocketWin> io_callback_;
scoped_ptr<ClientSocket> transport_;
std::string hostname_;
SSLConfig ssl_config_;
CompletionCallback* user_callback_;
// Used by both Read and Write functions.
char* user_buf_;
int user_buf_len_;
enum State {
STATE_NONE,
STATE_CONNECT,
STATE_CONNECT_COMPLETE,
STATE_HANDSHAKE_READ,
STATE_HANDSHAKE_READ_COMPLETE,
STATE_HANDSHAKE_WRITE,
STATE_HANDSHAKE_WRITE_COMPLETE,
STATE_PAYLOAD_ENCRYPT,
STATE_PAYLOAD_WRITE,
STATE_PAYLOAD_WRITE_COMPLETE,
STATE_PAYLOAD_READ,
STATE_PAYLOAD_READ_COMPLETE,
};
State next_state_;
SecPkgContext_StreamSizes stream_sizes_;
PCCERT_CONTEXT server_cert_;
int server_cert_status_;
CredHandle* creds_;
CtxtHandle ctxt_;
SecBuffer send_buffer_;
scoped_array<char> payload_send_buffer_;
int payload_send_buffer_len_;
int bytes_sent_;
// recv_buffer_ holds the received ciphertext. Since Schannel decrypts
// data in place, sometimes recv_buffer_ may contain decrypted plaintext and
// any undecrypted ciphertext. (Ciphertext is decrypted one full SSL record
// at a time.)
//
// If bytes_decrypted_ is 0, the received ciphertext is at the beginning of
// recv_buffer_, ready to be passed to DecryptMessage.
scoped_array<char> recv_buffer_;
char* decrypted_ptr_; // Points to the decrypted plaintext in recv_buffer_
int bytes_decrypted_; // The number of bytes of decrypted plaintext.
char* received_ptr_; // Points to the received ciphertext in recv_buffer_
int bytes_received_; // The number of bytes of received ciphertext.
bool completed_handshake_;
bool complete_handshake_on_write_complete_;
// Only used in the STATE_HANDSHAKE_READ_COMPLETE and
// STATE_PAYLOAD_READ_COMPLETE states. True if a 'result' argument of OK
// should be ignored, to prevent it from being interpreted as EOF.
//
// The reason we need this flag is that OK means not only "0 bytes of data
// were read" but also EOF. We set ignore_ok_result_ to true when we need
// to continue processing previously read data without reading more data.
// We have to pass a 'result' of OK to the DoLoop method, and don't want it
// to be interpreted as EOF.
bool ignore_ok_result_;
// True if the user has no client certificate.
bool no_client_cert_;
};
} // namespace net
#endif // NET_BASE_SSL_CLIENT_SOCKET_WIN_H_
|