lighttpd 1.4.x https://www.lighttpd.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1082 lines
35 KiB

  1. #include "first.h"
  2. #include "response.h"
  3. #include "request.h"
  4. #include "base.h"
  5. #include "fdevent.h"
  6. #include "http_header.h"
  7. #include "http_kv.h"
  8. #include "log.h"
  9. #include "stat_cache.h"
  10. #include "chunk.h"
  11. #include "http_chunk.h"
  12. #include "plugin.h"
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <limits.h>
  16. #include <errno.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <time.h>
  20. int
  21. http_response_omit_header (request_st * const r, const data_string * const ds)
  22. {
  23. const size_t klen = buffer_string_length(&ds->key);
  24. if (klen == sizeof("X-Sendfile")-1
  25. && buffer_eq_icase_ssn(ds->key.ptr, CONST_STR_LEN("X-Sendfile")))
  26. return 1;
  27. if (klen >= sizeof("X-LIGHTTPD-")-1
  28. && buffer_eq_icase_ssn(ds->key.ptr, CONST_STR_LEN("X-LIGHTTPD-"))) {
  29. if (klen == sizeof("X-LIGHTTPD-KBytes-per-second")-1
  30. && buffer_eq_icase_ssn(ds->key.ptr+sizeof("X-LIGHTTPD-")-1,
  31. CONST_STR_LEN("KBytes-per-second"))) {
  32. /* "X-LIGHTTPD-KBytes-per-second" */
  33. off_t limit = strtol(ds->value.ptr, NULL, 10) << 10; /*(*=1024)*/
  34. if (limit > 0
  35. && (limit < r->conf.bytes_per_second
  36. || 0 == r->conf.bytes_per_second)) {
  37. r->conf.bytes_per_second = limit;
  38. }
  39. }
  40. return 1;
  41. }
  42. return 0;
  43. }
  44. __attribute_cold__
  45. static void
  46. http_response_write_header_partial_1xx (request_st * const r, buffer * const b)
  47. {
  48. /* take data in con->write_queue and move into b
  49. * (to be sent prior to final response headers in r->write_queue) */
  50. connection * const con = r->con;
  51. /*assert(&r->write_queue != con->write_queue);*/
  52. chunkqueue * const cq = con->write_queue;
  53. con->write_queue = &r->write_queue;
  54. /*assert(0 == buffer_string_length(b));*//*expect empty buffer from caller*/
  55. uint32_t len = (uint32_t)chunkqueue_length(cq);
  56. /*(expecting MEM_CHUNK(s), so not expecting error reading files)*/
  57. if (chunkqueue_read_data(cq, buffer_string_prepare_append(b, len),
  58. len, r->conf.errh) < 0)
  59. len = 0;
  60. buffer_string_set_length(b, len);/*expect initial empty buffer from caller*/
  61. chunkqueue_free(cq);
  62. }
  63. void
  64. http_response_write_header (request_st * const r)
  65. {
  66. chunkqueue * const cq = &r->write_queue;
  67. buffer * const b = chunkqueue_prepend_buffer_open(cq);
  68. if (cq != r->con->write_queue)
  69. http_response_write_header_partial_1xx(r, b);
  70. const char * const httpv = (r->http_version == HTTP_VERSION_1_1) ? "HTTP/1.1 " : "HTTP/1.0 ";
  71. buffer_append_string_len(b, httpv, sizeof("HTTP/1.1 ")-1);
  72. http_status_append(b, r->http_status);
  73. /* disable keep-alive if requested */
  74. if (r->con->request_count > r->conf.max_keep_alive_requests || 0 == r->conf.max_keep_alive_idle) {
  75. r->keep_alive = 0;
  76. } else if (0 != r->reqbody_length
  77. && r->reqbody_length != r->reqbody_queue.bytes_in
  78. && (NULL == r->handler_module
  79. || 0 == (r->conf.stream_request_body
  80. & (FDEVENT_STREAM_REQUEST
  81. | FDEVENT_STREAM_REQUEST_BUFMIN)))) {
  82. r->keep_alive = 0;
  83. } else {
  84. r->con->keep_alive_idle = r->conf.max_keep_alive_idle;
  85. }
  86. if (light_btst(r->resp_htags, HTTP_HEADER_UPGRADE)
  87. && r->http_version == HTTP_VERSION_1_1) {
  88. http_header_response_set(r, HTTP_HEADER_CONNECTION, CONST_STR_LEN("Connection"), CONST_STR_LEN("upgrade"));
  89. } else if (0 == r->keep_alive) {
  90. http_header_response_set(r, HTTP_HEADER_CONNECTION, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
  91. } else if (r->http_version == HTTP_VERSION_1_0) {/*(&& r->keep_alive != 0)*/
  92. http_header_response_set(r, HTTP_HEADER_CONNECTION, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
  93. }
  94. if (304 == r->http_status
  95. && light_btst(r->resp_htags, HTTP_HEADER_CONTENT_ENCODING)) {
  96. http_header_response_unset(r, HTTP_HEADER_CONTENT_ENCODING, CONST_STR_LEN("Content-Encoding"));
  97. }
  98. /* add all headers */
  99. for (size_t i = 0; i < r->resp_headers.used; ++i) {
  100. const data_string * const ds = (data_string *)r->resp_headers.data[i];
  101. if (buffer_string_is_empty(&ds->value)) continue;
  102. if (buffer_string_is_empty(&ds->key)) continue;
  103. if ((ds->key.ptr[0] & 0xdf) == 'X' && http_response_omit_header(r, ds))
  104. continue;
  105. buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
  106. buffer_append_string_buffer(b, &ds->key);
  107. buffer_append_string_len(b, CONST_STR_LEN(": "));
  108. buffer_append_string_buffer(b, &ds->value);
  109. }
  110. if (!light_btst(r->resp_htags, HTTP_HEADER_DATE)) {
  111. static time_t tlast;
  112. static char tstr[32]; /* 30-chars for "%a, %d %b %Y %H:%M:%S GMT" */
  113. static size_t tlen;
  114. /* cache the generated timestamp */
  115. const time_t cur_ts = log_epoch_secs;
  116. if (tlast != cur_ts) {
  117. tlast = cur_ts;
  118. tlen = strftime(tstr, sizeof(tstr),
  119. "%a, %d %b %Y %H:%M:%S GMT", gmtime(&tlast));
  120. }
  121. /* HTTP/1.1 and later requires a Date: header */
  122. buffer_append_string_len(b, CONST_STR_LEN("\r\nDate: "));
  123. buffer_append_string_len(b, tstr, tlen);
  124. }
  125. if (!light_btst(r->resp_htags, HTTP_HEADER_SERVER)) {
  126. if (!buffer_string_is_empty(r->conf.server_tag)) {
  127. buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: "));
  128. buffer_append_string_len(b, CONST_BUF_LEN(r->conf.server_tag));
  129. }
  130. }
  131. buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
  132. r->resp_header_len = buffer_string_length(b);
  133. if (r->conf.log_response_header) {
  134. log_error(r->conf.errh,__FILE__,__LINE__,"Response-Header:\n%s",b->ptr);
  135. }
  136. chunkqueue_prepend_buffer_commit(cq);
  137. /*(optimization to use fewer syscalls to send a small response)*/
  138. off_t cqlen;
  139. if (r->resp_body_finished
  140. && light_btst(r->resp_htags, HTTP_HEADER_CONTENT_LENGTH)
  141. && (cqlen = chunkqueue_length(cq) - r->resp_header_len) > 0
  142. && cqlen <= 32768)
  143. chunkqueue_small_resp_optim(cq);
  144. }
  145. static handler_t http_response_physical_path_check(request_st * const r) {
  146. stat_cache_entry *sce = stat_cache_get_entry(&r->physical.path);
  147. if (sce) {
  148. /* file exists */
  149. } else {
  150. char *pathinfo = NULL;
  151. switch (errno) {
  152. case EACCES:
  153. r->http_status = 403;
  154. if (r->conf.log_request_handling) {
  155. log_error(r->conf.errh, __FILE__, __LINE__,
  156. "-- access denied");
  157. log_error(r->conf.errh, __FILE__, __LINE__,
  158. "Path : %s", r->physical.path.ptr);
  159. }
  160. buffer_reset(&r->physical.path);
  161. return HANDLER_FINISHED;
  162. case ENAMETOOLONG:
  163. /* file name to be read was too long. return 404 */
  164. case ENOENT:
  165. if (r->http_method == HTTP_METHOD_OPTIONS
  166. && light_btst(r->resp_htags, HTTP_HEADER_ALLOW)) {
  167. r->http_status = 200;
  168. return HANDLER_FINISHED;
  169. }
  170. r->http_status = 404;
  171. if (r->conf.log_request_handling) {
  172. log_error(r->conf.errh, __FILE__, __LINE__,
  173. "-- file not found");
  174. log_error(r->conf.errh, __FILE__, __LINE__,
  175. "Path : %s", r->physical.path.ptr);
  176. }
  177. buffer_reset(&r->physical.path);
  178. return HANDLER_FINISHED;
  179. case ENOTDIR:
  180. /* PATH_INFO ! :) */
  181. break;
  182. default:
  183. /* we have no idea what happened. let's tell the user so. */
  184. log_error(r->conf.errh, __FILE__, __LINE__,
  185. "file not found ... or so: %s -> %s",
  186. r->uri.path.ptr, r->physical.path.ptr);
  187. r->http_status = 500;
  188. buffer_reset(&r->physical.path);
  189. return HANDLER_FINISHED;
  190. }
  191. /* not found, perhaps PATHINFO */
  192. {
  193. /*(might check at startup that s->document_root does not end in '/')*/
  194. size_t len = buffer_string_length(&r->physical.basedir);
  195. if (len > 0 && '/' == r->physical.basedir.ptr[len-1]) --len;
  196. pathinfo = r->physical.path.ptr + len;
  197. if ('/' != *pathinfo) {
  198. pathinfo = NULL;
  199. }
  200. else if (pathinfo == r->physical.path.ptr) { /*(basedir is "/")*/
  201. pathinfo = strchr(pathinfo+1, '/');
  202. }
  203. }
  204. buffer * const tb = r->tmp_buf;
  205. for (char *pprev = pathinfo; pathinfo; pprev = pathinfo, pathinfo = strchr(pathinfo+1, '/')) {
  206. buffer_copy_string_len(tb, r->physical.path.ptr, pathinfo - r->physical.path.ptr);
  207. stat_cache_entry *nsce = stat_cache_get_entry(tb);
  208. if (NULL == nsce) {
  209. pathinfo = pathinfo != pprev ? pprev : NULL;
  210. break;
  211. }
  212. sce = nsce;
  213. if (!S_ISDIR(sce->st.st_mode)) break;
  214. }
  215. if (NULL == pathinfo || !S_ISREG(sce->st.st_mode)) {
  216. /* no it really doesn't exists */
  217. r->http_status = 404;
  218. if (r->conf.log_file_not_found) {
  219. log_error(r->conf.errh, __FILE__, __LINE__,
  220. "file not found: %s -> %s",
  221. r->uri.path.ptr, r->physical.path.ptr);
  222. }
  223. buffer_reset(&r->physical.path);
  224. return HANDLER_FINISHED;
  225. }
  226. /* we have a PATHINFO */
  227. if (pathinfo) {
  228. size_t len = strlen(pathinfo), reqlen;
  229. if (r->conf.force_lowercase_filenames
  230. && len <= (reqlen = buffer_string_length(&r->target))
  231. && buffer_eq_icase_ssn(r->target.ptr + reqlen - len, pathinfo, len)) {
  232. /* attempt to preserve case-insensitive PATH_INFO
  233. * (works in common case where mod_alias, mod_magnet, and other modules
  234. * have not modified the PATH_INFO portion of request URI, or did so
  235. * with exactly the PATH_INFO desired) */
  236. buffer_copy_string_len(&r->pathinfo, r->target.ptr + reqlen - len, len);
  237. } else {
  238. buffer_copy_string_len(&r->pathinfo, pathinfo, len);
  239. }
  240. /*
  241. * shorten uri.path
  242. */
  243. buffer_string_set_length(&r->uri.path, buffer_string_length(&r->uri.path) - len);
  244. buffer_string_set_length(&r->physical.path, (size_t)(pathinfo - r->physical.path.ptr));
  245. }
  246. }
  247. if (!r->conf.follow_symlink
  248. && 0 != stat_cache_path_contains_symlink(&r->physical.path, r->conf.errh)) {
  249. r->http_status = 403;
  250. if (r->conf.log_request_handling) {
  251. log_error(r->conf.errh, __FILE__, __LINE__,
  252. "-- access denied due symlink restriction");
  253. log_error(r->conf.errh, __FILE__, __LINE__,
  254. "Path : %s", r->physical.path.ptr);
  255. }
  256. buffer_reset(&r->physical.path);
  257. return HANDLER_FINISHED;
  258. }
  259. if (S_ISREG(sce->st.st_mode)) /*(common case)*/
  260. return HANDLER_GO_ON;
  261. if (S_ISDIR(sce->st.st_mode)) {
  262. if (r->uri.path.ptr[buffer_string_length(&r->uri.path) - 1] != '/') {
  263. /* redirect to .../ */
  264. http_response_redirect_to_directory(r, 301);
  265. return HANDLER_FINISHED;
  266. }
  267. } else {
  268. /* any special handling of other non-reg files ?*/
  269. }
  270. return HANDLER_GO_ON;
  271. }
  272. __attribute_cold__
  273. __attribute_noinline__
  274. static handler_t http_status_set_error_close (request_st * const r, int status) {
  275. r->keep_alive = 0;
  276. r->resp_body_finished = 1;
  277. r->handler_module = NULL;
  278. r->http_status = status;
  279. return HANDLER_FINISHED;
  280. }
  281. static handler_t http_response_config (request_st * const r) {
  282. if (r->conf.log_condition_handling)
  283. log_error(r->conf.errh, __FILE__, __LINE__, "run condition");
  284. config_cond_cache_reset(r);
  285. config_patch_config(r);
  286. /* do we have to downgrade from 1.1 to 1.0 ? (ignore for HTTP/2) */
  287. if (!r->conf.allow_http11 && r->http_version == HTTP_VERSION_1_1)
  288. r->http_version = HTTP_VERSION_1_0;
  289. /* r->conf.max_request_size is in kBytes */
  290. if (0 != r->conf.max_request_size &&
  291. (off_t)r->reqbody_length > ((off_t)r->conf.max_request_size << 10)) {
  292. log_error(r->conf.errh, __FILE__, __LINE__,
  293. "request-size too long: %lld -> 413", (long long) r->reqbody_length);
  294. return /* 413 Payload Too Large */
  295. http_status_set_error_close(r, 413);
  296. }
  297. return HANDLER_GO_ON;
  298. }
  299. __attribute_cold__
  300. static handler_t http_response_comeback (request_st * const r);
  301. static handler_t
  302. http_response_prepare (request_st * const r)
  303. {
  304. handler_t rc;
  305. do {
  306. /* looks like someone has already made a decision */
  307. if (r->http_status != 0 && r->http_status != 200) {
  308. if (0 == r->resp_body_finished)
  309. http_response_body_clear(r, 0);
  310. return HANDLER_FINISHED;
  311. }
  312. /* no decision yet, build conf->filename */
  313. if (buffer_is_empty(&r->physical.path)) {
  314. if (!r->async_callback) {
  315. rc = http_response_config(r);
  316. if (HANDLER_GO_ON != rc) continue;
  317. }
  318. r->async_callback = 0; /* reset */
  319. /* we only come here when we have the parse the full request again
  320. *
  321. * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
  322. * problem here as mod_setenv might get called multiple times
  323. *
  324. * fastcgi-auth might lead to a COMEBACK too
  325. * fastcgi again dead server too
  326. */
  327. if (r->conf.log_request_handling) {
  328. log_error(r->conf.errh, __FILE__, __LINE__,
  329. "-- parsed Request-URI");
  330. log_error(r->conf.errh, __FILE__, __LINE__,
  331. "Request-URI : %s", r->target.ptr);
  332. log_error(r->conf.errh, __FILE__, __LINE__,
  333. "URI-scheme : %s", r->uri.scheme.ptr);
  334. log_error(r->conf.errh, __FILE__, __LINE__,
  335. "URI-authority : %s", r->uri.authority.ptr);
  336. log_error(r->conf.errh, __FILE__, __LINE__,
  337. "URI-path (clean): %s", r->uri.path.ptr);
  338. log_error(r->conf.errh, __FILE__, __LINE__,
  339. "URI-query : %.*s",
  340. BUFFER_INTLEN_PTR(&r->uri.query));
  341. }
  342. /**
  343. *
  344. * call plugins
  345. *
  346. * - based on the raw URL
  347. *
  348. */
  349. rc = plugins_call_handle_uri_raw(r);
  350. if (HANDLER_GO_ON != rc) continue;
  351. /**
  352. *
  353. * call plugins
  354. *
  355. * - based on the clean URL
  356. *
  357. */
  358. rc = plugins_call_handle_uri_clean(r);
  359. if (HANDLER_GO_ON != rc) continue;
  360. if (r->http_method == HTTP_METHOD_OPTIONS &&
  361. r->uri.path.ptr[0] == '*' && r->uri.path.ptr[1] == '\0') {
  362. /* option requests are handled directly without checking of the path */
  363. http_header_response_append(r, HTTP_HEADER_ALLOW,
  364. CONST_STR_LEN("Allow"),
  365. CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
  366. r->http_status = 200;
  367. r->resp_body_finished = 1;
  368. return HANDLER_FINISHED;
  369. }
  370. if (r->http_method == HTTP_METHOD_CONNECT && NULL == r->handler_module) {
  371. return /* 405 Method Not Allowed */
  372. http_status_set_error_close(r, 405);
  373. }
  374. /***
  375. *
  376. * border
  377. *
  378. * logical filename (URI) becomes a physical filename here
  379. *
  380. *
  381. *
  382. */
  383. /* 1. stat()
  384. * ... ISREG() -> ok, go on
  385. * ... ISDIR() -> index-file -> redirect
  386. *
  387. * 2. pathinfo()
  388. * ... ISREG()
  389. *
  390. * 3. -> 404
  391. *
  392. */
  393. /*
  394. * SEARCH DOCUMENT ROOT
  395. */
  396. /* set a default */
  397. buffer_copy_buffer(&r->physical.doc_root, r->conf.document_root);
  398. buffer_copy_buffer(&r->physical.rel_path, &r->uri.path);
  399. #if defined(__WIN32) || defined(__CYGWIN__)
  400. /* strip dots from the end and spaces
  401. *
  402. * windows/dos handle those filenames as the same file
  403. *
  404. * foo == foo. == foo..... == "foo... " == "foo.. ./"
  405. *
  406. * This will affect in some cases PATHINFO
  407. *
  408. * on native windows we could prepend the filename with \\?\ to circumvent
  409. * this behaviour. I have no idea how to push this through cygwin
  410. *
  411. * */
  412. if (!buffer_string_is_empty(&r->physical.rel_path)) {
  413. buffer *b = &r->physical.rel_path;
  414. size_t len = buffer_string_length(b);
  415. /* strip trailing " /" or "./" once */
  416. if (len > 1 &&
  417. b->ptr[len - 1] == '/' &&
  418. (b->ptr[len - 2] == ' ' || b->ptr[len - 2] == '.')) {
  419. len -= 2;
  420. }
  421. /* strip all trailing " " and "." */
  422. while (len > 0 && ( ' ' == b->ptr[len-1] || '.' == b->ptr[len-1] ) ) --len;
  423. buffer_string_set_length(b, len);
  424. }
  425. #endif
  426. if (r->conf.log_request_handling) {
  427. log_error(r->conf.errh, __FILE__, __LINE__,
  428. "-- before doc_root");
  429. log_error(r->conf.errh, __FILE__, __LINE__,
  430. "Doc-Root : %s", r->physical.doc_root.ptr);
  431. log_error(r->conf.errh, __FILE__, __LINE__,
  432. "Rel-Path : %s", r->physical.rel_path.ptr);
  433. log_error(r->conf.errh, __FILE__, __LINE__,
  434. "Path : %s", r->physical.path.ptr);
  435. }
  436. /* the docroot plugin should set the doc_root and might also set the physical.path
  437. * for us (all vhost-plugins are supposed to set the doc_root)
  438. * */
  439. rc = plugins_call_handle_docroot(r);
  440. if (HANDLER_GO_ON != rc) continue;
  441. /* MacOS X and Windows can't distinguish between upper and lower-case
  442. *
  443. * convert to lower-case
  444. */
  445. if (r->conf.force_lowercase_filenames) {
  446. buffer_to_lower(&r->physical.rel_path);
  447. }
  448. /* the docroot plugins might set the servername, if they don't we take http-host */
  449. if (buffer_string_is_empty(r->server_name)) {
  450. r->server_name = &r->uri.authority;
  451. }
  452. /**
  453. * create physical filename
  454. * -> physical.path = docroot + rel_path
  455. *
  456. */
  457. buffer_copy_buffer(&r->physical.basedir, &r->physical.doc_root);
  458. buffer_copy_buffer(&r->physical.path, &r->physical.doc_root);
  459. buffer_append_path_len(&r->physical.path, CONST_BUF_LEN(&r->physical.rel_path));
  460. if (r->conf.log_request_handling) {
  461. log_error(r->conf.errh, __FILE__, __LINE__,
  462. "-- after doc_root");
  463. log_error(r->conf.errh, __FILE__, __LINE__,
  464. "Doc-Root : %s", r->physical.doc_root.ptr);
  465. log_error(r->conf.errh, __FILE__, __LINE__,
  466. "Rel-Path : %s", r->physical.rel_path.ptr);
  467. log_error(r->conf.errh, __FILE__, __LINE__,
  468. "Path : %s", r->physical.path.ptr);
  469. }
  470. if (r->http_method == HTTP_METHOD_CONNECT) {
  471. /* do not permit CONNECT requests to hit filesystem hooks
  472. * since the CONNECT URI bypassed path normalization */
  473. /* (This check is located here so that r->physical.path
  474. * is filled in above to avoid repeating work next time
  475. * http_response_prepare() is called while processing request) */
  476. } else {
  477. rc = plugins_call_handle_physical(r);
  478. if (HANDLER_GO_ON != rc) continue;
  479. if (r->conf.log_request_handling) {
  480. log_error(r->conf.errh, __FILE__, __LINE__,
  481. "-- logical -> physical");
  482. log_error(r->conf.errh, __FILE__, __LINE__,
  483. "Doc-Root : %s", r->physical.doc_root.ptr);
  484. log_error(r->conf.errh, __FILE__, __LINE__,
  485. "Basedir : %s", r->physical.basedir.ptr);
  486. log_error(r->conf.errh, __FILE__, __LINE__,
  487. "Rel-Path : %s", r->physical.rel_path.ptr);
  488. log_error(r->conf.errh, __FILE__, __LINE__,
  489. "Path : %s", r->physical.path.ptr);
  490. }
  491. }
  492. }
  493. if (NULL != r->handler_module) return HANDLER_GO_ON;
  494. /*
  495. * No module grabbed the request yet (like mod_access)
  496. *
  497. * Go on and check of the file exists at all
  498. */
  499. if (r->conf.log_request_handling) {
  500. log_error(r->conf.errh, __FILE__, __LINE__,
  501. "-- handling physical path");
  502. log_error(r->conf.errh, __FILE__, __LINE__,
  503. "Path : %s", r->physical.path.ptr);
  504. }
  505. rc = http_response_physical_path_check(r);
  506. if (HANDLER_GO_ON != rc) continue;
  507. if (r->conf.log_request_handling) {
  508. log_error(r->conf.errh, __FILE__, __LINE__,
  509. "-- handling subrequest");
  510. log_error(r->conf.errh, __FILE__, __LINE__,
  511. "Path : %s", r->physical.path.ptr);
  512. log_error(r->conf.errh, __FILE__, __LINE__,
  513. "URI : %s", r->uri.path.ptr);
  514. log_error(r->conf.errh, __FILE__, __LINE__,
  515. "Pathinfo : %s", r->pathinfo.ptr);
  516. }
  517. /* call the handlers */
  518. rc = plugins_call_handle_subrequest_start(r);
  519. if (HANDLER_GO_ON != rc) {
  520. if (r->conf.log_request_handling) {
  521. log_error(r->conf.errh, __FILE__, __LINE__,
  522. "-- subrequest finished");
  523. }
  524. continue;
  525. }
  526. /* if we are still here, no one wanted the file, status 403 is ok I think */
  527. if (NULL == r->handler_module && 0 == r->http_status) {
  528. r->http_status = (r->http_method != HTTP_METHOD_OPTIONS) ? 403 : 200;
  529. return HANDLER_FINISHED;
  530. }
  531. return HANDLER_GO_ON;
  532. } while (HANDLER_COMEBACK == rc
  533. && HANDLER_GO_ON ==(rc = http_response_comeback(r)));
  534. return rc;
  535. }
  536. __attribute_cold__
  537. static handler_t http_response_comeback (request_st * const r)
  538. {
  539. if (NULL != r->handler_module || !buffer_is_empty(&r->physical.path))
  540. return HANDLER_GO_ON;
  541. config_reset_config(r);
  542. buffer_copy_buffer(&r->uri.authority,r->http_host);/*copy even if NULL*/
  543. buffer_to_lower(&r->uri.authority);
  544. int status = http_request_parse_target(r, r->con->proto_default_port);
  545. if (0 == status) {
  546. r->conditional_is_valid = (1 << COMP_SERVER_SOCKET)
  547. | (1 << COMP_HTTP_SCHEME)
  548. | (1 << COMP_HTTP_HOST)
  549. | (1 << COMP_HTTP_REMOTE_IP)
  550. | (1 << COMP_HTTP_REQUEST_METHOD)
  551. | (1 << COMP_HTTP_URL)
  552. | (1 << COMP_HTTP_QUERY_STRING)
  553. | (1 << COMP_HTTP_REQUEST_HEADER);
  554. return HANDLER_GO_ON;
  555. }
  556. else {
  557. r->conditional_is_valid = (1 << COMP_SERVER_SOCKET)
  558. | (1 << COMP_HTTP_REMOTE_IP);
  559. config_cond_cache_reset(r);
  560. return http_status_set_error_close(r, status);
  561. }
  562. }
  563. __attribute_cold__
  564. static void
  565. http_response_errdoc_init (request_st * const r)
  566. {
  567. /* modules that produce headers required with error response should
  568. * typically also produce an error document. Make an exception for
  569. * mod_auth WWW-Authenticate response header. */
  570. buffer *www_auth = NULL;
  571. if (401 == r->http_status) {
  572. const buffer * const vb =
  573. http_header_response_get(r, HTTP_HEADER_WWW_AUTHENTICATE,
  574. CONST_STR_LEN("WWW-Authenticate"));
  575. if (NULL != vb) www_auth = buffer_init_buffer(vb);
  576. }
  577. buffer_reset(&r->physical.path);
  578. r->resp_htags = 0;
  579. array_reset_data_strings(&r->resp_headers);
  580. http_response_body_clear(r, 0);
  581. if (NULL != www_auth) {
  582. http_header_response_set(r, HTTP_HEADER_WWW_AUTHENTICATE,
  583. CONST_STR_LEN("WWW-Authenticate"),
  584. CONST_BUF_LEN(www_auth));
  585. buffer_free(www_auth);
  586. }
  587. }
  588. __attribute_cold__
  589. static void
  590. http_response_static_errdoc (request_st * const r)
  591. {
  592. if (NULL == r->handler_module
  593. ? r->error_handler_saved_status >= 65535
  594. : (!r->conf.error_intercept || r->error_handler_saved_status))
  595. return;
  596. http_response_errdoc_init(r);
  597. r->resp_body_finished = 1;
  598. /* try to send static errorfile */
  599. if (!buffer_string_is_empty(r->conf.errorfile_prefix)) {
  600. buffer_copy_buffer(&r->physical.path, r->conf.errorfile_prefix);
  601. buffer_append_int(&r->physical.path, r->http_status);
  602. buffer_append_string_len(&r->physical.path, CONST_STR_LEN(".html"));
  603. stat_cache_entry *sce =
  604. stat_cache_get_entry_open(&r->physical.path, r->conf.follow_symlink);
  605. int fd = sce && sce->fd >= 0 ? fdevent_dup_cloexec(sce->fd) : -1;
  606. if (fd >= 0 && 0 == http_chunk_append_file_fd(r, &r->physical.path,
  607. fd, sce->st.st_size)) {
  608. const buffer *content_type = (NULL != sce)
  609. ? stat_cache_content_type_get(sce, r)
  610. : NULL;
  611. if (content_type)
  612. http_header_response_set(r, HTTP_HEADER_CONTENT_TYPE,
  613. CONST_STR_LEN("Content-Type"),
  614. CONST_BUF_LEN(content_type));
  615. return;
  616. }
  617. }
  618. /* build default error-page */
  619. buffer_reset(&r->physical.path);
  620. buffer * const b = r->tmp_buf;
  621. buffer_copy_string_len(b, CONST_STR_LEN(
  622. "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
  623. "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
  624. " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
  625. "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
  626. " <head>\n"
  627. " <title>"));
  628. http_status_append(b, r->http_status);
  629. buffer_append_string_len(b, CONST_STR_LEN(
  630. "</title>\n"
  631. " </head>\n"
  632. " <body>\n"
  633. " <h1>"));
  634. http_status_append(b, r->http_status);
  635. buffer_append_string_len(b, CONST_STR_LEN(
  636. "</h1>\n"
  637. " </body>\n"
  638. "</html>\n"));
  639. (void)http_chunk_append_mem(r, CONST_BUF_LEN(b));
  640. http_header_response_set(r, HTTP_HEADER_CONTENT_TYPE,
  641. CONST_STR_LEN("Content-Type"),
  642. CONST_STR_LEN("text/html"));
  643. }
  644. __attribute_cold__
  645. static void
  646. http_response_merge_trailers (request_st * const r)
  647. {
  648. /* attempt to merge trailers into headers; header not yet sent by caller */
  649. if (buffer_string_is_empty(&r->gw_dechunk->b)) return;
  650. const int done = r->gw_dechunk->done;
  651. if (!done) return; /* XXX: !done; could scan for '\n' and send only those */
  652. /* do not include trailers if success status (when response was read from
  653. * backend) subsequently changed to error status. http_chunk could add the
  654. * trailers, but such actions are better on a different code layer than in
  655. * http_chunk.c */
  656. if (done < 400 && r->http_status >= 400) return;
  657. /* XXX: trailers passed through; no sanity check currently done
  658. * https://tools.ietf.org/html/rfc7230#section-4.1.2
  659. *
  660. * Not checking for disallowed fields
  661. * Not handling (deprecated) line wrapping
  662. * Not strictly checking fields
  663. */
  664. const char *k = strchr(r->gw_dechunk->b.ptr, '\n'); /*(skip final chunk)*/
  665. if (NULL == k) return; /*(should not happen)*/
  666. ++k;
  667. for (const char *v, *e; (e = strchr(k, '\n')); k = e+1) {
  668. v = memchr(k, ':', (size_t)(e - k));
  669. if (NULL == v || v == k || *k == ' ' || *k == '\t') continue;
  670. uint32_t klen = (uint32_t)(v - k);
  671. do { ++v; } while (*v == ' ' || *v == '\t');
  672. if (*v == '\r' || *v == '\n') continue;
  673. enum http_header_e id = http_header_hkey_get(k, klen);
  674. http_header_response_insert(r, id, k, klen, v, (size_t)(e - v));
  675. }
  676. http_header_response_unset(r, HTTP_HEADER_OTHER, CONST_STR_LEN("Trailer"));
  677. buffer_clear(&r->gw_dechunk->b);
  678. }
  679. static handler_t
  680. http_response_write_prepare(request_st * const r)
  681. {
  682. if (NULL == r->handler_module) {
  683. /* static files */
  684. switch(r->http_method) {
  685. case HTTP_METHOD_GET:
  686. case HTTP_METHOD_POST:
  687. case HTTP_METHOD_HEAD:
  688. break;
  689. case HTTP_METHOD_OPTIONS:
  690. if ((!r->http_status || r->http_status == 200)
  691. && !buffer_string_is_empty(&r->uri.path)
  692. && r->uri.path.ptr[0] != '*') {
  693. http_response_body_clear(r, 0);
  694. http_header_response_append(r, HTTP_HEADER_ALLOW,
  695. CONST_STR_LEN("Allow"),
  696. CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
  697. r->http_status = 200;
  698. r->resp_body_finished = 1;
  699. }
  700. break;
  701. default:
  702. if (r->http_status == 0)
  703. r->http_status = 501;
  704. break;
  705. }
  706. }
  707. switch (r->http_status) {
  708. case 200: /* common case */
  709. break;
  710. case 204: /* class: header only */
  711. case 205:
  712. case 304:
  713. /* disable chunked encoding again as we have no body */
  714. http_response_body_clear(r, 1);
  715. /* no Content-Body, no Content-Length */
  716. http_header_response_unset(r, HTTP_HEADER_CONTENT_LENGTH,
  717. CONST_STR_LEN("Content-Length"));
  718. r->resp_body_finished = 1;
  719. break;
  720. default: /* class: header + body */
  721. if (r->http_status == 0)
  722. r->http_status = 403;
  723. /* only custom body for 4xx and 5xx */
  724. if (r->http_status >= 400 && r->http_status < 600)
  725. http_response_static_errdoc(r);
  726. break;
  727. }
  728. if (r->gw_dechunk)
  729. http_response_merge_trailers(r);
  730. /* Allow filter plugins to change response headers */
  731. switch (plugins_call_handle_response_start(r)) {
  732. case HANDLER_GO_ON:
  733. case HANDLER_FINISHED:
  734. break;
  735. default:
  736. log_error(r->conf.errh, __FILE__, __LINE__,
  737. "response_start plugin failed");
  738. return HANDLER_ERROR;
  739. }
  740. if (r->resp_body_finished) {
  741. /* set content-length if length is known and not already set */
  742. if (!(r->resp_htags
  743. & (light_bshift(HTTP_HEADER_CONTENT_LENGTH)
  744. |light_bshift(HTTP_HEADER_TRANSFER_ENCODING)))) {
  745. off_t qlen = chunkqueue_length(&r->write_queue);
  746. /**
  747. * The Content-Length header can only be sent if we have content:
  748. * - HEAD does not have a content-body (but can have content-length)
  749. * - 1xx, 204 and 304 does not have a content-body
  750. * (RFC 2616 Section 4.3)
  751. *
  752. * Otherwise generate a Content-Length header
  753. * (if chunked encoding is not available)
  754. *
  755. * (should not reach here if 1xx (r->http_status < 200))
  756. */
  757. if (qlen > 0) {
  758. buffer * const tb = r->tmp_buf;
  759. buffer_clear(tb);
  760. buffer_append_int(tb, qlen);
  761. http_header_response_set(r, HTTP_HEADER_CONTENT_LENGTH,
  762. CONST_STR_LEN("Content-Length"),
  763. CONST_BUF_LEN(tb));
  764. }
  765. else if (r->http_method != HTTP_METHOD_HEAD
  766. && r->http_status != 204 && r->http_status != 304) {
  767. /* Content-Length: 0 is important for Redirects (301, ...) as
  768. * there might be content. */
  769. http_header_response_set(r, HTTP_HEADER_CONTENT_LENGTH,
  770. CONST_STR_LEN("Content-Length"),
  771. CONST_STR_LEN("0"));
  772. }
  773. }
  774. }
  775. else if (r->http_version == HTTP_VERSION_2) {
  776. /* handled by HTTP/2 framing */
  777. }
  778. else {
  779. /**
  780. * response is not yet finished, but we have all headers
  781. *
  782. * keep-alive requires one of:
  783. * - Content-Length: ... (HTTP/1.0 and HTTP/1.0)
  784. * - Transfer-Encoding: chunked (HTTP/1.1)
  785. * - Upgrade: ... (lighttpd then acts as transparent proxy)
  786. */
  787. if (!(r->resp_htags
  788. & (light_bshift(HTTP_HEADER_CONTENT_LENGTH)
  789. |light_bshift(HTTP_HEADER_TRANSFER_ENCODING)
  790. |light_bshift(HTTP_HEADER_UPGRADE)))) {
  791. if (r->http_method == HTTP_METHOD_CONNECT && r->http_status == 200){
  792. /*(no transfer-encoding if successful CONNECT)*/
  793. }
  794. else if (r->http_version == HTTP_VERSION_1_1) {
  795. off_t qlen = chunkqueue_length(&r->write_queue);
  796. r->resp_send_chunked = 1;
  797. if (qlen) {
  798. /* create initial Transfer-Encoding: chunked segment */
  799. buffer * const b =
  800. chunkqueue_prepend_buffer_open(&r->write_queue);
  801. buffer_append_uint_hex(b, (uintmax_t)qlen);
  802. buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
  803. chunkqueue_prepend_buffer_commit(&r->write_queue);
  804. chunkqueue_append_mem(&r->write_queue,
  805. CONST_STR_LEN("\r\n"));
  806. }
  807. http_header_response_append(r, HTTP_HEADER_TRANSFER_ENCODING,
  808. CONST_STR_LEN("Transfer-Encoding"),
  809. CONST_STR_LEN("chunked"));
  810. }
  811. else { /* if (r->http_version == HTTP_VERSION_1_0) */
  812. r->keep_alive = 0;
  813. }
  814. }
  815. }
  816. if (r->http_method == HTTP_METHOD_HEAD) {
  817. /* HEAD request is like a GET, but without the content */
  818. http_response_body_clear(r, 1);
  819. r->resp_body_finished = 1;
  820. }
  821. return HANDLER_GO_ON;
  822. }
  823. __attribute_cold__
  824. static handler_t
  825. http_response_call_error_handler (request_st * const r, const buffer * const error_handler)
  826. {
  827. /* call error-handler */
  828. /* set REDIRECT_STATUS to save current HTTP status code
  829. * for access by dynamic handlers
  830. * https://redmine.lighttpd.net/issues/1828 */
  831. buffer * const tb = r->tmp_buf;
  832. buffer_clear(tb);
  833. buffer_append_int(tb, r->http_status);
  834. http_header_env_set(r, CONST_STR_LEN("REDIRECT_STATUS"), CONST_BUF_LEN(tb));
  835. if (error_handler == r->conf.error_handler) {
  836. plugins_call_handle_request_reset(r);
  837. if (r->reqbody_length) {
  838. if (r->reqbody_length != r->reqbody_queue.bytes_in)
  839. r->keep_alive = 0;
  840. r->reqbody_length = 0;
  841. chunkqueue_reset(&r->reqbody_queue);
  842. }
  843. r->con->is_writable = 1;
  844. r->resp_body_finished = 0;
  845. r->resp_body_started = 0;
  846. r->error_handler_saved_status = r->http_status;
  847. r->error_handler_saved_method = r->http_method;
  848. r->http_method = HTTP_METHOD_GET;
  849. }
  850. else { /*(preserve behavior for server.error-handler-404)*/
  851. /*(negative to flag old behavior)*/
  852. r->error_handler_saved_status = -r->http_status;
  853. }
  854. if (r->http_version == HTTP_VERSION_UNSET)
  855. r->http_version = HTTP_VERSION_1_0;
  856. buffer_copy_buffer(&r->target, error_handler);
  857. http_response_errdoc_init(r);
  858. r->http_status = 0; /*(after http_response_errdoc_init())*/
  859. http_response_comeback(r);
  860. return HANDLER_COMEBACK;
  861. }
  862. handler_t
  863. http_response_handler (request_st * const r)
  864. {
  865. const plugin *p = r->handler_module;
  866. int rc;
  867. if (NULL != p
  868. || ((rc = http_response_prepare(r)) == HANDLER_GO_ON
  869. && NULL != (p = r->handler_module)))
  870. rc = p->handle_subrequest(r, p->data);
  871. switch (rc) {
  872. case HANDLER_WAIT_FOR_EVENT:
  873. if (!r->resp_body_finished
  874. && (!r->resp_body_started
  875. || 0 == (r->conf.stream_response_body
  876. & (FDEVENT_STREAM_RESPONSE
  877. |FDEVENT_STREAM_RESPONSE_BUFMIN))))
  878. return HANDLER_WAIT_FOR_EVENT; /* come back here */
  879. /* response headers received from backend; start response */
  880. __attribute_fallthrough__
  881. case HANDLER_GO_ON:
  882. case HANDLER_FINISHED: /*(HANDLER_FINISHED if request not handled)*/
  883. if (r->http_status == 0) r->http_status = 200;
  884. if (r->error_handler_saved_status > 0)
  885. r->http_method = r->error_handler_saved_method;
  886. if (NULL == r->handler_module || r->conf.error_intercept) {
  887. if (r->error_handler_saved_status) {
  888. const int subreq_status = r->http_status;
  889. if (r->error_handler_saved_status > 0)
  890. r->http_status = r->error_handler_saved_status;
  891. else if (r->http_status == 404 || r->http_status == 403)
  892. /* error-handler-404 is a 404 */
  893. r->http_status = -r->error_handler_saved_status;
  894. else {
  895. /* error-handler-404 is back and has generated content */
  896. /* if Status: was set, take it otherwise use 200 */
  897. }
  898. if (200 <= subreq_status && subreq_status <= 299) {
  899. /*(flag value to indicate that error handler succeeded)
  900. *(for (NULL == r->handler_module))*/
  901. r->error_handler_saved_status = 65535; /* >= 1000 */
  902. }
  903. }
  904. else if (r->http_status >= 400) {
  905. const buffer *error_handler = NULL;
  906. if (!buffer_string_is_empty(r->conf.error_handler))
  907. error_handler = r->conf.error_handler;
  908. else if ((r->http_status == 404 || r->http_status == 403)
  909. && !buffer_string_is_empty(r->conf.error_handler_404))
  910. error_handler = r->conf.error_handler_404;
  911. if (error_handler)
  912. return http_response_call_error_handler(r, error_handler);
  913. }
  914. }
  915. /* we have something to send; go on */
  916. /*(CON_STATE_RESPONSE_START; transient state)*/
  917. return http_response_write_prepare(r);
  918. case HANDLER_WAIT_FOR_FD:
  919. return HANDLER_WAIT_FOR_FD;
  920. case HANDLER_COMEBACK:
  921. http_response_comeback(r);
  922. return HANDLER_COMEBACK;
  923. /*case HANDLER_ERROR:*/
  924. default:
  925. return HANDLER_ERROR; /* something went wrong */
  926. }
  927. }