Blame src/examples/https_fileserver_example.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007, 2008 Christian Grothoff (and other contributing authors)
Packit 875988
Packit 875988
     This library is free software; you can redistribute it and/or
Packit 875988
     modify it under the terms of the GNU Lesser General Public
Packit 875988
     License as published by the Free Software Foundation; either
Packit 875988
     version 2.1 of the License, or (at your option) any later version.
Packit 875988
Packit 875988
     This library is distributed in the hope that it will be useful,
Packit 875988
     but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     Lesser General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU Lesser General Public
Packit 875988
     License along with this library; if not, write to the Free Software
Packit 875988
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 875988
*/
Packit 875988
/**
Packit 875988
 * @file https_fileserver_example.c
Packit 875988
 * @brief a simple HTTPS file server using TLS.
Packit 875988
 *
Packit 875988
 * Usage :
Packit 875988
 *
Packit 875988
 *  'http_fileserver_example HTTP-PORT SECONDS-TO-RUN'
Packit 875988
 *
Packit 875988
 * The certificate & key are required by the server to operate,  Omitting the
Packit 875988
 * path arguments will cause the server to use the hard coded example certificate & key.
Packit 875988
 *
Packit 875988
 * 'certtool' may be used to generate these if required.
Packit 875988
 *
Packit 875988
 * @author Sagie Amir
Packit 875988
 */
Packit 875988
Packit 875988
#include "platform.h"
Packit 875988
#include <microhttpd.h>
Packit 875988
#include <sys/stat.h>
Packit 875988
Packit 875988
#define BUF_SIZE 1024
Packit 875988
#define MAX_URL_LEN 255
Packit 875988
Packit 875988
/* TODO remove if unused */
Packit 875988
#define CAFILE "ca.pem"
Packit 875988
#define CRLFILE "crl.pem"
Packit 875988
Packit 875988
#define EMPTY_PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
Packit 875988
Packit 875988
/* Test Certificate */
Packit 875988
const char cert_pem[] =
Packit 875988
  "-----BEGIN CERTIFICATE-----\n"
Packit 875988
  "MIICpjCCAZCgAwIBAgIESEPtjjALBgkqhkiG9w0BAQUwADAeFw0wODA2MDIxMjU0\n"
Packit 875988
  "MzhaFw0wOTA2MDIxMjU0NDZaMAAwggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKC\n"
Packit 875988
  "AQC03TyUvK5HmUAirRp067taIEO4bibh5nqolUoUdo/LeblMQV+qnrv/RNAMTx5X\n"
Packit 875988
  "fNLZ45/kbM9geF8qY0vsPyQvP4jumzK0LOJYuIwmHaUm9vbXnYieILiwCuTgjaud\n"
Packit 875988
  "3VkZDoQ9fteIo+6we9UTpVqZpxpbLulBMh/VsvX0cPJ1VFC7rT59o9hAUlFf9jX/\n"
Packit 875988
  "GmKdYI79MtgVx0OPBjmmSD6kicBBfmfgkO7bIGwlRtsIyMznxbHu6VuoX/eVxrTv\n"
Packit 875988
  "rmCwgEXLWRZ6ru8MQl5YfqeGXXRVwMeXU961KefbuvmEPccgCxm8FZ1C1cnDHFXh\n"
Packit 875988
  "siSgAzMBjC/b6KVhNQ4KnUdZAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0O\n"
Packit 875988
  "BBYEFJcUvpjvE5fF/yzUshkWDpdYiQh/MAsGCSqGSIb3DQEBBQOCAQEARP7eKSB2\n"
Packit 875988
  "RNd6XjEjK0SrxtoTnxS3nw9sfcS7/qD1+XHdObtDFqGNSjGYFB3Gpx8fpQhCXdoN\n"
Packit 875988
  "8QUs3/5ZVa5yjZMQewWBgz8kNbnbH40F2y81MHITxxCe1Y+qqHWwVaYLsiOTqj2/\n"
Packit 875988
  "0S3QjEJ9tvklmg7JX09HC4m5QRYfWBeQLD1u8ZjA1Sf1xJriomFVyRLI2VPO2bNe\n"
Packit 875988
  "JDMXWuP+8kMC7gEvUnJ7A92Y2yrhu3QI3bjPk8uSpHea19Q77tul1UVBJ5g+zpH3\n"
Packit 875988
  "OsF5p0MyaVf09GTzcLds5nE/osTdXGUyHJapWReVmPm3Zn6gqYlnzD99z+DPIgIV\n"
Packit 875988
  "RhZvQx74NQnS6g==\n" "-----END CERTIFICATE-----\n";
Packit 875988
Packit 875988
const char key_pem[] =
Packit 875988
  "-----BEGIN RSA PRIVATE KEY-----\n"
Packit 875988
  "MIIEowIBAAKCAQEAtN08lLyuR5lAIq0adOu7WiBDuG4m4eZ6qJVKFHaPy3m5TEFf\n"
