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