ruby-lsapi 4.0 → 4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTBmYTY2NTdiZDk3NjAxNTViYmExOTc4ZDU5ZjJhYjk1MmFmNjhiZA==
5
+ data.tar.gz: !binary |-
6
+ YmRkNDNhMGZiMmI5Y2I2YjQ0M2Q4OTkzZWVhMjRkMmFmZjA4ZDFlYQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTg2NGQ5Zjc1NWUyYTExNDUzMTYzN2VhODAyMDI4N2Y0MDFhMTBiMThkMWNm
10
+ MWU3NDY0Njg4MzcxZDUyYmYzYjJjMjIyYTUxNGU4YTUyOGQ1ZDIxZDg1YWJh
11
+ YjZlNDJlNTJhMWJkMzZiOWVjMmE2ODQ2ZGNmMTkzMzk1MDRhMDg=
12
+ data.tar.gz: !binary |-
13
+ MzBmZDNhMmY5NGQ3NWY0NmJmMDIyMTgzNTUyMDBhZDczMzM2Y2MwY2I5YzAx
14
+ NGYxN2M0OWEyYTQ1YjYzNTEwNzlmNGQ3ZGY4ZDU1MGM3MTQ2NThlZDkwODBi
15
+ MjExZWRkOWIxZTI1NGVjMWEwMDNmYzBkNTBjMTBhNmFlZTc5ZTM=
data/ext/lsapi/lsapidef.h CHANGED
@@ -31,7 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
31
  */
32
32
 
33
33
  /***************************************************************************
34
- $Id: lsapidef.h,v 1.15 2008/01/03 18:31:50 gwang Exp $
34
+ $Id: lsapidef.h,v 1.17 2012/12/01 19:23:31 gwang Exp $
35
35
  -------------------
36
36
  begin : Thu Feb 10 2005
37
37
  author : George Wang
@@ -100,12 +100,14 @@ enum
100
100
  #define LSAPI_RESP_END 5
101
101
  #define LSAPI_STDERR_STREAM 6
102
102
  #define LSAPI_REQ_RECEIVED 7
103
+ #define LSAPI_CONN_CLOSE 8
104
+ #define LSAPI_INTERNAL_ERROR 9
103
105
 
104
106
 
105
107
  #define LSAPI_MAX_HEADER_LEN 65535
106
108
  #define LSAPI_MAX_DATA_PACKET_LEN 16384
107
109
 
108
- #define LSAPI_RESP_HTTP_HEADER_MAX 4096
110
+ #define LSAPI_RESP_HTTP_HEADER_MAX 32768
109
111
  #define LSAPI_PACKET_HEADER_LEN 8
110
112
 
111
113
 
data/ext/lsapi/lsapilib.c CHANGED
@@ -39,17 +39,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
39
  ***************************************************************************/
40
40
 
41
41
 
42
- #include <lsapilib.h>
43
-
44
42
  #include <ctype.h>
43
+ #include <dlfcn.h>
45
44
  #include <errno.h>
46
45
  #include <fcntl.h>
47
46
 
48
- #include <arpa/inet.h>
49
- #include <netdb.h>
50
- #include <netinet/in.h>
51
- #include <netinet/tcp.h>
52
- #include <sys/un.h>
47
+ #include <sys/stat.h>
53
48
  #include <signal.h>
54
49
  #include <stdlib.h>
55
50
  #include <stdio.h>
@@ -60,8 +55,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60
55
  #include <sys/time.h>
61
56
  #include <sys/uio.h>
62
57
  #include <sys/wait.h>
58
+ #include <grp.h>
59
+ #include <pwd.h>
63
60
  #include <time.h>
64
61
  #include <unistd.h>
62
+ #include <arpa/inet.h>
63
+ #include <netdb.h>
64
+ #include <netinet/in.h>
65
+ #include <netinet/tcp.h>
66
+ #include <sys/un.h>
67
+
68
+ #include "lsapilib.h"
69
+
70
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
71
+ #include <sys/prctl.h>
72
+ #endif
73
+
74
+ #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
75
+ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
76
+ #include <sys/sysctl.h>
77
+ #endif
78
+
79
+ #include <inttypes.h>
80
+ #ifndef uint32
81
+ #define uint32 uint32_t
82
+ #endif
83
+
84
+ struct lsapi_MD5Context {
85
+ uint32 buf[4];
86
+ uint32 bits[2];
87
+ unsigned char in[64];
88
+ };
89
+
90
+ void lsapi_MD5Init(struct lsapi_MD5Context *context);
91
+ void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
92
+ unsigned len);
93
+ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
94
+
95
+ /*
96
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
97
+ */
98
+ typedef struct lsapi_MD5Context lsapi_MD5_CTX;
99
+
65
100
 
66
101
  #define LSAPI_ST_REQ_HEADER 1
67
102
  #define LSAPI_ST_REQ_BODY 2
@@ -72,12 +107,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72
107
  #define LSAPI_INIT_RESP_HEADER_LEN 4096
73
108
 
74
109
 
110
+
75
111
  static int g_inited = 0;
76
112
  static int g_running = 1;
77
113
  static int s_ppid;
78
114
  static int s_slow_req_msecs = 0;
115
+ static int s_keepListener = 0;
116
+ static int s_dump_debug_info = 0;
117
+
79
118
  LSAPI_Request g_req = { -1, -1 };
80
119
 
120
+ static char s_pSecret[24];
121
+
122
+
81
123
  void Flush_RespBuf_r( LSAPI_Request * pReq );
82
124
 
83
125
  static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
@@ -160,6 +202,35 @@ static void lsapi_signal(int signo, sighandler_t handler)
160
202
  }
161
203
 
162
204
 
205
+ static int s_enable_core_dump = 0;
206
+ static void lsapi_enable_core_dump()
207
+ {
208
+ #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
209
+ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
210
+ int mib[2];
211
+ size_t len;
212
+
213
+ len = 2;
214
+ if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
215
+ {
216
+ len = sizeof(s_enable_core_dump);
217
+ if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
218
+ perror( "sysctl: Failed to set 'kern.sugid_coredump', "
219
+ "core dump may not be available!");
220
+ }
221
+
222
+
223
+ #endif
224
+
225
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
226
+ if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
227
+ perror( "prctl: Failed to set dumpable, "
228
+ "core dump may not be available!");
229
+ #endif
230
+ }
231
+
232
+
233
+
163
234
  static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
164
235
  char type, int len )
165
236
  {
@@ -202,9 +273,9 @@ static int lsapi_close( int fd )
202
273
  }
203
274
  }
204
275
 
