Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Contents of /trunk/TTProxy/SSLSocket.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3227 - (show annotations) (download) (as text)
Tue Mar 24 15:10:33 2009 UTC (15 years, 1 month ago) by maya
File MIME type: text/x-chdr
File size: 14060 byte(s)
CVS から SVN へ移行: 改行コードを LF から CR+LF へ変換
1 #ifndef _YEBISOCKS_SSLSOCKET_H_
2 #define _YEBISOCKS_SSLSOCKET_H_
3
4 #include <openssl/crypto.h>
5 #include <openssl/x509.h>
6 #include <openssl/pem.h>
7 #include <openssl/ssl.h>
8 #include <openssl/err.h>
9 #include <openssl/x509v3.h>
10
11 #include "SSLLIB.h"
12
13 #define IDS_UNABLE_TO_GET_ISSUER_CERT 200
14 #define IDS_UNABLE_TO_GET_CRL 201
15 #define IDS_UNABLE_TO_DECRYPT_CERT_SIGNATURE 202
16 #define IDS_UNABLE_TO_DECRYPT_CRL_SIGNATURE 203
17 #define IDS_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 204
18 #define IDS_CERT_SIGNATURE_FAILURE 205
19 #define IDS_CRL_SIGNATURE_FAILURE 206
20 #define IDS_CERT_NOT_YET_VALID 207
21 #define IDS_CERT_HAS_EXPIRED 208
22 #define IDS_CRL_NOT_YET_VALID 209
23 #define IDS_CRL_HAS_EXPIRED 210
24 #define IDS_ERROR_IN_CERT_NOT_BEFORE_FIELD 211
25 #define IDS_ERROR_IN_CERT_NOT_AFTER_FIELD 212
26 #define IDS_ERROR_IN_CRL_LAST_UPDATE_FIELD 213
27 #define IDS_ERROR_IN_CRL_NEXT_UPDATE_FIELD 214
28 #define IDS_OUT_OF_MEM 215
29 #define IDS_DEPTH_ZERO_SELF_SIGNED_CERT 216
30 #define IDS_SELF_SIGNED_CERT_IN_CHAIN 217
31 #define IDS_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 218
32 #define IDS_UNABLE_TO_VERIFY_LEAF_SIGNATURE 219
33 #define IDS_CERT_CHAIN_TOO_LONG 220
34 #define IDS_CERT_REVOKED 221
35 #define IDS_INVALID_CA 222
36 #define IDS_PATH_LENGTH_EXCEEDED 223
37 #define IDS_INVALID_PURPOSE 224
38 #define IDS_CERT_UNTRUSTED 225
39 #define IDS_CERT_REJECTED 226
40 #define IDS_SUBJECT_ISSUER_MISMATCH 227
41 #define IDS_AKID_SKID_MISMATCH 228
42 #define IDS_AKID_ISSUER_SERIAL_MISMATCH 229
43 #define IDS_KEYUSAGE_NO_CERTSIGN 230
44 #define IDS_APPLICATION_VERIFICATION 231
45 #define IDS_UNMATCH_COMMON_NAME 232
46 #define IDS_UNABLE_TO_GET_COMMON_NAME 233
47
48 class SSLSocket {
49 private:
50 class SSLContext {
51 friend class SSLSocket;
52 private:
53 SSL_CTX* ctx;
54
55 private:
56 SSLContext():ctx(NULL) {
57 SSL_library_init();
58 SSL_load_error_strings();
59 ctx = SSL_CTX_new(SSLv23_client_method());
60 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
61 }
62 public:
63 ~SSLContext() {
64 release();
65 }
66 void release() {
67 if (ctx != NULL) {
68 SSL_CTX_free(ctx);
69 ctx = NULL;
70 }
71 }
72 };
73 static SSLContext& context() {
74 static SSLContext instance;
75 return instance;
76 }
77 static HMODULE& LIBEAY32() {
78 static HMODULE module = NULL;
79 return module;
80 }
81 static HMODULE& SSLEAY32() {
82 static HMODULE module = NULL;
83 return module;
84 }
85 public:
86 static bool init() {
87 LIBEAY32() = ::LoadLibrary("LIBEAY32");
88 SSLEAY32() = ::LoadLibrary("SSLEAY32");
89 if (LIBEAY32() == NULL || SSLEAY32() == NULL) {
90 if (LIBEAY32() != NULL) {
91 ::FreeLibrary(LIBEAY32());
92 LIBEAY32() = NULL;
93 }
94 if (SSLEAY32() != NULL) {
95 ::FreeLibrary(SSLEAY32());
96 SSLEAY32() = NULL;
97 }
98 return false;
99 }
100 context();
101 return true;
102 }
103 static void exit() {
104 if (LIBEAY32() != NULL && SSLEAY32() != NULL) {
105 context().release();
106 ::FreeLibrary(LIBEAY32());
107 LIBEAY32() = NULL;
108 ::FreeLibrary(SSLEAY32());
109 SSLEAY32() = NULL;
110 }
111 }
112 static bool isEnabled() {
113 return LIBEAY32() != NULL && SSLEAY32() != NULL;
114 }
115
116 static bool addCertFile(const char* filename) {
117 return SSL_CTX_load_verify_locations(context().ctx, filename, NULL) != 0;
118 }
119 static bool addCertDirectory(const char* dirname) {
120 return SSL_CTX_load_verify_locations(context().ctx, NULL, dirname) != 0;
121 }
122 static bool addCert(const char* filename, const char* dirname) {
123 return SSL_CTX_load_verify_locations(context().ctx, filename, dirname) != 0;
124 }
125
126 private:
127 static int toLowerCase(int ch) {
128 return 'A' <= ch && ch <= 'Z' ? ch - 'A' + 'a' : ch;
129 }
130 static bool ssl_match_cert_ident(const char* ident, int ilen, const char* hostname) {
131 const char* s1 = ident;
132 const char* s2 = hostname;
133 const char* s1_end = s1 + ilen;
134 const char* s2_end = s2 + strlen(s2);
135 while (s1 < s1_end && s2 < s2_end) {
136 if (*s1 == '*' && s1 + 1 < s1_end && *(s1 + 1) == '.') {
137 s1++;
138 while (s2 < s2_end && *s2 != '.')
139 s2++;
140 if (*s2 != '.')
141 return false;
142 }else{
143 if (::IsDBCSLeadByte(*s1)) {
144 if (*s1 != *s2 || s1 + 1 >= s1_end || s2 + 1 >= s2_end || *(s1 + 1) != *(s2 + 1))
145 return false;
146 s1++;
147 s2++;
148 }else{
149 if (toLowerCase(*s1) != toLowerCase(*s2))
150 return false;
151 }
152 }
153 s1++;
154 s2++;
155 }
156 return true;
157 }
158
159 static int print_debugw32(const char *str, size_t len, void *u) {
160 char* buf = (char*) alloca(len + 1);
161 memcpy(buf, str, len);
162 buf[len] = '\0';
163 OutputDebugString(buf);
164 return len;
165 }
166 private:
167 SSL* ssl;
168 long verify_result;
169 public:
170 SSLSocket():ssl(NULL), verify_result(X509_V_ERR_OUT_OF_MEM) {
171 }
172 ~SSLSocket() {
173 close();
174 }
175 bool connect(SOCKET s, const char* hostname) {
176 close();
177 verify_result = IDS_APPLICATION_VERIFICATION;
178 ssl = SSL_new(context().ctx);
179 if (ssl != NULL) {
180 SSL_set_fd(ssl, s);
181 int ret;
182 do {
183 ret = SSL_connect(ssl);
184 if (SSL_get_error(ssl, ret) != SSL_ERROR_WANT_READ)
185 break;
186 fd_set ifd;
187 fd_set efd;
188 FD_ZERO(&ifd);
189 FD_ZERO(&efd);
190 FD_SET(s, &ifd);
191 FD_SET(s, &efd);
192 if (select((int) (s + 1), &ifd, NULL, &efd, NULL) == SOCKET_ERROR)
193 break;
194 if (!FD_ISSET(s, &ifd))
195 break;
196 }while (ret < 0);
197 if (ret == 1) {
198 X509* x509 = SSL_get_peer_certificate(ssl);
199 if (x509 != NULL) {
200 bool match = false;
201 /* SSL�����F�� */
202 int result = SSL_get_verify_result(ssl);
203 if (result == X509_V_OK) {
204 verify_result = 0;
205 int id = X509_get_ext_by_NID(x509, NID_subject_alt_name, -1);
206 if (id >= 0) {
207 X509_EXTENSION* ex = X509_get_ext(x509, id);
208 STACK_OF(GENERAL_NAME)* alt = (STACK_OF(GENERAL_NAME)*) X509V3_EXT_d2i(ex);
209 if (alt != NULL) {
210 int i;
211 int count = 0;
212 int n = sk_GENERAL_NAME_num(alt);
213 for (i = 0; i < n; i++) {
214 GENERAL_NAME* gn = sk_GENERAL_NAME_value(alt, i);
215 if (gn->type == GEN_DNS) {
216 char *sn = (char*) ASN1_STRING_data(gn->d.ia5);
217 int sl = ASN1_STRING_length(gn->d.ia5);
218 count++;
219 if (ssl_match_cert_ident(sn, sl, hostname))
220 break;
221 }
222 }
223 X509V3_EXT_METHOD* method = X509V3_EXT_get(ex);
224 sk_GENERAL_NAME_free(alt);
225 if (i < n)
226 match = true;
227 else if (count > 0)
228 verify_result = IDS_UNMATCH_COMMON_NAME; /* common name�����v���������� */
229 }
230 }
231 if (!match && verify_result == 0) {
232 X509_NAME* xn = X509_get_subject_name(x509);
233 char buf[1024];
234 if (X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof buf) == -1)
235 verify_result = IDS_UNABLE_TO_GET_COMMON_NAME; /* common name�����������s���� */
236 else if (!ssl_match_cert_ident(buf, strlen(buf), hostname))
237 verify_result = IDS_UNMATCH_COMMON_NAME; /* common name�����v���������� */
238 else
239 match = true;
240 }
241 }else{
242 static const long table[] = {
243 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, IDS_UNABLE_TO_GET_ISSUER_CERT,
244 X509_V_ERR_UNABLE_TO_GET_CRL, IDS_UNABLE_TO_GET_CRL,
245 X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, IDS_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
246 X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, IDS_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
247 X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, IDS_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
248 X509_V_ERR_CERT_SIGNATURE_FAILURE, IDS_CERT_SIGNATURE_FAILURE,
249 X509_V_ERR_CRL_SIGNATURE_FAILURE, IDS_CRL_SIGNATURE_FAILURE,
250 X509_V_ERR_CERT_NOT_YET_VALID, IDS_CERT_NOT_YET_VALID,
251 X509_V_ERR_CERT_HAS_EXPIRED, IDS_CERT_HAS_EXPIRED,
252 X509_V_ERR_CRL_NOT_YET_VALID, IDS_CRL_NOT_YET_VALID,
253 X509_V_ERR_CRL_HAS_EXPIRED, IDS_CRL_HAS_EXPIRED,
254 X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, IDS_ERROR_IN_CERT_NOT_BEFORE_FIELD,
255 X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, IDS_ERROR_IN_CERT_NOT_AFTER_FIELD,
256 X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, IDS_ERROR_IN_CRL_LAST_UPDATE_FIELD,
257 X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, IDS_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
258 X509_V_ERR_OUT_OF_MEM, IDS_OUT_OF_MEM,
259 X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, IDS_DEPTH_ZERO_SELF_SIGNED_CERT,
260 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, IDS_SELF_SIGNED_CERT_IN_CHAIN,
261 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, IDS_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
262 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, IDS_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
263 X509_V_ERR_CERT_CHAIN_TOO_LONG, IDS_CERT_CHAIN_TOO_LONG,
264 X509_V_ERR_CERT_REVOKED, IDS_CERT_REVOKED,
265 X509_V_ERR_INVALID_CA, IDS_INVALID_CA,
266 X509_V_ERR_PATH_LENGTH_EXCEEDED, IDS_PATH_LENGTH_EXCEEDED,
267 X509_V_ERR_INVALID_PURPOSE, IDS_INVALID_PURPOSE,
268 X509_V_ERR_CERT_UNTRUSTED, IDS_CERT_UNTRUSTED,
269 X509_V_ERR_CERT_REJECTED, IDS_CERT_REJECTED,
270 X509_V_ERR_SUBJECT_ISSUER_MISMATCH, IDS_SUBJECT_ISSUER_MISMATCH,
271 X509_V_ERR_AKID_SKID_MISMATCH, IDS_AKID_SKID_MISMATCH,
272 X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, IDS_AKID_ISSUER_SERIAL_MISMATCH,
273 X509_V_ERR_KEYUSAGE_NO_CERTSIGN, IDS_KEYUSAGE_NO_CERTSIGN,
274 X509_V_ERR_APPLICATION_VERIFICATION, IDS_APPLICATION_VERIFICATION,
275 };
276 for (int i = 0; i < countof(table); i += 2) {
277 if (table[i] == result) {
278 verify_result = table[i + 1];
279 break;
280 }
281 }
282 }
283 X509_free(x509);
284 if (match)
285 return true;
286 }
287 }
288 SSL_free(ssl);
289 ssl = NULL;
290 }
291 return false;
292 }
293 void close() {
294 if (ssl != NULL) {
295 SSL_shutdown(ssl);
296 SSL_free(ssl);
297 ssl = NULL;
298 }
299 }
300 char* get_cert_text()const {
301 char* text = NULL;
302 X509* x509 = SSL_get_peer_certificate(ssl);
303 if (x509 != NULL) {
304 BIO* bp = BIO_new(BIO_s_mem());
305 if (bp != NULL) {
306 if (PEM_write_bio_X509(bp, x509)) {
307 BUF_MEM* buf;
308 BIO_get_mem_ptr(bp, &buf);
309 text = (char*) OPENSSL_malloc(buf->length + 1);
310 if (text != NULL) {
311 memcpy(text, buf->data, buf->length);
312 text[buf->length] = '\0';
313 }
314 }
315 BIO_free(bp);
316 }
317 X509_free(x509);
318 }
319 return text;
320 }
321 size_t write(const void* buffer, size_t length) {
322 return ssl != NULL ? SSL_write(ssl, buffer, length) : -1;
323 }
324 size_t read(void* buffer, size_t length) {
325 return ssl != NULL ? SSL_read(ssl, buffer, length) : -1;
326 }
327 long get_verify_result()const {
328 return verify_result;
329 }
330 };
331
332 #endif//_YEBISOCKS_SSLSOCKET_H_

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26