libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

tlsauthentication.c (4815B)


      1 /* Feel free to use this example code in any way
      2    you see fit (Public Domain) */
      3 
      4 #include <sys/types.h>
      5 #ifndef _WIN32
      6 #include <sys/select.h>
      7 #include <sys/socket.h>
      8 #else
      9 #include <winsock2.h>
     10 #endif
     11 #include <microhttpd.h>
     12 #include <string.h>
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 
     16 #define PORT 8888
     17 
     18 #define REALM     "Maintenance"
     19 #define USER      "a legitimate user"
     20 #define PASSWORD  "and his password"
     21 
     22 #define SERVERKEYFILE "server.key"
     23 #define SERVERCERTFILE "server.pem"
     24 
     25 
     26 static size_t
     27 get_file_size (const char *filename)
     28 {
     29   FILE *fp;
     30 
     31   fp = fopen (filename, "rb");
     32   if (fp)
     33   {
     34     long size;
     35 
     36     if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp))))
     37       size = 0;
     38 
     39     fclose (fp);
     40 
     41     return (size_t) size;
     42   }
     43   else
     44     return 0;
     45 }
     46 
     47 
     48 static char *
     49 load_file (const char *filename)
     50 {
     51   FILE *fp;
     52   char *buffer;
     53   size_t size;
     54 
     55   size = get_file_size (filename);
     56   if (0 == size)
     57     return NULL;
     58 
     59   fp = fopen (filename, "rb");
     60   if (! fp)
     61     return NULL;
     62 
     63   buffer = malloc (size + 1);
     64   if (! buffer)
     65   {
     66     fclose (fp);
     67     return NULL;
     68   }
     69   buffer[size] = '\0';
     70 
     71   if (size != fread (buffer, 1, size, fp))
     72   {
     73     free (buffer);
     74     buffer = NULL;
     75   }
     76 
     77   fclose (fp);
     78   return buffer;
     79 }
     80 
     81 
     82 static enum MHD_Result
     83 ask_for_authentication (struct MHD_Connection *connection, const char *realm)
     84 {
     85   enum MHD_Result ret;
     86   struct MHD_Response *response;
     87 
     88   response = MHD_create_response_empty (MHD_RF_NONE);
     89   if (! response)
     90     return MHD_NO;
     91 
     92   ret = MHD_queue_basic_auth_required_response3 (connection,
     93                                                  realm,
     94                                                  MHD_YES,
     95                                                  response);
     96   MHD_destroy_response (response);
     97   return ret;
     98 }
     99 
    100 
    101 static int
    102 is_authenticated (struct MHD_Connection *connection,
    103                   const char *username,
    104                   const char *password)
    105 {
    106   struct MHD_BasicAuthInfo *auth_info;
    107   int authenticated;
    108 
    109   auth_info = MHD_basic_auth_get_username_password3 (connection);
    110   if (NULL == auth_info)
    111     return 0;
    112   authenticated =
    113     ( (strlen (username) == auth_info->username_len) &&
    114       (0 == memcmp (auth_info->username, username, auth_info->username_len)) &&
    115       /* The next check against NULL is optional,
    116        * if 'password' is NULL then 'password_len' is always zero. */
    117       (NULL != auth_info->password) &&
    118       (strlen (password) == auth_info->password_len) &&
    119       (0 == memcmp (auth_info->password, password, auth_info->password_len)) );
    120 
    121   MHD_free (auth_info);
    122 
    123   return authenticated;
    124 }
    125 
    126 
    127 static enum MHD_Result
    128 secret_page (struct MHD_Connection *connection)
    129 {
    130   enum MHD_Result ret;
    131   struct MHD_Response *response;
    132   const char *page = "<html><body>A secret.</body></html>";
    133 
    134   response = MHD_create_response_from_buffer_static (strlen (page), page);
    135   if (! response)
    136     return MHD_NO;
    137 
    138   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
    139   MHD_destroy_response (response);
    140 
    141   return ret;
    142 }
    143 
    144 
    145 static enum MHD_Result
    146 answer_to_connection (void *cls, struct MHD_Connection *connection,
    147                       const char *url, const char *method,
    148                       const char *version, const char *upload_data,
    149                       size_t *upload_data_size, void **req_cls)
    150 {
    151   (void) cls;               /* Unused. Silent compiler warning. */
    152   (void) url;               /* Unused. Silent compiler warning. */
    153   (void) version;           /* Unused. Silent compiler warning. */
    154   (void) upload_data;       /* Unused. Silent compiler warning. */
    155   (void) upload_data_size;  /* Unused. Silent compiler warning. */
    156 
    157   if (0 != strcmp (method, "GET"))
    158     return MHD_NO;
    159   if (NULL == *req_cls)
    160   {
    161     *req_cls = connection;
    162     return MHD_YES;
    163   }
    164 
    165   if (! is_authenticated (connection, USER, PASSWORD))
    166     return ask_for_authentication (connection, REALM);
    167 
    168   return secret_page (connection);
    169 }
    170 
    171 
    172 int
    173 main (void)
    174 {
    175   struct MHD_Daemon *daemon;
    176   char *key_pem;
    177   char *cert_pem;
    178 
    179   key_pem = load_file (SERVERKEYFILE);
    180   cert_pem = load_file (SERVERCERTFILE);
    181 
    182   if ((key_pem == NULL) || (cert_pem == NULL))
    183   {
    184     printf ("The key/certificate files could not be read.\n");
    185     if (NULL != key_pem)
    186       free (key_pem);
    187     if (NULL != cert_pem)
    188       free (cert_pem);
    189     return 1;
    190   }
    191 
    192   daemon =
    193     MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS, PORT, NULL,
    194                       NULL, &answer_to_connection, NULL,
    195                       MHD_OPTION_HTTPS_MEM_KEY, key_pem,
    196                       MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END);
    197   if (NULL == daemon)
    198   {
    199     printf ("%s\n", cert_pem);
    200 
    201     free (key_pem);
    202     free (cert_pem);
    203 
    204     return 1;
    205   }
    206 
    207   (void) getchar ();
    208 
    209   MHD_stop_daemon (daemon);
    210   free (key_pem);
    211   free (cert_pem);
    212 
    213   return 0;
    214 }