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 // This helper binary is only used for testing Chrome's SSL stack. | 5 // This helper binary is only used for testing Chrome's SSL stack. |
6 | 6 |
| 7 #include <arpa/inet.h> |
| 8 #include <netinet/tcp.h> |
7 #include <sys/types.h> | 9 #include <sys/types.h> |
8 #include <sys/socket.h> | 10 #include <sys/socket.h> |
| 11 #include <unistd.h> |
9 | 12 |
10 #include <openssl/bio.h> | 13 #include <openssl/bio.h> |
11 #include <openssl/ssl.h> | 14 #include <openssl/ssl.h> |
12 #include <openssl/err.h> | 15 #include <openssl/err.h> |
| 16 #include <openssl/srp.h> |
13 | 17 |
14 static const char kDefaultPEMFile[] = "net/data/ssl/certificates/ok_cert.pem"; | 18 static const char kDefaultPEMFile[] = "net/data/ssl/certificates/ok_cert.pem"; |
| 19 static const char kDefaultSRPVFile[] = "net/data/ssl/certificates/ok.srpv"; |
15 | 20 |
16 // Server Name Indication callback from OpenSSL | 21 // Server Name Indication callback from OpenSSL |
17 static int sni_cb(SSL *s, int *ad, void *arg) { | 22 static int sni_cb(SSL *s, int *ad, void *arg) { |
18 const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); | 23 const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); |
19 if (servername && strcmp(servername, "test.example.com") == 0) | 24 if (servername && strcmp(servername, "test.example.com") == 0) |
20 *reinterpret_cast<bool*>(arg) = true; | 25 *reinterpret_cast<bool*>(arg) = true; |
21 | 26 |
22 return SSL_TLSEXT_ERR_OK; | 27 return SSL_TLSEXT_ERR_OK; |
23 } | 28 } |
24 | 29 |
(...skipping 14 matching lines...) Expand all Loading... |
39 *out = (const unsigned char*) kProtos; | 44 *out = (const unsigned char*) kProtos; |
40 *outlen = sizeof(kProtos) - 1; | 45 *outlen = sizeof(kProtos) - 1; |
41 } else { | 46 } else { |
42 *out = (const unsigned char*) kProtos2; | 47 *out = (const unsigned char*) kProtos2; |
43 *outlen = sizeof(kProtos2) - 1; | 48 *outlen = sizeof(kProtos2) - 1; |
44 } | 49 } |
45 count++; | 50 count++; |
46 return SSL_TLSEXT_ERR_OK; | 51 return SSL_TLSEXT_ERR_OK; |
47 } | 52 } |
48 | 53 |
| 54 // This is a context that we pass to callbacks |
| 55 // (from openssl/apps/s_server.c) |
| 56 typedef struct srpsrvparm_st { |
| 57 int verbose; |
| 58 char *login; |
| 59 SRP_VBASE *vb; |
| 60 } srpsrvparm; |
| 61 |
| 62 // (from openssl/apps/s_server.c) |
| 63 static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) { |
| 64 srpsrvparm * p = (srpsrvparm *) arg; |
| 65 SRP_user_pwd *user; |
| 66 int rv; |
| 67 |
| 68 p->login = BUF_strdup(SSL_get_srp_username(s)); |
| 69 fprintf(stderr,"SRP username = \"%s\"\n",p->login); |
| 70 |
| 71 user = SRP_VBASE_get_by_user(p->vb, p->login); |
| 72 if (user == NULL) { |
| 73 fprintf(stderr, "User %s doesn't exist\n", p->login); |
| 74 return SSL3_AL_FATAL; |
| 75 } |
| 76 |
| 77 /* TODO(sqs): see why it expects non-const BIGNUM* */ |
| 78 rv = SSL_set_srp_server_param(s, (BIGNUM*)user->N, (BIGNUM*)user->g, |
| 79 user->s, user->v, user->info); |
| 80 if (rv < 0) { |
| 81 *ad = SSL_AD_INTERNAL_ERROR; |
| 82 return SSL3_AL_FATAL; |
| 83 } |
| 84 return SSL_ERROR_NONE; |
| 85 } |
| 86 |
49 int | 87 int |
50 main(int argc, char **argv) { | 88 main(int argc, char **argv) { |
51 SSL_library_init(); | 89 SSL_library_init(); |
52 ERR_load_crypto_strings(); | 90 ERR_load_crypto_strings(); |
53 OpenSSL_add_all_algorithms(); | 91 OpenSSL_add_all_algorithms(); |
54 SSL_load_error_strings(); | 92 SSL_load_error_strings(); |
55 | 93 |
56 bool sni = false, sni_good = false, snap_start = false; | 94 bool sni = false, sni_good = false, snap_start = false; |
57 bool snap_start_recovery = false, sslv3 = false, session_tickets = false; | 95 bool snap_start_recovery = false, sslv3 = false, session_tickets = false; |
58 bool fail_resume = false, client_cert = false, npn = false; | 96 bool fail_resume = false, client_cert = false, npn = false; |
59 bool npn_mispredict = false; | 97 bool npn_mispredict = false, tlssrp = false, open_socket = false; |
| 98 |
| 99 unsigned short listen_port = 4443; |
60 | 100 |
61 const char* key_file = kDefaultPEMFile; | 101 const char* key_file = kDefaultPEMFile; |
62 const char* cert_file = kDefaultPEMFile; | 102 const char* cert_file = kDefaultPEMFile; |
| 103 const char* srpv_file = kDefaultSRPVFile; |
| 104 |
| 105 srpsrvparm srpp; |
63 | 106 |
64 for (int i = 1; i < argc; i++) { | 107 for (int i = 1; i < argc; i++) { |
65 if (strcmp(argv[i], "sni") == 0) { | 108 if (strcmp(argv[i], "sni") == 0) { |
66 // Require SNI | 109 // Require SNI |
67 sni = true; | 110 sni = true; |
68 } else if (strcmp(argv[i], "snap-start") == 0) { | 111 } else if (strcmp(argv[i], "snap-start") == 0) { |
69 // Support Snap Start | 112 // Support Snap Start |
70 snap_start = true; | 113 snap_start = true; |
71 } else if (strcmp(argv[i], "snap-start-recovery") == 0) { | 114 } else if (strcmp(argv[i], "snap-start-recovery") == 0) { |
72 // Support Snap Start, but always trigger a recovery | 115 // Support Snap Start, but always trigger a recovery |
73 snap_start = true; | 116 snap_start = true; |
74 snap_start_recovery = true; | 117 snap_start_recovery = true; |
75 } else if (strcmp(argv[i], "sslv3") == 0) { | 118 } else if (strcmp(argv[i], "sslv3") == 0) { |
76 // Use SSLv3 | 119 // Use SSLv3 |
77 sslv3 = true; | 120 sslv3 = true; |
| 121 if (tlssrp) { |
| 122 fprintf(stderr, "TLS-SRP requires TLSv1; do not use sslv3 option\n"); |
| 123 return 1; |
| 124 } |
78 } else if (strcmp(argv[i], "session-tickets") == 0) { | 125 } else if (strcmp(argv[i], "session-tickets") == 0) { |
79 // Enable Session Tickets | 126 // Enable Session Tickets |
80 session_tickets = true; | 127 session_tickets = true; |
81 } else if (strcmp(argv[i], "fail-resume") == 0) { | 128 } else if (strcmp(argv[i], "fail-resume") == 0) { |
82 // Always fail to resume sessions | 129 // Always fail to resume sessions |
83 fail_resume = true; | 130 fail_resume = true; |
84 } else if (strcmp(argv[i], "client-cert") == 0) { | 131 } else if (strcmp(argv[i], "client-cert") == 0) { |
85 // Request a client certificate | 132 // Request a client certificate |
86 client_cert = true; | 133 client_cert = true; |
87 } else if (strcmp(argv[i], "npn") == 0) { | 134 } else if (strcmp(argv[i], "npn") == 0) { |
88 // Advertise NPN | 135 // Advertise NPN |
89 npn = true; | 136 npn = true; |
90 } else if (strcmp(argv[i], "npn-mispredict") == 0) { | 137 } else if (strcmp(argv[i], "npn-mispredict") == 0) { |
91 // Advertise NPN | 138 // Advertise NPN |
92 npn = true; | 139 npn = true; |
93 npn_mispredict = true; | 140 npn_mispredict = true; |
| 141 } else if (strcmp(argv[i], "open-socket") == 0) { |
| 142 open_socket = true; |
| 143 } else if (strcmp(argv[i], "tls-srp") == 0) { |
| 144 tlssrp = true; |
| 145 if (sslv3) { |
| 146 fprintf(stderr, "TLS-SRP requires TLSv1; do not use sslv3 option\n"); |
| 147 return 1; |
| 148 } |
94 } else if (strcmp(argv[i], "--key-file") == 0) { | 149 } else if (strcmp(argv[i], "--key-file") == 0) { |
95 // Use alternative key file | 150 // Use alternative key file |
96 i++; | 151 i++; |
97 if (i == argc) { | 152 if (i == argc) { |
98 fprintf(stderr, "Missing argument to --key-file\n"); | 153 fprintf(stderr, "Missing argument to --key-file\n"); |
99 return 1; | 154 return 1; |
100 } | 155 } |
101 key_file = argv[i]; | 156 key_file = argv[i]; |
102 } else if (strcmp(argv[i], "--cert-file") == 0) { | 157 } else if (strcmp(argv[i], "--cert-file") == 0) { |
103 // Use alternative certificate file | 158 // Use alternative certificate file |
104 i++; | 159 i++; |
105 if (i == argc) { | 160 if (i == argc) { |
106 fprintf(stderr, "Missing argument to --cert-file\n"); | 161 fprintf(stderr, "Missing argument to --cert-file\n"); |
107 return 1; | 162 return 1; |
108 } | 163 } |
109 cert_file = argv[i]; | 164 cert_file = argv[i]; |
| 165 } else if (strcmp(argv[i], "--srpv-file") == 0) { |
| 166 i++; |
| 167 if (i == argc) { |
| 168 fprintf(stderr, "Missing argument to --srpv-file\n"); |
| 169 return 1; |
| 170 } |
| 171 srpv_file = argv[i]; |
| 172 } else if (strcmp(argv[i], "--port") == 0) { |
| 173 i++; |
| 174 if (i == argc) { |
| 175 fprintf(stderr, "Missing argument to --port\n"); |
| 176 return 1; |
| 177 } |
| 178 listen_port = (unsigned short)atoi(argv[i]); |
110 } else { | 179 } else { |
111 fprintf(stderr, "Unknown argument: %s\n", argv[i]); | 180 fprintf(stderr, "Unknown argument: %s\n", argv[i]); |
112 return 1; | 181 return 1; |
113 } | 182 } |
114 } | 183 } |
115 | 184 |
116 SSL_CTX* ctx; | 185 SSL_CTX* ctx; |
117 | 186 |
118 if (sslv3) { | 187 if (sslv3) { |
119 ctx = SSL_CTX_new(SSLv3_server_method()); | 188 ctx = SSL_CTX_new(SSLv3_server_method()); |
120 } else { | 189 } else { |
121 ctx = SSL_CTX_new(TLSv1_server_method()); | 190 ctx = SSL_CTX_new(TLSv1_server_method()); |
122 } | 191 } |
123 | 192 |
124 if (sni) { | 193 if (sni) { |
125 SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb); | 194 SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb); |
126 SSL_CTX_set_tlsext_servername_arg(ctx, &sni_good); | 195 SSL_CTX_set_tlsext_servername_arg(ctx, &sni_good); |
127 } | 196 } |
128 | 197 |
129 BIO* key = BIO_new(BIO_s_file()); | 198 if (!tlssrp) { |
130 if (BIO_read_filename(key, key_file) <= 0) { | 199 BIO* key = BIO_new(BIO_s_file()); |
131 fprintf(stderr, "Failed to read %s\n", key_file); | 200 if (BIO_read_filename(key, key_file) <= 0) { |
132 return 1; | 201 fprintf(stderr, "Failed to read %s\n", key_file); |
133 } | 202 return 1; |
| 203 } |
134 | 204 |
135 EVP_PKEY *pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); | 205 EVP_PKEY *pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); |
136 if (!pkey) { | 206 if (!pkey) { |
137 fprintf(stderr, "Failed to parse %s\n", key_file); | 207 fprintf(stderr, "Failed to parse %s\n", key_file); |
138 return 1; | 208 return 1; |
139 } | 209 } |
140 BIO_free(key); | 210 BIO_free(key); |
141 | 211 |
142 | 212 |
143 BIO* cert = BIO_new(BIO_s_file()); | 213 BIO* cert = BIO_new(BIO_s_file()); |
144 if (BIO_read_filename(cert, cert_file) <= 0) { | 214 if (BIO_read_filename(cert, cert_file) <= 0) { |
145 fprintf(stderr, "Failed to read %s\n", cert_file); | 215 fprintf(stderr, "Failed to read %s\n", cert_file); |
146 return 1; | 216 return 1; |
| 217 } |
| 218 |
| 219 X509 *pcert = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); |
| 220 if (!pcert) { |
| 221 fprintf(stderr, "Failed to parse %s\n", cert_file); |
| 222 return 1; |
| 223 } |
| 224 BIO_free(cert); |
| 225 |
| 226 if (SSL_CTX_use_certificate(ctx, pcert) <= 0) { |
| 227 fprintf(stderr, "Failed to load %s\n", cert_file); |
| 228 return 1; |
| 229 } |
| 230 |
| 231 if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) { |
| 232 fprintf(stderr, "Failed to load %s\n", key_file); |
| 233 return 1; |
| 234 } |
| 235 |
| 236 if (!SSL_CTX_check_private_key(ctx)) { |
| 237 fprintf(stderr, "Public and private keys don't match\n"); |
| 238 return 1; |
| 239 } |
| 240 |
| 241 if (client_cert) |
| 242 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); |
147 } | 243 } |
148 | 244 |
149 X509 *pcert = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); | |
150 if (!pcert) { | |
151 fprintf(stderr, "Failed to parse %s\n", cert_file); | |
152 return 1; | |
153 } | |
154 BIO_free(cert); | |
155 | |
156 if (SSL_CTX_use_certificate(ctx, pcert) <= 0) { | |
157 fprintf(stderr, "Failed to load %s\n", cert_file); | |
158 return 1; | |
159 } | |
160 | |
161 if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) { | |
162 fprintf(stderr, "Failed to load %s\n", key_file); | |
163 return 1; | |
164 } | |
165 | |
166 if (!SSL_CTX_check_private_key(ctx)) { | |
167 fprintf(stderr, "Public and private keys don't match\n"); | |
168 return 1; | |
169 } | |
170 | |
171 if (client_cert) | |
172 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); | |
173 | |
174 if (session_tickets) | 245 if (session_tickets) |
175 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); | 246 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH); |
176 | 247 |
177 if (snap_start) { | 248 if (snap_start) { |
178 static const unsigned char orbit[8] = {1, 2, 3, 4, 5, 6, 7, 8}; | 249 static const unsigned char orbit[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
179 SSL_CTX_set_snap_start_orbit(ctx, orbit); | 250 SSL_CTX_set_snap_start_orbit(ctx, orbit); |
180 } | 251 } |
181 | 252 |
182 if (npn) | 253 if (npn) |
183 SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &npn_mispredict); | 254 SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &npn_mispredict); |
184 | 255 |
| 256 if (tlssrp) { |
| 257 srpp.vb = SRP_VBASE_new(NULL); |
| 258 if (SRP_VBASE_init(srpp.vb, (char *)srpv_file) != SRP_NO_ERROR) { |
| 259 fprintf(stderr, "Failed to load SRP verifier file %s\n", srpv_file); |
| 260 return 1; |
| 261 } |
| 262 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb); |
| 263 SSL_CTX_set_srp_cb_arg(ctx, &srpp); |
| 264 SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); |
| 265 fprintf(stderr, "Using SRP verifier file %s\n", srpv_file); |
| 266 } |
| 267 |
185 unsigned connection_limit = 1; | 268 unsigned connection_limit = 1; |
186 if (snap_start || session_tickets) | 269 if (snap_start || session_tickets) |
187 connection_limit = 2; | 270 connection_limit = 2; |
188 if (npn_mispredict) | 271 if (npn_mispredict) |
189 connection_limit = 3; | 272 connection_limit = 3; |
190 | 273 |
191 for (unsigned connections = 0; connections < connection_limit; | 274 for (unsigned connections = 0; connections < connection_limit; |
192 connections++) { | 275 connections++) { |
193 const int fd = accept(3, NULL, NULL); | 276 int listener = 3; /* default to using parent process' fd 3 */ |
| 277 |
| 278 if (open_socket) { |
| 279 listener = socket(AF_INET, SOCK_STREAM, 0); |
| 280 if (listener < 0) { |
| 281 fprintf(stderr, "Failed to open socket\n"); |
| 282 return 1; |
| 283 } |
| 284 |
| 285 struct sockaddr_in sin; |
| 286 memset(&sin, 0, sizeof(sin)); |
| 287 sin.sin_family = AF_INET; |
| 288 sin.sin_port = htons((unsigned short)listen_port); |
| 289 if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) != 0) { |
| 290 fprintf(stderr, "Failed to bind socket\n"); |
| 291 return 1; |
| 292 } |
| 293 |
| 294 if (listen(listener, 1) != 0) { |
| 295 fprintf(stderr, "Failed to listen on socket\n"); |
| 296 return 1; |
| 297 } |
| 298 |
| 299 fprintf(stderr, "Listening on localhost:%d\n", listen_port); |
| 300 } |
| 301 |
| 302 const int fd = accept(listener, NULL, NULL); |
194 | 303 |
195 SSL* server = SSL_new(ctx); | 304 SSL* server = SSL_new(ctx); |
196 BIO* bio = BIO_new_socket(fd, 1 /* take ownership of fd */); | 305 BIO* bio = BIO_new_socket(fd, 1 /* take ownership of fd */); |
197 SSL_set_bio(server, bio, bio); | 306 SSL_set_bio(server, bio, bio); |
198 | 307 |
199 if (fail_resume) { | 308 if (fail_resume) { |
200 SSL_set_session_id_context(server, (unsigned char*) &connections, | 309 SSL_set_session_id_context(server, (unsigned char*) &connections, |
201 sizeof(connections)); | 310 sizeof(connections)); |
202 } | 311 } |
203 | 312 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 unsigned char buffer[6]; | 354 unsigned char buffer[6]; |
246 | 355 |
247 int ret = SSL_read(server, buffer, sizeof(buffer)); | 356 int ret = SSL_read(server, buffer, sizeof(buffer)); |
248 if (ret == -1) { | 357 if (ret == -1) { |
249 err = SSL_get_error(server, ret); | 358 err = SSL_get_error(server, ret); |
250 ERR_print_errors_fp(stderr); | 359 ERR_print_errors_fp(stderr); |
251 fprintf(stderr, "SSL_read failed: %d\n", err); | 360 fprintf(stderr, "SSL_read failed: %d\n", err); |
252 } | 361 } |
253 if (memcmp(buffer, "hello!", sizeof(buffer)) == 0) { | 362 if (memcmp(buffer, "hello!", sizeof(buffer)) == 0) { |
254 SSL_write(server, "goodbye!", 8); | 363 SSL_write(server, "goodbye!", 8); |
| 364 } else if (memcmp(buffer, "whoami", sizeof(buffer)) == 0) { |
| 365 char *username = SSL_get_srp_username(server); |
| 366 if (username) { |
| 367 SSL_write(server, username, strlen(username)); |
| 368 } else { |
| 369 SSL_write(server, "not-using-tls-srp", 17); |
| 370 } |
255 } | 371 } |
256 | 372 |
257 SSL_shutdown(server); | 373 SSL_shutdown(server); |
258 SSL_shutdown(server); | 374 SSL_shutdown(server); |
| 375 close(fd); |
259 } | 376 } |
260 | 377 |
261 SSL_CTX_free(ctx); | 378 SSL_CTX_free(ctx); |
262 | 379 |
263 return 0; | 380 return 0; |
264 } | 381 } |
OLD | NEW |