Files
libmicrohttpd/src/examples/https_server_example.c
T

186 lines
6.3 KiB
C

/*
This file is part of libmicrohttpd
(C) 2007 Christian Grothoff
libmicrohttpd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2, or (at your
option) any later version.
libmicrohttpd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libmicrohttpd; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/**
* @file https_server_example.c
* @brief a simple https file server using TLS.
*
* This example assumes the existence of a private key file named "key.pem"
* and a server certificate file named "cert.pem". File path for these should be
* provided as command-line arguments. 'certtool' may be used to generate these if
* missing.
*
* Access server with your browser of choice or with curl :
*
* curl --insecure --tlsv1 --ciphers AES256-SHA <url>
*
* @author LV-426
*/
#include "config.h"
#include <microhttpd.h>
#include <sys/stat.h>
#include <stdlib.h>
#ifndef MINGW
#include <unistd.h>
#endif
#include <string.h>
#include <stdio.h>
#include "gnutls.h"
#include <gcrypt.h>
#define BUF_SIZE 1024
#define MAX_URL_LEN 255
// TODO remove if unused
#define CAFILE "ca.pem"
#define CRLFILE "crl.pem"
#define PAGE_NOT_FOUND "<html><head><title>File not found</title></head><body>File not found</body></html>"
/* Test Certificate */
const char cert_pem[] =
"-----BEGIN CERTIFICATE-----\n"
"MIICHjCCAYmgAwIBAgIERiYdNzALBgkqhkiG9w0BAQUwGTEXMBUGA1UEAxMOR251\n"
"VExTIHRlc3QgQ0EwHhcNMDcwNDE4MTMyOTI3WhcNMDgwNDE3MTMyOTI3WjAdMRsw\n"
"GQYDVQQDExJHbnVUTFMgdGVzdCBjbGllbnQwgZwwCwYJKoZIhvcNAQEBA4GMADCB\n"
"iAKBgLtmQ/Xyxde2jMzF3/WIO7HJS2oOoa0gUEAIgKFPXKPQ+GzP5jz37AR2ExeL\n"
"ZIkiW8DdU3w77XwEu4C5KL6Om8aOoKUSy/VXHqLnu7czSZ/ju0quak1o/8kR4jKN\n"
"zj2AC41179gAgY8oBAOgIo1hBAf6tjd9IQdJ0glhaZiQo1ipAgMBAAGjdjB0MAwG\n"
"A1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDwYDVR0PAQH/BAUDAweg\n"
"ADAdBgNVHQ4EFgQUTLkKm/odNON+3svSBxX+odrLaJEwHwYDVR0jBBgwFoAU6Twc\n"
"+62SbuYGpFYsouHAUyfI8pUwCwYJKoZIhvcNAQEFA4GBALujmBJVZnvaTXr9cFRJ\n"
"jpfc/3X7sLUsMvumcDE01ls/cG5mIatmiyEU9qI3jbgUf82z23ON/acwJf875D3/\n"
"U7jyOsBJ44SEQITbin2yUeJMIm1tievvdNXBDfW95AM507ShzP12sfiJkJfjjdhy\n"
"dc8Siq5JojruiMizAf0pA7in\n" "-----END CERTIFICATE-----\n";
const char key_pem[] =
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIICXAIBAAKBgQC7ZkP18sXXtozMxd/1iDuxyUtqDqGtIFBACIChT1yj0Phsz+Y8\n"
"9+wEdhMXi2SJIlvA3VN8O+18BLuAuSi+jpvGjqClEsv1Vx6i57u3M0mf47tKrmpN\n"
"aP/JEeIyjc49gAuNde/YAIGPKAQDoCKNYQQH+rY3fSEHSdIJYWmYkKNYqQIDAQAB\n"
"AoGADpmARG5CQxS+AesNkGmpauepiCz1JBF/JwnyiX6vEzUh0Ypd39SZztwrDxvF\n"
"PJjQaKVljml1zkJpIDVsqvHdyVdse8M+Qn6hw4x2p5rogdvhhIL1mdWo7jWeVJTF\n"
"RKB7zLdMPs3ySdtcIQaF9nUAQ2KJEvldkO3m/bRJFEp54k0CQQDYy+RlTmwRD6hy\n"
"7UtMjR0H3CSZJeQ8svMCxHLmOluG9H1UKk55ZBYfRTsXniqUkJBZ5wuV1L+pR9EK\n"
"ca89a+1VAkEA3UmBelwEv2u9cAU1QjKjmwju1JgXbrjEohK+3B5y0ESEXPAwNQT9\n"
"TrDM1m9AyxYTWLxX93dI5QwNFJtmbtjeBQJARSCWXhsoaDRG8QZrCSjBxfzTCqZD\n"
"ZXtl807ymCipgJm60LiAt0JLr4LiucAsMZz6+j+quQbSakbFCACB8SLV1QJBAKZQ\n"
"YKf+EPNtnmta/rRKKvySsi3GQZZN+Dt3q0r094XgeTsAqrqujVNfPhTMeP4qEVBX\n"
"/iVX2cmMTSh3w3z8MaECQEp0XJWDVKOwcTW6Ajp9SowtmiZ3YDYo1LF9igb4iaLv\n"
"sWZGfbnU3ryjvkb6YuFjgtzbZDZHWQCo8/cOtOBmPdk=\n"
"-----END RSA PRIVATE KEY-----\n";
static int
file_reader (void *cls, size_t pos, char *buf, int max)
{
FILE *file = cls;
fseek (file, pos, SEEK_SET);
return fread (buf, 1, max, file);
}
/* HTTP access handler call back */
static int
http_ahc (void *cls,
struct MHD_Connection *connection,
const char *url,
const char *method,
const char *upload_data,
const char *version, unsigned int *upload_data_size, void **ptr)
{
static int aptr;
struct MHD_Response *response;
int ret;
FILE *file;
struct stat buf;
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
return MHD_NO; /* unexpected method */
if (&aptr != *ptr)
{
/* do never respond on first call */
*ptr = &aptr;
return MHD_YES;
}
*ptr = NULL; /* reset when done */
file = fopen (url, "r");
if (file == NULL)
{
response = MHD_create_response_from_data (strlen (PAGE_NOT_FOUND),
(void *) PAGE_NOT_FOUND,
MHD_NO, MHD_NO);
ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response (response);
}
else
{
stat (url, &buf);
response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
&file_reader, file,
(MHD_ContentReaderFreeCallback)
& fclose);
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
}
return ret;
}
int
main (int argc, char *const *argv)
{
struct MHD_Daemon *TLS_daemon;
/* look for HTTPS arguments */
if (argc < 5)
{
printf
("Usage : %s HTTP-PORT SECONDS-TO-RUN HTTPS-PORT KEY-FILE CERT-FILE\n",
argv[0]);
return 1;
}
// TODO check if this is truly necessary - disallow usage of the blocking /dev/random */
// gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
TLS_daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG
| MHD_USE_SSL, atoi (argv[3]),
NULL,
NULL, &http_ahc,
NULL, MHD_OPTION_CONNECTION_TIMEOUT, 256,
MHD_OPTION_HTTPS_KEY_PATH, argv[4],
MHD_OPTION_HTTPS_CERT_PATH, argv[5],
MHD_OPTION_END);
if (TLS_daemon == NULL)
{
printf ("Error: failed to start TLS_daemon");
return 1;
}
sleep (atoi (argv[2]));
MHD_stop_daemon (TLS_daemon);
return 0;
}