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