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