15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This helper binary is only used for testing Chrome's SSL stack.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/bio.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/ssl.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/err.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kDefaultPEMFile[] = "net/data/ssl/certificates/ok_cert.pem";
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Server Name Indication callback from OpenSSL
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int sni_cb(SSL *s, int *ad, void *arg) {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (servername && strcmp(servername, "test.example.com") == 0)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *reinterpret_cast<bool*>(arg) = true;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SSL_TLSEXT_ERR_OK;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Client certificate verification callback from OpenSSL
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Next Protocol Negotiation callback from OpenSSL
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int next_proto_cb(SSL *ssl, const unsigned char **out,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         unsigned int *outlen, void *arg) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool* npn_mispredict = reinterpret_cast<bool*>(arg);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static char kProtos[] = "\003foo\003bar";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static char kProtos2[] = "\003baz\003boo";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static unsigned count = 0;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!*npn_mispredict || count == 0) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = (const unsigned char*) kProtos;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outlen = sizeof(kProtos) - 1;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = (const unsigned char*) kProtos2;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outlen = sizeof(kProtos2) - 1;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  count++;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SSL_TLSEXT_ERR_OK;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)main(int argc, char **argv) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_library_init();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ERR_load_crypto_strings();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenSSL_add_all_algorithms();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_load_error_strings();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sni = false, sni_good = false, snap_start = false;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool snap_start_recovery = false, sslv3 = false, session_tickets = false;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool fail_resume = false, client_cert = false, npn = false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool npn_mispredict = false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* key_file = kDefaultPEMFile;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* cert_file = kDefaultPEMFile;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < argc; i++) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (strcmp(argv[i], "sni") == 0) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Require SNI
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sni = true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "snap-start") == 0) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Support Snap Start
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap_start = true;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "snap-start-recovery") == 0) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Support Snap Start, but always trigger a recovery
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap_start = true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      snap_start_recovery = true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "sslv3") == 0) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use SSLv3
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sslv3 = true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "session-tickets") == 0) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Enable Session Tickets
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_tickets = true;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "fail-resume") == 0) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Always fail to resume sessions
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_resume = true;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "client-cert") == 0) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Request a client certificate
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_cert = true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "npn") == 0) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Advertise NPN
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      npn = true;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "npn-mispredict") == 0) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Advertise NPN
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      npn = true;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      npn_mispredict = true;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "--key-file") == 0) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use alternative key file
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == argc) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr, "Missing argument to --key-file\n");
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 1;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_file = argv[i];
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (strcmp(argv[i], "--cert-file") == 0) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use alternative certificate file
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == argc) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr, "Missing argument to --cert-file\n");
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 1;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_file = argv[i];
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(stderr, "Unknown argument: %s\n", argv[i]);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX* ctx;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sslv3) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx = SSL_CTX_new(SSLv3_server_method());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ctx = SSL_CTX_new(TLSv1_server_method());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sni) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_tlsext_servername_arg(ctx, &sni_good);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BIO* key = BIO_new(BIO_s_file());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BIO_read_filename(key, key_file) <= 0) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Failed to read %s\n", key_file);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EVP_PKEY *pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pkey) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Failed to parse %s\n", key_file);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BIO_free(key);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BIO* cert = BIO_new(BIO_s_file());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (BIO_read_filename(cert, cert_file) <= 0) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Failed to read %s\n", cert_file);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  X509 *pcert = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pcert) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Failed to parse %s\n", cert_file);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BIO_free(cert);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SSL_CTX_use_certificate(ctx, pcert) <= 0) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Failed to load %s\n", cert_file);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Failed to load %s\n", key_file);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SSL_CTX_check_private_key(ctx)) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "Public and private keys don't match\n");
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client_cert)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session_tickets)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (snap_start) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const unsigned char orbit[8] = {1, 2, 3, 4, 5, 6, 7, 8};
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_snap_start_orbit(ctx, orbit);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (npn)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &npn_mispredict);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned connection_limit = 1;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (snap_start || session_tickets)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_limit = 2;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (npn_mispredict)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_limit = 3;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned connections = 0; connections < connection_limit;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       connections++) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int fd = accept(3, NULL, NULL);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL* server = SSL_new(ctx);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BIO* bio = BIO_new_socket(fd, 1 /* take ownership of fd */);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_set_bio(server, bio, bio);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fail_resume) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSL_set_session_id_context(server, (unsigned char*) &connections,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 sizeof(connections));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int err;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (;;) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int ret = SSL_accept(server);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ret == 1)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      err = SSL_get_error(server, ret);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (err == SSL_ERROR_WANT_READ)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (err == SSL_ERROR_SERVER_RANDOM_VALIDATION_PENDING && snap_start) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_set_suggested_server_random_validity(
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            server, !snap_start_recovery);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ERR_print_errors_fp(stderr);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(stderr, "SSL_accept failed: %d\n", err);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sni && !sni_good) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(stderr, "SNI failed\n");
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (npn) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const unsigned char *data, *expected_data;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned len, expected_len;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSL_get0_next_proto_negotiated(server, &data, &len);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!npn_mispredict || connections == 0) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_data = (unsigned char*) "foo";
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_len = 3;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_data = (unsigned char*) "baz";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        expected_len = 3;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (len != expected_len || memcmp(data, expected_data, len) != 0) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fprintf(stderr, "Bad NPN: %d\n", len);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 1;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char buffer[6];
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = SSL_read(server, buffer, sizeof(buffer));
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == -1) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      err = SSL_get_error(server, ret);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ERR_print_errors_fp(stderr);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(stderr, "SSL_read failed: %d\n", err);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (memcmp(buffer, "hello!", sizeof(buffer)) == 0) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSL_write(server, "goodbye!", 8);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_shutdown(server);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_shutdown(server);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX_free(ctx);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265