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.

1288 lines
29 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
18 years ago
20 years ago
19 years ago
20 years ago
20 years ago
19 years ago
19 years ago
  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$ */
  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. #ifdef _WIN32
  27. #include <windows.h>
  28. typedef unsigned int in_addr_t;
  29. struct sockaddr_un {
  30. short sun_family;
  31. char sun_path[MAXPATHLEN];
  32. };
  33. static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE;
  34. static int is_impersonate = 0;
  35. #define FCGI_LOCK(fd) \
  36. if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
  37. DWORD ret; \
  38. while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \
  39. if (in_shutdown) return -1; \
  40. } \
  41. if (ret == WAIT_FAILED) { \
  42. fprintf(stderr, "WaitForSingleObject() failed\n"); \
  43. return -1; \
  44. } \
  45. }
  46. #define FCGI_UNLOCK(fd) \
  47. if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
  48. ReleaseMutex(fcgi_accept_mutex); \
  49. }
  50. #else
  51. # include <sys/types.h>
  52. # include <sys/stat.h>
  53. # include <unistd.h>
  54. # include <fcntl.h>
  55. # include <sys/socket.h>
  56. # include <sys/un.h>
  57. # include <netinet/in.h>
  58. # include <arpa/inet.h>
  59. # include <netdb.h>
  60. # include <signal.h>
  61. # define closesocket(s) close(s)
  62. # if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
  63. # include <sys/poll.h>
  64. # endif
  65. # if defined(HAVE_SYS_SELECT_H)
  66. # include <sys/select.h>
  67. # endif
  68. #ifndef INADDR_NONE
  69. #define INADDR_NONE ((unsigned long) -1)
  70. #endif
  71. # ifndef HAVE_SOCKLEN_T
  72. typedef unsigned int socklen_t;
  73. # endif
  74. # ifdef USE_LOCKING
  75. # define FCGI_LOCK(fd) \
  76. do { \
  77. struct flock lock; \
  78. lock.l_type = F_WRLCK; \
  79. lock.l_start = 0; \
  80. lock.l_whence = SEEK_SET; \
  81. lock.l_len = 0; \
  82. if (fcntl(fd, F_SETLKW, &lock) != -1) { \
  83. break; \
  84. } else if (errno != EINTR || in_shutdown) { \
  85. return -1; \
  86. } \
  87. } while (1)
  88. # define FCGI_UNLOCK(fd) \
  89. do { \
  90. int orig_errno = errno; \
  91. while (1) { \
  92. struct flock lock; \
  93. lock.l_type = F_UNLCK; \
  94. lock.l_start = 0; \
  95. lock.l_whence = SEEK_SET; \
  96. lock.l_len = 0; \
  97. if (fcntl(fd, F_SETLK, &lock) != -1) { \
  98. break; \
  99. } else if (errno != EINTR) { \
  100. return -1; \
  101. } \
  102. } \
  103. errno = orig_errno; \
  104. } while (0)
  105. # else
  106. # define FCGI_LOCK(fd)
  107. # define FCGI_UNLOCK(fd)
  108. # endif
  109. #endif
  110. typedef union _sa_t {
  111. struct sockaddr sa;
  112. struct sockaddr_un sa_unix;
  113. struct sockaddr_in sa_inet;
  114. } sa_t;
  115. static HashTable fcgi_mgmt_vars;
  116. static int is_initialized = 0;
  117. static int is_fastcgi = 0;
  118. static int in_shutdown = 0;
  119. static in_addr_t *allowed_clients = NULL;
  120. #ifdef _WIN32
  121. static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
  122. {
  123. HANDLE shutdown_event = (HANDLE) arg;
  124. WaitForSingleObject(shutdown_event, INFINITE);
  125. in_shutdown = 1;
  126. return 0;
  127. }
  128. #else
  129. static void fcgi_signal_handler(int signo)
  130. {
  131. if (signo == SIGUSR1 || signo == SIGTERM) {
  132. in_shutdown = 1;
  133. }
  134. }
  135. static void fcgi_setup_signals(void)
  136. {
  137. struct sigaction new_sa, old_sa;
  138. sigemptyset(&new_sa.sa_mask);
  139. new_sa.sa_flags = 0;
  140. new_sa.sa_handler = fcgi_signal_handler;
  141. sigaction(SIGUSR1, &new_sa, NULL);
  142. sigaction(SIGTERM, &new_sa, NULL);
  143. sigaction(SIGPIPE, NULL, &old_sa);
  144. if (old_sa.sa_handler == SIG_DFL) {
  145. sigaction(SIGPIPE, &new_sa, NULL);
  146. }
  147. }
  148. #endif
  149. int fcgi_in_shutdown(void)
  150. {
  151. return in_shutdown;
  152. }
  153. int fcgi_init(void)
  154. {
  155. if (!is_initialized) {
  156. #ifndef _WIN32
  157. sa_t sa;
  158. socklen_t len = sizeof(sa);
  159. #endif
  160. zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1);
  161. fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1);
  162. is_initialized = 1;
  163. #ifdef _WIN32
  164. # if 0
  165. /* TODO: Support for TCP sockets */
  166. WSADATA wsaData;
  167. if (WSAStartup(MAKEWORD(2,0), &wsaData)) {
  168. fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError());
  169. return 0;
  170. }
  171. # endif
  172. if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) &&
  173. (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) &&
  174. (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) {
  175. char *str;
  176. DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT;
  177. HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE);
  178. SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL);
  179. str = getenv("_FCGI_SHUTDOWN_EVENT_");
  180. if (str != NULL) {
  181. HANDLE shutdown_event = (HANDLE) atoi(str);
  182. if (!CreateThread(NULL, 0, fcgi_shutdown_thread,
  183. shutdown_event, 0, NULL)) {
  184. return -1;
  185. }
  186. }
  187. str = getenv("_FCGI_MUTEX_");
  188. if (str != NULL) {
  189. fcgi_accept_mutex = (HANDLE) atoi(str);
  190. }
  191. return is_fastcgi = 1;
  192. } else {
  193. return is_fastcgi = 0;
  194. }
  195. #else
  196. errno = 0;
  197. if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
  198. fcgi_setup_signals();
  199. return is_fastcgi = 1;
  200. } else {
  201. return is_fastcgi = 0;
  202. }
  203. #endif
  204. }
  205. return is_fastcgi;
  206. }
  207. int fcgi_is_fastcgi(void)
  208. {
  209. if (!is_initialized) {
  210. return fcgi_init();
  211. } else {
  212. return is_fastcgi;
  213. }
  214. }
  215. void fcgi_shutdown(void)
  216. {
  217. if (is_initialized) {
  218. zend_hash_destroy(&fcgi_mgmt_vars);
  219. }
  220. is_fastcgi = 0;
  221. }
  222. #ifdef _WIN32
  223. /* Do some black magic with the NT security API.
  224. * We prepare a DACL (Discretionary Access Control List) so that
  225. * we, the creator, are allowed all access, while "Everyone Else"
  226. * is only allowed to read and write to the pipe.
  227. * This avoids security issues on shared hosts where a luser messes
  228. * with the lower-level pipe settings and screws up the FastCGI service.
  229. */
  230. static PACL prepare_named_pipe_acl(PSECURITY_DESCRIPTOR sd, LPSECURITY_ATTRIBUTES sa)
  231. {
  232. DWORD req_acl_size;
  233. char everyone_buf[32], owner_buf[32];
  234. PSID sid_everyone, sid_owner;
  235. SID_IDENTIFIER_AUTHORITY
  236. siaWorld = SECURITY_WORLD_SID_AUTHORITY,
  237. siaCreator = SECURITY_CREATOR_SID_AUTHORITY;
  238. PACL acl;
  239. sid_everyone = (PSID)&everyone_buf;
  240. sid_owner = (PSID)&owner_buf;
  241. req_acl_size = sizeof(ACL) +
  242. (2 * ((sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetSidLengthRequired(1)));
  243. acl = malloc(req_acl_size);
  244. if (acl == NULL) {
  245. return NULL;
  246. }
  247. if (!InitializeSid(sid_everyone, &siaWorld, 1)) {
  248. goto out_fail;
  249. }
  250. *GetSidSubAuthority(sid_everyone, 0) = SECURITY_WORLD_RID;
  251. if (!InitializeSid(sid_owner, &siaCreator, 1)) {
  252. goto out_fail;
  253. }
  254. *GetSidSubAuthority(sid_owner, 0) = SECURITY_CREATOR_OWNER_RID;
  255. if (!InitializeAcl(acl, req_acl_size, ACL_REVISION)) {
  256. goto out_fail;
  257. }
  258. if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, sid_everyone)) {
  259. goto out_fail;
  260. }
  261. if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, sid_owner)) {
  262. goto out_fail;
  263. }
  264. if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) {
  265. goto out_fail;
  266. }
  267. if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE)) {
  268. goto out_fail;
  269. }
  270. sa->lpSecurityDescriptor = sd;
  271. return acl;
  272. out_fail:
  273. free(acl);
  274. return NULL;
  275. }
  276. #endif
  277. static int is_port_number(const char *bindpath)
  278. {
  279. while (*bindpath) {
  280. if (*bindpath < '0' || *bindpath > '9') {
  281. return 0;
  282. }
  283. bindpath++;
  284. }
  285. return 1;
  286. }
  287. int fcgi_listen(const char *path, int backlog)
  288. {
  289. char *s;
  290. int tcp = 0;
  291. char host[MAXPATHLEN];
  292. short port = 0;
  293. int listen_socket;
  294. sa_t sa;
  295. socklen_t sock_len;
  296. #ifdef SO_REUSEADDR
  297. # ifdef _WIN32
  298. BOOL reuse = 1;
  299. # else
  300. int reuse = 1;
  301. # endif
  302. #endif
  303. if ((s = strchr(path, ':'))) {
  304. port = atoi(s+1);
  305. if (port != 0 && (s-path) < MAXPATHLEN) {
  306. strncpy(host, path, s-path);
  307. host[s-path] = '\0';
  308. tcp = 1;
  309. }
  310. } else if (is_port_number(path)) {
  311. port = atoi(path);
  312. if (port != 0) {
  313. host[0] = '\0';
  314. tcp = 1;
  315. }
  316. }
  317. /* Prepare socket address */
  318. if (tcp) {
  319. memset(&sa.sa_inet, 0, sizeof(sa.sa_inet));
  320. sa.sa_inet.sin_family = AF_INET;
  321. sa.sa_inet.sin_port = htons(port);
  322. sock_len = sizeof(sa.sa_inet);
  323. if (!*host || !strncmp(host, "*", sizeof("*")-1)) {
  324. sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY);
  325. } else {
  326. sa.sa_inet.sin_addr.s_addr = inet_addr(host);
  327. if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) {
  328. struct hostent *hep;
  329. hep = gethostbyname(host);
  330. if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
  331. fprintf(stderr, "Cannot resolve host name '%s'!\n", host);
  332. return -1;
  333. } else if (hep->h_addr_list[1]) {
  334. fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
  335. return -1;
  336. }
  337. sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr;
  338. }
  339. }
  340. } else {
  341. #ifdef _WIN32
  342. SECURITY_DESCRIPTOR sd;
  343. SECURITY_ATTRIBUTES sa;
  344. PACL acl;
  345. HANDLE namedPipe;
  346. memset(&sa, 0, sizeof(sa));
  347. sa.nLength = sizeof(sa);
  348. sa.bInheritHandle = FALSE;
  349. acl = prepare_named_pipe_acl(&sd, &sa);
  350. namedPipe = CreateNamedPipe(path,
  351. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  352. PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE,
  353. PIPE_UNLIMITED_INSTANCES,
  354. 8192, 8192, 0, &sa);
  355. if (namedPipe == INVALID_HANDLE_VALUE) {
  356. return -1;
  357. }
  358. listen_socket = _open_osfhandle((long)namedPipe, 0);
  359. if (!is_initialized) {
  360. fcgi_init();
  361. }
  362. is_fastcgi = 1;
  363. return listen_socket;
  364. #else
  365. int path_len = strlen(path);
  366. if (path_len >= sizeof(sa.sa_unix.sun_path)) {
  367. fprintf(stderr, "Listening socket's path name is too long.\n");
  368. return -1;
  369. }
  370. memset(&sa.sa_unix, 0, sizeof(sa.sa_unix));
  371. sa.sa_unix.sun_family = AF_UNIX;
  372. memcpy(sa.sa_unix.sun_path, path, path_len + 1);
  373. sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len;
  374. #ifdef HAVE_SOCKADDR_UN_SUN_LEN
  375. sa.sa_unix.sun_len = sock_len;
  376. #endif
  377. unlink(path);
  378. #endif
  379. }
  380. /* Create, bind socket and start listen on it */
  381. if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 ||
  382. #ifdef SO_REUSEADDR
  383. setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0 ||
  384. #endif
  385. bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
  386. listen(listen_socket, backlog) < 0) {
  387. fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
  388. return -1;
  389. }
  390. if (!tcp) {
  391. chmod(path, 0777);
  392. } else {
  393. char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
  394. char *cur, *end;
  395. int n;
  396. if (ip) {
  397. ip = strdup(ip);
  398. cur = ip;
  399. n = 0;
  400. while (*cur) {
  401. if (*cur == ',') n++;
  402. cur++;
  403. }
  404. allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
  405. n = 0;
  406. cur = ip;
  407. while (cur) {
  408. end = strchr(cur, ',');
  409. if (end) {
  410. *end = 0;
  411. end++;
  412. }
  413. allowed_clients[n] = inet_addr(cur);
  414. if (allowed_clients[n] == INADDR_NONE) {
  415. fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
  416. }
  417. n++;
  418. cur = end;
  419. }
  420. allowed_clients[n] = INADDR_NONE;
  421. free(ip);
  422. }
  423. }
  424. if (!is_initialized) {
  425. fcgi_init();
  426. }
  427. is_fastcgi = 1;
  428. #ifdef _WIN32
  429. if (tcp) {
  430. listen_socket = _open_osfhandle((long)listen_socket, 0);
  431. }
  432. #else
  433. fcgi_setup_signals();
  434. #endif
  435. return listen_socket;
  436. }
  437. void fcgi_init_request(fcgi_request *req, int listen_socket)
  438. {
  439. memset(req, 0, sizeof(fcgi_request));
  440. req->listen_socket = listen_socket;
  441. req->fd = -1;
  442. req->id = -1;
  443. req->in_len = 0;
  444. req->in_pad = 0;
  445. req->out_hdr = NULL;
  446. req->out_pos = req->out_buf;
  447. #ifdef _WIN32
  448. req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
  449. #endif
  450. }
  451. static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
  452. {
  453. int ret;
  454. size_t n = 0;
  455. do {
  456. errno = 0;
  457. #ifdef _WIN32
  458. if (!req->tcp) {
  459. ret = write(req->fd, ((char*)buf)+n, count-n);
  460. } else {
  461. ret = send(req->fd, ((char*)buf)+n, count-n, 0);
  462. if (ret <= 0) {
  463. errno = WSAGetLastError();
  464. }
  465. }
  466. #else
  467. ret = write(req->fd, ((char*)buf)+n, count-n);
  468. #endif
  469. if (ret > 0) {
  470. n += ret;
  471. } else if (ret <= 0 && errno != 0 && errno != EINTR) {
  472. return ret;
  473. }
  474. } while (n != count);
  475. return n;
  476. }
  477. static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count)
  478. {
  479. int ret;
  480. size_t n = 0;
  481. do {
  482. errno = 0;
  483. #ifdef _WIN32
  484. if (!req->tcp) {
  485. ret = read(req->fd, ((char*)buf)+n, count-n);
  486. } else {
  487. ret = recv(req->fd, ((char*)buf)+n, count-n, 0);
  488. if (ret <= 0) {
  489. errno = WSAGetLastError();
  490. }
  491. }
  492. #else
  493. ret = read(req->fd, ((char*)buf)+n, count-n);
  494. #endif
  495. if (ret > 0) {
  496. n += ret;
  497. } else if (ret == 0 && errno == 0) {
  498. return n;
  499. } else if (ret <= 0 && errno != 0 && errno != EINTR) {
  500. return ret;
  501. }
  502. } while (n != count);
  503. return n;
  504. }
  505. static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len)
  506. {
  507. int pad = ((len + 7) & ~7) - len;
  508. hdr->contentLengthB0 = (unsigned char)(len & 0xff);
  509. hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff);
  510. hdr->paddingLength = (unsigned char)pad;
  511. hdr->requestIdB0 = (unsigned char)(req_id & 0xff);
  512. hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff);
  513. hdr->reserved = 0;
  514. hdr->type = type;
  515. hdr->version = FCGI_VERSION_1;
  516. if (pad) {
  517. memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad);
  518. }
  519. return pad;
  520. }
  521. static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end)
  522. {
  523. char buf[128];
  524. char *tmp = buf;
  525. int buf_size = sizeof(buf);
  526. int name_len, val_len;
  527. char *s;
  528. int ret = 1;
  529. while (p < end) {
  530. name_len = *p++;
  531. if (name_len >= 128) {
  532. name_len = ((name_len & 0x7f) << 24);
  533. name_len |= (*p++ << 16);
  534. name_len |= (*p++ << 8);
  535. name_len |= *p++;
  536. }
  537. val_len = *p++;
  538. if (val_len >= 128) {
  539. val_len = ((val_len & 0x7f) << 24);
  540. val_len |= (*p++ << 16);
  541. val_len |= (*p++ << 8);
  542. val_len |= *p++;
  543. }
  544. if (name_len + val_len < 0 ||
  545. name_len + val_len > end - p) {
  546. /* Malformated request */
  547. ret = 0;
  548. break;
  549. }
  550. if (name_len+1 >= buf_size) {
  551. buf_size = name_len + 64;
  552. tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size));
  553. }
  554. memcpy(tmp, p, name_len);
  555. tmp[name_len] = 0;
  556. s = estrndup((char*)p + name_len, val_len);
  557. zend_hash_update(req->env, tmp, name_len+1, &s, sizeof(char*), NULL);
  558. p += name_len + val_len;
  559. }
  560. if (tmp != buf && tmp != NULL) {
  561. efree(tmp);
  562. }
  563. return ret;
  564. }
  565. static void fcgi_free_var(char **s)
  566. {
  567. efree(*s);
  568. }
  569. static int fcgi_read_request(fcgi_request *req)
  570. {
  571. fcgi_header hdr;
  572. int len, padding;
  573. unsigned char buf[FCGI_MAX_LENGTH+8];
  574. req->keep = 0;
  575. req->closed = 0;
  576. req->in_len = 0;
  577. req->out_hdr = NULL;
  578. req->out_pos = req->out_buf;
  579. ALLOC_HASHTABLE(req->env);
  580. zend_hash_init(req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 0);
  581. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  582. hdr.version < FCGI_VERSION_1) {
  583. return 0;
  584. }
  585. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  586. padding = hdr.paddingLength;
  587. while (hdr.type == FCGI_STDIN && len == 0) {
  588. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  589. hdr.version < FCGI_VERSION_1) {
  590. return 0;
  591. }
  592. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  593. padding = hdr.paddingLength;
  594. }
  595. if (len + padding > FCGI_MAX_LENGTH) {
  596. return 0;
  597. }
  598. req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;
  599. if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
  600. char *val;
  601. if (safe_read(req, buf, len+padding) != len+padding) {
  602. return 0;
  603. }
  604. req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);
  605. switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
  606. case FCGI_RESPONDER:
  607. val = estrdup("RESPONDER");
  608. zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
  609. break;
  610. case FCGI_AUTHORIZER:
  611. val = estrdup("AUTHORIZER");
  612. zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
  613. break;
  614. case FCGI_FILTER:
  615. val = estrdup("FILTER");
  616. zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
  617. break;
  618. default:
  619. return 0;
  620. }
  621. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  622. hdr.version < FCGI_VERSION_1) {
  623. return 0;
  624. }
  625. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  626. padding = hdr.paddingLength;
  627. while (hdr.type == FCGI_PARAMS && len > 0) {
  628. if (len + padding > FCGI_MAX_LENGTH) {
  629. return 0;
  630. }
  631. if (safe_read(req, buf, len+padding) != len+padding) {
  632. req->keep = 0;
  633. return 0;
  634. }
  635. if (!fcgi_get_params(req, buf, buf+len)) {
  636. req->keep = 0;
  637. return 0;
  638. }
  639. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  640. hdr.version < FCGI_VERSION_1) {
  641. req->keep = 0;
  642. return 0;
  643. }
  644. len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  645. padding = hdr.paddingLength;
  646. }
  647. } else if (hdr.type == FCGI_GET_VALUES) {
  648. unsigned char *p = buf + sizeof(fcgi_header);
  649. HashPosition pos;
  650. char * str_index;
  651. uint str_length;
  652. ulong num_index;
  653. int key_type;
  654. zval ** value;
  655. if (safe_read(req, buf, len+padding) != len+padding) {
  656. req->keep = 0;
  657. return 0;
  658. }
  659. if (!fcgi_get_params(req, buf, buf+len)) {
  660. req->keep = 0;
  661. return 0;
  662. }
  663. zend_hash_internal_pointer_reset_ex(req->env, &pos);
  664. while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
  665. int zlen;
  666. zend_hash_move_forward_ex(req->env, &pos);
  667. if (key_type != HASH_KEY_IS_STRING) {
  668. continue;
  669. }
  670. if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) {
  671. continue;
  672. }
  673. --str_length;
  674. zlen = Z_STRLEN_PP(value);
  675. if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) {
  676. break;
  677. }
  678. if (str_length < 0x80) {
  679. *p++ = str_length;
  680. } else {
  681. *p++ = ((str_length >> 24) & 0xff) | 0x80;
  682. *p++ = (str_length >> 16) & 0xff;
  683. *p++ = (str_length >> 8) & 0xff;
  684. *p++ = str_length & 0xff;
  685. }
  686. if (zlen < 0x80) {
  687. *p++ = zlen;
  688. } else {
  689. *p++ = ((zlen >> 24) & 0xff) | 0x80;
  690. *p++ = (zlen >> 16) & 0xff;
  691. *p++ = (zlen >> 8) & 0xff;
  692. *p++ = zlen & 0xff;
  693. }
  694. memcpy(p, str_index, str_length);
  695. p += str_length;
  696. memcpy(p, Z_STRVAL_PP(value), zlen);
  697. p += zlen;
  698. }
  699. len = p - buf - sizeof(fcgi_header);
  700. len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
  701. if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
  702. req->keep = 0;
  703. return 0;
  704. }
  705. return 0;
  706. } else {
  707. return 0;
  708. }
  709. return 1;
  710. }
  711. int fcgi_read(fcgi_request *req, char *str, int len)
  712. {
  713. int ret, n, rest;
  714. fcgi_header hdr;
  715. unsigned char buf[255];
  716. n = 0;
  717. rest = len;
  718. while (rest > 0) {
  719. if (req->in_len == 0) {
  720. if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
  721. hdr.version < FCGI_VERSION_1 ||
  722. hdr.type != FCGI_STDIN) {
  723. req->keep = 0;
  724. return 0;
  725. }
  726. req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
  727. req->in_pad = hdr.paddingLength;
  728. if (req->in_len == 0) {
  729. return n;
  730. }
  731. }
  732. if (req->in_len >= rest) {
  733. ret = safe_read(req, str, rest);
  734. } else {
  735. ret = safe_read(req, str, req->in_len);
  736. }
  737. if (ret < 0) {
  738. req->keep = 0;
  739. return ret;
  740. } else if (ret > 0) {
  741. req->in_len -= ret;
  742. rest -= ret;
  743. n += ret;
  744. str += ret;
  745. if (req->in_len == 0) {
  746. if (req->in_pad) {
  747. if (safe_read(req, buf, req->in_pad) != req->in_pad) {
  748. req->keep = 0;
  749. return ret;
  750. }
  751. }
  752. } else {
  753. return n;
  754. }
  755. } else {
  756. return n;
  757. }
  758. }
  759. return n;
  760. }
  761. static inline void fcgi_close(fcgi_request *req, int force, int destroy)
  762. {
  763. if (destroy && req->env) {
  764. zend_hash_destroy(req->env);
  765. FREE_HASHTABLE(req->env);
  766. req->env = NULL;
  767. }
  768. #ifdef _WIN32
  769. if (is_impersonate && !req->tcp) {
  770. RevertToSelf();
  771. }
  772. #endif
  773. if ((force || !req->keep) && req->fd >= 0) {
  774. #ifdef _WIN32
  775. if (!req->tcp) {
  776. HANDLE pipe = (HANDLE)_get_osfhandle(req->fd);
  777. if (!force) {
  778. FlushFileBuffers(pipe);
  779. }
  780. DisconnectNamedPipe(pipe);
  781. } else {
  782. if (!force) {
  783. char buf[8];
  784. shutdown(req->fd, 1);
  785. while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
  786. }
  787. closesocket(req->fd);
  788. }
  789. #else
  790. if (!force) {
  791. char buf[8];
  792. shutdown(req->fd, 1);
  793. while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
  794. }
  795. close(req->fd);
  796. #endif
  797. req->fd = -1;
  798. }
  799. }
  800. int fcgi_accept_request(fcgi_request *req)
  801. {
  802. #ifdef _WIN32
  803. HANDLE pipe;
  804. OVERLAPPED ov;
  805. #endif
  806. while (1) {
  807. if (req->fd < 0) {
  808. while (1) {
  809. if (in_shutdown) {
  810. return -1;
  811. }
  812. #ifdef _WIN32
  813. if (!req->tcp) {
  814. pipe = (HANDLE)_get_osfhandle(req->listen_socket);
  815. FCGI_LOCK(req->listen_socket);
  816. ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  817. if (!ConnectNamedPipe(pipe, &ov)) {
  818. errno = GetLastError();
  819. if (errno == ERROR_IO_PENDING) {
  820. while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) {
  821. if (in_shutdown) {
  822. CloseHandle(ov.hEvent);
  823. FCGI_UNLOCK(req->listen_socket);
  824. return -1;
  825. }
  826. }
  827. } else if (errno != ERROR_PIPE_CONNECTED) {
  828. }
  829. }
  830. CloseHandle(ov.hEvent);
  831. req->fd = req->listen_socket;
  832. FCGI_UNLOCK(req->listen_socket);
  833. } else {
  834. SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket);
  835. #else
  836. {
  837. int listen_socket = req->listen_socket;
  838. #endif
  839. sa_t sa;
  840. socklen_t len = sizeof(sa);
  841. FCGI_LOCK(req->listen_socket);
  842. req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
  843. FCGI_UNLOCK(req->listen_socket);
  844. if (req->fd >= 0 && allowed_clients) {
  845. int n = 0;
  846. int allowed = 0;
  847. while (allowed_clients[n] != INADDR_NONE) {
  848. if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
  849. allowed = 1;
  850. break;
  851. }
  852. n++;
  853. }
  854. if (!allowed) {
  855. fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
  856. closesocket(req->fd);
  857. req->fd = -1;
  858. continue;
  859. }
  860. }
  861. }
  862. #ifdef _WIN32
  863. if (req->fd < 0 && (in_shutdown || errno != EINTR)) {
  864. #else
  865. if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) {
  866. #endif
  867. return -1;
  868. }
  869. #ifdef _WIN32
  870. break;
  871. #else
  872. if (req->fd >= 0) {
  873. #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
  874. struct pollfd fds;
  875. int ret;
  876. fds.fd = req->fd;
  877. fds.events = POLLIN;
  878. fds.revents = 0;
  879. do {
  880. errno = 0;
  881. ret = poll(&fds, 1, 5000);
  882. } while (ret < 0 && errno == EINTR);
  883. if (ret > 0 && (fds.revents & POLLIN)) {
  884. break;
  885. }
  886. fcgi_close(req, 1, 0);
  887. #else
  888. if (req->fd < FD_SETSIZE) {
  889. struct timeval tv = {5,0};
  890. fd_set set;
  891. int ret;
  892. FD_ZERO(&set);
  893. FD_SET(req->fd, &set);
  894. do {
  895. errno = 0;
  896. ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0;
  897. } while (ret < 0 && errno == EINTR);
  898. if (ret > 0 && FD_ISSET(req->fd, &set)) {
  899. break;
  900. }
  901. fcgi_close(req, 1, 0);
  902. } else {
  903. fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
  904. fcgi_close(req, 1, 0);
  905. }
  906. #endif
  907. }
  908. #endif
  909. }
  910. } else if (in_shutdown) {
  911. return -1;
  912. }
  913. if (fcgi_read_request(req)) {
  914. #ifdef _WIN32
  915. if (is_impersonate && !req->tcp) {
  916. pipe = (HANDLE)_get_osfhandle(req->fd);
  917. if (!ImpersonateNamedPipeClient(pipe)) {
  918. fcgi_close(req, 1, 1);
  919. continue;
  920. }
  921. }
  922. #endif
  923. return req->fd;
  924. } else {
  925. fcgi_close(req, 1, 1);
  926. }
  927. }
  928. }
  929. static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type)
  930. {
  931. req->out_hdr = (fcgi_header*) req->out_pos;
  932. req->out_hdr->type = type;
  933. req->out_pos += sizeof(fcgi_header);
  934. return req->out_hdr;
  935. }
  936. static inline void close_packet(fcgi_request *req)
  937. {
  938. if (req->out_hdr) {
  939. int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header));
  940. req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len);
  941. req->out_hdr = NULL;
  942. }
  943. }
  944. int fcgi_flush(fcgi_request *req, int close)
  945. {
  946. int len;
  947. close_packet(req);
  948. len = req->out_pos - req->out_buf;
  949. if (close) {
  950. fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos);
  951. fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request));
  952. rec->body.appStatusB3 = 0;
  953. rec->body.appStatusB2 = 0;
  954. rec->body.appStatusB1 = 0;
  955. rec->body.appStatusB0 = 0;
  956. rec->body.protocolStatus = FCGI_REQUEST_COMPLETE;
  957. len += sizeof(fcgi_end_request_rec);
  958. }
  959. if (safe_write(req, req->out_buf, len) != len) {
  960. req->keep = 0;
  961. return 0;
  962. }
  963. req->out_pos = req->out_buf;
  964. return 1;
  965. }
  966. int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
  967. {
  968. int limit, rest;
  969. if (len <= 0) {
  970. return 0;
  971. }
  972. if (req->out_hdr && req->out_hdr->type != type) {
  973. close_packet(req);
  974. }
  975. #if 0
  976. /* Unoptimized, but clear version */
  977. rest = len;
  978. while (rest > 0) {
  979. limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
  980. if (!req->out_hdr) {
  981. if (limit < sizeof(fcgi_header)) {
  982. if (!fcgi_flush(req, 0)) {
  983. return -1;
  984. }
  985. }
  986. open_packet(req, type);
  987. }
  988. limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
  989. if (rest < limit) {
  990. memcpy(req->out_pos, str, rest);
  991. req->out_pos += rest;
  992. return len;
  993. } else {
  994. memcpy(req->out_pos, str, limit);
  995. req->out_pos += limit;
  996. rest -= limit;
  997. str += limit;
  998. if (!fcgi_flush(req, 0)) {
  999. return -1;
  1000. }
  1001. }
  1002. }
  1003. #else
  1004. /* Optimized version */
  1005. limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
  1006. if (!req->out_hdr) {
  1007. limit -= sizeof(fcgi_header);
  1008. if (limit < 0) limit = 0;
  1009. }
  1010. if (len < limit) {
  1011. if (!req->out_hdr) {
  1012. open_packet(req, type);
  1013. }
  1014. memcpy(req->out_pos, str, len);
  1015. req->out_pos += len;
  1016. } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) {
  1017. if (!req->out_hdr) {
  1018. open_packet(req, type);
  1019. }
  1020. if (limit > 0) {
  1021. memcpy(req->out_pos, str, limit);
  1022. req->out_pos += limit;
  1023. }
  1024. if (!fcgi_flush(req, 0)) {
  1025. return -1;
  1026. }
  1027. if (len > limit) {
  1028. open_packet(req, type);
  1029. memcpy(req->out_pos, str + limit, len - limit);
  1030. req->out_pos += len - limit;
  1031. }
  1032. } else {
  1033. int pos = 0;
  1034. int pad;
  1035. close_packet(req);
  1036. while ((len - pos) > 0xffff) {
  1037. open_packet(req, type);
  1038. fcgi_make_header(req->out_hdr, type, req->id, 0xfff8);
  1039. req->out_hdr = NULL;
  1040. if (!fcgi_flush(req, 0)) {
  1041. return -1;
  1042. }
  1043. if (safe_write(req, str + pos, 0xfff8) != 0xfff8) {
  1044. req->keep = 0;
  1045. return -1;
  1046. }
  1047. pos += 0xfff8;
  1048. }
  1049. pad = (((len - pos) + 7) & ~7) - (len - pos);
  1050. rest = pad ? 8 - pad : 0;
  1051. open_packet(req, type);
  1052. fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest);
  1053. req->out_hdr = NULL;
  1054. if (!fcgi_flush(req, 0)) {
  1055. return -1;
  1056. }
  1057. if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) {
  1058. req->keep = 0;
  1059. return -1;
  1060. }
  1061. if (pad) {
  1062. open_packet(req, type);
  1063. memcpy(req->out_pos, str + len - rest, rest);
  1064. req->out_pos += rest;
  1065. }
  1066. }
  1067. #endif
  1068. return len;
  1069. }
  1070. int fcgi_finish_request(fcgi_request *req, int force_close)
  1071. {
  1072. int ret = 1;
  1073. if (req->fd >= 0) {
  1074. if (!req->closed) {
  1075. ret = fcgi_flush(req, 1);
  1076. req->closed = 1;
  1077. }
  1078. fcgi_close(req, force_close, 1);
  1079. }
  1080. return ret;
  1081. }
  1082. char* fcgi_getenv(fcgi_request *req, const char* var, int var_len)
  1083. {
  1084. char **val;
  1085. if (!req) return NULL;
  1086. if (zend_hash_find(req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) {
  1087. return *val;
  1088. }
  1089. return NULL;
  1090. }
  1091. char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val)
  1092. {
  1093. if (var && req) {
  1094. if (val == NULL) {
  1095. zend_hash_del(req->env, var, var_len+1);
  1096. } else {
  1097. char **ret;
  1098. val = estrdup(val);
  1099. if (zend_hash_update(req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) {
  1100. return *ret;
  1101. }
  1102. }
  1103. }
  1104. return NULL;
  1105. }
  1106. #ifdef _WIN32
  1107. void fcgi_impersonate(void)
  1108. {
  1109. char *os_name;
  1110. os_name = getenv("OS");
  1111. if (os_name && stricmp(os_name, "Windows_NT") == 0) {
  1112. is_impersonate = 1;
  1113. }
  1114. }
  1115. #endif
  1116. void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len)
  1117. {
  1118. zval * zvalue;
  1119. zvalue = pemalloc(sizeof(*zvalue), 1);
  1120. Z_TYPE_P(zvalue) = IS_STRING;
  1121. Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1);
  1122. Z_STRLEN_P(zvalue) = value_len;
  1123. zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL);
  1124. }
  1125. void fcgi_free_mgmt_var_cb(void * ptr)
  1126. {
  1127. zval ** var = (zval **)ptr;
  1128. pefree(Z_STRVAL_PP(var), 1);
  1129. pefree(*var, 1);
  1130. }
  1131. /*
  1132. * Local variables:
  1133. * tab-width: 4
  1134. * c-basic-offset: 4
  1135. * End:
  1136. * vim600: sw=4 ts=4 fdm=marker
  1137. * vim<600: sw=4 ts=4
  1138. */