205
- static inline int lsapi_read( int fd, void * pBuf, int len )
276
+ static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
206
277
  {
207
- int ret;
278
+ ssize_t ret;
208
279
  while( 1 )
209
280
  {
210
281
  ret = read( fd, (char *)pBuf, len );
@@ -251,7 +322,7 @@ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
251
322
  return totalLen - left;
252
323
  while( ret > 0 )
253
324
  {
254
- if ( (*pVec)->iov_len <= ret )
325
+ if ( (*pVec)->iov_len <= (unsigned int )ret )
255
326
  {
256
327
  ret -= (*pVec)->iov_len;
257
328
  ++(*pVec);
@@ -475,8 +546,426 @@ static void fixHeaderIndexEndian( LSAPI_Request * pReq )
475
546
  swapIntEndian( &pCur->valueLen );
476
547
  ++pCur;
477
548
  }
478
- }
549
+ }
550
+ }
551
+
552
+ static uid_t s_uid = 0;
553
+ static uid_t s_defaultUid; //web server need set this
554
+ static gid_t s_defaultGid;
555
+
556
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
557
+
558
+ #define LSAPI_LVE_DISABLED 0
559
+ #define LSAPI_LVE_ENABLED 1
560
+ #define LSAPI_CAGEFS_ENABLED 2
561
+ #define LSAPI_CAGEFS_NO_SUEXEC 3
562
+ struct liblve;
563
+ static int s_enable_lve = LSAPI_LVE_DISABLED;
564
+ static struct liblve * s_lve = NULL;
565
+
566
+ static void *s_liblve;
567
+ static int (*fp_lve_is_available)(void) = NULL;
568
+ static int (*fp_lve_instance_init)(struct liblve *) = NULL;
569
+ static int (*fp_lve_destroy)(struct liblve *) = NULL;
570
+ static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
571
+ static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
572
+ static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
573
+ static int lsapi_load_lve_lib()
574
+ {
575
+ s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
576
+ if (s_liblve)
577
+ {
578
+ fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
579
+ if (dlerror() == NULL)
580
+ {
581
+ if ( !(*fp_lve_is_available)() )
582
+ {
583
+ int uid = getuid();
584
+ if ( uid )
585
+ {
586
+ setreuid( s_uid, uid );
587
+ if ( !(*fp_lve_is_available)() )
588
+ s_enable_lve = 0;
589
+ setreuid( uid, s_uid );
590
+ }
591
+ }
592
+ }
593
+ }
594
+ else
595
+ {
596
+ s_enable_lve = LSAPI_LVE_DISABLED;
597
+ }
598
+ return (s_liblve)? 0 : -1;
599
+ }
600
+
601
+ static int init_lve_ex()
602
+ {
603
+ int rc;
604
+ if ( !s_liblve )
605
+ return -1;
606
+ fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
607
+ fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
608
+ fp_lve_enter = dlsym(s_liblve, "lve_enter");
609
+ fp_lve_leave = dlsym(s_liblve, "lve_leave");
610
+ if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
611
+ fp_lve_jail = dlsym(s_liblve, "jail" );
612
+
613
+ if ( s_lve == NULL )
614
+ {
615
+ rc = (*fp_lve_instance_init)(NULL);
616
+ s_lve = malloc(rc);
617
+ }
618
+ rc = (*fp_lve_instance_init)(s_lve);
619
+ if (rc != 0)
620
+ {
621
+ perror( "LSAPI: Unable to initialize LVE" );
622
+ free( s_lve );
623
+ s_lve = NULL;
624
+ return -1;
625
+ }
626
+ return 0;
627
+
628
+ }
629
+
630
+ #endif
631
+
632
+
633
+
634
+ static int readSecret( const char * pSecretFile )
635
+ {
636
+ struct stat st;
637
+ int fd = open( pSecretFile, O_RDONLY , 0600 );
638
+ if ( fd == -1 )
639
+ {
640
+ fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile );
641
+ return -1;
642
+ }
643
+ if ( fstat( fd, &st ) == -1 )
644
+ {
645
+ fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile );
646
+ close( fd );
647
+ return -1;
648
+ }
649
+ /*
650
+ if ( st.st_uid != s_uid )
651
+ {
652
+ fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile );
653
+ close( fd );
654
+ return -1;
655
+ }
656
+ */
657
+ if ( st.st_mode & 0077 )
658
+ {
659
+ fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile );
660
+ close( fd );
661
+ return -1;
662
+ }
663
+ if ( read( fd, s_pSecret, 16 ) < 16 )
664
+ {
665
+ fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
666
+ close( fd );
667
+ return -1;
668
+ }
669
+ close( fd );
670
+ return 0;
671
+ }
672
+
673
+ static int lsapi_initSuEXEC()
674
+ {
675
+ int i;
676
+ struct passwd * pw;
677
+ pw = getpwnam( "nobody" );
678
+ s_defaultUid = pw->pw_uid;
679
+ s_defaultGid = pw->pw_gid;
680
+ if ( s_uid == 0 )
681
+ {
682
+ const char * p = getenv( "LSAPI_DEFAULT_UID" );
683
+ if ( p )
684
+ {
685
+ i = atoi( p );
686
+ if ( i > 0 )
687
+ s_defaultUid = i;
688
+ }
689
+ p = getenv( "LSAPI_DEFAULT_GID" );
690
+ if ( p )
691
+ {
692
+ i = atoi( p );
693
+ if ( i > 0 )
694
+ s_defaultGid = i;
695
+ }
696
+ p = getenv( "LSAPI_SECRET" );
697
+ if (( !p )||( readSecret(p) == -1 ))
698
+ return -1;
699
+ }
700
+ return 0;
701
+ }
702
+
703
+ int LSAPI_is_suEXEC_Daemon()
704
+ {
705
+ if (( !s_uid )&&( s_pSecret[0] ))
706
+ return 1;
707
+ else
708
+ return 0;
709
+ }
710
+
711
+ static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
712
+ {
713
+ char achError[1024];
714
+ int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
715
+ if ( pReq )
716
+ LSAPI_Write_Stderr_r( pReq, achError, n );
717
+ else
718
+ write( STDERR_FILENO, achError, n );
719
+ return 0;
720
+ }
721
+
722
+ static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
723
+ {
724
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
725
+ if ( s_lve && uid ) //root user should not do that
726
+ {
727
+ uint32_t cookie;
728
+ int ret = -1;
729
+ ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
730
+ if ( ret < 0 )
731
+ {
732
+ fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret );
733
+ LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
734
+ return -1;
735
+ }
736
+ }
737
+ #endif
738
+
739
+ return 0;
740
+ }
741
+
742
+ static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
743
+ {
744
+ int ret = 0;
745
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
746
+ char error_msg[1024] = "";
747
+ ret = (*fp_lve_jail)( pw, error_msg );
748
+ if ( ret < 0 )
749
+ {
750
+ fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n",
751
+ getpid(), uid, ret, error_msg );
752
+ LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
753
+ return -1;
754
+ }
755
+ #endif
756
+ return ret;
757
+ }
758
+
759
+
760
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
761
+ static int lsapi_initLVE()
762
+ {
763
+ const char * pEnv;
764
+ if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
765
+ {
766
+ s_enable_lve = atol( pEnv );
767
+ pEnv = NULL;
768
+ }
769
+ else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
770
+ {
771
+ s_enable_lve = atol( pEnv );
772
+ pEnv = NULL;
773
+ }
774
+ if ( s_enable_lve && !s_uid )
775
+ {
776
+ lsapi_load_lve_lib();
777
+ if ( s_enable_lve )
778
+ {
779
+ return init_lve_ex();
780
+ }
781
+
782
+ }
783
+ return 0;
479
784
  }
