2
0

https_fileserver_example.pp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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.pp (Original: https_fileserver_example.c)
  18. * @brief a simple HTTPS file server using TLS.
  19. *
  20. * Usage :
  21. *
  22. * 'https_fileserver_example HTTP-PORT'
  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 / Silvio Clécio
  30. *)
  31. program https_fileserver_example;
  32. {$mode objfpc}{$H+}
  33. uses
  34. sysutils, BaseUnix, cutils, libmicrohttpd;
  35. const
  36. BUF_SIZE = 1024;
  37. MAX_URL_LEN = 255;
  38. // TODO remove if unused
  39. CAFILE: Pcchar = 'ca.pem';
  40. CRLFILE: Pcchar = 'crl.pem';
  41. EMPTY_PAGE: Pcchar = '<html><head><title>File not found</title></head><body>File not found</body></html>';
  42. (* Test Certificate *)
  43. cert_pem: array[0..980] of AnsiChar =
  44. '-----BEGIN CERTIFICATE-----'#10+
  45. 'MIICpjCCAZCgAwIBAgIESEPtjjALBgkqhkiG9w0BAQUwADAeFw0wODA2MDIxMjU0'#10+
  46. 'MzhaFw0wOTA2MDIxMjU0NDZaMAAwggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKC'#10+
  47. 'AQC03TyUvK5HmUAirRp067taIEO4bibh5nqolUoUdo/LeblMQV+qnrv/RNAMTx5X'#10+
  48. 'fNLZ45/kbM9geF8qY0vsPyQvP4jumzK0LOJYuIwmHaUm9vbXnYieILiwCuTgjaud'#10+
  49. '3VkZDoQ9fteIo+6we9UTpVqZpxpbLulBMh/VsvX0cPJ1VFC7rT59o9hAUlFf9jX/'#10+
  50. 'GmKdYI79MtgVx0OPBjmmSD6kicBBfmfgkO7bIGwlRtsIyMznxbHu6VuoX/eVxrTv'#10+
  51. 'rmCwgEXLWRZ6ru8MQl5YfqeGXXRVwMeXU961KefbuvmEPccgCxm8FZ1C1cnDHFXh'#10+
  52. 'siSgAzMBjC/b6KVhNQ4KnUdZAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0O'#10+
  53. 'BBYEFJcUvpjvE5fF/yzUshkWDpdYiQh/MAsGCSqGSIb3DQEBBQOCAQEARP7eKSB2'#10+
  54. 'RNd6XjEjK0SrxtoTnxS3nw9sfcS7/qD1+XHdObtDFqGNSjGYFB3Gpx8fpQhCXdoN'#10+
  55. '8QUs3/5ZVa5yjZMQewWBgz8kNbnbH40F2y81MHITxxCe1Y+qqHWwVaYLsiOTqj2/'#10+
  56. '0S3QjEJ9tvklmg7JX09HC4m5QRYfWBeQLD1u8ZjA1Sf1xJriomFVyRLI2VPO2bNe'#10+
  57. 'JDMXWuP+8kMC7gEvUnJ7A92Y2yrhu3QI3bjPk8uSpHea19Q77tul1UVBJ5g+zpH3'#10+
  58. 'OsF5p0MyaVf09GTzcLds5nE/osTdXGUyHJapWReVmPm3Zn6gqYlnzD99z+DPIgIV'#10+
  59. 'RhZvQx74NQnS6g=='#10+
  60. '-----END CERTIFICATE-----'#10;
  61. key_pem: array[0..1674] of AnsiChar =
  62. '-----BEGIN RSA PRIVATE KEY-----'#10+
  63. 'MIIEowIBAAKCAQEAtN08lLyuR5lAIq0adOu7WiBDuG4m4eZ6qJVKFHaPy3m5TEFf'#10+
  64. 'qp67/0TQDE8eV3zS2eOf5GzPYHhfKmNL7D8kLz+I7psytCziWLiMJh2lJvb2152I'#10+
  65. 'niC4sArk4I2rnd1ZGQ6EPX7XiKPusHvVE6VamacaWy7pQTIf1bL19HDydVRQu60+'#10+
  66. 'faPYQFJRX/Y1/xpinWCO/TLYFcdDjwY5pkg+pInAQX5n4JDu2yBsJUbbCMjM58Wx'#10+
  67. '7ulbqF/3lca0765gsIBFy1kWeq7vDEJeWH6nhl10VcDHl1PetSnn27r5hD3HIAsZ'#10+
  68. 'vBWdQtXJwxxV4bIkoAMzAYwv2+ilYTUOCp1HWQIDAQABAoIBAArOQv3R7gmqDspj'#10+
  69. 'lDaTFOz0C4e70QfjGMX0sWnakYnDGn6DU19iv3GnX1S072ejtgc9kcJ4e8VUO79R'#10+
  70. 'EmqpdRR7k8dJr3RTUCyjzf/C+qiCzcmhCFYGN3KRHA6MeEnkvRuBogX4i5EG1k5l'#10+
  71. '/5t+YBTZBnqXKWlzQLKoUAiMLPg0eRWh+6q7H4N7kdWWBmTpako7TEqpIwuEnPGx'#10+
  72. 'u3EPuTR+LN6lF55WBePbCHccUHUQaXuav18NuDkcJmCiMArK9SKb+h0RqLD6oMI/'#10+
  73. 'dKD6n8cZXeMBkK+C8U/K0sN2hFHACsu30b9XfdnljgP9v+BP8GhnB0nCB6tNBCPo'#10+
  74. '32srOwECgYEAxWh3iBT4lWqL6bZavVbnhmvtif4nHv2t2/hOs/CAq8iLAw0oWGZc'#10+
  75. '+JEZTUDMvFRlulr0kcaWra+4fN3OmJnjeuFXZq52lfMgXBIKBmoSaZpIh2aDY1Rd'#10+
  76. 'RbEse7nQl9hTEPmYspiXLGtnAXW7HuWqVfFFP3ya8rUS3t4d07Hig8ECgYEA6ou6'#10+
  77. 'OHiBRTbtDqLIv8NghARc/AqwNWgEc9PelCPe5bdCOLBEyFjqKiT2MttnSSUc2Zob'#10+
  78. 'XhYkHC6zN1Mlq30N0e3Q61YK9LxMdU1vsluXxNq2rfK1Scb1oOlOOtlbV3zA3VRF'#10+
  79. 'hV3t1nOA9tFmUrwZi0CUMWJE/zbPAyhwWotKyZkCgYEAh0kFicPdbABdrCglXVae'#10+
  80. 'SnfSjVwYkVuGd5Ze0WADvjYsVkYBHTvhgRNnRJMg+/vWz3Sf4Ps4rgUbqK8Vc20b'#10+
  81. 'AU5G6H6tlCvPRGm0ZxrwTWDHTcuKRVs+pJE8C/qWoklE/AAhjluWVoGwUMbPGuiH'#10+
  82. '6Gf1bgHF6oj/Sq7rv/VLZ8ECgYBeq7ml05YyLuJutuwa4yzQ/MXfghzv4aVyb0F3'#10+
  83. 'QCdXR6o2IYgR6jnSewrZKlA9aPqFJrwHNR6sNXlnSmt5Fcf/RWO/qgJQGLUv3+rG'#10+
  84. '7kuLTNDR05azSdiZc7J89ID3Bkb+z2YkV+6JUiPq/Ei1+nDBEXb/m+/HqALU/nyj'#10+
  85. 'P3gXeQKBgBusb8Rbd+KgxSA0hwY6aoRTPRt8LNvXdsB9vRcKKHUFQvxUWiUSS+L9'#10+
  86. '/Qu1sJbrUquKOHqksV5wCnWnAKyJNJlhHuBToqQTgKXjuNmVdYSe631saiI7PHyC'#10+
  87. 'eRJ6DxULPxABytJrYCRrNqmXi5TCiqR2mtfalEMOPxz8rUU8dYyx'#10+
  88. '-----END RSA PRIVATE KEY-----'#10;
  89. function file_reader(cls: Pointer; pos: cuint64; buf: Pcchar;
  90. max: size_t): ssize_t; cdecl;
  91. var
  92. &file: FILEptr;
  93. begin
  94. &file := cls;
  95. fseek(&file, pos, SEEK_SET);
  96. Result := fread(buf, 1, max, &file);
  97. end;
  98. procedure file_free_callback(cls: Pointer); cdecl;
  99. var
  100. &file: FILEptr;
  101. begin
  102. &file := cls;
  103. fclose(&file);
  104. end;
  105. function http_ahc(cls: Pointer; connection: PMHD_Connection; url: Pcchar;
  106. method: Pcchar; version: Pcchar; upload_data: Pcchar;
  107. upload_data_size: Psize_t; ptr: PPointer): cint; cdecl;
  108. const
  109. aptr: cint = 0;
  110. var
  111. response: PMHD_Response;
  112. ret: cint;
  113. &file: FILEptr;
  114. buf: stat;
  115. begin
  116. if 0 <> strcomp(method, MHD_HTTP_METHOD_GET) then
  117. Exit(MHD_NO); (* unexpected method *)
  118. if @aptr <> ptr^ then
  119. begin
  120. (* do never respond on first call *)
  121. ptr^ := @aptr;
  122. Exit(MHD_YES);
  123. end;
  124. ptr^ := nil; (* reset when done *)
  125. if (0 = FpStat(@url[1], buf)) and fpS_ISREG(buf.st_mode) then
  126. &file := fopen(@url[1], fopenread)
  127. else
  128. &file := nil;
  129. if &file = nil then
  130. begin
  131. response := MHD_create_response_from_buffer(strlen(EMPTY_PAGE),
  132. Pointer(EMPTY_PAGE), MHD_RESPMEM_PERSISTENT);
  133. ret := MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
  134. MHD_destroy_response(response);
  135. end
  136. else
  137. begin
  138. response := MHD_create_response_from_callback(buf.st_size, 32 * 1024, (* 32k page size *)
  139. @file_reader, &file, @file_free_callback);
  140. if response = nil then
  141. begin
  142. fclose(&file);
  143. Exit(MHD_NO);
  144. end;
  145. ret := MHD_queue_response(connection, MHD_HTTP_OK, response);
  146. MHD_destroy_response(response);
  147. end;
  148. Result := ret;
  149. end;
  150. var
  151. TLS_daemon: PMHD_Daemon;
  152. begin
  153. if argc = 2 then
  154. begin
  155. (* TODO check if this is truly necessary - disallow usage of the blocking /dev/random *)
  156. (* gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); *)
  157. TLS_daemon := MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION or
  158. MHD_USE_DEBUG or MHD_USE_SSL, StrToInt(argv[1]), nil, nil,
  159. @http_ahc, nil, MHD_OPTION_CONNECTION_TIMEOUT, 256,
  160. MHD_OPTION_HTTPS_MEM_KEY, key_pem,
  161. MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
  162. MHD_OPTION_END);
  163. end
  164. else
  165. begin
  166. WriteLn(' Usage: ', argv[0], ' HTTP-PORT');
  167. Halt(1);
  168. end;
  169. if TLS_daemon = nil then
  170. begin
  171. WriteLn(stderr, 'Error: failed to start TLS_daemon');
  172. Halt(1);
  173. end
  174. else
  175. WriteLn('MHD daemon listening on port ', argv[1]);
  176. ReadLn;
  177. MHD_stop_daemon(TLS_daemon);
  178. end.