Home | History | Annotate | Download | only in https
      1 /*
      2  This file is part of libmicrohttpd
      3  Copyright (C) 2007 Christian Grothoff
      4 
      5  libmicrohttpd is free software; you can redistribute it and/or modify
      6  it under the terms of the GNU General Public License as published
      7  by the Free Software Foundation; either version 2, or (at your
      8  option) any later version.
      9 
     10  libmicrohttpd is distributed in the hope that it will be useful, but
     11  WITHOUT ANY WARRANTY; without even the implied warranty of
     12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  General Public License for more details.
     14 
     15  You should have received a copy of the GNU General Public License
     16  along with libmicrohttpd; see the file COPYING.  If not, write to the
     17  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     18  Boston, MA 02111-1307, USA.
     19  */
     20 
     21 /**
     22  * @file mhds_session_info_test.c
     23  * @brief  Testcase for libmicrohttpd HTTPS connection querying operations
     24  * @author Sagie Amir
     25  */
     26 
     27 #include "platform.h"
     28 #include "microhttpd.h"
     29 #include <curl/curl.h>
     30 #include <gcrypt.h>
     31 #include "tls_test_common.h"
     32 
     33 extern int curl_check_version (const char *req_version, ...);
     34 extern const char srv_key_pem[];
     35 extern const char srv_self_signed_cert_pem[];
     36 
     37 struct MHD_Daemon *d;
     38 
     39 /*
     40  * HTTP access handler call back
     41  * used to query negotiated security parameters
     42  */
     43 static int
     44 query_session_ahc (void *cls, struct MHD_Connection *connection,
     45                    const char *url, const char *method,
     46                    const char *upload_data, const char *version,
     47                    size_t *upload_data_size, void **ptr)
     48 {
     49   struct MHD_Response *response;
     50   int ret;
     51 
     52   if (NULL == *ptr)
     53     {
     54       *ptr = &query_session_ahc;
     55       return MHD_YES;
     56     }
     57 
     58   if (GNUTLS_TLS1_1 !=
     59       (ret = MHD_get_connection_info
     60        (connection,
     61 	MHD_CONNECTION_INFO_PROTOCOL)->protocol))
     62     {
     63       if (GNUTLS_TLS1_2 == ret)
     64       {
     65         /* as usual, TLS implementations sometimes don't
     66            quite do what was asked, just mildly complain... */
     67         fprintf (stderr,
     68                  "Warning: requested TLS 1.1, got TLS 1.2\n");
     69       }
     70       else
     71       {
     72         /* really different version... */
     73         fprintf (stderr,
     74                  "Error: requested protocol mismatch (wanted %d, got %d)\n",
     75                  GNUTLS_TLS1_1,
     76                  ret);
     77         return -1;
     78       }
     79     }
     80 
     81   response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
     82 					      (void *) EMPTY_PAGE,
     83 					      MHD_RESPMEM_PERSISTENT);
     84   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     85   MHD_destroy_response (response);
     86   return ret;
     87 }
     88 
     89 
     90 /**
     91  * negotiate a secure connection with server & query negotiated security parameters
     92  */
     93 static int
     94 test_query_session ()
     95 {
     96   CURL *c;
     97   struct CBC cbc;
     98   CURLcode errornum;
     99   char url[256];
    100 
    101   if (NULL == (cbc.buf = malloc (sizeof (char) * 255)))
    102     return 16;
    103   cbc.size = 255;
    104   cbc.pos = 0;
    105 
    106   gen_test_file_url (url, DEAMON_TEST_PORT);
    107 
    108   /* setup test */
    109   d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL |
    110                         MHD_USE_DEBUG, DEAMON_TEST_PORT,
    111                         NULL, NULL, &query_session_ahc, NULL,
    112 			MHD_OPTION_HTTPS_PRIORITIES, "NORMAL:+ARCFOUR-128",
    113                         MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
    114                         MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
    115                         MHD_OPTION_END);
    116 
    117   if (d == NULL)
    118     return 2;
    119 
    120   const char *aes256_sha = "AES256-SHA";
    121   if (curl_uses_nss_ssl() == 0)
    122     {
    123       aes256_sha = "rsa_aes_256_sha";
    124     }
    125 
    126   c = curl_easy_init ();
    127 #if DEBUG_HTTPS_TEST
    128   curl_easy_setopt (c, CURLOPT_VERBOSE, 1);
    129 #endif
    130   curl_easy_setopt (c, CURLOPT_URL, url);
    131   curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    132   curl_easy_setopt (c, CURLOPT_TIMEOUT, 10L);
    133   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 10L);
    134   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    135   curl_easy_setopt (c, CURLOPT_FILE, &cbc);
    136   /* TLS options */
    137   curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
    138   curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha);
    139   /* currently skip any peer authentication */
    140   curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
    141   curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
    142   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
    143 
    144   // NOTE: use of CONNECTTIMEOUT without also
    145   //   setting NOSIGNAL results in really weird
    146   //   crashes on my system!
    147   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
    148   if (CURLE_OK != (errornum = curl_easy_perform (c)))
    149     {
    150       fprintf (stderr, "curl_easy_perform failed: `%s'\n",
    151                curl_easy_strerror (errornum));
    152 
    153       MHD_stop_daemon (d);
    154       curl_easy_cleanup (c);
    155       free (cbc.buf);
    156       return -1;
    157     }
    158 
    159   curl_easy_cleanup (c);
    160   MHD_stop_daemon (d);
    161   free (cbc.buf);
    162   return 0;
    163 }
    164 
    165 
    166 int
    167 main (int argc, char *const *argv)
    168 {
    169   unsigned int errorCount = 0;
    170 
    171   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
    172 #ifdef GCRYCTL_INITIALIZATION_FINISHED
    173   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    174 #endif
    175   if (0 != curl_global_init (CURL_GLOBAL_ALL))
    176     {
    177       fprintf (stderr, "Error (code: %u)\n", errorCount);
    178       return -1;
    179     }
    180   errorCount += test_query_session ();
    181   print_test_result (errorCount, argv[0]);
    182   curl_global_cleanup ();
    183   if (errorCount > 0)
    184     fprintf (stderr, "Error (code: %u)\n", errorCount);
    185   return errorCount;
    186 }
    187