785
+ #endif
786
+
787
+
788
+ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
789
+ {
790
+ int rv;
791
+ struct passwd * pw;
792
+ pw = getpwuid( uid );
793
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
794
+ if ( s_lve )
795
+ {
796
+ if( lsapi_enterLVE( pReq, uid ) == -1 )
797
+ return -1;
798
+ if ( pw && fp_lve_jail)
799
+ {
800
+ rv = lsapi_jailLVE( pReq, uid, pw );
801
+ if ( rv == -1 )
802
+ return -1;
803
+ if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC
804
+ {
805
+ uid = s_defaultUid;
806
+ gid = s_defaultGid;
807
+ pw = getpwuid( uid );
808
+ }
809
+ }
810
+ }
811
+ #endif
812
+ //if ( !uid || !gid ) //do not allow root
813
+ //{
814
+ // return -1;
815
+ //}
816
+
817
+ #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
818
+ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
819
+ if ( s_enable_core_dump )
820
+ lsapi_enable_core_dump();
821
+ #endif
822
+
823
+ rv = setgid(gid);
824
+ if (rv == -1)
825
+ {
826
+ LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
827
+ return -1;
828
+ }
829
+ if ( pw && (pw->pw_gid == gid ))
830
+ {
831
+ rv = initgroups( pw->pw_name, gid );
832
+ if (rv == -1)
833
+ {
834
+ LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
835
+ return -1;
836
+ }
837
+ }
838
+ else
839
+ {
840
+ rv = setgroups(1, &gid);
841
+ if (rv == -1)
842
+ {
843
+ LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
844
+ }
845
+ }
846
+ if ( pChroot )
847
+ {
848
+ rv = chroot( pChroot );
849
+ if ( rv == -1 )
850
+ {
851
+ LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
852
+ return -1;
853
+ }
854
+ }
855
+ rv = setuid(uid);
856
+ if (rv == -1)
857
+ {
858
+ LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
859
+ return -1;
860
+ }
861
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
862
+ if ( s_enable_core_dump )
863
+ lsapi_enable_core_dump();
864
+ #endif
865
+ return 0;
866
+ }
867
+
868
+ static int lsapi_suexec_auth( LSAPI_Request *pReq,
869
+ char * pAuth, int len, char * pUgid, int ugidLen )
870
+ {
871
+ lsapi_MD5_CTX md5ctx;
872
+ unsigned char achMD5[16];
873
+ if ( len < 32 )
874
+ return -1;
875
+ memmove( achMD5, pAuth + 16, 16 );
876
+ memmove( pAuth + 16, s_pSecret, 16 );
877
+ lsapi_MD5Init( &md5ctx );
878
+ lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
879
+ lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
880
+ lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
881
+ if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
882
+ return 0;
883
+ return 1;
884
+ }
885
+
886
+
887
+ static int lsapi_changeUGid( LSAPI_Request * pReq )
888
+ {
889
+ int uid = s_defaultUid;
890
+ int gid = s_defaultGid;
891
+ const char * pChroot = NULL;
892
+ struct LSAPI_key_value_pair * pEnv;
893
+ struct LSAPI_key_value_pair * pAuth;
894
+ int i;
895
+ if ( s_uid )
896
+ return 0;
897
+ //with special ID 0x00
898
+ //authenticate the suEXEC request;
899
+ //first one should be MD5( nonce + lscgid secret )
900
+ //remember to clear the secret after verification
901
+ //it should be set at the end of special env
902
+ i = pReq->m_pHeader->m_cntSpecialEnv - 1;
903
+ if ( i >= 0 )
904
+ {
905
+ pEnv = pReq->m_pSpecialEnvList + i;
906
+ if (( *pEnv->pKey == '\000' )&&
907
+ ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
908
+ {
909
+ --pReq->m_pHeader->m_cntSpecialEnv;
910
+ pAuth = pEnv--;
911
+ if (( *pEnv->pKey == '\000' )&&
912
+ ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
913
+ {
914
+ --pReq->m_pHeader->m_cntSpecialEnv;
915
+ uid = *(uint32_t *)pEnv->pValue;
916
+ gid = *(((uint32_t *)pEnv->pValue) + 1 );
917
+ //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
918
+ }
919
+ else
920
+ {
921
+ fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" );
922
+ pEnv = NULL;
923
+ }
924
+ if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
925
+ {
926
+ //read UID, GID from specialEnv
927
+
928
+ }
929
+ else
930
+ {
931
+ //authentication error
932
+ fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
933
+ uid = 0;
934
+ }
935
+ }
936
+ else
937
+ {
938
+ //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" );
939
+ }
940
+ }
941
+
942
+
943
+ if ( !uid )
944
+ {
945
+ uid = s_defaultUid;
946
+ gid = s_defaultGid;
947
+ }
948
+
949
+ //change uid
950
+ if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
951
+ {
952
+ return -1;
953
+ }
954
+
955
+ s_uid = uid;
956
+
957
+ return 0;
958
+
959
+ }
960
+
961
+ static int parseContentLenFromHeader(LSAPI_Request * pReq)
962
+ {
963
+ const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
964
+ if ( pContentLen )
965
+ pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
966
+ return 0;
967
+ }
968
+
480
969
 
481
970
  static int parseRequest( LSAPI_Request * pReq, int totalLen )
482
971
  {
@@ -523,13 +1012,21 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
523
1012
  pReq->m_pHttpHeader = pBegin;
524
1013
  pBegin += pReq->m_pHeader->m_httpHeaderLen;
525
1014
  if ( pBegin != pEnd )
1015
+ {
1016
+ fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen,
1017
+ pBegin - pReq->m_pReqBuf );
526
1018
  return -1;
527
-
1019
+ }
528
1020
  if ( shouldFixEndian )
529
1021
  {
530
1022
  fixHeaderIndexEndian( pReq );
531
1023
  }
532
-
1024
+ pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1025
+ if ( pReq->m_reqBodyLen == -2 )
1026
+ {
1027
+ parseContentLenFromHeader(pReq);
1028
+ }
1029
+
533
1030
  return 0;
534
1031
  }
535
1032
 
@@ -546,11 +1043,45 @@ static inline int notify_req_received( int fd )
546
1043
  return 0;
547
1044
  }
548
1045
 
1046
+ static inline int lsapi_notify_pid( int fd )
1047
+ {
1048
+ char achBuf[16];
1049
+ lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1050
+ 8 + LSAPI_PACKET_HEADER_LEN );
1051
+ memmove( &achBuf[8], "\0PID", 4 );
1052
+ *((int *)&achBuf[12]) = getpid();
1053
+
1054
+ if ( write( fd, achBuf, 16 ) < 16 )
1055
+ return -1;
1056
+ return 0;
1057
+ }
1058
+
1059
+ static char s_conn_key_packet[16];
1060
+ static inline int init_conn_key( int fd )
1061
+ {
1062
+ struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
1063
+ struct timeval tv;
1064
+ int i;
1065
+ gettimeofday( &tv, NULL );
1066
+ srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
1067
+ for( i = 8; i < 16; ++i )
1068
+ {
1069
+ s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
1070
+ }
1071
+ lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
1072
+ 8 + LSAPI_PACKET_HEADER_LEN );
1073
+ if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
1074
+ < LSAPI_PACKET_HEADER_LEN+8 )
1075
+ return -1;
1076
+ return 0;
1077
+
1078
+
1079
+ }
549
1080
 
