PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/sapi/fpm/fpm/fastcgi.c

http://github.com/infusion/PHP
C | 1128 lines | 969 code | 127 blank | 32 comment | 296 complexity | 758d03d068e5614c677fceaa5a083eda MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2009 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Dmitry Stogov <dmitry@zend.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id: fastcgi.c 287777 2009-08-26 19:17:32Z pajoye $ */
  19. #include "php.h"
  20. #include "fastcgi.h"
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <stdarg.h>
  25. #include <errno.h>
  26. #include <limits.h>
  27. #ifdef FPM_AUTOCONFIG_H
  28. #include <fpm_autoconfig.h>
  29. #else
  30. #include <php_config.h>
  31. #endif
  32. #include <fpm/fpm.h>
  33. #include <fpm/fpm_request.h>
  34. #ifdef _WIN32
  35. #include <windows.h>
  36. typedef unsigned int in_addr_t;
  37. struct sockaddr_un {
  38. short sun_family;
  39. char sun_path[MAXPATHLEN];
  40. };
  41. static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE;
  42. static int is_impersonate = 0;
  43. #define FCGI_LOCK(fd) \
  44. if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
  45. DWORD ret; \
  46. while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \
  47. if (in_shutdown) return -1; \
  48. } \
  49. if (ret == WAIT_FAILED) { \
  50. fprintf(stderr, "WaitForSingleObject() failed\n"); \
  51. return -1; \
  52. } \
  53. }
  54. #define FCGI_UNLOCK(fd) \
  55. if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
  56. ReleaseMutex(fcgi_accept_mutex); \
  57. }
  58. #else
  59. # include <sys/types.h>
  60. # include <sys/stat.h>
  61. # include <unistd.h>
  62. # include <fcntl.h>
  63. # include <sys/socket.h>
  64. # include <sys/un.h>
  65. # include <netinet/in.h>
  66. # include <arpa/inet.h>
  67. # include <netdb.h>
  68. # include <signal.h>
  69. # define closesocket(s) close(s)
  70. # if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
  71. # include <sys/poll.h>
  72. # endif
  73. # if defined(HAVE_SYS_SELECT_H)
  74. # include <sys/select.h>
  75. # endif
  76. #ifndef INADDR_NONE
  77. #define INADDR_NONE ((unsigned long) -1)
  78. #endif
  79. # ifndef HAVE_SOCKLEN_T
  80. typedef unsigned int socklen_t;
  81. # endif
  82. # ifdef USE_LOCKING
  83. # define FCGI_LOCK(fd) \
  84. do { \
  85. struct flock lock; \
  86. lock.l_type = F_WRLCK; \
  87. lock.l_start = 0; \
  88. lock.l_whence = SEEK_SET; \
  89. lock.l_len = 0; \
  90. if (fcntl(fd, F_SETLKW, &lock) != -1) { \
  91. break; \
  92. } else if (errno != EINTR || in_shutdown) { \
  93. return -1; \
  94. } \
  95. } while (1)
  96. # define FCGI_UNLOCK(fd) \
  97. do { \
  98. int orig_errno = errno; \
  99. while (1) { \
  100. struct flock lock; \
  101. lock.l_type = F_UNLCK; \
  102. lock.l_start = 0; \
  103. lock.l_whence = SEEK_SET; \
  104. lock.l_len = 0; \
  105. if (fcntl(fd, F_SETLK, &lock) != -1) { \
  106. break; \
  107. } else if (errno != EINTR) { \
  108. return -1; \
  109. } \
  110. } \
  111. errno = orig_errno; \
  112. } while (0)
  113. # else
  114. # define FCGI_LOCK(fd)
  115. # define FCGI_UNLOCK(fd)
  116. # endif
  117. #endif
  118. typedef union _sa_t {
  119. struct sockaddr sa;
  120. struct sockaddr_un sa_unix;
  121. struct sockaddr_in sa_inet;
  122. } sa_t;
  123. static HashTable fcgi_mgmt_vars;
  124. static int is_initialized = 0;
  125. static int is_fastcgi = 0;
  126. static int in_shutdown = 0;
  127. static in_addr_t *allowed_clients = NULL;
  128. #ifdef _WIN32
  129. static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
  130. {
  131. HANDLE shutdown_event = (HANDLE) arg;
  132. WaitForSingleObject(shutdown_event, INFINITE);
  133. in_shutdown = 1;
  134. return 0;
  135. }
  136. #else
  137. static void fcgi_signal_handler(int signo)
  138. {
  139. if (signo == SIGUSR1 || signo == SIGTERM) {
  140. in_shutdown = 1;
  141. }
  142. }
  143. static void fcgi_setup_signals(void)
  144. {
  145. struct sigaction new_sa, old_sa;
  146. sigemptyset(&new_sa.sa_mask);
  147. new_sa.sa_flags = 0;
  148. new_sa.sa_handler = fcgi_signal_handler;
  149. sigaction(SIGUSR1, &new_sa, NULL);
  150. sigaction(SIGTERM, &new_sa, NULL);
  151. sigaction(SIGPIPE, NULL, &old_sa);
  152. if (old_sa.sa_handler == SIG_DFL) {
  153. sigaction(SIGPIPE, &new_sa, NULL);
  154. }
  155. }
  156. #endif
  157. int fcgi_init(void)
  158. {
  159. if (!is_initialized) {
  160. #ifndef _WIN32
  161. sa_t sa;
  162. socklen_t len = sizeof(sa);
  163. #endif
  164. zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1);
  165. fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1);
  166. is_initialized = 1;
  167. #ifdef _WIN32
  168. # if 0
  169. /* TODO: Support for TCP sockets */
  170. WSADATA wsaData;
  171. if (WSAStartup(MAKEWORD(2,0), &wsaData)) {
  172. fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError());
  173. return 0;
  174. }
  175. # endif
  176. if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) &&
  177. (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) &&
  178. (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) {
  179. char *str;
  180. DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT;
  181. HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE);
  182. SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL);
  183. str = getenv("_FCGI_SHUTDOWN_EVENT_");
  184. if (str != NULL) {
  185. HANDLE shutdown_event = (HANDLE) atoi(str);
  186. if (!CreateThread(NULL, 0, fcgi_shutdown_thread,
  187. shutdown_event, 0, NULL)) {
  188. return -1;
  189. }
  190. }
  191. str = getenv("_FCGI_MUTEX_");
  192. if (str != NULL) {
  193. fcgi_accept_mutex = (HANDLE) atoi(str);
  194. }
  195. return is_fastcgi = 1;
  196. } else {
  197. return is_fastcgi = 0;
  198. }
  199. #else
  200. errno = 0;
  201. if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
  202. fcgi_setup_signals();
  203. return is_fastcgi = 1;
  204. } else {
  205. return is_fastcgi = 0;
  206. }
  207. #endif
  208. }
  209. return is_fastcgi;
  210. }
  211. int fcgi_is_fastcgi(void)
  212. {
  213. if (!is_initialized) {
  214. return fcgi_init();
  215. } else {
  216. return is_fastcgi;
  217. }
  218. }
  219. void fcgi_set_is_fastcgi(int new_value)
  220. {
  221. is_fastcgi = new_value;
  222. }
  223. void fcgi_set_in_shutdown(int new_value)
  224. {
  225. in_shutdown = new_value;
  226. }
  227. void fcgi_shutdown(void)
  228. {
  229. if (is_initialized) {
  230. zend_hash_destroy(&fcgi_mgmt_vars);
  231. }
  232. is_fastcgi = 0;
  233. if (allowed_clients) {
  234. free(allowed_clients);
  235. }
  236. }
  237. void fcgi_set_allowed_clients(char *ip)
  238. {
  239. char *cur, *end;
  240. int n;
  241. if (ip) {
  242. ip = strdup(ip);
  243. cur = ip;
  244. n = 0;
  245. while (*cur) {
  246. if (*cur == ',') n++;
  247. cur++;
  248. }
  249. if (allowed_clients) free(allowed_clients);
  250. allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
  251. n = 0;
  252. cur = ip;
  253. while (cur) {
  254. end = strchr(cur, ',');
  255. if (end) {
  256. *end = 0;
  257. end++;
  258. }
  259. allowed_clients[n] = inet_addr(cur);
  260. if (allowed_clients[n] == INADDR_NONE) {
  261. fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS or listen.allowed_clients\n", cur);
  262. }
  263. n++;
  264. cur = end;
  265. }
  266. allowed_clients[n] = INADDR_NONE;
  267. free(ip);
  268. }
  269. }
  270. void fcgi_init_request(fcgi_request *req, int listen_socket)
  271. {
  272. memset(req, 0, sizeof(fcgi_request));
  273. req->listen_socket = listen_socket;
  274. req->fd = -1;
  275. req->id = -1;
  276. req->in_len = 0;
  277. req->in_pad = 0;
  278. req->out_hdr = NULL;
  279. req->out_pos = req->out_buf;
  280. #ifdef _WIN32
  281. req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
  282. #endif
  283. }
  284. static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
  285. {
  286. int ret;
  287. size_t n = 0;
  288. do {
  289. errno = 0;
  290. #ifdef _WIN32
  291. if (!req->tcp) {
  292. ret = write(req->fd, ((char*)buf)+n, count-n);
  293. } else {
  294. ret = send(req->fd, ((char*)buf)+n, count-n, 0);
  295. if (ret <= 0) {
  296. errno = WSAGetLastError();
  297. }
  298. }
  299. #else
  300. ret = write(req->fd, ((char*)buf)+n, count-n);
  301. #endif
  302. if (ret > 0) {
  303. n += ret;
  304. } else if (ret <= 0 && errno != 0 && errno != EINTR) {
  305. return ret;
  306. }
  307. } while (n != count);
  308. return n;
  309. }
  310. static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count)
  311. {
  312. int ret;
  313. size_t n = 0;
  314. do {
  315. errno = 0;
  316. #ifdef _WIN32
  317. if (!req->tcp) {
  318. ret = read(req->fd, ((char*)buf)+n, count-n);
  319. } else {
  320. ret = recv(req->fd, ((char*)buf)+n, count-n, 0);
  321. if (ret <= 0) {
  322. errno = WSAGetLastError();
  323. }
  324. }
  325. #else
  326. ret = read(req->fd, ((char*)buf)+n, count-n);
  327. #endif
  328. if (ret > 0) {
  329. n += ret;
  330. } else if (ret == 0 && errno == 0) {
  331. return n;
  332. } else if (ret <= 0 && errno != 0 && errno != EINTR) {
  333. return ret;
  334. }
  335. } while (n != count);
  336. return n;
  337. }
  338. static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len)
  339. {
  340. int pad = ((len + 7) & ~7) - len;
  341. hdr->contentLengthB0 = (unsigned char)(len & 0xff);
  342. hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff);
  343. hdr->paddingLength = (unsigned char)pad;
  344. hdr->requestIdB0 = (unsigned char)(req_id & 0xff);
  345. hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff);
  346. hdr->reserved = 0;
  347. hdr->type = type;
  348. hdr->version = FCGI_VERSION_1;
  349. if (pad) {
  350. memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad);
  351. }
  352. return pad;
  353. }
  354. static inline size_t fcgi_get_params_len( int *result, unsigned char *p, unsigned char *end)
  355. {
  356. size_t ret = 0;
  357. if (p < end) {
  358. *result = p[0];
  359. if (*result < 128) {
  360. ret = 1;
  361. }
  362. else if (p + 3 < end) {
  363. *result = ((*result & 0x7f) << 24);
  364. *result |= (p[1] << 16);
  365. *result |= (p[2] << 8);
  366. *result |= p[3];
  367. ret = 4;
  368. }
  369. }
  370. if (*result < 0) {
  371. ret = 0;
  372. }
  373. return ret;
  374. }
  375. static inline int fcgi_param_get_eff_len( unsigned char *p, unsigned char *end, uint *eff_len)
  376. {
  377. int ret = 1;
  378. int zero_found = 0;
  379. *eff_len = 0;
  380. for (; p != end; ++p) {
  381. if (*p == '\0') {
  382. zero_found = 1;
  383. }
  384. else {
  385. if (zero_found) {
  386. ret = 0;
  387. break;
  388. }
  389. if (*eff_len < ((uint)-1)) {
  390. ++*eff_len;
  391. }
  392. else {
  393. ret = 0;
  394. break;
  395. }
  396. }
  397. }
  398. return ret;
  399. }
  400. static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end)
  401. {
  402. char buf[128];
  403. char *tmp = buf;
  404. size_t buf_size = sizeof(buf);
  405. int name_len, val_len;
  406. uint eff_name_len, eff_val_len;
  407. char *s;
  408. int ret = 1;
  409. size_t bytes_consumed;
  410. while (p < end) {
  411. bytes_consumed = fcgi_get_params_len(&name_len, p, end);
  412. if (!bytes_consumed) {
  413. /* Malformated request */
  414. ret = 0;
  415. break;
  416. }
  417. p += bytes_consumed;
  418. bytes_consumed = fcgi_get_params_len(&val_len, p, end);
  419. if (!bytes_consumed) {
  420. /* Malformated request */
  421. ret = 0;
  422. break;
  423. }
  424. p += bytes_consumed;
  425. if (name_len > (INT_MAX - val_len) || /* would the addition overflow? */
  426. name_len + val_len > end - p) { /* would we exceed the buffer? */
  427. /* Malformated request */
  428. ret = 0;
  429. break;
  430. }
  431. if (!fcgi_param_get_eff_len(p, p+name_len, &eff_name_len) ||
  432. !fcgi_param_get_eff_len(p+name_len, p+name_len+val_len, &eff_val_len)) {
  433. /* Malicious request */
  434. ret = 0;
  435. break;
  436. }
  437. if (eff_name_len >= buf_size-1) {
  438. if (eff_name_len > ((uint)-1)-64) {
  439. ret = 0;
  440. break;
  441. }
  442. buf_size = eff_name_len + 64;
  443. tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size));
  444. if (tmp == NULL) {
  445. ret = 0;
  446. break;
  447. }
  448. }
  449. memcpy(tmp, p, eff_name_len);
  450. tmp[eff_name_len] = 0;
  451. s = estrndup((char*)p + name_len, eff_val_len);
  452. if (s == NULL) {
  453. ret = 0;
  454. break;
  455. }
  456. zend_hash_update(req->env, tmp, eff_name_len+1, &s, sizeof(char*), NULL);
  457. p += name_len + val_len;
  458. }
  459. if (tmp != buf && tmp != NULL) {
  460. efree(tmp);
  461. }
  462. return ret;
  463. }
  464. static void fcgi_free_var(char **s)
  465. {
  466. efree(*s);
  467. }
  468. static int fcgi_read_request(fcgi_request *req)
  469. {
  470. fcgi_header hdr;
  471. int len, padding;
  472. unsigned char buf[FCGI_MAX_LENGTH+8];
  473. req->keep = 0;
  474. req->closed = 0;
  475. req->in_len = 0;
  476. req->out_hdr = NULL;
  477. req->out_pos = req->out_buf;
  478. ALLOC_HASHTABLE(req->env);
  479. zend_hash_init(req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 0);
  480. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  481. hdr.version < FCGI_VERSION_1) {
  482. return 0;
  483. }
  484. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  485. padding = hdr.paddingLength;
  486. while (hdr.type == FCGI_STDIN && len == 0) {
  487. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  488. hdr.version < FCGI_VERSION_1) {
  489. return 0;
  490. }
  491. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  492. padding = hdr.paddingLength;
  493. }
  494. if (len + padding > FCGI_MAX_LENGTH) {
  495. return 0;
  496. }
  497. req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;
  498. if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
  499. char *val;
  500. if (safe_read(req, buf, len+padding) != len+padding) {
  501. return 0;
  502. }
  503. req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);
  504. switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
  505. case FCGI_RESPONDER:
  506. val = estrdup("RESPONDER");
  507. zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
  508. break;
  509. case FCGI_AUTHORIZER:
  510. val = estrdup("AUTHORIZER");
  511. zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
  512. break;
  513. case FCGI_FILTER:
  514. val = estrdup("FILTER");
  515. zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
  516. break;
  517. default:
  518. return 0;
  519. }
  520. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  521. hdr.version < FCGI_VERSION_1) {
  522. return 0;
  523. }
  524. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  525. padding = hdr.paddingLength;
  526. while (hdr.type == FCGI_PARAMS && len > 0) {
  527. if (len + padding > FCGI_MAX_LENGTH) {
  528. return 0;
  529. }
  530. if (safe_read(req, buf, len+padding) != len+padding) {
  531. req->keep = 0;
  532. return 0;
  533. }
  534. if (!fcgi_get_params(req, buf, buf+len)) {
  535. req->keep = 0;
  536. return 0;
  537. }
  538. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  539. hdr.version < FCGI_VERSION_1) {
  540. req->keep = 0;
  541. return 0;
  542. }
  543. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  544. padding = hdr.paddingLength;
  545. }
  546. } else if (hdr.type == FCGI_GET_VALUES) {
  547. unsigned char *p = buf + sizeof(fcgi_header);
  548. HashPosition pos;
  549. char * str_index;
  550. uint str_length;
  551. ulong num_index;
  552. int key_type;
  553. zval ** value;
  554. if (safe_read(req, buf, len+padding) != len+padding) {
  555. req->keep = 0;
  556. return 0;
  557. }
  558. if (!fcgi_get_params(req, buf, buf+len)) {
  559. req->keep = 0;
  560. return 0;
  561. }
  562. zend_hash_internal_pointer_reset_ex(req->env, &pos);
  563. while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
  564. int zlen;
  565. zend_hash_move_forward_ex(req->env, &pos);
  566. if (key_type != HASH_KEY_IS_STRING) {
  567. continue;
  568. }
  569. if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) {
  570. continue;
  571. }
  572. --str_length;
  573. zlen = Z_STRLEN_PP(value);
  574. if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) {
  575. break;
  576. }
  577. if (str_length < 0x80) {
  578. *p++ = str_length;
  579. } else {
  580. *p++ = ((str_length >> 24) & 0xff) | 0x80;
  581. *p++ = (str_length >> 16) & 0xff;
  582. *p++ = (str_length >> 8) & 0xff;
  583. *p++ = str_length & 0xff;
  584. }
  585. if (zlen < 0x80) {
  586. *p++ = zlen;
  587. } else {
  588. *p++ = ((zlen >> 24) & 0xff) | 0x80;
  589. *p++ = (zlen >> 16) & 0xff;
  590. *p++ = (zlen >> 8) & 0xff;
  591. *p++ = zlen & 0xff;
  592. }
  593. memcpy(p, str_index, str_length);
  594. p += str_length;
  595. memcpy(p, Z_STRVAL_PP(value), zlen);
  596. p += zlen;
  597. }
  598. len = p - buf - sizeof(fcgi_header);
  599. len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
  600. if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
  601. req->keep = 0;
  602. return 0;
  603. }
  604. return 0;
  605. } else {
  606. return 0;
  607. }
  608. return 1;
  609. }
  610. int fcgi_read(fcgi_request *req, char *str, int len)
  611. {
  612. int ret, n, rest;
  613. fcgi_header hdr;
  614. unsigned char buf[255];
  615. n = 0;
  616. rest = len;
  617. while (rest > 0) {
  618. if (req->in_len == 0) {
  619. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  620. hdr.version < FCGI_VERSION_1 ||
  621. hdr.type != FCGI_STDIN) {
  622. req->keep = 0;
  623. return 0;
  624. }
  625. req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  626. req->in_pad = hdr.paddingLength;
  627. if (req->in_len == 0) {
  628. return n;
  629. }
  630. }
  631. if (req->in_len >= rest) {
  632. ret = safe_read(req, str, rest);
  633. } else {
  634. ret = safe_read(req, str, req->in_len);
  635. }
  636. if (ret < 0) {
  637. req->keep = 0;
  638. return ret;
  639. } else if (ret > 0) {
  640. req->in_len -= ret;
  641. rest -= ret;
  642. n += ret;
  643. str += ret;
  644. if (req->in_len == 0) {
  645. if (req->in_pad) {
  646. if (safe_read(req, buf, req->in_pad) != req->in_pad) {
  647. req->keep = 0;
  648. return ret;
  649. }
  650. }
  651. } else {
  652. return n;
  653. }
  654. } else {
  655. return n;
  656. }
  657. }
  658. return n;
  659. }
  660. void fcgi_close(fcgi_request *req, int force, int destroy)
  661. {
  662. if (destroy && req->env) {
  663. zend_hash_destroy(req->env);
  664. FREE_HASHTABLE(req->env);
  665. req->env = NULL;
  666. }
  667. #ifdef _WIN32
  668. if (is_impersonate && !req->tcp) {
  669. RevertToSelf();
  670. }
  671. #endif
  672. if ((force || !req->keep) && req->fd >= 0) {
  673. #ifdef _WIN32
  674. if (!req->tcp) {
  675. HANDLE pipe = (HANDLE)_get_osfhandle(req->fd);
  676. if (!force) {
  677. FlushFileBuffers(pipe);
  678. }
  679. DisconnectNamedPipe(pipe);
  680. } else {
  681. if (!force) {
  682. char buf[8];
  683. shutdown(req->fd, 1);
  684. while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
  685. }
  686. closesocket(req->fd);
  687. }
  688. #else
  689. if (!force) {
  690. char buf[8];
  691. shutdown(req->fd, 1);
  692. while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
  693. }
  694. close(req->fd);
  695. #endif
  696. req->fd = -1;
  697. fpm_request_finished();
  698. }
  699. }
  700. int fcgi_accept_request(fcgi_request *req)
  701. {
  702. #ifdef _WIN32
  703. HANDLE pipe;
  704. OVERLAPPED ov;
  705. #endif
  706. while (1) {
  707. if (req->fd < 0) {
  708. while (1) {
  709. if (in_shutdown) {
  710. return -1;
  711. }
  712. #ifdef _WIN32
  713. if (!req->tcp) {
  714. pipe = (HANDLE)_get_osfhandle(req->listen_socket);
  715. FCGI_LOCK(req->listen_socket);
  716. ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  717. if (!ConnectNamedPipe(pipe, &ov)) {
  718. errno = GetLastError();
  719. if (errno == ERROR_IO_PENDING) {
  720. while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) {
  721. if (in_shutdown) {
  722. CloseHandle(ov.hEvent);
  723. FCGI_UNLOCK(req->listen_socket);
  724. return -1;
  725. }
  726. }
  727. } else if (errno != ERROR_PIPE_CONNECTED) {
  728. }
  729. }
  730. CloseHandle(ov.hEvent);
  731. req->fd = req->listen_socket;
  732. FCGI_UNLOCK(req->listen_socket);
  733. } else {
  734. SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket);
  735. #else
  736. {
  737. int listen_socket = req->listen_socket;
  738. #endif
  739. sa_t sa;
  740. socklen_t len = sizeof(sa);
  741. fpm_request_accepting();
  742. FCGI_LOCK(req->listen_socket);
  743. req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
  744. FCGI_UNLOCK(req->listen_socket);
  745. if (req->fd >= 0 && allowed_clients) {
  746. int n = 0;
  747. int allowed = 0;
  748. while (allowed_clients[n] != INADDR_NONE) {
  749. if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
  750. allowed = 1;
  751. break;
  752. }
  753. n++;
  754. }
  755. if (!allowed) {
  756. fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
  757. closesocket(req->fd);
  758. req->fd = -1;
  759. continue;
  760. }
  761. }
  762. }
  763. #ifdef _WIN32
  764. if (req->fd < 0 && (in_shutdown || errno != EINTR)) {
  765. #else
  766. if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) {
  767. #endif
  768. return -1;
  769. }
  770. #ifdef _WIN32
  771. break;
  772. #else
  773. if (req->fd >= 0) {
  774. #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
  775. struct pollfd fds;
  776. int ret;
  777. fpm_request_reading_headers();
  778. fds.fd = req->fd;
  779. fds.events = POLLIN;
  780. fds.revents = 0;
  781. do {
  782. errno = 0;
  783. ret = poll(&fds, 1, 5000);
  784. } while (ret < 0 && errno == EINTR);
  785. if (ret > 0 && (fds.revents & POLLIN)) {
  786. break;
  787. }
  788. fcgi_close(req, 1, 0);
  789. #else
  790. fpm_request_reading_headers();
  791. if (req->fd < FD_SETSIZE) {
  792. struct timeval tv = {5,0};
  793. fd_set set;
  794. int ret;
  795. FD_ZERO(&set);
  796. FD_SET(req->fd, &set);
  797. do {
  798. errno = 0;
  799. ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0;
  800. } while (ret < 0 && errno == EINTR);
  801. if (ret > 0 && FD_ISSET(req->fd, &set)) {
  802. break;
  803. }
  804. fcgi_close(req, 1, 0);
  805. } else {
  806. fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
  807. fcgi_close(req, 1, 0);
  808. }
  809. #endif
  810. }
  811. #endif
  812. }
  813. } else if (in_shutdown) {
  814. return -1;
  815. }
  816. if (fcgi_read_request(req)) {
  817. #ifdef _WIN32
  818. if (is_impersonate && !req->tcp) {
  819. pipe = (HANDLE)_get_osfhandle(req->fd);
  820. if (!ImpersonateNamedPipeClient(pipe)) {
  821. fcgi_close(req, 1, 1);
  822. continue;
  823. }
  824. }
  825. #endif
  826. return req->fd;
  827. } else {
  828. fcgi_close(req, 1, 1);
  829. }
  830. }
  831. }
  832. static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type)
  833. {
  834. req->out_hdr = (fcgi_header*) req->out_pos;
  835. req->out_hdr->type = type;
  836. req->out_pos += sizeof(fcgi_header);
  837. return req->out_hdr;
  838. }
  839. static inline void close_packet(fcgi_request *req)
  840. {
  841. if (req->out_hdr) {
  842. int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header));
  843. req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len);
  844. req->out_hdr = NULL;
  845. }
  846. }
  847. int fcgi_flush(fcgi_request *req, int close)
  848. {
  849. int len;
  850. close_packet(req);
  851. len = req->out_pos - req->out_buf;
  852. if (close) {
  853. fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos);
  854. fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request));
  855. rec->body.appStatusB3 = 0;
  856. rec->body.appStatusB2 = 0;
  857. rec->body.appStatusB1 = 0;
  858. rec->body.appStatusB0 = 0;
  859. rec->body.protocolStatus = FCGI_REQUEST_COMPLETE;
  860. len += sizeof(fcgi_end_request_rec);
  861. }
  862. if (safe_write(req, req->out_buf, len) != len) {
  863. req->keep = 0;
  864. return 0;
  865. }
  866. req->out_pos = req->out_buf;
  867. return 1;
  868. }
  869. int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
  870. {
  871. int limit, rest;
  872. if (len <= 0) {
  873. return 0;
  874. }
  875. if (req->out_hdr && req->out_hdr->type != type) {
  876. close_packet(req);
  877. }
  878. /* Optimized version */
  879. limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
  880. if (!req->out_hdr) {
  881. limit -= sizeof(fcgi_header);
  882. if (limit < 0) limit = 0;
  883. }
  884. if (len < limit) {
  885. if (!req->out_hdr) {
  886. open_packet(req, type);
  887. }
  888. memcpy(req->out_pos, str, len);
  889. req->out_pos += len;
  890. } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) {
  891. if (!req->out_hdr) {
  892. open_packet(req, type);
  893. }
  894. if (limit > 0) {
  895. memcpy(req->out_pos, str, limit);
  896. req->out_pos += limit;
  897. }
  898. if (!fcgi_flush(req, 0)) {
  899. return -1;
  900. }
  901. if (len > limit) {
  902. open_packet(req, type);
  903. memcpy(req->out_pos, str + limit, len - limit);
  904. req->out_pos += len - limit;
  905. }
  906. } else {
  907. int pos = 0;
  908. int pad;
  909. close_packet(req);
  910. while ((len - pos) > 0xffff) {
  911. open_packet(req, type);
  912. fcgi_make_header(req->out_hdr, type, req->id, 0xfff8);
  913. req->out_hdr = NULL;
  914. if (!fcgi_flush(req, 0)) {
  915. return -1;
  916. }
  917. if (safe_write(req, str + pos, 0xfff8) != 0xfff8) {
  918. req->keep = 0;
  919. return -1;
  920. }
  921. pos += 0xfff8;
  922. }
  923. pad = (((len - pos) + 7) & ~7) - (len - pos);
  924. rest = pad ? 8 - pad : 0;
  925. open_packet(req, type);
  926. fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest);
  927. req->out_hdr = NULL;
  928. if (!fcgi_flush(req, 0)) {
  929. return -1;
  930. }
  931. if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) {
  932. req->keep = 0;
  933. return -1;
  934. }
  935. if (pad) {
  936. open_packet(req, type);
  937. memcpy(req->out_pos, str + len - rest, rest);
  938. req->out_pos += rest;
  939. }
  940. }
  941. return len;
  942. }
  943. int fcgi_finish_request(fcgi_request *req, int force_close)
  944. {
  945. int ret = 1;
  946. if (req->fd >= 0) {
  947. if (!req->closed) {
  948. ret = fcgi_flush(req, 1);
  949. req->closed = 1;
  950. }
  951. fcgi_close(req, force_close, 1);
  952. }
  953. return ret;
  954. }
  955. char* fcgi_getenv(fcgi_request *req, const char* var, int var_len)
  956. {
  957. char **val;
  958. if (!req) return NULL;
  959. if (zend_hash_find(req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) {
  960. return *val;
  961. }
  962. return NULL;
  963. }
  964. char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val)
  965. {
  966. if (var && req) {
  967. if (val == NULL) {
  968. zend_hash_del(req->env, var, var_len+1);
  969. } else {
  970. char **ret;
  971. val = estrdup(val);
  972. if (zend_hash_update(req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) {
  973. return *ret;
  974. }
  975. }
  976. }
  977. return NULL;
  978. }
  979. void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len)
  980. {
  981. zval * zvalue;
  982. zvalue = pemalloc(sizeof(*zvalue), 1);
  983. Z_TYPE_P(zvalue) = IS_STRING;
  984. Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1);
  985. Z_STRLEN_P(zvalue) = value_len;
  986. zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL);
  987. }
  988. void fcgi_free_mgmt_var_cb(void * ptr)
  989. {
  990. zval ** var = (zval **)ptr;
  991. pefree(Z_STRVAL_PP(var), 1);
  992. pefree(*var, 1);
  993. }
  994. /*
  995. * Local variables:
  996. * tab-width: 4
  997. * c-basic-offset: 4
  998. * End:
  999. * vim600: sw=4 ts=4 fdm=marker
  1000. * vim<600: sw=4 ts=4
  1001. */