ruby-lsapi 4.0 → 4.1

Sign up to get free protection for your applications and to get access to all the features.
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