550
1081
  static int readReq( LSAPI_Request * pReq )
551
1082
  {
552
- int len;
553
- int packetLen;
1083
+ int len;
1084
+ int packetLen;
554
1085
  if ( !pReq )
555
1086
  return -1;
556
1087
  if ( pReq->m_reqBufSize < 8192 )
@@ -570,9 +1101,15 @@ static int readReq( LSAPI_Request * pReq )
570
1101
 
571
1102
  packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
572
1103
  if ( packetLen < 0 )
1104
+ {
1105
+ fprintf( stderr, "%d: packetLen < 0\n", getpid() );
573
1106
  return -1;
1107
+ }
574
1108
  if ( packetLen > LSAPI_MAX_HEADER_LEN )
1109
+ {
1110
+ fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN );
575
1111
  return -1;
1112
+ }
576
1113
 
577
1114
  if ( packetLen + 1024 > pReq->m_reqBufSize )
578
1115
  {
@@ -587,7 +1124,13 @@ static int readReq( LSAPI_Request * pReq )
587
1124
  pReq->m_bufRead += len;
588
1125
  }
589
1126
  if ( parseRequest( pReq, packetLen ) < 0 )
1127
+ {
1128
+ fprintf( stderr, "%d: parseRequest error\n", getpid() );
590
1129
  return -1;
1130
+ }
1131
+ if ( !s_uid )
1132
+ if ( lsapi_changeUGid( pReq ) )
1133
+ return -1;
591
1134
  pReq->m_bufProcessed = packetLen;
592
1135
  pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
593
1136
 
@@ -604,6 +1147,8 @@ int LSAPI_Init(void)
604
1147
  {
605
1148
  if ( !g_inited )
606
1149
  {
1150
+ s_uid = geteuid();
1151
+ s_pSecret[0] = 0;
607
1152
  lsapi_signal(SIGPIPE, lsapi_sigpipe);
608
1153
  lsapi_signal(SIGUSR1, lsapi_siguser1);
609
1154
 
@@ -683,6 +1228,7 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
683
1228
  return -1;
684
1229
  if ( LSAPI_Finish_r( pReq ) == -1 )
685
1230
  return -1;
1231
+ lsapi_set_nblock( pReq->m_fdListen , 0 );
686
1232
  while( g_running )
687
1233
  {
688
1234
  if ( pReq->m_fd == -1 )
@@ -707,9 +1253,11 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
707
1253
  setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
708
1254
  (char *)&nodelay, sizeof(nodelay));
709
1255
  }
1256
+ //init_conn_key( pReq->m_fd );
710
1257
  //OPTIMIZATION
711
1258
  if ( s_accept_notify )
712
- return notify_req_received( pReq->m_fd );
1259
+ if ( notify_req_received( pReq->m_fd ) == -1 )
1260
+ return -1;
713
1261
  }
714
1262
  }
715
1263
  else
@@ -717,6 +1265,7 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
717
1265
  }
718
1266
  if ( !readReq( pReq ) )
719
1267
  break;
1268
+ //abort();
720
1269
  lsapi_close( pReq->m_fd );
721
1270
  pReq->m_fd = -1;
722
1271
  LSAPI_Reset_r( pReq );
@@ -799,13 +1348,13 @@ char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
799
1348
 
800
1349
  static int readBodyToReqBuf( LSAPI_Request * pReq )
801
1350
  {
802
- int bodyLeft;
803
- int len = pReq->m_bufRead - pReq->m_bufProcessed;
1351
+ off_t bodyLeft;
1352
+ ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
804
1353
  if ( len > 0 )
805
1354
  return len;
806
1355
  pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
807
1356
 
808
- bodyLeft = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
1357
+ bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
809
1358
  len = pReq->m_reqBufSize - pReq->m_bufRead;
810
1359
  if ( len < 0 )
811
1360
  return -1;
@@ -834,10 +1383,10 @@ int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
834
1383
 
835
1384
 
836
1385
 
837
- int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF )
1386
+ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
838
1387
  {
839
- int len;
840
- int left;
1388
+ ssize_t len;
1389
+ ssize_t left;
841
1390
  char * pBufEnd = pBuf + bufLen - 1;
842
1391
  char * pBufCur = pBuf;
843
1392
  char * pCur;
@@ -881,15 +1430,15 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *
881
1430
  }
882
1431
 
883
1432
 
884
- int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
1433
+ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
885
1434
  {
886
- int len;
887
- int total;
1435
+ ssize_t len;
1436
+ off_t total;
888
1437
  /* char *pOldBuf = pBuf; */
889
1438
  if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 ))
890
1439
  return -1;
891
1440
 
892
- total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
1441
+ total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
893
1442
 
894
1443
  if ( total <= 0 )
895
1444
  return 0;
@@ -930,14 +1479,14 @@ int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
930
1479
  }
931
1480
 
932
1481
 
933
- int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
1482
+ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
934
1483
  {
935
1484
  struct lsapi_packet_header * pHeader;
936
1485
  const char * pEnd;
937
1486
  const char * p;
938
- int bufLen;
939
- int toWrite;
940
- int packetLen;
1487
+ ssize_t bufLen;
1488
+ ssize_t toWrite;
1489
+ ssize_t packetLen;
941
1490
  int skip = 0;
942
1491
 
943
1492
  if ( !pReq || !pBuf || (pReq->m_fd == -1) )
@@ -1015,6 +1564,95 @@ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
1015
1564
  return p - pBuf;
1016
1565
  }
1017
1566
 
1567
+ #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
1568
+ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1569
+ {
1570
+ ssize_t ret;
1571
+ off_t written;
1572
+ ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1573
+ if ( written > 0 )
1574
+ {
1575
+ ret = written;
1576
+ *off += ret;
1577
+ }
1578
+ return ret;
1579
+ }
1580
+ #endif
1581
+
1582
+ #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1583
+ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1584
+ {
1585
+ ssize_t ret;
1586
+ off_t len = size;
1587
+ ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1588
+ if (( ret == 0 )&&( len > 0 ))
1589
+ {
1590
+ ret = len;
1591
+ *off += len;
1592
+ }
1593
+ return ret;
1594
+ }
1595
+ #endif
1596
+
1597
+ #if defined(sun) || defined(__sun)
1598
+ #include <sys/sendfile.h>
1599
+ ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1600
+ {
1601
+ int n = 0 ;
1602
+ sendfilevec_t vec[1];
1603
+
1604
+ vec[n].sfv_fd = fdIn;
1605
+ vec[n].sfv_flag = 0;
1606
+ vec[n].sfv_off = *off;
1607
+ vec[n].sfv_len = size;
1608
+ ++n;
1609
+
1610
+ size_t written;
1611
+ ssize_t ret = ::sendfilev( fdOut, vec, n, &written );
1612
+ if (( !ret )||( errno == EAGAIN ))
1613
+ ret = written;
1614
+ if ( ret > 0 )
1615
+ *off += ret;
1616
+ return ret;
1617
+ }
1618
+ #endif
1619
+
1620
+ #if defined(linux) || defined(__linux) || defined(__linux__) || \
1621
+ defined(__gnu_linux__)
1622
+ #include <sys/sendfile.h>
1623
+ #define gsendfile sendfile
1624
+ #endif
1625
+ #if defined(HPUX)
1626
+ ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
1627
+ {
1628
+ return sendfile( fdOut, fdIn, off, size, NULL, 0 );
1629
+ }
1630
+ #endif
1631
+
1632
+ ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
1633
+ {
1634
+ struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1635
+ if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
1636
+ return -1;
1637
+ if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1638
+ {
1639
+ LSAPI_FinalizeRespHeaders_r( pReq );
1640
+ }
1641
+ pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1642
+
1643
+ LSAPI_Flush_r(pReq);
1644
+
1645
+ lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1646
+ size + LSAPI_PACKET_HEADER_LEN );
1647
+
1648
+
1649
+ if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
1650
+ return -1;
1651
+
1652
+ return gsendfile( pReq->m_fd, fdIn, off, size );
1653
+ }
1654
+
1655
+
1018
1656
  void Flush_RespBuf_r( LSAPI_Request * pReq )
