https_fileserver_example.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. This file is part of libmicrohttpd
  3. Copyright (C) 2007, 2008 Christian Grothoff (and other contributing authors)
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  15. */
  16. /**
  17. * @file https_fileserver_example.c
  18. * @brief a simple HTTPS file server using TLS.
  19. *
  20. * Usage :
  21. *
  22. * 'http_fileserver_example HTTP-PORT SECONDS-TO-RUN'
  23. *
  24. * The certificate & key are required by the server to operate, omitting the
  25. * path arguments will cause the server to use the hard coded example certificate & key.
  26. *
  27. * 'certtool' may be used to generate these if required.
  28. *
  29. * @author Sagie Amir
  30. */
  31. #include "platform.h"
  32. #include <microhttpd.h>
  33. #include <sys/stat.h>
  34. #define BUF_SIZE 1024
  35. #define MAX_URL_LEN 255
  36. /* TODO remove if unused */
  37. #define CAFILE "ca.pem"
  38. #define CRLFILE "crl.pem"
  39. #define EMPTY_PAGE \
  40. "<html><head><title>File not found</title></head><body>File not found</body></html>"
  41. /* Test Certificate */
  42. const char cert_pem[] =
  43. "-----BEGIN CERTIFICATE-----\n"
  44. "MIICpjCCAZCgAwIBAgIESEPtjjALBgkqhkiG9w0BAQUwADAeFw0wODA2MDIxMjU0\n"
  45. "MzhaFw0wOTA2MDIxMjU0NDZaMAAwggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKC\n"
  46. "AQC03TyUvK5HmUAirRp067taIEO4bibh5nqolUoUdo/LeblMQV+qnrv/RNAMTx5X\n"
  47. "fNLZ45/kbM9geF8qY0vsPyQvP4jumzK0LOJYuIwmHaUm9vbXnYieILiwCuTgjaud\n"
  48. "3VkZDoQ9fteIo+6we9UTpVqZpxpbLulBMh/VsvX0cPJ1VFC7rT59o9hAUlFf9jX/\n"
  49. "GmKdYI79MtgVx0OPBjmmSD6kicBBfmfgkO7bIGwlRtsIyMznxbHu6VuoX/eVxrTv\n"
  50. "rmCwgEXLWRZ6ru8MQl5YfqeGXXRVwMeXU961KefbuvmEPccgCxm8FZ1C1cnDHFXh\n"
  51. "siSgAzMBjC/b6KVhNQ4KnUdZAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0O\n"
  52. "BBYEFJcUvpjvE5fF/yzUshkWDpdYiQh/MAsGCSqGSIb3DQEBBQOCAQEARP7eKSB2\n"
  53. "RNd6XjEjK0SrxtoTnxS3nw9sfcS7/qD1+XHdObtDFqGNSjGYFB3Gpx8fpQhCXdoN\n"
  54. "8QUs3/5ZVa5yjZMQewWBgz8kNbnbH40F2y81MHITxxCe1Y+qqHWwVaYLsiOTqj2/\n"
  55. "0S3QjEJ9tvklmg7JX09HC4m5QRYfWBeQLD1u8ZjA1Sf1xJriomFVyRLI2VPO2bNe\n"
  56. "JDMXWuP+8kMC7gEvUnJ7A92Y2yrhu3QI3bjPk8uSpHea19Q77tul1UVBJ5g+zpH3\n"
  57. "OsF5p0MyaVf09GTzcLds5nE/osTdXGUyHJapWReVmPm3Zn6gqYlnzD99z+DPIgIV\n"
  58. "RhZvQx74NQnS6g==\n" "-----END CERTIFICATE-----\n";
  59. const char key_pem[] =
  60. "-----BEGIN RSA PRIVATE KEY-----\n"
  61. "MIIEowIBAAKCAQEAtN08lLyuR5lAIq0adOu7WiBDuG4m4eZ6qJVKFHaPy3m5TEFf\n"
  62. "qp67/0TQDE8eV3zS2eOf5GzPYHhfKmNL7D8kLz+I7psytCziWLiMJh2lJvb2152I\n"
  63. "niC4sArk4I2rnd1ZGQ6EPX7XiKPusHvVE6VamacaWy7pQTIf1bL19HDydVRQu60+\n"
  64. "faPYQFJRX/Y1/xpinWCO/TLYFcdDjwY5pkg+pInAQX5n4JDu2yBsJUbbCMjM58Wx\n"
  65. "7ulbqF/3lca0765gsIBFy1kWeq7vDEJeWH6nhl10VcDHl1PetSnn27r5hD3HIAsZ\n"
  66. "vBWdQtXJwxxV4bIkoAMzAYwv2+ilYTUOCp1HWQIDAQABAoIBAArOQv3R7gmqDspj\n"
  67. "lDaTFOz0C4e70QfjGMX0sWnakYnDGn6DU19iv3GnX1S072ejtgc9kcJ4e8VUO79R\n"
  68. "EmqpdRR7k8dJr3RTUCyjzf/C+qiCzcmhCFYGN3KRHA6MeEnkvRuBogX4i5EG1k5l\n"
  69. "/5t+YBTZBnqXKWlzQLKoUAiMLPg0eRWh+6q7H4N7kdWWBmTpako7TEqpIwuEnPGx\n"
  70. "u3EPuTR+LN6lF55WBePbCHccUHUQaXuav18NuDkcJmCiMArK9SKb+h0RqLD6oMI/\n"
  71. "dKD6n8cZXeMBkK+C8U/K0sN2hFHACsu30b9XfdnljgP9v+BP8GhnB0nCB6tNBCPo\n"
  72. "32srOwECgYEAxWh3iBT4lWqL6bZavVbnhmvtif4nHv2t2/hOs/CAq8iLAw0oWGZc\n"
  73. "+JEZTUDMvFRlulr0kcaWra+4fN3OmJnjeuFXZq52lfMgXBIKBmoSaZpIh2aDY1Rd\n"
  74. "RbEse7nQl9hTEPmYspiXLGtnAXW7HuWqVfFFP3ya8rUS3t4d07Hig8ECgYEA6ou6\n"
  75. "OHiBRTbtDqLIv8NghARc/AqwNWgEc9PelCPe5bdCOLBEyFjqKiT2MttnSSUc2Zob\n"
  76. "XhYkHC6zN1Mlq30N0e3Q61YK9LxMdU1vsluXxNq2rfK1Scb1oOlOOtlbV3zA3VRF\n"
  77. "hV3t1nOA9tFmUrwZi0CUMWJE/zbPAyhwWotKyZkCgYEAh0kFicPdbABdrCglXVae\n"
  78. "SnfSjVwYkVuGd5Ze0WADvjYsVkYBHTvhgRNnRJMg+/vWz3Sf4Ps4rgUbqK8Vc20b\n"
  79. "AU5G6H6tlCvPRGm0ZxrwTWDHTcuKRVs+pJE8C/qWoklE/AAhjluWVoGwUMbPGuiH\n"
  80. "6Gf1bgHF6oj/Sq7rv/VLZ8ECgYBeq7ml05YyLuJutuwa4yzQ/MXfghzv4aVyb0F3\n"
  81. "QCdXR6o2IYgR6jnSewrZKlA9aPqFJrwHNR6sNXlnSmt5Fcf/RWO/qgJQGLUv3+rG\n"
  82. "7kuLTNDR05azSdiZc7J89ID3Bkb+z2YkV+6JUiPq/Ei1+nDBEXb/m+/HqALU/nyj\n"
  83. "P3gXeQKBgBusb8Rbd+KgxSA0hwY6aoRTPRt8LNvXdsB9vRcKKHUFQvxUWiUSS+L9\n"
  84. "/Qu1sJbrUquKOHqksV5wCnWnAKyJNJlhHuBToqQTgKXjuNmVdYSe631saiI7PHyC\n"
  85. "eRJ6DxULPxABytJrYCRrNqmXi5TCiqR2mtfalEMOPxz8rUU8dYyx\n"
  86. "-----END RSA PRIVATE KEY-----\n";
  87. static ssize_t
  88. file_reader (void *cls, uint64_t pos, char *buf, size_t max)
  89. {
  90. FILE *file = cls;
  91. (void) fseek (file, pos, SEEK_SET);
  92. return fread (buf, 1, max, file);
  93. }
  94. static void
  95. file_free_callback (void *cls)
  96. {
  97. FILE *file = cls;
  98. fclose (file);
  99. }
  100. /* HTTP access handler call back */
  101. static enum MHD_Result
  102. http_ahc (void *cls,
  103. struct MHD_Connection *connection,
  104. const char *url,
  105. const char *method,
  106. const char *version,
  107. const char *upload_data,
  108. size_t *upload_data_size, void **ptr)
  109. {
  110. static int aptr;
  111. struct MHD_Response *response;
  112. enum MHD_Result ret;
  113. FILE *file;
  114. int fd;
  115. struct stat buf;
  116. (void) cls; /* Unused. Silent compiler warning. */
  117. (void) version; /* Unused. Silent compiler warning. */
  118. (void) upload_data; /* Unused. Silent compiler warning. */
  119. (void) upload_data_size; /* Unused. Silent compiler warning. */
  120. if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
  121. return MHD_NO; /* unexpected method */
  122. if (&aptr != *ptr)
  123. {
  124. /* do never respond on first call */
  125. *ptr = &aptr;
  126. return MHD_YES;
  127. }
  128. *ptr = NULL; /* reset when done */
  129. file = fopen (&url[1], "rb");
  130. if (NULL != file)
  131. {
  132. fd = fileno (file);
  133. if (-1 == fd)
  134. {
  135. (void) fclose (file);
  136. return MHD_NO; /* internal error */
  137. }
  138. if ( (0 != fstat (fd, &buf)) ||
  139. (! S_ISREG (buf.st_mode)) )
  140. {
  141. /* not a regular file, refuse to serve */
  142. fclose (file);
  143. file = NULL;
  144. }
  145. }
  146. if (NULL == file)
  147. {
  148. response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
  149. (void *) EMPTY_PAGE,
  150. MHD_RESPMEM_PERSISTENT);
  151. ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
  152. MHD_destroy_response (response);
  153. }
  154. else
  155. {
  156. response = MHD_create_response_from_callback (buf.st_size, 32 * 1024, /* 32k PAGE_NOT_FOUND size */
  157. &file_reader, file,
  158. &file_free_callback);
  159. if (NULL == response)
  160. {
  161. fclose (file);
  162. return MHD_NO;
  163. }
  164. ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
  165. MHD_destroy_response (response);
  166. }
  167. return ret;
  168. }
  169. int
  170. main (int argc, char *const *argv)
  171. {
  172. struct MHD_Daemon *TLS_daemon;
  173. int port;
  174. if (argc != 2)
  175. {
  176. printf ("%s PORT\n", argv[0]);
  177. return 1;
  178. }
  179. port = atoi (argv[1]);
  180. if ( (1 > port) ||
  181. (port > UINT16_MAX) )
  182. {
  183. fprintf (stderr,
  184. "Port must be a number between 1 and 65535\n");
  185. return 1;
  186. }
  187. TLS_daemon =
  188. MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
  189. | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG
  190. | MHD_USE_TLS,
  191. (uint16_t) port,
  192. NULL, NULL,
  193. &http_ahc, NULL,
  194. MHD_OPTION_CONNECTION_TIMEOUT, 256,
  195. MHD_OPTION_HTTPS_MEM_KEY, key_pem,
  196. MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
  197. MHD_OPTION_END);
  198. if (NULL == TLS_daemon)
  199. {
  200. fprintf (stderr, "Error: failed to start TLS_daemon.\n");
  201. return 1;
  202. }
  203. printf ("MHD daemon listening on port %u\n",
  204. (unsigned int) port);
  205. (void) getc (stdin);
  206. MHD_stop_daemon (TLS_daemon);
  207. return 0;
  208. }