1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/*
2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  This file is part of libmicrohttpd
3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  Copyright (C) 2013 Christian Grothoff
4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  libmicrohttpd is free software; you can redistribute it and/or modify
6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  it under the terms of the GNU General Public License as published
7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  by the Free Software Foundation; either version 3, or (at your
8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  option) any later version.
9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  libmicrohttpd is distributed in the hope that it will be useful, but
11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  WITHOUT ANY WARRANTY; without even the implied warranty of
12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  General Public License for more details.
14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  You should have received a copy of the GNU General Public License
16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  along with libmicrohttpd; see the file COPYING.  If not, write to the
17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  Boston, MA 02111-1307, USA.
19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/
20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file test_https_sni.c
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief  Testcase for libmicrohttpd HTTPS with SNI operations
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Christian Grothoff
25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "platform.h"
27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "microhttpd.h"
28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <limits.h>
29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <sys/stat.h>
30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <curl/curl.h>
31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <gcrypt.h>
32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "tls_test_common.h"
33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <gnutls/gnutls.h>
34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* This test only works with GnuTLS >= 3.0 */
36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if GNUTLS_VERSION_MAJOR >= 3
37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include <gnutls/abstract.h>
39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * A hostname, server key and certificate.
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct Hosts
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct Hosts *next;
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  const char *hostname;
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gnutls_pcert_st pcrt;
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gnutls_privkey_t key;
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat};
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Linked list of supported TLDs and respective certificates.
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic struct Hosts *hosts;
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* Load the certificate and the private key.
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * (This code is largely taken from GnuTLS).
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic void
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratload_keys(const char *hostname,
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *CERT_FILE,
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          const char *KEY_FILE)
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gnutls_datum_t data;
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct Hosts *host;
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  host = malloc (sizeof (struct Hosts));
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == host)
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    abort ();
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  host->hostname = hostname;
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  host->next = hosts;
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  hosts = host;
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = gnutls_load_file (CERT_FILE, &data);
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (ret < 0)
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "*** Error loading certificate file %s.\n",
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               CERT_FILE);
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      exit (1);
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret =
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    gnutls_pcert_import_x509_raw (&host->pcrt, &data, GNUTLS_X509_FMT_PEM,
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  0);
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (ret < 0)
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "*** Error loading certificate file: %s\n",
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               gnutls_strerror (ret));
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      exit (1);
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gnutls_free (data.data);
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret = gnutls_load_file (KEY_FILE, &data);
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (ret < 0)
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "*** Error loading key file %s.\n",
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               KEY_FILE);
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      exit (1);
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gnutls_privkey_init (&host->key);
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ret =
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    gnutls_privkey_import_x509_raw (host->key,
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                    &data, GNUTLS_X509_FMT_PEM,
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                    NULL, 0);
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (ret < 0)
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "*** Error loading key file: %s\n",
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               gnutls_strerror (ret));
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      exit (1);
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gnutls_free (data.data);
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param session the session we are giving a cert for
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param req_ca_dn NULL on server side
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param nreqs length of req_ca_dn, and thus 0 on server side
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pk_algos NULL on server side
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pk_algos_length 0 on server side
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pcert list of certificates (to be set)
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pcert_length length of pcert (to be set)
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pkey the private key (to be set)
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratsni_callback (gnutls_session_t session,
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              const gnutls_datum_t* req_ca_dn,
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              int nreqs,
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              const gnutls_pk_algorithm_t* pk_algos,
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              int pk_algos_length,
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              gnutls_pcert_st** pcert,
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              unsigned int *pcert_length,
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat              gnutls_privkey_t * pkey)
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char name[256];
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t name_len;
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct Hosts *host;
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int type;
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  name_len = sizeof (name);
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (GNUTLS_E_SUCCESS !=
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      gnutls_server_name_get (session,
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                              name,
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                              &name_len,
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                              &type,
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                              0 /* index */))
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return -1;
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  for (host = hosts; NULL != host; host = host->next)
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if (0 == strncmp (name, host->hostname, name_len))
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      break;
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == host)
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr,
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               "Need certificate for %.*s\n",
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               (int) name_len,
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               name);
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return -1;
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if 0
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr,
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat           "Returning certificate for %.*s\n",
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat           (int) name_len,
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat           name);
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  *pkey = host->key;
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  *pcert_length = 1;
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  *pcert = &host->pcrt;
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* perform a HTTP GET request via SSL/TLS */
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratdo_get (const char *url)
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURL *c;
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct CBC cbc;
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  CURLcode errornum;
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t len;
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct curl_slist *dns_info;
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  len = strlen (test_data);
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == (cbc.buf = malloc (sizeof (char) * len)))
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, MHD_E_MEM);
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return -1;
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.size = len;
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  cbc.pos = 0;
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  c = curl_easy_init ();
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if DEBUG_HTTPS_TEST
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_URL, url);
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L);
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L);
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FILE, &cbc);
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /* perform peer authentication */
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /* TODO merge into send_curl_req */
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 2);
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  dns_info = curl_slist_append (NULL, "host1:4233:127.0.0.1");
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  dns_info = curl_slist_append (dns_info, "host2:4233:127.0.0.1");
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_RESOLVE, dns_info);
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /* NOTE: use of CONNECTTIMEOUT without also
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     setting NOSIGNAL results in really weird
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     crashes on my system! */
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (CURLE_OK != (errornum = curl_easy_perform (c)))
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, "curl_easy_perform failed: `%s'\n",
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat               curl_easy_strerror (errornum));
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_easy_cleanup (c);
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (cbc.buf);
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      curl_slist_free_all (dns_info);
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return errornum;
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_easy_cleanup (c);
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_slist_free_all (dns_info);
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (memcmp (cbc.buf, test_data, len) != 0)
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, "Error: local file & received file differ.\n");
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      free (cbc.buf);
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return -1;
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  free (cbc.buf);
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratmain (int argc, char *const *argv)
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned int error_count = 0;
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *d;
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifdef GCRYCTL_INITIALIZATION_FINISHED
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (0 != curl_global_init (CURL_GLOBAL_ALL))
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, "Error: %s\n", strerror (errno));
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return -1;
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  load_keys ("host1", ABS_SRCDIR "/host1.crt", ABS_SRCDIR "/host1.key");
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  load_keys ("host2", ABS_SRCDIR "/host2.crt", ABS_SRCDIR "/host2.key");
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL | MHD_USE_DEBUG,
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        4233,
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        NULL, NULL,
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        &http_ahc, NULL,
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_HTTPS_CERT_CALLBACK, &sni_callback,
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                        MHD_OPTION_END);
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (d == NULL)
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      fprintf (stderr, MHD_E_SERVER_INIT);
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return -1;
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  error_count += do_get ("https://host1:4233/");
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  error_count += do_get ("https://host2:4233/");
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (d);
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  curl_global_cleanup ();
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return error_count != 0;
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#else
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint main ()
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fprintf (stderr,
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat           "SNI not supported by GnuTLS < 3.0\n");
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
292