1019
1657
  {
1020
1658
  struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
@@ -1085,13 +1723,13 @@ int LSAPI_Flush_r( LSAPI_Request * pReq )
1085
1723
  }
1086
1724
 
1087
1725
 
1088
- int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
1726
+ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1089
1727
  {
1090
1728
  struct lsapi_packet_header header;
1091
1729
  const char * pEnd;
1092
1730
  const char * p;
1093
- int packetLen;
1094
- int totalLen;
1731
+ ssize_t packetLen;
1732
+ ssize_t totalLen;
1095
1733
  int ret;
1096
1734
  struct iovec iov[2];
1097
1735
  struct iovec *pIov;
@@ -1200,6 +1838,20 @@ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
1200
1838
  return NULL;
1201
1839
  }
1202
1840
 
1841
+ struct _headerInfo
1842
+ {
1843
+ const char * _name;
1844
+ int _nameLen;
1845
+ const char * _value;
1846
+ int _valueLen;
1847
+ };
1848
+
1849
+ int compareValueLocation(const void * v1, const void *v2 )
1850
+ {
1851
+ return ((const struct _headerInfo *)v1)->_value -
1852
+ ((const struct _headerInfo *)v2)->_value;
1853
+ }
1854
+
1203
1855
  int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1204
1856
  LSAPI_CB_EnvHandler fn, void * arg )
1205
1857
  {
@@ -1208,8 +1860,10 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1208
1860
  char * pValue;
1209
1861
  int ret;
1210
1862
  int count = 0;
1863
+ struct _headerInfo headers[512];
1211
1864
  if ( !pReq || !fn )
1212
1865
  return -1;
1866
+
1213
1867
  for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1214
1868
  {
1215
1869
  if ( pReq->m_pHeaderIndex->m_headerOff[i] )
@@ -1217,11 +1871,16 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1217
1871
  len = pReq->m_pHeaderIndex->m_headerLen[i];
1218
1872
  pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
1219
1873
  *(pValue + len ) = 0;
1220
- ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
1221
- pValue, len, arg );
1874
+ headers[count]._name = HTTP_HEADERS[i];
1875
+ headers[count]._nameLen = HTTP_HEADER_LEN[i];
1876
+ headers[count]._value = pValue;
1877
+ headers[count]._valueLen = len;
1222
1878
  ++count;
1223
- if ( ret <= 0 )
1224
- return ret;
1879
+
1880
+ //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
1881
+ // pValue, len, arg );
1882
+ //if ( ret <= 0 )
1883
+ // return ret;
1225
1884
  }
1226
1885
  }
1227
1886
  if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
@@ -1238,14 +1897,29 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1238
1897
 
1239
1898
  pValue = pReq->m_pHttpHeader + pCur->valueOff;
1240
1899
  *(pValue + pCur->valueLen ) = 0;
1241
- ret = (*fn)( pKey, keyLen,
1242
- pValue, pCur->valueLen, arg );
1243
- if ( ret <= 0 )
1244
- return ret;
1900
+ headers[count]._name = pKey;
1901
+ headers[count]._nameLen = keyLen;
1902
+ headers[count]._value = pValue;
1903
+ headers[count]._valueLen = pCur->valueLen;
1904
+ ++count;
1905
+ if ( count == 512 )
1906
+ break;
1907
+ //ret = (*fn)( pKey, keyLen,
1908
+ // pValue, pCur->valueLen, arg );
1909
+ //if ( ret <= 0 )
1910
+ // return ret;
1245
1911
  ++pCur;
1246
1912
  }
1247
1913
  }
1248
- return count + pReq->m_pHeader->m_cntUnknownHeaders;
1914
+ qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
1915
+ for( i = 0; i < count; ++i )
1916
+ {
1917
+ ret = (*fn)( headers[i]._name, headers[i]._nameLen,
1918
+ headers[i]._value, headers[i]._valueLen, arg );
1919
+ if ( ret <= 0 )
1920
+ return ret;
1921
+ }
1922
+ return count;
1249
1923
 
1250
1924
  }
1251
1925
 
@@ -1288,11 +1962,11 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
1288
1962
  {
1289
1963
  pKey = pReq->m_pHttpHeader + pCur->nameOff;
1290
1964
  keyLen = pCur->nameLen;
1965
+ if ( keyLen > 250 )
1966
+ keyLen = 250;
1291
1967
  pKeyEnd = pKey + keyLen;
1292
1968
  memcpy( achHeaderName, "HTTP_", 5 );
1293
1969
  p = &achHeaderName[5];
1294
- if ( keyLen > 250 )
1295
- keyLen = 250;
1296
1970
 
1297
1971
  while( pKey < pKeyEnd )
1298
1972
  {
@@ -1397,9 +2071,64 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
1397
2071
  }
1398
2072
 
1399
2073
 
2074
+ int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2075
+ const char * pHeaderValue )
2076
+ {
2077
+ int nameLen, valLen, len;
2078
+ if ( !pReq || !pHeaderName || !pHeaderValue )
2079
+ return -1;
2080
+ if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2081
+ return -1;
2082
+ if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2083
+ return -1;
2084
+ nameLen = strlen( pHeaderName );
2085
+ valLen = strlen( pHeaderValue );
2086
+ if ( nameLen == 0 )
2087
+ return -1;
2088
+ while( nameLen > 0 )
2089
+ {
2090
+ char ch = *(pHeaderName + nameLen - 1 );
2091
+ if (( ch == '\n' )||( ch == '\r' ))
2092
+ --nameLen;
2093
+ else
2094
+ break;
2095
+ }
2096
+ if ( nameLen <= 0 )
2097
+ return 0;
2098
+ while( valLen > 0 )
2099
+ {
2100
+ char ch = *(pHeaderValue + valLen - 1 );
2101
+ if (( ch == '\n' )||( ch == '\r' ))
2102
+ --valLen;
2103
+ else
2104
+ break;
2105
+ }
2106
+ len = nameLen + valLen + 1;
2107
+ if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2108
+ return -1;
2109
+
2110
+ if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2111
+ {
2112
+ int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2113
+ newlen -= newlen % 4096;
2114
+ if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2115
+ return -1;
2116
+ }
2117
+ memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2118
+ pReq->m_pRespHeaderBufPos += nameLen;
2119
+ *pReq->m_pRespHeaderBufPos++ = ':';
2120
+ memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2121
+ pReq->m_pRespHeaderBufPos += valLen;
2122
+ *pReq->m_pRespHeaderBufPos++ = 0;
2123
+ ++len; /* add one byte padding for \0 */
2124
+ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2125
+ ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2126
+ return 0;
2127
+ }
2128
+
1400
2129
 
