1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2014 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 at 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 | Author: George Wang <gwang@litespeedtech.com> |
16 +----------------------------------------------------------------------+
17 */
18
19 /*
20 Copyright (c) 2002-2014, Lite Speed Technologies Inc.
21 All rights reserved.
22
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions are
25 met:
26
27 * Redistributions of source code must retain the above copyright
28 notice, this list of conditions and the following disclaimer.
29 * Redistributions in binary form must reproduce the above
30 copyright notice, this list of conditions and the following
31 disclaimer in the documentation and/or other materials provided
32 with the distribution.
33 * Neither the name of the Lite Speed Technologies Inc nor the
34 names of its contributors may be used to endorse or promote
35 products derived from this software without specific prior
36 written permission.
37
38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 */
50
51
52 #include <ctype.h>
53 #include <dlfcn.h>
54 #include <errno.h>
55 #include <fcntl.h>
56
57 #include <sys/stat.h>
58 #include <signal.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <string.h>
62 #include <sys/mman.h>
63 #include <sys/resource.h>
64 #include <sys/socket.h>
65 #include <sys/time.h>
66 #include <sys/uio.h>
67 #include <sys/wait.h>
68 #include <grp.h>
69 #include <pwd.h>
70 #include <time.h>
71 #include <unistd.h>
72 #include <arpa/inet.h>
73 #include <netdb.h>
74 #include <netinet/in.h>
75 #include <netinet/tcp.h>
76 #include <sys/un.h>
77
78 #include "lsapilib.h"
79
80 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
81 #include <sys/prctl.h>
82 #endif
83
84 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
85 || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
86 #include <sys/sysctl.h>
87 #endif
88
89 #include <inttypes.h>
90 #ifndef uint32
91 #define uint32 uint32_t
92 #endif
93
94 struct lsapi_MD5Context {
95 uint32 buf[4];
96 uint32 bits[2];
97 unsigned char in[64];
98 };
99
100 void lsapi_MD5Init(struct lsapi_MD5Context *context);
101 void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
102 unsigned len);
103 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
104
105 /*
106 * This is needed to make RSAREF happy on some MS-DOS compilers.
107 */
108 typedef struct lsapi_MD5Context lsapi_MD5_CTX;
109
110
111 #define LSAPI_ST_REQ_HEADER 1
112 #define LSAPI_ST_REQ_BODY 2
113 #define LSAPI_ST_RESP_HEADER 4
114 #define LSAPI_ST_RESP_BODY 8
115
116 #define LSAPI_RESP_BUF_SIZE 8192
117 #define LSAPI_INIT_RESP_HEADER_LEN 4096
118
119
120
121 static int g_inited = 0;
122 static int g_running = 1;
123 static int s_ppid;
124 static int s_slow_req_msecs = 0;
125 static int s_keepListener = 0;
126 static int s_dump_debug_info = 0;
127 static int s_pid_dump_debug_info = 0;
128
129 LSAPI_Request g_req = { -1, -1 };
130
131 static char s_pSecret[24];
132
133
134 void Flush_RespBuf_r( LSAPI_Request * pReq );
135
136 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
137 {
138 "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
139 "HTTP_ACCEPT_ENCODING",
140 "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
141 "HTTP_CONNECTION", "CONTENT_TYPE",
142 "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
143 "HTTP_HOST", "HTTP_PRAGMA",
144 "HTTP_REFERER", "HTTP_USER_AGENT",
145 "HTTP_CACHE_CONTROL",
146 "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
147 "HTTP_IF_NONE_MATCH",
148 "HTTP_IF_RANGE",
149 "HTTP_IF_UNMODIFIED_SINCE",
150 "HTTP_KEEP_ALIVE",
151 "HTTP_RANGE",
152 "HTTP_X_FORWARDED_FOR",
153 "HTTP_VIA",
154 "HTTP_TRANSFER_ENCODING"
155 };
156
157 static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
158 { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
159 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
160
161
162 static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
163 {
164 "Accept", "Accept-Charset",
165 "Accept-Encoding",
166 "Accept-Language", "Authorization",
167 "Connection", "Content-Type",
168 "Content-Length", "Cookie", "Cookie2",
169 "Host", "Pragma",
170 "Referer", "User-Agent",
171 "Cache-Control",
172 "If-Modified-Since", "If-Match",
173 "If-None-Match",
174 "If-Range",
175 "If-Unmodified-Since",
176 "Keep-Alive",
177 "Range",
178 "X-Forwarded-For",
179 "Via",
180 "Transfer-Encoding"
181 };
182
183 static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
184 { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
185 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
186 };
187
lsapi_sigpipe(int sig)188 static void lsapi_sigpipe( int sig )
189 {
190 }
lsapi_siguser1(int sig)191 static void lsapi_siguser1( int sig )
192 {
193 g_running = 0;
194 }
195
196 #ifndef sighandler_t
197 typedef void (*sighandler_t)(int);
198 #endif
199
lsapi_signal(int signo,sighandler_t handler)200 static void lsapi_signal(int signo, sighandler_t handler)
201 {
202 struct sigaction sa;
203
204 sigaction(signo, NULL, &sa);
205
206 if (sa.sa_handler == SIG_DFL)
207 {
208 sigemptyset(&sa.sa_mask);
209 sa.sa_flags = 0;
210 sa.sa_handler = handler;
211 sigaction(signo, &sa, NULL);
212 }
213 }
214
215
216 static int s_enable_core_dump = 0;
lsapi_enable_core_dump()217 static void lsapi_enable_core_dump()
218 {
219 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
220 || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
221 int mib[2];
222 size_t len;
223
224 len = 2;
225 if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
226 {
227 len = sizeof(s_enable_core_dump);
228 if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
229 perror( "sysctl: Failed to set 'kern.sugid_coredump', "
230 "core dump may not be available!");
231 }
232
233
234 #endif
235
236 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
237 if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
238 perror( "prctl: Failed to set dumpable, "
239 "core dump may not be available!");
240 #endif
241 }
242
243
lsapi_buildPacketHeader(struct lsapi_packet_header * pHeader,char type,int len)244 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
245 char type, int len )
246 {
247 pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */
248 pHeader->m_versionB1 = LSAPI_VERSION_B1;
249 pHeader->m_type = type;
250 pHeader->m_flag = LSAPI_ENDIAN;
251 pHeader->m_packetLen.m_iLen = len;
252 }
253
lsapi_set_nblock(int fd,int nonblock)254 static int lsapi_set_nblock( int fd, int nonblock )
255 {
256 int val = fcntl( fd, F_GETFL, 0 );
257 if ( nonblock )
258 {
259 if (!( val & O_NONBLOCK ))
260 {
261 return fcntl( fd, F_SETFL, val | O_NONBLOCK );
262 }
263 }
264 else
265 {
266 if ( val & O_NONBLOCK )
267 {
268 return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
269 }
270 }
271 return 0;
272 }
273
lsapi_close(int fd)274 static int lsapi_close( int fd )
275 {
276 int ret;
277 while( 1 )
278 {
279 ret = close( fd );
280 if (( ret == -1 )&&( errno == EINTR )&&(g_running))
281 continue;
282 return ret;
283 }
284 }
285
lsapi_read(int fd,void * pBuf,size_t len)286 static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
287 {
288 ssize_t ret;
289 while( 1 )
290 {
291 ret = read( fd, (char *)pBuf, len );
292 if (( ret == -1 )&&( errno == EINTR )&&(g_running))
293 continue;
294 return ret;
295 }
296 }
297
298 /*
299 static int lsapi_write( int fd, const void * pBuf, int len )
300 {
301 int ret;
302 const char * pCur;
303 const char * pEnd;
304 if ( len == 0 )
305 return 0;
306 pCur = (const char *)pBuf;
307 pEnd = pCur + len;
308 while( g_running && (pCur < pEnd) )
309 {
310 ret = write( fd, pCur, pEnd - pCur );
311 if ( ret >= 0)
312 pCur += ret;
313 else if (( ret == -1 )&&( errno != EINTR ))
314 return ret;
315 }
316 return pCur - (const char *)pBuf;
317 }
318 */
319
lsapi_writev(int fd,struct iovec ** pVec,int count,int totalLen)320 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
321 {
322 int ret;
323 int left = totalLen;
324 int n = count;
325 while(( left > 0 )&&g_running )
326 {
327 ret = writev( fd, *pVec, n );
328 if ( ret > 0 )
329 {
330 left -= ret;
331 if (( left <= 0)||( !g_running ))
332 return totalLen - left;
333 while( ret > 0 )
334 {
335 if ( (*pVec)->iov_len <= (unsigned int )ret )
336 {
337 ret -= (*pVec)->iov_len;
338 ++(*pVec);
339 }
340 else
341 {
342 (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
343 (*pVec)->iov_len -= ret;
344 break;
345 }
346 }
347 }
348 else if ( ret == -1 )
349 {
350 if ( errno == EAGAIN )
351 {
352 if ( totalLen - left > 0 )
353 return totalLen - left;
354 else
355 return -1;
356 }
357 else if ( errno != EINTR )
358 return ret;
359 }
360 }
361 return totalLen - left;
362 }
363
364 /*
365 static int getTotalLen( struct iovec * pVec, int count )
366 {
367 struct iovec * pEnd = pVec + count;
368 int total = 0;
369 while( pVec < pEnd )
370 {
371 total += pVec->iov_len;
372 ++pVec;
373 }
374 return total;
375 }
376 */
377
allocateBuf(LSAPI_Request * pReq,int size)378 static inline int allocateBuf( LSAPI_Request * pReq, int size )
379 {
380 char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
381 if ( pBuf )
382 {
383 pReq->m_pReqBuf = pBuf;
384 pReq->m_reqBufSize = size;
385 pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
386 return 0;
387 }
388 return -1;
389 }
390
391
allocateIovec(LSAPI_Request * pReq,int n)392 static int allocateIovec( LSAPI_Request * pReq, int n )
393 {
394 struct iovec * p = (struct iovec *)realloc(
395 pReq->m_pIovec, sizeof(struct iovec) * n );
396 if ( !p )
397 return -1;
398 pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
399 pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
400 pReq->m_pIovec = p;
401 pReq->m_pIovecEnd = p + n;
402 return 0;
403 }
404
allocateRespHeaderBuf(LSAPI_Request * pReq,int size)405 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
406 {
407 char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
408 if ( !p )
409 return -1;
410 pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
411 pReq->m_pRespHeaderBuf = p;
412 pReq->m_pRespHeaderBufEnd = p + size;
413 return 0;
414 }
415
416
verifyHeader(struct lsapi_packet_header * pHeader,char pktType)417 static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
418 {
419 if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
420 ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
421 ( pktType != pHeader->m_type ))
422 return -1;
423 if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
424 {
425 register char b;
426 b = pHeader->m_packetLen.m_bytes[0];
427 pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
428 pHeader->m_packetLen.m_bytes[3] = b;
429 b = pHeader->m_packetLen.m_bytes[1];
430 pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
431 pHeader->m_packetLen.m_bytes[2] = b;
432 }
433 return pHeader->m_packetLen.m_iLen;
434 }
435
allocateEnvList(struct LSAPI_key_value_pair ** pEnvList,int * curSize,int newSize)436 static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
437 int *curSize, int newSize )
438 {
439 struct LSAPI_key_value_pair * pBuf;
440 if ( *curSize >= newSize )
441 return 0;
442 if ( newSize > 8192 )
443 return -1;
444 pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
445 sizeof(struct LSAPI_key_value_pair) );
446 if ( pBuf )
447 {
448 *pEnvList = pBuf;
449 *curSize = newSize;
450 return 0;
451 }
452 else
453 return -1;
454
455 }
456
isPipe(int fd)457 static inline int isPipe( int fd )
458 {
459 char achPeer[128];
460 socklen_t len = 128;
461 if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
462 ( errno == ENOTCONN ))
463 return 0;
464 else
465 return 1;
466 }
467
parseEnv(struct LSAPI_key_value_pair * pEnvList,int count,char ** pBegin,char * pEnd)468 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
469 char **pBegin, char * pEnd )
470 {
471 struct LSAPI_key_value_pair * pEnvEnd;
472 int keyLen = 0, valLen = 0;
473 if ( count > 8192 )
474 return -1;
475 pEnvEnd = pEnvList + count;
476 while( pEnvList != pEnvEnd )
477 {
478 if ( pEnd - *pBegin < 4 )
479 return -1;
480 keyLen = *((unsigned char *)((*pBegin)++));
481 keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
482 valLen = *((unsigned char *)((*pBegin)++));
483 valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
484 if ( *pBegin + keyLen + valLen > pEnd )
485 return -1;
486 if (( !keyLen )||( !valLen ))
487 return -1;
488
489 pEnvList->pKey = *pBegin;
490 *pBegin += keyLen;
491 pEnvList->pValue = *pBegin;
492 *pBegin += valLen;
493
494 pEnvList->keyLen = keyLen - 1;
495 pEnvList->valLen = valLen - 1;
496 ++pEnvList;
497 }
498 if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
499 return -1;
500 *pBegin += 4;
501 return 0;
502 }
503
swapIntEndian(int * pInteger)504 static inline void swapIntEndian( int * pInteger )
505 {
506 char * p = (char *)pInteger;
507 register char b;
508 b = p[0];
509 p[0] = p[3];
510 p[3] = b;
511 b = p[1];
512 p[1] = p[2];
513 p[2] = b;
514
515 }
516
fixEndian(LSAPI_Request * pReq)517 static inline void fixEndian( LSAPI_Request * pReq )
518 {
519 struct lsapi_req_header *p= pReq->m_pHeader;
520 swapIntEndian( &p->m_httpHeaderLen );
521 swapIntEndian( &p->m_reqBodyLen );
522 swapIntEndian( &p->m_scriptFileOff );
523 swapIntEndian( &p->m_scriptNameOff );
524 swapIntEndian( &p->m_queryStringOff );
525 swapIntEndian( &p->m_requestMethodOff );
526 swapIntEndian( &p->m_cntUnknownHeaders );
527 swapIntEndian( &p->m_cntEnv );
528 swapIntEndian( &p->m_cntSpecialEnv );
529 }
530
fixHeaderIndexEndian(LSAPI_Request * pReq)531 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
532 {
533 int i;
534 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
535 {
536 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
537 {
538 register char b;
539 char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
540 b = p[0];
541 p[0] = p[1];
542 p[1] = b;
543 swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
544 }
545 }
546 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
547 {
548 struct lsapi_header_offset * pCur, *pEnd;
549 pCur = pReq->m_pUnknownHeader;
550 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
551 while( pCur < pEnd )
552 {
553 swapIntEndian( &pCur->nameOff );
554 swapIntEndian( &pCur->nameLen );
555 swapIntEndian( &pCur->valueOff );
556 swapIntEndian( &pCur->valueLen );
557 ++pCur;
558 }
559 }
560 }
561
562 static uid_t s_uid = 0;
563 static uid_t s_defaultUid; //web server need set this
564 static gid_t s_defaultGid;
565
566 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
567
568 #define LSAPI_LVE_DISABLED 0
569 #define LSAPI_LVE_ENABLED 1
570 #define LSAPI_CAGEFS_ENABLED 2
571 #define LSAPI_CAGEFS_NO_SUEXEC 3
572 struct liblve;
573 static int s_enable_lve = LSAPI_LVE_DISABLED;
574 static struct liblve * s_lve = NULL;
575
576 static void *s_liblve;
577 static int (*fp_lve_is_available)(void) = NULL;
578 static int (*fp_lve_instance_init)(struct liblve *) = NULL;
579 static int (*fp_lve_destroy)(struct liblve *) = NULL;
580 static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
581 static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
582 static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
lsapi_load_lve_lib()583 static int lsapi_load_lve_lib()
584 {
585 s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
586 if (s_liblve)
587 {
588 fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
589 if (dlerror() == NULL)
590 {
591 if ( !(*fp_lve_is_available)() )
592 {
593 int uid = getuid();
594 if ( uid )
595 {
596 setreuid( s_uid, uid );
597 if ( !(*fp_lve_is_available)() )
598 s_enable_lve = 0;
599 setreuid( uid, s_uid );
600 }
601 }
602 }
603 }
604 else
605 {
606 s_enable_lve = LSAPI_LVE_DISABLED;
607 }
608 return (s_liblve)? 0 : -1;
609 }
610
init_lve_ex()611 static int init_lve_ex()
612 {
613 int rc;
614 if ( !s_liblve )
615 return -1;
616 fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
617 fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
618 fp_lve_enter = dlsym(s_liblve, "lve_enter");
619 fp_lve_leave = dlsym(s_liblve, "lve_leave");
620 if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
621 fp_lve_jail = dlsym(s_liblve, "jail" );
622
623 if ( s_lve == NULL )
624 {
625 rc = (*fp_lve_instance_init)(NULL);
626 s_lve = malloc(rc);
627 }
628 rc = (*fp_lve_instance_init)(s_lve);
629 if (rc != 0)
630 {
631 perror( "LSAPI: Unable to initialize LVE" );
632 free( s_lve );
633 s_lve = NULL;
634 return -1;
635 }
636 return 0;
637
638 }
639
640 #endif
641
642
643
readSecret(const char * pSecretFile)644 static int readSecret( const char * pSecretFile )
645 {
646 struct stat st;
647 int fd = open( pSecretFile, O_RDONLY , 0600 );
648 if ( fd == -1 )
649 {
650 fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile );
651 return -1;
652 }
653 if ( fstat( fd, &st ) == -1 )
654 {
655 fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile );
656 close( fd );
657 return -1;
658 }
659 /*
660 if ( st.st_uid != s_uid )
661 {
662 fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile );
663 close( fd );
664 return -1;
665 }
666 */
667 if ( st.st_mode & 0077 )
668 {
669 fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile );
670 close( fd );
671 return -1;
672 }
673 if ( read( fd, s_pSecret, 16 ) < 16 )
674 {
675 fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
676 close( fd );
677 return -1;
678 }
679 close( fd );
680 return 0;
681 }
682
LSAPI_is_suEXEC_Daemon()683 int LSAPI_is_suEXEC_Daemon()
684 {
685 if (( !s_uid )&&( s_pSecret[0] ))
686 return 1;
687 else
688 return 0;
689 }
690
LSAPI_perror_r(LSAPI_Request * pReq,const char * pErr1,const char * pErr2)691 static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
692 {
693 char achError[1024];
694 int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
695 if ( pReq )
696 LSAPI_Write_Stderr_r( pReq, achError, n );
697 else
698 write( STDERR_FILENO, achError, n );
699 return 0;
700 }
701
lsapi_lve_error(LSAPI_Request * pReq)702 static int lsapi_lve_error( LSAPI_Request * pReq )
703 {
704 static const char * headers[] =
705 {
706 "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
707 "Pragma: no-cache",
708 "Retry-After: 60",
709 "Content-Type: text/html",
710 NULL
711 };
712 static const char achBody[] =
713 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
714 "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
715 "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
716 "The website is temporarily unable to service your request as it exceeded resource limit.\n"
717 "Please try again later.\n"
718 "<HR>\n"
719 "</BODY></HTML>\n";
720
721 LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
722 return 0;
723 }
724
lsapi_enterLVE(LSAPI_Request * pReq,uid_t uid)725 static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
726 {
727 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
728 if ( s_lve && uid ) //root user should not do that
729 {
730 uint32_t cookie;
731 int ret = -1;
732 ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
733 if ( ret < 0 )
734 {
735 fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret );
736 LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
737 lsapi_lve_error( pReq );
738 return -1;
739 }
740 }
741 #endif
742
743 return 0;
744 }
745
lsapi_jailLVE(LSAPI_Request * pReq,uid_t uid,struct passwd * pw)746 static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
747 {
748 int ret = 0;
749 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
750 char error_msg[1024] = "";
751 ret = (*fp_lve_jail)( pw, error_msg );
752 if ( ret < 0 )
753 {
754 fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n",
755 getpid(), uid, ret, error_msg );
756 LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
757 return -1;
758 }
759 #endif
760 return ret;
761 }
762
763
764 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
lsapi_initLVE()765 static int lsapi_initLVE()
766 {
767 const char * pEnv;
768 if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
769 {
770 s_enable_lve = atol( pEnv );
771 pEnv = NULL;
772 }
773 else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
774 {
775 s_enable_lve = atol( pEnv );
776 pEnv = NULL;
777 }
778 if ( s_enable_lve && !s_uid )
779 {
780 lsapi_load_lve_lib();
781 if ( s_enable_lve )
782 {
783 return init_lve_ex();
784 }
785
786 }
787 return 0;
788 }
789 #endif
790
791
setUID_LVE(LSAPI_Request * pReq,uid_t uid,gid_t gid,const char * pChroot)792 static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
793 {
794 int rv;
795 struct passwd * pw;
796 pw = getpwuid( uid );
797 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
798 if ( s_lve )
799 {
800 if( lsapi_enterLVE( pReq, uid ) == -1 )
801 return -1;
802 if ( pw && fp_lve_jail)
803 {
804 rv = lsapi_jailLVE( pReq, uid, pw );
805 if ( rv == -1 )
806 return -1;
807 if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC
808 {
809 uid = s_defaultUid;
810 gid = s_defaultGid;
811 pw = getpwuid( uid );
812 }
813 }
814 }
815 #endif
816 //if ( !uid || !gid ) //do not allow root
817 //{
818 // return -1;
819 //}
820
821 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
822 || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
823 if ( s_enable_core_dump )
824 lsapi_enable_core_dump();
825 #endif
826
827 rv = setgid(gid);
828 if (rv == -1)
829 {
830 LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
831 return -1;
832 }
833 if ( pw && (pw->pw_gid == gid ))
834 {
835 rv = initgroups( pw->pw_name, gid );
836 if (rv == -1)
837 {
838 LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
839 return -1;
840 }
841 }
842 else
843 {
844 rv = setgroups(1, &gid);
845 if (rv == -1)
846 {
847 LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
848 }
849 }
850 if ( pChroot )
851 {
852 rv = chroot( pChroot );
853 if ( rv == -1 )
854 {
855 LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
856 return -1;
857 }
858 }
859 rv = setuid(uid);
860 if (rv == -1)
861 {
862 LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
863 return -1;
864 }
865 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
866 if ( s_enable_core_dump )
867 lsapi_enable_core_dump();
868 #endif
869 return 0;
870 }
871
lsapi_suexec_auth(LSAPI_Request * pReq,char * pAuth,int len,char * pUgid,int ugidLen)872 static int lsapi_suexec_auth( LSAPI_Request *pReq,
873 char * pAuth, int len, char * pUgid, int ugidLen )
874 {
875 lsapi_MD5_CTX md5ctx;
876 unsigned char achMD5[16];
877 if ( len < 32 )
878 return -1;
879 memmove( achMD5, pAuth + 16, 16 );
880 memmove( pAuth + 16, s_pSecret, 16 );
881 lsapi_MD5Init( &md5ctx );
882 lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
883 lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
884 lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
885 if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
886 return 0;
887 return 1;
888 }
889
890
lsapi_changeUGid(LSAPI_Request * pReq)891 static int lsapi_changeUGid( LSAPI_Request * pReq )
892 {
893 int uid = s_defaultUid;
894 int gid = s_defaultGid;
895 const char * pChroot = NULL;
896 struct LSAPI_key_value_pair * pEnv;
897 struct LSAPI_key_value_pair * pAuth;
898 int i;
899 if ( s_uid )
900 return 0;
901 //with special ID 0x00
902 //authenticate the suEXEC request;
903 //first one should be MD5( nonce + lscgid secret )
904 //remember to clear the secret after verification
905 //it should be set at the end of special env
906 i = pReq->m_pHeader->m_cntSpecialEnv - 1;
907 if ( i >= 0 )
908 {
909 pEnv = pReq->m_pSpecialEnvList + i;
910 if (( *pEnv->pKey == '\000' )&&
911 ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
912 {
913 --pReq->m_pHeader->m_cntSpecialEnv;
914 pAuth = pEnv--;
915 if (( *pEnv->pKey == '\000' )&&
916 ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
917 {
918 --pReq->m_pHeader->m_cntSpecialEnv;
919 uid = *(uint32_t *)pEnv->pValue;
920 gid = *(((uint32_t *)pEnv->pValue) + 1 );
921 //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
922 }
923 else
924 {
925 fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" );
926 pEnv = NULL;
927 }
928 if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
929 {
930 //read UID, GID from specialEnv
931
932 }
933 else
934 {
935 //authentication error
936 fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
937 uid = 0;
938 }
939 }
940 else
941 {
942 //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" );
943 }
944 }
945
946
947 if ( !uid )
948 {
949 uid = s_defaultUid;
950 gid = s_defaultGid;
951 }
952
953 //change uid
954 if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
955 {
956 return -1;
957 }
958
959 s_uid = uid;
960
961 return 0;
962
963 }
964
parseContentLenFromHeader(LSAPI_Request * pReq)965 static int parseContentLenFromHeader(LSAPI_Request * pReq)
966 {
967 const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
968 if ( pContentLen )
969 pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
970 return 0;
971 }
972
973
parseRequest(LSAPI_Request * pReq,int totalLen)974 static int parseRequest( LSAPI_Request * pReq, int totalLen )
975 {
976 int shouldFixEndian;
977 char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
978 char * pEnd = pReq->m_pReqBuf + totalLen;
979 shouldFixEndian = ( LSAPI_ENDIAN != (
980 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
981 if ( shouldFixEndian )
982 {
983 fixEndian( pReq );
984 }
985 if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
986 allocateEnvList( &pReq->m_pSpecialEnvList,
987 &pReq->m_specialEnvListSize,
988 pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
989 return -1;
990 if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
991 allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
992 pReq->m_pHeader->m_cntEnv ) == -1 )
993 return -1;
994
995 if ( parseEnv( pReq->m_pSpecialEnvList,
996 pReq->m_pHeader->m_cntSpecialEnv,
997 &pBegin, pEnd ) == -1 )
998 return -1;
999 if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1000 &pBegin, pEnd ) == -1 )
1001 return -1;
1002
1003 pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1004 pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1005 pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1006 pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1007
1008 pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1009 pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1010 pBegin += sizeof( struct lsapi_http_header_index );
1011
1012 pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1013 pBegin += sizeof( struct lsapi_header_offset) *
1014 pReq->m_pHeader->m_cntUnknownHeaders;
1015
1016 pReq->m_pHttpHeader = pBegin;
1017 pBegin += pReq->m_pHeader->m_httpHeaderLen;
1018 if ( pBegin != pEnd )
1019 {
1020 fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen,
1021 pBegin - pReq->m_pReqBuf );
1022 return -1;
1023 }
1024 if ( shouldFixEndian )
1025 {
1026 fixHeaderIndexEndian( pReq );
1027 }
1028 pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1029 if ( pReq->m_reqBodyLen == -2 )
1030 {
1031 parseContentLenFromHeader(pReq);
1032 }
1033
1034 return 0;
1035 }
1036
1037 //OPTIMIZATION
1038 static char s_accept_notify = 0;
1039 static char s_schedule_notify = 0;
1040 static char s_notify_scheduled = 0;
1041 static char s_notified_pid = 0;
1042
1043 static struct lsapi_packet_header s_ack = {'L', 'S',
1044 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1045
1046
write_req_received_notification(int fd)1047 static inline int write_req_received_notification( int fd )
1048 {
1049 if ( write( fd, &s_ack, LSAPI_PACKET_HEADER_LEN )
1050 < LSAPI_PACKET_HEADER_LEN )
1051 return -1;
1052 return 0;
1053 }
1054
lsapi_sigalarm(int sig)1055 static void lsapi_sigalarm( int sig )
1056 {
1057 if ( s_notify_scheduled )
1058 {
1059 s_notify_scheduled = 0;
1060 if ( g_req.m_fd != -1 )
1061 write_req_received_notification( g_req.m_fd );
1062 }
1063 }
1064
lsapi_schedule_notify()1065 static inline int lsapi_schedule_notify()
1066 {
1067 if ( !s_notify_scheduled )
1068 {
1069 alarm( 2 );
1070 s_notify_scheduled = 1;
1071 }
1072 return 0;
1073 }
1074
notify_req_received(int fd)1075 static inline int notify_req_received( int fd )
1076 {
1077 if ( s_schedule_notify )
1078 return lsapi_schedule_notify();
1079 return write_req_received_notification( fd );
1080
1081 }
1082
1083
lsapi_notify_pid(int fd)1084 static inline int lsapi_notify_pid( int fd )
1085 {
1086 char achBuf[16];
1087 lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1088 8 + LSAPI_PACKET_HEADER_LEN );
1089 memmove( &achBuf[8], "\0PID", 4 );
1090 *((int *)&achBuf[12]) = getpid();
1091
1092 if ( write( fd, achBuf, 16 ) < 16 )
1093 return -1;
1094 return 0;
1095 }
1096
1097 static char s_conn_key_packet[16];
init_conn_key(int fd)1098 static inline int init_conn_key( int fd )
1099 {
1100 struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
1101 struct timeval tv;
1102 int i;
1103 gettimeofday( &tv, NULL );
1104 srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
1105 for( i = 8; i < 16; ++i )
1106 {
1107 s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
1108 }
1109 lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
1110 8 + LSAPI_PACKET_HEADER_LEN );
1111 if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
1112 < LSAPI_PACKET_HEADER_LEN+8 )
1113 return -1;
1114 return 0;
1115
1116
1117 }
1118
readReq(LSAPI_Request * pReq)1119 static int readReq( LSAPI_Request * pReq )
1120 {
1121 int len;
1122 int packetLen;
1123 if ( !pReq )
1124 return -1;
1125 if ( pReq->m_reqBufSize < 8192 )
1126 {
1127 if ( allocateBuf( pReq, 8192 ) == -1 )
1128 return -1;
1129 }
1130
1131 while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1132 {
1133 len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1134 if ( len <= 0 )
1135 return -1;
1136 pReq->m_bufRead += len;
1137 }
1138 pReq->m_reqState = LSAPI_ST_REQ_HEADER;
1139
1140 packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1141 if ( packetLen < 0 )
1142 {
1143 fprintf( stderr, "%d: packetLen < 0\n", getpid() );
1144 return -1;
1145 }
1146 if ( packetLen > LSAPI_MAX_HEADER_LEN )
1147 {
1148 fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN );
1149 return -1;
1150 }
1151
1152 if ( packetLen + 1024 > pReq->m_reqBufSize )
1153 {
1154 if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
1155 return -1;
1156 }
1157 while( packetLen > pReq->m_bufRead )
1158 {
1159 len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
1160 if ( len <= 0 )
1161 return -1;
1162 pReq->m_bufRead += len;
1163 }
1164 if ( parseRequest( pReq, packetLen ) < 0 )
1165 {
1166 fprintf( stderr, "%d: parseRequest error\n", getpid() );
1167 return -1;
1168 }
1169
1170 pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1171
1172 if ( !s_uid )
1173 if ( lsapi_changeUGid( pReq ) )
1174 return -1;
1175 pReq->m_bufProcessed = packetLen;
1176
1177 //OPTIMIZATION
1178 if ( !s_accept_notify && !s_notified_pid )
1179 return notify_req_received( pReq->m_fd );
1180 else
1181 {
1182 s_notified_pid = 0;
1183 return 0;
1184 }
1185 }
1186
1187
1188
LSAPI_Init(void)1189 int LSAPI_Init(void)
1190 {
1191 if ( !g_inited )
1192 {
1193 s_uid = geteuid();
1194 s_pSecret[0] = 0;
1195 lsapi_signal(SIGPIPE, lsapi_sigpipe);
1196 lsapi_signal(SIGUSR1, lsapi_siguser1);
1197
1198 #if defined(SIGXFSZ) && defined(SIG_IGN)
1199 signal(SIGXFSZ, SIG_IGN);
1200 #endif
1201 /* let STDOUT function as STDERR,
1202 just in case writing to STDOUT directly */
1203 dup2( 2, 1 );
1204 if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1205 return -1;
1206 g_inited = 1;
1207 s_ppid = getppid();
1208 }
1209 return 0;
1210 }
1211
LSAPI_Stop(void)1212 void LSAPI_Stop(void)
1213 {
1214 g_running = 0;
1215 }
1216
LSAPI_IsRunning(void)1217 int LSAPI_IsRunning(void)
1218 {
1219 return g_running;
1220 }
1221
LSAPI_InitRequest(LSAPI_Request * pReq,int fd)1222 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1223 {
1224 int newfd;
1225 if ( !pReq )
1226 return -1;
1227 memset( pReq, 0, sizeof( LSAPI_Request ) );
1228 if ( allocateIovec( pReq, 16 ) == -1 )
1229 return -1;
1230 pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1231 if ( !pReq->m_pRespBuf )
1232 return -1;
1233 pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1234 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1235 pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1236 if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1237 return -1;
1238
1239 if ( fd == STDIN_FILENO )
1240 {
1241 fd = dup( fd );
1242 newfd = open( "/dev/null", O_RDWR );
1243 dup2( newfd, STDIN_FILENO );
1244 }
1245
1246 if ( isPipe( fd ) )
1247 {
1248 pReq->m_fdListen = -1;
1249 pReq->m_fd = fd;
1250 }
1251 else
1252 {
1253 pReq->m_fdListen = fd;
1254 pReq->m_fd = -1;
1255 lsapi_set_nblock( fd, 1 );
1256 }
1257 return 0;
1258 }
1259
LSAPI_Is_Listen(void)1260 int LSAPI_Is_Listen( void )
1261 {
1262 return LSAPI_Is_Listen_r( &g_req );
1263 }
1264
LSAPI_Is_Listen_r(LSAPI_Request * pReq)1265 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1266 {
1267 return pReq->m_fdListen != -1;
1268 }
1269
1270
1271
LSAPI_Accept_r(LSAPI_Request * pReq)1272 int LSAPI_Accept_r( LSAPI_Request * pReq )
1273 {
1274 char achPeer[128];
1275 socklen_t len;
1276 int nodelay = 1;
1277
1278 if ( !pReq )
1279 return -1;
1280 if ( LSAPI_Finish_r( pReq ) == -1 )
1281 return -1;
1282 lsapi_set_nblock( pReq->m_fdListen , 0 );
1283 while( g_running )
1284 {
1285 if ( pReq->m_fd == -1 )
1286 {
1287 if ( pReq->m_fdListen != -1)
1288 {
1289 len = sizeof( achPeer );
1290 pReq->m_fd = accept( pReq->m_fdListen,
1291 (struct sockaddr *)&achPeer, &len );
1292 if ( pReq->m_fd == -1 )
1293 {
1294 if (( errno == EINTR )||( errno == EAGAIN))
1295 continue;
1296 else
1297 return -1;
1298 }
1299 else
1300 {
1301 lsapi_set_nblock( pReq->m_fd , 0 );
1302 if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1303 {
1304 setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1305 (char *)&nodelay, sizeof(nodelay));
1306 }
1307 //init_conn_key( pReq->m_fd );
1308 //OPTIMIZATION
1309 if ( s_accept_notify )
1310 if ( notify_req_received( pReq->m_fd ) == -1 )
1311 return -1;
1312 }
1313 }
1314 else
1315 return -1;
1316 }
1317 if ( !readReq( pReq ) )
1318 break;
1319 //abort();
1320 lsapi_close( pReq->m_fd );
1321 pReq->m_fd = -1;
1322 LSAPI_Reset_r( pReq );
1323 }
1324 return 0;
1325 }
1326
1327 static struct lsapi_packet_header finish = {'L', 'S',
1328 LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1329
LSAPI_Finish_r(LSAPI_Request * pReq)1330 int LSAPI_Finish_r( LSAPI_Request * pReq )
1331 {
1332 /* finish req body */
1333 if ( !pReq )
1334 return -1;
1335 if (pReq->m_reqState)
1336 {
1337 if ( pReq->m_fd != -1 )
1338 {
1339 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1340 {
1341 LSAPI_FinalizeRespHeaders_r( pReq );
1342 }
1343 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1344 {
1345 Flush_RespBuf_r( pReq );
1346 }
1347
1348 pReq->m_pIovecCur->iov_base = (void *)&finish;
1349 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1350 pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1351 ++pReq->m_pIovecCur;
1352 LSAPI_Flush_r( pReq );
1353 }
1354 LSAPI_Reset_r( pReq );
1355 }
1356 return 0;
1357 }
1358
1359
LSAPI_Reset_r(LSAPI_Request * pReq)1360 void LSAPI_Reset_r( LSAPI_Request * pReq )
1361 {
1362 pReq->m_pRespBufPos = pReq->m_pRespBuf;
1363 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1364 pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
1365
1366 memset( &pReq->m_pHeaderIndex, 0,
1367 (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1368 }
1369
1370
LSAPI_Release_r(LSAPI_Request * pReq)1371 int LSAPI_Release_r( LSAPI_Request * pReq )
1372 {
1373 if ( pReq->m_pReqBuf )
1374 free( pReq->m_pReqBuf );
1375 if ( pReq->m_pSpecialEnvList )
1376 free( pReq->m_pSpecialEnvList );
1377 if ( pReq->m_pEnvList )
1378 free( pReq->m_pEnvList );
1379 if ( pReq->m_pRespHeaderBuf )
1380 free( pReq->m_pRespHeaderBuf );
1381 return 0;
1382 }
1383
1384
LSAPI_GetHeader_r(LSAPI_Request * pReq,int headerIndex)1385 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1386 {
1387 int off;
1388 if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
1389 return NULL;
1390 off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1391 if ( !off )
1392 return NULL;
1393 if ( *(pReq->m_pHttpHeader + off
1394 + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1395 {
1396 *( pReq->m_pHttpHeader + off
1397 + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1398 }
1399 return pReq->m_pHttpHeader + off;
1400 }
1401
readBodyToReqBuf(LSAPI_Request * pReq)1402 static int readBodyToReqBuf( LSAPI_Request * pReq )
1403 {
1404 off_t bodyLeft;
1405 ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1406 if ( len > 0 )
1407 return len;
1408 pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1409
1410 bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1411 len = pReq->m_reqBufSize - pReq->m_bufRead;
1412 if ( len < 0 )
1413 return -1;
1414 if ( len > bodyLeft )
1415 len = bodyLeft;
1416
1417 len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1418 if ( len > 0 )
1419 pReq->m_bufRead += len;
1420 return len;
1421 }
1422
1423
LSAPI_ReqBodyGetChar_r(LSAPI_Request * pReq)1424 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1425 {
1426 if (!pReq || (pReq->m_fd ==-1) )
1427 return EOF;
1428 if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1429 {
1430 if ( readBodyToReqBuf( pReq ) <= 0 )
1431 return EOF;
1432 }
1433 ++pReq->m_reqBodyRead;
1434 return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
1435 }
1436
1437
1438
LSAPI_ReqBodyGetLine_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen,int * getLF)1439 int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1440 {
1441 ssize_t len;
1442 ssize_t left;
1443 char * pBufEnd = pBuf + bufLen - 1;
1444 char * pBufCur = pBuf;
1445 char * pCur;
1446 char * p;
1447 if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF )
1448 return -1;
1449 *getLF = 0;
1450 while( (left = pBufEnd - pBufCur ) > 0 )
1451 {
1452
1453 len = pReq->m_bufRead - pReq->m_bufProcessed;
1454 if ( len <= 0 )
1455 {
1456 if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1457 {
1458 *getLF = 1;
1459 break;
1460 }
1461 }
1462 if ( len > left )
1463 len = left;
1464 pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
1465 p = memchr( pCur, '\n', len );
1466 if ( p )
1467 len = p - pCur + 1;
1468 memmove( pBufCur, pCur, len );
1469 pBufCur += len;
1470 pReq->m_bufProcessed += len;
1471
1472 pReq->m_reqBodyRead += len;
1473
1474 if ( p )
1475 {
1476 *getLF = 1;
1477 break;
1478 }
1479 }
1480 *pBufCur = 0;
1481
1482 return pBufCur - pBuf;
1483 }
1484
1485
LSAPI_ReadReqBody_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen)1486 ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1487 {
1488 ssize_t len;
1489 off_t total;
1490 /* char *pOldBuf = pBuf; */
1491 if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 ))
1492 return -1;
1493
1494 total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1495
1496 if ( total <= 0 )
1497 return 0;
1498 if ( total < bufLen )
1499 bufLen = total;
1500
1501 total = 0;
1502 len = pReq->m_bufRead - pReq->m_bufProcessed;
1503 if ( len > 0 )
1504 {
1505 if ( len > bufLen )
1506 len = bufLen;
1507 memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1508 pReq->m_bufProcessed += len;
1509 total += len;
1510 pBuf += len;
1511 bufLen -= len;
1512 }
1513 while( bufLen > 0 )
1514 {
1515 len = lsapi_read( pReq->m_fd, pBuf, bufLen );
1516 if ( len > 0 )
1517 {
1518 total += len;
1519 pBuf += len;
1520 bufLen -= len;
1521 }
1522 else if ( len <= 0 )
1523 {
1524 if ( !total)
1525 return -1;
1526 break;
1527 }
1528 }
1529 pReq->m_reqBodyRead += total;
1530 return total;
1531
1532 }
1533
1534
LSAPI_Write_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1535 ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1536 {
1537 struct lsapi_packet_header * pHeader;
1538 const char * pEnd;
1539 const char * p;
1540 ssize_t bufLen;
1541 ssize_t toWrite;
1542 ssize_t packetLen;
1543 int skip = 0;
1544
1545 if ( !pReq || !pBuf || (pReq->m_fd == -1) )
1546 return -1;
1547 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1548 {
1549 LSAPI_FinalizeRespHeaders_r( pReq );
1550 /*
1551 if ( *pBuf == '\r' )
1552 {
1553 ++skip;
1554 }
1555 if ( *pBuf == '\n' )
1556 {
1557 ++skip;
1558 }
1559 */
1560 }
1561 pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1562
1563 if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1564 {
1565 memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1566 pReq->m_pRespBufPos += len - skip;
1567 return len;
1568 }
1569
1570
1571 pHeader = pReq->m_respPktHeader;
1572 p = pBuf + skip;
1573 pEnd = pBuf + len;
1574 bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1575
1576 while( ( toWrite = pEnd - p ) > 0 )
1577 {
1578 packetLen = toWrite + bufLen;
1579 if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1580 {
1581 packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1582 toWrite = packetLen - bufLen;
1583 }
1584
1585 lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1586 packetLen + LSAPI_PACKET_HEADER_LEN );
1587 pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
1588
1589 pReq->m_pIovecCur->iov_base = (void *)pHeader;
1590 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1591 ++pReq->m_pIovecCur;
1592 ++pHeader;
1593 if ( bufLen > 0 )
1594 {
1595 pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1596 pReq->m_pIovecCur->iov_len = bufLen;
1597 pReq->m_pRespBufPos = pReq->m_pRespBuf;
1598 ++pReq->m_pIovecCur;
1599 bufLen = 0;
1600 }
1601
1602 pReq->m_pIovecCur->iov_base = (void *)p;
1603 pReq->m_pIovecCur->iov_len = toWrite;
1604 ++pReq->m_pIovecCur;
1605 p += toWrite;
1606
1607 if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
1608 {
1609 if ( LSAPI_Flush_r( pReq ) == -1 )
1610 return -1;
1611 pHeader = pReq->m_respPktHeader;
1612 }
1613 }
1614 if ( pHeader != pReq->m_respPktHeader )
1615 if ( LSAPI_Flush_r( pReq ) == -1 )
1616 return -1;
1617 return p - pBuf;
1618 }
1619
1620 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1621 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1622 {
1623 ssize_t ret;
1624 off_t written;
1625 ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1626 if ( written > 0 )
1627 {
1628 ret = written;
1629 *off += ret;
1630 }
1631 return ret;
1632 }
1633 #endif
1634
1635 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1636 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1637 {
1638 ssize_t ret;
1639 off_t len = size;
1640 ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1641 if (( ret == 0 )&&( len > 0 ))
1642 {
1643 ret = len;
1644 *off += len;
1645 }
1646 return ret;
1647 }
1648 #endif
1649
1650 #if defined(sun) || defined(__sun)
1651 #include <sys/sendfile.h>
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1652 ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1653 {
1654 int n = 0 ;
1655 sendfilevec_t vec[1];
1656
1657 vec[n].sfv_fd = fdIn;
1658 vec[n].sfv_flag = 0;
1659 vec[n].sfv_off = *off;
1660 vec[n].sfv_len = size;
1661 ++n;
1662
1663 size_t written;
1664 ssize_t ret = sendfilev( fdOut, vec, n, &written );
1665 if (( !ret )||( errno == EAGAIN ))
1666 ret = written;
1667 if ( ret > 0 )
1668 *off += ret;
1669 return ret;
1670 }
1671 #endif
1672
1673 #if defined(linux) || defined(__linux) || defined(__linux__) || \
1674 defined(__gnu_linux__)
1675 #include <sys/sendfile.h>
1676 #define gsendfile sendfile
1677 #endif
1678 #if defined(HPUX)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1679 ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
1680 {
1681 return sendfile( fdOut, fdIn, off, size, NULL, 0 );
1682 }
1683 #endif
1684
LSAPI_sendfile_r(LSAPI_Request * pReq,int fdIn,off_t * off,size_t size)1685 ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
1686 {
1687 struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1688 if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
1689 return -1;
1690 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1691 {
1692 LSAPI_FinalizeRespHeaders_r( pReq );
1693 }
1694 pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1695
1696 LSAPI_Flush_r(pReq);
1697
1698 lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1699 size + LSAPI_PACKET_HEADER_LEN );
1700
1701
1702 if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
1703 return -1;
1704
1705 return gsendfile( pReq->m_fd, fdIn, off, size );
1706 }
1707
1708
Flush_RespBuf_r(LSAPI_Request * pReq)1709 void Flush_RespBuf_r( LSAPI_Request * pReq )
1710 {
1711 struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1712 int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1713 pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1714 lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1715 bufLen + LSAPI_PACKET_HEADER_LEN );
1716 pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
1717
1718 pReq->m_pIovecCur->iov_base = (void *)pHeader;
1719 pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1720 ++pReq->m_pIovecCur;
1721 ++pHeader;
1722 if ( bufLen > 0 )
1723 {
1724 pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1725 pReq->m_pIovecCur->iov_len = bufLen;
1726 pReq->m_pRespBufPos = pReq->m_pRespBuf;
1727 ++pReq->m_pIovecCur;
1728 bufLen = 0;
1729 }
1730 }
1731
1732
1733
1734
LSAPI_Flush_r(LSAPI_Request * pReq)1735 int LSAPI_Flush_r( LSAPI_Request * pReq )
1736 {
1737 int ret = 0;
1738 int n;
1739 if ( !pReq )
1740 return -1;
1741 n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1742 if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
1743 return 0;
1744 if ( pReq->m_fd == -1 )
1745 {
1746 pReq->m_pRespBufPos = pReq->m_pRespBuf;
1747 pReq->m_totalLen = 0;
1748 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
1749 return -1;
1750 }
1751 if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1752 {
1753 LSAPI_FinalizeRespHeaders_r( pReq );
1754 }
1755 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1756 {
1757 Flush_RespBuf_r( pReq );
1758 }
1759
1760 n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1761 if ( n > 0 )
1762 {
1763
1764 ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
1765 n, pReq->m_totalLen );
1766 if ( ret < pReq->m_totalLen )
1767 {
1768 lsapi_close( pReq->m_fd );
1769 pReq->m_fd = -1;
1770 ret = -1;
1771 }
1772 pReq->m_totalLen = 0;
1773 pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
1774 }
1775 return ret;
1776 }
1777
1778
LSAPI_Write_Stderr_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1779 ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1780 {
1781 struct lsapi_packet_header header;
1782 const char * pEnd;
1783 const char * p;
1784 ssize_t packetLen;
1785 ssize_t totalLen;
1786 int ret;
1787 struct iovec iov[2];
1788 struct iovec *pIov;
1789
1790 if ( !pReq )
1791 return -1;
1792 if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
1793 return write( 2, pBuf, len );
1794 if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1795 {
1796 LSAPI_Flush_r( pReq );
1797 }
1798
1799 p = pBuf;
1800 pEnd = pBuf + len;
1801
1802 while( ( packetLen = pEnd - p ) > 0 )
1803 {
1804 if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1805 {
1806 packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1807 }
1808
1809 lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
1810 packetLen + LSAPI_PACKET_HEADER_LEN );
1811 totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
1812
1813 iov[0].iov_base = (void *)&header;
1814 iov[0].iov_len = LSAPI_PACKET_HEADER_LEN;
1815
1816 iov[1].iov_base = (void *)p;
1817 iov[1].iov_len = packetLen;
1818 p += packetLen;
1819 pIov = iov;
1820 ret = lsapi_writev( pReq->m_fd, &pIov,
1821 2, totalLen );
1822 if ( ret < totalLen )
1823 {
1824 lsapi_close( pReq->m_fd );
1825 pReq->m_fd = -1;
1826 ret = -1;
1827 }
1828 }
1829 return p - pBuf;
1830 }
1831
GetHeaderVar(LSAPI_Request * pReq,const char * name)1832 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
1833 {
1834 int i;
1835 char * pValue;
1836 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1837 {
1838 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1839 {
1840 if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
1841 {
1842 pValue = pReq->m_pHttpHeader
1843 + pReq->m_pHeaderIndex->m_headerOff[i];
1844 if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
1845 {
1846 *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
1847 }
1848 return pValue;
1849 }
1850 }
1851 }
1852 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
1853 {
1854 const char *p;
1855 char *pKey;
1856 char *pKeyEnd;
1857 int keyLen;
1858 struct lsapi_header_offset * pCur, *pEnd;
1859 pCur = pReq->m_pUnknownHeader;
1860 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
1861 while( pCur < pEnd )
1862 {
1863 pKey = pReq->m_pHttpHeader + pCur->nameOff;
1864 keyLen = pCur->nameLen;
1865 pKeyEnd = pKey + keyLen;
1866 p = &name[5];
1867
1868 while(( pKey < pKeyEnd )&&( *p ))
1869 {
1870 char ch = toupper( *pKey );
1871 if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
1872 break;
1873 ++p; ++pKey;
1874 }
1875 if (( pKey == pKeyEnd )&& (!*p ))
1876 {
1877 pValue = pReq->m_pHttpHeader + pCur->valueOff;
1878
1879 if ( *(pValue + pCur->valueLen) != '\0')
1880 {
1881 *(pValue + pCur->valueLen) = '\0';
1882 }
1883 return pValue;
1884 }
1885 ++pCur;
1886 }
1887 }
1888 return NULL;
1889 }
1890
1891
LSAPI_GetEnv_r(LSAPI_Request * pReq,const char * name)1892 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
1893 {
1894 struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
1895 struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
1896 if ( !pReq || !name )
1897 return NULL;
1898 if ( strncmp( name, "HTTP_", 5 ) == 0 )
1899 {
1900 return GetHeaderVar( pReq, name );
1901 }
1902 while( pBegin < pEnd )
1903 {
1904 if ( strcmp( name, pBegin->pKey ) == 0 )
1905 return pBegin->pValue;
1906 ++pBegin;
1907 }
1908 return NULL;
1909 }
1910
1911 struct _headerInfo
1912 {
1913 const char * _name;
1914 int _nameLen;
1915 const char * _value;
1916 int _valueLen;
1917 };
1918
compareValueLocation(const void * v1,const void * v2)1919 int compareValueLocation(const void * v1, const void *v2 )
1920 {
1921 return ((const struct _headerInfo *)v1)->_value -
1922 ((const struct _headerInfo *)v2)->_value;
1923 }
1924
LSAPI_ForeachOrgHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)1925 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1926 LSAPI_CB_EnvHandler fn, void * arg )
1927 {
1928 int i;
1929 int len = 0;
1930 char * pValue;
1931 int ret;
1932 int count = 0;
1933 struct _headerInfo headers[512];
1934
1935 if ( !pReq || !fn )
1936 return -1;
1937
1938 if ( !pReq->m_pHeaderIndex )
1939 return 0;
1940
1941 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1942 {
1943 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1944 {
1945 len = pReq->m_pHeaderIndex->m_headerLen[i];
1946 pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
1947 *(pValue + len ) = 0;
1948 headers[count]._name = HTTP_HEADERS[i];
1949 headers[count]._nameLen = HTTP_HEADER_LEN[i];
1950 headers[count]._value = pValue;
1951 headers[count]._valueLen = len;
1952 ++count;
1953
1954 //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
1955 // pValue, len, arg );
1956 //if ( ret <= 0 )
1957 // return ret;
1958 }
1959 }
1960 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
1961 {
1962 char *pKey;
1963 int keyLen;
1964 struct lsapi_header_offset * pCur, *pEnd;
1965 pCur = pReq->m_pUnknownHeader;
1966 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
1967 while( pCur < pEnd )
1968 {
1969 pKey = pReq->m_pHttpHeader + pCur->nameOff;
1970 keyLen = pCur->nameLen;
1971 *(pKey + keyLen ) = 0;
1972
1973 pValue = pReq->m_pHttpHeader + pCur->valueOff;
1974 *(pValue + pCur->valueLen ) = 0;
1975 headers[count]._name = pKey;
1976 headers[count]._nameLen = keyLen;
1977 headers[count]._value = pValue;
1978 headers[count]._valueLen = pCur->valueLen;
1979 ++count;
1980 if ( count == 512 )
1981 break;
1982 //ret = (*fn)( pKey, keyLen,
1983 // pValue, pCur->valueLen, arg );
1984 //if ( ret <= 0 )
1985 // return ret;
1986 ++pCur;
1987 }
1988 }
1989 qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
1990 for( i = 0; i < count; ++i )
1991 {
1992 ret = (*fn)( headers[i]._name, headers[i]._nameLen,
1993 headers[i]._value, headers[i]._valueLen, arg );
1994 if ( ret <= 0 )
1995 return ret;
1996 }
1997 return count;
1998
1999 }
2000
2001
LSAPI_ForeachHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2002 int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2003 LSAPI_CB_EnvHandler fn, void * arg )
2004 {
2005 int i;
2006 int len = 0;
2007 char * pValue;
2008 int ret;
2009 int count = 0;
2010 if ( !pReq || !fn )
2011 return -1;
2012 for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2013 {
2014 if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2015 {
2016 len = pReq->m_pHeaderIndex->m_headerLen[i];
2017 pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2018 *(pValue + len ) = 0;
2019 ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
2020 pValue, len, arg );
2021 ++count;
2022 if ( ret <= 0 )
2023 return ret;
2024 }
2025 }
2026 if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2027 {
2028 char achHeaderName[256];
2029 char *p;
2030 char *pKey;
2031 char *pKeyEnd ;
2032 int keyLen;
2033 struct lsapi_header_offset * pCur, *pEnd;
2034 pCur = pReq->m_pUnknownHeader;
2035 pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2036 while( pCur < pEnd )
2037 {
2038 pKey = pReq->m_pHttpHeader + pCur->nameOff;
2039 keyLen = pCur->nameLen;
2040 if ( keyLen > 250 )
2041 keyLen = 250;
2042 pKeyEnd = pKey + keyLen;
2043 memcpy( achHeaderName, "HTTP_", 5 );
2044 p = &achHeaderName[5];
2045
2046 while( pKey < pKeyEnd )
2047 {
2048 char ch = *pKey++;
2049 if ( ch == '-' )
2050 *p++ = '_';
2051 else
2052 *p++ = toupper( ch );
2053 }
2054 *p = 0;
2055 keyLen += 5;
2056
2057 pValue = pReq->m_pHttpHeader + pCur->valueOff;
2058 *(pValue + pCur->valueLen ) = 0;
2059 ret = (*fn)( achHeaderName, keyLen,
2060 pValue, pCur->valueLen, arg );
2061 if ( ret <= 0 )
2062 return ret;
2063 ++pCur;
2064 }
2065 }
2066 return count + pReq->m_pHeader->m_cntUnknownHeaders;
2067
2068 }
2069
EnvForeach(struct LSAPI_key_value_pair * pEnv,int n,LSAPI_CB_EnvHandler fn,void * arg)2070 static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2071 int n, LSAPI_CB_EnvHandler fn, void * arg )
2072 {
2073 struct LSAPI_key_value_pair * pEnd = pEnv + n;
2074 int ret;
2075 if ( !pEnv || !fn )
2076 return -1;
2077 while( pEnv < pEnd )
2078 {
2079 ret = (*fn)( pEnv->pKey, pEnv->keyLen,
2080 pEnv->pValue, pEnv->valLen, arg );
2081 if ( ret <= 0 )
2082 return ret;
2083 ++pEnv;
2084 }
2085 return n;
2086 }
2087
2088
2089
LSAPI_ForeachEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2090 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2091 LSAPI_CB_EnvHandler fn, void * arg )
2092 {
2093 if ( !pReq || !fn )
2094 return -1;
2095 if ( pReq->m_pHeader->m_cntEnv > 0 )
2096 {
2097 return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
2098 fn, arg );
2099 }
2100 return 0;
2101 }
2102
2103
2104
LSAPI_ForeachSpecialEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2105 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2106 LSAPI_CB_EnvHandler fn, void * arg )
2107 {
2108 if ( !pReq || !fn )
2109 return -1;
2110 if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
2111 {
2112 return EnvForeach( pReq->m_pSpecialEnvList,
2113 pReq->m_pHeader->m_cntSpecialEnv,
2114 fn, arg );
2115 }
2116 return 0;
2117
2118 }
2119
2120
2121
LSAPI_FinalizeRespHeaders_r(LSAPI_Request * pReq)2122 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2123 {
2124 if ( !pReq || !pReq->m_pIovec )
2125 return -1;
2126 if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
2127 return 0;
2128 pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
2129 if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
2130 {
2131 pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
2132 pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
2133 pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2134 ++pReq->m_pIovecCur;
2135 }
2136
2137 pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header)
2138 + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2139 pReq->m_totalLen += pReq->m_pIovec->iov_len;
2140
2141 lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
2142 LSAPI_RESP_HEADER, pReq->m_totalLen );
2143 pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
2144 pReq->m_pIovecToWrite = pReq->m_pIovec;
2145 return 0;
2146 }
2147
2148
LSAPI_AppendRespHeader2_r(LSAPI_Request * pReq,const char * pHeaderName,const char * pHeaderValue)2149 int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2150 const char * pHeaderValue )
2151 {
2152 int nameLen, valLen, len;
2153 if ( !pReq || !pHeaderName || !pHeaderValue )
2154 return -1;
2155 if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2156 return -1;
2157 if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2158 return -1;
2159 nameLen = strlen( pHeaderName );
2160 valLen = strlen( pHeaderValue );
2161 if ( nameLen == 0 )
2162 return -1;
2163 while( nameLen > 0 )
2164 {
2165 char ch = *(pHeaderName + nameLen - 1 );
2166 if (( ch == '\n' )||( ch == '\r' ))
2167 --nameLen;
2168 else
2169 break;
2170 }
2171 if ( nameLen <= 0 )
2172 return 0;
2173 while( valLen > 0 )
2174 {
2175 char ch = *(pHeaderValue + valLen - 1 );
2176 if (( ch == '\n' )||( ch == '\r' ))
2177 --valLen;
2178 else
2179 break;
2180 }
2181 len = nameLen + valLen + 1;
2182 if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2183 return -1;
2184
2185 if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2186 {
2187 int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2188 newlen -= newlen % 4096;
2189 if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2190 return -1;
2191 }
2192 memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2193 pReq->m_pRespHeaderBufPos += nameLen;
2194 *pReq->m_pRespHeaderBufPos++ = ':';
2195 memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2196 pReq->m_pRespHeaderBufPos += valLen;
2197 *pReq->m_pRespHeaderBufPos++ = 0;
2198 ++len; /* add one byte padding for \0 */
2199 pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2200 ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2201 return 0;
2202 }
2203
2204
2205
LSAPI_AppendRespHeader_r(LSAPI_Request * pReq,const char * pBuf,int len)2206 int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2207 {
2208 if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
2209 return -1;
2210 if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2211 return -1;
2212 if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2213 return -1;
2214 while( len > 0 )
2215 {
2216 char ch = *(pBuf + len - 1 );
2217 if (( ch == '\n' )||( ch == '\r' ))
2218 --len;
2219 else
2220 break;
2221 }
2222 if ( len <= 0 )
2223 return 0;
2224 if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2225 {
2226 int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2227 newlen -= newlen % 4096;
2228 if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2229 return -1;
2230 }
2231 memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
2232 pReq->m_pRespHeaderBufPos += len;
2233 *pReq->m_pRespHeaderBufPos++ = 0;
2234 ++len; /* add one byte padding for \0 */
2235 pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2236 ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2237 return 0;
2238 }
2239
2240
LSAPI_CreateListenSock2(const struct sockaddr * pServerAddr,int backlog)2241 int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2242 {
2243 int ret;
2244 int fd;
2245 int flag = 1;
2246 int addr_len;
2247
2248 switch( pServerAddr->sa_family )
2249 {
2250 case AF_INET:
2251 addr_len = 16;
2252 break;
2253 case AF_INET6:
2254 addr_len = sizeof( struct sockaddr_in6 );
2255 break;
2256 case AF_UNIX:
2257 addr_len = sizeof( struct sockaddr_un );
2258 unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2259 break;
2260 default:
2261 return -1;
2262 }
2263
2264 fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
2265 if ( fd == -1 )
2266 return -1;
2267
2268 fcntl( fd, F_SETFD, FD_CLOEXEC );
2269
2270 if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
2271 (char *)( &flag ), sizeof(flag)) == 0)
2272 {
2273 ret = bind( fd, pServerAddr, addr_len );
2274 if ( !ret )
2275 {
2276 ret = listen( fd, backlog );
2277 if ( !ret )
2278 return fd;
2279 }
2280 }
2281
2282 ret = errno;
2283 close(fd);
2284 errno = ret;
2285 return -1;
2286
2287 }
2288
LSAPI_ParseSockAddr(const char * pBind,struct sockaddr * pAddr)2289 int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2290 {
2291 char achAddr[256];
2292 char * p = achAddr;
2293 char * pEnd;
2294 struct addrinfo *res, hints;
2295 int doAddrInfo = 0;
2296 int port;
2297
2298 if ( !pBind )
2299 return -1;
2300
2301 while( isspace( *pBind ) )
2302 ++pBind;
2303
2304 strncpy( achAddr, pBind, 256 );
2305
2306 switch( *p )
2307 {
2308 case '/':
2309 pAddr->sa_family = AF_UNIX;
2310 strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
2311 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
2312 return 0;
2313
2314 case '[':
2315 pAddr->sa_family = AF_INET6;
2316 ++p;
2317 pEnd = strchr( p, ']' );
2318 if ( !pEnd )
2319 return -1;
2320 *pEnd++ = 0;
2321
2322 if ( *p == '*' )
2323 {
2324 strcpy( achAddr, "::" );
2325 p = achAddr;
2326 }
2327 doAddrInfo = 1;
2328 break;
2329
2330 default:
2331 pAddr->sa_family = AF_INET;
2332 pEnd = strchr( p, ':' );
2333 if ( !pEnd )
2334 return -1;
2335 *pEnd++ = 0;
2336
2337 doAddrInfo = 0;
2338 if ( *p == '*' )
2339 {
2340 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
2341 }
2342 else if (!strcasecmp( p, "localhost" ) )
2343 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2344 else
2345 {
2346 ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2347 if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2348 {
2349 doAddrInfo = 1;
2350 }
2351 }
2352 break;
2353 }
2354 if ( *pEnd == ':' )
2355 ++pEnd;
2356
2357 port = atoi( pEnd );
2358 if (( port <= 0 )||( port > 65535 ))
2359 return -1;
2360 if ( doAddrInfo )
2361 {
2362
2363 memset(&hints, 0, sizeof(hints));
2364
2365 hints.ai_family = pAddr->sa_family;
2366 hints.ai_socktype = SOCK_STREAM;
2367 hints.ai_protocol = IPPROTO_TCP;
2368
2369 if ( getaddrinfo(p, NULL, &hints, &res) )
2370 {
2371 return -1;
2372 }
2373
2374 memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2375 freeaddrinfo(res);
2376 }
2377
2378 if ( pAddr->sa_family == AF_INET )
2379 ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2380 else
2381 ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2382 return 0;
2383
2384 }
2385
LSAPI_CreateListenSock(const char * pBind,int backlog)2386 int LSAPI_CreateListenSock( const char * pBind, int backlog )
2387 {
2388 char serverAddr[128];
2389 int ret;
2390 int fd = -1;
2391 ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2392 if ( !ret )
2393 {
2394 fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2395 }
2396 return fd;
2397 }
2398
2399 static fn_select_t g_fnSelect = select;
2400
2401 typedef struct _lsapi_child_status
2402 {
2403 int m_pid;
2404 long m_tmStart;
2405
2406 volatile short m_iKillSent;
2407 volatile short m_inProcess;
2408 volatile int m_iReqCounter;
2409
2410 volatile long m_tmWaitBegin;
2411 volatile long m_tmReqBegin;
2412 volatile long m_tmLastCheckPoint;
2413 }
2414 lsapi_child_status;
2415
2416 static lsapi_child_status * s_pChildStatus = NULL;
2417
2418 typedef struct _lsapi_prefork_server
2419 {
2420 int m_fd;
2421 int m_iMaxChildren;
2422 int m_iExtraChildren;
2423 int m_iCurChildren;
2424 int m_iMaxIdleChildren;
2425 int m_iServerMaxIdle;
2426 int m_iChildrenMaxIdleTime;
2427 int m_iMaxReqProcessTime;
2428 int m_iAvoidFork;
2429
2430 lsapi_child_status * m_pChildrenStatus;
2431 lsapi_child_status * m_pChildrenStatusCur;
2432 lsapi_child_status * m_pChildrenStatusEnd;
2433
2434 }lsapi_prefork_server;
2435
2436 static lsapi_prefork_server * g_prefork_server = NULL;
2437
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)2438 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2439 {
2440 int pid;
2441 if ( g_prefork_server )
2442 return 0;
2443 if ( max_children <= 1 )
2444 return -1;
2445 if ( max_children >= 10000)
2446 max_children = 10000;
2447
2448
2449 g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2450 if ( !g_prefork_server )
2451 return -1;
2452 memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2453
2454 if ( fp != NULL )
2455 g_fnSelect = fp;
2456
2457 s_ppid = getppid();
2458 pid = getpid();
2459 setpgid( pid, pid );
2460 g_prefork_server->m_iAvoidFork = avoidFork;
2461 g_prefork_server->m_iMaxChildren = max_children;
2462
2463 g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2464 g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2465 if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2466 g_prefork_server->m_iMaxIdleChildren = 1;
2467 g_prefork_server->m_iChildrenMaxIdleTime = 300;
2468 g_prefork_server->m_iMaxReqProcessTime = 3600;
2469 return 0;
2470 }
2471
LSAPI_Set_Server_fd(int fd)2472 void LSAPI_Set_Server_fd( int fd )
2473 {
2474 if( g_prefork_server )
2475 g_prefork_server->m_fd = fd;
2476 }
2477
2478
lsapi_accept(int fdListen)2479 static int lsapi_accept( int fdListen )
2480 {
2481 int fd;
2482 int nodelay = 1;
2483 socklen_t len;
2484 char achPeer[128];
2485
2486 len = sizeof( achPeer );
2487 fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2488 if ( fd != -1 )
2489 {
2490 if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2491 {
2492 setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2493 (char *)&nodelay, sizeof(nodelay));
2494 }
2495
2496 //OPTIMIZATION
2497 //if ( s_accept_notify )
2498 // notify_req_received( fd );
2499 }
2500 return fd;
2501
2502 }
2503
2504
2505
2506
2507 static int s_req_processed = 0;
2508 static int s_max_reqs = 10000;
2509 static int s_max_idle_secs = 300;
2510
2511 static int s_stop;
2512
lsapi_cleanup(int signal)2513 static void lsapi_cleanup(int signal)
2514 {
2515 s_stop = signal;
2516 }
2517
find_child_status(int pid)2518 static lsapi_child_status * find_child_status( int pid )
2519 {
2520 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2521 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2522 while( pStatus < pEnd )
2523 {
2524 if ( pStatus->m_pid == pid )
2525 {
2526 if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2527 g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2528 return pStatus;
2529 }
2530 ++pStatus;
2531 }
2532 return NULL;
2533 }
2534
2535
2536
lsapi_sigchild(int signal)2537 static void lsapi_sigchild( int signal )
2538 {
2539 int status, pid;
2540 lsapi_child_status * child_status;
2541 while( 1 )
2542 {
2543 pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2544 if ( pid <= 0 )
2545 {
2546 break;
2547 }
2548 if ( WIFSIGNALED( status ))
2549 {
2550 int sig_num = WTERMSIG( status );
2551 int dump = WCOREDUMP( status );
2552 fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump );
2553 }
2554 if ( pid == s_pid_dump_debug_info )
2555 {
2556 pid = 0;
2557 continue;
2558 }
2559 child_status = find_child_status( pid );
2560 if ( child_status )
2561 {
2562 child_status->m_pid = 0;
2563 --g_prefork_server->m_iCurChildren;
2564
2565 }
2566 }
2567 while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2568 &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2569 --g_prefork_server->m_pChildrenStatusCur;
2570
2571 }
2572
lsapi_init_children_status()2573 static int lsapi_init_children_status()
2574 {
2575 int size = 4096;
2576
2577 char * pBuf;
2578 size = (g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren ) * sizeof( lsapi_child_status ) * 2;
2579 size = (size + 4095 ) / 4096 * 4096;
2580 pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2581 MAP_ANON | MAP_SHARED, -1, 0 );
2582 if ( pBuf == MAP_FAILED )
2583 {
2584 perror( "Anonymous mmap() failed" );
2585 return -1;
2586 }
2587 memset( pBuf, 0, size );
2588 g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2589 g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2590 g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + size / sizeof( lsapi_child_status );
2591 return 0;
2592 }
2593
dump_debug_info(lsapi_child_status * pStatus,long tmCur)2594 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2595 {
2596 char achCmd[1024];
2597 if ( s_pid_dump_debug_info )
2598 {
2599 if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
2600 return;
2601 }
2602 s_pid_dump_debug_info = fork();
2603
2604 fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
2605 ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
2606 tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2607 snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid );
2608 if ( system( achCmd ) == -1 )
2609 perror( "system()" );
2610 exit( 0 );
2611 }
2612
lsapi_check_child_status(long tmCur)2613 static void lsapi_check_child_status( long tmCur )
2614 {
2615 int idle = 0;
2616 int tobekilled;
2617 int dying = 0;
2618 int count = 0;
2619 lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2620 lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
2621 while( pStatus < pEnd )
2622 {
2623 tobekilled = 0;
2624 if ( pStatus->m_pid != 0 )
2625 {
2626 ++count;
2627 if ( !pStatus->m_inProcess )
2628 {
2629
2630 if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
2631 ( idle > g_prefork_server->m_iMaxIdleChildren ))
2632 {
2633 ++pStatus->m_iKillSent;
2634 //tobekilled = SIGUSR1;
2635 }
2636 else
2637 {
2638 if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
2639 {
2640 ++pStatus->m_iKillSent;
2641 //tobekilled = SIGUSR1;
2642 }
2643 }
2644 if ( !tobekilled )
2645 ++idle;
2646 }
2647 else
2648 {
2649 if ( tmCur - pStatus->m_tmReqBegin >
2650 g_prefork_server->m_iMaxReqProcessTime )
2651 {
2652 if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
2653 dump_debug_info( pStatus, tmCur );
2654 if ( pStatus->m_iKillSent > 5 )
2655 {
2656 tobekilled = SIGKILL;
2657 fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
2658 }
2659 else
2660 {
2661 tobekilled = SIGTERM;
2662 fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
2663 }
2664 }
2665 }
2666 if ( tobekilled )
2667 {
2668 if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH ))
2669 {
2670 pStatus->m_pid = 0;
2671 --count;
2672 }
2673 else
2674 {
2675 ++pStatus->m_iKillSent;
2676 ++dying;
2677 }
2678 }
2679 }
2680 ++pStatus;
2681 }
2682 if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
2683 {
2684 fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(),
2685 g_prefork_server->m_iCurChildren, count, idle, dying );
2686
2687 }
2688 }
2689
lsapi_all_children_must_die()2690 static int lsapi_all_children_must_die()
2691 {
2692 int maxWait;
2693 int sec =0;
2694 g_prefork_server->m_iMaxReqProcessTime = 10;
2695 g_prefork_server->m_iMaxIdleChildren = -1;
2696 maxWait = 15;
2697
2698 while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
2699 {
2700 lsapi_check_child_status(time(NULL));
2701 sleep( 1 );
2702 sec++;
2703 }
2704 if ( g_prefork_server->m_iCurChildren != 0 )
2705 kill( -getpgrp(), SIGKILL );
2706 return 0;
2707 }
2708
2709
2710
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)2711 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
2712 {
2713 struct sigaction act, old_term, old_quit, old_int,
2714 old_usr1, old_child;
2715 lsapi_child_status * child_status;
2716 int wait_secs = 0;
2717 int ret = 0;
2718 int pid;
2719 time_t lastTime = 0;
2720 time_t curTime = 0;
2721 fd_set readfds;
2722 struct timeval timeout;
2723
2724 sigset_t mask;
2725 sigset_t orig_mask;
2726
2727 lsapi_init_children_status();
2728
2729 setsid();
2730
2731 act.sa_flags = 0;
2732 act.sa_handler = lsapi_sigchild;
2733 if( sigaction( SIGCHLD, &act, &old_child ) )
2734 {
2735 perror( "Can't set signal handler for SIGCHILD" );
2736 return -1;
2737 }
2738
2739 /* Set up handler to kill children upon exit */
2740 act.sa_flags = 0;
2741 act.sa_handler = lsapi_cleanup;
2742 if( sigaction( SIGTERM, &act, &old_term ) ||
2743 sigaction( SIGINT, &act, &old_int ) ||
2744 sigaction( SIGUSR1, &act, &old_usr1 ) ||
2745 sigaction( SIGQUIT, &act, &old_quit ))
2746 {
2747 perror( "Can't set signals" );
2748 return -1;
2749 }
2750 s_stop = 0;
2751 while( !s_stop )
2752 {
2753 curTime = time( NULL );
2754 if (curTime != lastTime )
2755 {
2756 lastTime = curTime;
2757 if (s_ppid && (getppid() != s_ppid ))
2758 break;
2759 lsapi_check_child_status(curTime );
2760 if (pServer->m_iServerMaxIdle)
2761 {
2762 if ( pServer->m_iCurChildren <= 0 )
2763 {
2764 ++wait_secs;
2765 if ( wait_secs > pServer->m_iServerMaxIdle )
2766 return -1;
2767 }
2768 else
2769 wait_secs = 0;
2770 }
2771 }
2772
2773 if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
2774 {
2775 fprintf( stderr, "Reached max children process limit: %d, extra: %d, current: %d, please increase LSAPI_CHILDREN.\n",
2776 pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren );
2777 usleep( 100000 );
2778 continue;
2779 }
2780
2781 FD_ZERO( &readfds );
2782 FD_SET( pServer->m_fd, &readfds );
2783 timeout.tv_sec = 1; timeout.tv_usec = 0;
2784 if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
2785 {
2786 /*
2787 if ( pServer->m_iCurChildren >= 0 )
2788 {
2789 usleep( 10 );
2790 FD_ZERO( &readfds );
2791 FD_SET( pServer->m_fd, &readfds );
2792 timeout.tv_sec = 0; timeout.tv_usec = 0;
2793 if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
2794 continue;
2795 }*/
2796 }
2797 else if ( ret == -1 )
2798 {
2799 if ( errno == EINTR )
2800 continue;
2801 /* perror( "select()" ); */
2802 break;
2803 }
2804 else
2805 {
2806 continue;
2807 }
2808
2809 pReq->m_fd = lsapi_accept( pServer->m_fd );
2810 if ( pReq->m_fd != -1 )
2811 {
2812 child_status = find_child_status( 0 );
2813 if ( child_status )
2814 memset( child_status, 0, sizeof( *child_status ) );
2815
2816 sigemptyset( &mask );
2817 sigaddset( &mask, SIGCHLD );
2818
2819 if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
2820 {
2821 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
2822 }
2823
2824 pid = fork();
2825
2826 if ( !pid )
2827 {
2828 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2829 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
2830 g_prefork_server = NULL;
2831 s_ppid = getppid();
2832 s_req_processed = 0;
2833 s_pChildStatus = child_status;
2834 lsapi_set_nblock( pReq->m_fd, 0 );
2835 if ( pReq->m_fdListen != -1 )
2836 {
2837 close( pReq->m_fdListen );
2838 pReq->m_fdListen = -1;
2839 }
2840 /* don't catch our signals */
2841 sigaction( SIGCHLD, &old_child, 0 );
2842 sigaction( SIGTERM, &old_term, 0 );
2843 sigaction( SIGQUIT, &old_quit, 0 );
2844 sigaction( SIGINT, &old_int, 0 );
2845 sigaction( SIGUSR1, &old_usr1, 0 );
2846 //init_conn_key( pReq->m_fd );
2847 lsapi_notify_pid( pReq->m_fd );
2848 s_notified_pid = 1;
2849 //if ( s_accept_notify )
2850 // return notify_req_received( pReq->m_fd );
2851 return 0;
2852 }
2853 else if ( pid == -1 )
2854 {
2855 perror( "fork() failed, please increase process limit" );
2856 }
2857 else
2858 {
2859 ++pServer->m_iCurChildren;
2860 if ( child_status )
2861 {
2862 child_status->m_pid = pid;
2863 child_status->m_tmWaitBegin = curTime;
2864 child_status->m_tmStart = curTime;
2865 }
2866 }
2867 close( pReq->m_fd );
2868 pReq->m_fd = -1;
2869
2870 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2871 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
2872
2873 }
2874 else
2875 {
2876 if (( errno == EINTR )||( errno == EAGAIN))
2877 continue;
2878 perror( "accept() failed" );
2879 return -1;
2880 }
2881 }
2882 sigaction( SIGUSR1, &old_usr1, 0 );
2883 //kill( -getpgrp(), SIGUSR1 );
2884 //lsapi_all_children_must_die(); /* Sorry, children ;-) */
2885 return -1;
2886
2887 }
2888
lsapi_error(const char * pMessage,int err_no)2889 void lsapi_error( const char * pMessage, int err_no )
2890 {
2891 fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
2892 }
2893
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)2894 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2895 {
2896 int fd;
2897 int ret;
2898 int wait_secs;
2899 fd_set readfds;
2900 struct timeval timeout;
2901
2902 LSAPI_Finish_r( pReq );
2903
2904
2905 if ( g_prefork_server )
2906 {
2907 if ( g_prefork_server->m_fd != -1 )
2908 if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
2909 return -1;
2910 }
2911 if ( s_req_processed >= s_max_reqs )
2912 return -1;
2913
2914 if ( s_pChildStatus )
2915 {
2916 s_pChildStatus->m_tmWaitBegin = time( NULL );
2917 }
2918
2919
2920 while( g_running )
2921 {
2922 if ( pReq->m_fd != -1 )
2923 {
2924 fd = pReq->m_fd;
2925 }
2926 else if ( pReq->m_fdListen != -1 )
2927 fd = pReq->m_fdListen;
2928 else
2929 {
2930 break;
2931 }
2932 wait_secs = 0;
2933 while( 1 )
2934 {
2935 if ( !g_running )
2936 return -1;
2937 if ((s_req_processed)&&( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2938 return -1;
2939 FD_ZERO( &readfds );
2940 FD_SET( fd, &readfds );
2941 timeout.tv_sec = 1;
2942 timeout.tv_usec = 0;
2943 ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
2944 if ( ret == 0 )
2945 {
2946 if ( s_pChildStatus )
2947 {
2948 s_pChildStatus->m_inProcess = 0;
2949 }
2950 ++wait_secs;
2951 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
2952 return -1;
2953 if ( s_ppid &&( getppid() != s_ppid))
2954 return -1;
2955 }
2956 else if ( ret == -1 )
2957 {
2958 if ( errno == EINTR )
2959 continue;
2960 else
2961 return -1;
2962 }
2963 else if ( ret >= 1 )
2964 {
2965 if (s_req_processed && ( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2966 return -1;
2967 if ( fd == pReq->m_fdListen )
2968 {
2969 pReq->m_fd = lsapi_accept( pReq->m_fdListen );
2970 if ( pReq->m_fd != -1 )
2971 {
2972 fd = pReq->m_fd;
2973 lsapi_set_nblock( fd, 0 );
2974 //init_conn_key( pReq->m_fd );
2975 if ( !s_keepListener )
2976 {
2977 close( pReq->m_fdListen );
2978 pReq->m_fdListen = -1;
2979 }
2980 if ( s_accept_notify )
2981 if ( notify_req_received( pReq->m_fd ) == -1 )
2982 return -1;
2983 }
2984 else
2985 {
2986 if (( errno == EINTR )||( errno == EAGAIN))
2987 continue;
2988 lsapi_error( "lsapi_accept() error", errno );
2989 return -1;
2990 }
2991 }
2992 else
2993 break;
2994 }
2995 }
2996
2997 if ( !readReq( pReq ) )
2998 {
2999 if ( s_pChildStatus )
3000 {
3001 s_pChildStatus->m_iKillSent = 0;
3002 s_pChildStatus->m_inProcess = 1;
3003 ++s_pChildStatus->m_iReqCounter;
3004 s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
3005 }
3006 ++s_req_processed;
3007 return 0;
3008 }
3009 lsapi_close( pReq->m_fd );
3010 pReq->m_fd = -1;
3011 LSAPI_Reset_r( pReq );
3012 }
3013 return -1;
3014
3015 }
3016
LSAPI_Set_Max_Reqs(int reqs)3017 void LSAPI_Set_Max_Reqs( int reqs )
3018 { s_max_reqs = reqs; }
3019
LSAPI_Set_Max_Idle(int secs)3020 void LSAPI_Set_Max_Idle( int secs )
3021 { s_max_idle_secs = secs; }
3022
LSAPI_Set_Max_Children(int maxChildren)3023 void LSAPI_Set_Max_Children( int maxChildren )
3024 {
3025 if ( g_prefork_server )
3026 g_prefork_server->m_iMaxChildren = maxChildren;
3027 }
3028
LSAPI_Set_Extra_Children(int extraChildren)3029 void LSAPI_Set_Extra_Children( int extraChildren )
3030 {
3031 if (( g_prefork_server )&&( extraChildren >= 0 ))
3032 g_prefork_server->m_iExtraChildren = extraChildren;
3033 }
3034
LSAPI_Set_Max_Process_Time(int secs)3035 void LSAPI_Set_Max_Process_Time( int secs )
3036 {
3037 if (( g_prefork_server )&&( secs > 0 ))
3038 g_prefork_server->m_iMaxReqProcessTime = secs;
3039 }
3040
3041
LSAPI_Set_Max_Idle_Children(int maxIdleChld)3042 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3043 {
3044 if (( g_prefork_server )&&( maxIdleChld > 0 ))
3045 g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3046 }
3047
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)3048 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3049 {
3050 if ( g_prefork_server )
3051 g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3052 }
3053
LSAPI_Set_Slow_Req_Msecs(int msecs)3054 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3055 {
3056 s_slow_req_msecs = msecs;
3057 }
3058
LSAPI_Get_Slow_Req_Msecs()3059 int LSAPI_Get_Slow_Req_Msecs()
3060 {
3061 return s_slow_req_msecs;
3062 }
3063
3064
LSAPI_No_Check_ppid()3065 void LSAPI_No_Check_ppid()
3066 {
3067 s_ppid = 0;
3068 }
3069
3070 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3071 #include <crt_externs.h>
3072 #else
3073 extern char ** environ;
3074 #endif
unset_lsapi_envs()3075 static void unset_lsapi_envs()
3076 {
3077 char **env;
3078 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3079 env = *_NSGetEnviron();
3080 #else
3081 env = environ;
3082 #endif
3083 while( env != NULL && *env != NULL )
3084 {
3085 if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3086 || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3087 {
3088 char ** del = env;
3089 do
3090 *del = del[1];
3091 while( *del++ );
3092 }
3093 else
3094 ++env;
3095 }
3096 }
3097
lsapi_initSuEXEC()3098 static int lsapi_initSuEXEC()
3099 {
3100 int i;
3101 struct passwd * pw;
3102 s_defaultUid = 0;
3103 s_defaultGid = 0;
3104 if ( s_uid == 0 )
3105 {
3106 const char * p = getenv( "LSAPI_DEFAULT_UID" );
3107 if ( p )
3108 {
3109 i = atoi( p );
3110 if ( i > 0 )
3111 s_defaultUid = i;
3112 }
3113 p = getenv( "LSAPI_DEFAULT_GID" );
3114 if ( p )
3115 {
3116 i = atoi( p );
3117 if ( i > 0 )
3118 s_defaultGid = i;
3119 }
3120 p = getenv( "LSAPI_SECRET" );
3121 if (( !p )||( readSecret(p) == -1 ))
3122 return -1;
3123 if ( g_prefork_server )
3124 {
3125 if ( g_prefork_server->m_iMaxChildren < 100 )
3126 g_prefork_server->m_iMaxChildren = 100;
3127 if ( g_prefork_server->m_iExtraChildren < 1000 )
3128 g_prefork_server->m_iExtraChildren = 1000;
3129 }
3130 }
3131 if ( !s_defaultUid || !s_defaultGid )
3132 {
3133 pw = getpwnam( "nobody" );
3134 if ( pw )
3135 {
3136 if ( !s_defaultUid )
3137 s_defaultUid = pw->pw_uid;
3138 if ( !s_defaultGid )
3139 s_defaultGid = pw->pw_gid;
3140 }
3141 else
3142 {
3143 if ( !s_defaultUid )
3144 s_defaultUid = 10000;
3145 if ( !s_defaultGid )
3146 s_defaultGid = 10000;
3147 }
3148 }
3149 return 0;
3150 }
3151
3152
LSAPI_Init_Env_Parameters(fn_select_t fp)3153 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3154 {
3155 const char *p;
3156 int n;
3157 int avoidFork = 0;
3158 p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3159 if ( !p )
3160 p = getenv( "LSAPI_MAX_REQS" );
3161 if ( p )
3162 {
3163 n = atoi( p );
3164 if ( n > 0 )
3165 LSAPI_Set_Max_Reqs( n );
3166 }
3167
3168 p = getenv( "LSAPI_AVOID_FORK" );
3169 if ( p )
3170 {
3171 avoidFork = atoi( p );
3172 }
3173
3174 p = getenv( "LSAPI_ACCEPT_NOTIFY" );
3175 if ( p )
3176 {
3177 s_accept_notify = atoi( p );
3178 }
3179
3180 p = getenv( "LSAPI_SLOW_REQ_MSECS" );
3181 if ( p )
3182 {
3183 n = atoi( p );
3184 LSAPI_Set_Slow_Req_Msecs( n );
3185 }
3186
3187 #if defined( RLIMIT_CORE )
3188 p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
3189 if ( !p )
3190 {
3191 struct rlimit limit = { 0, 0 };
3192 setrlimit( RLIMIT_CORE, &limit );
3193 }
3194 else
3195 s_enable_core_dump = 1;
3196
3197 #endif
3198
3199 p = getenv( "LSAPI_MAX_IDLE" );
3200 if ( p )
3201 {
3202 n = atoi( p );
3203 LSAPI_Set_Max_Idle( n );
3204 }
3205
3206 p = getenv( "LSAPI_KEEP_LISTEN" );
3207 if ( p )
3208 {
3209 n = atoi( p );
3210 s_keepListener = n;
3211 }
3212
3213
3214 if ( LSAPI_Is_Listen() )
3215 {
3216 n = 0;
3217 p = getenv( "PHP_LSAPI_CHILDREN" );
3218 if ( !p )
3219 p = getenv( "LSAPI_CHILDREN" );
3220 if ( p )
3221 n = atoi( p );
3222 if ( n > 1 )
3223 {
3224 LSAPI_Init_Prefork_Server( n, fp, avoidFork );
3225 LSAPI_Set_Server_fd( g_req.m_fdListen );
3226 }
3227
3228 p = getenv( "LSAPI_EXTRA_CHILDREN" );
3229 if ( p )
3230 LSAPI_Set_Extra_Children( atoi( p ) );
3231
3232 p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
3233 if ( p )
3234 LSAPI_Set_Max_Idle_Children( atoi( p ) );
3235
3236 p = getenv( "LSAPI_PGRP_MAX_IDLE" );
3237 if ( p )
3238 {
3239 LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
3240 }
3241
3242 p = getenv( "LSAPI_MAX_PROCESS_TIME" );
3243 if ( p )
3244 LSAPI_Set_Max_Process_Time( atoi( p ) );
3245
3246 if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
3247 {
3248 LSAPI_No_Check_ppid();
3249 }
3250
3251 p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
3252 if ( p )
3253 s_dump_debug_info = atoi( p );
3254
3255 if ( lsapi_initSuEXEC() == -1 )
3256 return -1;
3257 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3258 lsapi_initLVE();
3259 #endif
3260 }
3261 unset_lsapi_envs();
3262 return 0;
3263 }
3264
3265
LSAPI_ErrResponse_r(LSAPI_Request * pReq,int code,const char ** pRespHeaders,const char * pBody,int bodyLen)3266 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
3267 const char * pBody, int bodyLen )
3268 {
3269 LSAPI_SetRespStatus_r( pReq, code );
3270 if ( pRespHeaders )
3271 {
3272 while( *pRespHeaders )
3273 {
3274 LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
3275 ++pRespHeaders;
3276 }
3277 }
3278 if ( pBody &&( bodyLen > 0 ))
3279 {
3280 LSAPI_Write_r( pReq, pBody, bodyLen );
3281 }
3282 LSAPI_Finish_r( pReq );
3283 return 0;
3284 }
3285
3286
3287 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
3288
3289 /*
3290 * Note: this code is harmless on little-endian machines.
3291 */
byteReverse(unsigned char * buf,unsigned longs)3292 static void byteReverse(unsigned char *buf, unsigned longs)
3293 {
3294 uint32 t;
3295 do {
3296 t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
3297 ((unsigned) buf[1] << 8 | buf[0]);
3298 *(uint32 *) buf = t;
3299 buf += 4;
3300 } while (--longs);
3301 }
3302
3303 /*
3304 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
3305 * initialization constants.
3306 */
lsapi_MD5Init(struct lsapi_MD5Context * ctx)3307 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
3308 {
3309 ctx->buf[0] = 0x67452301;
3310 ctx->buf[1] = 0xefcdab89;
3311 ctx->buf[2] = 0x98badcfe;
3312 ctx->buf[3] = 0x10325476;
3313
3314 ctx->bits[0] = 0;
3315 ctx->bits[1] = 0;
3316 }
3317
3318 /*
3319 * Update context to reflect the concatenation of another buffer full
3320 * of bytes.
3321 */
lsapi_MD5Update(struct lsapi_MD5Context * ctx,unsigned char const * buf,unsigned len)3322 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
3323 {
3324 register uint32 t;
3325
3326 /* Update bitcount */
3327
3328 t = ctx->bits[0];
3329 if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
3330 ctx->bits[1]++; /* Carry from low to high */
3331 ctx->bits[1] += len >> 29;
3332
3333 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
3334
3335 /* Handle any leading odd-sized chunks */
3336
3337 if (t) {
3338 unsigned char *p = (unsigned char *) ctx->in + t;
3339
3340 t = 64 - t;
3341 if (len < t) {
3342 memmove(p, buf, len);
3343 return;
3344 }
3345 memmove(p, buf, t);
3346 byteReverse(ctx->in, 16);
3347 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3348 buf += t;
3349 len -= t;
3350 }
3351 /* Process data in 64-byte chunks */
3352
3353 while (len >= 64) {
3354 memmove(ctx->in, buf, 64);
3355 byteReverse(ctx->in, 16);
3356 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3357 buf += 64;
3358 len -= 64;
3359 }
3360
3361 /* Handle any remaining bytes of data. */
3362
3363 memmove(ctx->in, buf, len);
3364 }
3365
3366 /*
3367 * Final wrapup - pad to 64-byte boundary with the bit pattern
3368 * 1 0* (64-bit count of bits processed, MSB-first)
3369 */
lsapi_MD5Final(unsigned char digest[16],struct lsapi_MD5Context * ctx)3370 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
3371 {
3372 unsigned int count;
3373 unsigned char *p;
3374
3375 /* Compute number of bytes mod 64 */
3376 count = (ctx->bits[0] >> 3) & 0x3F;
3377
3378 /* Set the first char of padding to 0x80. This is safe since there is
3379 always at least one byte free */
3380 p = ctx->in + count;
3381 *p++ = 0x80;
3382
3383 /* Bytes of padding needed to make 64 bytes */
3384 count = 64 - 1 - count;
3385
3386 /* Pad out to 56 mod 64 */
3387 if (count < 8) {
3388 /* Two lots of padding: Pad the first block to 64 bytes */
3389 memset(p, 0, count);
3390 byteReverse(ctx->in, 16);
3391 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3392
3393 /* Now fill the next block with 56 bytes */
3394 memset(ctx->in, 0, 56);
3395 } else {
3396 /* Pad block to 56 bytes */
3397 memset(p, 0, count - 8);
3398 }
3399 byteReverse(ctx->in, 14);
3400
3401 /* Append length in bits and transform */
3402 ((uint32 *) ctx->in)[14] = ctx->bits[0];
3403 ((uint32 *) ctx->in)[15] = ctx->bits[1];
3404
3405 lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3406 byteReverse((unsigned char *) ctx->buf, 4);
3407 memmove(digest, ctx->buf, 16);
3408 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
3409 }
3410
3411 /* The four core functions - F1 is optimized somewhat */
3412
3413 /* #define F1(x, y, z) (x & y | ~x & z) */
3414 #define F1(x, y, z) (z ^ (x & (y ^ z)))
3415 #define F2(x, y, z) F1(z, x, y)
3416 #define F3(x, y, z) (x ^ y ^ z)
3417 #define F4(x, y, z) (y ^ (x | ~z))
3418
3419 /* This is the central step in the MD5 algorithm. */
3420 #define MD5STEP(f, w, x, y, z, data, s) \
3421 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
3422
3423 /*
3424 * The core of the MD5 algorithm, this alters an existing MD5 hash to
3425 * reflect the addition of 16 longwords of new data. MD5Update blocks
3426 * the data and converts bytes into longwords for this routine.
3427 */
lsapi_MD5Transform(uint32 buf[4],uint32 const in[16])3428 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
3429 {
3430 register uint32 a, b, c, d;
3431
3432 a = buf[0];
3433 b = buf[1];
3434 c = buf[2];
3435 d = buf[3];
3436
3437 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3438 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3439 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
3440 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3441 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3442 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3443 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
3444 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
3445 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
3446 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3447 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3448 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3449 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
3450 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
3451 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
3452 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
3453
3454 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3455 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
3456 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3457 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3458 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3459 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
3460 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3461 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3462 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3463 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3464 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3465 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3466 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3467 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3468 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3469 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
3470
3471 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
3472 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
3473 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
3474 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
3475 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
3476 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
3477 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
3478 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
3479 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
3480 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
3481 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
3482 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
3483 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
3484 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
3485 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
3486 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
3487
3488 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
3489 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
3490 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
3491 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
3492 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
3493 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
3494 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
3495 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
3496 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
3497 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
3498 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
3499 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
3500 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
3501 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
3502 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
3503 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
3504
3505 buf[0] += a;
3506 buf[1] += b;
3507 buf[2] += c;
3508 buf[3] += d;
3509 }
3510
3511