Packit 875988
  "qp67/0TQDE8eV3zS2eOf5GzPYHhfKmNL7D8kLz+I7psytCziWLiMJh2lJvb2152I\n"
Packit 875988
  "niC4sArk4I2rnd1ZGQ6EPX7XiKPusHvVE6VamacaWy7pQTIf1bL19HDydVRQu60+\n"
Packit 875988
  "faPYQFJRX/Y1/xpinWCO/TLYFcdDjwY5pkg+pInAQX5n4JDu2yBsJUbbCMjM58Wx\n"
Packit 875988
  "7ulbqF/3lca0765gsIBFy1kWeq7vDEJeWH6nhl10VcDHl1PetSnn27r5hD3HIAsZ\n"
Packit 875988
  "vBWdQtXJwxxV4bIkoAMzAYwv2+ilYTUOCp1HWQIDAQABAoIBAArOQv3R7gmqDspj\n"
Packit 875988
  "lDaTFOz0C4e70QfjGMX0sWnakYnDGn6DU19iv3GnX1S072ejtgc9kcJ4e8VUO79R\n"
Packit 875988
  "EmqpdRR7k8dJr3RTUCyjzf/C+qiCzcmhCFYGN3KRHA6MeEnkvRuBogX4i5EG1k5l\n"
Packit 875988
  "/5t+YBTZBnqXKWlzQLKoUAiMLPg0eRWh+6q7H4N7kdWWBmTpako7TEqpIwuEnPGx\n"
Packit 875988
  "u3EPuTR+LN6lF55WBePbCHccUHUQaXuav18NuDkcJmCiMArK9SKb+h0RqLD6oMI/\n"
Packit 875988
  "dKD6n8cZXeMBkK+C8U/K0sN2hFHACsu30b9XfdnljgP9v+BP8GhnB0nCB6tNBCPo\n"
Packit 875988
  "32srOwECgYEAxWh3iBT4lWqL6bZavVbnhmvtif4nHv2t2/hOs/CAq8iLAw0oWGZc\n"
Packit 875988
  "+JEZTUDMvFRlulr0kcaWra+4fN3OmJnjeuFXZq52lfMgXBIKBmoSaZpIh2aDY1Rd\n"
Packit 875988
  "RbEse7nQl9hTEPmYspiXLGtnAXW7HuWqVfFFP3ya8rUS3t4d07Hig8ECgYEA6ou6\n"
Packit 875988
  "OHiBRTbtDqLIv8NghARc/AqwNWgEc9PelCPe5bdCOLBEyFjqKiT2MttnSSUc2Zob\n"
Packit 875988
  "XhYkHC6zN1Mlq30N0e3Q61YK9LxMdU1vsluXxNq2rfK1Scb1oOlOOtlbV3zA3VRF\n"
Packit 875988
  "hV3t1nOA9tFmUrwZi0CUMWJE/zbPAyhwWotKyZkCgYEAh0kFicPdbABdrCglXVae\n"
Packit 875988
  "SnfSjVwYkVuGd5Ze0WADvjYsVkYBHTvhgRNnRJMg+/vWz3Sf4Ps4rgUbqK8Vc20b\n"
Packit 875988
  "AU5G6H6tlCvPRGm0ZxrwTWDHTcuKRVs+pJE8C/qWoklE/AAhjluWVoGwUMbPGuiH\n"
Packit 875988
  "6Gf1bgHF6oj/Sq7rv/VLZ8ECgYBeq7ml05YyLuJutuwa4yzQ/MXfghzv4aVyb0F3\n"
Packit 875988
  "QCdXR6o2IYgR6jnSewrZKlA9aPqFJrwHNR6sNXlnSmt5Fcf/RWO/qgJQGLUv3+rG\n"
Packit 875988
  "7kuLTNDR05azSdiZc7J89ID3Bkb+z2YkV+6JUiPq/Ei1+nDBEXb/m+/HqALU/nyj\n"
Packit 875988
  "P3gXeQKBgBusb8Rbd+KgxSA0hwY6aoRTPRt8LNvXdsB9vRcKKHUFQvxUWiUSS+L9\n"
Packit 875988
  "/Qu1sJbrUquKOHqksV5wCnWnAKyJNJlhHuBToqQTgKXjuNmVdYSe631saiI7PHyC\n"
Packit 875988
  "eRJ6DxULPxABytJrYCRrNqmXi5TCiqR2mtfalEMOPxz8rUU8dYyx\n"
Packit 875988
  "-----END RSA PRIVATE KEY-----\n";