1401
2130
 
1402
- int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len )
2131
+ int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
1403
2132
  {
1404
2133
  if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
1405
2134
  return -1;
@@ -1494,7 +2223,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
1494
2223
  if ( !pBind )
1495
2224
  return -1;
1496
2225
 
1497
- while( isspace( *p ) )
2226
+ while( isspace( *pBind ) )
1498
2227
  ++pBind;
1499
2228
 
1500
2229
  strncpy( achAddr, pBind, 256 );
@@ -1551,7 +2280,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
1551
2280
  ++pEnd;
1552
2281
 
1553
2282
  port = atoi( pEnd );
1554
- if (( port <= 0 )||( port > 655535 ))
2283
+ if (( port <= 0 )||( port > 65535 ))
1555
2284
  return -1;
1556
2285
  if ( doAddrInfo )
1557
2286
  {
@@ -1597,9 +2326,11 @@ static fn_select_t g_fnSelect = select;
1597
2326
  typedef struct _lsapi_child_status
1598
2327
  {
1599
2328
  int m_pid;
2329
+ long m_tmStart;
1600
2330
 
1601
2331
  volatile short m_iKillSent;
1602
2332
  volatile short m_inProcess;
2333
+ volatile int m_iReqCounter;
1603
2334
 
1604
2335
  volatile long m_tmWaitBegin;
1605
2336
  volatile long m_tmReqBegin;
@@ -1629,6 +2360,7 @@ static lsapi_prefork_server * g_prefork_server = NULL;
1629
2360
 
1630
2361
  int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
1631
2362
  {
2363
+ int pid;
1632
2364
  if ( g_prefork_server )
1633
2365
  return 0;
1634
2366
  if ( max_children <= 1 )
@@ -1646,11 +2378,15 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
1646
2378
  g_fnSelect = fp;
1647
2379
 
1648
2380
  s_ppid = getppid();
2381
+ pid = getpid();
2382
+ setpgid( pid, pid );
1649
2383
  g_prefork_server->m_iAvoidFork = avoidFork;
1650
2384
  g_prefork_server->m_iMaxChildren = max_children;
1651
2385
 
1652
2386
  g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
1653
2387
  g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2388
+ if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2389
+ g_prefork_server->m_iMaxIdleChildren = 1;
1654
2390
  g_prefork_server->m_iChildrenMaxIdleTime = 300;
1655
2391
  g_prefork_server->m_iMaxReqProcessTime = 300;
1656
2392
  return 0;
@@ -1679,9 +2415,10 @@ static int lsapi_accept( int fdListen )
1679
2415
  setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
1680
2416
  (char *)&nodelay, sizeof(nodelay));
1681
2417
  }
2418
+
1682
2419
  //OPTIMIZATION
1683
- if ( s_accept_notify )
1684
- notify_req_received( fd );
2420
+ //if ( s_accept_notify )
2421
+ // notify_req_received( fd );
1685
2422
  }
1686
2423
  return fd;
1687
2424
 
@@ -1727,10 +2464,18 @@ static void lsapi_sigchild( int signal )
1727
2464
  {
1728
2465
  break;
1729
2466
  }
2467
+ if ( WIFSIGNALED( status ))
2468
+ {
2469
+ int sig_num = WTERMSIG( status );
2470
+ int dump = WCOREDUMP( status );
2471
+ fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump );
2472
+ }
1730
2473
  child_status = find_child_status( pid );
1731
2474
  if ( child_status )
2475
+ {
1732
2476
  child_status->m_pid = 0;
1733
- --g_prefork_server->m_iCurChildren;
2477
+ --g_prefork_server->m_iCurChildren;
2478
+ }
1734
2479
  }
1735
2480
 
1736
2481
  }
@@ -1754,70 +2499,87 @@ static int lsapi_init_children_status()
1754
2499
  return 0;
1755
2500
  }
1756
2501
 
2502
+ static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2503
+ {
2504
+ char achCmd[1024];
2505
+ int pid = fork();
2506
+ if ( pid != 0 )
2507
+ return;
2508
+ fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
2509
+ ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
2510
+ tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2511
+ 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 );
2512
+ if ( system( achCmd ) == -1 )
2513
+ perror( "system()" );
2514
+ exit( 0 );
2515
+ }
2516
+
1757
2517
  static void lsapi_check_child_status( long tmCur )
1758
2518
  {
1759
2519
  int idle = 0;
1760
2520
  int tobekilled;
1761
2521
  int dying = 0;
2522
+ int count = 0;
1762
2523
  lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
1763
2524
  lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
1764
2525
  while( pStatus < pEnd )
1765
2526
  {
1766
- tobekilled = pStatus->m_iKillSent;
2527
+ tobekilled = 0;
1767
2528
  if ( pStatus->m_pid != 0 )
1768
2529
  {
1769
- if ( !tobekilled )
2530
+ ++count;
2531
+ if ( !pStatus->m_inProcess )
1770
2532
  {
1771
- if ( !pStatus->m_inProcess )
2533
+
2534
+ if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
2535
+ ( idle > g_prefork_server->m_iMaxIdleChildren ))
1772
2536
  {
1773
-
1774
- if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
1775
- ( idle >= g_prefork_server->m_iMaxIdleChildren ))
1776
- {
1777
- tobekilled = 1;
1778
- }
1779
- else
1780
- {
1781
- if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
1782
- tobekilled = 1;
1783
- }
1784
- if ( !tobekilled )
1785
- ++idle;
2537
+ tobekilled = SIGUSR1;
1786
2538
  }
1787
2539
  else
1788
2540
  {
1789
- if ( tmCur - pStatus->m_tmReqBegin >
1790
- g_prefork_server->m_iMaxReqProcessTime )
1791
- tobekilled = 1;
2541
+ if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
2542
+ {
2543
+ tobekilled = SIGUSR1;
2544
+ }
1792
2545
  }
2546
+ if ( !tobekilled )
2547
+ ++idle;
1793
2548
  }
1794
2549
  else
1795
2550
  {
1796
- if ( pStatus->m_inProcess )
1797
- tobekilled = pStatus->m_iKillSent = 0;
2551
+ if ( tmCur - pStatus->m_tmReqBegin >
2552
+ g_prefork_server->m_iMaxReqProcessTime )
2553
+ {
2554
+ if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
2555
+ dump_debug_info( pStatus, tmCur );
2556
+ if ( pStatus->m_iKillSent > 5 )
2557
+ {
2558
+ tobekilled = SIGKILL;
2559
+ fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
2560
+ }
2561
+ else
2562
+ {
2563
+ tobekilled = SIGTERM;
2564
+ fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
2565
+ }
2566
+ }
1798
2567
  }
1799
2568
  if ( tobekilled )
1800
2569
  {
1801
- tobekilled = 0;
1802
- if ( pStatus->m_iKillSent > 5 )
1803
- tobekilled = SIGKILL;
1804
- else if ( pStatus->m_iKillSent == 3 )
1805
- tobekilled = SIGTERM;
1806
- else if ( pStatus->m_iKillSent == 1 )
1807
- {
1808
- tobekilled = SIGUSR1;
1809
- }
1810
- if ( tobekilled )
1811
- kill( pStatus->m_pid, tobekilled );
2570
+ kill( pStatus->m_pid, tobekilled );
1812
2571
  ++pStatus->m_iKillSent;
1813
2572
  ++dying;
1814
2573
  }
1815
-
1816
2574
  }
1817
- else
1818
- ++dying;
1819
2575
  ++pStatus;
1820
2576
  }
2577
+ if ( g_prefork_server->m_iCurChildren != count )
2578
+ {
2579
+ fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(),
2580
+ g_prefork_server->m_iCurChildren, count, idle, dying );
2581
+
2582
+ }
1821
2583
  }
1822
2584
 
1823
2585
  static int lsapi_all_children_must_die()
@@ -1880,10 +2642,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1880
2642
  s_stop = 0;
1881
2643
  while( !s_stop )
1882
2644
  {
1883
- if ( ret )
1884
- curTime = time( NULL );
1885
- else
1886
- ++curTime;
2645
+ curTime = time( NULL );
1887
2646
  if (curTime != lastTime )
1888
2647
  {
1889
2648
  lastTime = curTime;
@@ -1914,6 +2673,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1914
2673
  timeout.tv_sec = 1; timeout.tv_usec = 0;
1915
2674
  if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
1916
2675
  {
2676
+ /*
1917
2677
  if ( pServer->m_iCurChildren >= 0 )
1918
2678
  {
1919
2679
  usleep( 10 );
@@ -1922,7 +2682,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1922
2682
  timeout.tv_sec = 0; timeout.tv_usec = 0;
1923
2683
  if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
1924
2684
  continue;
1925
- }
2685
+ }*/
1926
2686
  }
1927
2687
  else if ( ret == -1 )
1928
2688
  {
@@ -1940,6 +2700,8 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1940
2700
  if ( pReq->m_fd != -1 )
1941
2701
  {
1942
2702
  child_status = find_child_status( 0 );
2703
+ if ( child_status )
2704
+ memset( child_status, 0, sizeof( *child_status ) );
1943
2705
  pid = fork();
1944
2706
  if ( !pid )
1945
2707
  {
@@ -1947,15 +2709,22 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1947
2709
  s_ppid = getppid();
1948
2710
  s_req_processed = 0;
1949
2711
  s_pChildStatus = child_status;
1950
- child_status->m_iKillSent = 0;
1951
2712
  lsapi_set_nblock( pReq->m_fd, 0 );
1952
-
2713
+ if ( pReq->m_fdListen != -1 )
2714
+ {
2715
+ close( pReq->m_fdListen );
2716
+ pReq->m_fdListen = -1;
2717
+ }
1953
2718
  /* don't catch our signals */
1954
2719
  sigaction( SIGCHLD, &old_child, 0 );
1955
2720
  sigaction( SIGTERM, &old_term, 0 );
1956
2721
  sigaction( SIGQUIT, &old_quit, 0 );
1957
2722
  sigaction( SIGINT, &old_int, 0 );
1958
2723
  sigaction( SIGUSR1, &old_usr1, 0 );
2724
+ //init_conn_key( pReq->m_fd );
2725
+ lsapi_notify_pid( pReq->m_fd );
2726
+ if ( s_accept_notify )
2727
+ return notify_req_received( pReq->m_fd );
1959
2728
  return 0;
1960
2729
  }
1961
2730
  else if ( pid == -1 )
@@ -1968,8 +2737,8 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1968
2737
  if ( child_status )
1969
2738
  {
1970
2739
  child_status->m_pid = pid;
1971
- child_status->m_iKillSent = 0;
1972
- child_status->m_tmWaitBegin = time(NULL);
2740
+ child_status->m_tmWaitBegin = curTime;
2741
+ child_status->m_tmStart = curTime;
1973
2742
  }
1974
2743
  }
1975
2744
  close( pReq->m_fd );
@@ -1991,7 +2760,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re
1991
2760
 
1992
2761
  }
1993
2762
 
1994
- void lsapi_error( char * pMessage, int err_no )
2763
+ void lsapi_error( const char * pMessage, int err_no )
1995
2764
  {
1996
2765
  fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
1997
2766
  }
@@ -2020,6 +2789,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2020
2789
  {
2021
2790
  s_pChildStatus->m_tmWaitBegin = time( NULL );
2022
2791
  }
2792
+
2023
2793
 
2024
2794
  while( g_running )
2025
2795
  {
@@ -2031,8 +2801,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2031
2801
  fd = pReq->m_fdListen;
2032
2802
  else
2033
2803
  {
2034
- lsapi_error( "no available fd", 0 );
2035
- return -1;
2804
+ break;
2036
2805
  }
2037
2806
  wait_secs = 0;
2038
2807
  while( 1 )
@@ -2076,6 +2845,15 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2076
2845
  {
2077
2846
  fd = pReq->m_fd;
2078
2847
  lsapi_set_nblock( fd, 0 );
2848
+ //init_conn_key( pReq->m_fd );
2849
+ if ( !s_keepListener )
2850
+ {
2851
+ close( pReq->m_fdListen );
2852
+ pReq->m_fdListen = -1;
2853
+ }
2854
+ if ( s_accept_notify )
2855
+ if ( notify_req_received( pReq->m_fd ) == -1 )
2856
+ return -1;
2079
2857
  }
2080
2858
  else
2081
2859
  {
@@ -2094,7 +2872,9 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2094
2872
  {
2095
2873
  if ( s_pChildStatus )
2096
2874
  {
2875
+ s_pChildStatus->m_iKillSent = 0;
2097
2876
  s_pChildStatus->m_inProcess = 1;
2877
+ ++s_pChildStatus->m_iReqCounter;
2098
2878
  s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
2099
2879
  }
2100
2880
  ++s_req_processed;
@@ -2176,7 +2956,8 @@ static void unset_lsapi_envs()
2176
2956
  #endif
2177
2957
  while( env != NULL && *env != NULL )
2178
2958
  {
2179
- if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) )
2959
+ if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
2960
+ || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
2180
2961
  {
2181
2962
  char ** del = env;
2182
2963
  do
@@ -2188,7 +2969,7 @@ static void unset_lsapi_envs()
2188
2969
  }
2189
2970
  }
2190
2971
 
2191
- void LSAPI_Init_Env_Parameters( fn_select_t fp )
2972
+ int LSAPI_Init_Env_Parameters( fn_select_t fp )
2192
2973
  {
2193
2974
  const char *p;
2194
2975
  int n;
@@ -2229,6 +3010,9 @@ void LSAPI_Init_Env_Parameters( fn_select_t fp )
2229
3010
  struct rlimit limit = { 0, 0 };
2230
3011
  setrlimit( RLIMIT_CORE, &limit );
2231
3012
  }
3013
+ else
3014
+ s_enable_core_dump = 1;
3015
+
2232
3016
  #endif
2233
3017
 
2234
3018
  p = getenv( "LSAPI_MAX_IDLE" );
@@ -2238,6 +3022,14 @@ void LSAPI_Init_Env_Parameters( fn_select_t fp )
2238
3022
  LSAPI_Set_Max_Idle( n );
2239
3023
  }
2240
3024
 
3025
+ p = getenv( "LSAPI_KEEP_LISTEN" );
3026
+ if ( p )
3027
+ {
3028
+ n = atoi( p );
3029
+ s_keepListener = n;
3030
+ }
3031
+
3032
+
2241
3033
  if ( LSAPI_Is_Listen() )
2242
3034
  {
2243
3035
  n = 0;
@@ -2274,8 +3066,246 @@ void LSAPI_Init_Env_Parameters( fn_select_t fp )
2274
3066
  {
2275
3067
  LSAPI_No_Check_ppid();
2276
3068
  }
3069
+
3070
+ p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
3071
+ if ( p )
3072
+ s_dump_debug_info = atoi( p );
3073
+
3074
+ if ( lsapi_initSuEXEC() == -1 )
3075
+ return -1;
3076
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3077
+ lsapi_initLVE();
3078
+ #endif
2277
3079
  }
2278
3080
  unset_lsapi_envs();
3081
+ return 0;
3082
+ }
3083
+
3084
+
3085
+
3086
+
3087
+
3088
+ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
3089
+
3090
+ /*
3091
+ * Note: this code is harmless on little-endian machines.
3092
+ */
3093
+ static void byteReverse(unsigned char *buf, unsigned longs)
3094
+ {
3095
+ uint32 t;
3096
+ do {
3097
+ t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
3098
+ ((unsigned) buf[1] << 8 | buf[0]);
3099
+ *(uint32 *) buf = t;
3100
+ buf += 4;
3101
+ } while (--longs);
2279
3102
  }
2280
3103
 
3104
+ /*
3105
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
3106
+ * initialization constants.
3107
+ */
3108
+ void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
3109
+ {
3110
+ ctx->buf[0] = 0x67452301;
3111
+ ctx->buf[1] = 0xefcdab89;
3112
+ ctx->buf[2] = 0x98badcfe;
3113
+ ctx->buf[3] = 0x10325476;
3114
+
3115
+ ctx->bits[0] = 0;
3116
+ ctx->bits[1] = 0;
3117
+ }
3118
+
3119
+ /*
3120
+ * Update context to reflect the concatenation of another buffer full
3121
+ * of bytes.
3122
+ */
3123
+ void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
3124
+ {
3125
+ register uint32 t;
3126
+
3127
+ /* Update bitcount */
3128
+
3129
+ t = ctx->bits[0];
3130
+ if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
3131
+ ctx->bits[1]++; /* Carry from low to high */
3132
+ ctx->bits[1] += len >> 29;
3133
+
3134
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
3135
+
3136
+ /* Handle any leading odd-sized chunks */
3137
+
3138
+ if (t) {
3139
+ unsigned char *p = (unsigned char *) ctx->in + t;
3140
+
3141
+ t = 64 - t;
3142
+ if (len < t) {
3143
+ memmove(p, buf, len);
3144
+ return;
3145
+ }
3146
+ memmove(p, buf, t);
3147
+ byteReverse(ctx->in, 16);
3148
+ lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3149
+ buf += t;
3150
+ len -= t;
3151
+ }
3152
+ /* Process data in 64-byte chunks */
3153
+
3154
+ while (len >= 64) {
3155
+ memmove(ctx->in, buf, 64);
3156
+ byteReverse(ctx->in, 16);
3157
+ lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3158
+ buf += 64;
3159
+ len -= 64;
3160
+ }
3161
+
3162
+ /* Handle any remaining bytes of data. */
3163
+
3164
+ memmove(ctx->in, buf, len);
3165
+ }
3166
+
3167
+ /*
3168
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
3169
+ * 1 0* (64-bit count of bits processed, MSB-first)
3170
+ */
3171
+ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
3172
+ {
3173
+ unsigned int count;
3174
+ unsigned char *p;
3175
+
3176
+ /* Compute number of bytes mod 64 */
3177
+ count = (ctx->bits[0] >> 3) & 0x3F;
3178
+
3179
+ /* Set the first char of padding to 0x80. This is safe since there is
3180
+ always at least one byte free */
3181
+ p = ctx->in + count;
3182
+ *p++ = 0x80;
3183
+
3184
+ /* Bytes of padding needed to make 64 bytes */
3185
+ count = 64 - 1 - count;
3186
+
3187
+ /* Pad out to 56 mod 64 */
3188
+ if (count < 8) {
3189
+ /* Two lots of padding: Pad the first block to 64 bytes */
3190
+ memset(p, 0, count);
3191
+ byteReverse(ctx->in, 16);
3192
+ lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3193
+
3194
+ /* Now fill the next block with 56 bytes */
3195
+ memset(ctx->in, 0, 56);
3196
+ } else {
3197
+ /* Pad block to 56 bytes */
3198
+ memset(p, 0, count - 8);
3199
+ }
3200
+ byteReverse(ctx->in, 14);
3201
+
3202
+ /* Append length in bits and transform */
3203
+ ((uint32 *) ctx->in)[14] = ctx->bits[0];
3204
+ ((uint32 *) ctx->in)[15] = ctx->bits[1];
3205
+
3206
+ lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3207
+ byteReverse((unsigned char *) ctx->buf, 4);
3208
+ memmove(digest, ctx->buf, 16);
3209
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
3210
+ }
3211
+
3212
+ /* The four core functions - F1 is optimized somewhat */
3213
+
3214
+ /* #define F1(x, y, z) (x & y | ~x & z) */
3215
+ #define F1(x, y, z) (z ^ (x & (y ^ z)))
3216
+ #define F2(x, y, z) F1(z, x, y)
3217
+ #define F3(x, y, z) (x ^ y ^ z)
3218
+ #define F4(x, y, z) (y ^ (x | ~z))
3219
+
3220
+ /* This is the central step in the MD5 algorithm. */
3221
+ #define MD5STEP(f, w, x, y, z, data, s) \
3222
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
3223
+
3224
+ /*
3225
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
3226
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
3227
+ * the data and converts bytes into longwords for this routine.
3228
+ */
3229
+ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
3230
+ {
3231
+ register uint32 a, b, c, d;
3232
+
3233
+ a = buf[0];
3234
+ b = buf[1];
3235
+ c = buf[2];
3236
+ d = buf[3];
3237
+
3238
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3239
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3240
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
3241
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3242
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3243
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3244
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
3245
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
3246
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
3247
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3248
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3249
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3250
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
3251
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
3252
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
3253
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
3254
+
3255
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3256
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
3257
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3258
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3259
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3260
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
3261
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3262
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3263
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3264
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3265
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3266
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3267
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3268
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3269
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3270
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
3271
+
3272
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
3273
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
3274
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
3275
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
3276
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
3277
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
3278
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
3279
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
3280
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
3281
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
3282
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
3283
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
3284
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
3285
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
3286
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
3287
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
3288
+
3289
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
3290
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
3291
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
3292
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
3293
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
3294
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
3295
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
3296
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
3297
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
3298
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
3299
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
3300
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
3301
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
3302
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
3303
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
3304
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
3305
+
3306
+ buf[0] += a;
3307
+ buf[1] += b;
3308
+ buf[2] += c;
3309
+ buf[3] += d;
3310
+ }
2281
3311