Packit 875988
Packit 875988
static ssize_t
Packit 875988
file_reader (void *cls, uint64_t pos, char *buf, size_t max)
Packit 875988
{
Packit 875988
  FILE *file = cls;
Packit 875988
Packit 875988
  (void) fseek (file, pos, SEEK_SET);
Packit 875988
  return fread (buf, 1, max, file);
Packit 875988
}
Packit 875988
Packit 875988
static void
Packit 875988
file_free_callback (void *cls)
Packit 875988
{
Packit 875988
  FILE *file = cls;
Packit 875988
  fclose (file);
Packit 875988
}
Packit 875988
Packit 875988
/* HTTP access handler call back */
Packit 875988
static int
Packit 875988
http_ahc (void *cls,
Packit 875988
          struct MHD_Connection *connection,
Packit 875988
          const char *url,
Packit 875988
          const char *method,
Packit 875988
          const char *version,
Packit 875988
          const char *upload_data,
Packit 875988
	  size_t *upload_data_size, void **ptr)
Packit 875988
{
Packit 875988
  static int aptr;
Packit 875988
  struct MHD_Response *response;
Packit 875988
  int ret;
Packit 875988
  FILE *file;
Packit 875988
  int fd;
Packit 875988
  struct stat buf;
Packit 875988
  (void)cls;               /* Unused. Silent compiler warning. */
Packit 875988
  (void)version;           /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data;       /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data_size;  /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
Packit 875988
    return MHD_NO;              /* unexpected method */
Packit 875988
  if (&aptr != *ptr)
Packit 875988
    {
Packit 875988
      /* do never respond on first call */
Packit 875988
      *ptr = &apt;;
Packit 875988
      return MHD_YES;
Packit 875988
    }
Packit 875988
  *ptr = NULL;                  /* reset when done */
Packit 875988
Packit 875988
  file = fopen (&url[1], "rb");
Packit 875988
  if (NULL != file)
Packit 875988
    {
Packit 875988
      fd = fileno (file);
Packit 875988
      if (-1 == fd)
Packit 875988
        {
Packit 875988
          (void) fclose (file);
Packit 875988
          return MHD_NO; /* internal error */
Packit 875988
        }
Packit 875988
      if ( (0 != fstat (fd, &buf)) ||
Packit 875988
           (! S_ISREG (buf.st_mode)) )
Packit 875988
        {
Packit 875988
          /* not a regular file, refuse to serve */
Packit 875988
          fclose (file);
Packit 875988
          file = NULL;
Packit 875988
        }
Packit 875988
    }
Packit 875988
Packit 875988
  if (NULL == file)
Packit 875988
    {
Packit 875988
      response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
Packit 875988
						  (void *) EMPTY_PAGE,
Packit 875988
						  MHD_RESPMEM_PERSISTENT);
Packit 875988
      ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
Packit 875988
      MHD_destroy_response (response);
Packit 875988
    }
Packit 875988
  else
Packit 875988
    {
Packit 875988
      response = MHD_create_response_from_callback (buf.st_size, 32 * 1024,     /* 32k PAGE_NOT_FOUND size */
Packit 875988
                                                    &file_reader, file,
Packit 875988
                                                    &file_free_callback);
Packit 875988
      if (NULL == response)
Packit 875988
	{
Packit 875988
	  fclose (file);
Packit 875988
	  return MHD_NO;
Packit 875988
	}
Packit 875988
      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
Packit 875988
      MHD_destroy_response (response);
Packit 875988
    }
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main (int argc, char *const *argv)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *TLS_daemon;
Packit 875988
  int port;
Packit 875988
Packit 875988
  if (argc != 2)
Packit 875988
    {
Packit 875988
      printf ("%s PORT\n", argv[0]);
Packit 875988
      return 1;
Packit 875988
    }
Packit 875988
  port = atoi (argv[1]);
Packit 875988
  if ( (1 > port) ||
Packit 875988
       (port > UINT16_MAX) )
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
               "Port must be a number between 1 and 65535\n");
Packit 875988
      return 1;
Packit 875988
    }
Packit 875988
Packit 875988
  TLS_daemon =
Packit 875988
    MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG |
Packit 875988
                      MHD_USE_TLS,
Packit 875988
                      (uint16_t) port,
Packit 875988
                      NULL, NULL,
Packit 875988
                      &http_ahc, NULL,
Packit 875988
                      MHD_OPTION_CONNECTION_TIMEOUT, 256,
Packit 875988
                      MHD_OPTION_HTTPS_MEM_KEY, key_pem,
Packit 875988
                      MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
Packit 875988
                      MHD_OPTION_END);
Packit 875988
  if (NULL == TLS_daemon)
Packit 875988
    {
Packit 875988
      fprintf (stderr, "Error: failed to start TLS_daemon\n");
Packit 875988
      return 1;
Packit 875988
    }
Packit 875988
  printf ("MHD daemon listening on port %u\n",
Packit 875988
          (unsigned int) port);
Packit 875988
Packit 875988
  (void) getc (stdin);
Packit 875988
Packit 875988
  MHD_stop_daemon (TLS_daemon);
Packit 875988
  return 0;
Packit 875988
}