diff options
66 files changed, 13967 insertions, 0 deletions
| @@ -0,0 +1,2 @@ | |||
| 1 | suhosin | ||
| 2 | Stefan Esser | ||
diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..eb90e44 --- /dev/null +++ b/Changelog | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | 2009-08-15 - 0.9.29 | ||
| 2 | |||
| 3 | - Fixing crash bugs with PHP 5.3.0 caused by unexpected NULL in EG(active_symbol_table) | ||
| 4 | - Added more compatible way to retrieve ext/session globals | ||
| 5 | - Increased default length and count limit for POST variables (for people not reading docu) | ||
| 6 | |||
| 7 | 2009-08-14 - 0.9.28 | ||
| 8 | |||
| 9 | - Fixed crash bug with PHP 5.2.10 caused by a change in extension load order of ext/session | ||
| 10 | - Fixed harmless parameter order error in a bogus memset() | ||
| 11 | - Disable suhosin.session.cryptua by default because of Internet Explorer 8 "features" | ||
| 12 | - Added suhosin.executor.include.allow_writable_files which can be disabled to disallow | ||
| 13 | inclusion of files writable by the webserver | ||
| 14 | |||
| 15 | 2008-08-23 - 0.9.27 | ||
| 16 | |||
| 17 | - Fixed typo in replacement rand() / mt_rand() that was hidden by LAZY symbol loading | ||
| 18 | |||
| 19 | 2008-08-22 - 0.9.26 | ||
| 20 | |||
| 21 | - Fixed problem with suhosin.perdir | ||
| 22 | Thanks to Hosteurope for tracking this down | ||
| 23 | - Fixed problems with ext/uploadprogress | ||
| 24 | Reported by: Christian Stocker | ||
| 25 | - Added suhosin.srand.ignore and suhosin.mt_srand.ignore (default: on) | ||
| 26 | - Modified rand()/srand() to use the Mersenne Twister algorithm with separate state | ||
| 27 | - Added better internal seeding of rand() and mt_rand() | ||
| 28 | |||
| 29 | 2008-08-06 - 0.9.25 | ||
| 30 | |||
| 31 | - Fixed PHP 4 compilation problem introduced in 0.9.24 | ||
| 32 | - Fixed PHP 5.3 compilation problem | ||
| 33 | - Changed PHP default POST handler to PHP's current handler | ||
| 34 | |||
| 35 | 2008-05-10 - 0.9.24 | ||
| 36 | |||
| 37 | - Added support for method-calls to function handling | ||
| 38 | - This fixes white- and blacklist affecting methods with the same name | ||
| 39 | |||
| 40 | 2008-01-14 - 0.9.23 | ||
| 41 | |||
| 42 | - Fixed suhosin extension now compiles with snapshots of PHP 5.3 | ||
| 43 | - Fixed crypt() behaves like normal again when there is no salt supplied | ||
| 44 | |||
| 45 | 2007-12-01 - 0.9.22 | ||
| 46 | |||
| 47 | - Removed LFS warning message because it crashed on several systems | ||
| 48 | |||
| 49 | 2007-11-30 - 0.9.21 | ||
| 50 | |||
| 51 | - Fixed function_exists() now checks the Suhosin permissions | ||
| 52 | - Fixed crypt() salt no longer uses Blowfish by default | ||
| 53 | - Fixed .htaccess/perdir support | ||
| 54 | - Fixed compilation problem on OS/X | ||
| 55 | - Added protection against some attacks through _SERVER variables | ||
| 56 | - Added suhosin.server.strip and suhosin.server.encode | ||
| 57 | - Added error message that warns about the LFS binary incompatibility | ||
| 58 | |||
| 59 | 2007-05-19 - 0.9.20 | ||
| 60 | |||
| 61 | - Added protection flags against whitespace at variable start | ||
| 62 | - Added mutex around crypt() to close the PHP crypt() | ||
| 63 | thread safety vulnerability class | ||
| 64 | - Improved HTTP Response Splitting Protection | ||
| 65 | - Changed default maximum array depth to 50 for GPCR | ||
| 66 | - Fixed possible endless loop in file logging | ||
| 67 | - Fixed file locking in file logging | ||
| 68 | |||
| 69 | 2007-05-01 - 0.9.19 | ||
| 70 | |||
| 71 | - Fixed typo in HTTP header protection (only during simulation mode) | ||
| 72 | Reported by: Ilia Alshanetsky | ||
| 73 | - Fixed wrong \0 termination in cookie decryptor | ||
| 74 | - Fixed possible crash in SERVER variables protection when SAPI=embedded | ||
| 75 | Fix provided by: Olivier Blin/Mandriva Linux | ||
| 76 | - Added possibility to en-/disable INI_PERDIR | ||
| 77 | Problem reported by: Ilia Alshanetsky | ||
| 78 | - Added PHP Warning when disabled function is called | ||
| 79 | - Added examples for new configuration option in suhosin.ini | ||
| 80 | |||
| 81 | 2007-03-06 - 0.9.18 | ||
| 82 | |||
| 83 | - Fixed session double hooking in edge case | ||
| 84 | - Added additional crash protection for PHP's session module | ||
| 85 | |||
| 86 | 2007-03-04 - 0.9.17 | ||
| 87 | |||
| 88 | - Added a suhosin.ini example configuration | ||
| 89 | Thanks to Mandriva Linux for supplying us with one | ||
| 90 | - Added new logging device: file | ||
| 91 | - Fixed that suhosin.filter.action did not affect POST limits | ||
| 92 | - Fixed behaviour of request variable limit to be an upper limit | ||
| 93 | for the other settings instead of being additive limit | ||
| 94 | - Fixed hard_memory_limit bypass due to casting bug in PHP | ||
| 95 | Problem was found by: Ilia Alshanetsky | ||
| 96 | - Fixed some sql prefix/postfix problems | ||
| 97 | - Added experimental SQL injection heuristic | ||
| 98 | |||
| 99 | 2006-12-02 - 0.9.16 | ||
| 100 | |||
| 101 | - Added suhosin.stealth which controls if suhosin loads in | ||
| 102 | stealth mode when it is not the only zend_extension | ||
| 103 | (Required for full compatibility with certain encoders | ||
| 104 | that consider open source untrusted. e.g. ionCube, Zend) | ||
| 105 | - Activate suhosin.stealth by default | ||
| 106 | - Fixed that Suhosin tries handling functions disabled by | ||
| 107 | disable_function. In v0.9.15 it was impossible to disable | ||
| 108 | phpinfo() with disable_function. | ||
| 109 | Problem was found by: Thorsten Schifferdecker | ||
| 110 | |||
| 111 | 2006-11-28 - 0.9.15 | ||
| 112 | |||
| 113 | - Added a transparent protection for open phpinfo() pages by | ||
| 114 | adding an HTML META ROBOTS tag to the output that forbids | ||
| 115 | indexing and archiving | ||
| 116 | |||
| 117 | 2006-11-22 - 0.9.14 | ||
| 118 | |||
| 119 | - Drop wrongly decrypted cookies instead of leaving them empty | ||
| 120 | - Fix another problem with urlencoded cookie names | ||
| 121 | - Fix compilation problem with PHP4 | ||
| 122 | - Added better regression to the release process to stop | ||
| 123 | compilation and missing symbol problems | ||
| 124 | |||
| 125 | 2006-11-20 - 0.9.13 | ||
| 126 | |||
| 127 | - More compatible support for ap_php_snprintf() for old PHP | ||
| 128 | - Changed phpinfo() output to put suhosin logo into a data: URL | ||
| 129 | for Opera and Gecko based browsers when expose_php=off | ||
| 130 | |||
| 131 | 2006-11-14 - 0.9.12 | ||
| 132 | |||
| 133 | - Adding ap_php_snprintf() when compiling against PHP 4.3.9 | ||
| 134 | - Added suhosin.protectkey to remove cryptkeys from phpinfo() output | ||
| 135 | - Disabled suhosin.cookie.encrypt in default install | ||
| 136 | - Fixed static compilation against PHP 5.2.0 | ||
| 137 | |||
| 138 | 2006-11-06 - 0.9.11 | ||
| 139 | |||
| 140 | - Fixed input filter for simulation mode | ||
| 141 | |||
| 142 | 2006-10-26 - 0.9.10 | ||
| 143 | |||
| 144 | - Fixed ZTS compile problem in new code | ||
| 145 | - Fixed PHP4 compile problem in new code | ||
| 146 | |||
| 147 | 2006-10-25 - 0.9.9 | ||
| 148 | |||
| 149 | - Fixed mail() protection that failed to detect some injected headers | ||
| 150 | - Fixed cookie decryption to not potentially trash apache memory | ||
| 151 | - Fixed cookie enctyption to handle url encoded names correctly | ||
| 152 | - Added suhosin.cookie/session.checkraddr | ||
| 153 | - Added suhosin.cookie.cryptlist | ||
| 154 | - Added suhosin.cookie.plainlist | ||
| 155 | - Added suhosin_encrypt_cookie function for JS | ||
| 156 | - Added suhosin_get_raw_cookies function | ||
| 157 | - Changed dropped variable error messages | ||
| 158 | |||
| 159 | 2006-10-08 - 0.9.8 | ||
| 160 | |||
| 161 | - Fixed a PHP4 ZTS compile problem | ||
| 162 | |||
| 163 | 2006-10-08 - 0.9.7 | ||
| 164 | |||
| 165 | - Moved input handler hooking to a later place to ensure better compatibility | ||
| 166 | with 3rd party extensions | ||
| 167 | - Fixed a problem with overlong mail headers in mail protection | ||
| 168 | - Fixed a problem with empty log/verification script names | ||
| 169 | - Fixed a PHP4 compile problem with old gcc/in ZTS mode | ||
| 170 | - Added mbregex.h from PHP4 to solve compile problems on systesm with broken | ||
| 171 | header installations | ||
| 172 | |||
| 173 | 2006-10-02 - 0.9.6 | ||
| 174 | |||
| 175 | - Disallow symlink() when open_basedir (activated by default) | ||
| 176 | - Fix a problem with compilation in Visual Studio | ||
| 177 | |||
| 178 | 2006-09-29 - 0.9.5 | ||
| 179 | |||
| 180 | - Added missing logo file | ||
| 181 | - Added suhosin.apc_bug_workaround flag to enable compatibility with buggy APC 3.0.12x | ||
| 182 | |||
| 183 | 2006-09-29 - 0.9.4 | ||
| 184 | |||
| 185 | - Added version number and logo to phpinfo() output | ||
| 186 | - Fixed that all uploaded files are dropped after a single one was disallowed | ||
| 187 | - Added undocumented suhosin.coredump flag to tell suhosin to dump core instead | ||
| 188 | of logging S_MEMORY events | ||
| 189 | - Disable handling of rfc1867 mbstring decoding | ||
| 190 | |||
| 191 | 2006-09-24 - 0.9.3 | ||
| 192 | |||
| 193 | - Added protection against endless recursion for suhosin.log.phpscript | ||
| 194 | - Added possibility to disable open_basedir and safe_mode for suhosin.log.phpscript | ||
| 195 | - Added suhosin.executor.include.max_traversal to stop directory traversal includes | ||
| 196 | |||
| 197 | 2006-09-19 - 0.9.2 | ||
| 198 | |||
| 199 | - Fixes broken rfc1867 fileupload hook | ||
| 200 | - Changed definition of binary to: 0..31, 128..255 except whitespace | ||
| 201 | - Added suhosin.log.phpscript(.name) directive to log to a PHP script | ||
| 202 | |||
| 203 | 2006-09-16 - 0.9.1 | ||
| 204 | |||
| 205 | - A bunch of changes to compile and work on Windows | ||
| 206 | |||
| 207 | 2006-09-09 - BETA | ||
| 208 | |||
| 209 | - Added decryption of HTTP_COOKIE | ||
| 210 | - Fixed a last problem in suhosin_strcasestr() helper function | ||
| 211 | |||
| 212 | 2006-09-08 - BETA | ||
| 213 | |||
| 214 | - Fixed a problem within suhosin_strcasestr() because it broke | ||
| 215 | URL checks | ||
| 216 | |||
| 217 | 2006-09-07 - BETA | ||
| 218 | |||
| 219 | - CVS version of PHP 5.2.0 was changed to support incasesensitive | ||
| 220 | URLs, support for this in suhosin added | ||
| 221 | - Fixed a problem when preg_replace() was called with more than | ||
| 222 | 4 parameters | ||
| 223 | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | /* Rijndael Block Cipher - rijndael.c | ||
| 2 | |||
| 3 | Written by Mike Scott 21st April 1999 | ||
| 4 | mike@compapp.dcu.ie | ||
| 5 | An alternative faster version is implemented in MIRACL | ||
| 6 | ftp://ftp.computing.dcu.ie/pub/crypto/miracl.zip | ||
| 7 | |||
| 8 | Copyright (c) 1999 Mike Scott | ||
| 9 | |||
| 10 | Simply compile and run, e.g. | ||
| 11 | |||
| 12 | cl /O2 rijndael.c (Microsoft C) | ||
| 13 | bcc32 /O2 rijndael.c (Borland C) | ||
| 14 | gcc -O2 rijndael.c -o rijndael (Gnu C) | ||
| 15 | |||
| 16 | Compiles and runs fine as a C++ program also. | ||
| 17 | |||
| 18 | See rijndael documentation. The code follows the documentation as closely | ||
| 19 | as possible, and where possible uses the same function and variable names. | ||
| 20 | |||
| 21 | Permission for free direct or derivative use is granted subject | ||
| 22 | to compliance with any conditions that the originators of the | ||
| 23 | algorithm place on its exploitation. | ||
| 24 | |||
| 25 | Inspiration from Brian Gladman's implementation is acknowledged. | ||
| 26 | |||
| 27 | Written for clarity, rather than speed. | ||
| 28 | Assumes long is 32 bit quantity. | ||
| 29 | Full implementation. | ||
| 30 | Endian indifferent. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include "php.h" | ||
| 34 | #include "php_suhosin.h" | ||
| 35 | |||
| 36 | /* rotates x one bit to the left */ | ||
| 37 | |||
| 38 | #define ROTL(x) (((x)>>7)|((x)<<1)) | ||
| 39 | |||
| 40 | /* Rotates 32-bit word left by 1, 2 or 3 byte */ | ||
| 41 | |||
| 42 | #define ROTL8(x) (((x)<<8)|((x)>>24)) | ||
| 43 | #define ROTL16(x) (((x)<<16)|((x)>>16)) | ||
| 44 | #define ROTL24(x) (((x)<<24)|((x)>>8)) | ||
| 45 | |||
| 46 | /* Fixed Data */ | ||
| 47 | |||
| 48 | static BYTE InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */ | ||
| 49 | |||
| 50 | static BYTE fbsub[256]; | ||
| 51 | static BYTE rbsub[256]; | ||
| 52 | static BYTE ptab[256],ltab[256]; | ||
| 53 | static WORD ftable[256]; | ||
| 54 | static WORD rtable[256]; | ||
| 55 | static WORD rco[30]; | ||
| 56 | |||
| 57 | /* Parameter-dependent data */ | ||
| 58 | |||
| 59 | static int Nk,Nb,Nr; | ||
| 60 | |||
| 61 | static WORD pack(BYTE *b) | ||
| 62 | { /* pack bytes into a 32-bit Word */ | ||
| 63 | return ((WORD)b[3]<<24)|((WORD)b[2]<<16)|((WORD)b[1]<<8)|(WORD)b[0]; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void unpack(WORD a,BYTE *b) | ||
| 67 | { /* unpack bytes from a word */ | ||
| 68 | b[0]=(BYTE)a; | ||
| 69 | b[1]=(BYTE)(a>>8); | ||
| 70 | b[2]=(BYTE)(a>>16); | ||
| 71 | b[3]=(BYTE)(a>>24); | ||
| 72 | } | ||
| 73 | |||
| 74 | static BYTE xtime(BYTE a) | ||
| 75 | { | ||
| 76 | BYTE b; | ||
| 77 | if (a&0x80) b=0x1B; | ||
| 78 | else b=0; | ||
| 79 | a<<=1; | ||
| 80 | a^=b; | ||
| 81 | return a; | ||
| 82 | } | ||
| 83 | |||
| 84 | static BYTE bmul(BYTE x,BYTE y) | ||
| 85 | { /* x.y= AntiLog(Log(x) + Log(y)) */ | ||
| 86 | if (x && y) return ptab[(ltab[x]+ltab[y])%255]; | ||
| 87 | else return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static WORD SubByte(WORD a) | ||
| 91 | { | ||
| 92 | BYTE b[4]; | ||
| 93 | unpack(a,b); | ||
| 94 | b[0]=fbsub[b[0]]; | ||
| 95 | b[1]=fbsub[b[1]]; | ||
| 96 | b[2]=fbsub[b[2]]; | ||
| 97 | b[3]=fbsub[b[3]]; | ||
| 98 | return pack(b); | ||
| 99 | } | ||
| 100 | |||
| 101 | static BYTE product(WORD x,WORD y) | ||
| 102 | { /* dot product of two 4-byte arrays */ | ||
| 103 | BYTE xb[4],yb[4]; | ||
| 104 | unpack(x,xb); | ||
| 105 | unpack(y,yb); | ||
| 106 | return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]); | ||
| 107 | } | ||
| 108 | |||
| 109 | static WORD InvMixCol(WORD x) | ||
| 110 | { /* matrix Multiplication */ | ||
| 111 | WORD y,m; | ||
| 112 | BYTE b[4]; | ||
| 113 | |||
| 114 | m=pack(InCo); | ||
| 115 | b[3]=product(m,x); | ||
| 116 | m=ROTL24(m); | ||
| 117 | b[2]=product(m,x); | ||
| 118 | m=ROTL24(m); | ||
| 119 | b[1]=product(m,x); | ||
| 120 | m=ROTL24(m); | ||
| 121 | b[0]=product(m,x); | ||
| 122 | y=pack(b); | ||
| 123 | return y; | ||
| 124 | } | ||
| 125 | |||
| 126 | static BYTE ByteSub(BYTE x) | ||
| 127 | { | ||
| 128 | BYTE y=ptab[255-ltab[x]]; /* multiplicative inverse */ | ||
| 129 | x=y; x=ROTL(x); | ||
| 130 | y^=x; x=ROTL(x); | ||
| 131 | y^=x; x=ROTL(x); | ||
| 132 | y^=x; x=ROTL(x); | ||
| 133 | y^=x; y^=0x63; | ||
| 134 | return y; | ||
| 135 | } | ||
| 136 | |||
| 137 | void suhosin_aes_gentables() | ||
| 138 | { /* generate tables */ | ||
| 139 | int i; | ||
| 140 | BYTE y,b[4]; | ||
| 141 | |||
| 142 | /* use 3 as primitive root to generate power and log tables */ | ||
| 143 | |||
| 144 | ltab[0]=0; | ||
| 145 | ptab[0]=1; ltab[1]=0; | ||
| 146 | ptab[1]=3; ltab[3]=1; | ||
| 147 | for (i=2;i<256;i++) | ||
| 148 | { | ||
| 149 | ptab[i]=ptab[i-1]^xtime(ptab[i-1]); | ||
| 150 | ltab[ptab[i]]=i; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* affine transformation:- each bit is xored with itself shifted one bit */ | ||
| 154 | |||
| 155 | fbsub[0]=0x63; | ||
| 156 | rbsub[0x63]=0; | ||
| 157 | for (i=1;i<256;i++) | ||
| 158 | { | ||
| 159 | y=ByteSub((BYTE)i); | ||
| 160 | fbsub[i]=y; rbsub[y]=i; | ||
| 161 | } | ||
| 162 | |||
| 163 | for (i=0,y=1;i<30;i++) | ||
| 164 | { | ||
| 165 | rco[i]=y; | ||
| 166 | y=xtime(y); | ||
| 167 | } | ||
| 168 | |||
| 169 | /* calculate forward and reverse tables */ | ||
| 170 | for (i=0;i<256;i++) | ||
| 171 | { | ||
| 172 | y=fbsub[i]; | ||
| 173 | b[3]=y^xtime(y); b[2]=y; | ||
| 174 | b[1]=y; b[0]=xtime(y); | ||
| 175 | ftable[i]=pack(b); | ||
| 176 | |||
| 177 | y=rbsub[i]; | ||
| 178 | b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y); | ||
| 179 | b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y); | ||
| 180 | rtable[i]=pack(b); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | void suhosin_aes_gkey(int nb,int nk,char *key TSRMLS_DC) | ||
| 185 | { /* blocksize=32*nb bits. Key=32*nk bits */ | ||
| 186 | /* currently nb,bk = 4, 6 or 8 */ | ||
| 187 | /* key comes as 4*Nk bytes */ | ||
| 188 | /* Key Scheduler. Create expanded encryption key */ | ||
| 189 | int i,j,k,m,N; | ||
| 190 | int C1,C2,C3; | ||
| 191 | WORD CipherKey[8]; | ||
| 192 | |||
| 193 | Nb=nb; Nk=nk; | ||
| 194 | |||
| 195 | /* Nr is number of rounds */ | ||
| 196 | if (Nb>=Nk) Nr=6+Nb; | ||
| 197 | else Nr=6+Nk; | ||
| 198 | |||
| 199 | C1=1; | ||
| 200 | if (Nb<8) { C2=2; C3=3; } | ||
| 201 | else { C2=3; C3=4; } | ||
| 202 | |||
| 203 | /* pre-calculate forward and reverse increments */ | ||
| 204 | for (m=j=0;j<nb;j++,m+=3) | ||
| 205 | { | ||
| 206 | SUHOSIN_G(fi)[m]=(j+C1)%nb; | ||
| 207 | SUHOSIN_G(fi)[m+1]=(j+C2)%nb; | ||
| 208 | SUHOSIN_G(fi)[m+2]=(j+C3)%nb; | ||
| 209 | SUHOSIN_G(ri)[m]=(nb+j-C1)%nb; | ||
| 210 | SUHOSIN_G(ri)[m+1]=(nb+j-C2)%nb; | ||
| 211 | SUHOSIN_G(ri)[m+2]=(nb+j-C3)%nb; | ||
| 212 | } | ||
| 213 | |||
| 214 | N=Nb*(Nr+1); | ||
| 215 | |||
| 216 | for (i=j=0;i<Nk;i++,j+=4) | ||
| 217 | { | ||
| 218 | CipherKey[i]=pack((BYTE *)&key[j]); | ||
| 219 | } | ||
| 220 | for (i=0;i<Nk;i++) SUHOSIN_G(fkey)[i]=CipherKey[i]; | ||
| 221 | for (j=Nk,k=0;j<N;j+=Nk,k++) | ||
| 222 | { | ||
| 223 | SUHOSIN_G(fkey)[j]=SUHOSIN_G(fkey)[j-Nk]^SubByte(ROTL24(SUHOSIN_G(fkey)[j-1]))^rco[k]; | ||
| 224 | if (Nk<=6) | ||
| 225 | { | ||
| 226 | for (i=1;i<Nk && (i+j)<N;i++) | ||
| 227 | SUHOSIN_G(fkey)[i+j]=SUHOSIN_G(fkey)[i+j-Nk]^SUHOSIN_G(fkey)[i+j-1]; | ||
| 228 | } | ||
| 229 | else | ||
| 230 | { | ||
| 231 | for (i=1;i<4 &&(i+j)<N;i++) | ||
| 232 | SUHOSIN_G(fkey)[i+j]=SUHOSIN_G(fkey)[i+j-Nk]^SUHOSIN_G(fkey)[i+j-1]; | ||
| 233 | if ((j+4)<N) SUHOSIN_G(fkey)[j+4]=SUHOSIN_G(fkey)[j+4-Nk]^SubByte(SUHOSIN_G(fkey)[j+3]); | ||
| 234 | for (i=5;i<Nk && (i+j)<N;i++) | ||
| 235 | SUHOSIN_G(fkey)[i+j]=SUHOSIN_G(fkey)[i+j-Nk]^SUHOSIN_G(fkey)[i+j-1]; | ||
| 236 | } | ||
| 237 | |||
| 238 | } | ||
| 239 | |||
| 240 | /* now for the expanded decrypt key in reverse order */ | ||
| 241 | |||
| 242 | for (j=0;j<Nb;j++) SUHOSIN_G(rkey)[j+N-Nb]=SUHOSIN_G(fkey)[j]; | ||
| 243 | for (i=Nb;i<N-Nb;i+=Nb) | ||
| 244 | { | ||
| 245 | k=N-Nb-i; | ||
| 246 | for (j=0;j<Nb;j++) SUHOSIN_G(rkey)[k+j]=InvMixCol(SUHOSIN_G(fkey)[i+j]); | ||
| 247 | } | ||
| 248 | for (j=N-Nb;j<N;j++) SUHOSIN_G(rkey)[j-N+Nb]=SUHOSIN_G(fkey)[j]; | ||
| 249 | } | ||
| 250 | |||
| 251 | |||
| 252 | /* There is an obvious time/space trade-off possible here. * | ||
| 253 | * Instead of just one ftable[], I could have 4, the other * | ||
| 254 | * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */ | ||
| 255 | |||
| 256 | void suhosin_aes_encrypt(char *buff TSRMLS_DC) | ||
| 257 | { | ||
| 258 | int i,j,k,m; | ||
| 259 | WORD a[8],b[8],*x,*y,*t; | ||
| 260 | |||
| 261 | for (i=j=0;i<Nb;i++,j+=4) | ||
| 262 | { | ||
| 263 | a[i]=pack((BYTE *)&buff[j]); | ||
| 264 | a[i]^=SUHOSIN_G(fkey)[i]; | ||
| 265 | } | ||
| 266 | k=Nb; | ||
| 267 | x=a; y=b; | ||
| 268 | |||
| 269 | /* State alternates between a and b */ | ||
| 270 | for (i=1;i<Nr;i++) | ||
| 271 | { /* Nr is number of rounds. May be odd. */ | ||
| 272 | |||
| 273 | /* if Nb is fixed - unroll this next | ||
| 274 | loop and hard-code in the values of fi[] */ | ||
| 275 | |||
| 276 | for (m=j=0;j<Nb;j++,m+=3) | ||
| 277 | { /* deal with each 32-bit element of the State */ | ||
| 278 | /* This is the time-critical bit */ | ||
| 279 | y[j]=SUHOSIN_G(fkey)[k++]^ftable[(BYTE)x[j]]^ | ||
| 280 | ROTL8(ftable[(BYTE)(x[SUHOSIN_G(fi)[m]]>>8)])^ | ||
| 281 | ROTL16(ftable[(BYTE)(x[SUHOSIN_G(fi)[m+1]]>>16)])^ | ||
| 282 | ROTL24(ftable[x[SUHOSIN_G(fi)[m+2]]>>24]); | ||
| 283 | } | ||
| 284 | t=x; x=y; y=t; /* swap pointers */ | ||
| 285 | } | ||
| 286 | |||
| 287 | /* Last Round - unroll if possible */ | ||
| 288 | for (m=j=0;j<Nb;j++,m+=3) | ||
| 289 | { | ||
| 290 | y[j]=SUHOSIN_G(fkey)[k++]^(WORD)fbsub[(BYTE)x[j]]^ | ||
| 291 | ROTL8((WORD)fbsub[(BYTE)(x[SUHOSIN_G(fi)[m]]>>8)])^ | ||
| 292 | ROTL16((WORD)fbsub[(BYTE)(x[SUHOSIN_G(fi)[m+1]]>>16)])^ | ||
| 293 | ROTL24((WORD)fbsub[x[SUHOSIN_G(fi)[m+2]]>>24]); | ||
| 294 | } | ||
| 295 | for (i=j=0;i<Nb;i++,j+=4) | ||
| 296 | { | ||
| 297 | unpack(y[i],(BYTE *)&buff[j]); | ||
| 298 | x[i]=y[i]=0; /* clean up stack */ | ||
| 299 | } | ||
| 300 | return; | ||
| 301 | } | ||
| 302 | |||
| 303 | void suhosin_aes_decrypt(char *buff TSRMLS_DC) | ||
| 304 | { | ||
| 305 | int i,j,k,m; | ||
| 306 | WORD a[8],b[8],*x,*y,*t; | ||
| 307 | |||
| 308 | for (i=j=0;i<Nb;i++,j+=4) | ||
| 309 | { | ||
| 310 | a[i]=pack((BYTE *)&buff[j]); | ||
| 311 | a[i]^=SUHOSIN_G(rkey)[i]; | ||
| 312 | } | ||
| 313 | k=Nb; | ||
| 314 | x=a; y=b; | ||
| 315 | |||
| 316 | /* State alternates between a and b */ | ||
| 317 | for (i=1;i<Nr;i++) | ||
| 318 | { /* Nr is number of rounds. May be odd. */ | ||
| 319 | |||
| 320 | /* if Nb is fixed - unroll this next | ||
| 321 | loop and hard-code in the values of ri[] */ | ||
| 322 | |||
| 323 | for (m=j=0;j<Nb;j++,m+=3) | ||
| 324 | { /* This is the time-critical bit */ | ||
| 325 | y[j]=SUHOSIN_G(rkey)[k++]^rtable[(BYTE)x[j]]^ | ||
| 326 | ROTL8(rtable[(BYTE)(x[SUHOSIN_G(ri)[m]]>>8)])^ | ||
| 327 | ROTL16(rtable[(BYTE)(x[SUHOSIN_G(ri)[m+1]]>>16)])^ | ||
| 328 | ROTL24(rtable[x[SUHOSIN_G(ri)[m+2]]>>24]); | ||
| 329 | } | ||
| 330 | t=x; x=y; y=t; /* swap pointers */ | ||
| 331 | } | ||
| 332 | |||
| 333 | /* Last Round - unroll if possible */ | ||
| 334 | for (m=j=0;j<Nb;j++,m+=3) | ||
| 335 | { | ||
| 336 | y[j]=SUHOSIN_G(rkey)[k++]^(WORD)rbsub[(BYTE)x[j]]^ | ||
| 337 | ROTL8((WORD)rbsub[(BYTE)(x[SUHOSIN_G(ri)[m]]>>8)])^ | ||
| 338 | ROTL16((WORD)rbsub[(BYTE)(x[SUHOSIN_G(ri)[m+1]]>>16)])^ | ||
| 339 | ROTL24((WORD)rbsub[x[SUHOSIN_G(ri)[m+2]]>>24]); | ||
| 340 | } | ||
| 341 | for (i=j=0;i<Nb;i++,j+=4) | ||
| 342 | { | ||
| 343 | unpack(y[i],(BYTE *)&buff[j]); | ||
| 344 | x[i]=y[i]=0; /* clean up stack */ | ||
| 345 | } | ||
| 346 | return; | ||
| 347 | } | ||
| 348 | |||
| 349 | |||
| 350 | /* | ||
| 351 | static int main() | ||
| 352 | { | ||
| 353 | int i,nb,nk; | ||
| 354 | char key[32]; | ||
| 355 | char block[32]; | ||
| 356 | |||
| 357 | gentables(); | ||
| 358 | |||
| 359 | for (i=0;i<32;i++) key[i]=0; | ||
| 360 | key[0]=1; | ||
| 361 | for (i=0;i<32;i++) block[i]=i; | ||
| 362 | |||
| 363 | for (nb=4;nb<=8;nb+=2) | ||
| 364 | for (nk=4;nk<=8;nk+=2) | ||
| 365 | { | ||
| 366 | printf("\nBlock Size= %d bits, Key Size= %d bits\n",nb*32,nk*32); | ||
| 367 | gkey(nb,nk,key); | ||
| 368 | printf("Plain= "); | ||
| 369 | for (i=0;i<nb*4;i++) printf("%02x",block[i]); | ||
| 370 | printf("\n"); | ||
| 371 | encrypt(block); | ||
| 372 | printf("Encrypt= "); | ||
| 373 | for (i=0;i<nb*4;i++) printf("%02x",(unsigned char)block[i]); | ||
| 374 | printf("\n"); | ||
| 375 | decrypt(block); | ||
| 376 | printf("Decrypt= "); | ||
| 377 | for (i=0;i<nb*4;i++) printf("%02x",block[i]); | ||
| 378 | printf("\n"); | ||
| 379 | } | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | */ | ||
diff --git a/compat_snprintf.c b/compat_snprintf.c new file mode 100644 index 0000000..8f3682f --- /dev/null +++ b/compat_snprintf.c | |||
| @@ -0,0 +1,1001 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | PHP Version 4 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 1997-2003 The PHP Group | | ||
| 6 | +----------------------------------------------------------------------+ | ||
| 7 | | This source file is subject to version 2.02 of the PHP license, | | ||
| 8 | | that is bundled with this package in the file LICENSE, and is | | ||
| 9 | | available at through the world-wide-web at | | ||
| 10 | | http://www.php.net/license/2_02.txt. | | ||
| 11 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 12 | | obtain it through the world-wide-web, please send a note to | | ||
| 13 | | license@php.net so we can mail you a copy immediately. | | ||
| 14 | +----------------------------------------------------------------------+ | ||
| 15 | | Author: | | ||
| 16 | +----------------------------------------------------------------------+ | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* $Id: compat_snprintf.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 20 | |||
| 21 | /* ==================================================================== | ||
| 22 | * Copyright (c) 1995-1998 The Apache Group. All rights reserved. | ||
| 23 | * | ||
| 24 | * Redistribution and use in source and binary forms, with or without | ||
| 25 | * modification, are permitted provided that the following conditions | ||
| 26 | * are met: | ||
| 27 | * | ||
| 28 | * 1. Redistributions of source code must retain the above copyright | ||
| 29 | * notice, this list of conditions and the following disclaimer. | ||
| 30 | * | ||
| 31 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 32 | * notice, this list of conditions and the following disclaimer in | ||
| 33 | * the documentation and/or other materials provided with the | ||
| 34 | * distribution. | ||
| 35 | * | ||
| 36 | * 3. All advertising materials mentioning features or use of this | ||
| 37 | * software must display the following acknowledgment: | ||
| 38 | * "This product includes software developed by the Apache Group | ||
| 39 | * for use in the Apache HTTP server project (http://www.apache.org/)." | ||
| 40 | * | ||
| 41 | * 4. The names "Apache Server" and "Apache Group" must not be used to | ||
| 42 | * endorse or promote products derived from this software without | ||
| 43 | * prior written permission. | ||
| 44 | * | ||
| 45 | * 5. Redistributions of any form whatsoever must retain the following | ||
| 46 | * acknowledgment: | ||
| 47 | * "This product includes software developed by the Apache Group | ||
| 48 | * for use in the Apache HTTP server project (http://www.apache.org/)." | ||
| 49 | * | ||
| 50 | * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY | ||
| 51 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 52 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 53 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR | ||
| 54 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 56 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 57 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 59 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 60 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
| 61 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 62 | * ==================================================================== | ||
| 63 | * | ||
| 64 | * This software consists of voluntary contributions made by many | ||
| 65 | * individuals on behalf of the Apache Group and was originally based | ||
| 66 | * on public domain software written at the National Center for | ||
| 67 | * Supercomputing Applications, University of Illinois, Urbana-Champaign. | ||
| 68 | * For more information on the Apache Group and the Apache HTTP server | ||
| 69 | * project, please see <http://www.apache.org/>. | ||
| 70 | * | ||
| 71 | * This code is based on, and used with the permission of, the | ||
| 72 | * SIO stdio-replacement strx_* functions by Panos Tsirigotis | ||
| 73 | * <panos@alumni.cs.colorado.edu> for xinetd. | ||
| 74 | */ | ||
| 75 | |||
| 76 | #include "php.h" | ||
| 77 | |||
| 78 | #if ((PHP_MAJOR_VERSION == 4) && (PHP_MINOR_VERSION == 3) && (PHP_RELEASE_VERSION < 10)) | ||
| 79 | |||
| 80 | #include <stdio.h> | ||
| 81 | #include <ctype.h> | ||
| 82 | #include <sys/types.h> | ||
| 83 | #include <stdarg.h> | ||
| 84 | #include <string.h> | ||
| 85 | #include <stdlib.h> | ||
| 86 | #include <math.h> | ||
| 87 | |||
| 88 | #define FALSE 0 | ||
| 89 | #define TRUE 1 | ||
| 90 | #define NUL '\0' | ||
| 91 | #define INT_NULL ((int *)0) | ||
| 92 | |||
| 93 | #define S_NULL "(null)" | ||
| 94 | #define S_NULL_LEN 6 | ||
| 95 | |||
| 96 | #define FLOAT_DIGITS 6 | ||
| 97 | #define EXPONENT_LENGTH 10 | ||
| 98 | |||
| 99 | |||
| 100 | /* | ||
| 101 | * Convert num to its decimal format. | ||
| 102 | * Return value: | ||
| 103 | * - a pointer to a string containing the number (no sign) | ||
| 104 | * - len contains the length of the string | ||
| 105 | * - is_negative is set to TRUE or FALSE depending on the sign | ||
| 106 | * of the number (always set to FALSE if is_unsigned is TRUE) | ||
| 107 | * | ||
| 108 | * The caller provides a buffer for the string: that is the buf_end argument | ||
| 109 | * which is a pointer to the END of the buffer + 1 (i.e. if the buffer | ||
| 110 | * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) | ||
| 111 | */ | ||
| 112 | char * | ||
| 113 | ap_php_conv_10(register wide_int num, register bool_int is_unsigned, | ||
| 114 | register bool_int * is_negative, char *buf_end, register int *len) | ||
| 115 | { | ||
| 116 | register char *p = buf_end; | ||
| 117 | register u_wide_int magnitude; | ||
| 118 | |||
| 119 | if (is_unsigned) { | ||
| 120 | magnitude = (u_wide_int) num; | ||
| 121 | *is_negative = FALSE; | ||
| 122 | } else { | ||
| 123 | *is_negative = (num < 0); | ||
| 124 | |||
| 125 | /* | ||
| 126 | * On a 2's complement machine, negating the most negative integer | ||
| 127 | * results in a number that cannot be represented as a signed integer. | ||
| 128 | * Here is what we do to obtain the number's magnitude: | ||
| 129 | * a. add 1 to the number | ||
| 130 | * b. negate it (becomes positive) | ||
| 131 | * c. convert it to unsigned | ||
| 132 | * d. add 1 | ||
| 133 | */ | ||
| 134 | if (*is_negative) { | ||
| 135 | wide_int t = num + 1; | ||
| 136 | |||
| 137 | magnitude = ((u_wide_int) - t) + 1; | ||
| 138 | } else | ||
| 139 | magnitude = (u_wide_int) num; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * We use a do-while loop so that we write at least 1 digit | ||
| 144 | */ | ||
| 145 | do { | ||
| 146 | register u_wide_int new_magnitude = magnitude / 10; | ||
| 147 | |||
| 148 | *--p = (char)(magnitude - new_magnitude * 10 + '0'); | ||
| 149 | magnitude = new_magnitude; | ||
| 150 | } | ||
| 151 | while (magnitude); | ||
| 152 | |||
| 153 | *len = buf_end - p; | ||
| 154 | return (p); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* If you change this value then also change bug24640.phpt. | ||
| 158 | */ | ||
| 159 | #define NDIG 80 | ||
| 160 | |||
| 161 | |||
| 162 | /* | ||
| 163 | * Convert a floating point number to a string formats 'f', 'e' or 'E'. | ||
| 164 | * The result is placed in buf, and len denotes the length of the string | ||
| 165 | * The sign is returned in the is_negative argument (and is not placed | ||
| 166 | * in buf). | ||
| 167 | */ | ||
| 168 | char * | ||
| 169 | ap_php_conv_fp(register char format, register double num, | ||
| 170 | boolean_e add_dp, int precision, bool_int * is_negative, char *buf, int *len) | ||
| 171 | { | ||
| 172 | register char *s = buf; | ||
| 173 | register char *p; | ||
| 174 | int decimal_point; | ||
| 175 | char buf1[NDIG]; | ||
| 176 | |||
| 177 | if (format == 'f') | ||
| 178 | p = ap_php_fcvt(num, precision, &decimal_point, is_negative, buf1); | ||
| 179 | else /* either e or E format */ | ||
| 180 | p = ap_php_ecvt(num, precision + 1, &decimal_point, is_negative, buf1); | ||
| 181 | |||
| 182 | /* | ||
| 183 | * Check for Infinity and NaN | ||
| 184 | */ | ||
| 185 | if (isalpha((int)*p)) { | ||
| 186 | *len = strlen(p); | ||
| 187 | memcpy(buf, p, *len + 1); | ||
| 188 | *is_negative = FALSE; | ||
| 189 | return (buf); | ||
| 190 | } | ||
| 191 | if (format == 'f') { | ||
| 192 | if (decimal_point <= 0) { | ||
| 193 | *s++ = '0'; | ||
| 194 | if (precision > 0) { | ||
| 195 | *s++ = '.'; | ||
| 196 | while (decimal_point++ < 0) | ||
| 197 | *s++ = '0'; | ||
| 198 | } else if (add_dp) { | ||
| 199 | *s++ = '.'; | ||
| 200 | } | ||
| 201 | } else { | ||
| 202 | while (decimal_point-- > 0) { | ||
| 203 | *s++ = *p++; | ||
| 204 | } | ||
| 205 | if (precision > 0 || add_dp) { | ||
| 206 | *s++ = '.'; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } else { | ||
| 210 | *s++ = *p++; | ||
| 211 | if (precision > 0 || add_dp) | ||
| 212 | *s++ = '.'; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* | ||
| 216 | * copy the rest of p, the NUL is NOT copied | ||
| 217 | */ | ||
| 218 | while (*p) | ||
| 219 | *s++ = *p++; | ||
| 220 | |||
| 221 | if (format != 'f') { | ||
| 222 | char temp[EXPONENT_LENGTH]; /* for exponent conversion */ | ||
| 223 | int t_len; | ||
| 224 | bool_int exponent_is_negative; | ||
| 225 | |||
| 226 | *s++ = format; /* either e or E */ | ||
| 227 | decimal_point--; | ||
| 228 | if (decimal_point != 0) { | ||
| 229 | p = ap_php_conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, | ||
| 230 | &temp[EXPONENT_LENGTH], &t_len); | ||
| 231 | *s++ = exponent_is_negative ? '-' : '+'; | ||
| 232 | |||
| 233 | /* | ||
| 234 | * Make sure the exponent has at least 2 digits | ||
| 235 | */ | ||
| 236 | if (t_len == 1) | ||
| 237 | *s++ = '0'; | ||
| 238 | while (t_len--) | ||
| 239 | *s++ = *p++; | ||
| 240 | } else { | ||
| 241 | *s++ = '+'; | ||
| 242 | *s++ = '0'; | ||
| 243 | *s++ = '0'; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | *len = s - buf; | ||
| 247 | return (buf); | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | /* | ||
| 252 | * Convert num to a base X number where X is a power of 2. nbits determines X. | ||
| 253 | * For example, if nbits is 3, we do base 8 conversion | ||
| 254 | * Return value: | ||
| 255 | * a pointer to a string containing the number | ||
| 256 | * | ||
| 257 | * The caller provides a buffer for the string: that is the buf_end argument | ||
| 258 | * which is a pointer to the END of the buffer + 1 (i.e. if the buffer | ||
| 259 | * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) | ||
| 260 | */ | ||
| 261 | char * | ||
| 262 | ap_php_conv_p2(register u_wide_int num, register int nbits, | ||
| 263 | char format, char *buf_end, register int *len) | ||
| 264 | { | ||
| 265 | register int mask = (1 << nbits) - 1; | ||
| 266 | register char *p = buf_end; | ||
| 267 | static char low_digits[] = "0123456789abcdef"; | ||
| 268 | static char upper_digits[] = "0123456789ABCDEF"; | ||
| 269 | register char *digits = (format == 'X') ? upper_digits : low_digits; | ||
| 270 | |||
| 271 | do { | ||
| 272 | *--p = digits[num & mask]; | ||
| 273 | num >>= nbits; | ||
| 274 | } | ||
| 275 | while (num); | ||
| 276 | |||
| 277 | *len = buf_end - p; | ||
| 278 | return (p); | ||
| 279 | } | ||
| 280 | |||
| 281 | /* | ||
| 282 | * cvt.c - IEEE floating point formatting routines for FreeBSD | ||
| 283 | * from GNU libc-4.6.27 | ||
| 284 | */ | ||
| 285 | |||
| 286 | /* | ||
| 287 | * ap_php_ecvt converts to decimal | ||
| 288 | * the number of digits is specified by ndigit | ||
| 289 | * decpt is set to the position of the decimal point | ||
| 290 | * sign is set to 0 for positive, 1 for negative | ||
| 291 | */ | ||
| 292 | |||
| 293 | |||
| 294 | char * | ||
| 295 | ap_php_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf) | ||
| 296 | { | ||
| 297 | register int r2; | ||
| 298 | int mvl; | ||
| 299 | double fi, fj; | ||
| 300 | register char *p, *p1; | ||
| 301 | |||
| 302 | if (ndigits >= NDIG - 1) | ||
| 303 | ndigits = NDIG - 2; | ||
| 304 | r2 = 0; | ||
| 305 | *sign = 0; | ||
| 306 | p = &buf[0]; | ||
| 307 | if (arg < 0) { | ||
| 308 | *sign = 1; | ||
| 309 | arg = -arg; | ||
| 310 | } | ||
| 311 | arg = modf(arg, &fi); | ||
| 312 | p1 = &buf[NDIG]; | ||
| 313 | /* | ||
| 314 | * Do integer part | ||
| 315 | */ | ||
| 316 | if (fi != 0) { | ||
| 317 | p1 = &buf[NDIG]; | ||
| 318 | while (fi != 0) { | ||
| 319 | fj = modf(fi / 10, &fi); | ||
| 320 | if (p1 <= &buf[0]) { | ||
| 321 | mvl = NDIG - ndigits; | ||
| 322 | memmove(&buf[mvl], &buf[0], NDIG-mvl-1); | ||
| 323 | p1 += mvl; | ||
| 324 | } | ||
| 325 | *--p1 = (int) ((fj + .03) * 10) + '0'; | ||
| 326 | r2++; | ||
| 327 | } | ||
| 328 | while (p1 < &buf[NDIG]) | ||
| 329 | *p++ = *p1++; | ||
| 330 | } else if (arg > 0) { | ||
| 331 | while ((fj = arg * 10) < 1) { | ||
| 332 | if (!eflag && (r2 * -1) < ndigits) { | ||
| 333 | break; | ||
| 334 | } | ||
| 335 | arg = fj; | ||
| 336 | r2--; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | p1 = &buf[ndigits]; | ||
| 340 | if (eflag == 0) | ||
| 341 | p1 += r2; | ||
| 342 | *decpt = r2; | ||
| 343 | if (p1 < &buf[0]) { | ||
| 344 | buf[0] = '\0'; | ||
| 345 | return (buf); | ||
| 346 | } | ||
| 347 | if (p <= p1 && p < &buf[NDIG]) { | ||
| 348 | arg = modf(arg * 10, &fj); | ||
| 349 | if ((int)fj==10) { | ||
| 350 | *p++ = '1'; | ||
| 351 | fj = 0; | ||
| 352 | *decpt = ++r2; | ||
| 353 | } | ||
| 354 | while (p <= p1 && p < &buf[NDIG]) { | ||
| 355 | *p++ = (int) fj + '0'; | ||
| 356 | arg = modf(arg * 10, &fj); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | if (p1 >= &buf[NDIG]) { | ||
| 360 | buf[NDIG - 1] = '\0'; | ||
| 361 | return (buf); | ||
| 362 | } | ||
| 363 | p = p1; | ||
| 364 | *p1 += 5; | ||
| 365 | while (*p1 > '9') { | ||
| 366 | *p1 = '0'; | ||
| 367 | if (p1 > buf) | ||
| 368 | ++ * --p1; | ||
| 369 | else { | ||
| 370 | *p1 = '1'; | ||
| 371 | (*decpt)++; | ||
| 372 | if (eflag == 0) { | ||
| 373 | if (p > buf) | ||
| 374 | *p = '0'; | ||
| 375 | p++; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | } | ||
| 379 | *p = '\0'; | ||
| 380 | return (buf); | ||
| 381 | } | ||
| 382 | |||
| 383 | char * | ||
| 384 | ap_php_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf) | ||
| 385 | { | ||
| 386 | return (ap_php_cvt(arg, ndigits, decpt, sign, 1, buf)); | ||
| 387 | } | ||
| 388 | |||
| 389 | char * | ||
| 390 | ap_php_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf) | ||
| 391 | { | ||
| 392 | return (ap_php_cvt(arg, ndigits, decpt, sign, 0, buf)); | ||
| 393 | } | ||
| 394 | |||
| 395 | /* | ||
| 396 | * ap_php_gcvt - Floating output conversion to | ||
| 397 | * minimal length string | ||
| 398 | */ | ||
| 399 | |||
| 400 | char * | ||
| 401 | ap_php_gcvt(double number, int ndigit, char *buf, boolean_e altform) | ||
| 402 | { | ||
| 403 | int sign, decpt; | ||
| 404 | register char *p1, *p2; | ||
| 405 | register int i; | ||
| 406 | char buf1[NDIG]; | ||
| 407 | |||
| 408 | if (ndigit >= NDIG - 1) { | ||
| 409 | ndigit = NDIG - 2; | ||
| 410 | } | ||
| 411 | |||
| 412 | p1 = ap_php_ecvt(number, ndigit, &decpt, &sign, buf1); | ||
| 413 | p2 = buf; | ||
| 414 | if (sign) | ||
| 415 | *p2++ = '-'; | ||
| 416 | for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) | ||
| 417 | ndigit--; | ||
| 418 | if ((decpt >= 0 && decpt - ndigit > 4) | ||
| 419 | || (decpt < 0 && decpt < -3)) { /* use E-style */ | ||
| 420 | decpt--; | ||
| 421 | *p2++ = *p1++; | ||
| 422 | *p2++ = '.'; | ||
| 423 | for (i = 1; i < ndigit; i++) | ||
| 424 | *p2++ = *p1++; | ||
| 425 | if (*(p2 - 1) == '.') { | ||
| 426 | *p2++ = '0'; | ||
| 427 | } | ||
| 428 | *p2++ = 'e'; | ||
| 429 | if (decpt < 0) { | ||
| 430 | decpt = -decpt; | ||
| 431 | *p2++ = '-'; | ||
| 432 | } else | ||
| 433 | *p2++ = '+'; | ||
| 434 | if (decpt / 100 > 0) | ||
| 435 | *p2++ = decpt / 100 + '0'; | ||
| 436 | if (decpt / 10 > 0) | ||
| 437 | *p2++ = (decpt % 100) / 10 + '0'; | ||
| 438 | *p2++ = decpt % 10 + '0'; | ||
| 439 | } else { | ||
| 440 | if (decpt <= 0) { | ||
| 441 | if (*p1 != '0') { | ||
| 442 | *p2++ = '0'; | ||
| 443 | *p2++ = '.'; | ||
| 444 | } | ||
| 445 | while (decpt < 0) { | ||
| 446 | decpt++; | ||
| 447 | *p2++ = '0'; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | for (i = 1; i <= ndigit; i++) { | ||
| 451 | *p2++ = *p1++; | ||
| 452 | if (i == decpt) | ||
| 453 | *p2++ = '.'; | ||
| 454 | } | ||
| 455 | if (ndigit < decpt) { | ||
| 456 | while (ndigit++ < decpt) | ||
| 457 | *p2++ = '0'; | ||
| 458 | *p2++ = '.'; | ||
| 459 | } | ||
| 460 | } | ||
| 461 | if (p2[-1] == '.' && !altform) | ||
| 462 | p2--; | ||
| 463 | *p2 = '\0'; | ||
| 464 | return (buf); | ||
| 465 | } | ||
| 466 | |||
| 467 | |||
| 468 | /* | ||
| 469 | * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions | ||
| 470 | * | ||
| 471 | * XXX: this is a magic number; do not decrease it | ||
| 472 | */ | ||
| 473 | #define NUM_BUF_SIZE 512 | ||
| 474 | |||
| 475 | |||
| 476 | /* | ||
| 477 | * Descriptor for buffer area | ||
| 478 | */ | ||
| 479 | struct buf_area { | ||
| 480 | char *buf_end; | ||
| 481 | char *nextb; /* pointer to next byte to read/write */ | ||
| 482 | }; | ||
| 483 | |||
| 484 | typedef struct buf_area buffy; | ||
| 485 | |||
| 486 | /* | ||
| 487 | * The INS_CHAR macro inserts a character in the buffer and writes | ||
| 488 | * the buffer back to disk if necessary | ||
| 489 | * It uses the char pointers sp and bep: | ||
| 490 | * sp points to the next available character in the buffer | ||
| 491 | * bep points to the end-of-buffer+1 | ||
| 492 | * While using this macro, note that the nextb pointer is NOT updated. | ||
| 493 | * | ||
| 494 | * NOTE: Evaluation of the c argument should not have any side-effects | ||
| 495 | */ | ||
| 496 | #define INS_CHAR(c, sp, bep, cc) \ | ||
| 497 | { \ | ||
| 498 | if (sp < bep) \ | ||
| 499 | { \ | ||
| 500 | *sp++ = c; \ | ||
| 501 | } \ | ||
| 502 | cc++; \ | ||
| 503 | } | ||
| 504 | |||
| 505 | #define NUM( c ) ( c - '0' ) | ||
| 506 | |||
| 507 | #define STR_TO_DEC( str, num ) \ | ||
| 508 | num = NUM( *str++ ) ; \ | ||
| 509 | while ( isdigit((int)*str ) ) \ | ||
| 510 | { \ | ||
| 511 | num *= 10 ; \ | ||
| 512 | num += NUM( *str++ ) ; \ | ||
| 513 | } | ||
| 514 | |||
| 515 | /* | ||
| 516 | * This macro does zero padding so that the precision | ||
| 517 | * requirement is satisfied. The padding is done by | ||
| 518 | * adding '0's to the left of the string that is going | ||
| 519 | * to be printed. | ||
| 520 | */ | ||
| 521 | #define FIX_PRECISION( adjust, precision, s, s_len ) \ | ||
| 522 | if ( adjust ) \ | ||
| 523 | while ( s_len < precision ) \ | ||
| 524 | { \ | ||
| 525 | *--s = '0' ; \ | ||
| 526 | s_len++ ; \ | ||
| 527 | } | ||
| 528 | |||
| 529 | /* | ||
| 530 | * Macro that does padding. The padding is done by printing | ||
| 531 | * the character ch. | ||
| 532 | */ | ||
| 533 | #define PAD( width, len, ch ) do \ | ||
| 534 | { \ | ||
| 535 | INS_CHAR( ch, sp, bep, cc ) ; \ | ||
| 536 | width-- ; \ | ||
| 537 | } \ | ||
| 538 | while ( width > len ) | ||
| 539 | |||
| 540 | /* | ||
| 541 | * Prefix the character ch to the string str | ||
| 542 | * Increase length | ||
| 543 | * Set the has_prefix flag | ||
| 544 | */ | ||
| 545 | #define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES | ||
| 546 | |||
| 547 | |||
| 548 | /* | ||
| 549 | * Do format conversion placing the output in buffer | ||
| 550 | */ | ||
| 551 | static int format_converter(register buffy * odp, const char *fmt, | ||
| 552 | va_list ap) | ||
| 553 | { | ||
| 554 | register char *sp; | ||
| 555 | register char *bep; | ||
| 556 | register int cc = 0; | ||
| 557 | register int i; | ||
| 558 | |||
| 559 | register char *s = NULL; | ||
| 560 | char *q; | ||
| 561 | int s_len; | ||
| 562 | |||
| 563 | register int min_width = 0; | ||
| 564 | int precision = 0; | ||
| 565 | enum { | ||
| 566 | LEFT, RIGHT | ||
| 567 | } adjust; | ||
| 568 | char pad_char; | ||
| 569 | char prefix_char; | ||
| 570 | |||
| 571 | double fp_num; | ||
| 572 | wide_int i_num = (wide_int) 0; | ||
| 573 | u_wide_int ui_num; | ||
| 574 | |||
| 575 | char num_buf[NUM_BUF_SIZE]; | ||
| 576 | char char_buf[2]; /* for printing %% and %<unknown> */ | ||
| 577 | |||
| 578 | /* | ||
| 579 | * Flag variables | ||
| 580 | */ | ||
| 581 | boolean_e is_long; | ||
| 582 | boolean_e alternate_form; | ||
| 583 | boolean_e print_sign; | ||
| 584 | boolean_e print_blank; | ||
| 585 | boolean_e adjust_precision; | ||
| 586 | boolean_e adjust_width; | ||
| 587 | bool_int is_negative; | ||
| 588 | |||
| 589 | sp = odp->nextb; | ||
| 590 | bep = odp->buf_end; | ||
| 591 | |||
| 592 | while (*fmt) { | ||
| 593 | if (*fmt != '%') { | ||
| 594 | INS_CHAR(*fmt, sp, bep, cc); | ||
| 595 | } else { | ||
| 596 | /* | ||
| 597 | * Default variable settings | ||
| 598 | */ | ||
| 599 | adjust = RIGHT; | ||
| 600 | alternate_form = print_sign = print_blank = NO; | ||
| 601 | pad_char = ' '; | ||
| 602 | prefix_char = NUL; | ||
| 603 | |||
| 604 | fmt++; | ||
| 605 | |||
| 606 | /* | ||
| 607 | * Try to avoid checking for flags, width or precision | ||
| 608 | */ | ||
| 609 | if (isascii((int)*fmt) && !islower((int)*fmt)) { | ||
| 610 | /* | ||
| 611 | * Recognize flags: -, #, BLANK, + | ||
| 612 | */ | ||
| 613 | for (;; fmt++) { | ||
| 614 | if (*fmt == '-') | ||
| 615 | adjust = LEFT; | ||
| 616 | else if (*fmt == '+') | ||
| 617 | print_sign = YES; | ||
| 618 | else if (*fmt == '#') | ||
| 619 | alternate_form = YES; | ||
| 620 | else if (*fmt == ' ') | ||
| 621 | print_blank = YES; | ||
| 622 | else if (*fmt == '0') | ||
| 623 | pad_char = '0'; | ||
| 624 | else | ||
| 625 | break; | ||
| 626 | } | ||
| 627 | |||
| 628 | /* | ||
| 629 | * Check if a width was specified | ||
| 630 | */ | ||
| 631 | if (isdigit((int)*fmt)) { | ||
| 632 | STR_TO_DEC(fmt, min_width); | ||
| 633 | adjust_width = YES; | ||
| 634 | } else if (*fmt == '*') { | ||
| 635 | min_width = va_arg(ap, int); | ||
| 636 | fmt++; | ||
| 637 | adjust_width = YES; | ||
| 638 | if (min_width < 0) { | ||
| 639 | adjust = LEFT; | ||
| 640 | min_width = -min_width; | ||
| 641 | } | ||
| 642 | } else | ||
| 643 | adjust_width = NO; | ||
| 644 | |||
| 645 | /* | ||
| 646 | * Check if a precision was specified | ||
| 647 | * | ||
| 648 | * XXX: an unreasonable amount of precision may be specified | ||
| 649 | * resulting in overflow of num_buf. Currently we | ||
| 650 | * ignore this possibility. | ||
| 651 | */ | ||
| 652 | if (*fmt == '.') { | ||
| 653 | adjust_precision = YES; | ||
| 654 | fmt++; | ||
| 655 | if (isdigit((int)*fmt)) { | ||
| 656 | STR_TO_DEC(fmt, precision); | ||
| 657 | } else if (*fmt == '*') { | ||
| 658 | precision = va_arg(ap, int); | ||
| 659 | fmt++; | ||
| 660 | if (precision < 0) | ||
| 661 | precision = 0; | ||
| 662 | } else | ||
| 663 | precision = 0; | ||
| 664 | } else | ||
| 665 | adjust_precision = NO; | ||
| 666 | } else | ||
| 667 | adjust_precision = adjust_width = NO; | ||
| 668 | |||
| 669 | /* | ||
| 670 | * Modifier check | ||
| 671 | */ | ||
| 672 | if (*fmt == 'l') { | ||
| 673 | is_long = YES; | ||
| 674 | fmt++; | ||
| 675 | } else | ||
| 676 | is_long = NO; | ||
| 677 | |||
| 678 | /* | ||
| 679 | * Argument extraction and printing. | ||
| 680 | * First we determine the argument type. | ||
| 681 | * Then, we convert the argument to a string. | ||
| 682 | * On exit from the switch, s points to the string that | ||
| 683 | * must be printed, s_len has the length of the string | ||
| 684 | * The precision requirements, if any, are reflected in s_len. | ||
| 685 | * | ||
| 686 | * NOTE: pad_char may be set to '0' because of the 0 flag. | ||
| 687 | * It is reset to ' ' by non-numeric formats | ||
| 688 | */ | ||
| 689 | switch (*fmt) { | ||
| 690 | case 'u': | ||
| 691 | if (is_long) | ||
| 692 | i_num = va_arg(ap, u_wide_int); | ||
| 693 | else | ||
| 694 | i_num = (wide_int) va_arg(ap, unsigned int); | ||
| 695 | /* | ||
| 696 | * The rest also applies to other integer formats, so fall | ||
| 697 | * into that case. | ||
| 698 | */ | ||
| 699 | case 'd': | ||
| 700 | case 'i': | ||
| 701 | /* | ||
| 702 | * Get the arg if we haven't already. | ||
| 703 | */ | ||
| 704 | if ((*fmt) != 'u') { | ||
| 705 | if (is_long) | ||
| 706 | i_num = va_arg(ap, wide_int); | ||
| 707 | else | ||
| 708 | i_num = (wide_int) va_arg(ap, int); | ||
| 709 | }; | ||
| 710 | s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative, | ||
| 711 | &num_buf[NUM_BUF_SIZE], &s_len); | ||
| 712 | FIX_PRECISION(adjust_precision, precision, s, s_len); | ||
| 713 | |||
| 714 | if (*fmt != 'u') { | ||
| 715 | if (is_negative) | ||
| 716 | prefix_char = '-'; | ||
| 717 | else if (print_sign) | ||
| 718 | prefix_char = '+'; | ||
| 719 | else if (print_blank) | ||
| 720 | prefix_char = ' '; | ||
| 721 | } | ||
| 722 | break; | ||
| 723 | |||
| 724 | |||
| 725 | case 'o': | ||
| 726 | if (is_long) | ||
| 727 | ui_num = va_arg(ap, u_wide_int); | ||
| 728 | else | ||
| 729 | ui_num = (u_wide_int) va_arg(ap, unsigned int); | ||
| 730 | s = ap_php_conv_p2(ui_num, 3, *fmt, | ||
| 731 | &num_buf[NUM_BUF_SIZE], &s_len); | ||
| 732 | FIX_PRECISION(adjust_precision, precision, s, s_len); | ||
| 733 | if (alternate_form && *s != '0') { | ||
| 734 | *--s = '0'; | ||
| 735 | s_len++; | ||
| 736 | } | ||
| 737 | break; | ||
| 738 | |||
| 739 | |||
| 740 | case 'x': | ||
| 741 | case 'X': | ||
| 742 | if (is_long) | ||
| 743 | ui_num = (u_wide_int) va_arg(ap, u_wide_int); | ||
| 744 | else | ||
| 745 | ui_num = (u_wide_int) va_arg(ap, unsigned int); | ||
| 746 | s = ap_php_conv_p2(ui_num, 4, *fmt, | ||
| 747 | &num_buf[NUM_BUF_SIZE], &s_len); | ||
| 748 | FIX_PRECISION(adjust_precision, precision, s, s_len); | ||
| 749 | if (alternate_form && i_num != 0) { | ||
| 750 | *--s = *fmt; /* 'x' or 'X' */ | ||
| 751 | *--s = '0'; | ||
| 752 | s_len += 2; | ||
| 753 | } | ||
| 754 | break; | ||
| 755 | |||
| 756 | |||
| 757 | case 's': | ||
| 758 | s = va_arg(ap, char *); | ||
| 759 | if (s != NULL) { | ||
| 760 | s_len = strlen(s); | ||
| 761 | if (adjust_precision && precision < s_len) | ||
| 762 | s_len = precision; | ||
| 763 | } else { | ||
| 764 | s = S_NULL; | ||
| 765 | s_len = S_NULL_LEN; | ||
| 766 | } | ||
| 767 | pad_char = ' '; | ||
| 768 | break; | ||
| 769 | |||
| 770 | |||
| 771 | case 'f': | ||
| 772 | case 'e': | ||
| 773 | case 'E': | ||
| 774 | fp_num = va_arg(ap, double); | ||
| 775 | |||
| 776 | if (zend_isnan(fp_num)) { | ||
| 777 | s = "nan"; | ||
| 778 | s_len = 3; | ||
| 779 | } else if (zend_isinf(fp_num)) { | ||
| 780 | s = "inf"; | ||
| 781 | s_len = 3; | ||
| 782 | } else { | ||
| 783 | s = ap_php_conv_fp(*fmt, fp_num, alternate_form, | ||
| 784 | (adjust_precision == NO) ? FLOAT_DIGITS : precision, | ||
| 785 | &is_negative, &num_buf[1], &s_len); | ||
| 786 | if (is_negative) | ||
| 787 | prefix_char = '-'; | ||
| 788 | else if (print_sign) | ||
| 789 | prefix_char = '+'; | ||
| 790 | else if (print_blank) | ||
| 791 | prefix_char = ' '; | ||
| 792 | } | ||
| 793 | break; | ||
| 794 | |||
| 795 | |||
| 796 | case 'g': | ||
| 797 | case 'G': | ||
| 798 | fp_num = va_arg(ap, double); | ||
| 799 | |||
| 800 | if (zend_isnan(fp_num)) { | ||
| 801 | s = "NAN"; | ||
| 802 | s_len = 3; | ||
| 803 | break; | ||
| 804 | } else if (zend_isinf(fp_num)) { | ||
| 805 | if (fp_num > 0) { | ||
| 806 | s = "INF"; | ||
| 807 | s_len = 3; | ||
| 808 | } else { | ||
| 809 | s = "-INF"; | ||
| 810 | s_len = 4; | ||
| 811 | } | ||
| 812 | break; | ||
| 813 | } | ||
| 814 | |||
| 815 | if (adjust_precision == NO) | ||
| 816 | precision = FLOAT_DIGITS; | ||
| 817 | else if (precision == 0) | ||
| 818 | precision = 1; | ||
| 819 | /* | ||
| 820 | * * We use &num_buf[ 1 ], so that we have room for the sign | ||
| 821 | */ | ||
| 822 | s = ap_php_gcvt(fp_num, precision, &num_buf[1], alternate_form); | ||
| 823 | if (*s == '-') | ||
| 824 | prefix_char = *s++; | ||
| 825 | else if (print_sign) | ||
| 826 | prefix_char = '+'; | ||
| 827 | else if (print_blank) | ||
| 828 | prefix_char = ' '; | ||
| 829 | |||
| 830 | s_len = strlen(s); | ||
| 831 | |||
| 832 | if (alternate_form && (q = strchr(s, '.')) == NULL) | ||
| 833 | s[s_len++] = '.'; | ||
| 834 | if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) | ||
| 835 | *q = 'E'; | ||
| 836 | break; | ||
| 837 | |||
| 838 | |||
| 839 | case 'c': | ||
| 840 | char_buf[0] = (char) (va_arg(ap, int)); | ||
| 841 | s = &char_buf[0]; | ||
| 842 | s_len = 1; | ||
| 843 | pad_char = ' '; | ||
| 844 | break; | ||
| 845 | |||
| 846 | |||
| 847 | case '%': | ||
| 848 | char_buf[0] = '%'; | ||
| 849 | s = &char_buf[0]; | ||
| 850 | s_len = 1; | ||
| 851 | pad_char = ' '; | ||
| 852 | break; | ||
| 853 | |||
| 854 | |||
| 855 | case 'n': | ||
| 856 | *(va_arg(ap, int *)) = cc; | ||
| 857 | break; | ||
| 858 | |||
| 859 | /* | ||
| 860 | * Always extract the argument as a "char *" pointer. We | ||
| 861 | * should be using "void *" but there are still machines | ||
| 862 | * that don't understand it. | ||
| 863 | * If the pointer size is equal to the size of an unsigned | ||
| 864 | * integer we convert the pointer to a hex number, otherwise | ||
| 865 | * we print "%p" to indicate that we don't handle "%p". | ||
| 866 | */ | ||
| 867 | case 'p': | ||
| 868 | ui_num = (u_wide_int) va_arg(ap, char *); | ||
| 869 | |||
| 870 | if (sizeof(char *) <= sizeof(u_wide_int)) | ||
| 871 | s = ap_php_conv_p2(ui_num, 4, 'x', | ||
| 872 | &num_buf[NUM_BUF_SIZE], &s_len); | ||
| 873 | else { | ||
| 874 | s = "%p"; | ||
| 875 | s_len = 2; | ||
| 876 | } | ||
| 877 | pad_char = ' '; | ||
| 878 | break; | ||
| 879 | |||
| 880 | |||
| 881 | case NUL: | ||
| 882 | /* | ||
| 883 | * The last character of the format string was %. | ||
| 884 | * We ignore it. | ||
| 885 | */ | ||
| 886 | continue; | ||
| 887 | |||
| 888 | |||
| 889 | /* | ||
| 890 | * The default case is for unrecognized %'s. | ||
| 891 | * We print %<char> to help the user identify what | ||
| 892 | * option is not understood. | ||
| 893 | * This is also useful in case the user wants to pass | ||
| 894 | * the output of format_converter to another function | ||
| 895 | * that understands some other %<char> (like syslog). | ||
| 896 | * Note that we can't point s inside fmt because the | ||
| 897 | * unknown <char> could be preceded by width etc. | ||
| 898 | */ | ||
| 899 | default: | ||
| 900 | char_buf[0] = '%'; | ||
| 901 | char_buf[1] = *fmt; | ||
| 902 | s = char_buf; | ||
| 903 | s_len = 2; | ||
| 904 | pad_char = ' '; | ||
| 905 | break; | ||
| 906 | } | ||
| 907 | |||
| 908 | if (prefix_char != NUL) { | ||
| 909 | *--s = prefix_char; | ||
| 910 | s_len++; | ||
| 911 | } | ||
| 912 | if (adjust_width && adjust == RIGHT && min_width > s_len) { | ||
| 913 | if (pad_char == '0' && prefix_char != NUL) { | ||
| 914 | INS_CHAR(*s, sp, bep, cc) | ||
| 915 | s++; | ||
| 916 | s_len--; | ||
| 917 | min_width--; | ||
| 918 | } | ||
| 919 | PAD(min_width, s_len, pad_char); | ||
| 920 | } | ||
| 921 | /* | ||
| 922 | * Print the string s. | ||
| 923 | */ | ||
| 924 | for (i = s_len; i != 0; i--) { | ||
| 925 | INS_CHAR(*s, sp, bep, cc); | ||
| 926 | s++; | ||
| 927 | } | ||
| 928 | |||
| 929 | if (adjust_width && adjust == LEFT && min_width > s_len) | ||
| 930 | PAD(min_width, s_len, pad_char); | ||
| 931 | } | ||
| 932 | fmt++; | ||
| 933 | } | ||
| 934 | odp->nextb = sp; | ||
| 935 | return (cc); | ||
| 936 | } | ||
| 937 | |||
| 938 | |||
| 939 | /* | ||
| 940 | * This is the general purpose conversion function. | ||
| 941 | */ | ||
| 942 | static void strx_printv(int *ccp, char *buf, size_t len, const char *format, | ||
| 943 | va_list ap) | ||
| 944 | { | ||
| 945 | buffy od; | ||
| 946 | int cc; | ||
| 947 | |||
| 948 | /* | ||
| 949 | * First initialize the descriptor | ||
| 950 | * Notice that if no length is given, we initialize buf_end to the | ||
| 951 | * highest possible address. | ||
| 952 | */ | ||
| 953 | if (len == 0) { | ||
| 954 | od.buf_end = (char *) ~0; | ||
| 955 | od.nextb = (char *) ~0; | ||
| 956 | } else { | ||
| 957 | od.buf_end = &buf[len-1]; | ||
| 958 | od.nextb = buf; | ||
| 959 | } | ||
| 960 | |||
| 961 | /* | ||
| 962 | * Do the conversion | ||
| 963 | */ | ||
| 964 | cc = format_converter(&od, format, ap); | ||
| 965 | if (len != 0 && od.nextb <= od.buf_end) | ||
| 966 | *(od.nextb) = '\0'; | ||
| 967 | if (ccp) | ||
| 968 | *ccp = cc; | ||
| 969 | } | ||
| 970 | |||
| 971 | |||
| 972 | int ap_php_snprintf(char *buf, size_t len, const char *format,...) | ||
| 973 | { | ||
| 974 | int cc; | ||
| 975 | va_list ap; | ||
| 976 | |||
| 977 | va_start(ap, format); | ||
| 978 | strx_printv(&cc, buf, len, format, ap); | ||
| 979 | va_end(ap); | ||
| 980 | return (cc); | ||
| 981 | } | ||
| 982 | |||
| 983 | |||
| 984 | int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) | ||
| 985 | { | ||
| 986 | int cc; | ||
| 987 | |||
| 988 | strx_printv(&cc, buf, len, format, ap); | ||
| 989 | return (cc); | ||
| 990 | } | ||
| 991 | |||
| 992 | #endif | ||
| 993 | |||
| 994 | /* | ||
| 995 | * Local variables: | ||
| 996 | * tab-width: 4 | ||
| 997 | * c-basic-offset: 4 | ||
| 998 | * End: | ||
| 999 | * vim600: sw=4 ts=4 fdm=marker | ||
| 1000 | * vim<600: sw=4 ts=4 | ||
| 1001 | */ | ||
diff --git a/config.m4 b/config.m4 new file mode 100644 index 0000000..d5e52e2 --- /dev/null +++ b/config.m4 | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | dnl $Id: config.m4,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 2 | dnl config.m4 for extension suhosin | ||
| 3 | |||
| 4 | PHP_ARG_ENABLE(suhosin, whether to enable suhosin support, | ||
| 5 | [ --enable-suhosin Enable suhosin support]) | ||
| 6 | |||
| 7 | if test "$PHP_SUHOSIN" != "no"; then | ||
| 8 | PHP_NEW_EXTENSION(suhosin, suhosin.c crypt.c crypt_blowfish.c sha256.c memory_limit.c treat_data.c ifilter.c post_handler.c ufilter.c rfc1867.c log.c header.c execute.c ex_imp.c session.c aes.c compat_snprintf.c, $ext_shared) | ||
| 9 | fi | ||
diff --git a/config.w32 b/config.w32 new file mode 100644 index 0000000..bd0e169 --- /dev/null +++ b/config.w32 | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | // $Id: config.w32,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 2 | // vim:ft=javascript | ||
| 3 | |||
| 4 | ARG_ENABLE("suhosin", "whether to enable suhosin support", "yes"); | ||
| 5 | |||
| 6 | if (PHP_SUHOSIN == "yes") { | ||
| 7 | EXTENSION("suhosin", "suhosin.c crypt.c crypt_blowfish.c sha256.c memory_limit.c treat_data.c ifilter.c post_handler.c ufilter.c rfc1867.c log.c header.c execute.c ex_imp.c session.c aes.c"); | ||
| 8 | if (PHP_SUHOSIN_SHARED) { | ||
| 9 | ADD_SOURCES(configure_module_dirname, "crypt_win32.c crypt_md5.c", "suhosin"); | ||
| 10 | } | ||
| 11 | } | ||
| @@ -0,0 +1,214 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: crypt.c,v 1.2 2008-01-04 11:23:47 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "php_suhosin.h" | ||
| 30 | |||
| 31 | |||
| 32 | #if HAVE_UNISTD_H | ||
| 33 | #include <unistd.h> | ||
| 34 | #endif | ||
| 35 | #if HAVE_CRYPT_H | ||
| 36 | #include <crypt.h> | ||
| 37 | #endif | ||
| 38 | #if TM_IN_SYS_TIME | ||
| 39 | #include <sys/time.h> | ||
| 40 | #else | ||
| 41 | #include <time.h> | ||
| 42 | #endif | ||
| 43 | #if HAVE_STRING_H | ||
| 44 | #include <string.h> | ||
| 45 | #else | ||
| 46 | #include <strings.h> | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #ifdef PHP_WIN32 | ||
| 50 | #include <process.h> | ||
| 51 | extern char *crypt(char *__key, char *__salt); | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #include "ext/standard/php_lcg.h" | ||
| 55 | #include "ext/standard/php_crypt.h" | ||
| 56 | #include "ext/standard/php_rand.h" | ||
| 57 | |||
| 58 | |||
| 59 | #define PHP_CRYPT_RAND php_rand(TSRMLS_C) | ||
| 60 | |||
| 61 | #define BLOWFISH_SALT_LEN 60 | ||
| 62 | |||
| 63 | #ifdef ZTS | ||
| 64 | static MUTEX_T suhosin_crypt_mutex; | ||
| 65 | #endif | ||
| 66 | |||
| 67 | static int CRYPT_MD5 = 0; | ||
| 68 | |||
| 69 | char *suhosin_crypt_blowfish_rn(char *key, char *setting, char *output, int size); | ||
| 70 | char *suhosin_crypt_gensalt_blowfish_rn(unsigned long count, char *input, int size, char *output, int output_size); | ||
| 71 | |||
| 72 | static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | ||
| 73 | |||
| 74 | static void php_to64(char *s, long v, int n) | ||
| 75 | { | ||
| 76 | while (--n >= 0) { | ||
| 77 | *s++ = itoa64[v&0x3f]; | ||
| 78 | v >>= 6; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | /* {{{ proto string crypt(string str [, string salt]) | ||
| 83 | Encrypt a string */ | ||
| 84 | static PHP_FUNCTION(suhosin_crypt) | ||
| 85 | { | ||
| 86 | char salt[BLOWFISH_SALT_LEN+1]; | ||
| 87 | char *str, *salt_in = NULL; | ||
| 88 | int str_len, salt_in_len; | ||
| 89 | |||
| 90 | salt[0]=salt[BLOWFISH_SALT_LEN]='\0'; | ||
| 91 | /* This will produce suitable results if people depend on DES-encryption | ||
| 92 | available (passing always 2-character salt). At least for glibc6.1 */ | ||
| 93 | memset(&salt[1], '$', BLOWFISH_SALT_LEN-1); | ||
| 94 | |||
| 95 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, | ||
| 96 | &salt_in, &salt_in_len) == FAILURE) { | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 100 | if (salt_in) { | ||
| 101 | memcpy(salt, salt_in, MIN(BLOWFISH_SALT_LEN, salt_in_len)); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* The automatic salt generation only covers standard DES and md5-crypt */ | ||
| 105 | if(!*salt) { | ||
| 106 | if (CRYPT_MD5) { | ||
| 107 | strcpy(salt, "$1$"); | ||
| 108 | php_to64(&salt[3], PHP_CRYPT_RAND, 4); | ||
| 109 | php_to64(&salt[7], PHP_CRYPT_RAND, 4); | ||
| 110 | strcpy(&salt[11], "$"); | ||
| 111 | } else { | ||
| 112 | php_to64(&salt[0], PHP_CRYPT_RAND, 2); | ||
| 113 | salt[2] = '\0'; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | if (salt[0] == '$' && | ||
| 118 | salt[1] == '2' && | ||
| 119 | salt[2] == 'a' && | ||
| 120 | salt[3] == '$' && | ||
| 121 | salt[4] >= '0' && salt[4] <= '3' && | ||
| 122 | salt[5] >= '0' && salt[5] <= '9' && | ||
| 123 | salt[6] == '$') { | ||
| 124 | |||
| 125 | char output[BLOWFISH_SALT_LEN+1]; | ||
| 126 | |||
| 127 | output[0] = 0; | ||
| 128 | suhosin_crypt_blowfish_rn(str, salt, output, sizeof(output)); | ||
| 129 | RETVAL_STRING(output, 1); | ||
| 130 | |||
| 131 | } else { | ||
| 132 | #ifdef ZTS | ||
| 133 | tsrm_mutex_lock(suhosin_crypt_mutex); | ||
| 134 | #endif | ||
| 135 | RETVAL_STRING(crypt(str, salt), 1); | ||
| 136 | #ifdef ZTS | ||
| 137 | tsrm_mutex_unlock(suhosin_crypt_mutex); | ||
| 138 | #endif | ||
| 139 | } | ||
| 140 | } | ||
| 141 | /* }}} */ | ||
| 142 | |||
| 143 | |||
| 144 | /* {{{ suhosin_crypt_functions[] | ||
| 145 | */ | ||
| 146 | static function_entry suhosin_crypt_functions[] = { | ||
| 147 | PHP_NAMED_FE(crypt, PHP_FN(suhosin_crypt), NULL) | ||
| 148 | {NULL, NULL, NULL} | ||
| 149 | }; | ||
| 150 | /* }}} */ | ||
| 151 | |||
| 152 | |||
| 153 | void suhosin_hook_crypt() | ||
| 154 | { | ||
| 155 | zend_constant *c; | ||
| 156 | TSRMLS_FETCH(); | ||
| 157 | |||
| 158 | /* check if we have MD5 support */ | ||
| 159 | if (zend_hash_find(EG(zend_constants), "CRYPT_MD5", sizeof("CRYPT_MD5"), (void **) &c) == SUCCESS) { | ||
| 160 | if (c->value.type == IS_LONG && c->value.value.lval > 0) { | ||
| 161 | CRYPT_MD5 = 1; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /* check if we already have blowfish support */ | ||
| 166 | if (zend_hash_find(EG(zend_constants), "CRYPT_BLOWFISH", sizeof("CRYPT_BLOWFISH"), (void **) &c) == FAILURE) { | ||
| 167 | |||
| 168 | /* should we just bailout when this constant is not known at all? */ | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (c->value.type == IS_LONG && c->value.value.lval > 0) { | ||
| 173 | |||
| 174 | /* blowfish support already installed */ | ||
| 175 | return; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* mark blowfish as supported */ | ||
| 179 | c->value.type = IS_LONG; | ||
| 180 | c->value.value.lval = 1; | ||
| 181 | |||
| 182 | /* now fix the CRYPT_SALT_LENGTH constant */ | ||
| 183 | if (zend_hash_find(EG(zend_constants), "CRYPT_SALT_LENGTH", sizeof("CRYPT_SALT_LENGTH"), (void **) &c) == SUCCESS) { | ||
| 184 | c->value.type = IS_LONG; | ||
| 185 | c->value.value.lval = BLOWFISH_SALT_LEN; | ||
| 186 | } | ||
| 187 | #ifdef ZTS | ||
| 188 | suhosin_crypt_mutex = tsrm_mutex_alloc(); | ||
| 189 | #endif | ||
| 190 | |||
| 191 | /* replace the crypt() function */ | ||
| 192 | zend_hash_del(CG(function_table), "crypt", sizeof("crypt")); | ||
| 193 | #ifndef ZEND_ENGINE_2 | ||
| 194 | zend_register_functions(suhosin_crypt_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); | ||
| 195 | #else | ||
| 196 | zend_register_functions(NULL, suhosin_crypt_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); | ||
| 197 | #endif | ||
| 198 | |||
| 199 | |||
| 200 | |||
| 201 | |||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | /* | ||
| 206 | * Local variables: | ||
| 207 | * tab-width: 4 | ||
| 208 | * c-basic-offset: 4 | ||
| 209 | * End: | ||
| 210 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 211 | * vim<600: noet sw=4 ts=4 | ||
| 212 | */ | ||
| 213 | |||
| 214 | |||
diff --git a/crypt_blowfish.c b/crypt_blowfish.c new file mode 100644 index 0000000..cdc3ac5 --- /dev/null +++ b/crypt_blowfish.c | |||
| @@ -0,0 +1,751 @@ | |||
| 1 | /* | ||
| 2 | $Id: crypt_blowfish.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 3 | */ | ||
| 4 | /* | ||
| 5 | * This code comes from John the Ripper password cracker, with reentrant | ||
| 6 | * and crypt(3) interfaces added, but optimizations specific to password | ||
| 7 | * cracking removed. | ||
| 8 | * | ||
| 9 | * Written by Solar Designer <solar at openwall.com> in 1998-2002 and | ||
| 10 | * placed in the public domain. | ||
| 11 | * | ||
| 12 | * There's absolutely no warranty. | ||
| 13 | * | ||
| 14 | * It is my intent that you should be able to use this on your system, | ||
| 15 | * as a part of a software package, or anywhere else to improve security, | ||
| 16 | * ensure compatibility, or for any other purpose. I would appreciate | ||
| 17 | * it if you give credit where it is due and keep your modifications in | ||
| 18 | * the public domain as well, but I don't require that in order to let | ||
| 19 | * you place this code and any modifications you make under a license | ||
| 20 | * of your choice. | ||
| 21 | * | ||
| 22 | * This implementation is compatible with OpenBSD bcrypt.c (version 2a) | ||
| 23 | * by Niels Provos <provos at citi.umich.edu>, and uses some of his | ||
| 24 | * ideas. The password hashing algorithm was designed by David Mazieres | ||
| 25 | * <dm at lcs.mit.edu>. | ||
| 26 | * | ||
| 27 | * There's a paper on the algorithm that explains its design decisions: | ||
| 28 | * | ||
| 29 | * http://www.usenix.org/events/usenix99/provos.html | ||
| 30 | * | ||
| 31 | * Some of the tricks in BF_ROUND might be inspired by Eric Young's | ||
| 32 | * Blowfish library (I can't be sure if I would think of something if I | ||
| 33 | * hadn't seen his code). | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include <string.h> | ||
| 37 | |||
| 38 | #include <errno.h> | ||
| 39 | #ifndef __set_errno | ||
| 40 | #define __set_errno(val) errno = (val) | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #undef __CONST | ||
| 44 | #ifdef __GNUC__ | ||
| 45 | #define __CONST __const | ||
| 46 | #else | ||
| 47 | #define __CONST | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #ifdef __i386__ | ||
| 51 | #define BF_ASM 0 | ||
| 52 | #define BF_SCALE 1 | ||
| 53 | #elif defined(__alpha__) || defined(__hppa__) | ||
| 54 | #define BF_ASM 0 | ||
| 55 | #define BF_SCALE 1 | ||
| 56 | #else | ||
| 57 | #define BF_ASM 0 | ||
| 58 | #define BF_SCALE 0 | ||
| 59 | #endif | ||
| 60 | |||
| 61 | typedef unsigned int BF_word; | ||
| 62 | |||
| 63 | /* Number of Blowfish rounds, this is also hardcoded into a few places */ | ||
| 64 | #define BF_N 16 | ||
| 65 | |||
| 66 | typedef BF_word BF_key[BF_N + 2]; | ||
| 67 | |||
| 68 | typedef struct { | ||
| 69 | BF_word S[4][0x100]; | ||
| 70 | BF_key P; | ||
| 71 | } BF_ctx; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Magic IV for 64 Blowfish encryptions that we do at the end. | ||
| 75 | * The string is "OrpheanBeholderScryDoubt" on big-endian. | ||
| 76 | */ | ||
| 77 | static BF_word BF_magic_w[6] = { | ||
| 78 | 0x4F727068, 0x65616E42, 0x65686F6C, | ||
| 79 | 0x64657253, 0x63727944, 0x6F756274 | ||
| 80 | }; | ||
| 81 | |||
| 82 | /* | ||
| 83 | * P-box and S-box tables initialized with digits of Pi. | ||
| 84 | */ | ||
| 85 | static BF_ctx BF_init_state = { | ||
| 86 | { | ||
| 87 | { | ||
| 88 | 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, | ||
| 89 | 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, | ||
| 90 | 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, | ||
| 91 | 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, | ||
| 92 | 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, | ||
| 93 | 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, | ||
| 94 | 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, | ||
| 95 | 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, | ||
| 96 | 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, | ||
| 97 | 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, | ||
| 98 | 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, | ||
| 99 | 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, | ||
| 100 | 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, | ||
| 101 | 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, | ||
| 102 | 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, | ||
| 103 | 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, | ||
| 104 | 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, | ||
| 105 | 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, | ||
| 106 | 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, | ||
| 107 | 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, | ||
| 108 | 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, | ||
| 109 | 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, | ||
| 110 | 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, | ||
| 111 | 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, | ||
| 112 | 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, | ||
| 113 | 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, | ||
| 114 | 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, | ||
| 115 | 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, | ||
| 116 | 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, | ||
| 117 | 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, | ||
| 118 | 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, | ||
| 119 | 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, | ||
| 120 | 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, | ||
| 121 | 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, | ||
| 122 | 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, | ||
| 123 | 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, | ||
| 124 | 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, | ||
| 125 | 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, | ||
| 126 | 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, | ||
| 127 | 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, | ||
| 128 | 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, | ||
| 129 | 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, | ||
| 130 | 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, | ||
| 131 | 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, | ||
| 132 | 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, | ||
| 133 | 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, | ||
| 134 | 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, | ||
| 135 | 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, | ||
| 136 | 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, | ||
| 137 | 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, | ||
| 138 | 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, | ||
| 139 | 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, | ||
| 140 | 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, | ||
| 141 | 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, | ||
| 142 | 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, | ||
| 143 | 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, | ||
| 144 | 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, | ||
| 145 | 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, | ||
| 146 | 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, | ||
| 147 | 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, | ||
| 148 | 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, | ||
| 149 | 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, | ||
| 150 | 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, | ||
| 151 | 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a | ||
| 152 | }, { | ||
| 153 | 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, | ||
| 154 | 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, | ||
| 155 | 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, | ||
| 156 | 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, | ||
| 157 | 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, | ||
| 158 | 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, | ||
| 159 | 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, | ||
| 160 | 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, | ||
| 161 | 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, | ||
| 162 | 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, | ||
| 163 | 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, | ||
| 164 | 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, | ||
| 165 | 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, | ||
| 166 | 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, | ||
| 167 | 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, | ||
| 168 | 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, | ||
| 169 | 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, | ||
| 170 | 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, | ||
| 171 | 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, | ||
| 172 | 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, | ||
| 173 | 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, | ||
| 174 | 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, | ||
| 175 | 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, | ||
| 176 | 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, | ||
| 177 | 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, | ||
| 178 | 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, | ||
| 179 | 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, | ||
| 180 | 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, | ||
| 181 | 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, | ||
| 182 | 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, | ||
| 183 | 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, | ||
| 184 | 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, | ||
| 185 | 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, | ||
| 186 | 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, | ||
| 187 | 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, | ||
| 188 | 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, | ||
| 189 | 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, | ||
| 190 | 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, | ||
| 191 | 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, | ||
| 192 | 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, | ||
| 193 | 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, | ||
| 194 | 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, | ||
| 195 | 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, | ||
| 196 | 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, | ||
| 197 | 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, | ||
| 198 | 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, | ||
| 199 | 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, | ||
| 200 | 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, | ||
| 201 | 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, | ||
| 202 | 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, | ||
| 203 | 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, | ||
| 204 | 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, | ||
| 205 | 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, | ||
| 206 | 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, | ||
| 207 | 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, | ||
| 208 | 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, | ||
| 209 | 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, | ||
| 210 | 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, | ||
| 211 | 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, | ||
| 212 | 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, | ||
| 213 | 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, | ||
| 214 | 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, | ||
| 215 | 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, | ||
| 216 | 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 | ||
| 217 | }, { | ||
| 218 | 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, | ||
| 219 | 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, | ||
| 220 | 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, | ||
| 221 | 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, | ||
| 222 | 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, | ||
| 223 | 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, | ||
| 224 | 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, | ||
| 225 | 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, | ||
| 226 | 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, | ||
| 227 | 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, | ||
| 228 | 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, | ||
| 229 | 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, | ||
| 230 | 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, | ||
| 231 | 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, | ||
| 232 | 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, | ||
| 233 | 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, | ||
| 234 | 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, | ||
| 235 | 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, | ||
| 236 | 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, | ||
| 237 | 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, | ||
| 238 | 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, | ||
| 239 | 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, | ||
| 240 | 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, | ||
| 241 | 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, | ||
| 242 | 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, | ||
| 243 | 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, | ||
| 244 | 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, | ||
| 245 | 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, | ||
| 246 | 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, | ||
| 247 | 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, | ||
| 248 | 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, | ||
| 249 | 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, | ||
| 250 | 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, | ||
| 251 | 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, | ||
| 252 | 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, | ||
| 253 | 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, | ||
| 254 | 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, | ||
| 255 | 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, | ||
| 256 | 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, | ||
| 257 | 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, | ||
| 258 | 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, | ||
| 259 | 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, | ||
| 260 | 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, | ||
| 261 | 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, | ||
| 262 | 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, | ||
| 263 | 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, | ||
| 264 | 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, | ||
| 265 | 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, | ||
| 266 | 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, | ||
| 267 | 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, | ||
| 268 | 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, | ||
| 269 | 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, | ||
| 270 | 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, | ||
| 271 | 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, | ||
| 272 | 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, | ||
| 273 | 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, | ||
| 274 | 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, | ||
| 275 | 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, | ||
| 276 | 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, | ||
| 277 | 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, | ||
| 278 | 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, | ||
| 279 | 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, | ||
| 280 | 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, | ||
| 281 | 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 | ||
| 282 | }, { | ||
| 283 | 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, | ||
| 284 | 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, | ||
| 285 | 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, | ||
| 286 | 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, | ||
| 287 | 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, | ||
| 288 | 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, | ||
| 289 | 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, | ||
| 290 | 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, | ||
| 291 | 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, | ||
| 292 | 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, | ||
| 293 | 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, | ||
| 294 | 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, | ||
| 295 | 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, | ||
| 296 | 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, | ||
| 297 | 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, | ||
| 298 | 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, | ||
| 299 | 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, | ||
| 300 | 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, | ||
| 301 | 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, | ||
| 302 | 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, | ||
| 303 | 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, | ||
| 304 | 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, | ||
| 305 | 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, | ||
| 306 | 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, | ||
| 307 | 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, | ||
| 308 | 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, | ||
| 309 | 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, | ||
| 310 | 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, | ||
| 311 | 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, | ||
| 312 | 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, | ||
| 313 | 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, | ||
| 314 | 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, | ||
| 315 | 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, | ||
| 316 | 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, | ||
| 317 | 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, | ||
| 318 | 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, | ||
| 319 | 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, | ||
| 320 | 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, | ||
| 321 | 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, | ||
| 322 | 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, | ||
| 323 | 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, | ||
| 324 | 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, | ||
| 325 | 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, | ||
| 326 | 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, | ||
| 327 | 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, | ||
| 328 | 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, | ||
| 329 | 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, | ||
| 330 | 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, | ||
| 331 | 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, | ||
| 332 | 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, | ||
| 333 | 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, | ||
| 334 | 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, | ||
| 335 | 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, | ||
| 336 | 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, | ||
| 337 | 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, | ||
| 338 | 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, | ||
| 339 | 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, | ||
| 340 | 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, | ||
| 341 | 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, | ||
| 342 | 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, | ||
| 343 | 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, | ||
| 344 | 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, | ||
| 345 | 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, | ||
| 346 | 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 | ||
| 347 | } | ||
| 348 | }, { | ||
| 349 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, | ||
| 350 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, | ||
| 351 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, | ||
| 352 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, | ||
| 353 | 0x9216d5d9, 0x8979fb1b | ||
| 354 | } | ||
| 355 | }; | ||
| 356 | |||
| 357 | static unsigned char BF_itoa64[64 + 1] = | ||
| 358 | "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||
| 359 | |||
| 360 | static unsigned char BF_atoi64[0x60] = { | ||
| 361 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, | ||
| 362 | 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, | ||
| 363 | 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, | ||
| 364 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64, | ||
| 365 | 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, | ||
| 366 | 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64 | ||
| 367 | }; | ||
| 368 | |||
| 369 | /* | ||
| 370 | * This may be optimized out if built with function inlining and no BF_ASM. | ||
| 371 | */ | ||
| 372 | static void clean(void *data, int size) | ||
| 373 | { | ||
| 374 | #if BF_ASM | ||
| 375 | extern void _BF_clean(void *data); | ||
| 376 | #endif | ||
| 377 | memset(data, 0, size); | ||
| 378 | #if BF_ASM | ||
| 379 | _BF_clean(data); | ||
| 380 | #endif | ||
| 381 | } | ||
| 382 | |||
| 383 | #define BF_safe_atoi64(dst, src) \ | ||
| 384 | { \ | ||
| 385 | tmp = (unsigned char)(src); \ | ||
| 386 | if (tmp == '$') break; \ | ||
| 387 | if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ | ||
| 388 | tmp = BF_atoi64[tmp]; \ | ||
| 389 | if (tmp > 63) return -1; \ | ||
| 390 | (dst) = tmp; \ | ||
| 391 | } | ||
| 392 | |||
| 393 | static int BF_decode(BF_word *dst, __CONST char *src, int size) | ||
| 394 | { | ||
| 395 | unsigned char *dptr = (unsigned char *)dst; | ||
| 396 | unsigned char *end = dptr + size; | ||
| 397 | unsigned char *sptr = (unsigned char *)src; | ||
| 398 | unsigned int tmp, c1, c2, c3, c4; | ||
| 399 | |||
| 400 | do { | ||
| 401 | BF_safe_atoi64(c1, *sptr++); | ||
| 402 | BF_safe_atoi64(c2, *sptr++); | ||
| 403 | *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); | ||
| 404 | if (dptr >= end) break; | ||
| 405 | |||
| 406 | BF_safe_atoi64(c3, *sptr++); | ||
| 407 | *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); | ||
| 408 | if (dptr >= end) break; | ||
| 409 | |||
| 410 | BF_safe_atoi64(c4, *sptr++); | ||
| 411 | *dptr++ = ((c3 & 0x03) << 6) | c4; | ||
| 412 | } while (dptr < end); | ||
| 413 | |||
| 414 | while (dptr < end) | ||
| 415 | *dptr++ = 0; | ||
| 416 | |||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | |||
| 420 | static void BF_encode(char *dst, __CONST BF_word *src, int size) | ||
| 421 | { | ||
| 422 | unsigned char *sptr = (unsigned char *)src; | ||
| 423 | unsigned char *end = sptr + size; | ||
| 424 | unsigned char *dptr = (unsigned char *)dst; | ||
| 425 | unsigned int c1, c2; | ||
| 426 | |||
| 427 | do { | ||
| 428 | c1 = *sptr++; | ||
| 429 | *dptr++ = BF_itoa64[c1 >> 2]; | ||
| 430 | c1 = (c1 & 0x03) << 4; | ||
| 431 | if (sptr >= end) { | ||
| 432 | *dptr++ = BF_itoa64[c1]; | ||
| 433 | break; | ||
| 434 | } | ||
| 435 | |||
| 436 | c2 = *sptr++; | ||
| 437 | c1 |= c2 >> 4; | ||
| 438 | *dptr++ = BF_itoa64[c1]; | ||
| 439 | c1 = (c2 & 0x0f) << 2; | ||
| 440 | if (sptr >= end) { | ||
| 441 | *dptr++ = BF_itoa64[c1]; | ||
| 442 | break; | ||
| 443 | } | ||
| 444 | |||
| 445 | c2 = *sptr++; | ||
| 446 | c1 |= c2 >> 6; | ||
| 447 | *dptr++ = BF_itoa64[c1]; | ||
| 448 | *dptr++ = BF_itoa64[c2 & 0x3f]; | ||
| 449 | } while (sptr < end); | ||
| 450 | } | ||
| 451 | |||
| 452 | static void BF_swap(BF_word *x, int count) | ||
| 453 | { | ||
| 454 | static int endianness_check = 1; | ||
| 455 | char *is_little_endian = (char *)&endianness_check; | ||
| 456 | BF_word tmp; | ||
| 457 | |||
| 458 | if (*is_little_endian) | ||
| 459 | do { | ||
| 460 | tmp = *x; | ||
| 461 | tmp = (tmp << 16) | (tmp >> 16); | ||
| 462 | *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); | ||
| 463 | } while (--count); | ||
| 464 | } | ||
| 465 | |||
| 466 | #if BF_SCALE | ||
| 467 | /* Architectures which can shift addresses left by 2 bits with no extra cost */ | ||
| 468 | #define BF_ROUND(L, R, N) \ | ||
| 469 | tmp1 = L & 0xFF; \ | ||
| 470 | tmp2 = L >> 8; \ | ||
| 471 | tmp2 &= 0xFF; \ | ||
| 472 | tmp3 = L >> 16; \ | ||
| 473 | tmp3 &= 0xFF; \ | ||
| 474 | tmp4 = L >> 24; \ | ||
| 475 | tmp1 = data.ctx.S[3][tmp1]; \ | ||
| 476 | tmp2 = data.ctx.S[2][tmp2]; \ | ||
| 477 | tmp3 = data.ctx.S[1][tmp3]; \ | ||
| 478 | tmp3 += data.ctx.S[0][tmp4]; \ | ||
| 479 | tmp3 ^= tmp2; \ | ||
| 480 | R ^= data.ctx.P[N + 1]; \ | ||
| 481 | tmp3 += tmp1; \ | ||
| 482 | R ^= tmp3; | ||
| 483 | #else | ||
| 484 | /* Architectures with no complicated addressing modes supported */ | ||
| 485 | #define BF_INDEX(S, i) \ | ||
| 486 | (*((BF_word *)(((unsigned char *)S) + (i)))) | ||
| 487 | #define BF_ROUND(L, R, N) \ | ||
| 488 | tmp1 = L & 0xFF; \ | ||
| 489 | tmp1 <<= 2; \ | ||
| 490 | tmp2 = L >> 6; \ | ||
| 491 | tmp2 &= 0x3FC; \ | ||
| 492 | tmp3 = L >> 14; \ | ||
| 493 | tmp3 &= 0x3FC; \ | ||
| 494 | tmp4 = L >> 22; \ | ||
| 495 | tmp4 &= 0x3FC; \ | ||
| 496 | tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \ | ||
| 497 | tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \ | ||
| 498 | tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \ | ||
| 499 | tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \ | ||
| 500 | tmp3 ^= tmp2; \ | ||
| 501 | R ^= data.ctx.P[N + 1]; \ | ||
| 502 | tmp3 += tmp1; \ | ||
| 503 | R ^= tmp3; | ||
| 504 | #endif | ||
| 505 | |||
| 506 | /* | ||
| 507 | * Encrypt one block, BF_N is hardcoded here. | ||
| 508 | */ | ||
| 509 | #define BF_ENCRYPT \ | ||
| 510 | L ^= data.ctx.P[0]; \ | ||
| 511 | BF_ROUND(L, R, 0); \ | ||
| 512 | BF_ROUND(R, L, 1); \ | ||
| 513 | BF_ROUND(L, R, 2); \ | ||
| 514 | BF_ROUND(R, L, 3); \ | ||
| 515 | BF_ROUND(L, R, 4); \ | ||
| 516 | BF_ROUND(R, L, 5); \ | ||
| 517 | BF_ROUND(L, R, 6); \ | ||
| 518 | BF_ROUND(R, L, 7); \ | ||
| 519 | BF_ROUND(L, R, 8); \ | ||
| 520 | BF_ROUND(R, L, 9); \ | ||
| 521 | BF_ROUND(L, R, 10); \ | ||
| 522 | BF_ROUND(R, L, 11); \ | ||
| 523 | BF_ROUND(L, R, 12); \ | ||
| 524 | BF_ROUND(R, L, 13); \ | ||
| 525 | BF_ROUND(L, R, 14); \ | ||
| 526 | BF_ROUND(R, L, 15); \ | ||
| 527 | tmp4 = R; \ | ||
| 528 | R = L; \ | ||
| 529 | L = tmp4 ^ data.ctx.P[BF_N + 1]; | ||
| 530 | |||
| 531 | #if BF_ASM | ||
| 532 | #define BF_body() \ | ||
| 533 | _BF_body_r(&data.ctx); | ||
| 534 | #else | ||
| 535 | #define BF_body() \ | ||
| 536 | L = R = 0; \ | ||
| 537 | ptr = data.ctx.P; \ | ||
| 538 | do { \ | ||
| 539 | ptr += 2; \ | ||
| 540 | BF_ENCRYPT; \ | ||
| 541 | *(ptr - 2) = L; \ | ||
| 542 | *(ptr - 1) = R; \ | ||
| 543 | } while (ptr < &data.ctx.P[BF_N + 2]); \ | ||
| 544 | \ | ||
| 545 | ptr = data.ctx.S[0]; \ | ||
| 546 | do { \ | ||
| 547 | ptr += 2; \ | ||
| 548 | BF_ENCRYPT; \ | ||
| 549 | *(ptr - 2) = L; \ | ||
| 550 | *(ptr - 1) = R; \ | ||
| 551 | } while (ptr < &data.ctx.S[3][0xFF]); | ||
| 552 | #endif | ||
| 553 | |||
| 554 | static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial) | ||
| 555 | { | ||
| 556 | __CONST char *ptr = key; | ||
| 557 | int i, j; | ||
| 558 | BF_word tmp; | ||
| 559 | |||
| 560 | for (i = 0; i < BF_N + 2; i++) { | ||
| 561 | tmp = 0; | ||
| 562 | for (j = 0; j < 4; j++) { | ||
| 563 | tmp <<= 8; | ||
| 564 | tmp |= *ptr; | ||
| 565 | |||
| 566 | if (!*ptr) ptr = key; else ptr++; | ||
| 567 | } | ||
| 568 | |||
| 569 | expanded[i] = tmp; | ||
| 570 | initial[i] = BF_init_state.P[i] ^ tmp; | ||
| 571 | } | ||
| 572 | } | ||
| 573 | |||
| 574 | char *suhosin_crypt_blowfish_rn(__CONST char *key, __CONST char *setting, | ||
| 575 | char *output, int size) | ||
| 576 | { | ||
| 577 | #if BF_ASM | ||
| 578 | extern void _BF_body_r(BF_ctx *ctx); | ||
| 579 | #endif | ||
| 580 | struct { | ||
| 581 | BF_ctx ctx; | ||
| 582 | BF_key expanded_key; | ||
| 583 | union { | ||
| 584 | BF_word salt[4]; | ||
| 585 | BF_word output[6]; | ||
| 586 | } binary; | ||
| 587 | } data; | ||
| 588 | BF_word L, R; | ||
| 589 | BF_word tmp1, tmp2, tmp3, tmp4; | ||
| 590 | BF_word *ptr; | ||
| 591 | BF_word count; | ||
| 592 | int i; | ||
| 593 | |||
| 594 | if (size < 7 + 22 + 31 + 1) { | ||
| 595 | __set_errno(ERANGE); | ||
| 596 | return NULL; | ||
| 597 | } | ||
| 598 | |||
| 599 | if (setting[0] != '$' || | ||
| 600 | setting[1] != '2' || | ||
| 601 | setting[2] != 'a' || | ||
| 602 | setting[3] != '$' || | ||
| 603 | setting[4] < '0' || setting[4] > '3' || | ||
| 604 | setting[5] < '0' || setting[5] > '9' || | ||
| 605 | setting[6] != '$') { | ||
| 606 | __set_errno(EINVAL); | ||
| 607 | return NULL; | ||
| 608 | } | ||
| 609 | |||
| 610 | count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0')); | ||
| 611 | if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) { | ||
| 612 | clean(data.binary.salt, sizeof(data.binary.salt)); | ||
| 613 | __set_errno(EINVAL); | ||
| 614 | return NULL; | ||
| 615 | } | ||
| 616 | |||
| 617 | BF_swap(data.binary.salt, 4); | ||
| 618 | |||
| 619 | BF_set_key(key, data.expanded_key, data.ctx.P); | ||
| 620 | |||
| 621 | memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S)); | ||
| 622 | |||
| 623 | L = R = 0; | ||
| 624 | for (i = 0; i < BF_N + 2; i += 2) { | ||
| 625 | L ^= data.binary.salt[i & 2]; | ||
| 626 | R ^= data.binary.salt[(i & 2) + 1]; | ||
| 627 | BF_ENCRYPT; | ||
| 628 | data.ctx.P[i] = L; | ||
| 629 | data.ctx.P[i + 1] = R; | ||
| 630 | } | ||
| 631 | |||
| 632 | ptr = data.ctx.S[0]; | ||
| 633 | do { | ||
| 634 | ptr += 4; | ||
| 635 | L ^= data.binary.salt[(BF_N + 2) & 3]; | ||
| 636 | R ^= data.binary.salt[(BF_N + 3) & 3]; | ||
| 637 | BF_ENCRYPT; | ||
| 638 | *(ptr - 4) = L; | ||
| 639 | *(ptr - 3) = R; | ||
| 640 | |||
| 641 | L ^= data.binary.salt[(BF_N + 4) & 3]; | ||
| 642 | R ^= data.binary.salt[(BF_N + 5) & 3]; | ||
| 643 | BF_ENCRYPT; | ||
| 644 | *(ptr - 2) = L; | ||
| 645 | *(ptr - 1) = R; | ||
| 646 | } while (ptr < &data.ctx.S[3][0xFF]); | ||
| 647 | |||
| 648 | do { | ||
| 649 | data.ctx.P[0] ^= data.expanded_key[0]; | ||
| 650 | data.ctx.P[1] ^= data.expanded_key[1]; | ||
| 651 | data.ctx.P[2] ^= data.expanded_key[2]; | ||
| 652 | data.ctx.P[3] ^= data.expanded_key[3]; | ||
| 653 | data.ctx.P[4] ^= data.expanded_key[4]; | ||
| 654 | data.ctx.P[5] ^= data.expanded_key[5]; | ||
| 655 | data.ctx.P[6] ^= data.expanded_key[6]; | ||
| 656 | data.ctx.P[7] ^= data.expanded_key[7]; | ||
| 657 | data.ctx.P[8] ^= data.expanded_key[8]; | ||
| 658 | data.ctx.P[9] ^= data.expanded_key[9]; | ||
| 659 | data.ctx.P[10] ^= data.expanded_key[10]; | ||
| 660 | data.ctx.P[11] ^= data.expanded_key[11]; | ||
| 661 | data.ctx.P[12] ^= data.expanded_key[12]; | ||
| 662 | data.ctx.P[13] ^= data.expanded_key[13]; | ||
| 663 | data.ctx.P[14] ^= data.expanded_key[14]; | ||
| 664 | data.ctx.P[15] ^= data.expanded_key[15]; | ||
| 665 | data.ctx.P[16] ^= data.expanded_key[16]; | ||
| 666 | data.ctx.P[17] ^= data.expanded_key[17]; | ||
| 667 | |||
| 668 | BF_body(); | ||
| 669 | |||
| 670 | tmp1 = data.binary.salt[0]; | ||
| 671 | tmp2 = data.binary.salt[1]; | ||
| 672 | tmp3 = data.binary.salt[2]; | ||
| 673 | tmp4 = data.binary.salt[3]; | ||
| 674 | data.ctx.P[0] ^= tmp1; | ||
| 675 | data.ctx.P[1] ^= tmp2; | ||
| 676 | data.ctx.P[2] ^= tmp3; | ||
| 677 | data.ctx.P[3] ^= tmp4; | ||
| 678 | data.ctx.P[4] ^= tmp1; | ||
| 679 | data.ctx.P[5] ^= tmp2; | ||
| 680 | data.ctx.P[6] ^= tmp3; | ||
| 681 | data.ctx.P[7] ^= tmp4; | ||
| 682 | data.ctx.P[8] ^= tmp1; | ||
| 683 | data.ctx.P[9] ^= tmp2; | ||
| 684 | data.ctx.P[10] ^= tmp3; | ||
| 685 | data.ctx.P[11] ^= tmp4; | ||
| 686 | data.ctx.P[12] ^= tmp1; | ||
| 687 | data.ctx.P[13] ^= tmp2; | ||
| 688 | data.ctx.P[14] ^= tmp3; | ||
| 689 | data.ctx.P[15] ^= tmp4; | ||
| 690 | data.ctx.P[16] ^= tmp1; | ||
| 691 | data.ctx.P[17] ^= tmp2; | ||
| 692 | |||
| 693 | BF_body(); | ||
| 694 | } while (--count); | ||
| 695 | |||
| 696 | for (i = 0; i < 6; i += 2) { | ||
| 697 | L = BF_magic_w[i]; | ||
| 698 | R = BF_magic_w[i + 1]; | ||
| 699 | |||
| 700 | count = 64; | ||
| 701 | do { | ||
| 702 | BF_ENCRYPT; | ||
| 703 | } while (--count); | ||
| 704 | |||
| 705 | data.binary.output[i] = L; | ||
| 706 | data.binary.output[i + 1] = R; | ||
| 707 | } | ||
| 708 | |||
| 709 | memcpy(output, setting, 7 + 22 - 1); | ||
| 710 | output[7 + 22 - 1] = BF_itoa64[(int) | ||
| 711 | BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30]; | ||
| 712 | |||
| 713 | /* This has to be bug-compatible with the original implementation, so | ||
| 714 | * only encode 23 of the 24 bytes. :-) */ | ||
| 715 | BF_swap(data.binary.output, 6); | ||
| 716 | BF_encode(&output[7 + 22], data.binary.output, 23); | ||
| 717 | output[7 + 22 + 31] = '\0'; | ||
| 718 | |||
| 719 | /* Overwrite the most obvious sensitive data we have on the stack. Note | ||
| 720 | * that this does not guarantee there's no sensitive data left on the | ||
| 721 | * stack and/or in registers; I'm not aware of portable code that does. */ | ||
| 722 | clean(&data, sizeof(data)); | ||
| 723 | |||
| 724 | return output; | ||
| 725 | } | ||
| 726 | |||
| 727 | char *suhosin_crypt_gensalt_blowfish_rn(unsigned long count, | ||
| 728 | __CONST char *input, int size, char *output, int output_size) | ||
| 729 | { | ||
| 730 | if (size < 16 || output_size < 7 + 22 + 1 || | ||
| 731 | (count && (count < 4 || count > 31))) { | ||
| 732 | if (output_size > 0) output[0] = '\0'; | ||
| 733 | __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); | ||
| 734 | return NULL; | ||
| 735 | } | ||
| 736 | |||
| 737 | if (!count) count = 5; | ||
| 738 | |||
| 739 | output[0] = '$'; | ||
| 740 | output[1] = '2'; | ||
| 741 | output[2] = 'a'; | ||
| 742 | output[3] = '$'; | ||
| 743 | output[4] = '0' + count / 10; | ||
| 744 | output[5] = '0' + count % 10; | ||
| 745 | output[6] = '$'; | ||
| 746 | |||
| 747 | BF_encode(&output[7], (BF_word *)input, 16); | ||
| 748 | output[7 + 22] = '\0'; | ||
| 749 | |||
| 750 | return output; | ||
| 751 | } | ||
diff --git a/crypt_md5.c b/crypt_md5.c new file mode 100644 index 0000000..14aeb79 --- /dev/null +++ b/crypt_md5.c | |||
| @@ -0,0 +1,163 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | PHP Version 5 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 1997-2006 The PHP Group | | ||
| 6 | +----------------------------------------------------------------------+ | ||
| 7 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 8 | | that is bundled with this package in the file LICENSE, and is | | ||
| 9 | | available through the world-wide-web at the following url: | | ||
| 10 | | http://www.php.net/license/3_01.txt | | ||
| 11 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 12 | | obtain it through the world-wide-web, please send a note to | | ||
| 13 | | license@php.net so we can mail you a copy immediately. | | ||
| 14 | +----------------------------------------------------------------------+ | ||
| 15 | | Author: Edin Kadribasic | | ||
| 16 | +----------------------------------------------------------------------+ | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* $Id: crypt_md5.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 20 | |||
| 21 | /* | ||
| 22 | * ---------------------------------------------------------------------------- | ||
| 23 | * "THE BEER-WARE LICENSE" (Revision 42): | ||
| 24 | * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you | ||
| 25 | * can do whatever you want with this stuff. If we meet some day, and you think | ||
| 26 | * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp | ||
| 27 | * ---------------------------------------------------------------------------- | ||
| 28 | * | ||
| 29 | * from FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp | ||
| 30 | * via OpenBSD: md5crypt.c,v 1.9 1997/07/23 20:58:27 kstailey Exp | ||
| 31 | * via NetBSD: md5crypt.c,v 1.4.2.1 2002/01/22 19:31:59 he Exp | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include "php.h" | ||
| 36 | #include "ext/standard/md5.h" | ||
| 37 | #include "crypt_md5.h" | ||
| 38 | |||
| 39 | static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ | ||
| 40 | "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | ||
| 41 | |||
| 42 | static void to64(char *, php_uint32, int); | ||
| 43 | |||
| 44 | static void | ||
| 45 | to64(char *s, php_uint32 v, int n) | ||
| 46 | { | ||
| 47 | |||
| 48 | while (--n >= 0) { | ||
| 49 | *s++ = itoa64[v & 0x3f]; | ||
| 50 | v >>= 6; | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 55 | * MD5 password encryption. | ||
| 56 | */ | ||
| 57 | char * | ||
| 58 | md5_crypt(const char *pw, const char *salt) | ||
| 59 | { | ||
| 60 | static char passwd[120], *p; | ||
| 61 | const char *sp, *ep; | ||
| 62 | unsigned char final[16]; | ||
| 63 | unsigned int i, sl, pwl; | ||
| 64 | PHP_MD5_CTX ctx, ctx1; | ||
| 65 | php_uint32 l; | ||
| 66 | int pl; | ||
| 67 | |||
| 68 | pwl = strlen(pw); | ||
| 69 | |||
| 70 | /* Refine the salt first */ | ||
| 71 | sp = salt; | ||
| 72 | |||
| 73 | /* If it starts with the magic string, then skip that */ | ||
| 74 | if (strncmp(sp, MD5_MAGIC, MD5_MAGIC_LEN) == 0) | ||
| 75 | sp += MD5_MAGIC_LEN; | ||
| 76 | |||
| 77 | /* It stops at the first '$', max 8 chars */ | ||
| 78 | for (ep = sp; *ep != '\0' && *ep != '$' && ep < (sp + 8); ep++) | ||
| 79 | continue; | ||
| 80 | |||
| 81 | /* get the length of the true salt */ | ||
| 82 | sl = ep - sp; | ||
| 83 | |||
| 84 | PHP_MD5Init(&ctx); | ||
| 85 | |||
| 86 | /* The password first, since that is what is most unknown */ | ||
| 87 | PHP_MD5Update(&ctx, (const unsigned char *)pw, pwl); | ||
| 88 | |||
| 89 | /* Then our magic string */ | ||
| 90 | PHP_MD5Update(&ctx, (const unsigned char *)MD5_MAGIC, MD5_MAGIC_LEN); | ||
| 91 | |||
| 92 | /* Then the raw salt */ | ||
| 93 | PHP_MD5Update(&ctx, (const unsigned char *)sp, sl); | ||
| 94 | |||
| 95 | /* Then just as many characters of the MD5(pw,salt,pw) */ | ||
| 96 | PHP_MD5Init(&ctx1); | ||
| 97 | PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl); | ||
| 98 | PHP_MD5Update(&ctx1, (const unsigned char *)sp, sl); | ||
| 99 | PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl); | ||
| 100 | PHP_MD5Final(final, &ctx1); | ||
| 101 | |||
| 102 | for (pl = pwl; pl > 0; pl -= 16) | ||
| 103 | PHP_MD5Update(&ctx, final, (unsigned int)(pl > 16 ? 16 : pl)); | ||
| 104 | |||
| 105 | /* Don't leave anything around in vm they could use. */ | ||
| 106 | memset(final, 0, sizeof(final)); | ||
| 107 | |||
| 108 | /* Then something really weird... */ | ||
| 109 | for (i = pwl; i != 0; i >>= 1) | ||
| 110 | if ((i & 1) != 0) | ||
| 111 | PHP_MD5Update(&ctx, final, 1); | ||
| 112 | else | ||
| 113 | PHP_MD5Update(&ctx, (const unsigned char *)pw, 1); | ||
| 114 | |||
| 115 | /* Now make the output string */ | ||
| 116 | memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN); | ||
| 117 | strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1); | ||
| 118 | strcat(passwd, "$"); | ||
| 119 | |||
| 120 | PHP_MD5Final(final, &ctx); | ||
| 121 | |||
| 122 | /* | ||
| 123 | * And now, just to make sure things don't run too fast. On a 60 MHz | ||
| 124 | * Pentium this takes 34 msec, so you would need 30 seconds to build | ||
| 125 | * a 1000 entry dictionary... | ||
| 126 | */ | ||
| 127 | for (i = 0; i < 1000; i++) { | ||
| 128 | PHP_MD5Init(&ctx1); | ||
| 129 | |||
| 130 | if ((i & 1) != 0) | ||
| 131 | PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl); | ||
| 132 | else | ||
| 133 | PHP_MD5Update(&ctx1, final, 16); | ||
| 134 | |||
| 135 | if ((i % 3) != 0) | ||
| 136 | PHP_MD5Update(&ctx1, (const unsigned char *)sp, sl); | ||
| 137 | |||
| 138 | if ((i % 7) != 0) | ||
| 139 | PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl); | ||
| 140 | |||
| 141 | if ((i & 1) != 0) | ||
| 142 | PHP_MD5Update(&ctx1, final, 16); | ||
| 143 | else | ||
| 144 | PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl); | ||
| 145 | |||
| 146 | PHP_MD5Final(final, &ctx1); | ||
| 147 | } | ||
| 148 | |||
| 149 | p = passwd + sl + MD5_MAGIC_LEN + 1; | ||
| 150 | |||
| 151 | l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; | ||
| 152 | l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; | ||
| 153 | l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; | ||
| 154 | l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; | ||
| 155 | l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; | ||
| 156 | l = final[11] ; to64(p,l,2); p += 2; | ||
| 157 | *p = '\0'; | ||
| 158 | |||
| 159 | /* Don't leave anything around in vm they could use. */ | ||
| 160 | memset(final, 0, sizeof(final)); | ||
| 161 | return (passwd); | ||
| 162 | } | ||
| 163 | |||
diff --git a/crypt_md5.h b/crypt_md5.h new file mode 100644 index 0000000..56f03a2 --- /dev/null +++ b/crypt_md5.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | PHP Version 5 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 1997-2006 The PHP Group | | ||
| 6 | +----------------------------------------------------------------------+ | ||
| 7 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 8 | | that is bundled with this package in the file LICENSE, and is | | ||
| 9 | | available through the world-wide-web at the following url: | | ||
| 10 | | http://www.php.net/license/3_01.txt | | ||
| 11 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 12 | | obtain it through the world-wide-web, please send a note to | | ||
| 13 | | license@php.net so we can mail you a copy immediately. | | ||
| 14 | +----------------------------------------------------------------------+ | ||
| 15 | | Author: Edin Kadribasic | | ||
| 16 | +----------------------------------------------------------------------+ | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* $Id: crypt_md5.h,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 20 | #ifndef _MD5CRYPT_H_ | ||
| 21 | #define _MD5CRYPT_H_ | ||
| 22 | |||
| 23 | #ifdef __cplusplus | ||
| 24 | extern "C" | ||
| 25 | { | ||
| 26 | #endif | ||
| 27 | |||
| 28 | #define MD5_MAGIC "$1$" | ||
| 29 | #define MD5_MAGIC_LEN 3 | ||
| 30 | |||
| 31 | char *md5_crypt(const char *pw, const char *salt); | ||
| 32 | |||
| 33 | #ifdef __cplusplus | ||
| 34 | } | ||
| 35 | #endif | ||
| 36 | |||
| 37 | #endif /* _MD5CRYPT_H_ */ \ No newline at end of file | ||
diff --git a/crypt_win32.c b/crypt_win32.c new file mode 100644 index 0000000..c1afe00 --- /dev/null +++ b/crypt_win32.c | |||
| @@ -0,0 +1,355 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | PHP Version 5 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 1997-2006 The PHP Group | | ||
| 6 | +----------------------------------------------------------------------+ | ||
| 7 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 8 | | that is bundled with this package in the file LICENSE, and is | | ||
| 9 | | available through the world-wide-web at the following url: | | ||
| 10 | | http://www.php.net/license/3_01.txt | | ||
| 11 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 12 | | obtain it through the world-wide-web, please send a note to | | ||
| 13 | | license@php.net so we can mail you a copy immediately. | | ||
| 14 | +----------------------------------------------------------------------+ | ||
| 15 | | Author: | | ||
| 16 | +----------------------------------------------------------------------+ | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* $Id: crypt_win32.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 20 | |||
| 21 | /* This code is distributed under the PHP license with permission from | ||
| 22 | the author Jochen Obalek <jochen.obalek@bigfoot.de> */ | ||
| 23 | |||
| 24 | /* encrypt.c - providing 56 bit DES encryption | ||
| 25 | Copyright (C) 1991 Jochen Obalek | ||
| 26 | |||
| 27 | This program is free software; you can redistribute it and/or modify | ||
| 28 | it under the terms of the GNU General Public License as published by | ||
| 29 | the Free Software Foundation; either version 2, or (at your option) | ||
| 30 | any later version. | ||
| 31 | |||
| 32 | This program is distributed in the hope that it will be useful, | ||
| 33 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 35 | GNU General Public License for more details. | ||
| 36 | |||
| 37 | You should have received a copy of the GNU General Public License | ||
| 38 | along with this program; if not, write to the Free Software | ||
| 39 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 40 | |||
| 41 | #include <time.h> | ||
| 42 | #include <string.h> | ||
| 43 | #include <stdlib.h> | ||
| 44 | #include "crypt_md5.h" | ||
| 45 | |||
| 46 | #define BS 64 | ||
| 47 | #define BS2 32 | ||
| 48 | #define KS 48 | ||
| 49 | #define KS2 24 | ||
| 50 | #define IS 56 | ||
| 51 | #define IS2 28 | ||
| 52 | |||
| 53 | static char schluessel[16][KS]; | ||
| 54 | |||
| 55 | |||
| 56 | static char PC1[] = | ||
| 57 | { | ||
| 58 | 56, 48, 40, 32, 24, 16, 8, 0, | ||
| 59 | 57, 49, 41, 33, 25, 17, 9, 1, | ||
| 60 | 58, 50, 42, 34, 26, 18, 10, 2, | ||
| 61 | 59, 51, 43, 35, | ||
| 62 | 62, 54, 46, 38, 30, 22, 14, 6, | ||
| 63 | 61, 53, 45, 37, 29, 21, 13, 5, | ||
| 64 | 60, 52, 44, 36, 28, 20, 12, 4, | ||
| 65 | 27, 19, 11, 3 | ||
| 66 | }; | ||
| 67 | |||
| 68 | |||
| 69 | static char PC2[] = | ||
| 70 | { | ||
| 71 | 13, 16, 10, 23, 0, 4, 2, 27, | ||
| 72 | 14, 5, 20, 9, 22, 18, 11, 3, | ||
| 73 | 25, 7, 15, 6, 26, 19, 12, 1, | ||
| 74 | 40, 51, 30, 36, 46, 54, 29, 39, | ||
| 75 | 50, 44, 32, 47, 43, 48, 38, 55, | ||
| 76 | 33, 52, 45, 41, 49, 35, 28, 31 | ||
| 77 | }; | ||
| 78 | |||
| 79 | |||
| 80 | static char IP[] = | ||
| 81 | { | ||
| 82 | 57, 49, 41, 33, 25, 17, 9, 1, | ||
| 83 | 59, 51, 43, 35, 27, 19, 11, 3, | ||
| 84 | 61, 53, 45, 37, 29, 21, 13, 5, | ||
| 85 | 63, 55, 47, 39, 31, 23, 15, 7, | ||
| 86 | 56, 48, 40, 32, 24, 16, 8, 0, | ||
| 87 | 58, 50, 42, 34, 26, 18, 10, 2, | ||
| 88 | 60, 52, 44, 36, 28, 20, 12, 4, | ||
| 89 | 62, 54, 46, 38, 30, 22, 14, 6 | ||
| 90 | }; | ||
| 91 | |||
| 92 | |||
| 93 | static char EP[] = | ||
| 94 | { | ||
| 95 | 7, 39, 15, 47, 23, 55, 31, 63, | ||
| 96 | 6, 38, 14, 46, 22, 54, 30, 62, | ||
| 97 | 5, 37, 13, 45, 21, 53, 29, 61, | ||
| 98 | 4, 36, 12, 44, 20, 52, 28, 60, | ||
| 99 | 3, 35, 11, 43, 19, 51, 27, 59, | ||
| 100 | 2, 34, 10, 42, 18, 50, 26, 58, | ||
| 101 | 1, 33, 9, 41, 17, 49, 25, 57, | ||
| 102 | 0, 32, 8, 40, 16, 48, 24, 56 | ||
| 103 | }; | ||
| 104 | |||
| 105 | |||
| 106 | static char E0[] = | ||
| 107 | { | ||
| 108 | 31, 0, 1, 2, 3, 4, 3, 4, | ||
| 109 | 5, 6, 7, 8, 7, 8, 9, 10, | ||
| 110 | 11, 12, 11, 12, 13, 14, 15, 16, | ||
| 111 | 15, 16, 17, 18, 19, 20, 19, 20, | ||
| 112 | 21, 22, 23, 24, 23, 24, 25, 26, | ||
| 113 | 27, 28, 27, 28, 29, 30, 31, 0 | ||
| 114 | }; | ||
| 115 | |||
| 116 | |||
| 117 | static char E[KS]; | ||
| 118 | |||
| 119 | |||
| 120 | static char PERM[] = | ||
| 121 | { | ||
| 122 | 15, 6, 19, 20, 28, 11, 27, 16, | ||
| 123 | 0, 14, 22, 25, 4, 17, 30, 9, | ||
| 124 | 1, 7, 23, 13, 31, 26, 2, 8, | ||
| 125 | 18, 12, 29, 5, 21, 10, 3, 24 | ||
| 126 | }; | ||
| 127 | |||
| 128 | |||
| 129 | static char S_BOX[][64] = | ||
| 130 | { | ||
| 131 | { | ||
| 132 | 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, | ||
| 133 | 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, | ||
| 134 | 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, | ||
| 135 | 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13 | ||
| 136 | }, | ||
| 137 | { | ||
| 138 | 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, | ||
| 139 | 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, | ||
| 140 | 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, | ||
| 141 | 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9 | ||
| 142 | }, | ||
| 143 | { | ||
| 144 | 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, | ||
| 145 | 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, | ||
| 146 | 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, | ||
| 147 | 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12 | ||
| 148 | }, | ||
| 149 | { | ||
| 150 | 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, | ||
| 151 | 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, | ||
| 152 | 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, | ||
| 153 | 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14 | ||
| 154 | }, | ||
| 155 | { | ||
| 156 | 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, | ||
| 157 | 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, | ||
| 158 | 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, | ||
| 159 | 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3 | ||
| 160 | }, | ||
| 161 | { | ||
| 162 | 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, | ||
| 163 | 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, | ||
| 164 | 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, | ||
| 165 | 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13 | ||
| 166 | }, | ||
| 167 | { | ||
| 168 | 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, | ||
| 169 | 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, | ||
| 170 | 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, | ||
| 171 | 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12 | ||
| 172 | }, | ||
| 173 | { | ||
| 174 | 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, | ||
| 175 | 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, | ||
| 176 | 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, | ||
| 177 | 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 | ||
| 178 | } | ||
| 179 | }; | ||
| 180 | |||
| 181 | static void | ||
| 182 | perm (a, e, pc, n) | ||
| 183 | register char *a, *e; | ||
| 184 | register char *pc; | ||
| 185 | int n; | ||
| 186 | { | ||
| 187 | for (; n--; pc++, a++) | ||
| 188 | *a = e[*pc]; | ||
| 189 | } | ||
| 190 | |||
| 191 | static void | ||
| 192 | crypt_main (nachr_l, nachr_r, schl) | ||
| 193 | register char *nachr_l, *nachr_r; | ||
| 194 | register char *schl; | ||
| 195 | { | ||
| 196 | char tmp[KS]; | ||
| 197 | register int sbval; | ||
| 198 | register char *tp = tmp; | ||
| 199 | register char *e = E; | ||
| 200 | register int i, j; | ||
| 201 | |||
| 202 | for (i = 0; i < 8; i++) | ||
| 203 | { | ||
| 204 | for (j = 0, sbval = 0; j < 6; j++) | ||
| 205 | sbval = (sbval << 1) | (nachr_r[*e++] ^ *schl++); | ||
| 206 | sbval = S_BOX[i][sbval]; | ||
| 207 | for (tp += 4, j = 4; j--; sbval >>= 1) | ||
| 208 | *--tp = sbval & 1; | ||
| 209 | tp += 4; | ||
| 210 | } | ||
| 211 | |||
| 212 | e = PERM; | ||
| 213 | for (i = 0; i < BS2; i++) | ||
| 214 | *nachr_l++ ^= tmp[*e++]; | ||
| 215 | } | ||
| 216 | |||
| 217 | void | ||
| 218 | encrypt (char *nachr, int decr) | ||
| 219 | { | ||
| 220 | char (*schl)[KS] = decr ? schluessel + 15 : schluessel; | ||
| 221 | char tmp[BS]; | ||
| 222 | int i; | ||
| 223 | |||
| 224 | perm (tmp, nachr, IP, BS); | ||
| 225 | |||
| 226 | for (i = 8; i--;) | ||
| 227 | { | ||
| 228 | crypt_main (tmp, tmp + BS2, *schl); | ||
| 229 | if (decr) | ||
| 230 | schl--; | ||
| 231 | else | ||
| 232 | schl++; | ||
| 233 | crypt_main (tmp + BS2, tmp, *schl); | ||
| 234 | if (decr) | ||
| 235 | schl--; | ||
| 236 | else | ||
| 237 | schl++; | ||
| 238 | } | ||
| 239 | |||
| 240 | perm (nachr, tmp, EP, BS); | ||
| 241 | } | ||
| 242 | |||
| 243 | void | ||
| 244 | setkey (char *schl) | ||
| 245 | { | ||
| 246 | char tmp1[IS]; | ||
| 247 | register unsigned int ls = 0x7efc; | ||
| 248 | register int i, j, k; | ||
| 249 | register int shval = 0; | ||
| 250 | register char *akt_schl; | ||
| 251 | |||
| 252 | memcpy (E, E0, KS); | ||
| 253 | perm (tmp1, schl, PC1, IS); | ||
| 254 | |||
| 255 | for (i = 0; i < 16; i++) | ||
| 256 | { | ||
| 257 | shval += 1 + (ls & 1); | ||
| 258 | akt_schl = schluessel[i]; | ||
| 259 | for (j = 0; j < KS; j++) | ||
| 260 | { | ||
| 261 | if ((k = PC2[j]) >= IS2) | ||
| 262 | { | ||
| 263 | if ((k += shval) >= IS) | ||
| 264 | k = (k - IS2) % IS2 + IS2; | ||
| 265 | } | ||
| 266 | else if ((k += shval) >= IS2) | ||
| 267 | k %= IS2; | ||
| 268 | *akt_schl++ = tmp1[k]; | ||
| 269 | } | ||
| 270 | ls >>= 1; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | char * | ||
| 275 | des_crypt (const char *wort, const char *salt) | ||
| 276 | { | ||
| 277 | static char retkey[14]; | ||
| 278 | char key[BS + 2]; | ||
| 279 | char *k; | ||
| 280 | int tmp, keybyte; | ||
| 281 | int i, j; | ||
| 282 | |||
| 283 | memset (key, 0, BS + 2); | ||
| 284 | |||
| 285 | for (k = key, i = 0; i < BS; i++) | ||
| 286 | { | ||
| 287 | if (!(keybyte = *wort++)) | ||
| 288 | break; | ||
| 289 | k += 7; | ||
| 290 | for (j = 0; j < 7; j++, i++) | ||
| 291 | { | ||
| 292 | *--k = keybyte & 1; | ||
| 293 | keybyte >>= 1; | ||
| 294 | } | ||
| 295 | k += 8; | ||
| 296 | } | ||
| 297 | |||
| 298 | setkey (key); | ||
| 299 | memset (key, 0, BS + 2); | ||
| 300 | |||
| 301 | for (k = E, i = 0; i < 2; i++) | ||
| 302 | { | ||
| 303 | retkey[i] = keybyte = *salt++; | ||
| 304 | if (keybyte > 'Z') | ||
| 305 | keybyte -= 'a' - 'Z' - 1; | ||
| 306 | if (keybyte > '9') | ||
| 307 | keybyte -= 'A' - '9' - 1; | ||
| 308 | keybyte -= '.'; | ||
| 309 | |||
| 310 | for (j = 0; j < 6; j++, keybyte >>= 1, k++) | ||
| 311 | { | ||
| 312 | if (!(keybyte & 1)) | ||
| 313 | continue; | ||
| 314 | tmp = *k; | ||
| 315 | *k = k[24]; | ||
| 316 | k[24] = tmp; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | for (i = 0; i < 25; i++) | ||
| 321 | encrypt (key, 0); | ||
| 322 | |||
| 323 | for (k = key, i = 0; i < 11; i++) | ||
| 324 | { | ||
| 325 | for (j = keybyte = 0; j < 6; j++) | ||
| 326 | { | ||
| 327 | keybyte <<= 1; | ||
| 328 | keybyte |= *k++; | ||
| 329 | } | ||
| 330 | |||
| 331 | keybyte += '.'; | ||
| 332 | if (keybyte > '9') | ||
| 333 | keybyte += 'A' - '9' - 1; | ||
| 334 | if (keybyte > 'Z') | ||
| 335 | keybyte += 'a' - 'Z' - 1; | ||
| 336 | retkey[i + 2] = keybyte; | ||
| 337 | } | ||
| 338 | |||
| 339 | retkey[i + 2] = 0; | ||
| 340 | |||
| 341 | if (!retkey[1]) | ||
| 342 | retkey[1] = *retkey; | ||
| 343 | |||
| 344 | return retkey; | ||
| 345 | } | ||
| 346 | |||
| 347 | char * | ||
| 348 | crypt (const char *pw, const char *salt) | ||
| 349 | { | ||
| 350 | if (strlen(salt)>MD5_MAGIC_LEN && strncmp(salt, MD5_MAGIC, MD5_MAGIC_LEN)==0) { | ||
| 351 | return md5_crypt(pw, salt); | ||
| 352 | } else { | ||
| 353 | return des_crypt(pw, salt); | ||
| 354 | } | ||
| 355 | } | ||
diff --git a/crypt_win32.h b/crypt_win32.h new file mode 100644 index 0000000..9dd5ffa --- /dev/null +++ b/crypt_win32.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | PHP Version 5 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 1997-2006 The PHP Group | | ||
| 6 | +----------------------------------------------------------------------+ | ||
| 7 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 8 | | that is bundled with this package in the file LICENSE, and is | | ||
| 9 | | available through the world-wide-web at the following url: | | ||
| 10 | | http://www.php.net/license/3_01.txt | | ||
| 11 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 12 | | obtain it through the world-wide-web, please send a note to | | ||
| 13 | | license@php.net so we can mail you a copy immediately. | | ||
| 14 | +----------------------------------------------------------------------+ | ||
| 15 | | Author: | | ||
| 16 | +----------------------------------------------------------------------+ | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* $Id: crypt_win32.h,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 20 | |||
| 21 | /* This code is distributed under the PHP license with permission from | ||
| 22 | the author Jochen Obalek <jochen.obalek@bigfoot.de> */ | ||
| 23 | |||
| 24 | /* encrypt.h - API to 56 bit DES encryption via calls | ||
| 25 | encrypt(3), setkey(3) and crypt(3) | ||
| 26 | Copyright (C) 1991 Jochen Obalek | ||
| 27 | |||
| 28 | This program is free software; you can redistribute it and/or modify | ||
| 29 | it under the terms of the GNU General Public License as published by | ||
| 30 | the Free Software Foundation; either version 2, or (at your option) | ||
| 31 | any later version. | ||
| 32 | |||
| 33 | This program is distributed in the hope that it will be useful, | ||
| 34 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 35 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 36 | GNU General Public License for more details. | ||
| 37 | |||
| 38 | You should have received a copy of the GNU General Public License | ||
| 39 | along with this program; if not, write to the Free Software | ||
| 40 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 41 | |||
| 42 | #ifndef _ENCRYPT_H_ | ||
| 43 | #define _ENCRYPT_H_ | ||
| 44 | |||
| 45 | #ifdef __cplusplus | ||
| 46 | extern "C" | ||
| 47 | { | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #include <_ansi.h> | ||
| 51 | |||
| 52 | void _EXFUN(encrypt, (char *block, int edflag)); | ||
| 53 | void _EXFUN(setkey, (char *key)); | ||
| 54 | char * _EXFUN(crypt, (const char *key, const char *salt)); | ||
| 55 | |||
| 56 | #ifdef __cplusplus | ||
| 57 | } | ||
| 58 | #endif | ||
| 59 | |||
| 60 | #endif /* _ENCRYPT_H_ */ | ||
diff --git a/ex_imp.c b/ex_imp.c new file mode 100644 index 0000000..f602860 --- /dev/null +++ b/ex_imp.c | |||
| @@ -0,0 +1,450 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: ex_imp.c,v 1.2 2008-01-04 11:23:47 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "php_suhosin.h" | ||
| 30 | #include "ext/standard/php_smart_str.h" | ||
| 31 | |||
| 32 | |||
| 33 | #define EXTR_OVERWRITE 0 | ||
| 34 | #define EXTR_SKIP 1 | ||
| 35 | #define EXTR_PREFIX_SAME 2 | ||
| 36 | #define EXTR_PREFIX_ALL 3 | ||
| 37 | #define EXTR_PREFIX_INVALID 4 | ||
| 38 | #define EXTR_PREFIX_IF_EXISTS 5 | ||
| 39 | #define EXTR_IF_EXISTS 6 | ||
| 40 | |||
| 41 | #define EXTR_REFS 0x100 | ||
| 42 | |||
| 43 | |||
| 44 | static int php_valid_var_name(char *var_name) | ||
| 45 | { | ||
| 46 | int len, i; | ||
| 47 | |||
| 48 | if (!var_name) | ||
| 49 | return 0; | ||
| 50 | |||
| 51 | len = strlen(var_name); | ||
| 52 | |||
| 53 | if (!isalpha((int)((unsigned char *)var_name)[0]) && var_name[0] != '_') | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | if (len > 1) { | ||
| 57 | for (i=1; i<len; i++) { | ||
| 58 | if (!isalnum((int)((unsigned char *)var_name)[i]) && var_name[i] != '_') { | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | if (var_name[0] == 'H') { | ||
| 65 | if ((strcmp(var_name, "HTTP_GET_VARS")==0)|| | ||
| 66 | (strcmp(var_name, "HTTP_POST_VARS")==0)|| | ||
| 67 | (strcmp(var_name, "HTTP_POST_FILES")==0)|| | ||
| 68 | (strcmp(var_name, "HTTP_ENV_VARS")==0)|| | ||
| 69 | (strcmp(var_name, "HTTP_SERVER_VARS")==0)|| | ||
| 70 | (strcmp(var_name, "HTTP_SESSION_VARS")==0)|| | ||
| 71 | (strcmp(var_name, "HTTP_COOKIE_VARS")==0)|| | ||
| 72 | (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) { | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | } else if (var_name[0] == '_') { | ||
| 76 | if ((strcmp(var_name, "_COOKIE")==0)|| | ||
| 77 | (strcmp(var_name, "_ENV")==0)|| | ||
| 78 | (strcmp(var_name, "_FILES")==0)|| | ||
| 79 | (strcmp(var_name, "_GET")==0)|| | ||
| 80 | (strcmp(var_name, "_POST")==0)|| | ||
| 81 | (strcmp(var_name, "_REQUEST")==0)|| | ||
| 82 | (strcmp(var_name, "_SESSION")==0)|| | ||
| 83 | (strcmp(var_name, "_SERVER")==0)) { | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | } else if (strcmp(var_name, "GLOBALS")==0) { | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | return 1; | ||
| 91 | } | ||
| 92 | |||
| 93 | |||
| 94 | /* {{{ proto int extract(array var_array [, int extract_type [, string prefix]]) | ||
| 95 | Imports variables into symbol table from an array */ | ||
| 96 | PHP_FUNCTION(suhosin_extract) | ||
| 97 | { | ||
| 98 | zval **var_array, **z_extract_type, **prefix; | ||
| 99 | zval **entry, *data; | ||
| 100 | char *var_name; | ||
| 101 | smart_str final_name = {0}; | ||
| 102 | ulong num_key; | ||
| 103 | uint var_name_len; | ||
| 104 | int var_exists, extract_type, key_type, count = 0; | ||
| 105 | int extract_refs = 0; | ||
| 106 | HashPosition pos; | ||
| 107 | |||
| 108 | switch (ZEND_NUM_ARGS()) { | ||
| 109 | case 1: | ||
| 110 | if (zend_get_parameters_ex(1, &var_array) == FAILURE) { | ||
| 111 | WRONG_PARAM_COUNT; | ||
| 112 | } | ||
| 113 | extract_type = EXTR_OVERWRITE; | ||
| 114 | break; | ||
| 115 | |||
| 116 | case 2: | ||
| 117 | if (zend_get_parameters_ex(2, &var_array, &z_extract_type) == FAILURE) { | ||
| 118 | WRONG_PARAM_COUNT; | ||
| 119 | } | ||
| 120 | convert_to_long_ex(z_extract_type); | ||
| 121 | extract_type = Z_LVAL_PP(z_extract_type); | ||
| 122 | extract_refs = (extract_type & EXTR_REFS); | ||
| 123 | extract_type &= 0xff; | ||
| 124 | if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS) { | ||
| 125 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Prefix expected to be specified"); | ||
| 126 | return; | ||
| 127 | } | ||
| 128 | break; | ||
| 129 | |||
| 130 | case 3: | ||
| 131 | if (zend_get_parameters_ex(3, &var_array, &z_extract_type, &prefix) == FAILURE) { | ||
| 132 | WRONG_PARAM_COUNT; | ||
| 133 | } | ||
| 134 | convert_to_long_ex(z_extract_type); | ||
| 135 | extract_type = Z_LVAL_PP(z_extract_type); | ||
| 136 | extract_refs = (extract_type & EXTR_REFS); | ||
| 137 | extract_type &= 0xff; | ||
| 138 | convert_to_string_ex(prefix); | ||
| 139 | break; | ||
| 140 | |||
| 141 | default: | ||
| 142 | WRONG_PARAM_COUNT; | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | |||
| 146 | #if PHP_VERSION_ID >= 50300 | ||
| 147 | if (!EG(active_symbol_table)) { | ||
| 148 | zend_rebuild_symbol_table(TSRMLS_C); | ||
| 149 | } | ||
| 150 | #endif | ||
| 151 | |||
| 152 | if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) { | ||
| 153 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown extract type"); | ||
| 154 | return; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (Z_TYPE_PP(var_array) != IS_ARRAY) { | ||
| 158 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument should be an array"); | ||
| 159 | return; | ||
| 160 | } | ||
| 161 | |||
| 162 | zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(var_array), &pos); | ||
| 163 | while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(var_array), (void **)&entry, &pos) == SUCCESS) { | ||
| 164 | key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(var_array), &var_name, &var_name_len, &num_key, 0, &pos); | ||
| 165 | var_exists = 0; | ||
| 166 | |||
| 167 | if (key_type == HASH_KEY_IS_STRING) { | ||
| 168 | var_name_len--; | ||
| 169 | var_exists = zend_hash_exists(EG(active_symbol_table), var_name, var_name_len + 1); | ||
| 170 | } else if (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID) { | ||
| 171 | smart_str_appendl(&final_name, Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); | ||
| 172 | smart_str_appendc(&final_name, '_'); | ||
| 173 | smart_str_append_long(&final_name, num_key); | ||
| 174 | } else { | ||
| 175 | zend_hash_move_forward_ex(Z_ARRVAL_PP(var_array), &pos); | ||
| 176 | continue; | ||
| 177 | } | ||
| 178 | |||
| 179 | switch (extract_type) { | ||
| 180 | case EXTR_IF_EXISTS: | ||
| 181 | if (!var_exists) break; | ||
| 182 | /* break omitted intentionally */ | ||
| 183 | |||
| 184 | case EXTR_OVERWRITE: | ||
| 185 | /* GLOBALS protection */ | ||
| 186 | if (var_exists && !strcmp(var_name, "GLOBALS")) { | ||
| 187 | break; | ||
| 188 | } | ||
| 189 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 190 | break; | ||
| 191 | |||
| 192 | case EXTR_PREFIX_IF_EXISTS: | ||
| 193 | if (var_exists) { | ||
| 194 | smart_str_appendl(&final_name, Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); | ||
| 195 | smart_str_appendc(&final_name, '_'); | ||
| 196 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 197 | } | ||
| 198 | break; | ||
| 199 | |||
| 200 | case EXTR_PREFIX_SAME: | ||
| 201 | if (!var_exists) | ||
| 202 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 203 | /* break omitted intentionally */ | ||
| 204 | |||
| 205 | case EXTR_PREFIX_ALL: | ||
| 206 | if (final_name.len == 0 && var_name_len != 0) { | ||
| 207 | smart_str_appendl(&final_name, Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); | ||
| 208 | smart_str_appendc(&final_name, '_'); | ||
| 209 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 210 | } | ||
| 211 | break; | ||
| 212 | |||
| 213 | case EXTR_PREFIX_INVALID: | ||
| 214 | if (final_name.len == 0) { | ||
| 215 | if (!php_valid_var_name(var_name)) { | ||
| 216 | smart_str_appendl(&final_name, Z_STRVAL_PP(prefix), Z_STRLEN_PP(prefix)); | ||
| 217 | smart_str_appendc(&final_name, '_'); | ||
| 218 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 219 | } else | ||
| 220 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 221 | } | ||
| 222 | break; | ||
| 223 | |||
| 224 | default: | ||
| 225 | if (!var_exists) | ||
| 226 | smart_str_appendl(&final_name, var_name, var_name_len); | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | |||
| 230 | if (final_name.len) { | ||
| 231 | smart_str_0(&final_name); | ||
| 232 | if (php_valid_var_name(final_name.c)) { | ||
| 233 | if (extract_refs) { | ||
| 234 | zval **orig_var; | ||
| 235 | |||
| 236 | if (zend_hash_find(EG(active_symbol_table), final_name.c, final_name.len+1, (void **) &orig_var) == SUCCESS) { | ||
| 237 | SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); | ||
| 238 | zval_add_ref(entry); | ||
| 239 | |||
| 240 | zval_ptr_dtor(orig_var); | ||
| 241 | |||
| 242 | *orig_var = *entry; | ||
| 243 | } else { | ||
| 244 | if (Z_REFCOUNT_PP(var_array) > 1) { | ||
| 245 | SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); | ||
| 246 | } else { | ||
| 247 | Z_SET_ISREF_PP(entry); | ||
| 248 | } | ||
| 249 | zval_add_ref(entry); | ||
| 250 | zend_hash_update(EG(active_symbol_table), final_name.c, final_name.len+1, (void **) entry, sizeof(zval *), NULL); | ||
| 251 | } | ||
| 252 | } else { | ||
| 253 | MAKE_STD_ZVAL(data); | ||
| 254 | *data = **entry; | ||
| 255 | zval_copy_ctor(data); | ||
| 256 | |||
| 257 | ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table), final_name.c, final_name.len+1, data, 1, 0); | ||
| 258 | } | ||
| 259 | |||
| 260 | count++; | ||
| 261 | } | ||
| 262 | final_name.len = 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | zend_hash_move_forward_ex(Z_ARRVAL_PP(var_array), &pos); | ||
| 266 | } | ||
| 267 | |||
| 268 | smart_str_free(&final_name); | ||
| 269 | |||
| 270 | RETURN_LONG(count); | ||
| 271 | } | ||
| 272 | /* }}} */ | ||
| 273 | |||
| 274 | |||
| 275 | static int copy_request_variable(void *pDest, int num_args, va_list args, zend_hash_key *hash_key) | ||
| 276 | { | ||
| 277 | char *prefix, *new_key; | ||
| 278 | uint prefix_len, new_key_len; | ||
| 279 | zval **var = (zval **) pDest; | ||
| 280 | TSRMLS_FETCH(); | ||
| 281 | |||
| 282 | if (num_args != 2) { | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | prefix = va_arg(args, char *); | ||
| 287 | prefix_len = va_arg(args, uint); | ||
| 288 | |||
| 289 | if (!prefix_len) { | ||
| 290 | if (!hash_key->nKeyLength) { | ||
| 291 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Numeric key detected - possible security hazard."); | ||
| 292 | return 0; | ||
| 293 | } else if (!strcmp(hash_key->arKey, "GLOBALS")) { | ||
| 294 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempted GLOBALS variable overwrite."); | ||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | if (hash_key->nKeyLength) { | ||
| 300 | new_key_len = prefix_len + hash_key->nKeyLength; | ||
| 301 | new_key = (char *) emalloc(new_key_len); | ||
| 302 | |||
| 303 | memcpy(new_key, prefix, prefix_len); | ||
| 304 | memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength); | ||
| 305 | } else { | ||
| 306 | new_key_len = spprintf(&new_key, 0, "%s%ld", prefix, hash_key->h); | ||
| 307 | } | ||
| 308 | |||
| 309 | if (new_key[0] == 'H') { | ||
| 310 | if ((strcmp(new_key, "HTTP_GET_VARS")==0)|| | ||
| 311 | (strcmp(new_key, "HTTP_POST_VARS")==0)|| | ||
| 312 | (strcmp(new_key, "HTTP_POST_FILES")==0)|| | ||
| 313 | (strcmp(new_key, "HTTP_ENV_VARS")==0)|| | ||
| 314 | (strcmp(new_key, "HTTP_SERVER_VARS")==0)|| | ||
| 315 | (strcmp(new_key, "HTTP_SESSION_VARS")==0)|| | ||
| 316 | (strcmp(new_key, "HTTP_COOKIE_VARS")==0)|| | ||
| 317 | (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) { | ||
| 318 | efree(new_key); | ||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | } else if (new_key[0] == '_') { | ||
| 322 | if ((strcmp(new_key, "_COOKIE")==0)|| | ||
| 323 | (strcmp(new_key, "_ENV")==0)|| | ||
| 324 | (strcmp(new_key, "_FILES")==0)|| | ||
| 325 | (strcmp(new_key, "_GET")==0)|| | ||
| 326 | (strcmp(new_key, "_POST")==0)|| | ||
| 327 | (strcmp(new_key, "_REQUEST")==0)|| | ||
| 328 | (strcmp(new_key, "_SESSION")==0)|| | ||
| 329 | (strcmp(new_key, "_SERVER")==0)) { | ||
| 330 | efree(new_key); | ||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | } else if (strcmp(new_key, "GLOBALS")==0) { | ||
| 334 | efree(new_key); | ||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | #if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) | ||
| 339 | zend_delete_global_variable(new_key, new_key_len-1 TSRMLS_CC); | ||
| 340 | #else | ||
| 341 | zend_hash_del(&EG(symbol_table), new_key, new_key_len-1); | ||
| 342 | #endif | ||
| 343 | ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, Z_REFCOUNT_PP(var)+1, 0); | ||
| 344 | |||
| 345 | efree(new_key); | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* {{{ proto bool import_request_variables(string types [, string prefix]) | ||
| 350 | Import GET/POST/Cookie variables into the global scope */ | ||
| 351 | PHP_FUNCTION(suhosin_import_request_variables) | ||
| 352 | { | ||
| 353 | zval **z_types, **z_prefix; | ||
| 354 | char *types, *prefix; | ||
| 355 | uint prefix_len; | ||
| 356 | char *p; | ||
| 357 | |||
| 358 | switch (ZEND_NUM_ARGS()) { | ||
| 359 | |||
| 360 | case 1: | ||
| 361 | if (zend_get_parameters_ex(1, &z_types) == FAILURE) { | ||
| 362 | RETURN_FALSE; | ||
| 363 | } | ||
| 364 | prefix = ""; | ||
| 365 | prefix_len = 0; | ||
| 366 | break; | ||
| 367 | |||
| 368 | case 2: | ||
| 369 | if (zend_get_parameters_ex(2, &z_types, &z_prefix) == FAILURE) { | ||
| 370 | RETURN_FALSE; | ||
| 371 | } | ||
| 372 | convert_to_string_ex(z_prefix); | ||
| 373 | prefix = Z_STRVAL_PP(z_prefix); | ||
| 374 | prefix_len = Z_STRLEN_PP(z_prefix); | ||
| 375 | break; | ||
| 376 | |||
| 377 | default: | ||
| 378 | ZEND_WRONG_PARAM_COUNT(); | ||
| 379 | } | ||
| 380 | |||
| 381 | if (prefix_len == 0) { | ||
| 382 | php_error_docref(NULL TSRMLS_CC, E_NOTICE, "No prefix specified - possible security hazard"); | ||
| 383 | } | ||
| 384 | |||
| 385 | convert_to_string_ex(z_types); | ||
| 386 | types = Z_STRVAL_PP(z_types); | ||
| 387 | |||
| 388 | for (p = types; p && *p; p++) { | ||
| 389 | switch (*p) { | ||
| 390 | |||
| 391 | case 'g': | ||
| 392 | case 'G': | ||
| 393 | zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]), (apply_func_args_t) copy_request_variable, 2, prefix, prefix_len); | ||
| 394 | break; | ||
| 395 | |||
| 396 | case 'p': | ||
| 397 | case 'P': | ||
| 398 | zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]), (apply_func_args_t) copy_request_variable, 2, prefix, prefix_len); | ||
| 399 | zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_FILES]), (apply_func_args_t) copy_request_variable, 2, prefix, prefix_len); | ||
| 400 | break; | ||
| 401 | |||
| 402 | case 'c': | ||
| 403 | case 'C': | ||
| 404 | zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]), (apply_func_args_t) copy_request_variable, 2, prefix, prefix_len); | ||
| 405 | break; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | } | ||
| 409 | /* }}} */ | ||
| 410 | |||
| 411 | |||
| 412 | /* {{{ suhosin_ex_imp_functions[] | ||
| 413 | */ | ||
| 414 | function_entry suhosin_ex_imp_functions[] = { | ||
| 415 | PHP_NAMED_FE(extract, PHP_FN(suhosin_extract), NULL) | ||
| 416 | PHP_NAMED_FE(import_request_variables, PHP_FN(suhosin_import_request_variables), NULL) | ||
| 417 | {NULL, NULL, NULL} | ||
| 418 | }; | ||
| 419 | /* }}} */ | ||
| 420 | |||
| 421 | |||
| 422 | void suhosin_hook_ex_imp() | ||
| 423 | { | ||
| 424 | TSRMLS_FETCH(); | ||
| 425 | |||
| 426 | /* replace the extract and import_request_variables functions */ | ||
| 427 | zend_hash_del(CG(function_table), "extract", sizeof("extract")); | ||
| 428 | zend_hash_del(CG(function_table), "import_request_variables", sizeof("import_request_variables")); | ||
| 429 | #ifndef ZEND_ENGINE_2 | ||
| 430 | zend_register_functions(suhosin_ex_imp_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); | ||
| 431 | #else | ||
| 432 | zend_register_functions(NULL, suhosin_ex_imp_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); | ||
| 433 | #endif | ||
| 434 | |||
| 435 | |||
| 436 | |||
| 437 | |||
| 438 | } | ||
| 439 | |||
| 440 | |||
| 441 | /* | ||
| 442 | * Local variables: | ||
| 443 | * tab-width: 4 | ||
| 444 | * c-basic-offset: 4 | ||
| 445 | * End: | ||
| 446 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 447 | * vim<600: noet sw=4 ts=4 | ||
| 448 | */ | ||
| 449 | |||
| 450 | |||
diff --git a/execute.c b/execute.c new file mode 100644 index 0000000..aaa672b --- /dev/null +++ b/execute.c | |||
| @@ -0,0 +1,1750 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: execute.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 21 | |||
| 22 | #ifdef HAVE_CONFIG_H | ||
| 23 | #include "config.h" | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #include "php.h" | ||
| 27 | #include "php_ini.h" | ||
| 28 | #include "zend_hash.h" | ||
| 29 | #include "zend_extensions.h" | ||
| 30 | #include "ext/standard/info.h" | ||
| 31 | #include "ext/standard/php_rand.h" | ||
| 32 | #include "php_suhosin.h" | ||
| 33 | #include "zend_compile.h" | ||
| 34 | #include "zend_llist.h" | ||
| 35 | #include "SAPI.h" | ||
| 36 | |||
| 37 | #include "sha256.h" | ||
| 38 | |||
| 39 | |||
| 40 | static void (*old_execute)(zend_op_array *op_array TSRMLS_DC); | ||
| 41 | static void suhosin_execute(zend_op_array *op_array TSRMLS_DC); | ||
| 42 | static void (*old_execute_ZO)(zend_op_array *op_array, long dummy TSRMLS_DC); | ||
| 43 | static void suhosin_execute_ZO(zend_op_array *op_array, long dummy TSRMLS_DC); | ||
| 44 | static void *(*zo_set_oe_ex)(void *ptr) = NULL; | ||
| 45 | |||
| 46 | /*STATIC zend_op_array* (*old_compile_file)(zend_file_handle* file_handle, int type TSRMLS_DC); | ||
| 47 | STATIC zend_op_array* suhosin_compile_file(zend_file_handle*, int TSRMLS_DC);*/ | ||
| 48 | |||
| 49 | static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); | ||
| 50 | static void (*old_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); | ||
| 51 | |||
| 52 | extern zend_extension suhosin_zend_extension_entry; | ||
| 53 | |||
| 54 | /* {{{ suhosin_strcasestr */ | ||
| 55 | static char *suhosin_strcasestr(char *haystack, char *needle) | ||
| 56 | { | ||
| 57 | unsigned char *t, *h, *n; | ||
| 58 | h = (unsigned char *) haystack; | ||
| 59 | conts: | ||
| 60 | while (*h) { | ||
| 61 | n = (unsigned char *) needle; | ||
| 62 | if (toupper(*h++) == toupper(*n++)) { | ||
| 63 | for (t=h; *n; t++, n++) { | ||
| 64 | if (toupper(*t) != toupper(*n)) goto conts; | ||
| 65 | } | ||
| 66 | return ((char*)h-1); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | return (NULL); | ||
| 71 | } | ||
| 72 | /* }}} */ | ||
| 73 | |||
| 74 | |||
| 75 | #define SUHOSIN_CODE_TYPE_UNKNOWN 0 | ||
| 76 | #define SUHOSIN_CODE_TYPE_COMMANDLINE 1 | ||
| 77 | #define SUHOSIN_CODE_TYPE_EVAL 2 | ||
| 78 | #define SUHOSIN_CODE_TYPE_REGEXP 3 | ||
| 79 | #define SUHOSIN_CODE_TYPE_ASSERT 4 | ||
| 80 | #define SUHOSIN_CODE_TYPE_CFUNC 5 | ||
| 81 | #define SUHOSIN_CODE_TYPE_SUHOSIN 6 | ||
| 82 | #define SUHOSIN_CODE_TYPE_UPLOADED 7 | ||
| 83 | #define SUHOSIN_CODE_TYPE_0FILE 8 | ||
| 84 | #define SUHOSIN_CODE_TYPE_BLACKURL 9 | ||
| 85 | #define SUHOSIN_CODE_TYPE_BADURL 10 | ||
| 86 | #define SUHOSIN_CODE_TYPE_GOODFILE 11 | ||
| 87 | #define SUHOSIN_CODE_TYPE_BADFILE 12 | ||
| 88 | #define SUHOSIN_CODE_TYPE_LONGNAME 13 | ||
| 89 | #define SUHOSIN_CODE_TYPE_MANYDOTS 14 | ||
| 90 | #define SUHOSIN_CODE_TYPE_WRITABLE 15 | ||
| 91 | |||
| 92 | static int suhosin_check_filename(char *s, int len TSRMLS_DC) | ||
| 93 | { | ||
| 94 | char fname[MAXPATHLEN+1]; | ||
| 95 | char *t, *h, *h2, *index, *e; | ||
| 96 | int tlen, i, count=0; | ||
| 97 | uint indexlen; | ||
| 98 | ulong numindex; | ||
| 99 | zend_bool isOk; | ||
| 100 | |||
| 101 | /* check if filename is too long */ | ||
| 102 | if (len > MAXPATHLEN) { | ||
| 103 | return SUHOSIN_CODE_TYPE_LONGNAME; | ||
| 104 | } | ||
| 105 | memcpy(fname, s, len); | ||
| 106 | fname[len] = 0; | ||
| 107 | s = (char *)&fname; | ||
| 108 | e = s + len; | ||
| 109 | |||
| 110 | /* check if ASCIIZ attack -> not working yet (and cannot work in PHP4 + ZO) */ | ||
| 111 | if (len != strlen(s)) { | ||
| 112 | return SUHOSIN_CODE_TYPE_0FILE; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* disallow uploaded files */ | ||
| 116 | if (SG(rfc1867_uploaded_files)) { | ||
| 117 | if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) s, e-s+1)) { | ||
| 118 | return SUHOSIN_CODE_TYPE_UPLOADED; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | /* count number of directory traversals */ | ||
| 123 | for (i=0; i < len-3; i++) { | ||
| 124 | if (s[i] == '.' && s[i+1] == '.' && (s[i+2] == '/' || s[i+2] == '\\')) { | ||
| 125 | count++; | ||
| 126 | i+=2; | ||
| 127 | } | ||
| 128 | } | ||
| 129 | if (SUHOSIN_G(executor_include_max_traversal) && SUHOSIN_G(executor_include_max_traversal)<=count) { | ||
| 130 | return SUHOSIN_CODE_TYPE_MANYDOTS; | ||
| 131 | } | ||
| 132 | |||
| 133 | SDEBUG("xxx %08x %08x",SUHOSIN_G(include_whitelist),SUHOSIN_G(include_blacklist)); | ||
| 134 | /* no black or whitelist then disallow all */ | ||
| 135 | if (SUHOSIN_G(include_whitelist)==NULL && SUHOSIN_G(include_blacklist)==NULL) { | ||
| 136 | /* disallow all URLs */ | ||
| 137 | if (strstr(s, "://") != NULL || suhosin_strcasestr(s, "data:") != NULL) { | ||
| 138 | return SUHOSIN_CODE_TYPE_BADURL; | ||
| 139 | } | ||
| 140 | } else | ||
| 141 | /* whitelist is stronger than blacklist */ | ||
| 142 | if (SUHOSIN_G(include_whitelist)) { | ||
| 143 | |||
| 144 | do { | ||
| 145 | isOk = 0; | ||
| 146 | |||
| 147 | h = strstr(s, "://"); | ||
| 148 | h2 = suhosin_strcasestr(s, "data:"); | ||
| 149 | h2 = h2 == NULL ? NULL : h2 + 4; | ||
| 150 | t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h < h2) ? h : h2 ) ); | ||
| 151 | if (h == NULL) break; | ||
| 152 | |||
| 153 | while (t > s && (isalnum(t[-1]) || t[-1]=='_')) { | ||
| 154 | t--; | ||
| 155 | } | ||
| 156 | |||
| 157 | tlen = e-t; | ||
| 158 | |||
| 159 | zend_hash_internal_pointer_reset(SUHOSIN_G(include_whitelist)); | ||
| 160 | do { | ||
| 161 | int r = zend_hash_get_current_key_ex(SUHOSIN_G(include_whitelist), &index, &indexlen, &numindex, 0, NULL); | ||
| 162 | |||
| 163 | if (r==HASH_KEY_NON_EXISTANT) { | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | if (r==HASH_KEY_IS_STRING) { | ||
| 167 | if (h-t <= indexlen-1 && tlen>=indexlen-1) { | ||
| 168 | if (strncasecmp(t, index, indexlen-1)==0) { | ||
| 169 | isOk = 1; | ||
| 170 | break; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | zend_hash_move_forward(SUHOSIN_G(include_whitelist)); | ||
| 176 | } while (1); | ||
| 177 | |||
| 178 | /* not found in whitelist */ | ||
| 179 | if (!isOk) { | ||
| 180 | return SUHOSIN_CODE_TYPE_BADURL; | ||
| 181 | } | ||
| 182 | |||
| 183 | s = h + 1; | ||
| 184 | } while (1); | ||
| 185 | } else { | ||
| 186 | |||
| 187 | do { | ||
| 188 | int tlen; | ||
| 189 | |||
| 190 | h = strstr(s, "://"); | ||
| 191 | h2 = suhosin_strcasestr(s, "data:"); | ||
| 192 | h2 = h2 == NULL ? NULL : h2 + 4; | ||
| 193 | t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h < h2) ? h : h2 ) ); | ||
| 194 | if (h == NULL) break; | ||
| 195 | |||
| 196 | while (t > s && (isalnum(t[-1]) || t[-1]=='_')) { | ||
| 197 | t--; | ||
| 198 | } | ||
| 199 | |||
| 200 | tlen = e-t; | ||
| 201 | |||
| 202 | zend_hash_internal_pointer_reset(SUHOSIN_G(include_blacklist)); | ||
| 203 | do { | ||
| 204 | int r = zend_hash_get_current_key_ex(SUHOSIN_G(include_blacklist), &index, &indexlen, &numindex, 0, NULL); | ||
| 205 | |||
| 206 | if (r==HASH_KEY_NON_EXISTANT) { | ||
| 207 | break; | ||
| 208 | } | ||
| 209 | if (r==HASH_KEY_IS_STRING) { | ||
| 210 | if (h-t <= indexlen-1 && tlen>=indexlen-1) { | ||
| 211 | if (strncasecmp(t, index, indexlen-1)==0) { | ||
| 212 | return SUHOSIN_CODE_TYPE_BLACKURL; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | zend_hash_move_forward(SUHOSIN_G(include_blacklist)); | ||
| 218 | } while (1); | ||
| 219 | |||
| 220 | s = h + 1; | ||
| 221 | } while (1); | ||
| 222 | } | ||
| 223 | |||
| 224 | /* disallow writable files */ | ||
| 225 | if (!SUHOSIN_G(executor_include_allow_writable_files)) { | ||
| 226 | /* protection against *REMOTE* attacks, potential | ||
| 227 | race condition of access() is irrelevant */ | ||
| 228 | if (access(s, W_OK) == 0) { | ||
| 229 | return SUHOSIN_CODE_TYPE_WRITABLE; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | return SUHOSIN_CODE_TYPE_GOODFILE; | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | #ifdef ZEND_ENGINE_2 | ||
| 238 | static int (*old_zend_stream_open)(const char *filename, zend_file_handle *fh TSRMLS_DC); | ||
| 239 | #else | ||
| 240 | static zend_bool (*old_zend_open)(const char *filename, zend_file_handle *fh); | ||
| 241 | #endif | ||
| 242 | |||
| 243 | #ifdef ZEND_ENGINE_2 | ||
| 244 | static int suhosin_zend_stream_open(const char *filename, zend_file_handle *fh TSRMLS_DC) | ||
| 245 | { | ||
| 246 | zend_execute_data *exd; | ||
| 247 | #else | ||
| 248 | static zend_bool suhosin_zend_open(const char *filename, zend_file_handle *fh) | ||
| 249 | { | ||
| 250 | zend_execute_data *exd; | ||
| 251 | TSRMLS_FETCH(); | ||
| 252 | #endif | ||
| 253 | exd=EG(current_execute_data); | ||
| 254 | if (EG(in_execution) && (exd!=NULL) && (exd->opline != NULL) && (exd->opline->opcode == ZEND_INCLUDE_OR_EVAL)) { | ||
| 255 | int filetype = suhosin_check_filename((char *)filename, strlen(filename) TSRMLS_CC); | ||
| 256 | |||
| 257 | switch (filetype) { | ||
| 258 | case SUHOSIN_CODE_TYPE_LONGNAME: | ||
| 259 | suhosin_log(S_INCLUDE, "Include filename ('%s') is too long", filename); | ||
| 260 | suhosin_bailout(TSRMLS_C); | ||
| 261 | break; | ||
| 262 | |||
| 263 | case SUHOSIN_CODE_TYPE_UPLOADED: | ||
| 264 | suhosin_log(S_INCLUDE, "Include filename is an uploaded file"); | ||
| 265 | suhosin_bailout(TSRMLS_C); | ||
| 266 | break; | ||
| 267 | |||
| 268 | case SUHOSIN_CODE_TYPE_0FILE: | ||
| 269 | suhosin_log(S_INCLUDE, "Include filename contains an ASCIIZ character"); | ||
| 270 | suhosin_bailout(TSRMLS_C); | ||
| 271 | break; | ||
| 272 | |||
| 273 | case SUHOSIN_CODE_TYPE_WRITABLE: | ||
| 274 | suhosin_log(S_INCLUDE, "Include filename ('%s') is writable by PHP process", filename); | ||
| 275 | suhosin_bailout(TSRMLS_C); | ||
| 276 | break; | ||
| 277 | |||
| 278 | case SUHOSIN_CODE_TYPE_BLACKURL: | ||
| 279 | suhosin_log(S_INCLUDE, "Include filename ('%s') is an URL that is forbidden by the blacklist", filename); | ||
| 280 | suhosin_bailout(TSRMLS_C); | ||
| 281 | break; | ||
| 282 | |||
| 283 | case SUHOSIN_CODE_TYPE_BADURL: | ||
| 284 | suhosin_log(S_INCLUDE, "Include filename ('%s') is an URL that is not allowed", filename); | ||
| 285 | suhosin_bailout(TSRMLS_C); | ||
| 286 | break; | ||
| 287 | |||
| 288 | case SUHOSIN_CODE_TYPE_MANYDOTS: | ||
| 289 | suhosin_log(S_INCLUDE, "Include filename ('%s') contains too many '../'", filename); | ||
| 290 | suhosin_bailout(TSRMLS_C); | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | #ifdef ZEND_ENGINE_2 | ||
| 295 | return old_zend_stream_open(filename, fh TSRMLS_CC); | ||
| 296 | #else | ||
| 297 | return old_zend_open(filename, fh); | ||
| 298 | #endif | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | static int suhosin_detect_codetype(zend_op_array *op_array TSRMLS_DC) | ||
| 303 | { | ||
| 304 | char *s; | ||
| 305 | int r; | ||
| 306 | |||
| 307 | s = op_array->filename; | ||
| 308 | |||
| 309 | /* eval, assert, create_function, preg_replace */ | ||
| 310 | if (op_array->type == ZEND_EVAL_CODE) { | ||
| 311 | |||
| 312 | if (s == NULL) { | ||
| 313 | return SUHOSIN_CODE_TYPE_UNKNOWN; | ||
| 314 | } | ||
| 315 | |||
| 316 | if (strstr(s, "eval()'d code") != NULL) { | ||
| 317 | return SUHOSIN_CODE_TYPE_EVAL; | ||
| 318 | } | ||
| 319 | |||
| 320 | if (strstr(s, "regexp code") != NULL) { | ||
| 321 | return SUHOSIN_CODE_TYPE_REGEXP; | ||
| 322 | } | ||
| 323 | |||
| 324 | if (strstr(s, "assert code") != NULL) { | ||
| 325 | return SUHOSIN_CODE_TYPE_ASSERT; | ||
| 326 | } | ||
| 327 | |||
| 328 | if (strstr(s, "runtime-created function") != NULL) { | ||
| 329 | return SUHOSIN_CODE_TYPE_CFUNC; | ||
| 330 | } | ||
| 331 | |||
| 332 | if (strstr(s, "Command line code") != NULL) { | ||
| 333 | return SUHOSIN_CODE_TYPE_COMMANDLINE; | ||
| 334 | } | ||
| 335 | |||
| 336 | if (strstr(s, "suhosin internal code") != NULL) { | ||
| 337 | return SUHOSIN_CODE_TYPE_SUHOSIN; | ||
| 338 | } | ||
| 339 | |||
| 340 | } else { | ||
| 341 | |||
| 342 | r = suhosin_check_filename(s, strlen(s) TSRMLS_CC); | ||
| 343 | /* switch (r) { | ||
| 344 | case SUHOSIN_CODE_TYPE_GOODFILE: | ||
| 345 | break; | ||
| 346 | } */ | ||
| 347 | return r; | ||
| 348 | |||
| 349 | } | ||
| 350 | |||
| 351 | return SUHOSIN_CODE_TYPE_UNKNOWN; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* {{{ void suhosin_execute_ex(zend_op_array *op_array TSRMLS_DC) | ||
| 355 | * This function provides a hook for execution */ | ||
| 356 | static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRMLS_DC) | ||
| 357 | { | ||
| 358 | zend_op_array *new_op_array; | ||
| 359 | int op_array_type, len; | ||
| 360 | char *fn; | ||
| 361 | zval cs; | ||
| 362 | zend_uint orig_code_type; | ||
| 363 | unsigned long *suhosin_flags = NULL; | ||
| 364 | |||
| 365 | if (SUHOSIN_G(abort_request) && !SUHOSIN_G(simulation) && SUHOSIN_G(filter_action)) { | ||
| 366 | |||
| 367 | char *action = SUHOSIN_G(filter_action); | ||
| 368 | long code = -1; | ||
| 369 | |||
| 370 | SUHOSIN_G(abort_request) = 0; /* we do not want to endlessloop */ | ||
| 371 | |||
| 372 | while (*action == ' ' || *action == '\t') action++; | ||
| 373 | |||
| 374 | if (*action >= '0' && *action <= '9') { | ||
| 375 | char *end = action; | ||
| 376 | while (*end && *end != ',' && *end != ';') end++; | ||
| 377 | code = zend_atoi(action, end-action); | ||
| 378 | action = end; | ||
| 379 | } | ||
| 380 | |||
| 381 | while (*action == ' ' || *action == '\t' || *action == ',' || *action == ';') action++; | ||
| 382 | |||
| 383 | if (*action) { | ||
| 384 | |||
| 385 | if (strncmp("http://", action, sizeof("http://")-1)==0) { | ||
| 386 | sapi_header_line ctr = {0}; | ||
| 387 | |||
| 388 | if (code == -1) { | ||
| 389 | code = 302; | ||
| 390 | } | ||
| 391 | |||
| 392 | ctr.line_len = spprintf(&ctr.line, 0, "Location: %s", action); | ||
| 393 | ctr.response_code = code; | ||
| 394 | sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); | ||
| 395 | efree(ctr.line); | ||
| 396 | } else { | ||
| 397 | zend_file_handle file_handle; | ||
| 398 | zend_op_array *new_op_array; | ||
| 399 | zval *result = NULL; | ||
| 400 | |||
| 401 | if (code == -1) { | ||
| 402 | code = 200; | ||
| 403 | } | ||
| 404 | |||
| 405 | #ifdef ZEND_ENGINE_2 | ||
| 406 | if (zend_stream_open(action, &file_handle TSRMLS_CC) == SUCCESS) { | ||
| 407 | #else | ||
| 408 | if (zend_open(action, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { | ||
| 409 | file_handle.filename = action; | ||
| 410 | file_handle.free_filename = 0; | ||
| 411 | #endif | ||
| 412 | if (!file_handle.opened_path) { | ||
| 413 | file_handle.opened_path = estrndup(action, strlen(action)); | ||
| 414 | } | ||
| 415 | new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); | ||
| 416 | zend_destroy_file_handle(&file_handle TSRMLS_CC); | ||
| 417 | if (new_op_array) { | ||
| 418 | EG(return_value_ptr_ptr) = &result; | ||
| 419 | EG(active_op_array) = new_op_array; | ||
| 420 | zend_execute(new_op_array TSRMLS_CC); | ||
| 421 | #ifdef ZEND_ENGINE_2 | ||
| 422 | destroy_op_array(new_op_array TSRMLS_CC); | ||
| 423 | #else | ||
| 424 | destroy_op_array(new_op_array); | ||
| 425 | #endif | ||
| 426 | efree(new_op_array); | ||
| 427 | #ifdef ZEND_ENGINE_2 | ||
| 428 | if (!EG(exception)) | ||
| 429 | #endif | ||
| 430 | { | ||
| 431 | if (EG(return_value_ptr_ptr)) { | ||
| 432 | zval_ptr_dtor(EG(return_value_ptr_ptr)); | ||
| 433 | EG(return_value_ptr_ptr) = NULL; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | } else { | ||
| 437 | code = 500; | ||
| 438 | } | ||
| 439 | } else { | ||
| 440 | code = 500; | ||
| 441 | } | ||
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 | sapi_header_op(SAPI_HEADER_SET_STATUS, (void *)code TSRMLS_CC); | ||
| 446 | zend_bailout(); | ||
| 447 | } | ||
| 448 | |||
| 449 | SDEBUG("%s %s", op_array->filename, op_array->function_name); | ||
| 450 | |||
| 451 | SUHOSIN_G(execution_depth)++; | ||
| 452 | |||
| 453 | if (SUHOSIN_G(max_execution_depth) && SUHOSIN_G(execution_depth) > SUHOSIN_G(max_execution_depth)) { | ||
| 454 | suhosin_log(S_EXECUTOR, "maximum execution depth reached - script terminated"); | ||
| 455 | suhosin_bailout(TSRMLS_C); | ||
| 456 | } | ||
| 457 | |||
| 458 | fn = op_array->filename; | ||
| 459 | len = strlen(fn); | ||
| 460 | |||
| 461 | orig_code_type = SUHOSIN_G(in_code_type); | ||
| 462 | if (op_array->type == ZEND_EVAL_CODE) { | ||
| 463 | SUHOSIN_G(in_code_type) = SUHOSIN_EVAL; | ||
| 464 | } else { | ||
| 465 | if (suhosin_zend_extension_entry.resource_number != -1) { | ||
| 466 | suhosin_flags = (unsigned long *) &op_array->reserved[suhosin_zend_extension_entry.resource_number]; | ||
| 467 | SDEBUG("suhosin flags: %08x", *suhosin_flags); | ||
| 468 | |||
| 469 | if (*suhosin_flags & SUHOSIN_FLAG_CREATED_BY_EVAL) { | ||
| 470 | SUHOSIN_G(in_code_type) = SUHOSIN_EVAL; | ||
| 471 | } | ||
| 472 | if (*suhosin_flags & SUHOSIN_FLAG_NOT_EVALED_CODE) { | ||
| 473 | goto not_evaled_code; | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | if (strstr(op_array->filename, "eval()'d code")) { | ||
| 478 | SUHOSIN_G(in_code_type) = SUHOSIN_EVAL; | ||
| 479 | } else { | ||
| 480 | if (suhosin_flags) { | ||
| 481 | *suhosin_flags |= SUHOSIN_FLAG_NOT_EVALED_CODE; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | } | ||
| 485 | not_evaled_code: | ||
| 486 | SDEBUG("code type %u", SUHOSIN_G(in_code_type)); | ||
| 487 | if (op_array->function_name) { | ||
| 488 | goto continue_execution; | ||
| 489 | } | ||
| 490 | |||
| 491 | /* if (SUHOSIN_G(deactivate)) { | ||
| 492 | goto continue_execution; | ||
| 493 | } | ||
| 494 | */ | ||
| 495 | |||
| 496 | op_array_type = suhosin_detect_codetype(op_array TSRMLS_CC); | ||
| 497 | |||
| 498 | switch (op_array_type) { | ||
| 499 | case SUHOSIN_CODE_TYPE_EVAL: | ||
| 500 | if (SUHOSIN_G(executor_disable_eval)) { | ||
| 501 | suhosin_log(S_EXECUTOR, "use of eval is forbidden by configuration"); | ||
| 502 | if (!SUHOSIN_G(simulation)) { | ||
| 503 | zend_error(E_ERROR, "SUHOSIN - Use of eval is forbidden by configuration"); | ||
| 504 | } | ||
| 505 | } | ||
| 506 | break; | ||
| 507 | |||
| 508 | case SUHOSIN_CODE_TYPE_REGEXP: | ||
| 509 | if (SUHOSIN_G(executor_disable_emod)) { | ||
| 510 | suhosin_log(S_EXECUTOR, "use of preg_replace() with /e modifier is forbidden by configuration"); | ||
| 511 | if (!SUHOSIN_G(simulation)) { | ||
| 512 | zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration"); | ||
| 513 | } | ||
| 514 | } | ||
| 515 | break; | ||
| 516 | |||
| 517 | case SUHOSIN_CODE_TYPE_ASSERT: | ||
| 518 | break; | ||
| 519 | |||
| 520 | case SUHOSIN_CODE_TYPE_CFUNC: | ||
| 521 | break; | ||
| 522 | |||
| 523 | case SUHOSIN_CODE_TYPE_LONGNAME: | ||
| 524 | suhosin_log(S_INCLUDE, "Include filename ('%s') is too long", op_array->filename); | ||
| 525 | suhosin_bailout(TSRMLS_C); | ||
| 526 | break; | ||
| 527 | |||
| 528 | case SUHOSIN_CODE_TYPE_MANYDOTS: | ||
| 529 | suhosin_log(S_INCLUDE, "Include filename ('%s') contains too many '../'", op_array->filename); | ||
| 530 | suhosin_bailout(TSRMLS_C); | ||
| 531 | break; | ||
| 532 | |||
| 533 | case SUHOSIN_CODE_TYPE_UPLOADED: | ||
| 534 | suhosin_log(S_INCLUDE, "Include filename is an uploaded file"); | ||
| 535 | suhosin_bailout(TSRMLS_C); | ||
| 536 | break; | ||
| 537 | |||
| 538 | case SUHOSIN_CODE_TYPE_0FILE: | ||
| 539 | suhosin_log(S_INCLUDE, "Include filename contains an ASCIIZ character"); | ||
| 540 | suhosin_bailout(TSRMLS_C); | ||
| 541 | break; | ||
| 542 | |||
| 543 | case SUHOSIN_CODE_TYPE_WRITABLE: | ||
| 544 | suhosin_log(S_INCLUDE, "Include filename ('%s') is writable by PHP process", op_array->filename); | ||
| 545 | suhosin_bailout(TSRMLS_C); | ||
| 546 | break; | ||
| 547 | |||
| 548 | case SUHOSIN_CODE_TYPE_BLACKURL: | ||
| 549 | suhosin_log(S_INCLUDE, "Include filename ('%s') is an URL that is forbidden by the blacklist", op_array->filename); | ||
| 550 | suhosin_bailout(TSRMLS_C); | ||
| 551 | break; | ||
| 552 | |||
| 553 | case SUHOSIN_CODE_TYPE_BADURL: | ||
| 554 | suhosin_log(S_INCLUDE, "Include filename ('%s') is an URL that is not allowed", op_array->filename); | ||
| 555 | suhosin_bailout(TSRMLS_C); | ||
| 556 | break; | ||
| 557 | |||
| 558 | case SUHOSIN_CODE_TYPE_BADFILE: | ||
| 559 | cs.type = IS_STRING; | ||
| 560 | #define DIE_WITH_MSG "die('disallowed_file'.chr(10).chr(10));" | ||
| 561 | cs.value.str.val = estrndup(DIE_WITH_MSG, sizeof(DIE_WITH_MSG)-1); | ||
| 562 | cs.value.str.len = sizeof(DIE_WITH_MSG)-1; | ||
| 563 | new_op_array = compile_string(&cs, "suhosin internal code" TSRMLS_CC); | ||
| 564 | if (new_op_array) { | ||
| 565 | op_array = new_op_array; | ||
| 566 | goto continue_execution; | ||
| 567 | } | ||
| 568 | suhosin_bailout(TSRMLS_C); | ||
| 569 | break; | ||
| 570 | |||
| 571 | case SUHOSIN_CODE_TYPE_COMMANDLINE: | ||
| 572 | case SUHOSIN_CODE_TYPE_SUHOSIN: | ||
| 573 | case SUHOSIN_CODE_TYPE_UNKNOWN: | ||
| 574 | case SUHOSIN_CODE_TYPE_GOODFILE: | ||
| 575 | goto continue_execution; | ||
| 576 | break; | ||
| 577 | } | ||
| 578 | |||
| 579 | continue_execution: | ||
| 580 | if (zo) { | ||
| 581 | old_execute_ZO (op_array, dummy TSRMLS_CC); | ||
| 582 | } else { | ||
| 583 | old_execute (op_array TSRMLS_CC); | ||
| 584 | } | ||
| 585 | /* nothing to do */ | ||
| 586 | SUHOSIN_G(in_code_type) = orig_code_type; | ||
| 587 | SUHOSIN_G(execution_depth)--; | ||
| 588 | } | ||
| 589 | /* }}} */ | ||
| 590 | |||
| 591 | /* {{{ void suhosin_execute(zend_op_array *op_array TSRMLS_DC) | ||
| 592 | * This function provides a hook for execution */ | ||
| 593 | static void suhosin_execute(zend_op_array *op_array TSRMLS_DC) | ||
| 594 | { | ||
| 595 | suhosin_execute_ex(op_array, 0, 0 TSRMLS_CC); | ||
| 596 | } | ||
| 597 | |||
| 598 | /* {{{ void suhosin_execute(zend_op_array *op_array, long dummy TSRMLS_DC) | ||
| 599 | * This function provides a hook for execution */ | ||
| 600 | static void suhosin_execute_ZO(zend_op_array *op_array, long dummy TSRMLS_DC) | ||
| 601 | { | ||
| 602 | suhosin_execute_ex(op_array, 1, dummy TSRMLS_CC); | ||
| 603 | } | ||
| 604 | /* }}} */ | ||
| 605 | |||
| 606 | |||
| 607 | #define IH_HANDLER_PARAMS_REST zend_execute_data *execute_data_ptr, int return_value_used, int ht, zval *return_value TSRMLS_DC | ||
| 608 | #define IH_HANDLER_PARAMS internal_function_handler *ih, IH_HANDLER_PARAMS_REST | ||
| 609 | #define IH_HANDLER_PARAM_PASSTHRU ih, execute_data_ptr, return_value_used, ht, return_value TSRMLS_CC | ||
| 610 | |||
| 611 | HashTable ihandler_table; | ||
| 612 | |||
| 613 | typedef struct _internal_function_handler { | ||
| 614 | |||
| 615 | char *name; | ||
| 616 | int (*handler)(struct _internal_function_handler *ih, IH_HANDLER_PARAMS_REST); | ||
| 617 | void *arg1; | ||
| 618 | void *arg2; | ||
| 619 | void *arg3; | ||
| 620 | |||
| 621 | } internal_function_handler; | ||
| 622 | |||
| 623 | int ih_preg_replace(IH_HANDLER_PARAMS) | ||
| 624 | { | ||
| 625 | zval **regex, | ||
| 626 | **replace, | ||
| 627 | **subject, | ||
| 628 | **limit; | ||
| 629 | |||
| 630 | if (ZEND_NUM_ARGS() < 3 || zend_get_parameters_ex(3, ®ex, &replace, &subject, &limit) == FAILURE) { | ||
| 631 | return (0); | ||
| 632 | } | ||
| 633 | |||
| 634 | if (Z_TYPE_PP(regex) == IS_ARRAY) { | ||
| 635 | zval **regex_entry; | ||
| 636 | |||
| 637 | zend_hash_internal_pointer_reset(Z_ARRVAL_PP(regex)); | ||
| 638 | /* For each entry in the regex array, get the entry */ | ||
| 639 | while (zend_hash_get_current_data(Z_ARRVAL_PP(regex), (void **)®ex_entry) == SUCCESS) { | ||
| 640 | |||
| 641 | if (Z_TYPE_PP(regex_entry) == IS_STRING) { | ||
| 642 | if (strlen(Z_STRVAL_PP(regex_entry)) != Z_STRLEN_PP(regex_entry)) { | ||
| 643 | suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); | ||
| 644 | if (!SUHOSIN_G(simulation)) { | ||
| 645 | RETVAL_FALSE; | ||
| 646 | return (1); | ||
| 647 | } | ||
| 648 | } | ||
| 649 | } | ||
| 650 | |||
| 651 | zend_hash_move_forward(Z_ARRVAL_PP(regex)); | ||
| 652 | |||
| 653 | } | ||
| 654 | |||
| 655 | } else if (Z_TYPE_PP(regex) == IS_STRING) { | ||
| 656 | if (strlen(Z_STRVAL_PP(regex)) != Z_STRLEN_PP(regex)) { | ||
| 657 | suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); | ||
| 658 | if (!SUHOSIN_G(simulation)) { | ||
| 659 | RETVAL_FALSE; | ||
| 660 | return (1); | ||
| 661 | } | ||
| 662 | } | ||
| 663 | } | ||
| 664 | |||
| 665 | return (0); | ||
| 666 | } | ||
| 667 | |||
| 668 | int ih_symlink(IH_HANDLER_PARAMS) | ||
| 669 | { | ||
| 670 | if (SUHOSIN_G(executor_allow_symlink)) { | ||
| 671 | return (0); | ||
| 672 | } | ||
| 673 | |||
| 674 | if (PG(open_basedir) && PG(open_basedir)[0]) { | ||
| 675 | suhosin_log(S_EXECUTOR, "symlink called during open_basedir"); | ||
| 676 | if (!SUHOSIN_G(simulation)) { | ||
| 677 | RETVAL_FALSE; | ||
| 678 | return (1); | ||
| 679 | } | ||
| 680 | } | ||
| 681 | |||
| 682 | return (0); | ||
| 683 | } | ||
| 684 | |||
| 685 | int ih_mail(IH_HANDLER_PARAMS) | ||
| 686 | { | ||
| 687 | char *to=NULL, *message=NULL, *headers=NULL; | ||
| 688 | char *subject=NULL, *extra_cmd=NULL; | ||
| 689 | char *tmp; | ||
| 690 | int to_len, message_len, headers_len; | ||
| 691 | int subject_len, extra_cmd_len; | ||
| 692 | |||
| 693 | if (SUHOSIN_G(mailprotect) == 0) { | ||
| 694 | return (0); | ||
| 695 | } | ||
| 696 | |||
| 697 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss", | ||
| 698 | &to, &to_len, | ||
| 699 | &subject, &subject_len, | ||
| 700 | &message, &message_len, | ||
| 701 | &headers, &headers_len, | ||
| 702 | &extra_cmd, &extra_cmd_len | ||
| 703 | ) == FAILURE) { | ||
| 704 | RETVAL_FALSE; | ||
| 705 | return (1); | ||
| 706 | } | ||
| 707 | |||
| 708 | if (headers_len > 0 && headers && (strstr(headers,"\n\n") || strstr(headers,"\r\n\r\n")) ) { | ||
| 709 | suhosin_log(S_MAIL, "mail() - double newline in headers, possible injection, mail dropped"); | ||
| 710 | if (!SUHOSIN_G(simulation)) { | ||
| 711 | RETVAL_FALSE; | ||
| 712 | return (1); | ||
| 713 | } | ||
| 714 | } | ||
| 715 | |||
| 716 | /* check for spam attempts with buggy webforms */ | ||
| 717 | if (to_len > 0 && to) { | ||
| 718 | do { | ||
| 719 | tmp = strchr(to, '\n'); | ||
| 720 | tmp = tmp == NULL ? strchr(to, '\r') : tmp; | ||
| 721 | if (tmp == NULL) break; | ||
| 722 | to = tmp+1; | ||
| 723 | if (isspace(*to)) continue; | ||
| 724 | } while (1); | ||
| 725 | if (tmp != NULL) { | ||
| 726 | suhosin_log(S_MAIL, "mail() - newline in to header, possible injection, mail dropped"); | ||
| 727 | if (!SUHOSIN_G(simulation)) { | ||
| 728 | RETVAL_FALSE; | ||
| 729 | return (1); | ||
| 730 | } | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 734 | if (subject_len > 0 && subject) { | ||
| 735 | do { | ||
| 736 | tmp = strchr(subject, '\n'); | ||
| 737 | tmp = tmp == NULL ? strchr(subject, '\r') : tmp; | ||
| 738 | if (tmp == NULL) break; | ||
| 739 | subject = tmp+1; | ||
| 740 | if (isspace(*subject)) continue; | ||
| 741 | } while (1); | ||
| 742 | if (tmp != NULL) { | ||
| 743 | suhosin_log(S_MAIL, "mail() - newline in subject header, possible injection, mail dropped"); | ||
| 744 | if (!SUHOSIN_G(simulation)) { | ||
| 745 | RETVAL_FALSE; | ||
| 746 | return (1); | ||
| 747 | } | ||
| 748 | } | ||
| 749 | } | ||
| 750 | |||
| 751 | if (SUHOSIN_G(mailprotect) > 1) { | ||
| 752 | /* search for to, cc or bcc headers */ | ||
| 753 | if (headers_len > 0 && headers != NULL) { | ||
| 754 | if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || suhosin_strcasestr(headers, "\nto:")) { | ||
| 755 | suhosin_log(S_MAIL, "mail() - To: headers aren't allowed in the headers parameter."); | ||
| 756 | if (!SUHOSIN_G(simulation)) { | ||
| 757 | RETVAL_FALSE; | ||
| 758 | return (1); | ||
| 759 | } | ||
| 760 | } | ||
| 761 | |||
| 762 | if (strncasecmp(headers, "cc:", sizeof("cc:") - 1) == 0 || suhosin_strcasestr(headers, "\ncc:")) { | ||
| 763 | suhosin_log(S_MAIL, "mail() - CC: headers aren't allowed in the headers parameter."); | ||
| 764 | if (!SUHOSIN_G(simulation)) { | ||
| 765 | RETVAL_FALSE; | ||
| 766 | return (1); | ||
| 767 | } | ||
| 768 | } | ||
| 769 | |||
| 770 | if (strncasecmp(headers, "bcc:", sizeof("bcc:") - 1) == 0 || suhosin_strcasestr(headers, "\nbcc:")) { | ||
| 771 | suhosin_log(S_MAIL, "mail() - BCC: headers aren't allowed in the headers parameter."); | ||
| 772 | if (!SUHOSIN_G(simulation)) { | ||
| 773 | RETVAL_FALSE; | ||
| 774 | return (1); | ||
| 775 | } | ||
| 776 | } | ||
| 777 | } | ||
| 778 | } | ||
| 779 | |||
| 780 | return (0); | ||
| 781 | } | ||
| 782 | |||
| 783 | #define SQLSTATE_SQL 0 | ||
| 784 | #define SQLSTATE_IDENTIFIER 1 | ||
| 785 | #define SQLSTATE_STRING 2 | ||
| 786 | #define SQLSTATE_COMMENT 3 | ||
| 787 | #define SQLSTATE_MLCOMMENT 4 | ||
| 788 | |||
| 789 | int ih_querycheck(IH_HANDLER_PARAMS) | ||
| 790 | { | ||
| 791 | #ifdef PHP_ATLEAST_5_3 | ||
| 792 | void **p = zend_vm_stack_top(TSRMLS_C) - 1; | ||
| 793 | #else | ||
| 794 | void **p = EG(argument_stack).top_element-2; | ||
| 795 | #endif | ||
| 796 | unsigned long arg_count; | ||
| 797 | zval **arg; | ||
| 798 | char *query, *s, *e; | ||
| 799 | zval *backup; | ||
| 800 | int len; | ||
| 801 | char quote; | ||
| 802 | int state = SQLSTATE_SQL; | ||
| 803 | int cnt_union = 0, cnt_select = 0, cnt_comment = 0, cnt_opencomment = 0; | ||
| 804 | int mysql_extension = 0; | ||
| 805 | |||
| 806 | |||
| 807 | SDEBUG("function: %s", ih->name); | ||
| 808 | arg_count = (unsigned long) *p; | ||
| 809 | |||
| 810 | if (ht < (long) ih->arg1) { | ||
| 811 | return (0); | ||
| 812 | } | ||
| 813 | |||
| 814 | if ((long) ih->arg1) { | ||
| 815 | mysql_extension = 1; | ||
| 816 | } | ||
| 817 | |||
| 818 | arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ | ||
| 819 | |||
| 820 | backup = *arg; | ||
| 821 | if (Z_TYPE_P(backup) != IS_STRING) { | ||
| 822 | return (0); | ||
| 823 | } | ||
| 824 | len = Z_STRLEN_P(backup); | ||
| 825 | query = Z_STRVAL_P(backup); | ||
| 826 | |||
| 827 | s = query; | ||
| 828 | e = s+len; | ||
| 829 | |||
| 830 | while (s < e) { | ||
| 831 | switch (state) | ||
| 832 | { | ||
| 833 | case SQLSTATE_SQL: | ||
| 834 | switch (s[0]) | ||
| 835 | { | ||
| 836 | case '`': | ||
| 837 | state = SQLSTATE_IDENTIFIER; | ||
| 838 | quote = '`'; | ||
| 839 | break; | ||
| 840 | case '\'': | ||
| 841 | case '"': | ||
| 842 | state = SQLSTATE_STRING; | ||
| 843 | quote = *s; | ||
| 844 | break; | ||
| 845 | case '/': | ||
| 846 | if (s[1]=='*') { | ||
| 847 | if (mysql_extension == 1 && s[2] == '!') { | ||
| 848 | s += 2; | ||
| 849 | break; | ||
| 850 | } | ||
| 851 | s++; | ||
| 852 | state = SQLSTATE_MLCOMMENT; | ||
| 853 | cnt_comment++; | ||
| 854 | } | ||
| 855 | break; | ||
| 856 | case '-': | ||
| 857 | if (s[1]=='-') { | ||
| 858 | s++; | ||
| 859 | state = SQLSTATE_COMMENT; | ||
| 860 | cnt_comment++; | ||
| 861 | } | ||
| 862 | break; | ||
| 863 | case '#': | ||
| 864 | state = SQLSTATE_COMMENT; | ||
| 865 | cnt_comment++; | ||
| 866 | break; | ||
| 867 | case 'u': | ||
| 868 | case 'U': | ||
| 869 | if (strncasecmp("union", s, 5)==0) { | ||
| 870 | s += 4; | ||
| 871 | cnt_union++; | ||
| 872 | } | ||
| 873 | break; | ||
| 874 | case 's': | ||
| 875 | case 'S': | ||
| 876 | if (strncasecmp("select", s, 6)==0) { | ||
| 877 | s += 5; | ||
| 878 | cnt_select++; | ||
| 879 | } | ||
| 880 | break; | ||
| 881 | } | ||
| 882 | break; | ||
| 883 | case SQLSTATE_STRING: | ||
| 884 | case SQLSTATE_IDENTIFIER: | ||
| 885 | if (s[0] == quote) { | ||
| 886 | if (s[1] == quote) { | ||
| 887 | s++; | ||
| 888 | } else { | ||
| 889 | state = SQLSTATE_SQL; | ||
| 890 | } | ||
| 891 | } | ||
| 892 | if (s[0] == '\\') { | ||
| 893 | s++; | ||
| 894 | } | ||
| 895 | break; | ||
| 896 | case SQLSTATE_COMMENT: | ||
| 897 | while (s[0] && s[0] != '\n') { | ||
| 898 | s++; | ||
| 899 | } | ||
| 900 | state = SQLSTATE_SQL; | ||
| 901 | break; | ||
| 902 | case SQLSTATE_MLCOMMENT: | ||
| 903 | while (s[0] && (s[0] != '*' || s[1] != '/')) { | ||
| 904 | s++; | ||
| 905 | } | ||
| 906 | if (s[0]) { | ||
| 907 | state = SQLSTATE_SQL; | ||
| 908 | } | ||
| 909 | break; | ||
| 910 | } | ||
| 911 | s++; | ||
| 912 | } | ||
| 913 | if (state == SQLSTATE_MLCOMMENT) { | ||
| 914 | cnt_opencomment = 1; | ||
| 915 | } | ||
| 916 | |||
| 917 | if (cnt_opencomment && SUHOSIN_G(sql_opencomment)>0) { | ||
| 918 | suhosin_log(S_SQL, "Open comment in SQL query: '%*s'", len, query); | ||
| 919 | if (SUHOSIN_G(sql_opencomment)>1) { | ||
| 920 | suhosin_bailout(TSRMLS_C); | ||
| 921 | } | ||
| 922 | } | ||
| 923 | |||
| 924 | if (cnt_comment && SUHOSIN_G(sql_comment)>0) { | ||
| 925 | suhosin_log(S_SQL, "Comment in SQL query: '%*s'", len, query); | ||
| 926 | if (SUHOSIN_G(sql_comment)>1) { | ||
| 927 | suhosin_bailout(TSRMLS_C); | ||
| 928 | } | ||
| 929 | } | ||
| 930 | |||
| 931 | if (cnt_union && SUHOSIN_G(sql_union)>0) { | ||
| 932 | suhosin_log(S_SQL, "UNION in SQL query: '%*s'", len, query); | ||
| 933 | if (SUHOSIN_G(sql_union)>1) { | ||
| 934 | suhosin_bailout(TSRMLS_C); | ||
| 935 | } | ||
| 936 | } | ||
| 937 | |||
| 938 | if (cnt_select>1 && SUHOSIN_G(sql_mselect)>0) { | ||
| 939 | suhosin_log(S_SQL, "Multiple SELECT in SQL query: '%*s'", len, query); | ||
| 940 | if (SUHOSIN_G(sql_mselect)>1) { | ||
| 941 | suhosin_bailout(TSRMLS_C); | ||
| 942 | } | ||
| 943 | } | ||
| 944 | |||
| 945 | return (0); | ||
| 946 | } | ||
| 947 | |||
| 948 | |||
| 949 | int ih_fixusername(IH_HANDLER_PARAMS) | ||
| 950 | { | ||
| 951 | #ifdef PHP_ATLEAST_5_3 | ||
| 952 | void **p = zend_vm_stack_top(TSRMLS_C) - 1; | ||
| 953 | #else | ||
| 954 | void **p = EG(argument_stack).top_element-2; | ||
| 955 | #endif | ||
| 956 | unsigned long arg_count; | ||
| 957 | zval **arg;char *prefix, *postfix, *user; | ||
| 958 | zval *backup, *my_user; | ||
| 959 | int prefix_len, postfix_len, len; | ||
| 960 | |||
| 961 | SDEBUG("function: %s", ih->name); | ||
| 962 | |||
| 963 | prefix = SUHOSIN_G(sql_user_prefix); | ||
| 964 | postfix = SUHOSIN_G(sql_user_postfix); | ||
| 965 | |||
| 966 | if ((prefix == NULL || prefix[0] == 0)&& | ||
| 967 | (postfix == NULL || postfix[0] == 0)) { | ||
| 968 | return (0); | ||
| 969 | } | ||
| 970 | |||
| 971 | if (prefix == NULL) { | ||
| 972 | prefix = ""; | ||
| 973 | } | ||
| 974 | if (postfix == NULL) { | ||
| 975 | postfix = ""; | ||
| 976 | } | ||
| 977 | |||
| 978 | prefix_len = strlen(prefix); | ||
| 979 | postfix_len = strlen(postfix); | ||
| 980 | |||
| 981 | arg_count = (unsigned long) *p; | ||
| 982 | |||
| 983 | if (ht < (long) ih->arg1) { | ||
| 984 | return (0); | ||
| 985 | } | ||
| 986 | |||
| 987 | arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ | ||
| 988 | |||
| 989 | backup = *arg; | ||
| 990 | if (Z_TYPE_P(backup) != IS_STRING) { | ||
| 991 | user = ""; | ||
| 992 | len = 0; | ||
| 993 | } else { | ||
| 994 | len = Z_STRLEN_P(backup); | ||
| 995 | user = Z_STRVAL_P(backup); | ||
| 996 | } | ||
| 997 | |||
| 998 | if (prefix_len && prefix_len <= len) { | ||
| 999 | if (strncmp(prefix, user, prefix_len)==0) { | ||
| 1000 | prefix = ""; | ||
| 1001 | len -= prefix_len; | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | if (postfix_len && postfix_len <= len) { | ||
| 1006 | if (strncmp(postfix, user+len-postfix_len, postfix_len)==0) { | ||
| 1007 | postfix = ""; | ||
| 1008 | } | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | MAKE_STD_ZVAL(my_user); | ||
| 1012 | my_user->type = IS_STRING; | ||
| 1013 | my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); | ||
| 1014 | |||
| 1015 | /* XXX: memory_leak? */ | ||
| 1016 | *arg = my_user; | ||
| 1017 | |||
| 1018 | SDEBUG("function: %s - user: %s", ih->name, user); | ||
| 1019 | |||
| 1020 | return (0); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | static int suhosin_php_body_write(const char *str, uint str_length TSRMLS_DC) | ||
| 1024 | { | ||
| 1025 | #define P_META_ROBOTS "<meta name=\"ROBOTS\" content=\"NOINDEX,NOFOLLOW,NOARCHIVE\" />" | ||
| 1026 | #define S_META_ROBOTS "<meta name=\"ROBOTS\" content=\"NOINDEX,FOLLOW,NOARCHIVE\" />" | ||
| 1027 | |||
| 1028 | SDEBUG("bw: %s", str); | ||
| 1029 | |||
| 1030 | if ((str_length == sizeof("</head>\n")-1) && (strcmp(str, "</head>\n")==0)) { | ||
| 1031 | SUHOSIN_G(old_php_body_write)(S_META_ROBOTS, sizeof(S_META_ROBOTS)-1 TSRMLS_CC); | ||
| 1032 | OG(php_body_write) = SUHOSIN_G(old_php_body_write); | ||
| 1033 | return SUHOSIN_G(old_php_body_write)(str, str_length TSRMLS_CC); | ||
| 1034 | } else if ((str_length == sizeof(P_META_ROBOTS)-1) && (strcmp(str, P_META_ROBOTS)==0)) { | ||
| 1035 | return str_length; | ||
| 1036 | } | ||
| 1037 | return SUHOSIN_G(old_php_body_write)(str, str_length TSRMLS_CC); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | static int ih_phpinfo(IH_HANDLER_PARAMS) | ||
| 1041 | { | ||
| 1042 | int argc = ZEND_NUM_ARGS(); | ||
| 1043 | long flag; | ||
| 1044 | |||
| 1045 | if (zend_parse_parameters(argc TSRMLS_CC, "|l", &flag) == FAILURE) { | ||
| 1046 | RETVAL_FALSE; | ||
| 1047 | return (1); | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | if(!argc) { | ||
| 1051 | flag = PHP_INFO_ALL; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | /* Andale! Andale! Yee-Hah! */ | ||
| 1055 | php_start_ob_buffer(NULL, 4096, 0 TSRMLS_CC); | ||
| 1056 | if (!sapi_module.phpinfo_as_text) { | ||
| 1057 | SUHOSIN_G(old_php_body_write) = OG(php_body_write); | ||
| 1058 | OG(php_body_write) = suhosin_php_body_write; | ||
| 1059 | } | ||
| 1060 | php_print_info(flag TSRMLS_CC); | ||
| 1061 | php_end_ob_buffer(1, 0 TSRMLS_CC); | ||
| 1062 | |||
| 1063 | RETVAL_TRUE; | ||
| 1064 | return (1); | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | |||
| 1068 | static int ih_function_exists(IH_HANDLER_PARAMS) | ||
| 1069 | { | ||
| 1070 | zval **function_name; | ||
| 1071 | zend_function *func; | ||
| 1072 | char *lcname; | ||
| 1073 | zend_bool retval; | ||
| 1074 | int func_name_len; | ||
| 1075 | |||
| 1076 | if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) { | ||
| 1077 | ZEND_WRONG_PARAM_COUNT(); | ||
| 1078 | } | ||
| 1079 | convert_to_string_ex(function_name); | ||
| 1080 | func_name_len = Z_STRLEN_PP(function_name); | ||
| 1081 | lcname = estrndup(Z_STRVAL_PP(function_name), func_name_len); | ||
| 1082 | zend_str_tolower(lcname, func_name_len); | ||
| 1083 | |||
| 1084 | retval = (zend_hash_find(EG(function_table), lcname, func_name_len+1, (void **)&func) == SUCCESS); | ||
| 1085 | |||
| 1086 | efree(lcname); | ||
| 1087 | |||
| 1088 | /* | ||
| 1089 | * A bit of a hack, but not a bad one: we see if the handler of the function | ||
| 1090 | * is actually one that displays "function is disabled" message. | ||
| 1091 | */ | ||
| 1092 | if (retval && func->type == ZEND_INTERNAL_FUNCTION && | ||
| 1093 | func->internal_function.handler == zif_display_disabled_function) { | ||
| 1094 | retval = 0; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | /* Now check if function is forbidden by Suhosin */ | ||
| 1098 | if (SUHOSIN_G(in_code_type) == SUHOSIN_EVAL) { | ||
| 1099 | if (SUHOSIN_G(eval_whitelist) != NULL) { | ||
| 1100 | if (!zend_hash_exists(SUHOSIN_G(eval_whitelist), lcname, func_name_len+1)) { | ||
| 1101 | retval = 0; | ||
| 1102 | } | ||
| 1103 | } else if (SUHOSIN_G(eval_blacklist) != NULL) { | ||
| 1104 | if (zend_hash_exists(SUHOSIN_G(eval_blacklist), lcname, func_name_len+1)) { | ||
| 1105 | retval = 0; | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | if (SUHOSIN_G(func_whitelist) != NULL) { | ||
| 1111 | if (!zend_hash_exists(SUHOSIN_G(func_whitelist), lcname, func_name_len+1)) { | ||
| 1112 | retval = 0; | ||
| 1113 | } | ||
| 1114 | } else if (SUHOSIN_G(func_blacklist) != NULL) { | ||
| 1115 | if (zend_hash_exists(SUHOSIN_G(func_blacklist), lcname, func_name_len+1)) { | ||
| 1116 | retval = 0; | ||
| 1117 | } | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | RETVAL_BOOL(retval); | ||
| 1121 | return (1); | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | /* MT RAND FUNCTIONS */ | ||
| 1125 | |||
| 1126 | /* | ||
| 1127 | The following php_mt_...() functions are based on a C++ class MTRand by | ||
| 1128 | Richard J. Wagner. For more information see the web page at | ||
| 1129 | http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html | ||
| 1130 | |||
| 1131 | Mersenne Twister random number generator -- a C++ class MTRand | ||
| 1132 | Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus | ||
| 1133 | Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com | ||
| 1134 | |||
| 1135 | The Mersenne Twister is an algorithm for generating random numbers. It | ||
| 1136 | was designed with consideration of the flaws in various other generators. | ||
| 1137 | The period, 2^19937-1, and the order of equidistribution, 623 dimensions, | ||
| 1138 | are far greater. The generator is also fast; it avoids multiplication and | ||
| 1139 | division, and it benefits from caches and pipelines. For more information | ||
| 1140 | see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html | ||
| 1141 | |||
| 1142 | Reference | ||
| 1143 | M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally | ||
| 1144 | Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on | ||
| 1145 | Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. | ||
| 1146 | |||
| 1147 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, | ||
| 1148 | Copyright (C) 2000 - 2003, Richard J. Wagner | ||
| 1149 | All rights reserved. | ||
| 1150 | |||
| 1151 | Redistribution and use in source and binary forms, with or without | ||
| 1152 | modification, are permitted provided that the following conditions | ||
| 1153 | are met: | ||
| 1154 | |||
| 1155 | 1. Redistributions of source code must retain the above copyright | ||
| 1156 | notice, this list of conditions and the following disclaimer. | ||
| 1157 | |||
| 1158 | 2. Redistributions in binary form must reproduce the above copyright | ||
| 1159 | notice, this list of conditions and the following disclaimer in the | ||
| 1160 | documentation and/or other materials provided with the distribution. | ||
| 1161 | |||
| 1162 | 3. The names of its contributors may not be used to endorse or promote | ||
| 1163 | products derived from this software without specific prior written | ||
| 1164 | permission. | ||
| 1165 | |||
| 1166 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 1167 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 1168 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 1169 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| 1170 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
| 1171 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
| 1172 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
| 1173 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
| 1174 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
| 1175 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
| 1176 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 1177 | |||
| 1178 | The original code included the following notice: | ||
| 1179 | |||
| 1180 | When you use this, send an email to: matumoto@math.keio.ac.jp | ||
| 1181 | with an appropriate reference to your work. | ||
| 1182 | |||
| 1183 | It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu | ||
| 1184 | when you write. | ||
| 1185 | */ | ||
| 1186 | |||
| 1187 | #define N 624 /* length of state vector */ | ||
| 1188 | #define M (397) /* a period parameter */ | ||
| 1189 | #define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ | ||
| 1190 | #define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ | ||
| 1191 | #define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ | ||
| 1192 | #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ | ||
| 1193 | |||
| 1194 | #define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(u))) & 0x9908b0dfU)) | ||
| 1195 | |||
| 1196 | /* {{{ php_mt_initialize | ||
| 1197 | */ | ||
| 1198 | static inline void suhosin_mt_initialize(php_uint32 seed, php_uint32 *state) | ||
| 1199 | { | ||
| 1200 | /* Initialize generator state with seed | ||
| 1201 | See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. | ||
| 1202 | In previous versions, most significant bits (MSBs) of the seed affect | ||
| 1203 | only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */ | ||
| 1204 | |||
| 1205 | register php_uint32 *s = state; | ||
| 1206 | register php_uint32 *r = state; | ||
| 1207 | register int i = 1; | ||
| 1208 | |||
| 1209 | *s++ = seed & 0xffffffffU; | ||
| 1210 | for( ; i < N; ++i ) { | ||
| 1211 | *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU; | ||
| 1212 | r++; | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | /* }}} */ | ||
| 1216 | |||
| 1217 | static inline void suhosin_mt_init_by_array(php_uint32 *key, int keylen, php_uint32 *state) | ||
| 1218 | { | ||
| 1219 | int i, j, k; | ||
| 1220 | suhosin_mt_initialize(19650218U, state); | ||
| 1221 | i = 1; j = 0; | ||
| 1222 | k = (N > keylen ? N : keylen); | ||
| 1223 | for (; k; k--) { | ||
| 1224 | state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525U)) + key[j] + j; | ||
| 1225 | i++; j = (j+1) % keylen; | ||
| 1226 | if (i >= N) { state[0] = state[N-1]; i=1; } | ||
| 1227 | } | ||
| 1228 | for (k=N-1; k; k--) { | ||
| 1229 | state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941U)) - i; | ||
| 1230 | i++; | ||
| 1231 | if (i >= N) { state[0] = state[N-1]; i=1; } | ||
| 1232 | } | ||
| 1233 | state[0] = 0x80000000U; | ||
| 1234 | } | ||
| 1235 | /* }}} */ | ||
| 1236 | |||
| 1237 | |||
| 1238 | /* {{{ suhosin_mt_reload | ||
| 1239 | */ | ||
| 1240 | static inline void suhosin_mt_reload(php_uint32 *state, php_uint32 **next, int *left) | ||
| 1241 | { | ||
| 1242 | /* Generate N new values in state | ||
| 1243 | Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) */ | ||
| 1244 | |||
| 1245 | register php_uint32 *p = state; | ||
| 1246 | register int i; | ||
| 1247 | |||
| 1248 | for (i = N - M; i--; ++p) | ||
| 1249 | *p = twist(p[M], p[0], p[1]); | ||
| 1250 | for (i = M; --i; ++p) | ||
| 1251 | *p = twist(p[M-N], p[0], p[1]); | ||
| 1252 | *p = twist(p[M-N], p[0], state[0]); | ||
| 1253 | *left = N; | ||
| 1254 | *next = state; | ||
| 1255 | } | ||
| 1256 | /* }}} */ | ||
| 1257 | |||
| 1258 | /* {{{ suhosin_mt_srand | ||
| 1259 | */ | ||
| 1260 | static void suhosin_mt_srand(php_uint32 seed TSRMLS_DC) | ||
| 1261 | { | ||
| 1262 | /* Seed the generator with a simple uint32 */ | ||
| 1263 | suhosin_mt_initialize(seed, SUHOSIN_G(mt_state)); | ||
| 1264 | suhosin_mt_reload(SUHOSIN_G(mt_state), &SUHOSIN_G(mt_next), &SUHOSIN_G(mt_left)); | ||
| 1265 | |||
| 1266 | /* Seed only once */ | ||
| 1267 | SUHOSIN_G(mt_is_seeded) = 1; | ||
| 1268 | } | ||
| 1269 | /* }}} */ | ||
| 1270 | |||
| 1271 | /* {{{ suhosin_mt_rand | ||
| 1272 | */ | ||
| 1273 | static php_uint32 suhosin_mt_rand(TSRMLS_D) | ||
| 1274 | { | ||
| 1275 | /* Pull a 32-bit integer from the generator state | ||
| 1276 | Every other access function simply transforms the numbers extracted here */ | ||
| 1277 | |||
| 1278 | register php_uint32 s1; | ||
| 1279 | |||
| 1280 | if (SUHOSIN_G(mt_left) == 0) { | ||
| 1281 | suhosin_mt_reload(SUHOSIN_G(mt_state), &SUHOSIN_G(mt_next), &SUHOSIN_G(mt_left)); | ||
| 1282 | } | ||
| 1283 | --SUHOSIN_G(mt_left); | ||
| 1284 | |||
| 1285 | s1 = *SUHOSIN_G(mt_next)++; | ||
| 1286 | s1 ^= (s1 >> 11); | ||
| 1287 | s1 ^= (s1 << 7) & 0x9d2c5680U; | ||
| 1288 | s1 ^= (s1 << 15) & 0xefc60000U; | ||
| 1289 | return ( s1 ^ (s1 >> 18) ); | ||
| 1290 | } | ||
| 1291 | /* }}} */ | ||
| 1292 | |||
| 1293 | /* {{{ suhosin_gen_entropy | ||
| 1294 | */ | ||
| 1295 | static void suhosin_gen_entropy(php_uint32 *seedbuf TSRMLS_DC) | ||
| 1296 | { | ||
| 1297 | /* On a modern OS code, stack and heap base are randomized */ | ||
| 1298 | unsigned long code_value = (unsigned long)suhosin_gen_entropy; | ||
| 1299 | unsigned long stack_value = (unsigned long)&code_value; | ||
| 1300 | unsigned long heap_value = (unsigned long)SUHOSIN_G(r_state); | ||
| 1301 | suhosin_SHA256_CTX context; | ||
| 1302 | |||
| 1303 | code_value ^= code_value >> 32; | ||
| 1304 | stack_value ^= stack_value >> 32; | ||
| 1305 | heap_value ^= heap_value >> 32; | ||
| 1306 | |||
| 1307 | seedbuf[0] = code_value; | ||
| 1308 | seedbuf[1] = stack_value; | ||
| 1309 | seedbuf[2] = heap_value; | ||
| 1310 | seedbuf[3] = time(0); | ||
| 1311 | #ifdef PHP_WIN32 | ||
| 1312 | seedbuf[4] = GetCurrentProcessId(); | ||
| 1313 | #else | ||
| 1314 | seedbuf[4] = getpid(); | ||
| 1315 | #endif | ||
| 1316 | seedbuf[5] = (php_uint32) 0x7fffffff * php_combined_lcg(TSRMLS_C); | ||
| 1317 | |||
| 1318 | suhosin_SHA256Init(&context); | ||
| 1319 | suhosin_SHA256Update(&context, (void *) seedbuf, sizeof(php_uint32) * 6); | ||
| 1320 | suhosin_SHA256Final(seedbuf, &context); | ||
| 1321 | } | ||
| 1322 | /* }}} */ | ||
| 1323 | |||
| 1324 | |||
| 1325 | /* {{{ suhosin_srand_auto | ||
| 1326 | */ | ||
| 1327 | static void suhosin_srand_auto(TSRMLS_D) | ||
| 1328 | { | ||
| 1329 | php_uint32 seed[8]; | ||
| 1330 | suhosin_gen_entropy(&seed[0] TSRMLS_CC); | ||
| 1331 | |||
| 1332 | suhosin_mt_init_by_array(seed, 8, SUHOSIN_G(r_state)); | ||
| 1333 | suhosin_mt_reload(SUHOSIN_G(r_state), &SUHOSIN_G(r_next), &SUHOSIN_G(r_left)); | ||
| 1334 | |||
| 1335 | /* Seed only once */ | ||
| 1336 | SUHOSIN_G(r_is_seeded) = 1; | ||
| 1337 | } | ||
| 1338 | /* }}} */ | ||
| 1339 | |||
| 1340 | /* {{{ suhosin_mt_srand_auto | ||
| 1341 | */ | ||
| 1342 | static void suhosin_mt_srand_auto(TSRMLS_D) | ||
| 1343 | { | ||
| 1344 | php_uint32 seed[8]; | ||
| 1345 | suhosin_gen_entropy(&seed[0] TSRMLS_CC); | ||
| 1346 | |||
| 1347 | suhosin_mt_init_by_array(seed, 8, SUHOSIN_G(mt_state)); | ||
| 1348 | suhosin_mt_reload(SUHOSIN_G(mt_state), &SUHOSIN_G(mt_next), &SUHOSIN_G(mt_left)); | ||
| 1349 | |||
| 1350 | /* Seed only once */ | ||
| 1351 | SUHOSIN_G(mt_is_seeded) = 1; | ||
| 1352 | } | ||
| 1353 | /* }}} */ | ||
| 1354 | |||
| 1355 | |||
| 1356 | /* {{{ suhosin_srand | ||
| 1357 | */ | ||
| 1358 | static void suhosin_srand(php_uint32 seed TSRMLS_DC) | ||
| 1359 | { | ||
| 1360 | /* Seed the generator with a simple uint32 */ | ||
| 1361 | suhosin_mt_initialize(seed+0x12345, SUHOSIN_G(r_state)); | ||
| 1362 | suhosin_mt_reload(SUHOSIN_G(r_state), &SUHOSIN_G(r_next), &SUHOSIN_G(r_left)); | ||
| 1363 | |||
| 1364 | /* Seed only once */ | ||
| 1365 | SUHOSIN_G(r_is_seeded) = 1; | ||
| 1366 | } | ||
| 1367 | /* }}} */ | ||
| 1368 | |||
| 1369 | /* {{{ suhosin_mt_rand | ||
| 1370 | */ | ||
| 1371 | static php_uint32 suhosin_rand(TSRMLS_D) | ||
| 1372 | { | ||
| 1373 | /* Pull a 32-bit integer from the generator state | ||
| 1374 | Every other access function simply transforms the numbers extracted here */ | ||
| 1375 | |||
| 1376 | register php_uint32 s1; | ||
| 1377 | |||
| 1378 | if (SUHOSIN_G(r_left) == 0) { | ||
| 1379 | suhosin_mt_reload(SUHOSIN_G(r_state), &SUHOSIN_G(r_next), &SUHOSIN_G(r_left)); | ||
| 1380 | } | ||
| 1381 | --SUHOSIN_G(r_left); | ||
| 1382 | |||
| 1383 | s1 = *SUHOSIN_G(r_next)++; | ||
| 1384 | s1 ^= (s1 >> 11); | ||
| 1385 | s1 ^= (s1 << 7) & 0x9d2c5680U; | ||
| 1386 | s1 ^= (s1 << 15) & 0xefc60000U; | ||
| 1387 | return ( s1 ^ (s1 >> 18) ); | ||
| 1388 | } | ||
| 1389 | /* }}} */ | ||
| 1390 | |||
| 1391 | static int ih_srand(IH_HANDLER_PARAMS) | ||
| 1392 | { | ||
| 1393 | int argc = ZEND_NUM_ARGS(); | ||
| 1394 | long seed; | ||
| 1395 | |||
| 1396 | if (zend_parse_parameters(argc TSRMLS_CC, "|l", &seed) == FAILURE || SUHOSIN_G(srand_ignore)) { | ||
| 1397 | RETVAL_FALSE; | ||
| 1398 | return (1); | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | if (argc == 0) { | ||
| 1402 | suhosin_srand_auto(TSRMLS_C); | ||
| 1403 | } else { | ||
| 1404 | suhosin_srand(seed TSRMLS_CC); | ||
| 1405 | } | ||
| 1406 | RETVAL_TRUE; | ||
| 1407 | return (1); | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | static int ih_mt_srand(IH_HANDLER_PARAMS) | ||
| 1411 | { | ||
| 1412 | int argc = ZEND_NUM_ARGS(); | ||
| 1413 | long seed; | ||
| 1414 | |||
| 1415 | if (zend_parse_parameters(argc TSRMLS_CC, "|l", &seed) == FAILURE || SUHOSIN_G(mt_srand_ignore)) { | ||
| 1416 | RETVAL_FALSE; | ||
| 1417 | return (1); | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | if (argc == 0) { | ||
| 1421 | suhosin_mt_srand_auto(TSRMLS_C); | ||
| 1422 | } else { | ||
| 1423 | suhosin_mt_srand(seed TSRMLS_CC); | ||
| 1424 | } | ||
| 1425 | RETVAL_TRUE; | ||
| 1426 | return (1); | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static int ih_mt_rand(IH_HANDLER_PARAMS) | ||
| 1430 | { | ||
| 1431 | int argc = ZEND_NUM_ARGS(); | ||
| 1432 | long min; | ||
| 1433 | long max; | ||
| 1434 | long number; | ||
| 1435 | |||
| 1436 | if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) { | ||
| 1437 | return (1); | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | if (!SUHOSIN_G(mt_is_seeded)) { | ||
| 1441 | suhosin_mt_srand_auto(TSRMLS_C); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | number = (long) (suhosin_mt_rand(TSRMLS_C) >> 1); | ||
| 1445 | if (argc == 2) { | ||
| 1446 | RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | RETURN_LONG(number); | ||
| 1450 | } | ||
| 1451 | |||
| 1452 | static int ih_rand(IH_HANDLER_PARAMS) | ||
| 1453 | { | ||
| 1454 | int argc = ZEND_NUM_ARGS(); | ||
| 1455 | long min; | ||
| 1456 | long max; | ||
| 1457 | long number; | ||
| 1458 | |||
| 1459 | if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE) { | ||
| 1460 | return (1); | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | if (!SUHOSIN_G(r_is_seeded)) { | ||
| 1464 | suhosin_srand_auto(TSRMLS_C); | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | number = (long) (suhosin_rand(TSRMLS_C) >> 1); | ||
| 1468 | if (argc == 2) { | ||
| 1469 | RAND_RANGE(number, min, max, PHP_MT_RAND_MAX); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | RETURN_LONG(number); | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | static int ih_getrandmax(IH_HANDLER_PARAMS) | ||
| 1476 | { | ||
| 1477 | int argc = ZEND_NUM_ARGS(); | ||
| 1478 | |||
| 1479 | if (argc != 0) { | ||
| 1480 | ZEND_WRONG_PARAM_COUNT(); | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | RETVAL_LONG(PHP_MT_RAND_MAX); | ||
| 1484 | return (1); | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | internal_function_handler ihandlers[] = { | ||
| 1488 | { "preg_replace", ih_preg_replace, NULL, NULL, NULL }, | ||
| 1489 | { "mail", ih_mail, NULL, NULL, NULL }, | ||
| 1490 | { "symlink", ih_symlink, NULL, NULL, NULL }, | ||
| 1491 | { "phpinfo", ih_phpinfo, NULL, NULL, NULL }, | ||
| 1492 | |||
| 1493 | { "srand", ih_srand, NULL, NULL, NULL }, | ||
| 1494 | { "mt_srand", ih_mt_srand, NULL, NULL, NULL }, | ||
| 1495 | { "rand", ih_rand, NULL, NULL, NULL }, | ||
| 1496 | { "mt_rand", ih_mt_rand, NULL, NULL, NULL }, | ||
| 1497 | { "getrandmax", ih_getrandmax, NULL, NULL, NULL }, | ||
| 1498 | { "mt_getrandmax", ih_getrandmax, NULL, NULL, NULL }, | ||
| 1499 | |||
| 1500 | { "ocilogon", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1501 | { "ociplogon", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1502 | { "ocinlogon", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1503 | { "oci_connect", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1504 | { "oci_pconnect", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1505 | { "oci_new_connect", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1506 | |||
| 1507 | { "fbsql_change_user", ih_fixusername, (void *)1, NULL, NULL }, | ||
| 1508 | { "fbsql_connect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1509 | { "fbsql_pconnect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1510 | |||
| 1511 | { "function_exists", ih_function_exists, NULL, NULL, NULL }, | ||
| 1512 | |||
| 1513 | { "ifx_connect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1514 | { "ifx_pconnect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1515 | |||
| 1516 | { "ibase_connect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1517 | { "ibase_pconnect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1518 | |||
| 1519 | { "maxdb", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1520 | { "maxdb_change_user", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1521 | { "maxdb_connect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1522 | { "maxdb_pconnect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1523 | { "maxdb_real_connect", ih_fixusername, (void *)3, NULL, NULL }, | ||
| 1524 | |||
| 1525 | { "mssql_connect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1526 | { "mssql_pconnect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1527 | |||
| 1528 | { "mysql_query", ih_querycheck, (void *)1, (void *)1, NULL }, | ||
| 1529 | { "mysql_db_query", ih_querycheck, (void *)2, (void *)1, NULL }, | ||
| 1530 | { "mysql_unbuffered_query", ih_querycheck, (void *)1, (void *)1, NULL }, | ||
| 1531 | { "mysqli_query", ih_querycheck, (void *)2, (void *)1, NULL }, | ||
| 1532 | { "mysqli_real_query", ih_querycheck, (void *)2, (void *)1, NULL }, | ||
| 1533 | { "mysqli_send_query", ih_querycheck, (void *)2, (void *)1, NULL }, | ||
| 1534 | { "mysqli_master_query", ih_querycheck, (void *)2, (void *)1, NULL }, | ||
| 1535 | { "mysqli_slave_query", ih_querycheck, (void *)2, (void *)1, NULL }, | ||
| 1536 | |||
| 1537 | { "mysqli", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1538 | { "mysql_connect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1539 | { "mysql_pconnect", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1540 | { "mysqli_change_user", ih_fixusername, (void *)2, NULL, NULL }, | ||
| 1541 | { "mysql_real_connect", ih_fixusername, (void *)3, NULL, NULL }, | ||
| 1542 | { NULL, NULL, NULL, NULL, NULL } | ||
| 1543 | }; | ||
| 1544 | |||
| 1545 | #define FUNCTION_WARNING() zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C)); | ||
| 1546 | |||
| 1547 | /* {{{ void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) | ||
| 1548 | * This function provides a hook for internal execution */ | ||
| 1549 | static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) | ||
| 1550 | { | ||
| 1551 | char *lcname; | ||
| 1552 | int function_name_strlen, free_lcname = 0; | ||
| 1553 | zval *return_value; | ||
| 1554 | zend_class_entry *ce = NULL; | ||
| 1555 | int ht; | ||
| 1556 | internal_function_handler *ih; | ||
| 1557 | |||
| 1558 | #ifdef ZEND_ENGINE_2 | ||
| 1559 | ce = ((zend_internal_function *) execute_data_ptr->function_state.function)->scope; | ||
| 1560 | #endif | ||
| 1561 | lcname = ((zend_internal_function *) execute_data_ptr->function_state.function)->function_name; | ||
| 1562 | function_name_strlen = strlen(lcname); | ||
| 1563 | |||
| 1564 | /* handle methodcalls correctly */ | ||
| 1565 | if (ce != NULL) { | ||
| 1566 | char *tmp = (char *) emalloc(function_name_strlen + 2 + ce->name_length + 1); | ||
| 1567 | memcpy(tmp, ce->name, ce->name_length); | ||
| 1568 | memcpy(tmp+ce->name_length, "::", 2); | ||
| 1569 | memcpy(tmp+ce->name_length+2, lcname, function_name_strlen); | ||
| 1570 | lcname = tmp; | ||
| 1571 | free_lcname = 1; | ||
| 1572 | function_name_strlen += ce->name_length + 2; | ||
| 1573 | lcname[function_name_strlen] = 0; | ||
| 1574 | zend_str_tolower(lcname, function_name_strlen); | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | #ifdef ZEND_ENGINE_2 | ||
| 1578 | return_value = (*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr; | ||
| 1579 | #else | ||
| 1580 | return_value = execute_data_ptr->Ts[execute_data_ptr->opline->result.u.var].var.ptr; | ||
| 1581 | #endif | ||
| 1582 | ht = execute_data_ptr->opline->extended_value; | ||
| 1583 | |||
| 1584 | SDEBUG("function: %s", lcname); | ||
| 1585 | |||
| 1586 | if (SUHOSIN_G(in_code_type) == SUHOSIN_EVAL) { | ||
| 1587 | |||
| 1588 | if (SUHOSIN_G(eval_whitelist) != NULL) { | ||
| 1589 | if (!zend_hash_exists(SUHOSIN_G(eval_whitelist), lcname, function_name_strlen+1)) { | ||
| 1590 | suhosin_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname); | ||
| 1591 | goto execute_internal_bailout; | ||
| 1592 | } | ||
| 1593 | } else if (SUHOSIN_G(eval_blacklist) != NULL) { | ||
| 1594 | if (zend_hash_exists(SUHOSIN_G(eval_blacklist), lcname, function_name_strlen+1)) { | ||
| 1595 | suhosin_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname); | ||
| 1596 | goto execute_internal_bailout; | ||
| 1597 | } | ||
| 1598 | } | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | if (SUHOSIN_G(func_whitelist) != NULL) { | ||
| 1602 | if (!zend_hash_exists(SUHOSIN_G(func_whitelist), lcname, function_name_strlen+1)) { | ||
| 1603 | suhosin_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname); | ||
| 1604 | goto execute_internal_bailout; | ||
| 1605 | } | ||
| 1606 | } else if (SUHOSIN_G(func_blacklist) != NULL) { | ||
| 1607 | if (zend_hash_exists(SUHOSIN_G(func_blacklist), lcname, function_name_strlen+1)) { | ||
| 1608 | suhosin_log(S_EXECUTOR, "function within blacklist called: %s()", lcname); | ||
| 1609 | goto execute_internal_bailout; | ||
| 1610 | } | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | if (zend_hash_find(&ihandler_table, lcname, function_name_strlen+1, (void **)&ih) == SUCCESS) { | ||
| 1614 | |||
| 1615 | int retval = 0; | ||
| 1616 | void *handler = ((zend_internal_function *) execute_data_ptr->function_state.function)->handler; | ||
| 1617 | |||
| 1618 | if (handler != ZEND_FN(display_disabled_function)) { | ||
| 1619 | retval = ih->handler(IH_HANDLER_PARAM_PASSTHRU); | ||
| 1620 | } | ||
| 1621 | |||
| 1622 | if (retval == 0) { | ||
| 1623 | old_execute_internal(execute_data_ptr, return_value_used TSRMLS_CC); | ||
| 1624 | } | ||
| 1625 | } else { | ||
| 1626 | old_execute_internal(execute_data_ptr, return_value_used TSRMLS_CC); | ||
| 1627 | } | ||
| 1628 | if (free_lcname == 1) { | ||
| 1629 | efree(lcname); | ||
| 1630 | } | ||
| 1631 | return; | ||
| 1632 | execute_internal_bailout: | ||
| 1633 | if (free_lcname == 1) { | ||
| 1634 | efree(lcname); | ||
| 1635 | } | ||
| 1636 | FUNCTION_WARNING() | ||
| 1637 | suhosin_bailout(TSRMLS_C); | ||
| 1638 | } | ||
| 1639 | /* }}} */ | ||
| 1640 | |||
| 1641 | |||
| 1642 | /* {{{ int function_lookup(zend_extension *extension) | ||
| 1643 | */ | ||
| 1644 | static int function_lookup(zend_extension *extension) | ||
| 1645 | { | ||
| 1646 | if (zo_set_oe_ex != NULL) { | ||
| 1647 | return ZEND_HASH_APPLY_STOP; | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | if (extension->handle != NULL) { | ||
| 1651 | |||
| 1652 | zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(extension->handle, "zend_optimizer_set_oe_ex"); | ||
| 1653 | |||
| 1654 | } | ||
| 1655 | |||
| 1656 | return 0; | ||
| 1657 | } | ||
| 1658 | /* }}} */ | ||
| 1659 | |||
| 1660 | |||
| 1661 | /* {{{ void suhosin_hook_execute() | ||
| 1662 | */ | ||
| 1663 | void suhosin_hook_execute(TSRMLS_D) | ||
| 1664 | { | ||
| 1665 | internal_function_handler *ih; | ||
| 1666 | |||
| 1667 | old_execute = zend_execute; | ||
| 1668 | zend_execute = suhosin_execute; | ||
| 1669 | |||
| 1670 | /* old_compile_file = zend_compile_file; | ||
| 1671 | zend_compile_file = suhosin_compile_file; */ | ||
| 1672 | |||
| 1673 | if (zo_set_oe_ex == NULL) { | ||
| 1674 | zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(NULL, "zend_optimizer_set_oe_ex"); | ||
| 1675 | } | ||
| 1676 | if (zo_set_oe_ex == NULL) { | ||
| 1677 | zend_llist_apply(&zend_extensions, (llist_apply_func_t)function_lookup TSRMLS_CC); | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | if (zo_set_oe_ex != NULL) { | ||
| 1681 | old_execute_ZO = zo_set_oe_ex(suhosin_execute_ZO); | ||
| 1682 | } | ||
| 1683 | |||
| 1684 | old_execute_internal = zend_execute_internal; | ||
| 1685 | if (old_execute_internal == NULL) { | ||
| 1686 | old_execute_internal = execute_internal; | ||
| 1687 | } | ||
| 1688 | zend_execute_internal = suhosin_execute_internal; | ||
| 1689 | /* register internal function handlers */ | ||
| 1690 | zend_hash_init(&ihandler_table, 16, NULL, NULL, 1); | ||
| 1691 | ih = &ihandlers[0]; | ||
| 1692 | while (ih->name) { | ||
| 1693 | zend_hash_add(&ihandler_table, ih->name, strlen(ih->name)+1, ih, sizeof(internal_function_handler), NULL); | ||
| 1694 | ih++; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | |||
| 1698 | /* Add additional protection layer, that SHOULD | ||
| 1699 | catch ZEND_INCLUDE_OR_EVAL *before* the engine tries | ||
| 1700 | to execute */ | ||
| 1701 | #ifdef ZEND_ENGINE_2 | ||
| 1702 | old_zend_stream_open = zend_stream_open_function; | ||
| 1703 | zend_stream_open_function = suhosin_zend_stream_open; | ||
| 1704 | #else | ||
| 1705 | old_zend_open = zend_open; | ||
| 1706 | zend_open = suhosin_zend_open; | ||
| 1707 | #endif | ||
| 1708 | |||
| 1709 | } | ||
| 1710 | /* }}} */ | ||
| 1711 | |||
| 1712 | |||
| 1713 | /* {{{ void suhosin_unhook_execute() | ||
| 1714 | */ | ||
| 1715 | void suhosin_unhook_execute() | ||
| 1716 | { | ||
| 1717 | if (zo_set_oe_ex) { | ||
| 1718 | zo_set_oe_ex(old_execute_ZO); | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | zend_execute = old_execute; | ||
| 1722 | |||
| 1723 | /* zend_compile_file = old_compile_file; */ | ||
| 1724 | |||
| 1725 | if (old_execute_internal == execute_internal) { | ||
| 1726 | old_execute_internal = NULL; | ||
| 1727 | } | ||
| 1728 | zend_execute_internal = old_execute_internal; | ||
| 1729 | zend_hash_clean(&ihandler_table); | ||
| 1730 | |||
| 1731 | /* remove zend_open protection */ | ||
| 1732 | #ifdef ZEND_ENGINE_2 | ||
| 1733 | zend_stream_open_function = old_zend_stream_open; | ||
| 1734 | #else | ||
| 1735 | zend_open = old_zend_open; | ||
| 1736 | #endif | ||
| 1737 | |||
| 1738 | } | ||
| 1739 | /* }}} */ | ||
| 1740 | |||
| 1741 | |||
| 1742 | |||
| 1743 | /* | ||
| 1744 | * Local variables: | ||
| 1745 | * tab-width: 4 | ||
| 1746 | * c-basic-offset: 4 | ||
| 1747 | * End: | ||
| 1748 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 1749 | * vim<600: noet sw=4 ts=4 | ||
| 1750 | */ | ||
diff --git a/header.c b/header.c new file mode 100644 index 0000000..9750232 --- /dev/null +++ b/header.c | |||
| @@ -0,0 +1,353 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: header.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "ext/standard/info.h" | ||
| 30 | #include "ext/standard/url.h" | ||
| 31 | #include "php_suhosin.h" | ||
| 32 | #include "SAPI.h" | ||
| 33 | #include "php_variables.h" | ||
| 34 | |||
| 35 | static int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) = NULL; | ||
| 36 | |||
| 37 | char *suhosin_encrypt_single_cookie(char *name, int name_len, char *value, int value_len, char *key TSRMLS_DC) | ||
| 38 | { | ||
| 39 | char buffer[4096]; | ||
| 40 | char buffer2[4096]; | ||
| 41 | char *buf = buffer, *buf2 = buffer2, *d, *d_url; | ||
| 42 | int l; | ||
| 43 | |||
| 44 | if (name_len > sizeof(buffer)-2) { | ||
| 45 | buf = estrndup(name, name_len); | ||
| 46 | } else { | ||
| 47 | memcpy(buf, name, name_len); | ||
| 48 | buf[name_len] = 0; | ||
| 49 | } | ||
| 50 | |||
| 51 | name_len = php_url_decode(buf, name_len); | ||
| 52 | normalize_varname(buf); | ||
| 53 | name_len = strlen(buf); | ||
| 54 | |||
| 55 | if (SUHOSIN_G(cookie_plainlist)) { | ||
| 56 | if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), buf, name_len+1)) { | ||
| 57 | encrypt_return_plain: | ||
| 58 | if (buf != buffer) { | ||
| 59 | efree(buf); | ||
| 60 | } | ||
| 61 | return estrndup(value, value_len); | ||
| 62 | } | ||
| 63 | } else if (SUHOSIN_G(cookie_cryptlist)) { | ||
| 64 | if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), buf, name_len+1)) { | ||
| 65 | goto encrypt_return_plain; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | if (strlen(value) <= sizeof(buffer2)-2) { | ||
| 70 | memcpy(buf2, value, value_len); | ||
| 71 | buf2[value_len] = 0; | ||
| 72 | } else { | ||
| 73 | buf2 = estrndup(value, value_len); | ||
| 74 | } | ||
| 75 | |||
| 76 | value_len = php_url_decode(buf2, value_len); | ||
| 77 | |||
| 78 | d = suhosin_encrypt_string(buf2, value_len, buf, name_len, key TSRMLS_CC); | ||
| 79 | d_url = php_url_encode(d, strlen(d), &l); | ||
| 80 | efree(d); | ||
| 81 | if (buf != buffer) { | ||
| 82 | efree(buf); | ||
| 83 | } | ||
| 84 | if (buf2 != buffer2) { | ||
| 85 | efree(buf2); | ||
| 86 | } | ||
| 87 | return d_url; | ||
| 88 | } | ||
| 89 | |||
| 90 | char *suhosin_decrypt_single_cookie(char *name, int name_len, char *value, int value_len, char *key, char **where TSRMLS_DC) | ||
| 91 | { | ||
| 92 | char buffer[4096]; | ||
| 93 | char buffer2[4096]; | ||
| 94 | int o_name_len = name_len; | ||
| 95 | char *buf = buffer, *buf2 = buffer2, *d, *d_url; | ||
| 96 | int l; | ||
| 97 | |||
| 98 | if (name_len > sizeof(buffer)-2) { | ||
| 99 | buf = estrndup(name, name_len); | ||
| 100 | } else { | ||
| 101 | memcpy(buf, name, name_len); | ||
| 102 | buf[name_len] = 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | name_len = php_url_decode(buf, name_len); | ||
| 106 | normalize_varname(buf); | ||
| 107 | name_len = strlen(buf); | ||
| 108 | |||
| 109 | if (SUHOSIN_G(cookie_plainlist)) { | ||
| 110 | if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), buf, name_len+1)) { | ||
| 111 | decrypt_return_plain: | ||
| 112 | if (buf != buffer) { | ||
| 113 | efree(buf); | ||
| 114 | } | ||
| 115 | memcpy(*where, name, o_name_len); | ||
| 116 | *where += o_name_len; | ||
| 117 | **where = '='; *where +=1; | ||
| 118 | memcpy(*where, value, value_len); | ||
| 119 | *where += value_len; | ||
| 120 | return *where; | ||
| 121 | } | ||
| 122 | } else if (SUHOSIN_G(cookie_cryptlist)) { | ||
| 123 | if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), buf, name_len+1)) { | ||
| 124 | goto decrypt_return_plain; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | |||
| 129 | if (strlen(value) <= sizeof(buffer2)-2) { | ||
| 130 | memcpy(buf2, value, value_len); | ||
| 131 | buf2[value_len] = 0; | ||
| 132 | } else { | ||
| 133 | buf2 = estrndup(value, value_len); | ||
| 134 | } | ||
| 135 | |||
| 136 | value_len = php_url_decode(buf2, value_len); | ||
| 137 | |||
| 138 | d = suhosin_decrypt_string(buf2, value_len, buf, name_len, key, &l, SUHOSIN_G(cookie_checkraddr) TSRMLS_CC); | ||
| 139 | if (d == NULL) { | ||
| 140 | goto skip_cookie; | ||
| 141 | } | ||
| 142 | d_url = php_url_encode(d, l, &l); | ||
| 143 | efree(d); | ||
| 144 | memcpy(*where, name, o_name_len); | ||
| 145 | *where += o_name_len; | ||
| 146 | **where = '=';*where += 1; | ||
| 147 | memcpy(*where, d_url, l); | ||
| 148 | *where += l; | ||
| 149 | efree(d_url); | ||
| 150 | skip_cookie: | ||
| 151 | if (buf != buffer) { | ||
| 152 | efree(buf); | ||
| 153 | } | ||
| 154 | if (buf2 != buffer2) { | ||
| 155 | efree(buf2); | ||
| 156 | } | ||
| 157 | return *where; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* {{{ suhosin_cookie_decryptor | ||
| 161 | */ | ||
| 162 | char *suhosin_cookie_decryptor(TSRMLS_D) | ||
| 163 | { | ||
| 164 | char *raw_cookie = SG(request_info).cookie_data; | ||
| 165 | char *decrypted, *ret, *var, *val, *tmp; | ||
| 166 | int j; | ||
| 167 | char cryptkey[33]; | ||
| 168 | |||
| 169 | /* | ||
| 170 | if (...deactivated...) { | ||
| 171 | return estrdup(raw_cookie); | ||
| 172 | } | ||
| 173 | */ | ||
| 174 | |||
| 175 | suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC); | ||
| 176 | |||
| 177 | ret = decrypted = emalloc(strlen(raw_cookie)*4+1); | ||
| 178 | raw_cookie = estrdup(raw_cookie); | ||
| 179 | SUHOSIN_G(raw_cookie) = estrdup(raw_cookie); | ||
| 180 | |||
| 181 | |||
| 182 | j = 0; tmp = raw_cookie; | ||
| 183 | while (*tmp) { | ||
| 184 | char *d_url;int varlen; | ||
| 185 | while (*tmp == '\t' || *tmp == ' ') tmp++; | ||
| 186 | var = tmp; | ||
| 187 | while (*tmp && *tmp != ';' && *tmp != '=') tmp++; | ||
| 188 | |||
| 189 | varlen = tmp-var; | ||
| 190 | /*memcpy(decrypted, var, varlen); | ||
| 191 | decrypted += varlen;*/ | ||
| 192 | if (*tmp == 0) break; | ||
| 193 | |||
| 194 | if (*tmp++ == ';') { | ||
| 195 | *decrypted++ = ';'; | ||
| 196 | continue; | ||
| 197 | } | ||
| 198 | |||
| 199 | /**decrypted++ = '=';*/ | ||
| 200 | |||
| 201 | val = tmp; | ||
| 202 | while (*tmp && *tmp != ';') tmp++; | ||
| 203 | |||
| 204 | d_url = suhosin_decrypt_single_cookie(var, varlen, val, tmp-val, (char *)&cryptkey, &decrypted TSRMLS_CC); | ||
| 205 | if (*tmp == ';') { | ||
| 206 | *decrypted++ = ';'; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (*tmp == 0) break; | ||
| 210 | tmp++; | ||
| 211 | } | ||
| 212 | *decrypted++ = 0; | ||
| 213 | ret = erealloc(ret, decrypted-ret); | ||
| 214 | |||
| 215 | SUHOSIN_G(decrypted_cookie) = ret; | ||
| 216 | efree(raw_cookie); | ||
| 217 | |||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | /* }}} */ | ||
| 221 | |||
| 222 | /* {{{ suhosin_header_handler | ||
| 223 | */ | ||
| 224 | int suhosin_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) | ||
| 225 | { | ||
| 226 | int retval = SAPI_HEADER_ADD, i; | ||
| 227 | char *tmp; | ||
| 228 | |||
| 229 | if (!SUHOSIN_G(allow_multiheader) && sapi_header && sapi_header->header) { | ||
| 230 | |||
| 231 | tmp = sapi_header->header; | ||
| 232 | |||
| 233 | for (i=0; i<sapi_header->header_len; i++, tmp++) { | ||
| 234 | if (tmp[0] == 0) { | ||
| 235 | char *fname = get_active_function_name(TSRMLS_C); | ||
| 236 | |||
| 237 | if (!fname) { | ||
| 238 | fname = "unknown"; | ||
| 239 | } | ||
| 240 | |||
| 241 | suhosin_log(S_MISC, "%s() - wanted to send a HTTP header with an ASCII NUL in it", fname); | ||
| 242 | if (!SUHOSIN_G(simulation)) { | ||
| 243 | sapi_header->header_len = i; | ||
| 244 | } | ||
| 245 | } else if ((tmp[0] == '\r' && (tmp[1] != '\n' || i == 0)) || | ||
| 246 | (tmp[0] == '\n' && (i == sapi_header->header_len-1 || i == 0 || (tmp[1] != ' ' && tmp[1] != '\t')))) { | ||
| 247 | char *fname = get_active_function_name(TSRMLS_C); | ||
| 248 | |||
| 249 | if (!fname) { | ||
| 250 | fname = "unknown"; | ||
| 251 | } | ||
| 252 | |||
| 253 | suhosin_log(S_MISC, "%s() - wanted to send multiple HTTP headers at once", fname); | ||
| 254 | if (!SUHOSIN_G(simulation)) { | ||
| 255 | sapi_header->header_len = i; | ||
| 256 | tmp[0] = 0; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | /* Handle a potential cookie */ | ||
| 263 | |||
| 264 | if (SUHOSIN_G(cookie_encrypt) && (strncasecmp("Set-Cookie:", sapi_header->header, sizeof("Set-Cookie:")-1) == 0)) { | ||
| 265 | |||
| 266 | char *start, *end, *rend, *tmp; | ||
| 267 | char *name, *value; | ||
| 268 | int nlen, vlen, len, tlen; | ||
| 269 | char cryptkey[33]; | ||
| 270 | |||
| 271 | suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC); | ||
| 272 | start = estrndup(sapi_header->header, sapi_header->header_len); | ||
| 273 | rend = end = start + sapi_header->header_len; | ||
| 274 | |||
| 275 | tmp = memchr(start, ';', end-start); | ||
| 276 | if (tmp != NULL) { | ||
| 277 | end = tmp; | ||
| 278 | } | ||
| 279 | |||
| 280 | tmp = start + sizeof("Set-Cookie:") - 1; | ||
| 281 | while (tmp < end && tmp[0]==' ') { | ||
| 282 | tmp++; | ||
| 283 | } | ||
| 284 | name = tmp; | ||
| 285 | nlen = end-name; | ||
| 286 | tmp = memchr(name, '=', nlen); | ||
| 287 | if (tmp == NULL) { | ||
| 288 | value = end; | ||
| 289 | } else { | ||
| 290 | value = tmp+1; | ||
| 291 | nlen = tmp-name; | ||
| 292 | } | ||
| 293 | vlen = end-value; | ||
| 294 | |||
| 295 | value = suhosin_encrypt_single_cookie(name, nlen, value, vlen, (char *)&cryptkey TSRMLS_CC); | ||
| 296 | vlen = strlen(value); | ||
| 297 | |||
| 298 | len = sizeof("Set-Cookie: ")-1 + nlen + 1 + vlen + rend-end; | ||
| 299 | tmp = emalloc(len + 1); | ||
| 300 | tlen = sprintf(tmp, "Set-Cookie: %.*s=%s", nlen,name, value); | ||
| 301 | memcpy(tmp + tlen, end, rend-end); | ||
| 302 | tmp[len] = 0; | ||
| 303 | |||
| 304 | efree(sapi_header->header); | ||
| 305 | efree(value); | ||
| 306 | efree(start); | ||
| 307 | |||
| 308 | sapi_header->header = tmp; | ||
| 309 | sapi_header->header_len = len; | ||
| 310 | } | ||
| 311 | |||
| 312 | |||
| 313 | /* If existing call the sapi header handler */ | ||
| 314 | if (orig_header_handler) { | ||
| 315 | retval = orig_header_handler(sapi_header, sapi_headers TSRMLS_CC); | ||
| 316 | } | ||
| 317 | |||
| 318 | return retval; | ||
| 319 | } | ||
| 320 | /* }}} */ | ||
| 321 | |||
| 322 | |||
| 323 | /* {{{ suhosin_hook_header_handler | ||
| 324 | */ | ||
| 325 | void suhosin_hook_header_handler() | ||
| 326 | { | ||
| 327 | if (orig_header_handler == NULL) { | ||
| 328 | orig_header_handler = sapi_module.header_handler; | ||
| 329 | sapi_module.header_handler = suhosin_header_handler; | ||
| 330 | } | ||
| 331 | } | ||
| 332 | /* }}} */ | ||
| 333 | |||
| 334 | /* {{{ suhosin_unhook_header_handler | ||
| 335 | */ | ||
| 336 | void suhosin_unhook_header_handler() | ||
| 337 | { | ||
| 338 | sapi_module.header_handler = orig_header_handler; | ||
| 339 | orig_header_handler = NULL; | ||
| 340 | } | ||
| 341 | /* }}} */ | ||
| 342 | |||
| 343 | |||
| 344 | /* | ||
| 345 | * Local variables: | ||
| 346 | * tab-width: 4 | ||
| 347 | * c-basic-offset: 4 | ||
| 348 | * End: | ||
| 349 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 350 | * vim<600: noet sw=4 ts=4 | ||
| 351 | */ | ||
| 352 | |||
| 353 | |||
diff --git a/ifilter.c b/ifilter.c new file mode 100644 index 0000000..f90173b --- /dev/null +++ b/ifilter.c | |||
| @@ -0,0 +1,732 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: ifilter.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "ext/standard/info.h" | ||
| 30 | #include "php_suhosin.h" | ||
| 31 | #include "php_variables.h" | ||
| 32 | |||
| 33 | |||
| 34 | static void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = NULL; | ||
| 35 | |||
| 36 | #ifdef ZEND_ENGINE_2 | ||
| 37 | #define HASH_HTTP_GET_VARS 0x2095733f | ||
| 38 | #define HASH_HTTP_POST_VARS 0xbfee1265 | ||
| 39 | #define HASH_HTTP_COOKIE_VARS 0xaaca9d99 | ||
| 40 | #define HASH_HTTP_ENV_VARS 0x1fe186a8 | ||
| 41 | #define HASH_HTTP_SERVER_VARS 0xc987afd6 | ||
| 42 | #define HASH_HTTP_SESSION_VARS 0x7aba0d43 | ||
| 43 | #define HASH_HTTP_POST_FILES 0x98eb1ddc | ||
| 44 | #define HASH_HTTP_RAW_POST_DATA 0xdd633fec | ||
| 45 | #else | ||
| 46 | #define HASH_HTTP_GET_VARS 0x8d8645bd | ||
| 47 | #define HASH_HTTP_POST_VARS 0x7c699bf3 | ||
| 48 | #define HASH_HTTP_COOKIE_VARS 0x93ad0d6f | ||
| 49 | #define HASH_HTTP_ENV_VARS 0x84da3016 | ||
| 50 | #define HASH_HTTP_SERVER_VARS 0x6dbf964e | ||
| 51 | #define HASH_HTTP_SESSION_VARS 0x322906f5 | ||
| 52 | #define HASH_HTTP_POST_FILES 0xe4e4ce70 | ||
| 53 | #define HASH_HTTP_RAW_POST_DATA 0xe6137a0e | ||
| 54 | #endif | ||
| 55 | |||
| 56 | |||
| 57 | /* {{{ normalize_varname | ||
| 58 | */ | ||
| 59 | void normalize_varname(char *varname) | ||
| 60 | { | ||
| 61 | char *s=varname, *index=NULL, *indexend=NULL, *p; | ||
| 62 | |||
| 63 | /* overjump leading space */ | ||
| 64 | while (*s == ' ') { | ||
| 65 | s++; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* and remove it */ | ||
| 69 | if (s != varname) { | ||
| 70 | memmove(varname, s, strlen(s)+1); | ||
| 71 | } | ||
| 72 | |||
| 73 | for (p=varname; *p && *p != '['; p++) { | ||
| 74 | switch(*p) { | ||
| 75 | case ' ': | ||
| 76 | case '.': | ||
| 77 | *p='_'; | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | /* find index */ | ||
| 83 | index = strchr(varname, '['); | ||
| 84 | if (index) { | ||
| 85 | index++; | ||
| 86 | s=index; | ||
| 87 | } else { | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* done? */ | ||
| 92 | while (index) { | ||
| 93 | |||
| 94 | while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') { | ||
| 95 | index++; | ||
| 96 | } | ||
| 97 | indexend = strchr(index, ']'); | ||
| 98 | indexend = indexend ? indexend + 1 : index + strlen(index); | ||
| 99 | |||
| 100 | if (s != index) { | ||
| 101 | memmove(s, index, strlen(index)+1); | ||
| 102 | s += indexend-index; | ||
| 103 | } else { | ||
| 104 | s = indexend; | ||
| 105 | } | ||
| 106 | |||
| 107 | if (*s == '[') { | ||
| 108 | s++; | ||
| 109 | index = s; | ||
| 110 | } else { | ||
| 111 | index = NULL; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | *s++='\0'; | ||
| 115 | } | ||
| 116 | /* }}} */ | ||
| 117 | |||
| 118 | static unsigned char suhosin_hexchars[] = "0123456789ABCDEF"; | ||
| 119 | |||
| 120 | static const char suhosin_is_dangerous_char[256] = { | ||
| 121 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 122 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 123 | 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 124 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, | ||
| 125 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 126 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 127 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 128 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 129 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 130 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 131 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 132 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 133 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 134 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 135 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 137 | }; | ||
| 138 | |||
| 139 | /* {{{ suhosin_server_encode | ||
| 140 | */ | ||
| 141 | static void suhosin_server_strip(HashTable *arr, char *key, int klen) | ||
| 142 | { | ||
| 143 | zval **tzval; | ||
| 144 | unsigned char *s, *t; | ||
| 145 | |||
| 146 | if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS && | ||
| 147 | Z_TYPE_PP(tzval) == IS_STRING) { | ||
| 148 | |||
| 149 | s = t = Z_STRVAL_PP(tzval); | ||
| 150 | for (; *t; t++) { | ||
| 151 | if (suhosin_is_dangerous_char[*t]) { | ||
| 152 | *t = '?'; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | Z_STRLEN_PP(tzval) = t-s; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | /* }}} */ | ||
| 159 | |||
| 160 | /* {{{ suhosin_server_encode | ||
| 161 | */ | ||
| 162 | static void suhosin_server_encode(HashTable *arr, char *key, int klen) | ||
| 163 | { | ||
| 164 | zval **tzval; | ||
| 165 | unsigned char *temp = NULL, *t, *newv, *n; | ||
| 166 | int extra = 0; | ||
| 167 | |||
| 168 | if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS && | ||
| 169 | Z_TYPE_PP(tzval) == IS_STRING) { | ||
| 170 | |||
| 171 | temp = Z_STRVAL_PP(tzval); | ||
| 172 | |||
| 173 | t = temp; | ||
| 174 | for (t = temp; *t; t++) { | ||
| 175 | if (suhosin_is_dangerous_char[*t]) { | ||
| 176 | extra += 2; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | /* no extra bytes required */ | ||
| 181 | if (extra == 0) { | ||
| 182 | return; | ||
| 183 | } | ||
| 184 | |||
| 185 | n = newv = emalloc(t - temp + 1 + extra); | ||
| 186 | t = temp; | ||
| 187 | for (t = temp; *t; t++, n++) { | ||
| 188 | if (suhosin_is_dangerous_char[*t]) { | ||
| 189 | *n++ = '%'; | ||
| 190 | *n++ = suhosin_hexchars[*t >> 4]; | ||
| 191 | *n = suhosin_hexchars[*t & 15]; | ||
| 192 | } else { | ||
| 193 | *n = *t; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | *n = 0; | ||
| 197 | |||
| 198 | Z_STRVAL_PP(tzval) = newv; | ||
| 199 | Z_STRLEN_PP(tzval) = n-newv; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | /* }}} */ | ||
| 203 | |||
| 204 | /* {{{ suhosin_register_server_variables | ||
| 205 | */ | ||
| 206 | void suhosin_register_server_variables(zval *track_vars_array TSRMLS_DC) | ||
| 207 | { | ||
| 208 | HashTable *svars; | ||
| 209 | int retval, failure=0; | ||
| 210 | |||
| 211 | orig_register_server_variables(track_vars_array TSRMLS_CC); | ||
| 212 | |||
| 213 | svars = Z_ARRVAL_P(track_vars_array); | ||
| 214 | |||
| 215 | if (!SUHOSIN_G(simulation)) { | ||
| 216 | retval = zend_hash_del_key_or_index(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), HASH_HTTP_GET_VARS, HASH_DEL_INDEX); | ||
| 217 | if (retval == SUCCESS) failure = 1; | ||
| 218 | retval = zend_hash_del_key_or_index(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), HASH_HTTP_POST_VARS, HASH_DEL_INDEX); | ||
| 219 | if (retval == SUCCESS) failure = 1; | ||
| 220 | retval = zend_hash_del_key_or_index(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"), HASH_HTTP_COOKIE_VARS, HASH_DEL_INDEX); | ||
| 221 | if (retval == SUCCESS) failure = 1; | ||
| 222 | retval = zend_hash_del_key_or_index(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), HASH_HTTP_ENV_VARS, HASH_DEL_INDEX); | ||
| 223 | if (retval == SUCCESS) failure = 1; | ||
| 224 | retval = zend_hash_del_key_or_index(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), HASH_HTTP_SERVER_VARS, HASH_DEL_INDEX); | ||
| 225 | if (retval == SUCCESS) failure = 1; | ||
| 226 | retval = zend_hash_del_key_or_index(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), HASH_HTTP_SESSION_VARS, HASH_DEL_INDEX); | ||
| 227 | if (retval == SUCCESS) failure = 1; | ||
| 228 | retval = zend_hash_del_key_or_index(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"), HASH_HTTP_POST_FILES, HASH_DEL_INDEX); | ||
| 229 | if (retval == SUCCESS) failure = 1; | ||
| 230 | retval = zend_hash_del_key_or_index(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), HASH_HTTP_RAW_POST_DATA, HASH_DEL_INDEX); | ||
| 231 | if (retval == SUCCESS) failure = 1; | ||
| 232 | } else { | ||
| 233 | retval = zend_hash_exists(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS")); | ||
| 234 | retval+= zend_hash_exists(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS")); | ||
| 235 | retval+= zend_hash_exists(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS")); | ||
| 236 | retval+= zend_hash_exists(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS")); | ||
| 237 | retval+= zend_hash_exists(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS")); | ||
| 238 | retval+= zend_hash_exists(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS")); | ||
| 239 | retval+= zend_hash_exists(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES")); | ||
| 240 | retval+= zend_hash_exists(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA")); | ||
| 241 | if (retval > 0) failure = 1; | ||
| 242 | } | ||
| 243 | |||
| 244 | if (failure) { | ||
| 245 | suhosin_log(S_VARS, "Attacker tried to overwrite a superglobal through a HTTP header"); | ||
| 246 | } | ||
| 247 | |||
| 248 | if (SUHOSIN_G(raw_cookie)) { | ||
| 249 | zval *z; | ||
| 250 | MAKE_STD_ZVAL(z); | ||
| 251 | ZVAL_STRING(z, SUHOSIN_G(raw_cookie), 1); | ||
| 252 | zend_hash_add(svars, "RAW_HTTP_COOKIE", sizeof("RAW_HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL); | ||
| 253 | } | ||
| 254 | if (SUHOSIN_G(decrypted_cookie)) { | ||
| 255 | zval *z; | ||
| 256 | MAKE_STD_ZVAL(z); | ||
| 257 | ZVAL_STRING(z, SUHOSIN_G(decrypted_cookie), 0); | ||
| 258 | zend_hash_update(svars, "HTTP_COOKIE", sizeof("HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL); | ||
| 259 | SUHOSIN_G(decrypted_cookie) = NULL; | ||
| 260 | } | ||
| 261 | |||
| 262 | if (SUHOSIN_G(server_encode)) { | ||
| 263 | /* suhosin_server_encode(svars, "argv", sizeof("argv")); */ | ||
| 264 | suhosin_server_encode(svars, "REQUEST_URI", sizeof("REQUEST_URI")); | ||
| 265 | suhosin_server_encode(svars, "QUERY_STRING", sizeof("QUERY_STRING")); | ||
| 266 | } | ||
| 267 | if (SUHOSIN_G(server_strip)) { | ||
| 268 | suhosin_server_strip(svars, "PHP_SELF", sizeof("PHP_SELF")); | ||
| 269 | suhosin_server_strip(svars, "PATH_INFO", sizeof("PATH_INFO")); | ||
| 270 | suhosin_server_strip(svars, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED")); | ||
| 271 | } | ||
| 272 | } | ||
| 273 | /* }}} */ | ||
| 274 | |||
| 275 | |||
| 276 | #ifdef ZEND_ENGINE_2 | ||
| 277 | /* Old Input filter */ | ||
| 278 | unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) = NULL; | ||
| 279 | |||
| 280 | /* {{{ suhosin_input_filter_wrapper | ||
| 281 | */ | ||
| 282 | unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) | ||
| 283 | { | ||
| 284 | zend_bool already_scanned = SUHOSIN_G(already_scanned); | ||
| 285 | SUHOSIN_G(already_scanned) = 0; | ||
| 286 | |||
| 287 | if (SUHOSIN_G(do_not_scan)) { | ||
| 288 | if (new_val_len) { | ||
| 289 | *new_val_len = val_len; | ||
| 290 | } | ||
| 291 | return 1; | ||
| 292 | } | ||
| 293 | |||
| 294 | if (!already_scanned) { | ||
| 295 | if (suhosin_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC)==0) { | ||
| 296 | SUHOSIN_G(abort_request)=1; | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | if (new_val_len) { | ||
| 300 | val_len = *new_val_len; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | if (old_input_filter) { | ||
| 304 | return old_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC); | ||
| 305 | } else { | ||
| 306 | return 1; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | #endif | ||
| 310 | |||
| 311 | /* {{{ suhosin_input_filter | ||
| 312 | */ | ||
| 313 | unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) | ||
| 314 | { | ||
| 315 | char *index, *prev_index = NULL; | ||
| 316 | unsigned int var_len, total_len, depth = 0; | ||
| 317 | |||
| 318 | /* Mark that we were called */ | ||
| 319 | SUHOSIN_G(already_scanned) = 1; | ||
| 320 | |||
| 321 | if (new_val_len) { | ||
| 322 | *new_val_len = 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* Drop this variable if the limit was reached */ | ||
| 326 | switch (arg) { | ||
| 327 | case PARSE_GET: | ||
| 328 | if (SUHOSIN_G(no_more_get_variables)) { | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | break; | ||
| 332 | case PARSE_POST: | ||
| 333 | if (SUHOSIN_G(no_more_post_variables)) { | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | break; | ||
| 337 | case PARSE_COOKIE: | ||
| 338 | if (SUHOSIN_G(no_more_cookie_variables)) { | ||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | break; | ||
| 342 | default: /* we do not want to protect parse_str() and friends */ | ||
| 343 | if (new_val_len) { | ||
| 344 | *new_val_len = val_len; | ||
| 345 | } | ||
| 346 | return 1; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* Drop this variable if the limit is now reached */ | ||
| 350 | switch (arg) { | ||
| 351 | case PARSE_GET: | ||
| 352 | if (SUHOSIN_G(max_get_vars) && SUHOSIN_G(max_get_vars) <= SUHOSIN_G(cur_get_vars)) { | ||
| 353 | suhosin_log(S_VARS, "configured GET variable limit exceeded - dropped variable '%s'", var); | ||
| 354 | if (!SUHOSIN_G(simulation)) { | ||
| 355 | SUHOSIN_G(no_more_get_variables) = 1; | ||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | break; | ||
| 360 | case PARSE_COOKIE: | ||
| 361 | if (SUHOSIN_G(max_cookie_vars) && SUHOSIN_G(max_cookie_vars) <= SUHOSIN_G(cur_cookie_vars)) { | ||
| 362 | suhosin_log(S_VARS, "configured COOKIE variable limit exceeded - dropped variable '%s'", var); | ||
| 363 | if (!SUHOSIN_G(simulation)) { | ||
| 364 | SUHOSIN_G(no_more_cookie_variables) = 1; | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | break; | ||
| 369 | case PARSE_POST: | ||
| 370 | if (SUHOSIN_G(max_post_vars) && SUHOSIN_G(max_post_vars) <= SUHOSIN_G(cur_post_vars)) { | ||
| 371 | suhosin_log(S_VARS, "configured POST variable limit exceeded - dropped variable '%s'", var); | ||
| 372 | if (!SUHOSIN_G(simulation)) { | ||
| 373 | SUHOSIN_G(no_more_post_variables) = 1; | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | break; | ||
| 378 | } | ||
| 379 | |||
| 380 | /* Drop this variable if it begins with whitespace which is disallowed */ | ||
| 381 | if (*var == ' ') { | ||
| 382 | if (SUHOSIN_G(disallow_ws)) { | ||
| 383 | suhosin_log(S_VARS, "request variable name begins with disallowed whitespace - dropped variable '%s'", var); | ||
| 384 | if (!SUHOSIN_G(simulation)) { | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | switch (arg) { | ||
| 389 | case PARSE_GET: | ||
| 390 | if (SUHOSIN_G(disallow_get_ws)) { | ||
| 391 | suhosin_log(S_VARS, "GET variable name begins with disallowed whitespace - dropped variable '%s'", var); | ||
| 392 | if (!SUHOSIN_G(simulation)) { | ||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | break; | ||
| 397 | case PARSE_POST: | ||
| 398 | if (SUHOSIN_G(disallow_post_ws)) { | ||
| 399 | suhosin_log(S_VARS, "POST variable name begins with disallowed whitespace - dropped variable '%s'", var); | ||
| 400 | if (!SUHOSIN_G(simulation)) { | ||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | break; | ||
| 405 | case PARSE_COOKIE: | ||
| 406 | if (SUHOSIN_G(disallow_cookie_ws)) { | ||
| 407 | suhosin_log(S_VARS, "COOKIE variable name begins with disallowed whitespace - dropped variable '%s'", var); | ||
| 408 | if (!SUHOSIN_G(simulation)) { | ||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | break; | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | /* Drop this variable if it exceeds the value length limit */ | ||
| 417 | if (SUHOSIN_G(max_value_length) && SUHOSIN_G(max_value_length) < val_len) { | ||
| 418 | suhosin_log(S_VARS, "configured request variable value length limit exceeded - dropped variable '%s'", var); | ||
| 419 | if (!SUHOSIN_G(simulation)) { | ||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | } | ||
| 423 | switch (arg) { | ||
| 424 | case PARSE_GET: | ||
| 425 | if (SUHOSIN_G(max_get_value_length) && SUHOSIN_G(max_get_value_length) < val_len) { | ||
| 426 | suhosin_log(S_VARS, "configured GET variable value length limit exceeded - dropped variable '%s'", var); | ||
| 427 | if (!SUHOSIN_G(simulation)) { | ||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | } | ||
| 431 | break; | ||
| 432 | case PARSE_COOKIE: | ||
| 433 | if (SUHOSIN_G(max_cookie_value_length) && SUHOSIN_G(max_cookie_value_length) < val_len) { | ||
| 434 | suhosin_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped variable '%s'", var); | ||
| 435 | if (!SUHOSIN_G(simulation)) { | ||
| 436 | return 0; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | break; | ||
| 440 | case PARSE_POST: | ||
| 441 | if (SUHOSIN_G(max_post_value_length) && SUHOSIN_G(max_post_value_length) < val_len) { | ||
| 442 | suhosin_log(S_VARS, "configured POST variable value length limit exceeded - dropped variable '%s'", var); | ||
| 443 | if (!SUHOSIN_G(simulation)) { | ||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | } | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | |||
| 450 | /* Normalize the variable name */ | ||
| 451 | normalize_varname(var); | ||
| 452 | |||
| 453 | /* Find length of variable name */ | ||
| 454 | index = strchr(var, '['); | ||
| 455 | total_len = strlen(var); | ||
| 456 | var_len = index ? index-var : total_len; | ||
| 457 | |||
| 458 | /* Drop this variable if it exceeds the varname/total length limit */ | ||
| 459 | if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) { | ||
| 460 | suhosin_log(S_VARS, "configured request variable name length limit exceeded - dropped variable '%s'", var); | ||
| 461 | if (!SUHOSIN_G(simulation)) { | ||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | if (SUHOSIN_G(max_totalname_length) && SUHOSIN_G(max_totalname_length) < total_len) { | ||
| 466 | suhosin_log(S_VARS, "configured request variable total name length limit exceeded - dropped variable '%s'", var); | ||
| 467 | if (!SUHOSIN_G(simulation)) { | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | switch (arg) { | ||
| 472 | case PARSE_GET: | ||
| 473 | if (SUHOSIN_G(max_get_name_length) && SUHOSIN_G(max_get_name_length) < var_len) { | ||
| 474 | suhosin_log(S_VARS, "configured GET variable name length limit exceeded - dropped variable '%s'", var); | ||
| 475 | if (!SUHOSIN_G(simulation)) { | ||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | if (SUHOSIN_G(max_get_totalname_length) && SUHOSIN_G(max_get_totalname_length) < var_len) { | ||
| 480 | suhosin_log(S_VARS, "configured GET variable total name length limit exceeded - dropped variable '%s'", var); | ||
| 481 | if (!SUHOSIN_G(simulation)) { | ||
| 482 | return 0; | ||
| 483 | } | ||
| 484 | } | ||
| 485 | break; | ||
| 486 | case PARSE_COOKIE: | ||
| 487 | if (SUHOSIN_G(max_cookie_name_length) && SUHOSIN_G(max_cookie_name_length) < var_len) { | ||
| 488 | suhosin_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped variable '%s'", var); | ||
| 489 | if (!SUHOSIN_G(simulation)) { | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | } | ||
| 493 | if (SUHOSIN_G(max_cookie_totalname_length) && SUHOSIN_G(max_cookie_totalname_length) < var_len) { | ||
| 494 | suhosin_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped variable '%s'", var); | ||
| 495 | if (!SUHOSIN_G(simulation)) { | ||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | } | ||
| 499 | break; | ||
| 500 | case PARSE_POST: | ||
| 501 | if (SUHOSIN_G(max_post_name_length) && SUHOSIN_G(max_post_name_length) < var_len) { | ||
| 502 | suhosin_log(S_VARS, "configured POST variable name length limit exceeded - dropped variable '%s'", var); | ||
| 503 | if (!SUHOSIN_G(simulation)) { | ||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | } | ||
| 507 | if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < var_len) { | ||
| 508 | suhosin_log(S_VARS, "configured POST variable total name length limit exceeded - dropped variable '%s'", var); | ||
| 509 | if (!SUHOSIN_G(simulation)) { | ||
| 510 | return 0; | ||
| 511 | } | ||
| 512 | } | ||
| 513 | break; | ||
| 514 | } | ||
| 515 | |||
| 516 | /* Find out array depth */ | ||
| 517 | while (index) { | ||
| 518 | unsigned int index_length; | ||
| 519 | |||
| 520 | depth++; | ||
| 521 | index = strchr(index+1, '['); | ||
| 522 | |||
| 523 | if (prev_index) { | ||
| 524 | index_length = index ? index - 1 - prev_index - 1: strlen(prev_index); | ||
| 525 | |||
| 526 | if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) { | ||
| 527 | suhosin_log(S_VARS, "configured request variable array index length limit exceeded - dropped variable '%s'", var); | ||
| 528 | if (!SUHOSIN_G(simulation)) { | ||
| 529 | return 0; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | switch (arg) { | ||
| 533 | case PARSE_GET: | ||
| 534 | if (SUHOSIN_G(max_get_array_index_length) && SUHOSIN_G(max_get_array_index_length) < index_length) { | ||
| 535 | suhosin_log(S_VARS, "configured GET variable array index length limit exceeded - dropped variable '%s'", var); | ||
| 536 | if (!SUHOSIN_G(simulation)) { | ||
| 537 | return 0; | ||
| 538 | } | ||
| 539 | } | ||
| 540 | break; | ||
| 541 | case PARSE_COOKIE: | ||
| 542 | if (SUHOSIN_G(max_cookie_array_index_length) && SUHOSIN_G(max_cookie_array_index_length) < index_length) { | ||
| 543 | suhosin_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped variable '%s'", var); | ||
| 544 | if (!SUHOSIN_G(simulation)) { | ||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | } | ||
| 548 | break; | ||
| 549 | case PARSE_POST: | ||
| 550 | if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) { | ||
| 551 | suhosin_log(S_VARS, "configured POST variable array index length limit exceeded - dropped variable '%s'", var); | ||
| 552 | if (!SUHOSIN_G(simulation)) { | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | } | ||
| 556 | break; | ||
| 557 | } | ||
| 558 | prev_index = index; | ||
| 559 | } | ||
| 560 | |||
| 561 | } | ||
| 562 | |||
| 563 | /* Drop this variable if it exceeds the array depth limit */ | ||
| 564 | if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) { | ||
| 565 | suhosin_log(S_VARS, "configured request variable array depth limit exceeded - dropped variable '%s'", var); | ||
| 566 | if (!SUHOSIN_G(simulation)) { | ||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | switch (arg) { | ||
| 571 | case PARSE_GET: | ||
| 572 | if (SUHOSIN_G(max_get_array_depth) && SUHOSIN_G(max_get_array_depth) < depth) { | ||
| 573 | suhosin_log(S_VARS, "configured GET variable array depth limit exceeded - dropped variable '%s'", var); | ||
| 574 | if (!SUHOSIN_G(simulation)) { | ||
| 575 | return 0; | ||
| 576 | } | ||
| 577 | } | ||
| 578 | break; | ||
| 579 | case PARSE_COOKIE: | ||
| 580 | if (SUHOSIN_G(max_cookie_array_depth) && SUHOSIN_G(max_cookie_array_depth) < depth) { | ||
| 581 | suhosin_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped variable '%s'", var); | ||
| 582 | if (!SUHOSIN_G(simulation)) { | ||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | break; | ||
| 587 | case PARSE_POST: | ||
| 588 | if (SUHOSIN_G(max_post_array_depth) && SUHOSIN_G(max_post_array_depth) < depth) { | ||
| 589 | suhosin_log(S_VARS, "configured POST variable array depth limit exceeded - dropped variable '%s'", var); | ||
| 590 | if (!SUHOSIN_G(simulation)) { | ||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | break; | ||
| 595 | } | ||
| 596 | |||
| 597 | /* Check if variable value is truncated by a \0 */ | ||
| 598 | |||
| 599 | if (val && *val && val_len != strlen(*val)) { | ||
| 600 | |||
| 601 | if (SUHOSIN_G(disallow_nul)) { | ||
| 602 | suhosin_log(S_VARS, "ASCII-NUL chars not allowed within request variables - dropped variable '%s'", var); | ||
| 603 | if (!SUHOSIN_G(simulation)) { | ||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | } | ||
| 607 | switch (arg) { | ||
| 608 | case PARSE_GET: | ||
| 609 | if (SUHOSIN_G(disallow_get_nul)) { | ||
| 610 | suhosin_log(S_VARS, "ASCII-NUL chars not allowed within GET variables - dropped variable '%s'", var); | ||
| 611 | if (!SUHOSIN_G(simulation)) { | ||
| 612 | return 0; | ||
| 613 | } | ||
| 614 | } | ||
| 615 | break; | ||
| 616 | case PARSE_COOKIE: | ||
| 617 | if (SUHOSIN_G(disallow_cookie_nul)) { | ||
| 618 | suhosin_log(S_VARS, "ASCII-NUL chars not allowed within COOKIE variables - dropped variable '%s'", var); | ||
| 619 | if (!SUHOSIN_G(simulation)) { | ||
| 620 | return 0; | ||
| 621 | } | ||
| 622 | } | ||
| 623 | break; | ||
| 624 | case PARSE_POST: | ||
| 625 | if (SUHOSIN_G(disallow_post_nul)) { | ||
| 626 | suhosin_log(S_VARS, "ASCII-NUL chars not allowed within POST variables - dropped variable '%s'", var); | ||
| 627 | if (!SUHOSIN_G(simulation)) { | ||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | } | ||
| 631 | break; | ||
| 632 | } | ||
| 633 | } | ||
| 634 | |||
| 635 | /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */ | ||
| 636 | /* This is to protect several silly scripts that do globalizing themself */ | ||
| 637 | |||
| 638 | switch (var_len) { | ||
| 639 | case 18: | ||
| 640 | if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname; | ||
| 641 | break; | ||
| 642 | case 17: | ||
| 643 | if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname; | ||
| 644 | break; | ||
| 645 | case 16: | ||
| 646 | if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname; | ||
| 647 | if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname; | ||
| 648 | break; | ||
| 649 | case 15: | ||
| 650 | if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname; | ||
| 651 | break; | ||
| 652 | case 14: | ||
| 653 | if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname; | ||
| 654 | break; | ||
| 655 | case 13: | ||
| 656 | if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname; | ||
| 657 | if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname; | ||
| 658 | break; | ||
| 659 | case 8: | ||
| 660 | if (memcmp(var, "_SESSION", 8)==0) goto protected_varname; | ||
| 661 | if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname; | ||
| 662 | break; | ||
| 663 | case 7: | ||
| 664 | if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname; | ||
| 665 | if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname; | ||
| 666 | if (memcmp(var, "_SERVER", 7)==0) goto protected_varname; | ||
| 667 | break; | ||
| 668 | case 6: | ||
| 669 | if (memcmp(var, "_FILES", 6)==0) goto protected_varname; | ||
| 670 | break; | ||
| 671 | case 5: | ||
| 672 | if (memcmp(var, "_POST", 5)==0) goto protected_varname; | ||
| 673 | break; | ||
| 674 | case 4: | ||
| 675 | if (memcmp(var, "_ENV", 4)==0) goto protected_varname; | ||
| 676 | if (memcmp(var, "_GET", 4)==0) goto protected_varname; | ||
| 677 | break; | ||
| 678 | } | ||
| 679 | |||
| 680 | /* Okay let PHP register this variable */ | ||
| 681 | SUHOSIN_G(cur_request_variables)++; | ||
| 682 | switch (arg) { | ||
| 683 | case PARSE_GET: | ||
| 684 | SUHOSIN_G(cur_get_vars)++; | ||
| 685 | break; | ||
| 686 | case PARSE_COOKIE: | ||
| 687 | SUHOSIN_G(cur_cookie_vars)++; | ||
| 688 | break; | ||
| 689 | case PARSE_POST: | ||
| 690 | SUHOSIN_G(cur_post_vars)++; | ||
| 691 | break; | ||
| 692 | } | ||
| 693 | |||
| 694 | if (new_val_len) { | ||
| 695 | *new_val_len = val_len; | ||
| 696 | } | ||
| 697 | |||
| 698 | return 1; | ||
| 699 | protected_varname: | ||
| 700 | suhosin_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE"); | ||
| 701 | if (!SUHOSIN_G(simulation)) { | ||
| 702 | return 0; | ||
| 703 | } else { | ||
| 704 | return 1; | ||
| 705 | } | ||
| 706 | } | ||
| 707 | /* }}} */ | ||
| 708 | |||
| 709 | |||
| 710 | |||
| 711 | /* {{{ suhosin_hook_register_server_variables | ||
| 712 | */ | ||
| 713 | void suhosin_hook_register_server_variables() | ||
| 714 | { | ||
| 715 | if (sapi_module.register_server_variables) { | ||
| 716 | orig_register_server_variables = sapi_module.register_server_variables; | ||
| 717 | sapi_module.register_server_variables = suhosin_register_server_variables; | ||
| 718 | } | ||
| 719 | } | ||
| 720 | /* }}} */ | ||
| 721 | |||
| 722 | |||
| 723 | /* | ||
| 724 | * Local variables: | ||
| 725 | * tab-width: 4 | ||
| 726 | * c-basic-offset: 4 | ||
| 727 | * End: | ||
| 728 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 729 | * vim<600: noet sw=4 ts=4 | ||
| 730 | */ | ||
| 731 | |||
| 732 | |||
| @@ -0,0 +1,404 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: log.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "php_suhosin.h" | ||
| 30 | #include <fcntl.h> | ||
| 31 | #include "SAPI.h" | ||
| 32 | #include "ext/standard/datetime.h" | ||
| 33 | #include "ext/standard/flock_compat.h" | ||
| 34 | |||
| 35 | #ifdef HAVE_SYS_SOCKET_H | ||
| 36 | #include <sys/socket.h> | ||
| 37 | #endif | ||
| 38 | |||
| 39 | #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) | ||
| 40 | #undef AF_UNIX | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #if defined(AF_UNIX) | ||
| 44 | #include <sys/un.h> | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #define SYSLOG_PATH "/dev/log" | ||
| 48 | |||
| 49 | #include "snprintf.h" | ||
| 50 | |||
| 51 | #ifdef PHP_WIN32 | ||
| 52 | static HANDLE log_source = 0; | ||
| 53 | #endif | ||
| 54 | |||
| 55 | |||
| 56 | static char *loglevel2string(int loglevel) | ||
| 57 | { | ||
| 58 | switch (loglevel) { | ||
| 59 | case S_FILES: | ||
| 60 | return "FILES"; | ||
| 61 | case S_INCLUDE: | ||
| 62 | return "INCLUDE"; | ||
| 63 | case S_MEMORY: | ||
| 64 | return "MEMORY"; | ||
| 65 | case S_MISC: | ||
| 66 | return "MISC"; | ||
| 67 | case S_MAIL: | ||
| 68 | return "MAIL"; | ||
| 69 | case S_SESSION: | ||
| 70 | return "SESSION"; | ||
| 71 | case S_SQL: | ||
| 72 | return "SQL"; | ||
| 73 | case S_EXECUTOR: | ||
| 74 | return "EXECUTOR"; | ||
| 75 | case S_VARS: | ||
| 76 | return "VARS"; | ||
| 77 | default: | ||
| 78 | return "UNKNOWN"; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | static char *month_names[] = { | ||
| 83 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
| 84 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | ||
| 85 | }; | ||
| 86 | |||
| 87 | PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...) | ||
| 88 | { | ||
| 89 | int s, r, i=0, fd; | ||
| 90 | long written, towrite; | ||
| 91 | char *wbuf; | ||
| 92 | struct timeval tv; | ||
| 93 | time_t now; | ||
| 94 | struct tm tm; | ||
| 95 | #if defined(AF_UNIX) | ||
| 96 | struct sockaddr_un saun; | ||
| 97 | #endif | ||
| 98 | #ifdef PHP_WIN32 | ||
| 99 | LPTSTR strs[2]; | ||
| 100 | unsigned short etype; | ||
| 101 | DWORD evid; | ||
| 102 | #endif | ||
| 103 | char buf[4096+64]; | ||
| 104 | char error[4096+100]; | ||
| 105 | char *ip_address; | ||
| 106 | char *fname; | ||
| 107 | char *alertstring; | ||
| 108 | int lineno; | ||
| 109 | va_list ap; | ||
| 110 | TSRMLS_FETCH(); | ||
| 111 | |||
| 112 | SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script)); | ||
| 113 | |||
| 114 | /* dump core if wanted */ | ||
| 115 | if (SUHOSIN_G(coredump) && loglevel == S_MEMORY) { | ||
| 116 | volatile unsigned int *x = 0; | ||
| 117 | volatile int y = *x; | ||
| 118 | } | ||
| 119 | |||
| 120 | if (SUHOSIN_G(log_use_x_forwarded_for)) { | ||
| 121 | ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC); | ||
| 122 | if (ip_address == NULL) { | ||
| 123 | ip_address = "X-FORWARDED-FOR not set"; | ||
| 124 | } | ||
| 125 | } else { | ||
| 126 | ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC); | ||
| 127 | if (ip_address == NULL) { | ||
| 128 | ip_address = "REMOTE_ADDR not set"; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | |||
| 133 | va_start(ap, fmt); | ||
| 134 | ap_php_vsnprintf(error, sizeof(error), fmt, ap); | ||
| 135 | va_end(ap); | ||
| 136 | while (error[i]) { | ||
| 137 | if (error[i] < 32) error[i] = '.'; | ||
| 138 | i++; | ||
| 139 | } | ||
| 140 | |||
| 141 | if (SUHOSIN_G(simulation)) { | ||
| 142 | alertstring = "ALERT-SIMULATION"; | ||
| 143 | } else { | ||
| 144 | alertstring = "ALERT"; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (zend_is_executing(TSRMLS_C)) { | ||
| 148 | if (EG(current_execute_data)) { | ||
| 149 | lineno = EG(current_execute_data)->opline->lineno; | ||
| 150 | fname = EG(current_execute_data)->op_array->filename; | ||
| 151 | } else { | ||
| 152 | lineno = zend_get_executed_lineno(TSRMLS_C); | ||
| 153 | fname = zend_get_executed_filename(TSRMLS_C); | ||
| 154 | } | ||
| 155 | ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno); | ||
| 156 | } else { | ||
| 157 | fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC); | ||
| 158 | if (fname==NULL) { | ||
| 159 | fname = "unknown"; | ||
| 160 | } | ||
| 161 | ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname); | ||
| 162 | } | ||
| 163 | |||
| 164 | /* Syslog-Logging disabled? */ | ||
| 165 | if (((SUHOSIN_G(log_syslog)|S_INTERNAL) & loglevel)==0) { | ||
| 166 | goto log_file; | ||
| 167 | } | ||
| 168 | |||
| 169 | #if defined(AF_UNIX) | ||
| 170 | ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SUHOSIN_G(log_syslog_facility)|SUHOSIN_G(log_syslog_priority)),getpid(),buf); | ||
| 171 | |||
| 172 | s = socket(AF_UNIX, SOCK_DGRAM, 0); | ||
| 173 | if (s == -1) { | ||
| 174 | goto log_file; | ||
| 175 | } | ||
| 176 | |||
| 177 | memset(&saun, 0, sizeof(saun)); | ||
| 178 | saun.sun_family = AF_UNIX; | ||
| 179 | strcpy(saun.sun_path, SYSLOG_PATH); | ||
| 180 | /*saun.sun_len = sizeof(saun);*/ | ||
| 181 | |||
| 182 | r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); | ||
| 183 | if (r) { | ||
| 184 | close(s); | ||
| 185 | s = socket(AF_UNIX, SOCK_STREAM, 0); | ||
| 186 | if (s == -1) { | ||
| 187 | goto log_file; | ||
| 188 | } | ||
| 189 | |||
| 190 | memset(&saun, 0, sizeof(saun)); | ||
| 191 | saun.sun_family = AF_UNIX; | ||
| 192 | strcpy(saun.sun_path, SYSLOG_PATH); | ||
| 193 | /*saun.sun_len = sizeof(saun);*/ | ||
| 194 | |||
| 195 | r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); | ||
| 196 | if (r) { | ||
| 197 | close(s); | ||
| 198 | goto log_file; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | send(s, error, strlen(error), 0); | ||
| 202 | |||
| 203 | close(s); | ||
| 204 | #endif | ||
| 205 | #ifdef PHP_WIN32 | ||
| 206 | ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf); | ||
| 207 | |||
| 208 | switch (SUHOSIN_G(log_syslog_priority)) { /* translate UNIX type into NT type */ | ||
| 209 | case 1: /*LOG_ALERT:*/ | ||
| 210 | etype = EVENTLOG_ERROR_TYPE; | ||
| 211 | break; | ||
| 212 | case 6: /*LOG_INFO:*/ | ||
| 213 | etype = EVENTLOG_INFORMATION_TYPE; | ||
| 214 | break; | ||
| 215 | default: | ||
| 216 | etype = EVENTLOG_WARNING_TYPE; | ||
| 217 | } | ||
| 218 | evid = loglevel; | ||
| 219 | strs[0] = error; | ||
| 220 | /* report the event */ | ||
| 221 | if (log_source == NULL) { | ||
| 222 | log_source = RegisterEventSource(NULL, "Suhosin-" SUHOSIN_EXT_VERSION); | ||
| 223 | } | ||
| 224 | ReportEvent(log_source, etype, (unsigned short) SUHOSIN_G(log_syslog_priority), evid, NULL, 1, 0, strs, NULL); | ||
| 225 | |||
| 226 | #endif | ||
| 227 | log_file: | ||
| 228 | /* File-Logging disabled? */ | ||
| 229 | if ((SUHOSIN_G(log_file) & loglevel)==0) { | ||
| 230 | goto log_sapi; | ||
| 231 | } | ||
| 232 | |||
| 233 | if (!SUHOSIN_G(log_filename) || !SUHOSIN_G(log_filename)[0]) { | ||
| 234 | goto log_sapi; | ||
| 235 | } | ||
| 236 | fd = open(SUHOSIN_G(log_filename), O_CREAT|O_APPEND|O_WRONLY, 0640); | ||
| 237 | if (fd == -1) { | ||
| 238 | suhosin_log(S_INTERNAL, "Unable to open logfile: %s", SUHOSIN_G(log_filename)); | ||
| 239 | return; | ||
| 240 | } | ||
| 241 | |||
| 242 | gettimeofday(&tv, NULL); | ||
| 243 | now = tv.tv_sec; | ||
| 244 | php_gmtime_r(&now, &tm); | ||
| 245 | ap_php_snprintf(error, sizeof(error), "%s %2d %02d:%02d:%02d [%u] %s\n", month_names[tm.tm_mon], tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, getpid(),buf); | ||
| 246 | towrite = strlen(error); | ||
| 247 | wbuf = error; | ||
| 248 | php_flock(fd, LOCK_EX); | ||
| 249 | while (towrite > 0) { | ||
| 250 | written = write(fd, wbuf, towrite); | ||
| 251 | if (written < 0) { | ||
| 252 | break; | ||
| 253 | } | ||
| 254 | towrite -= written; | ||
| 255 | wbuf += written; | ||
| 256 | } | ||
| 257 | php_flock(fd, LOCK_UN); | ||
| 258 | close(fd); | ||
| 259 | |||
| 260 | log_sapi: | ||
| 261 | /* SAPI Logging activated? */ | ||
| 262 | SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script), SUHOSIN_G(log_phpscript)); | ||
| 263 | if (((SUHOSIN_G(log_sapi)|S_INTERNAL) & loglevel)!=0) { | ||
| 264 | sapi_module.log_message(buf); | ||
| 265 | } | ||
| 266 | |||
| 267 | /*log_script:*/ | ||
| 268 | /* script logging activaed? */ | ||
| 269 | if (((SUHOSIN_G(log_script) & loglevel)!=0) && SUHOSIN_G(log_scriptname)!=NULL) { | ||
| 270 | char cmd[8192], *cmdpos, *bufpos; | ||
| 271 | FILE *in; | ||
| 272 | int space; | ||
| 273 | |||
| 274 | char *sname = SUHOSIN_G(log_scriptname); | ||
| 275 | while (isspace(*sname)) ++sname; | ||
| 276 | if (*sname == 0) goto log_phpscript; | ||
| 277 | |||
| 278 | ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", sname, loglevel2string(loglevel)); | ||
| 279 | space = sizeof(cmd) - strlen(cmd); | ||
| 280 | cmdpos = cmd + strlen(cmd); | ||
| 281 | bufpos = buf; | ||
| 282 | if (space <= 1) return; | ||
| 283 | while (space > 2 && *bufpos) { | ||
| 284 | if (*bufpos == '\'') { | ||
| 285 | if (space<=5) break; | ||
| 286 | *cmdpos++ = '\''; | ||
| 287 | *cmdpos++ = '\\'; | ||
| 288 | *cmdpos++ = '\''; | ||
| 289 | *cmdpos++ = '\''; | ||
| 290 | bufpos++; | ||
| 291 | space-=4; | ||
| 292 | } else { | ||
| 293 | *cmdpos++ = *bufpos++; | ||
| 294 | space--; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | *cmdpos++ = '\''; | ||
| 298 | *cmdpos = 0; | ||
| 299 | |||
| 300 | if ((in=VCWD_POPEN(cmd, "r"))==NULL) { | ||
| 301 | suhosin_log(S_INTERNAL, "Unable to execute logging shell script: %s", sname); | ||
| 302 | return; | ||
| 303 | } | ||
| 304 | /* read and forget the result */ | ||
| 305 | while (1) { | ||
| 306 | int readbytes = fread(cmd, 1, sizeof(cmd), in); | ||
| 307 | if (readbytes<=0) { | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | } | ||
| 311 | pclose(in); | ||
| 312 | } | ||
| 313 | log_phpscript: | ||
| 314 | if ((SUHOSIN_G(log_phpscript) & loglevel)!=0 && EG(in_execution) && SUHOSIN_G(log_phpscriptname) && SUHOSIN_G(log_phpscriptname)[0]) { | ||
| 315 | zend_file_handle file_handle; | ||
| 316 | zend_op_array *new_op_array; | ||
| 317 | zval *result = NULL; | ||
| 318 | |||
| 319 | long orig_execution_depth = SUHOSIN_G(execution_depth); | ||
| 320 | zend_bool orig_safe_mode = PG(safe_mode); | ||
| 321 | char *orig_basedir = PG(open_basedir); | ||
| 322 | |||
| 323 | char *phpscript = SUHOSIN_G(log_phpscriptname); | ||
| 324 | SDEBUG("scriptname %s", SUHOSIN_G(log_phpscriptname)); | ||
| 325 | #ifdef ZEND_ENGINE_2 | ||
| 326 | if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) { | ||
| 327 | #else | ||
| 328 | if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { | ||
| 329 | file_handle.filename = phpscript; | ||
| 330 | file_handle.free_filename = 0; | ||
| 331 | #endif | ||
| 332 | if (!file_handle.opened_path) { | ||
| 333 | file_handle.opened_path = estrndup(phpscript, strlen(phpscript)); | ||
| 334 | } | ||
| 335 | new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); | ||
| 336 | zend_destroy_file_handle(&file_handle TSRMLS_CC); | ||
| 337 | if (new_op_array) { | ||
| 338 | HashTable *active_symbol_table = EG(active_symbol_table); | ||
| 339 | zval *zerror, *zerror_class; | ||
| 340 | |||
| 341 | if (active_symbol_table == NULL) { | ||
| 342 | active_symbol_table = &EG(symbol_table); | ||
| 343 | } | ||
| 344 | EG(return_value_ptr_ptr) = &result; | ||
| 345 | EG(active_op_array) = new_op_array; | ||
| 346 | |||
| 347 | MAKE_STD_ZVAL(zerror); | ||
| 348 | MAKE_STD_ZVAL(zerror_class); | ||
| 349 | ZVAL_STRING(zerror, buf, 1); | ||
| 350 | ZVAL_LONG(zerror_class, loglevel); | ||
| 351 | |||
| 352 | zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL); | ||
| 353 | zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL); | ||
| 354 | |||
| 355 | SUHOSIN_G(execution_depth) = 0; | ||
| 356 | if (SUHOSIN_G(log_phpscript_is_safe)) { | ||
| 357 | PG(safe_mode) = 0; | ||
| 358 | PG(open_basedir) = NULL; | ||
| 359 | } | ||
| 360 | |||
| 361 | zend_execute(new_op_array TSRMLS_CC); | ||
| 362 | |||
| 363 | SUHOSIN_G(execution_depth) = orig_execution_depth; | ||
| 364 | PG(safe_mode) = orig_safe_mode; | ||
| 365 | PG(open_basedir) = orig_basedir; | ||
| 366 | |||
| 367 | #ifdef ZEND_ENGINE_2 | ||
| 368 | destroy_op_array(new_op_array TSRMLS_CC); | ||
| 369 | #else | ||
| 370 | destroy_op_array(new_op_array); | ||
| 371 | #endif | ||
| 372 | efree(new_op_array); | ||
| 373 | #ifdef ZEND_ENGINE_2 | ||
| 374 | if (!EG(exception)) | ||
| 375 | #endif | ||
| 376 | { | ||
| 377 | if (EG(return_value_ptr_ptr)) { | ||
| 378 | zval_ptr_dtor(EG(return_value_ptr_ptr)); | ||
| 379 | EG(return_value_ptr_ptr) = NULL; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | } else { | ||
| 383 | suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname)); | ||
| 384 | return; | ||
| 385 | } | ||
| 386 | } else { | ||
| 387 | suhosin_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SUHOSIN_G(log_phpscriptname)); | ||
| 388 | return; | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | } | ||
| 393 | |||
| 394 | |||
| 395 | /* | ||
| 396 | * Local variables: | ||
| 397 | * tab-width: 4 | ||
| 398 | * c-basic-offset: 4 | ||
| 399 | * End: | ||
| 400 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 401 | * vim<600: noet sw=4 ts=4 | ||
| 402 | */ | ||
| 403 | |||
| 404 | |||
diff --git a/mbregex.h b/mbregex.h new file mode 100644 index 0000000..014f002 --- /dev/null +++ b/mbregex.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: mbregex.h,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 21 | |||
| 22 | #if HAVE_MBREGEX | ||
| 23 | |||
| 24 | #include "mbregex/mbregex.h" | ||
| 25 | |||
| 26 | #endif \ No newline at end of file | ||
diff --git a/mbregex/COPYING.LIB b/mbregex/COPYING.LIB new file mode 100644 index 0000000..c4792dd --- /dev/null +++ b/mbregex/COPYING.LIB | |||
| @@ -0,0 +1,515 @@ | |||
| 1 | |||
| 2 | GNU LESSER GENERAL PUBLIC LICENSE | ||
| 3 | Version 2.1, February 1999 | ||
| 4 | |||
| 5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. | ||
| 6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 7 | Everyone is permitted to copy and distribute verbatim copies | ||
| 8 | of this license document, but changing it is not allowed. | ||
| 9 | |||
| 10 | [This is the first released version of the Lesser GPL. It also counts | ||
| 11 | as the successor of the GNU Library Public License, version 2, hence | ||
| 12 | the version number 2.1.] | ||
| 13 | |||
| 14 | Preamble | ||
| 15 | |||
| 16 | The licenses for most software are designed to take away your | ||
| 17 | freedom to share and change it. By contrast, the GNU General Public | ||
| 18 | Licenses are intended to guarantee your freedom to share and change | ||
| 19 | free software--to make sure the software is free for all its users. | ||
| 20 | |||
| 21 | This license, the Lesser General Public License, applies to some | ||
| 22 | specially designated software packages--typically libraries--of the | ||
| 23 | Free Software Foundation and other authors who decide to use it. You | ||
| 24 | can use it too, but we suggest you first think carefully about whether | ||
| 25 | this license or the ordinary General Public License is the better | ||
| 26 | strategy to use in any particular case, based on the explanations | ||
| 27 | below. | ||
| 28 | |||
| 29 | When we speak of free software, we are referring to freedom of use, | ||
| 30 | not price. Our General Public Licenses are designed to make sure that | ||
| 31 | you have the freedom to distribute copies of free software (and charge | ||
| 32 | for this service if you wish); that you receive source code or can get | ||
| 33 | it if you want it; that you can change the software and use pieces of | ||
| 34 | it in new free programs; and that you are informed that you can do | ||
| 35 | these things. | ||
| 36 | |||
| 37 | To protect your rights, we need to make restrictions that forbid | ||
| 38 | distributors to deny you these rights or to ask you to surrender these | ||
| 39 | rights. These restrictions translate to certain responsibilities for | ||
| 40 | you if you distribute copies of the library or if you modify it. | ||
| 41 | |||
| 42 | For example, if you distribute copies of the library, whether gratis | ||
| 43 | or for a fee, you must give the recipients all the rights that we gave | ||
| 44 | you. You must make sure that they, too, receive or can get the source | ||
| 45 | code. If you link other code with the library, you must provide | ||
| 46 | complete object files to the recipients, so that they can relink them | ||
| 47 | with the library after making changes to the library and recompiling | ||
| 48 | it. And you must show them these terms so they know their rights. | ||
| 49 | |||
| 50 | We protect your rights with a two-step method: (1) we copyright the | ||
| 51 | library, and (2) we offer you this license, which gives you legal | ||
| 52 | permission to copy, distribute and/or modify the library. | ||
| 53 | |||
| 54 | To protect each distributor, we want to make it very clear that | ||
| 55 | there is no warranty for the free library. Also, if the library is | ||
| 56 | modified by someone else and passed on, the recipients should know | ||
| 57 | that what they have is not the original version, so that the original | ||
| 58 | author's reputation will not be affected by problems that might be | ||
| 59 | introduced by others. | ||
| 60 | ^L | ||
| 61 | Finally, software patents pose a constant threat to the existence of | ||
| 62 | any free program. We wish to make sure that a company cannot | ||
| 63 | effectively restrict the users of a free program by obtaining a | ||
| 64 | restrictive license from a patent holder. Therefore, we insist that | ||
| 65 | any patent license obtained for a version of the library must be | ||
| 66 | consistent with the full freedom of use specified in this license. | ||
| 67 | |||
| 68 | Most GNU software, including some libraries, is covered by the | ||
| 69 | ordinary GNU General Public License. This license, the GNU Lesser | ||
| 70 | General Public License, applies to certain designated libraries, and | ||
| 71 | is quite different from the ordinary General Public License. We use | ||
| 72 | this license for certain libraries in order to permit linking those | ||
| 73 | libraries into non-free programs. | ||
| 74 | |||
| 75 | When a program is linked with a library, whether statically or using | ||
| 76 | a shared library, the combination of the two is legally speaking a | ||
| 77 | combined work, a derivative of the original library. The ordinary | ||
| 78 | General Public License therefore permits such linking only if the | ||
| 79 | entire combination fits its criteria of freedom. The Lesser General | ||
| 80 | Public License permits more lax criteria for linking other code with | ||
| 81 | the library. | ||
| 82 | |||
| 83 | We call this license the "Lesser" General Public License because it | ||
| 84 | does Less to protect the user's freedom than the ordinary General | ||
| 85 | Public License. It also provides other free software developers Less | ||
| 86 | of an advantage over competing non-free programs. These disadvantages | ||
| 87 | are the reason we use the ordinary General Public License for many | ||
| 88 | libraries. However, the Lesser license provides advantages in certain | ||
| 89 | special circumstances. | ||
| 90 | |||
| 91 | For example, on rare occasions, there may be a special need to | ||
| 92 | encourage the widest possible use of a certain library, so that it | ||
| 93 | becomes | ||
| 94 | a de-facto standard. To achieve this, non-free programs must be | ||
| 95 | allowed to use the library. A more frequent case is that a free | ||
| 96 | library does the same job as widely used non-free libraries. In this | ||
| 97 | case, there is little to gain by limiting the free library to free | ||
| 98 | software only, so we use the Lesser General Public License. | ||
| 99 | |||
| 100 | In other cases, permission to use a particular library in non-free | ||
| 101 | programs enables a greater number of people to use a large body of | ||
| 102 | free software. For example, permission to use the GNU C Library in | ||
| 103 | non-free programs enables many more people to use the whole GNU | ||
| 104 | operating system, as well as its variant, the GNU/Linux operating | ||
| 105 | system. | ||
| 106 | |||
| 107 | Although the Lesser General Public License is Less protective of the | ||
| 108 | users' freedom, it does ensure that the user of a program that is | ||
| 109 | linked with the Library has the freedom and the wherewithal to run | ||
| 110 | that program using a modified version of the Library. | ||
| 111 | |||
| 112 | The precise terms and conditions for copying, distribution and | ||
| 113 | modification follow. Pay close attention to the difference between a | ||
| 114 | "work based on the library" and a "work that uses the library". The | ||
| 115 | former contains code derived from the library, whereas the latter must | ||
| 116 | be combined with the library in order to run. | ||
| 117 | ^L | ||
| 118 | GNU LESSER GENERAL PUBLIC LICENSE | ||
| 119 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
| 120 | |||
| 121 | 0. This License Agreement applies to any software library or other | ||
| 122 | program which contains a notice placed by the copyright holder or | ||
| 123 | other authorized party saying it may be distributed under the terms of | ||
| 124 | this Lesser General Public License (also called "this License"). | ||
| 125 | Each licensee is addressed as "you". | ||
| 126 | |||
| 127 | A "library" means a collection of software functions and/or data | ||
| 128 | prepared so as to be conveniently linked with application programs | ||
| 129 | (which use some of those functions and data) to form executables. | ||
| 130 | |||
| 131 | The "Library", below, refers to any such software library or work | ||
| 132 | which has been distributed under these terms. A "work based on the | ||
| 133 | Library" means either the Library or any derivative work under | ||
| 134 | copyright law: that is to say, a work containing the Library or a | ||
| 135 | portion of it, either verbatim or with modifications and/or translated | ||
| 136 | straightforwardly into another language. (Hereinafter, translation is | ||
| 137 | included without limitation in the term "modification".) | ||
| 138 | |||
| 139 | "Source code" for a work means the preferred form of the work for | ||
| 140 | making modifications to it. For a library, complete source code means | ||
| 141 | all the source code for all modules it contains, plus any associated | ||
| 142 | interface definition files, plus the scripts used to control | ||
| 143 | compilation | ||
| 144 | and installation of the library. | ||
| 145 | |||
| 146 | Activities other than copying, distribution and modification are not | ||
| 147 | covered by this License; they are outside its scope. The act of | ||
| 148 | running a program using the Library is not restricted, and output from | ||
| 149 | such a program is covered only if its contents constitute a work based | ||
| 150 | on the Library (independent of the use of the Library in a tool for | ||
| 151 | writing it). Whether that is true depends on what the Library does | ||
| 152 | and what the program that uses the Library does. | ||
| 153 | |||
| 154 | 1. You may copy and distribute verbatim copies of the Library's | ||
| 155 | complete source code as you receive it, in any medium, provided that | ||
| 156 | you conspicuously and appropriately publish on each copy an | ||
| 157 | appropriate copyright notice and disclaimer of warranty; keep intact | ||
| 158 | all the notices that refer to this License and to the absence of any | ||
| 159 | warranty; and distribute a copy of this License along with the | ||
| 160 | Library. | ||
| 161 | |||
| 162 | You may charge a fee for the physical act of transferring a copy, | ||
| 163 | and you may at your option offer warranty protection in exchange for a | ||
| 164 | fee. | ||
| 165 | |||
| 166 | 2. You may modify your copy or copies of the Library or any portion | ||
| 167 | of it, thus forming a work based on the Library, and copy and | ||
| 168 | distribute such modifications or work under the terms of Section 1 | ||
| 169 | above, provided that you also meet all of these conditions: | ||
| 170 | |||
| 171 | a) The modified work must itself be a software library. | ||
| 172 | |||
| 173 | b) You must cause the files modified to carry prominent notices | ||
| 174 | stating that you changed the files and the date of any change. | ||
| 175 | |||
| 176 | c) You must cause the whole of the work to be licensed at no | ||
| 177 | charge to all third parties under the terms of this License. | ||
| 178 | |||
| 179 | d) If a facility in the modified Library refers to a function or a | ||
| 180 | table of data to be supplied by an application program that uses | ||
| 181 | the facility, other than as an argument passed when the facility | ||
| 182 | is invoked, then you must make a good faith effort to ensure that, | ||
| 183 | in the event an application does not supply such function or | ||
| 184 | table, the facility still operates, and performs whatever part of | ||
| 185 | its purpose remains meaningful. | ||
| 186 | |||
| 187 | (For example, a function in a library to compute square roots has | ||
| 188 | a purpose that is entirely well-defined independent of the | ||
| 189 | application. Therefore, Subsection 2d requires that any | ||
| 190 | application-supplied function or table used by this function must | ||
| 191 | be optional: if the application does not supply it, the square | ||
| 192 | root function must still compute square roots.) | ||
| 193 | |||
| 194 | These requirements apply to the modified work as a whole. If | ||
| 195 | identifiable sections of that work are not derived from the Library, | ||
| 196 | and can be reasonably considered independent and separate works in | ||
| 197 | themselves, then this License, and its terms, do not apply to those | ||
| 198 | sections when you distribute them as separate works. But when you | ||
| 199 | distribute the same sections as part of a whole which is a work based | ||
| 200 | on the Library, the distribution of the whole must be on the terms of | ||
| 201 | this License, whose permissions for other licensees extend to the | ||
| 202 | entire whole, and thus to each and every part regardless of who wrote | ||
| 203 | it. | ||
| 204 | |||
| 205 | Thus, it is not the intent of this section to claim rights or contest | ||
| 206 | your rights to work written entirely by you; rather, the intent is to | ||
| 207 | exercise the right to control the distribution of derivative or | ||
| 208 | collective works based on the Library. | ||
| 209 | |||
| 210 | In addition, mere aggregation of another work not based on the Library | ||
| 211 | with the Library (or with a work based on the Library) on a volume of | ||
| 212 | a storage or distribution medium does not bring the other work under | ||
| 213 | the scope of this License. | ||
| 214 | |||
| 215 | 3. You may opt to apply the terms of the ordinary GNU General Public | ||
| 216 | License instead of this License to a given copy of the Library. To do | ||
| 217 | this, you must alter all the notices that refer to this License, so | ||
| 218 | that they refer to the ordinary GNU General Public License, version 2, | ||
| 219 | instead of to this License. (If a newer version than version 2 of the | ||
| 220 | ordinary GNU General Public License has appeared, then you can specify | ||
| 221 | that version instead if you wish.) Do not make any other change in | ||
| 222 | these notices. | ||
| 223 | ^L | ||
| 224 | Once this change is made in a given copy, it is irreversible for | ||
| 225 | that copy, so the ordinary GNU General Public License applies to all | ||
| 226 | subsequent copies and derivative works made from that copy. | ||
| 227 | |||
| 228 | This option is useful when you wish to copy part of the code of | ||
| 229 | the Library into a program that is not a library. | ||
| 230 | |||
| 231 | 4. You may copy and distribute the Library (or a portion or | ||
| 232 | derivative of it, under Section 2) in object code or executable form | ||
| 233 | under the terms of Sections 1 and 2 above provided that you accompany | ||
| 234 | it with the complete corresponding machine-readable source code, which | ||
| 235 | must be distributed under the terms of Sections 1 and 2 above on a | ||
| 236 | medium customarily used for software interchange. | ||
| 237 | |||
| 238 | If distribution of object code is made by offering access to copy | ||
| 239 | from a designated place, then offering equivalent access to copy the | ||
| 240 | source code from the same place satisfies the requirement to | ||
| 241 | distribute the source code, even though third parties are not | ||
| 242 | compelled to copy the source along with the object code. | ||
| 243 | |||
| 244 | 5. A program that contains no derivative of any portion of the | ||
| 245 | Library, but is designed to work with the Library by being compiled or | ||
| 246 | linked with it, is called a "work that uses the Library". Such a | ||
| 247 | work, in isolation, is not a derivative work of the Library, and | ||
| 248 | therefore falls outside the scope of this License. | ||
| 249 | |||
| 250 | However, linking a "work that uses the Library" with the Library | ||
| 251 | creates an executable that is a derivative of the Library (because it | ||
| 252 | contains portions of the Library), rather than a "work that uses the | ||
| 253 | library". The executable is therefore covered by this License. | ||
| 254 | Section 6 states terms for distribution of such executables. | ||
| 255 | |||
| 256 | When a "work that uses the Library" uses material from a header file | ||
| 257 | that is part of the Library, the object code for the work may be a | ||
| 258 | derivative work of the Library even though the source code is not. | ||
| 259 | Whether this is true is especially significant if the work can be | ||
| 260 | linked without the Library, or if the work is itself a library. The | ||
| 261 | threshold for this to be true is not precisely defined by law. | ||
| 262 | |||
| 263 | If such an object file uses only numerical parameters, data | ||
| 264 | structure layouts and accessors, and small macros and small inline | ||
| 265 | functions (ten lines or less in length), then the use of the object | ||
| 266 | file is unrestricted, regardless of whether it is legally a derivative | ||
| 267 | work. (Executables containing this object code plus portions of the | ||
| 268 | Library will still fall under Section 6.) | ||
| 269 | |||
| 270 | Otherwise, if the work is a derivative of the Library, you may | ||
| 271 | distribute the object code for the work under the terms of Section 6. | ||
| 272 | Any executables containing that work also fall under Section 6, | ||
| 273 | whether or not they are linked directly with the Library itself. | ||
| 274 | ^L | ||
| 275 | 6. As an exception to the Sections above, you may also combine or | ||
| 276 | link a "work that uses the Library" with the Library to produce a | ||
| 277 | work containing portions of the Library, and distribute that work | ||
| 278 | under terms of your choice, provided that the terms permit | ||
| 279 | modification of the work for the customer's own use and reverse | ||
| 280 | engineering for debugging such modifications. | ||
| 281 | |||
| 282 | You must give prominent notice with each copy of the work that the | ||
| 283 | Library is used in it and that the Library and its use are covered by | ||
| 284 | this License. You must supply a copy of this License. If the work | ||
| 285 | during execution displays copyright notices, you must include the | ||
| 286 | copyright notice for the Library among them, as well as a reference | ||
| 287 | directing the user to the copy of this License. Also, you must do one | ||
| 288 | of these things: | ||
| 289 | |||
| 290 | a) Accompany the work with the complete corresponding | ||
| 291 | machine-readable source code for the Library including whatever | ||
| 292 | changes were used in the work (which must be distributed under | ||
| 293 | Sections 1 and 2 above); and, if the work is an executable linked | ||
| 294 | with the Library, with the complete machine-readable "work that | ||
| 295 | uses the Library", as object code and/or source code, so that the | ||
| 296 | user can modify the Library and then relink to produce a modified | ||
| 297 | executable containing the modified Library. (It is understood | ||
| 298 | that the user who changes the contents of definitions files in the | ||
| 299 | Library will not necessarily be able to recompile the application | ||
| 300 | to use the modified definitions.) | ||
| 301 | |||
| 302 | b) Use a suitable shared library mechanism for linking with the | ||
| 303 | Library. A suitable mechanism is one that (1) uses at run time a | ||
| 304 | copy of the library already present on the user's computer system, | ||
| 305 | rather than copying library functions into the executable, and (2) | ||
| 306 | will operate properly with a modified version of the library, if | ||
| 307 | the user installs one, as long as the modified version is | ||
| 308 | interface-compatible with the version that the work was made with. | ||
| 309 | |||
| 310 | c) Accompany the work with a written offer, valid for at | ||
| 311 | least three years, to give the same user the materials | ||
| 312 | specified in Subsection 6a, above, for a charge no more | ||
| 313 | than the cost of performing this distribution. | ||
| 314 | |||
| 315 | d) If distribution of the work is made by offering access to copy | ||
| 316 | from a designated place, offer equivalent access to copy the above | ||
| 317 | specified materials from the same place. | ||
| 318 | |||
| 319 | e) Verify that the user has already received a copy of these | ||
| 320 | materials or that you have already sent this user a copy. | ||
| 321 | |||
| 322 | For an executable, the required form of the "work that uses the | ||
| 323 | Library" must include any data and utility programs needed for | ||
| 324 | reproducing the executable from it. However, as a special exception, | ||
| 325 | the materials to be distributed need not include anything that is | ||
| 326 | normally distributed (in either source or binary form) with the major | ||
| 327 | components (compiler, kernel, and so on) of the operating system on | ||
| 328 | which the executable runs, unless that component itself accompanies | ||
| 329 | the executable. | ||
| 330 | |||
| 331 | It may happen that this requirement contradicts the license | ||
| 332 | restrictions of other proprietary libraries that do not normally | ||
| 333 | accompany the operating system. Such a contradiction means you cannot | ||
| 334 | use both them and the Library together in an executable that you | ||
| 335 | distribute. | ||
| 336 | ^L | ||
| 337 | 7. You may place library facilities that are a work based on the | ||
| 338 | Library side-by-side in a single library together with other library | ||
| 339 | facilities not covered by this License, and distribute such a combined | ||
| 340 | library, provided that the separate distribution of the work based on | ||
| 341 | the Library and of the other library facilities is otherwise | ||
| 342 | permitted, and provided that you do these two things: | ||
| 343 | |||
| 344 | a) Accompany the combined library with a copy of the same work | ||
| 345 | based on the Library, uncombined with any other library | ||
| 346 | facilities. This must be distributed under the terms of the | ||
| 347 | Sections above. | ||
| 348 | |||
| 349 | b) Give prominent notice with the combined library of the fact | ||
| 350 | that part of it is a work based on the Library, and explaining | ||
| 351 | where to find the accompanying uncombined form of the same work. | ||
| 352 | |||
| 353 | 8. You may not copy, modify, sublicense, link with, or distribute | ||
| 354 | the Library except as expressly provided under this License. Any | ||
| 355 | attempt otherwise to copy, modify, sublicense, link with, or | ||
| 356 | distribute the Library is void, and will automatically terminate your | ||
| 357 | rights under this License. However, parties who have received copies, | ||
| 358 | or rights, from you under this License will not have their licenses | ||
| 359 | terminated so long as such parties remain in full compliance. | ||
| 360 | |||
| 361 | 9. You are not required to accept this License, since you have not | ||
| 362 | signed it. However, nothing else grants you permission to modify or | ||
| 363 | distribute the Library or its derivative works. These actions are | ||
| 364 | prohibited by law if you do not accept this License. Therefore, by | ||
| 365 | modifying or distributing the Library (or any work based on the | ||
| 366 | Library), you indicate your acceptance of this License to do so, and | ||
| 367 | all its terms and conditions for copying, distributing or modifying | ||
| 368 | the Library or works based on it. | ||
| 369 | |||
| 370 | 10. Each time you redistribute the Library (or any work based on the | ||
| 371 | Library), the recipient automatically receives a license from the | ||
| 372 | original licensor to copy, distribute, link with or modify the Library | ||
| 373 | subject to these terms and conditions. You may not impose any further | ||
| 374 | restrictions on the recipients' exercise of the rights granted herein. | ||
| 375 | You are not responsible for enforcing compliance by third parties with | ||
| 376 | this License. | ||
| 377 | ^L | ||
| 378 | 11. If, as a consequence of a court judgment or allegation of patent | ||
| 379 | infringement or for any other reason (not limited to patent issues), | ||
| 380 | conditions are imposed on you (whether by court order, agreement or | ||
| 381 | otherwise) that contradict the conditions of this License, they do not | ||
| 382 | excuse you from the conditions of this License. If you cannot | ||
| 383 | distribute so as to satisfy simultaneously your obligations under this | ||
| 384 | License and any other pertinent obligations, then as a consequence you | ||
| 385 | may not distribute the Library at all. For example, if a patent | ||
| 386 | license would not permit royalty-free redistribution of the Library by | ||
| 387 | all those who receive copies directly or indirectly through you, then | ||
| 388 | the only way you could satisfy both it and this License would be to | ||
| 389 | refrain entirely from distribution of the Library. | ||
| 390 | |||
| 391 | If any portion of this section is held invalid or unenforceable under | ||
| 392 | any particular circumstance, the balance of the section is intended to | ||
| 393 | apply, and the section as a whole is intended to apply in other | ||
| 394 | circumstances. | ||
| 395 | |||
| 396 | It is not the purpose of this section to induce you to infringe any | ||
| 397 | patents or other property right claims or to contest validity of any | ||
| 398 | such claims; this section has the sole purpose of protecting the | ||
| 399 | integrity of the free software distribution system which is | ||
| 400 | implemented by public license practices. Many people have made | ||
| 401 | generous contributions to the wide range of software distributed | ||
| 402 | through that system in reliance on consistent application of that | ||
| 403 | system; it is up to the author/donor to decide if he or she is willing | ||
| 404 | to distribute software through any other system and a licensee cannot | ||
| 405 | impose that choice. | ||
| 406 | |||
| 407 | This section is intended to make thoroughly clear what is believed to | ||
| 408 | be a consequence of the rest of this License. | ||
| 409 | |||
| 410 | 12. If the distribution and/or use of the Library is restricted in | ||
| 411 | certain countries either by patents or by copyrighted interfaces, the | ||
| 412 | original copyright holder who places the Library under this License | ||
| 413 | may add an explicit geographical distribution limitation excluding those | ||
| 414 | countries, so that distribution is permitted only in or among | ||
| 415 | countries not thus excluded. In such case, this License incorporates | ||
| 416 | the limitation as if written in the body of this License. | ||
| 417 | |||
| 418 | 13. The Free Software Foundation may publish revised and/or new | ||
| 419 | versions of the Lesser General Public License from time to time. | ||
| 420 | Such new versions will be similar in spirit to the present version, | ||
| 421 | but may differ in detail to address new problems or concerns. | ||
| 422 | |||
| 423 | Each version is given a distinguishing version number. If the Library | ||
| 424 | specifies a version number of this License which applies to it and | ||
| 425 | "any later version", you have the option of following the terms and | ||
| 426 | conditions either of that version or of any later version published by | ||
| 427 | the Free Software Foundation. If the Library does not specify a | ||
| 428 | license version number, you may choose any version ever published by | ||
| 429 | the Free Software Foundation. | ||
| 430 | ^L | ||
| 431 | 14. If you wish to incorporate parts of the Library into other free | ||
| 432 | programs whose distribution conditions are incompatible with these, | ||
| 433 | write to the author to ask for permission. For software which is | ||
| 434 | copyrighted by the Free Software Foundation, write to the Free | ||
| 435 | Software Foundation; we sometimes make exceptions for this. Our | ||
| 436 | decision will be guided by the two goals of preserving the free status | ||
| 437 | of all derivatives of our free software and of promoting the sharing | ||
| 438 | and reuse of software generally. | ||
| 439 | |||
| 440 | NO WARRANTY | ||
| 441 | |||
| 442 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO | ||
| 443 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | ||
| 444 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | ||
| 445 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY | ||
| 446 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 447 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 448 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | ||
| 449 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME | ||
| 450 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||
| 451 | |||
| 452 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | ||
| 453 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | ||
| 454 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU | ||
| 455 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR | ||
| 456 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | ||
| 457 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | ||
| 458 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | ||
| 459 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF | ||
| 460 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | ||
| 461 | DAMAGES. | ||
| 462 | |||
| 463 | END OF TERMS AND CONDITIONS | ||
| 464 | ^L | ||
| 465 | How to Apply These Terms to Your New Libraries | ||
| 466 | |||
| 467 | If you develop a new library, and you want it to be of the greatest | ||
| 468 | possible use to the public, we recommend making it free software that | ||
| 469 | everyone can redistribute and change. You can do so by permitting | ||
| 470 | redistribution under these terms (or, alternatively, under the terms | ||
| 471 | of the ordinary General Public License). | ||
| 472 | |||
| 473 | To apply these terms, attach the following notices to the library. | ||
| 474 | It is safest to attach them to the start of each source file to most | ||
| 475 | effectively convey the exclusion of warranty; and each file should | ||
| 476 | have at least the "copyright" line and a pointer to where the full | ||
| 477 | notice is found. | ||
| 478 | |||
| 479 | |||
| 480 | <one line to give the library's name and a brief idea of what it | ||
| 481 | does.> | ||
| 482 | Copyright (C) <year> <name of author> | ||
| 483 | |||
| 484 | This library is free software; you can redistribute it and/or | ||
| 485 | modify it under the terms of the GNU Lesser General Public | ||
| 486 | License as published by the Free Software Foundation; either | ||
| 487 | version 2 of the License, or (at your option) any later version. | ||
| 488 | |||
| 489 | This library is distributed in the hope that it will be useful, | ||
| 490 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 491 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 492 | Lesser General Public License for more details. | ||
| 493 | |||
| 494 | You should have received a copy of the GNU Lesser General Public | ||
| 495 | License along with this library; if not, write to the Free Software | ||
| 496 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 497 | |||
| 498 | Also add information on how to contact you by electronic and paper | ||
| 499 | mail. | ||
| 500 | |||
| 501 | You should also get your employer (if you work as a programmer) or | ||
| 502 | your | ||
| 503 | school, if any, to sign a "copyright disclaimer" for the library, if | ||
| 504 | necessary. Here is a sample; alter the names: | ||
| 505 | |||
| 506 | Yoyodyne, Inc., hereby disclaims all copyright interest in the | ||
| 507 | library `Frob' (a library for tweaking knobs) written by James | ||
| 508 | Random Hacker. | ||
| 509 | |||
| 510 | <signature of Ty Coon>, 1 April 1990 | ||
| 511 | Ty Coon, President of Vice | ||
| 512 | |||
| 513 | That's all there is to it! | ||
| 514 | |||
| 515 | |||
diff --git a/mbregex/mbregex.h b/mbregex/mbregex.h new file mode 100644 index 0000000..03292bc --- /dev/null +++ b/mbregex/mbregex.h | |||
| @@ -0,0 +1,213 @@ | |||
| 1 | /* Definitions for data structures and routines for the regular | ||
| 2 | expression library, version 0.12. | ||
| 3 | Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of the GNU C Library. Its master source is NOT part of | ||
| 6 | the C library, however. The master source lives in /gd/gnu/lib. | ||
| 7 | |||
| 8 | The GNU C Library is free software; you can redistribute it and/or | ||
| 9 | modify it under the terms of the GNU Library General Public License as | ||
| 10 | published by the Free Software Foundation; either version 2 of the | ||
| 11 | License, or (at your option) any later version. | ||
| 12 | |||
| 13 | The GNU C Library is distributed in the hope that it will be useful, | ||
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | Library General Public License for more details. | ||
| 17 | |||
| 18 | You should have received a copy of the GNU Library General Public | ||
| 19 | License along with the GNU C Library; see the file COPYING.LIB. If not, | ||
| 20 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 21 | Boston, MA 02111-1307, USA. */ | ||
| 22 | /* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) | ||
| 23 | Last change: May 21, 1993 by t^2 */ | ||
| 24 | /* modified for Ruby by matz@netlab.co.jp */ | ||
| 25 | |||
| 26 | #ifndef __MB_REGEXP_LIBRARY | ||
| 27 | #define __MB_REGEXP_LIBRARY | ||
| 28 | |||
| 29 | #include <stddef.h> | ||
| 30 | |||
| 31 | /* Define number of parens for which we record the beginnings and ends. | ||
| 32 | This affects how much space the `struct re_registers' type takes up. */ | ||
| 33 | #ifndef MBRE_NREGS | ||
| 34 | #define MBRE_NREGS 10 | ||
| 35 | #endif | ||
| 36 | |||
| 37 | #define MBRE_BYTEWIDTH 8 | ||
| 38 | |||
| 39 | #define MBRE_REG_MAX ((1<<MBRE_BYTEWIDTH)-1) | ||
| 40 | |||
| 41 | /* Maximum number of duplicates an interval can allow. */ | ||
| 42 | #ifndef MBRE_DUP_MAX | ||
| 43 | #define MBRE_DUP_MAX ((1 << 15) - 1) | ||
| 44 | #endif | ||
| 45 | |||
| 46 | |||
| 47 | /* If this bit is set, then character classes are supported; they are: | ||
| 48 | [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], | ||
| 49 | [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. | ||
| 50 | If not set, then character classes are not supported. */ | ||
| 51 | #define MBRE_CHAR_CLASSES (1L << 9) | ||
| 52 | |||
| 53 | /* match will be done case insensetively */ | ||
| 54 | #define MBRE_OPTION_IGNORECASE (1L) | ||
| 55 | /* perl-style extended pattern available */ | ||
| 56 | #define MBRE_OPTION_EXTENDED (MBRE_OPTION_IGNORECASE<<1) | ||
| 57 | /* newline will be included for . */ | ||
| 58 | #define MBRE_OPTION_MULTILINE (MBRE_OPTION_EXTENDED<<1) | ||
| 59 | /* ^ and $ ignore newline */ | ||
| 60 | #define MBRE_OPTION_SINGLELINE (MBRE_OPTION_MULTILINE<<1) | ||
| 61 | /* works line Perl's /s; it's called POSIX for wrong reason */ | ||
| 62 | #define MBRE_OPTION_POSIXLINE (MBRE_OPTION_MULTILINE|MBRE_OPTION_SINGLELINE) | ||
| 63 | /* search for longest match, in accord with POSIX regexp */ | ||
| 64 | #define MBRE_OPTION_LONGEST (MBRE_OPTION_SINGLELINE<<1) | ||
| 65 | |||
| 66 | #define MBRE_MAY_IGNORECASE (MBRE_OPTION_LONGEST<<1) | ||
| 67 | #define MBRE_OPTIMIZE_ANCHOR (MBRE_MAY_IGNORECASE<<1) | ||
| 68 | #define MBRE_OPTIMIZE_EXACTN (MBRE_OPTIMIZE_ANCHOR<<1) | ||
| 69 | #define MBRE_OPTIMIZE_NO_BM (MBRE_OPTIMIZE_EXACTN<<1) | ||
| 70 | #define MBRE_OPTIMIZE_BMATCH (MBRE_OPTIMIZE_NO_BM<<1) | ||
| 71 | |||
| 72 | /* For multi-byte char support */ | ||
| 73 | #define MBCTYPE_ASCII 0 | ||
| 74 | #define MBCTYPE_EUC 1 | ||
| 75 | #define MBCTYPE_SJIS 2 | ||
| 76 | #define MBCTYPE_UTF8 3 | ||
| 77 | |||
| 78 | #if 0 | ||
| 79 | #if defined IMPORT || defined USEIMPORTLIB | ||
| 80 | extern __declspec(dllimport) | ||
| 81 | #elif defined EXPORT | ||
| 82 | extern __declspec(dllexport) | ||
| 83 | #else | ||
| 84 | extern | ||
| 85 | #endif | ||
| 86 | const unsigned char *re_mbctab; | ||
| 87 | #if defined(__STDC__) | ||
| 88 | void re_mbcinit (int); | ||
| 89 | #else | ||
| 90 | void re_mbcinit (); | ||
| 91 | #endif | ||
| 92 | #endif | ||
| 93 | |||
| 94 | #undef ismbchar | ||
| 95 | #define ismbchar(c) re_mbctab[(unsigned char)(c)] | ||
| 96 | #define mbclen(c) (re_mbctab[(unsigned char)(c)]+1) | ||
| 97 | |||
| 98 | /* Structure used in re_match() */ | ||
| 99 | |||
| 100 | typedef union | ||
| 101 | { | ||
| 102 | unsigned char *word; | ||
| 103 | struct { | ||
| 104 | unsigned is_active : 1; | ||
| 105 | unsigned matched_something : 1; | ||
| 106 | } bits; | ||
| 107 | } mbre_register_info_type; | ||
| 108 | |||
| 109 | /* This data structure is used to represent a compiled pattern. */ | ||
| 110 | |||
| 111 | struct mbre_pattern_buffer | ||
| 112 | { | ||
| 113 | char *buffer; /* Space holding the compiled pattern commands. */ | ||
| 114 | int allocated; /* Size of space that `buffer' points to. */ | ||
| 115 | int used; /* Length of portion of buffer actually occupied */ | ||
| 116 | char *fastmap; /* Pointer to fastmap, if any, or zero if none. */ | ||
| 117 | /* re_search uses the fastmap, if there is one, | ||
| 118 | to skip over totally implausible characters. */ | ||
| 119 | char *must; /* Pointer to exact pattern which strings should have | ||
| 120 | to be matched. */ | ||
| 121 | int *must_skip; /* Pointer to exact pattern skip table for bm_search */ | ||
| 122 | char *stclass; /* Pointer to character class list at top */ | ||
| 123 | long options; /* Flags for options such as extended_pattern. */ | ||
| 124 | long re_nsub; /* Number of subexpressions found by the compiler. */ | ||
| 125 | char fastmap_accurate; | ||
| 126 | /* Set to zero when a new pattern is stored, | ||
| 127 | set to one when the fastmap is updated from it. */ | ||
| 128 | char can_be_null; /* Set to one by compiling fastmap | ||
| 129 | if this pattern might match the null string. | ||
| 130 | It does not necessarily match the null string | ||
| 131 | in that case, but if this is zero, it cannot. | ||
| 132 | 2 as value means can match null string | ||
| 133 | but at end of range or before a character | ||
| 134 | listed in the fastmap. */ | ||
| 135 | |||
| 136 | /* stack & working area for re_match() */ | ||
| 137 | unsigned char **regstart; | ||
| 138 | unsigned char **regend; | ||
| 139 | unsigned char **old_regstart; | ||
| 140 | unsigned char **old_regend; | ||
| 141 | mbre_register_info_type *reg_info; | ||
| 142 | unsigned char **best_regstart; | ||
| 143 | unsigned char **best_regend; | ||
| 144 | |||
| 145 | int mbctype; | ||
| 146 | }; | ||
| 147 | |||
| 148 | typedef struct mbre_pattern_buffer mb_regex_t; | ||
| 149 | |||
| 150 | /* Structure to store register contents data in. | ||
| 151 | |||
| 152 | Pass the address of such a structure as an argument to re_match, etc., | ||
| 153 | if you want this information back. | ||
| 154 | |||
| 155 | For i from 1 to MBRE_NREGS - 1, start[i] records the starting index in | ||
| 156 | the string of where the ith subexpression matched, and end[i] records | ||
| 157 | one after the ending index. start[0] and end[0] are analogous, for | ||
| 158 | the entire pattern. */ | ||
| 159 | |||
| 160 | struct mbre_registers | ||
| 161 | { | ||
| 162 | int allocated; | ||
| 163 | int num_regs; | ||
| 164 | int *beg; | ||
| 165 | int *end; | ||
| 166 | }; | ||
| 167 | |||
| 168 | #if 0 | ||
| 169 | /* Type for byte offsets within the string. POSIX mandates this. */ | ||
| 170 | typedef size_t regoff_t; | ||
| 171 | |||
| 172 | /* POSIX specification for registers. Aside from the different names than | ||
| 173 | `mbre_registers', POSIX uses an array of structures, instead of a | ||
| 174 | structure of arrays. */ | ||
| 175 | typedef struct | ||
| 176 | { | ||
| 177 | regoff_t rm_so; /* Byte offset from string's start to substring's start. */ | ||
| 178 | regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ | ||
| 179 | } regmatch_t; | ||
| 180 | #endif | ||
| 181 | |||
| 182 | |||
| 183 | #ifdef __STDC__ | ||
| 184 | |||
| 185 | extern char *mbre_compile_pattern (const char *, int, struct mbre_pattern_buffer *); | ||
| 186 | void mbre_free_pattern (struct mbre_pattern_buffer *); | ||
| 187 | /* Is this really advertised? */ | ||
| 188 | extern int mbre_adjust_startpos (struct mbre_pattern_buffer *, const char*, int, int, int); | ||
| 189 | extern void mbre_compile_fastmap (struct mbre_pattern_buffer *); | ||
| 190 | extern int mbre_search (struct mbre_pattern_buffer *, const char*, int, int, int, | ||
| 191 | struct mbre_registers *); | ||
| 192 | extern int mbre_match (struct mbre_pattern_buffer *, const char *, int, int, | ||
| 193 | struct mbre_registers *); | ||
| 194 | extern void mbre_set_casetable (const char *table); | ||
| 195 | extern void mbre_copy_registers (struct mbre_registers*, struct mbre_registers*); | ||
| 196 | extern void mbre_free_registers (struct mbre_registers*); | ||
| 197 | |||
| 198 | #else /* !__STDC__ */ | ||
| 199 | |||
| 200 | extern char *mbre_compile_pattern (); | ||
| 201 | void mbre_free_pattern (); | ||
| 202 | /* Is this really advertised? */ | ||
| 203 | extern int mbre_adjust_startpos (); | ||
| 204 | extern void mbre_compile_fastmap (); | ||
| 205 | extern int mbre_search (); | ||
| 206 | extern int mbre_match (); | ||
| 207 | extern void mbre_set_casetable (); | ||
| 208 | extern void mbre_copy_registers (); | ||
| 209 | extern void mbre_free_registers (); | ||
| 210 | |||
| 211 | #endif /* __STDC__ */ | ||
| 212 | |||
| 213 | #endif /* !__MB_REGEXP_LIBRARY */ | ||
diff --git a/memory_limit.c b/memory_limit.c new file mode 100644 index 0000000..fd54301 --- /dev/null +++ b/memory_limit.c | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: memory_limit.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "ext/standard/info.h" | ||
| 30 | #include "php_suhosin.h" | ||
| 31 | |||
| 32 | |||
| 33 | /* {{{ PHP_INI_MH | ||
| 34 | */ | ||
| 35 | static PHP_INI_MH(suhosin_OnChangeMemoryLimit) | ||
| 36 | { | ||
| 37 | long hard_memory_limit = 1<<30; | ||
| 38 | |||
| 39 | if (stage == ZEND_INI_STAGE_RUNTIME) { | ||
| 40 | if (SUHOSIN_G(memory_limit) > 0) { | ||
| 41 | SUHOSIN_G(hard_memory_limit) = SUHOSIN_G(memory_limit); | ||
| 42 | } else if (SUHOSIN_G(hard_memory_limit) == 0) { | ||
| 43 | SUHOSIN_G(hard_memory_limit) = PG(memory_limit); | ||
| 44 | } | ||
| 45 | hard_memory_limit = SUHOSIN_G(hard_memory_limit); | ||
| 46 | } else { | ||
| 47 | SUHOSIN_G(hard_memory_limit) = 0; | ||
| 48 | } | ||
| 49 | if (new_value) { | ||
| 50 | PG(memory_limit) = zend_atoi(new_value, new_value_length); | ||
| 51 | if (PG(memory_limit) > hard_memory_limit || PG(memory_limit) < 0) { | ||
| 52 | suhosin_log(S_MISC, "script tried to increase memory_limit to %u bytes which is above the allowed value", PG(memory_limit)); | ||
| 53 | if (!SUHOSIN_G(simulation)) { | ||
| 54 | PG(memory_limit) = hard_memory_limit; | ||
| 55 | return FAILURE; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | } else { | ||
| 59 | PG(memory_limit) = hard_memory_limit; | ||
| 60 | } | ||
| 61 | return zend_set_memory_limit(PG(memory_limit)); | ||
| 62 | } | ||
| 63 | /* }}} */ | ||
| 64 | |||
| 65 | |||
| 66 | void suhosin_hook_memory_limit() | ||
| 67 | { | ||
| 68 | zend_ini_entry *ini_entry; | ||
| 69 | TSRMLS_FETCH(); | ||
| 70 | |||
| 71 | /* check if we are compiled against memory_limit */ | ||
| 72 | if (zend_hash_find(EG(ini_directives), "memory_limit", sizeof("memory_limit"), (void **) &ini_entry)==FAILURE) { | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* replace OnUpdateMemoryLimit handler */ | ||
| 77 | ini_entry->on_modify = suhosin_OnChangeMemoryLimit; | ||
| 78 | } | ||
| 79 | |||
| 80 | |||
| 81 | /* | ||
| 82 | * Local variables: | ||
| 83 | * tab-width: 4 | ||
| 84 | * c-basic-offset: 4 | ||
| 85 | * End: | ||
| 86 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 87 | * vim<600: noet sw=4 ts=4 | ||
| 88 | */ | ||
| 89 | |||
| 90 | |||
diff --git a/php_suhosin.h b/php_suhosin.h new file mode 100644 index 0000000..56869ec --- /dev/null +++ b/php_suhosin.h | |||
| @@ -0,0 +1,420 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: php_suhosin.h,v 1.4 2008-01-13 22:50:37 sesser Exp $ */ | ||
| 21 | |||
| 22 | #ifndef PHP_SUHOSIN_H | ||
| 23 | #define PHP_SUHOSIN_H | ||
| 24 | |||
| 25 | #define SUHOSIN_EXT_VERSION "0.9.29" | ||
| 26 | |||
| 27 | /*#define SUHOSIN_DEBUG*/ | ||
| 28 | #define SUHOSIN_LOG "/tmp/suhosin_log.txt" | ||
| 29 | |||
| 30 | #ifdef PHP_WIN32 | ||
| 31 | #define SDEBUG | ||
| 32 | #else | ||
| 33 | |||
| 34 | #ifdef SUHOSIN_DEBUG | ||
| 35 | #define SDEBUG(msg...) \ | ||
| 36 | {FILE *f;f=fopen(SUHOSIN_LOG, "a+");if(f){fprintf(f,"[%u] ",getpid());fprintf(f, msg);fprintf(f,"\n");fclose(f);}} | ||
| 37 | #else | ||
| 38 | #define SDEBUG(...) | ||
| 39 | #endif | ||
| 40 | #endif | ||
| 41 | |||
| 42 | extern zend_module_entry suhosin_module_entry; | ||
| 43 | #define phpext_suhosin_ptr &suhosin_module_entry | ||
| 44 | |||
| 45 | #ifdef PHP_WIN32 | ||
| 46 | #define PHP_SUHOSIN_API __declspec(dllexport) | ||
| 47 | #else | ||
| 48 | #define PHP_SUHOSIN_API | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #ifdef ZTS | ||
| 52 | #include "TSRM.h" | ||
| 53 | #endif | ||
| 54 | |||
| 55 | /*#define STATIC static*/ | ||
| 56 | #define STATIC | ||
| 57 | |||
| 58 | #define BYTE unsigned char /* 8 bits */ | ||
| 59 | #define WORD unsigned int /* 32 bits */ | ||
| 60 | |||
| 61 | PHP_MINIT_FUNCTION(suhosin); | ||
| 62 | PHP_MSHUTDOWN_FUNCTION(suhosin); | ||
| 63 | PHP_RINIT_FUNCTION(suhosin); | ||
| 64 | PHP_RSHUTDOWN_FUNCTION(suhosin); | ||
| 65 | PHP_MINFO_FUNCTION(suhosin); | ||
| 66 | |||
| 67 | #include "ext/standard/basic_functions.h" | ||
| 68 | |||
| 69 | ZEND_BEGIN_MODULE_GLOBALS(suhosin) | ||
| 70 | zend_uint in_code_type; | ||
| 71 | long execution_depth; | ||
| 72 | zend_bool simulation; | ||
| 73 | zend_bool stealth; | ||
| 74 | zend_bool protectkey; | ||
| 75 | zend_bool executor_allow_symlink; | ||
| 76 | char *filter_action; | ||
| 77 | char *sql_user_prefix; | ||
| 78 | char *sql_user_postfix; | ||
| 79 | long sql_comment; | ||
| 80 | long sql_opencomment; | ||
| 81 | long sql_union; | ||
| 82 | long sql_mselect; | ||
| 83 | |||
| 84 | long max_execution_depth; | ||
| 85 | zend_bool abort_request; | ||
| 86 | long executor_include_max_traversal; | ||
| 87 | zend_bool executor_include_allow_writable_files; | ||
| 88 | |||
| 89 | |||
| 90 | HashTable *include_whitelist; | ||
| 91 | HashTable *include_blacklist; | ||
| 92 | |||
| 93 | HashTable *func_whitelist; | ||
| 94 | HashTable *func_blacklist; | ||
| 95 | HashTable *eval_whitelist; | ||
| 96 | HashTable *eval_blacklist; | ||
| 97 | |||
| 98 | zend_bool executor_disable_eval; | ||
| 99 | zend_bool executor_disable_emod; | ||
| 100 | |||
| 101 | |||
| 102 | /* request variables */ | ||
| 103 | long max_request_variables; | ||
| 104 | long cur_request_variables; | ||
| 105 | long max_varname_length; | ||
| 106 | long max_totalname_length; | ||
| 107 | long max_value_length; | ||
| 108 | long max_array_depth; | ||
| 109 | long max_array_index_length; | ||
| 110 | zend_bool disallow_nul; | ||
| 111 | zend_bool disallow_ws; | ||
| 112 | /* cookie variables */ | ||
| 113 | long max_cookie_vars; | ||
| 114 | long cur_cookie_vars; | ||
| 115 | long max_cookie_name_length; | ||
| 116 | long max_cookie_totalname_length; | ||
| 117 | long max_cookie_value_length; | ||
| 118 | long max_cookie_array_depth; | ||
| 119 | long max_cookie_array_index_length; | ||
| 120 | zend_bool disallow_cookie_nul; | ||
| 121 | zend_bool disallow_cookie_ws; | ||
| 122 | /* get variables */ | ||
| 123 | long max_get_vars; | ||
| 124 | long cur_get_vars; | ||
| 125 | long max_get_name_length; | ||
| 126 | long max_get_totalname_length; | ||
| 127 | long max_get_value_length; | ||
| 128 | long max_get_array_depth; | ||
| 129 | long max_get_array_index_length; | ||
| 130 | zend_bool disallow_get_nul; | ||
| 131 | zend_bool disallow_get_ws; | ||
| 132 | /* post variables */ | ||
| 133 | long max_post_vars; | ||
| 134 | long cur_post_vars; | ||
| 135 | long max_post_name_length; | ||
| 136 | long max_post_totalname_length; | ||
| 137 | long max_post_value_length; | ||
| 138 | long max_post_array_depth; | ||
| 139 | long max_post_array_index_length; | ||
| 140 | zend_bool disallow_post_nul; | ||
| 141 | zend_bool disallow_post_ws; | ||
| 142 | |||
| 143 | /* fileupload */ | ||
| 144 | long upload_limit; | ||
| 145 | long num_uploads; | ||
| 146 | zend_bool upload_disallow_elf; | ||
| 147 | zend_bool upload_disallow_binary; | ||
| 148 | zend_bool upload_remove_binary; | ||
| 149 | char *upload_verification_script; | ||
| 150 | |||
| 151 | zend_bool no_more_variables; | ||
| 152 | zend_bool no_more_get_variables; | ||
| 153 | zend_bool no_more_post_variables; | ||
| 154 | zend_bool no_more_cookie_variables; | ||
| 155 | zend_bool no_more_uploads; | ||
| 156 | |||
| 157 | |||
| 158 | |||
| 159 | /* log */ | ||
| 160 | zend_bool log_use_x_forwarded_for; | ||
| 161 | long log_syslog; | ||
| 162 | long log_syslog_facility; | ||
| 163 | long log_syslog_priority; | ||
| 164 | long log_script; | ||
| 165 | long log_sapi; | ||
| 166 | char *log_scriptname; | ||
| 167 | long log_phpscript; | ||
| 168 | char *log_phpscriptname; | ||
| 169 | zend_bool log_phpscript_is_safe; | ||
| 170 | long log_file; | ||
| 171 | char *log_filename; | ||
| 172 | |||
| 173 | /* header handler */ | ||
| 174 | zend_bool allow_multiheader; | ||
| 175 | |||
| 176 | /* mailprotect */ | ||
| 177 | long mailprotect; | ||
| 178 | |||
| 179 | /* memory_limit */ | ||
| 180 | long memory_limit; | ||
| 181 | long hard_memory_limit; | ||
| 182 | |||
| 183 | /* sqlprotect */ | ||
| 184 | zend_bool sql_bailout_on_error; | ||
| 185 | |||
| 186 | int (*old_php_body_write)(const char *str, unsigned int str_length TSRMLS_DC); | ||
| 187 | |||
| 188 | /* session */ | ||
| 189 | void *s_module; | ||
| 190 | int (*old_s_read)(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC); | ||
| 191 | int (*old_s_write)(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC); | ||
| 192 | int (*old_s_destroy)(void **mod_data, const char *key TSRMLS_DC); | ||
| 193 | |||
| 194 | BYTE fi[24],ri[24]; | ||
| 195 | WORD fkey[120]; | ||
| 196 | WORD rkey[120]; | ||
| 197 | |||
| 198 | zend_bool session_encrypt; | ||
| 199 | char* session_cryptkey; | ||
| 200 | zend_bool session_cryptua; | ||
| 201 | zend_bool session_cryptdocroot; | ||
| 202 | long session_cryptraddr; | ||
| 203 | long session_checkraddr; | ||
| 204 | |||
| 205 | long session_max_id_length; | ||
| 206 | |||
| 207 | char* decrypted_cookie; | ||
| 208 | char* raw_cookie; | ||
| 209 | zend_bool cookie_encrypt; | ||
| 210 | char* cookie_cryptkey; | ||
| 211 | zend_bool cookie_cryptua; | ||
| 212 | zend_bool cookie_cryptdocroot; | ||
| 213 | long cookie_cryptraddr; | ||
| 214 | long cookie_checkraddr; | ||
| 215 | HashTable *cookie_plainlist; | ||
| 216 | HashTable *cookie_cryptlist; | ||
| 217 | |||
| 218 | zend_bool coredump; | ||
| 219 | zend_bool apc_bug_workaround; | ||
| 220 | zend_bool already_scanned; | ||
| 221 | zend_bool do_not_scan; | ||
| 222 | |||
| 223 | zend_bool server_encode; | ||
| 224 | zend_bool server_strip; | ||
| 225 | |||
| 226 | zend_bool disable_display_errors; | ||
| 227 | |||
| 228 | php_uint32 r_state[625]; | ||
| 229 | php_uint32 *r_next; | ||
| 230 | int r_left; | ||
| 231 | zend_bool srand_ignore; | ||
| 232 | zend_bool mt_srand_ignore; | ||
| 233 | php_uint32 mt_state[625]; | ||
| 234 | php_uint32 *mt_next; | ||
| 235 | int mt_left; | ||
| 236 | |||
| 237 | zend_bool r_is_seeded; | ||
| 238 | zend_bool mt_is_seeded; | ||
| 239 | |||
| 240 | /* PERDIR Handling */ | ||
| 241 | char *perdir; | ||
| 242 | zend_bool log_perdir; | ||
| 243 | zend_bool exec_perdir; | ||
| 244 | zend_bool get_perdir; | ||
| 245 | zend_bool post_perdir; | ||
| 246 | zend_bool cookie_perdir; | ||
| 247 | zend_bool request_perdir; | ||
| 248 | zend_bool upload_perdir; | ||
| 249 | zend_bool sql_perdir; | ||
| 250 | zend_bool misc_perdir; | ||
| 251 | |||
| 252 | ZEND_END_MODULE_GLOBALS(suhosin) | ||
| 253 | |||
| 254 | #ifdef ZTS | ||
| 255 | #define SUHOSIN_G(v) TSRMG(suhosin_globals_id, zend_suhosin_globals *, v) | ||
| 256 | #else | ||
| 257 | #define SUHOSIN_G(v) (suhosin_globals.v) | ||
| 258 | #endif | ||
| 259 | |||
| 260 | #ifndef ZEND_INI_STAGE_HTACCESS | ||
| 261 | #define ZEND_INI_STAGE_HTACCESS (1<<5) | ||
| 262 | #endif | ||
| 263 | |||
| 264 | #ifndef ZEND_ENGINE_2 | ||
| 265 | #define OnUpdateLong OnUpdateInt | ||
| 266 | #define zend_symtable_find zend_hash_find | ||
| 267 | #define zend_symtable_update zend_hash_update | ||
| 268 | #define zend_symtable_exists zend_hash_exists | ||
| 269 | #endif | ||
| 270 | |||
| 271 | |||
| 272 | /* Error Constants */ | ||
| 273 | #ifndef S_MEMORY | ||
| 274 | #define S_MEMORY (1<<0L) | ||
| 275 | #define S_MISC (1<<1L) | ||
| 276 | #define S_VARS (1<<2L) | ||
| 277 | #define S_FILES (1<<3L) | ||
| 278 | #define S_INCLUDE (1<<4L) | ||
| 279 | #define S_SQL (1<<5L) | ||
| 280 | #define S_EXECUTOR (1<<6L) | ||
| 281 | #define S_MAIL (1<<7L) | ||
| 282 | #define S_SESSION (1<<8L) | ||
| 283 | #define S_INTERNAL (1<<29L) | ||
| 284 | #define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR) | ||
| 285 | #endif | ||
| 286 | |||
| 287 | #define SUHOSIN_NORMAL 0 | ||
| 288 | #define SUHOSIN_EVAL 1 | ||
| 289 | |||
| 290 | #define SUHOSIN_FLAG_CREATED_BY_EVAL 1 | ||
| 291 | #define SUHOSIN_FLAG_NOT_EVALED_CODE 2 | ||
| 292 | |||
| 293 | ZEND_EXTERN_MODULE_GLOBALS(suhosin) | ||
| 294 | |||
| 295 | static inline char * | ||
| 296 | suhosin_str_tolower_dup(const char *source, unsigned int length) | ||
| 297 | { | ||
| 298 | register char *dup = estrndup(source, length); | ||
| 299 | zend_str_tolower(dup, length); | ||
| 300 | return dup; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* functions */ | ||
| 304 | PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...); | ||
| 305 | char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC); | ||
| 306 | char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, char *key, int *orig_len, int check_ra TSRMLS_DC); | ||
| 307 | char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC); | ||
| 308 | char *suhosin_cookie_decryptor(TSRMLS_D); | ||
| 309 | void suhosin_hook_post_handlers(TSRMLS_D); | ||
| 310 | void suhosin_hook_register_server_variables(); | ||
| 311 | void suhosin_hook_header_handler(); | ||
| 312 | void suhosin_unhook_header_handler(); | ||
| 313 | void suhosin_hook_session(TSRMLS_D); | ||
| 314 | void suhosin_unhook_session(TSRMLS_D); | ||
| 315 | void suhosin_hook_crypt(); | ||
| 316 | void suhosin_hook_sha256(); | ||
| 317 | void suhosin_hook_ex_imp(); | ||
| 318 | void suhosin_hook_treat_data(); | ||
| 319 | void suhosin_hook_memory_limit(); | ||
| 320 | void suhosin_hook_execute(TSRMLS_D); | ||
| 321 | void suhosin_unhook_execute(); | ||
| 322 | void suhosin_aes_gentables(); | ||
| 323 | void suhosin_aes_gkey(int nb,int nk,char *key TSRMLS_DC); | ||
| 324 | void suhosin_aes_encrypt(char *buff TSRMLS_DC); | ||
| 325 | void suhosin_aes_decrypt(char *buff TSRMLS_DC); | ||
| 326 | unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC); | ||
| 327 | unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC); | ||
| 328 | extern unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC); | ||
| 329 | void normalize_varname(char *varname); | ||
| 330 | int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC); | ||
| 331 | void suhosin_bailout(TSRMLS_D); | ||
| 332 | |||
| 333 | /* Add pseudo refcount macros for PHP version < 5.3 */ | ||
| 334 | #ifndef Z_REFCOUNT_PP | ||
| 335 | |||
| 336 | #define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) | ||
| 337 | #define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) | ||
| 338 | #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) | ||
| 339 | #define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz)) | ||
| 340 | #define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) | ||
| 341 | #define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) | ||
| 342 | #define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) | ||
| 343 | #define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref) | ||
| 344 | |||
| 345 | #define Z_REFCOUNT_P(pz) zval_refcount_p(pz) | ||
| 346 | #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) | ||
| 347 | #define Z_ADDREF_P(pz) zval_addref_p(pz) | ||
| 348 | #define Z_DELREF_P(pz) zval_delref_p(pz) | ||
| 349 | #define Z_ISREF_P(pz) zval_isref_p(pz) | ||
| 350 | #define Z_SET_ISREF_P(pz) zval_set_isref_p(pz) | ||
| 351 | #define Z_UNSET_ISREF_P(pz) zval_unset_isref_p(pz) | ||
| 352 | #define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref) | ||
| 353 | |||
| 354 | #define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) | ||
| 355 | #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc) | ||
| 356 | #define Z_ADDREF(z) Z_ADDREF_P(&(z)) | ||
| 357 | #define Z_DELREF(z) Z_DELREF_P(&(z)) | ||
| 358 | #define Z_ISREF(z) Z_ISREF_P(&(z)) | ||
| 359 | #define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z)) | ||
| 360 | #define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z)) | ||
| 361 | #define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref) | ||
| 362 | |||
| 363 | #if defined(__GNUC__) | ||
| 364 | #define zend_always_inline inline __attribute__((always_inline)) | ||
| 365 | #elif defined(_MSC_VER) | ||
| 366 | #define zend_always_inline __forceinline | ||
| 367 | #else | ||
| 368 | #define zend_always_inline inline | ||
| 369 | #endif | ||
| 370 | |||
| 371 | static zend_always_inline zend_uint zval_refcount_p(zval* pz) { | ||
| 372 | return pz->refcount; | ||
| 373 | } | ||
| 374 | |||
| 375 | static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) { | ||
| 376 | return pz->refcount = rc; | ||
| 377 | } | ||
| 378 | |||
| 379 | static zend_always_inline zend_uint zval_addref_p(zval* pz) { | ||
| 380 | return ++pz->refcount; | ||
| 381 | } | ||
| 382 | |||
| 383 | static zend_always_inline zend_uint zval_delref_p(zval* pz) { | ||
| 384 | return --pz->refcount; | ||
| 385 | } | ||
| 386 | |||
| 387 | static zend_always_inline zend_bool zval_isref_p(zval* pz) { | ||
| 388 | return pz->is_ref; | ||
| 389 | } | ||
| 390 | |||
| 391 | static zend_always_inline zend_bool zval_set_isref_p(zval* pz) { | ||
| 392 | return pz->is_ref = 1; | ||
| 393 | } | ||
| 394 | |||
| 395 | static zend_always_inline zend_bool zval_unset_isref_p(zval* pz) { | ||
| 396 | return pz->is_ref = 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static zend_always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref) { | ||
| 400 | return pz->is_ref = isref; | ||
| 401 | } | ||
| 402 | |||
| 403 | #else | ||
| 404 | |||
| 405 | #define PHP_ATLEAST_5_3 true | ||
| 406 | |||
| 407 | #endif | ||
| 408 | |||
| 409 | |||
| 410 | #endif /* PHP_SUHOSIN_H */ | ||
| 411 | |||
| 412 | |||
| 413 | /* | ||
| 414 | * Local variables: | ||
| 415 | * tab-width: 4 | ||
| 416 | * c-basic-offset: 4 | ||
| 417 | * End: | ||
| 418 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 419 | * vim<600: noet sw=4 ts=4 | ||
| 420 | */ | ||
diff --git a/post_handler.c b/post_handler.c new file mode 100644 index 0000000..a7ac060 --- /dev/null +++ b/post_handler.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: post_handler.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "php_suhosin.h" | ||
| 30 | #include "SAPI.h" | ||
| 31 | #include "php_variables.h" | ||
| 32 | #include "php_content_types.h" | ||
| 33 | #include "suhosin_rfc1867.h" | ||
| 34 | #include "ext/standard/url.h" | ||
| 35 | |||
| 36 | SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler); | ||
| 37 | |||
| 38 | |||
| 39 | SAPI_POST_HANDLER_FUNC(suhosin_std_post_handler) | ||
| 40 | { | ||
| 41 | char *var, *val, *e, *s, *p; | ||
| 42 | zval *array_ptr = (zval *) arg; | ||
| 43 | |||
| 44 | if (SG(request_info).post_data==NULL) { | ||
| 45 | return; | ||
| 46 | } | ||
| 47 | |||
| 48 | s = SG(request_info).post_data; | ||
| 49 | e = s + SG(request_info).post_data_length; | ||
| 50 | |||
| 51 | while (s < e && (p = memchr(s, '&', (e - s)))) { | ||
| 52 | last_value: | ||
| 53 | if ((val = memchr(s, '=', (p - s)))) { /* have a value */ | ||
| 54 | unsigned int val_len, new_val_len; | ||
| 55 | var = s; | ||
| 56 | |||
| 57 | php_url_decode(var, (val - s)); | ||
| 58 | val++; | ||
| 59 | val_len = php_url_decode(val, (p - val)); | ||
| 60 | val = estrndup(val, val_len); | ||
| 61 | if (suhosin_input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) { | ||
| 62 | #ifdef ZEND_ENGINE_2 | ||
| 63 | if (sapi_module.input_filter(PARSE_POST, var, &val, new_val_len, &new_val_len TSRMLS_CC)) { | ||
| 64 | #endif | ||
| 65 | php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); | ||
| 66 | #ifdef ZEND_ENGINE_2 | ||
| 67 | } | ||
| 68 | #endif | ||
| 69 | } else { | ||
| 70 | SUHOSIN_G(abort_request)=1; | ||
| 71 | } | ||
| 72 | efree(val); | ||
| 73 | } | ||
| 74 | s = p + 1; | ||
| 75 | } | ||
| 76 | if (s < e) { | ||
| 77 | p = e; | ||
| 78 | goto last_value; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | /* {{{ php_post_entries[] | ||
| 83 | */ | ||
| 84 | static sapi_post_entry suhosin_post_entries[] = { | ||
| 85 | { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, suhosin_std_post_handler }, | ||
| 86 | { MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, NULL, suhosin_rfc1867_post_handler }, | ||
| 87 | { NULL, 0, NULL, NULL } | ||
| 88 | }; | ||
| 89 | /* }}} */ | ||
| 90 | |||
| 91 | void suhosin_hook_post_handlers(TSRMLS_D) | ||
| 92 | { | ||
| 93 | #if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 0) | ||
| 94 | sapi_unregister_post_entry(&suhosin_post_entries[0] TSRMLS_CC); | ||
| 95 | sapi_unregister_post_entry(&suhosin_post_entries[1] TSRMLS_CC); | ||
| 96 | sapi_register_post_entries(suhosin_post_entries TSRMLS_CC); | ||
| 97 | #else | ||
| 98 | sapi_unregister_post_entry(&suhosin_post_entries[0]); | ||
| 99 | sapi_unregister_post_entry(&suhosin_post_entries[1]); | ||
| 100 | sapi_register_post_entries(suhosin_post_entries); | ||
| 101 | #endif | ||
| 102 | } | ||
| 103 | |||
| 104 | |||
| 105 | /* | ||
| 106 | * Local variables: | ||
| 107 | * tab-width: 4 | ||
| 108 | * c-basic-offset: 4 | ||
| 109 | * End: | ||
| 110 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 111 | * vim<600: noet sw=4 ts=4 | ||
| 112 | */ | ||
| 113 | |||
| 114 | |||
diff --git a/rfc1867.c b/rfc1867.c new file mode 100644 index 0000000..9e819c2 --- /dev/null +++ b/rfc1867.c | |||
| @@ -0,0 +1,1355 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | PHP Version 5 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 1997-2006 The PHP Group | | ||
| 6 | +----------------------------------------------------------------------+ | ||
| 7 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 8 | | that is bundled with this package in the file LICENSE, and is | | ||
| 9 | | available through the world-wide-web at the following url: | | ||
| 10 | | http://www.php.net/license/3_01.txt | | ||
| 11 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 12 | | obtain it through the world-wide-web, please send a note to | | ||
| 13 | | license@php.net so we can mail you a copy immediately. | | ||
| 14 | +----------------------------------------------------------------------+ | ||
| 15 | | Authors: Rasmus Lerdorf <rasmus@php.net> | | ||
| 16 | | Jani Taskinen <sniper@php.net> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: rfc1867.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 21 | |||
| 22 | /* | ||
| 23 | * This product includes software developed by the Apache Group | ||
| 24 | * for use in the Apache HTTP server project (http://www.apache.org/). | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <stdio.h> | ||
| 29 | #include "php.h" | ||
| 30 | #include "php_open_temporary_file.h" | ||
| 31 | #include "zend_globals.h" | ||
| 32 | #include "php_globals.h" | ||
| 33 | #include "php_variables.h" | ||
| 34 | #include "php_suhosin.h" | ||
| 35 | #include "suhosin_rfc1867.h" | ||
| 36 | |||
| 37 | #define DEBUG_FILE_UPLOAD ZEND_DEBUG | ||
| 38 | |||
| 39 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 40 | #include "ext/mbstring/mbstring.h" | ||
| 41 | |||
| 42 | static void safe_php_register_variable(char *var, char *strval, zval *track_vars_array, zend_bool override_protection TSRMLS_DC); | ||
| 43 | |||
| 44 | #define SAFE_RETURN { \ | ||
| 45 | php_mb_flush_gpc_variables(num_vars, val_list, len_list, array_ptr TSRMLS_CC); \ | ||
| 46 | if (lbuf) efree(lbuf); \ | ||
| 47 | if (abuf) efree(abuf); \ | ||
| 48 | if (array_index) efree(array_index); \ | ||
| 49 | zend_hash_destroy(&PG(rfc1867_protected_variables)); \ | ||
| 50 | zend_llist_destroy(&header); \ | ||
| 51 | if (mbuff->boundary_next) efree(mbuff->boundary_next); \ | ||
| 52 | if (mbuff->boundary) efree(mbuff->boundary); \ | ||
| 53 | if (mbuff->buffer) efree(mbuff->buffer); \ | ||
| 54 | if (mbuff) efree(mbuff); \ | ||
| 55 | return; } | ||
| 56 | |||
| 57 | static void php_mb_flush_gpc_variables(int num_vars, char **val_list, int *len_list, zval *array_ptr TSRMLS_DC) | ||
| 58 | { | ||
| 59 | int i; | ||
| 60 | if (php_mb_encoding_translation(TSRMLS_C)) { | ||
| 61 | if (num_vars > 0 && | ||
| 62 | php_mb_gpc_encoding_detector(val_list, len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) { | ||
| 63 | php_mb_gpc_encoding_converter(val_list, len_list, num_vars, NULL, NULL TSRMLS_CC); | ||
| 64 | } | ||
| 65 | for (i=0; i<num_vars; i+=2){ | ||
| 66 | safe_php_register_variable(val_list[i], val_list[i+1], array_ptr, 0 TSRMLS_CC); | ||
| 67 | efree(val_list[i]); | ||
| 68 | efree(val_list[i+1]); | ||
| 69 | } | ||
| 70 | efree(val_list); | ||
| 71 | efree(len_list); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | static void php_mb_gpc_realloc_buffer(char ***pval_list, int **plen_list, int *num_vars_max, int inc TSRMLS_DC) | ||
| 76 | { | ||
| 77 | /* allow only even increments */ | ||
| 78 | if (inc & 1) { | ||
| 79 | inc++; | ||
| 80 | } | ||
| 81 | (*num_vars_max) += inc; | ||
| 82 | *pval_list = (char **)erealloc(*pval_list, (*num_vars_max+2)*sizeof(char *)); | ||
| 83 | *plen_list = (int *)erealloc(*plen_list, (*num_vars_max+2)*sizeof(int)); | ||
| 84 | } | ||
| 85 | |||
| 86 | static void php_mb_gpc_stack_variable(char *param, char *value, char ***pval_list, int **plen_list, int *num_vars, int *num_vars_max TSRMLS_DC) | ||
| 87 | { | ||
| 88 | char **val_list=*pval_list; | ||
| 89 | int *len_list=*plen_list; | ||
| 90 | |||
| 91 | if (*num_vars>=*num_vars_max){ | ||
| 92 | php_mb_gpc_realloc_buffer(pval_list, plen_list, num_vars_max, | ||
| 93 | 16 TSRMLS_CC); | ||
| 94 | /* in case realloc relocated the buffer */ | ||
| 95 | val_list = *pval_list; | ||
| 96 | len_list = *plen_list; | ||
| 97 | } | ||
| 98 | |||
| 99 | val_list[*num_vars] = (char *)estrdup(param); | ||
| 100 | len_list[*num_vars] = strlen(param); | ||
| 101 | (*num_vars)++; | ||
| 102 | val_list[*num_vars] = (char *)estrdup(value); | ||
| 103 | len_list[*num_vars] = strlen(value); | ||
| 104 | (*num_vars)++; | ||
| 105 | } | ||
| 106 | |||
| 107 | #else | ||
| 108 | |||
| 109 | #define SAFE_RETURN { \ | ||
| 110 | if (lbuf) efree(lbuf); \ | ||
| 111 | if (abuf) efree(abuf); \ | ||
| 112 | if (array_index) efree(array_index); \ | ||
| 113 | zend_hash_destroy(&PG(rfc1867_protected_variables)); \ | ||
| 114 | zend_llist_destroy(&header); \ | ||
| 115 | if (mbuff->boundary_next) efree(mbuff->boundary_next); \ | ||
| 116 | if (mbuff->boundary) efree(mbuff->boundary); \ | ||
| 117 | if (mbuff->buffer) efree(mbuff->buffer); \ | ||
| 118 | if (mbuff) efree(mbuff); \ | ||
| 119 | return; } | ||
| 120 | #endif | ||
| 121 | |||
| 122 | /* The longest property name we use in an uploaded file array */ | ||
| 123 | #define MAX_SIZE_OF_INDEX sizeof("[tmp_name]") | ||
| 124 | |||
| 125 | /* The longest anonymous name */ | ||
| 126 | #define MAX_SIZE_ANONNAME 33 | ||
| 127 | |||
| 128 | /* Errors */ | ||
| 129 | #define UPLOAD_ERROR_OK 0 /* File upload succesful */ | ||
| 130 | #define UPLOAD_ERROR_A 1 /* Uploaded file exceeded upload_max_filesize */ | ||
| 131 | #define UPLOAD_ERROR_B 2 /* Uploaded file exceeded MAX_FILE_SIZE */ | ||
| 132 | #define UPLOAD_ERROR_C 3 /* Partially uploaded */ | ||
| 133 | #define UPLOAD_ERROR_D 4 /* No file uploaded */ | ||
| 134 | #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */ | ||
| 135 | #define UPLOAD_ERROR_F 7 /* Failed to write file to disk */ | ||
| 136 | #define UPLOAD_ERROR_X 8 /* File upload stopped by extension */ | ||
| 137 | |||
| 138 | /* | ||
| 139 | void php_rfc1867_register_constants(TSRMLS_D) | ||
| 140 | { | ||
| 141 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_OK", UPLOAD_ERROR_OK, CONST_CS | CONST_PERSISTENT); | ||
| 142 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_INI_SIZE", UPLOAD_ERROR_A, CONST_CS | CONST_PERSISTENT); | ||
| 143 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FORM_SIZE", UPLOAD_ERROR_B, CONST_CS | CONST_PERSISTENT); | ||
| 144 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT); | ||
| 145 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT); | ||
| 146 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT); | ||
| 147 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_CANT_WRITE", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT); | ||
| 148 | REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_EXTENSION", UPLOAD_ERROR_X, CONST_CS | CONST_PERSISTENT); | ||
| 149 | } | ||
| 150 | */ | ||
| 151 | |||
| 152 | static void normalize_protected_variable(char *varname TSRMLS_DC) | ||
| 153 | { | ||
| 154 | char *s=varname, *index=NULL, *indexend=NULL, *p; | ||
| 155 | |||
| 156 | /* overjump leading space */ | ||
| 157 | while (*s == ' ') { | ||
| 158 | s++; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* and remove it */ | ||
| 162 | if (s != varname) { | ||
| 163 | memmove(varname, s, strlen(s)+1); | ||
| 164 | } | ||
| 165 | |||
| 166 | for (p=varname; *p && *p != '['; p++) { | ||
| 167 | switch(*p) { | ||
| 168 | case ' ': | ||
| 169 | case '.': | ||
| 170 | *p='_'; | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | /* find index */ | ||
| 176 | index = strchr(varname, '['); | ||
| 177 | if (index) { | ||
| 178 | index++; | ||
| 179 | s=index; | ||
| 180 | } else { | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* done? */ | ||
| 185 | while (index) { | ||
| 186 | |||
| 187 | while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') { | ||
| 188 | index++; | ||
| 189 | } | ||
| 190 | indexend = strchr(index, ']'); | ||
| 191 | indexend = indexend ? indexend + 1 : index + strlen(index); | ||
| 192 | |||
| 193 | if (s != index) { | ||
| 194 | memmove(s, index, strlen(index)+1); | ||
| 195 | s += indexend-index; | ||
| 196 | } else { | ||
| 197 | s = indexend; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (*s == '[') { | ||
| 201 | s++; | ||
| 202 | index = s; | ||
| 203 | } else { | ||
| 204 | index = NULL; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | *s++='\0'; | ||
| 208 | } | ||
| 209 | |||
| 210 | |||
| 211 | static void add_protected_variable(char *varname TSRMLS_DC) | ||
| 212 | { | ||
| 213 | int dummy=1; | ||
| 214 | |||
| 215 | normalize_protected_variable(varname TSRMLS_CC); | ||
| 216 | zend_hash_add(&PG(rfc1867_protected_variables), varname, strlen(varname)+1, &dummy, sizeof(int), NULL); | ||
| 217 | } | ||
| 218 | |||
| 219 | |||
| 220 | static zend_bool is_protected_variable(char *varname TSRMLS_DC) | ||
| 221 | { | ||
| 222 | normalize_protected_variable(varname TSRMLS_CC); | ||
| 223 | return zend_hash_exists(&PG(rfc1867_protected_variables), varname, strlen(varname)+1); | ||
| 224 | } | ||
| 225 | |||
| 226 | |||
| 227 | static void safe_php_register_variable(char *var, char *strval, zval *track_vars_array, zend_bool override_protection TSRMLS_DC) | ||
| 228 | { | ||
| 229 | if (override_protection || !is_protected_variable(var TSRMLS_CC)) { | ||
| 230 | php_register_variable(var, strval, track_vars_array TSRMLS_CC); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | |||
| 235 | static void safe_php_register_variable_ex(char *var, zval *val, zval *track_vars_array, zend_bool override_protection TSRMLS_DC) | ||
| 236 | { | ||
| 237 | if (override_protection || !is_protected_variable(var TSRMLS_CC)) { | ||
| 238 | php_register_variable_ex(var, val, track_vars_array TSRMLS_CC); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | |||
| 243 | static void register_http_post_files_variable(char *strvar, char *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC) | ||
| 244 | { | ||
| 245 | int register_globals = PG(register_globals); | ||
| 246 | |||
| 247 | PG(register_globals) = 0; | ||
| 248 | safe_php_register_variable(strvar, val, http_post_files, override_protection TSRMLS_CC); | ||
| 249 | PG(register_globals) = register_globals; | ||
| 250 | } | ||
| 251 | |||
| 252 | |||
| 253 | static void register_http_post_files_variable_ex(char *var, zval *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC) | ||
| 254 | { | ||
| 255 | int register_globals = PG(register_globals); | ||
| 256 | |||
| 257 | PG(register_globals) = 0; | ||
| 258 | safe_php_register_variable_ex(var, val, http_post_files, override_protection TSRMLS_CC); | ||
| 259 | PG(register_globals) = register_globals; | ||
| 260 | } | ||
| 261 | |||
| 262 | /* | ||
| 263 | * Following code is based on apache_multipart_buffer.c from libapreq-0.33 package. | ||
| 264 | * | ||
| 265 | */ | ||
| 266 | |||
| 267 | #define FILLUNIT (1024 * 5) | ||
| 268 | |||
| 269 | typedef struct { | ||
| 270 | |||
| 271 | /* read buffer */ | ||
| 272 | char *buffer; | ||
| 273 | char *buf_begin; | ||
| 274 | int bufsize; | ||
| 275 | int bytes_in_buffer; | ||
| 276 | |||
| 277 | /* boundary info */ | ||
| 278 | char *boundary; | ||
| 279 | char *boundary_next; | ||
| 280 | int boundary_next_len; | ||
| 281 | |||
| 282 | } multipart_buffer; | ||
| 283 | |||
| 284 | |||
| 285 | typedef struct { | ||
| 286 | char *key; | ||
| 287 | char *value; | ||
| 288 | } mime_header_entry; | ||
| 289 | |||
| 290 | |||
| 291 | /* | ||
| 292 | fill up the buffer with client data. | ||
| 293 | returns number of bytes added to buffer. | ||
| 294 | */ | ||
| 295 | static int fill_buffer(multipart_buffer *self TSRMLS_DC) | ||
| 296 | { | ||
| 297 | int bytes_to_read, total_read = 0, actual_read = 0; | ||
| 298 | |||
| 299 | /* shift the existing data if necessary */ | ||
| 300 | if (self->bytes_in_buffer > 0 && self->buf_begin != self->buffer) { | ||
| 301 | memmove(self->buffer, self->buf_begin, self->bytes_in_buffer); | ||
| 302 | } | ||
| 303 | |||
| 304 | self->buf_begin = self->buffer; | ||
| 305 | |||
| 306 | /* calculate the free space in the buffer */ | ||
| 307 | bytes_to_read = self->bufsize - self->bytes_in_buffer; | ||
| 308 | |||
| 309 | /* read the required number of bytes */ | ||
| 310 | while (bytes_to_read > 0) { | ||
| 311 | |||
| 312 | char *buf = self->buffer + self->bytes_in_buffer; | ||
| 313 | |||
| 314 | actual_read = sapi_module.read_post(buf, bytes_to_read TSRMLS_CC); | ||
| 315 | |||
| 316 | /* update the buffer length */ | ||
| 317 | if (actual_read > 0) { | ||
| 318 | self->bytes_in_buffer += actual_read; | ||
| 319 | SG(read_post_bytes) += actual_read; | ||
| 320 | total_read += actual_read; | ||
| 321 | bytes_to_read -= actual_read; | ||
| 322 | } else { | ||
| 323 | break; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | return total_read; | ||
| 328 | } | ||
| 329 | |||
| 330 | |||
| 331 | /* eof if we are out of bytes, or if we hit the final boundary */ | ||
| 332 | static int multipart_buffer_eof(multipart_buffer *self TSRMLS_DC) | ||
| 333 | { | ||
| 334 | if ( (self->bytes_in_buffer == 0 && fill_buffer(self TSRMLS_CC) < 1) ) { | ||
| 335 | return 1; | ||
| 336 | } else { | ||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | |||
| 342 | /* create new multipart_buffer structure */ | ||
| 343 | static multipart_buffer *multipart_buffer_new(char *boundary, int boundary_len) | ||
| 344 | { | ||
| 345 | multipart_buffer *self = (multipart_buffer *) ecalloc(1, sizeof(multipart_buffer)); | ||
| 346 | |||
| 347 | int minsize = boundary_len + 6; | ||
| 348 | if (minsize < FILLUNIT) minsize = FILLUNIT; | ||
| 349 | |||
| 350 | self->buffer = (char *) ecalloc(1, minsize + 1); | ||
| 351 | self->bufsize = minsize; | ||
| 352 | |||
| 353 | self->boundary = (char *) ecalloc(1, boundary_len + 3); | ||
| 354 | sprintf(self->boundary, "--%s", boundary); | ||
| 355 | |||
| 356 | self->boundary_next = (char *) ecalloc(1, boundary_len + 4); | ||
| 357 | sprintf(self->boundary_next, "\n--%s", boundary); | ||
| 358 | self->boundary_next_len = boundary_len + 3; | ||
| 359 | |||
| 360 | self->buf_begin = self->buffer; | ||
| 361 | self->bytes_in_buffer = 0; | ||
| 362 | |||
| 363 | return self; | ||
| 364 | } | ||
| 365 | |||
| 366 | |||
| 367 | /* | ||
| 368 | gets the next CRLF terminated line from the input buffer. | ||
| 369 | if it doesn't find a CRLF, and the buffer isn't completely full, returns | ||
| 370 | NULL; otherwise, returns the beginning of the null-terminated line, | ||
| 371 | minus the CRLF. | ||
| 372 | |||
| 373 | note that we really just look for LF terminated lines. this works | ||
| 374 | around a bug in internet explorer for the macintosh which sends mime | ||
| 375 | boundaries that are only LF terminated when you use an image submit | ||
| 376 | button in a multipart/form-data form. | ||
| 377 | */ | ||
| 378 | static char *next_line(multipart_buffer *self) | ||
| 379 | { | ||
| 380 | /* look for LF in the data */ | ||
| 381 | char* line = self->buf_begin; | ||
| 382 | char* ptr = memchr(self->buf_begin, '\n', self->bytes_in_buffer); | ||
| 383 | |||
| 384 | if (ptr) { /* LF found */ | ||
| 385 | |||
| 386 | /* terminate the string, remove CRLF */ | ||
| 387 | if ((ptr - line) > 0 && *(ptr-1) == '\r') { | ||
| 388 | *(ptr-1) = 0; | ||
| 389 | } else { | ||
| 390 | *ptr = 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | /* bump the pointer */ | ||
| 394 | self->buf_begin = ptr + 1; | ||
| 395 | self->bytes_in_buffer -= (self->buf_begin - line); | ||
| 396 | |||
| 397 | } else { /* no LF found */ | ||
| 398 | |||
| 399 | /* buffer isn't completely full, fail */ | ||
| 400 | if (self->bytes_in_buffer < self->bufsize) { | ||
| 401 | return NULL; | ||
| 402 | } | ||
| 403 | /* return entire buffer as a partial line */ | ||
| 404 | line[self->bufsize] = 0; | ||
| 405 | self->buf_begin = ptr; | ||
| 406 | self->bytes_in_buffer = 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | return line; | ||
| 410 | } | ||
| 411 | |||
| 412 | |||
| 413 | /* returns the next CRLF terminated line from the client */ | ||
| 414 | static char *get_line(multipart_buffer *self TSRMLS_DC) | ||
| 415 | { | ||
| 416 | char* ptr = next_line(self); | ||
| 417 | |||
| 418 | if (!ptr) { | ||
| 419 | fill_buffer(self TSRMLS_CC); | ||
| 420 | ptr = next_line(self); | ||
| 421 | } | ||
| 422 | |||
| 423 | return ptr; | ||
| 424 | } | ||
| 425 | |||
| 426 | |||
| 427 | /* Free header entry */ | ||
| 428 | static void php_free_hdr_entry(mime_header_entry *h) | ||
| 429 | { | ||
| 430 | if (h->key) { | ||
| 431 | efree(h->key); | ||
| 432 | } | ||
| 433 | if (h->value) { | ||
| 434 | efree(h->value); | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | |||
| 439 | /* finds a boundary */ | ||
| 440 | static int find_boundary(multipart_buffer *self, char *boundary TSRMLS_DC) | ||
| 441 | { | ||
| 442 | char *line; | ||
| 443 | |||
| 444 | /* loop thru lines */ | ||
| 445 | while( (line = get_line(self TSRMLS_CC)) ) | ||
| 446 | { | ||
| 447 | /* finished if we found the boundary */ | ||
| 448 | if (!strcmp(line, boundary)) { | ||
| 449 | return 1; | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | /* didn't find the boundary */ | ||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | |||
| 457 | |||
| 458 | /* parse headers */ | ||
| 459 | static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC) | ||
| 460 | { | ||
| 461 | char *line; | ||
| 462 | mime_header_entry prev_entry, entry; | ||
| 463 | int prev_len, cur_len; | ||
| 464 | |||
| 465 | /* didn't find boundary, abort */ | ||
| 466 | if (!find_boundary(self, self->boundary TSRMLS_CC)) { | ||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* get lines of text, or CRLF_CRLF */ | ||
| 471 | |||
| 472 | while( (line = get_line(self TSRMLS_CC)) && strlen(line) > 0 ) | ||
| 473 | { | ||
| 474 | /* add header to table */ | ||
| 475 | |||
| 476 | char *key = line; | ||
| 477 | char *value = NULL; | ||
| 478 | |||
| 479 | /* space in the beginning means same header */ | ||
| 480 | if (!isspace(line[0])) { | ||
| 481 | value = strchr(line, ':'); | ||
| 482 | } | ||
| 483 | |||
| 484 | if (value) { | ||
| 485 | *value = 0; | ||
| 486 | do { value++; } while(isspace(*value)); | ||
| 487 | |||
| 488 | entry.value = estrdup(value); | ||
| 489 | entry.key = estrdup(key); | ||
| 490 | |||
| 491 | } else if (zend_llist_count(header)) { /* If no ':' on the line, add to previous line */ | ||
| 492 | |||
| 493 | prev_len = strlen(prev_entry.value); | ||
| 494 | cur_len = strlen(line); | ||
| 495 | |||
| 496 | entry.value = emalloc(prev_len + cur_len + 1); | ||
| 497 | memcpy(entry.value, prev_entry.value, prev_len); | ||
| 498 | memcpy(entry.value + prev_len, line, cur_len); | ||
| 499 | entry.value[cur_len + prev_len] = '\0'; | ||
| 500 | |||
| 501 | entry.key = estrdup(prev_entry.key); | ||
| 502 | |||
| 503 | zend_llist_remove_tail(header); | ||
| 504 | } else { | ||
| 505 | continue; | ||
| 506 | } | ||
| 507 | |||
| 508 | zend_llist_add_element(header, &entry); | ||
| 509 | prev_entry = entry; | ||
| 510 | } | ||
| 511 | |||
| 512 | return 1; | ||
| 513 | } | ||
| 514 | |||
| 515 | |||
| 516 | static char *php_mime_get_hdr_value(zend_llist header, char *key) | ||
| 517 | { | ||
| 518 | mime_header_entry *entry; | ||
| 519 | |||
| 520 | if (key == NULL) { | ||
| 521 | return NULL; | ||
| 522 | } | ||
| 523 | |||
| 524 | entry = zend_llist_get_first(&header); | ||
| 525 | while (entry) { | ||
| 526 | if (!strcasecmp(entry->key, key)) { | ||
| 527 | return entry->value; | ||
| 528 | } | ||
| 529 | entry = zend_llist_get_next(&header); | ||
| 530 | } | ||
| 531 | |||
| 532 | return NULL; | ||
| 533 | } | ||
| 534 | |||
| 535 | |||
| 536 | static char *php_ap_getword(char **line, char stop) | ||
| 537 | { | ||
| 538 | char *pos = *line, quote; | ||
| 539 | char *res; | ||
| 540 | |||
| 541 | while (*pos && *pos != stop) { | ||
| 542 | |||
| 543 | if ((quote = *pos) == '"' || quote == '\'') { | ||
| 544 | ++pos; | ||
| 545 | while (*pos && *pos != quote) { | ||
| 546 | if (*pos == '\\' && pos[1] && pos[1] == quote) { | ||
| 547 | pos += 2; | ||
| 548 | } else { | ||
| 549 | ++pos; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | if (*pos) { | ||
| 553 | ++pos; | ||
| 554 | } | ||
| 555 | } else ++pos; | ||
| 556 | |||
| 557 | } | ||
| 558 | if (*pos == '\0') { | ||
| 559 | res = estrdup(*line); | ||
| 560 | *line += strlen(*line); | ||
| 561 | return res; | ||
| 562 | } | ||
| 563 | |||
| 564 | res = estrndup(*line, pos - *line); | ||
| 565 | |||
| 566 | while (*pos == stop) { | ||
| 567 | ++pos; | ||
| 568 | } | ||
| 569 | |||
| 570 | *line = pos; | ||
| 571 | return res; | ||
| 572 | } | ||
| 573 | |||
| 574 | |||
| 575 | static char *substring_conf(char *start, int len, char quote TSRMLS_DC) | ||
| 576 | { | ||
| 577 | char *result = emalloc(len + 2); | ||
| 578 | char *resp = result; | ||
| 579 | int i; | ||
| 580 | |||
| 581 | for (i = 0; i < len; ++i) { | ||
| 582 | if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) { | ||
| 583 | *resp++ = start[++i]; | ||
| 584 | } else { | ||
| 585 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 586 | if (php_mb_encoding_translation(TSRMLS_C)) { | ||
| 587 | size_t j = php_mb_gpc_mbchar_bytes(start+i TSRMLS_CC); | ||
| 588 | while (j-- > 0 && i < len) { | ||
| 589 | *resp++ = start[i++]; | ||
| 590 | } | ||
| 591 | --i; | ||
| 592 | } else { | ||
| 593 | *resp++ = start[i]; | ||
| 594 | } | ||
| 595 | #else | ||
| 596 | *resp++ = start[i]; | ||
| 597 | #endif | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | *resp++ = '\0'; | ||
| 602 | return result; | ||
| 603 | } | ||
| 604 | |||
| 605 | |||
| 606 | static char *php_ap_getword_conf(char **line TSRMLS_DC) | ||
| 607 | { | ||
| 608 | char *str = *line, *strend, *res, quote; | ||
| 609 | |||
| 610 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 611 | if (php_mb_encoding_translation(TSRMLS_C)) { | ||
| 612 | int len=strlen(str); | ||
| 613 | php_mb_gpc_encoding_detector(&str, &len, 1, NULL TSRMLS_CC); | ||
| 614 | } | ||
| 615 | #endif | ||
| 616 | |||
| 617 | while (*str && isspace(*str)) { | ||
| 618 | ++str; | ||
| 619 | } | ||
| 620 | |||
| 621 | if (!*str) { | ||
| 622 | *line = str; | ||
| 623 | return estrdup(""); | ||
| 624 | } | ||
| 625 | |||
| 626 | if ((quote = *str) == '"' || quote == '\'') { | ||
| 627 | strend = str + 1; | ||
| 628 | look_for_quote: | ||
| 629 | while (*strend && *strend != quote) { | ||
| 630 | if (*strend == '\\' && strend[1] && strend[1] == quote) { | ||
| 631 | strend += 2; | ||
| 632 | } else { | ||
| 633 | ++strend; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | if (*strend && *strend == quote) { | ||
| 637 | char p = *(strend + 1); | ||
| 638 | if (p != '\r' && p != '\n' && p != '\0') { | ||
| 639 | strend++; | ||
| 640 | goto look_for_quote; | ||
| 641 | } | ||
| 642 | } | ||
| 643 | |||
| 644 | res = substring_conf(str + 1, strend - str - 1, quote TSRMLS_CC); | ||
| 645 | |||
| 646 | if (*strend == quote) { | ||
| 647 | ++strend; | ||
| 648 | } | ||
| 649 | |||
| 650 | } else { | ||
| 651 | |||
| 652 | strend = str; | ||
| 653 | while (*strend && !isspace(*strend)) { | ||
| 654 | ++strend; | ||
| 655 | } | ||
| 656 | res = substring_conf(str, strend - str, 0 TSRMLS_CC); | ||
| 657 | } | ||
| 658 | |||
| 659 | while (*strend && isspace(*strend)) { | ||
| 660 | ++strend; | ||
| 661 | } | ||
| 662 | |||
| 663 | *line = strend; | ||
| 664 | return res; | ||
| 665 | } | ||
| 666 | |||
| 667 | |||
| 668 | /* | ||
| 669 | search for a string in a fixed-length byte string. | ||
| 670 | if partial is true, partial matches are allowed at the end of the buffer. | ||
| 671 | returns NULL if not found, or a pointer to the start of the first match. | ||
| 672 | */ | ||
| 673 | static void *php_ap_memstr(char *haystack, int haystacklen, char *needle, int needlen, int partial) | ||
| 674 | { | ||
| 675 | int len = haystacklen; | ||
| 676 | char *ptr = haystack; | ||
| 677 | |||
| 678 | /* iterate through first character matches */ | ||
| 679 | while( (ptr = memchr(ptr, needle[0], len)) ) { | ||
| 680 | |||
| 681 | /* calculate length after match */ | ||
| 682 | len = haystacklen - (ptr - (char *)haystack); | ||
| 683 | |||
| 684 | /* done if matches up to capacity of buffer */ | ||
| 685 | if (memcmp(needle, ptr, needlen < len ? needlen : len) == 0 && (partial || len >= needlen)) { | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | |||
| 689 | /* next character */ | ||
| 690 | ptr++; len--; | ||
| 691 | } | ||
| 692 | |||
| 693 | return ptr; | ||
| 694 | } | ||
| 695 | |||
| 696 | |||
| 697 | /* read until a boundary condition */ | ||
| 698 | static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes, int *end TSRMLS_DC) | ||
| 699 | { | ||
| 700 | int len, max; | ||
| 701 | char *bound; | ||
| 702 | |||
| 703 | /* fill buffer if needed */ | ||
| 704 | if (bytes > self->bytes_in_buffer) { | ||
| 705 | fill_buffer(self TSRMLS_CC); | ||
| 706 | } | ||
| 707 | |||
| 708 | /* look for a potential boundary match, only read data up to that point */ | ||
| 709 | if ((bound = php_ap_memstr(self->buf_begin, self->bytes_in_buffer, self->boundary_next, self->boundary_next_len, 1))) { | ||
| 710 | max = bound - self->buf_begin; | ||
| 711 | if (end && php_ap_memstr(self->buf_begin, self->bytes_in_buffer, self->boundary_next, self->boundary_next_len, 0)) { | ||
| 712 | *end = 1; | ||
| 713 | } | ||
| 714 | } else { | ||
| 715 | max = self->bytes_in_buffer; | ||
| 716 | } | ||
| 717 | |||
| 718 | /* maximum number of bytes we are reading */ | ||
| 719 | len = max < bytes-1 ? max : bytes-1; | ||
| 720 | |||
| 721 | /* if we read any data... */ | ||
| 722 | if (len > 0) { | ||
| 723 | |||
| 724 | /* copy the data */ | ||
| 725 | memcpy(buf, self->buf_begin, len); | ||
| 726 | buf[len] = 0; | ||
| 727 | |||
| 728 | if (bound && len > 0 && buf[len-1] == '\r') { | ||
| 729 | buf[--len] = 0; | ||
| 730 | } | ||
| 731 | |||
| 732 | /* update the buffer */ | ||
| 733 | self->bytes_in_buffer -= len; | ||
| 734 | self->buf_begin += len; | ||
| 735 | } | ||
| 736 | |||
| 737 | return len; | ||
| 738 | } | ||
| 739 | |||
| 740 | |||
| 741 | /* | ||
| 742 | XXX: this is horrible memory-usage-wise, but we only expect | ||
| 743 | to do this on small pieces of form data. | ||
| 744 | */ | ||
| 745 | static char *multipart_buffer_read_body(multipart_buffer *self, unsigned int *len TSRMLS_DC) | ||
| 746 | { | ||
| 747 | char buf[FILLUNIT], *out=NULL; | ||
| 748 | int total_bytes=0, read_bytes=0; | ||
| 749 | |||
| 750 | while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf), NULL TSRMLS_CC))) { | ||
| 751 | out = erealloc(out, total_bytes + read_bytes + 1); | ||
| 752 | memcpy(out + total_bytes, buf, read_bytes); | ||
| 753 | total_bytes += read_bytes; | ||
| 754 | } | ||
| 755 | |||
| 756 | if (out) out[total_bytes] = '\0'; | ||
| 757 | *len = total_bytes; | ||
| 758 | |||
| 759 | return out; | ||
| 760 | } | ||
| 761 | |||
| 762 | |||
| 763 | /* | ||
| 764 | * The combined READER/HANDLER | ||
| 765 | * | ||
| 766 | */ | ||
| 767 | |||
| 768 | SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) | ||
| 769 | { | ||
| 770 | char *boundary, *s=NULL, *boundary_end = NULL, *start_arr=NULL, *array_index=NULL; | ||
| 771 | char *temp_filename=NULL, *lbuf=NULL, *abuf=NULL; | ||
| 772 | int boundary_len=0, total_bytes=0, cancel_upload=0, is_arr_upload=0, array_len=0; | ||
| 773 | int max_file_size=0, skip_upload=0, anonindex=0, is_anonymous; | ||
| 774 | zval *http_post_files=NULL; HashTable *uploaded_files=NULL; | ||
| 775 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 776 | int str_len = 0, num_vars = 0, num_vars_max = 2*10, *len_list = NULL; | ||
| 777 | char **val_list = NULL; | ||
| 778 | #endif | ||
| 779 | zend_bool magic_quotes_gpc; | ||
| 780 | multipart_buffer *mbuff; | ||
| 781 | zval *array_ptr = (zval *) arg; | ||
| 782 | int fd=-1; | ||
| 783 | zend_llist header; | ||
| 784 | void *event_extra_data = NULL; | ||
| 785 | |||
| 786 | SDEBUG("suhosin_rfc1867_handler"); | ||
| 787 | |||
| 788 | if (SG(request_info).content_length > SG(post_max_size)) { | ||
| 789 | sapi_module.sapi_error(E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes", SG(request_info).content_length, SG(post_max_size)); | ||
| 790 | return; | ||
| 791 | } | ||
| 792 | |||
| 793 | /* Get the boundary */ | ||
| 794 | boundary = strstr(content_type_dup, "boundary"); | ||
| 795 | if (!boundary || !(boundary=strchr(boundary, '='))) { | ||
| 796 | sapi_module.sapi_error(E_WARNING, "Missing boundary in multipart/form-data POST data"); | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | boundary++; | ||
| 801 | boundary_len = strlen(boundary); | ||
| 802 | |||
| 803 | if (boundary[0] == '"') { | ||
| 804 | boundary++; | ||
| 805 | boundary_end = strchr(boundary, '"'); | ||
| 806 | if (!boundary_end) { | ||
| 807 | sapi_module.sapi_error(E_WARNING, "Invalid boundary in multipart/form-data POST data"); | ||
| 808 | return; | ||
| 809 | } | ||
| 810 | } else { | ||
| 811 | /* search for the end of the boundary */ | ||
| 812 | boundary_end = strchr(boundary, ','); | ||
| 813 | } | ||
| 814 | if (boundary_end) { | ||
| 815 | boundary_end[0] = '\0'; | ||
| 816 | boundary_len = boundary_end-boundary; | ||
| 817 | } | ||
| 818 | |||
| 819 | /* Initialize the buffer */ | ||
| 820 | if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) { | ||
| 821 | sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer"); | ||
| 822 | return; | ||
| 823 | } | ||
| 824 | |||
| 825 | /* Initialize $_FILES[] */ | ||
| 826 | zend_hash_init(&PG(rfc1867_protected_variables), 5, NULL, NULL, 0); | ||
| 827 | |||
| 828 | ALLOC_HASHTABLE(uploaded_files); | ||
| 829 | zend_hash_init(uploaded_files, 5, NULL, (dtor_func_t) free_estring, 0); | ||
| 830 | SG(rfc1867_uploaded_files) = uploaded_files; | ||
| 831 | |||
| 832 | ALLOC_ZVAL(http_post_files); | ||
| 833 | array_init(http_post_files); | ||
| 834 | INIT_PZVAL(http_post_files); | ||
| 835 | PG(http_globals)[TRACK_VARS_FILES] = http_post_files; | ||
| 836 | |||
| 837 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 838 | if (php_mb_encoding_translation(TSRMLS_C)) { | ||
| 839 | val_list = (char **)ecalloc(num_vars_max+2, sizeof(char *)); | ||
| 840 | len_list = (int *)ecalloc(num_vars_max+2, sizeof(int)); | ||
| 841 | } | ||
| 842 | #endif | ||
| 843 | zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) php_free_hdr_entry, 0); | ||
| 844 | |||
| 845 | |||
| 846 | { | ||
| 847 | multipart_event_start event_start; | ||
| 848 | |||
| 849 | event_start.content_length = SG(request_info).content_length; | ||
| 850 | if (suhosin_rfc1867_filter(MULTIPART_EVENT_START, &event_start, &event_extra_data TSRMLS_CC) == FAILURE) { | ||
| 851 | goto fileupload_done; | ||
| 852 | } | ||
| 853 | } | ||
| 854 | |||
| 855 | while (!multipart_buffer_eof(mbuff TSRMLS_CC)) | ||
| 856 | { | ||
| 857 | char buff[FILLUNIT]; | ||
| 858 | char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL; | ||
| 859 | size_t blen=0, wlen=0; | ||
| 860 | off_t offset; | ||
| 861 | |||
| 862 | zend_llist_clean(&header); | ||
| 863 | |||
| 864 | if (!multipart_buffer_headers(mbuff, &header TSRMLS_CC)) { | ||
| 865 | goto fileupload_done; | ||
| 866 | } | ||
| 867 | |||
| 868 | if ((cd = php_mime_get_hdr_value(header, "Content-Disposition"))) { | ||
| 869 | char *pair=NULL; | ||
| 870 | int end=0; | ||
| 871 | |||
| 872 | while (isspace(*cd)) { | ||
| 873 | ++cd; | ||
| 874 | } | ||
| 875 | |||
| 876 | while (*cd && (pair = php_ap_getword(&cd, ';'))) | ||
| 877 | { | ||
| 878 | char *key=NULL, *word = pair; | ||
| 879 | |||
| 880 | while (isspace(*cd)) { | ||
| 881 | ++cd; | ||
| 882 | } | ||
| 883 | |||
| 884 | if (strchr(pair, '=')) { | ||
| 885 | key = php_ap_getword(&pair, '='); | ||
| 886 | |||
| 887 | if (!strcasecmp(key, "name")) { | ||
| 888 | if (param) { | ||
| 889 | efree(param); | ||
| 890 | } | ||
| 891 | param = php_ap_getword_conf(&pair TSRMLS_CC); | ||
| 892 | } else if (!strcasecmp(key, "filename")) { | ||
| 893 | if (filename) { | ||
| 894 | efree(filename); | ||
| 895 | } | ||
| 896 | filename = php_ap_getword_conf(&pair TSRMLS_CC); | ||
| 897 | } | ||
| 898 | } | ||
| 899 | if (key) { | ||
| 900 | efree(key); | ||
| 901 | } | ||
| 902 | efree(word); | ||
| 903 | } | ||
| 904 | |||
| 905 | /* Normal form variable, safe to read all data into memory */ | ||
| 906 | if (!filename && param) { | ||
| 907 | |||
| 908 | unsigned int value_len; | ||
| 909 | char *value = multipart_buffer_read_body(mbuff, &value_len TSRMLS_CC); | ||
| 910 | unsigned int new_val_len; /* Dummy variable */ | ||
| 911 | |||
| 912 | if (!value) { | ||
| 913 | value = estrdup(""); | ||
| 914 | } | ||
| 915 | SDEBUG("calling inputfilter"); | ||
| 916 | if (suhosin_input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC) == 0) { | ||
| 917 | efree(param); | ||
| 918 | efree(value); | ||
| 919 | continue; | ||
| 920 | } | ||
| 921 | |||
| 922 | #ifdef ZEND_ENGINE_2 | ||
| 923 | if (sapi_module.input_filter(PARSE_POST, param, &value, new_val_len, &new_val_len TSRMLS_CC)) { | ||
| 924 | #endif | ||
| 925 | { | ||
| 926 | multipart_event_formdata event_formdata; | ||
| 927 | size_t newlength = 0; | ||
| 928 | |||
| 929 | event_formdata.post_bytes_processed = SG(read_post_bytes); | ||
| 930 | event_formdata.name = param; | ||
| 931 | event_formdata.value = &value; | ||
| 932 | event_formdata.length = new_val_len; | ||
| 933 | event_formdata.newlength = &newlength; | ||
| 934 | if (suhosin_rfc1867_filter(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data TSRMLS_CC) == FAILURE) { | ||
| 935 | efree(param); | ||
| 936 | efree(value); | ||
| 937 | continue; | ||
| 938 | } | ||
| 939 | new_val_len = newlength; | ||
| 940 | } | ||
| 941 | |||
| 942 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 943 | if (php_mb_encoding_translation(TSRMLS_C)) { | ||
| 944 | php_mb_gpc_stack_variable(param, value, &val_list, &len_list, | ||
| 945 | &num_vars, &num_vars_max TSRMLS_CC); | ||
| 946 | } else { | ||
| 947 | safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); | ||
| 948 | } | ||
| 949 | #else | ||
| 950 | safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); | ||
| 951 | #endif | ||
| 952 | #ifdef ZEND_ENGINE_2 | ||
| 953 | } else { | ||
| 954 | multipart_event_formdata event_formdata; | ||
| 955 | |||
| 956 | event_formdata.post_bytes_processed = SG(read_post_bytes); | ||
| 957 | event_formdata.name = param; | ||
| 958 | event_formdata.value = &value; | ||
| 959 | event_formdata.length = value_len; | ||
| 960 | event_formdata.newlength = NULL; | ||
| 961 | suhosin_rfc1867_filter(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data TSRMLS_CC); | ||
| 962 | } | ||
| 963 | #endif | ||
| 964 | if (!strcasecmp(param, "MAX_FILE_SIZE")) { | ||
| 965 | max_file_size = atol(value); | ||
| 966 | } | ||
| 967 | |||
| 968 | efree(param); | ||
| 969 | efree(value); | ||
| 970 | continue; | ||
| 971 | } | ||
| 972 | |||
| 973 | /* If file_uploads=off, skip the file part */ | ||
| 974 | if (!PG(file_uploads)) { | ||
| 975 | skip_upload = 1; | ||
| 976 | } | ||
| 977 | |||
| 978 | /* Return with an error if the posted data is garbled */ | ||
| 979 | if (!param && !filename) { | ||
| 980 | sapi_module.sapi_error(E_WARNING, "File Upload Mime headers garbled"); | ||
| 981 | goto fileupload_done; | ||
| 982 | } | ||
| 983 | |||
| 984 | if (!param) { | ||
| 985 | is_anonymous = 1; | ||
| 986 | param = emalloc(MAX_SIZE_ANONNAME); | ||
| 987 | snprintf(param, MAX_SIZE_ANONNAME, "%u", anonindex++); | ||
| 988 | } else { | ||
| 989 | is_anonymous = 0; | ||
| 990 | } | ||
| 991 | |||
| 992 | /* New Rule: never repair potential malicious user input */ | ||
| 993 | if (!skip_upload) { | ||
| 994 | char *tmp = param; | ||
| 995 | long c = 0; | ||
| 996 | |||
| 997 | while (*tmp) { | ||
| 998 | if (*tmp == '[') { | ||
| 999 | c++; | ||
| 1000 | } else if (*tmp == ']') { | ||
| 1001 | c--; | ||
| 1002 | if (tmp[1] && tmp[1] != '[') { | ||
| 1003 | skip_upload = 1; | ||
| 1004 | break; | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | if (c < 0) { | ||
| 1008 | skip_upload = 1; | ||
| 1009 | break; | ||
| 1010 | } | ||
| 1011 | tmp++; | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | total_bytes = cancel_upload = 0; | ||
| 1016 | |||
| 1017 | if (!skip_upload) { | ||
| 1018 | multipart_event_file_start event_file_start; | ||
| 1019 | |||
| 1020 | /* Handle file */ | ||
| 1021 | fd = php_open_temporary_fd(PG(upload_tmp_dir), "php", &temp_filename TSRMLS_CC); | ||
| 1022 | if (fd==-1) { | ||
| 1023 | sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file"); | ||
| 1024 | cancel_upload = UPLOAD_ERROR_E; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | event_file_start.post_bytes_processed = SG(read_post_bytes); | ||
| 1028 | event_file_start.name = param; | ||
| 1029 | event_file_start.filename = &filename; | ||
| 1030 | if (suhosin_rfc1867_filter(MULTIPART_EVENT_FILE_START, &event_file_start, &event_extra_data TSRMLS_CC) == FAILURE) { | ||
| 1031 | if (temp_filename) { | ||
| 1032 | if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */ | ||
| 1033 | close(fd); | ||
| 1034 | unlink(temp_filename); | ||
| 1035 | } | ||
| 1036 | efree(temp_filename); | ||
| 1037 | } | ||
| 1038 | temp_filename = NULL; | ||
| 1039 | efree(param); | ||
| 1040 | efree(filename); | ||
| 1041 | continue; | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | |||
| 1046 | if (skip_upload) { | ||
| 1047 | efree(param); | ||
| 1048 | efree(filename); | ||
| 1049 | continue; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | if(strlen(filename) == 0) { | ||
| 1053 | #if DEBUG_FILE_UPLOAD | ||
| 1054 | sapi_module.sapi_error(E_NOTICE, "No file uploaded"); | ||
| 1055 | #endif | ||
| 1056 | cancel_upload = UPLOAD_ERROR_D; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | offset = 0; | ||
| 1060 | end = 0; | ||
| 1061 | while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC))) | ||
| 1062 | { | ||
| 1063 | { | ||
| 1064 | multipart_event_file_data event_file_data; | ||
| 1065 | |||
| 1066 | event_file_data.post_bytes_processed = SG(read_post_bytes); | ||
| 1067 | event_file_data.offset = offset; | ||
| 1068 | event_file_data.data = buff; | ||
| 1069 | event_file_data.length = blen; | ||
| 1070 | event_file_data.newlength = &blen; | ||
| 1071 | if (suhosin_rfc1867_filter(MULTIPART_EVENT_FILE_DATA, &event_file_data, &event_extra_data TSRMLS_CC) == FAILURE) { | ||
| 1072 | cancel_upload = UPLOAD_ERROR_X; | ||
| 1073 | continue; | ||
| 1074 | } | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | |||
| 1078 | if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) { | ||
| 1079 | #if DEBUG_FILE_UPLOAD | ||
| 1080 | sapi_module.sapi_error(E_NOTICE, "upload_max_filesize of %ld bytes exceeded - file [%s=%s] not saved", PG(upload_max_filesize), param, filename); | ||
| 1081 | #endif | ||
| 1082 | cancel_upload = UPLOAD_ERROR_A; | ||
| 1083 | } else if (max_file_size && (total_bytes > max_file_size)) { | ||
| 1084 | #if DEBUG_FILE_UPLOAD | ||
| 1085 | sapi_module.sapi_error(E_NOTICE, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename); | ||
| 1086 | #endif | ||
| 1087 | cancel_upload = UPLOAD_ERROR_B; | ||
| 1088 | } else if (blen > 0) { | ||
| 1089 | |||
| 1090 | wlen = write(fd, buff, blen); | ||
| 1091 | |||
| 1092 | if (wlen < blen) { | ||
| 1093 | #if DEBUG_FILE_UPLOAD | ||
| 1094 | sapi_module.sapi_error(E_NOTICE, "Only %d bytes were written, expected to write %d", wlen, blen); | ||
| 1095 | #endif | ||
| 1096 | cancel_upload = UPLOAD_ERROR_F; | ||
| 1097 | } else { | ||
| 1098 | total_bytes += wlen; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | offset += wlen; | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | if (fd!=-1) { /* may not be initialized if file could not be created */ | ||
| 1105 | close(fd); | ||
| 1106 | } | ||
| 1107 | if (!cancel_upload && !end) { | ||
| 1108 | #if DEBUG_FILE_UPLOAD | ||
| 1109 | sapi_module.sapi_error(E_NOTICE, "Missing mime boundary at the end of the data for file %s", strlen(filename) > 0 ? filename : ""); | ||
| 1110 | #endif | ||
| 1111 | cancel_upload = UPLOAD_ERROR_C; | ||
| 1112 | } | ||
| 1113 | #if DEBUG_FILE_UPLOAD | ||
| 1114 | if(strlen(filename) > 0 && total_bytes == 0 && !cancel_upload) { | ||
| 1115 | sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename); | ||
| 1116 | cancel_upload = 5; | ||
| 1117 | } | ||
| 1118 | #endif | ||
| 1119 | |||
| 1120 | { | ||
| 1121 | multipart_event_file_end event_file_end; | ||
| 1122 | |||
| 1123 | event_file_end.post_bytes_processed = SG(read_post_bytes); | ||
| 1124 | event_file_end.temp_filename = temp_filename; | ||
| 1125 | event_file_end.cancel_upload = cancel_upload; | ||
| 1126 | if (suhosin_rfc1867_filter(MULTIPART_EVENT_FILE_END, &event_file_end, &event_extra_data TSRMLS_CC) == FAILURE) { | ||
| 1127 | cancel_upload = UPLOAD_ERROR_X; | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | if (cancel_upload) { | ||
| 1132 | if (temp_filename) { | ||
| 1133 | if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */ | ||
| 1134 | unlink(temp_filename); | ||
| 1135 | } | ||
| 1136 | efree(temp_filename); | ||
| 1137 | } | ||
| 1138 | temp_filename=""; | ||
| 1139 | } else { | ||
| 1140 | zend_hash_add(SG(rfc1867_uploaded_files), temp_filename, strlen(temp_filename) + 1, &temp_filename, sizeof(char *), NULL); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | /* is_arr_upload is true when name of file upload field | ||
| 1144 | * ends in [.*] | ||
| 1145 | * start_arr is set to point to 1st [ | ||
| 1146 | */ | ||
| 1147 | is_arr_upload = (start_arr = strchr(param,'[')) && (param[strlen(param)-1] == ']'); | ||
| 1148 | |||
| 1149 | if (is_arr_upload) { | ||
| 1150 | array_len = strlen(start_arr); | ||
| 1151 | if (array_index) { | ||
| 1152 | efree(array_index); | ||
| 1153 | } | ||
| 1154 | array_index = estrndup(start_arr+1, array_len-2); | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | /* Add $foo_name */ | ||
| 1158 | if (lbuf) { | ||
| 1159 | efree(lbuf); | ||
| 1160 | } | ||
| 1161 | lbuf = (char *) emalloc(strlen(param) + MAX_SIZE_OF_INDEX + 1); | ||
| 1162 | |||
| 1163 | if (is_arr_upload) { | ||
| 1164 | if (abuf) efree(abuf); | ||
| 1165 | abuf = estrndup(param, strlen(param)-array_len); | ||
| 1166 | sprintf(lbuf, "%s_name[%s]", abuf, array_index); | ||
| 1167 | } else { | ||
| 1168 | sprintf(lbuf, "%s_name", param); | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 1172 | if (php_mb_encoding_translation(TSRMLS_C)) { | ||
| 1173 | if (num_vars>=num_vars_max){ | ||
| 1174 | php_mb_gpc_realloc_buffer(&val_list, &len_list, &num_vars_max, | ||
| 1175 | 1 TSRMLS_CC); | ||
| 1176 | } | ||
| 1177 | val_list[num_vars] = filename; | ||
| 1178 | len_list[num_vars] = strlen(filename); | ||
| 1179 | num_vars++; | ||
| 1180 | if(php_mb_gpc_encoding_detector(val_list, len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) { | ||
| 1181 | str_len = strlen(filename); | ||
| 1182 | php_mb_gpc_encoding_converter(&filename, &str_len, 1, NULL, NULL TSRMLS_CC); | ||
| 1183 | } | ||
| 1184 | s = php_mb_strrchr(filename, '\\' TSRMLS_CC); | ||
| 1185 | if ((tmp = php_mb_strrchr(filename, '/' TSRMLS_CC)) > s) { | ||
| 1186 | s = tmp; | ||
| 1187 | } | ||
| 1188 | num_vars--; | ||
| 1189 | goto filedone; | ||
| 1190 | } | ||
| 1191 | #endif | ||
| 1192 | /* The \ check should technically be needed for win32 systems only where | ||
| 1193 | * it is a valid path separator. However, IE in all it's wisdom always sends | ||
| 1194 | * the full path of the file on the user's filesystem, which means that unless | ||
| 1195 | * the user does basename() they get a bogus file name. Until IE's user base drops | ||
| 1196 | * to nill or problem is fixed this code must remain enabled for all systems. | ||
| 1197 | */ | ||
| 1198 | s = strrchr(filename, '\\'); | ||
| 1199 | if ((tmp = strrchr(filename, '/')) > s) { | ||
| 1200 | s = tmp; | ||
| 1201 | } | ||
| 1202 | #ifdef PHP_WIN32 | ||
| 1203 | if (PG(magic_quotes_gpc)) { | ||
| 1204 | s = s ? s : filename; | ||
| 1205 | tmp = strrchr(s, '\''); | ||
| 1206 | s = tmp > s ? tmp : s; | ||
| 1207 | tmp = strrchr(s, '"'); | ||
| 1208 | s = tmp > s ? tmp : s; | ||
| 1209 | } | ||
| 1210 | #endif | ||
| 1211 | |||
| 1212 | #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) | ||
| 1213 | filedone: | ||
| 1214 | #endif | ||
| 1215 | |||
| 1216 | if (!is_anonymous) { | ||
| 1217 | if (s && s > filename) { | ||
| 1218 | safe_php_register_variable(lbuf, s+1, NULL, 0 TSRMLS_CC); | ||
| 1219 | } else { | ||
| 1220 | safe_php_register_variable(lbuf, filename, NULL, 0 TSRMLS_CC); | ||
| 1221 | } | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | /* Add $foo[name] */ | ||
| 1225 | if (is_arr_upload) { | ||
| 1226 | sprintf(lbuf, "%s[name][%s]", abuf, array_index); | ||
| 1227 | } else { | ||
| 1228 | sprintf(lbuf, "%s[name]", param); | ||
| 1229 | } | ||
| 1230 | if (s && s > filename) { | ||
| 1231 | register_http_post_files_variable(lbuf, s+1, http_post_files, 0 TSRMLS_CC); | ||
| 1232 | } else { | ||
| 1233 | register_http_post_files_variable(lbuf, filename, http_post_files, 0 TSRMLS_CC); | ||
| 1234 | } | ||
| 1235 | efree(filename); | ||
| 1236 | s = NULL; | ||
| 1237 | |||
| 1238 | /* Possible Content-Type: */ | ||
| 1239 | if (cancel_upload || !(cd = php_mime_get_hdr_value(header, "Content-Type"))) { | ||
| 1240 | cd = ""; | ||
| 1241 | } else { | ||
| 1242 | /* fix for Opera 6.01 */ | ||
| 1243 | s = strchr(cd, ';'); | ||
| 1244 | if (s != NULL) { | ||
| 1245 | *s = '\0'; | ||
| 1246 | } | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | /* Add $foo_type */ | ||
| 1250 | if (is_arr_upload) { | ||
| 1251 | sprintf(lbuf, "%s_type[%s]", abuf, array_index); | ||
| 1252 | } else { | ||
| 1253 | sprintf(lbuf, "%s_type", param); | ||
| 1254 | } | ||
| 1255 | if (!is_anonymous) { | ||
| 1256 | safe_php_register_variable(lbuf, cd, NULL, 0 TSRMLS_CC); | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | /* Add $foo[type] */ | ||
| 1260 | if (is_arr_upload) { | ||
| 1261 | sprintf(lbuf, "%s[type][%s]", abuf, array_index); | ||
| 1262 | } else { | ||
| 1263 | sprintf(lbuf, "%s[type]", param); | ||
| 1264 | } | ||
| 1265 | register_http_post_files_variable(lbuf, cd, http_post_files, 0 TSRMLS_CC); | ||
| 1266 | |||
| 1267 | /* Restore Content-Type Header */ | ||
| 1268 | if (s != NULL) { | ||
| 1269 | *s = ';'; | ||
| 1270 | } | ||
| 1271 | s = ""; | ||
| 1272 | |||
| 1273 | /* Initialize variables */ | ||
| 1274 | add_protected_variable(param TSRMLS_CC); | ||
| 1275 | |||
| 1276 | magic_quotes_gpc = PG(magic_quotes_gpc); | ||
| 1277 | PG(magic_quotes_gpc) = 0; | ||
| 1278 | /* if param is of form xxx[.*] this will cut it to xxx */ | ||
| 1279 | if (!is_anonymous) { | ||
| 1280 | safe_php_register_variable(param, temp_filename, NULL, 1 TSRMLS_CC); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | /* Add $foo[tmp_name] */ | ||
| 1284 | if (is_arr_upload) { | ||
| 1285 | sprintf(lbuf, "%s[tmp_name][%s]", abuf, array_index); | ||
| 1286 | } else { | ||
| 1287 | sprintf(lbuf, "%s[tmp_name]", param); | ||
| 1288 | } | ||
| 1289 | add_protected_variable(lbuf TSRMLS_CC); | ||
| 1290 | register_http_post_files_variable(lbuf, temp_filename, http_post_files, 1 TSRMLS_CC); | ||
| 1291 | |||
| 1292 | PG(magic_quotes_gpc) = magic_quotes_gpc; | ||
| 1293 | |||
| 1294 | { | ||
| 1295 | zval file_size, error_type; | ||
| 1296 | |||
| 1297 | error_type.value.lval = cancel_upload; | ||
| 1298 | error_type.type = IS_LONG; | ||
| 1299 | |||
| 1300 | /* Add $foo[error] */ | ||
| 1301 | if (cancel_upload) { | ||
| 1302 | file_size.value.lval = 0; | ||
| 1303 | file_size.type = IS_LONG; | ||
| 1304 | } else { | ||
| 1305 | file_size.value.lval = total_bytes; | ||
| 1306 | file_size.type = IS_LONG; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | if (is_arr_upload) { | ||
| 1310 | sprintf(lbuf, "%s[error][%s]", abuf, array_index); | ||
| 1311 | } else { | ||
| 1312 | sprintf(lbuf, "%s[error]", param); | ||
| 1313 | } | ||
| 1314 | register_http_post_files_variable_ex(lbuf, &error_type, http_post_files, 0 TSRMLS_CC); | ||
| 1315 | |||
| 1316 | /* Add $foo_size */ | ||
| 1317 | if (is_arr_upload) { | ||
| 1318 | sprintf(lbuf, "%s_size[%s]", abuf, array_index); | ||
| 1319 | } else { | ||
| 1320 | sprintf(lbuf, "%s_size", param); | ||
| 1321 | } | ||
| 1322 | if (!is_anonymous) { | ||
| 1323 | safe_php_register_variable_ex(lbuf, &file_size, NULL, 0 TSRMLS_CC); | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | /* Add $foo[size] */ | ||
| 1327 | if (is_arr_upload) { | ||
| 1328 | sprintf(lbuf, "%s[size][%s]", abuf, array_index); | ||
| 1329 | } else { | ||
| 1330 | sprintf(lbuf, "%s[size]", param); | ||
| 1331 | } | ||
| 1332 | register_http_post_files_variable_ex(lbuf, &file_size, http_post_files, 0 TSRMLS_CC); | ||
| 1333 | } | ||
| 1334 | efree(param); | ||
| 1335 | } | ||
| 1336 | } | ||
| 1337 | fileupload_done: | ||
| 1338 | { | ||
| 1339 | multipart_event_end event_end; | ||
| 1340 | |||
| 1341 | event_end.post_bytes_processed = SG(read_post_bytes); | ||
| 1342 | suhosin_rfc1867_filter(MULTIPART_EVENT_END, &event_end, &event_extra_data TSRMLS_CC); | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | SAFE_RETURN; | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | /* | ||
| 1349 | * Local variables: | ||
| 1350 | * tab-width: 4 | ||
| 1351 | * c-basic-offset: 4 | ||
| 1352 | * End: | ||
| 1353 | * vim600: sw=4 ts=4 fdm=marker | ||
| 1354 | * vim<600: sw=4 ts=4 | ||
| 1355 | */ | ||
diff --git a/session.c b/session.c new file mode 100644 index 0000000..b784d9b --- /dev/null +++ b/session.c | |||
| @@ -0,0 +1,714 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: session.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "TSRM.h" | ||
| 29 | #include "SAPI.h" | ||
| 30 | #include "php_ini.h" | ||
| 31 | #include "php_suhosin.h" | ||
| 32 | #include "ext/standard/base64.h" | ||
| 33 | #include "sha256.h" | ||
| 34 | |||
| 35 | #define PS_OPEN_ARGS void **mod_data, const char *save_path, const char *session_name TSRMLS_DC | ||
| 36 | #define PS_CLOSE_ARGS void **mod_data TSRMLS_DC | ||
| 37 | #define PS_READ_ARGS void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC | ||
| 38 | #define PS_WRITE_ARGS void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC | ||
| 39 | #define PS_DESTROY_ARGS void **mod_data, const char *key TSRMLS_DC | ||
| 40 | #define PS_GC_ARGS void **mod_data, int maxlifetime, int *nrdels TSRMLS_DC | ||
| 41 | #define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC | ||
| 42 | |||
| 43 | typedef struct ps_module_struct { | ||
| 44 | const char *s_name; | ||
| 45 | int (*s_open)(PS_OPEN_ARGS); | ||
| 46 | int (*s_close)(PS_CLOSE_ARGS); | ||
| 47 | int (*s_read)(PS_READ_ARGS); | ||
| 48 | int (*s_write)(PS_WRITE_ARGS); | ||
| 49 | int (*s_destroy)(PS_DESTROY_ARGS); | ||
| 50 | int (*s_gc)(PS_GC_ARGS); | ||
| 51 | char *(*s_create_sid)(PS_CREATE_SID_ARGS); | ||
| 52 | } ps_module; | ||
| 53 | |||
| 54 | typedef enum { | ||
| 55 | php_session_disabled, | ||
| 56 | php_session_none, | ||
| 57 | php_session_active | ||
| 58 | } php_session_status; | ||
| 59 | |||
| 60 | #define PS_SERIALIZER_ENCODE_ARGS char **newstr, int *newlen TSRMLS_DC | ||
| 61 | #define PS_SERIALIZER_DECODE_ARGS const char *val, int vallen TSRMLS_DC | ||
| 62 | |||
| 63 | typedef struct ps_serializer_struct { | ||
| 64 | const char *name; | ||
| 65 | int (*encode)(PS_SERIALIZER_ENCODE_ARGS); | ||
| 66 | int (*decode)(PS_SERIALIZER_DECODE_ARGS); | ||
| 67 | } ps_serializer; | ||
| 68 | |||
| 69 | typedef struct _php_ps_globals_43_44 { | ||
| 70 | char *save_path; | ||
| 71 | char *session_name; | ||
| 72 | char *id; | ||
| 73 | char *extern_referer_chk; | ||
| 74 | char *entropy_file; | ||
| 75 | char *cache_limiter; | ||
| 76 | long entropy_length; | ||
| 77 | long cookie_lifetime; | ||
| 78 | char *cookie_path; | ||
| 79 | char *cookie_domain; | ||
| 80 | zend_bool cookie_secure; | ||
| 81 | ps_module *mod; | ||
| 82 | void *mod_data; | ||
| 83 | php_session_status session_status; | ||
| 84 | long gc_probability; | ||
| 85 | long gc_divisor; | ||
| 86 | long gc_maxlifetime; | ||
| 87 | int module_number; | ||
| 88 | long cache_expire; | ||
| 89 | zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ | ||
| 90 | zend_bool bug_compat_warn; /* Whether to warn about it */ | ||
| 91 | const struct ps_serializer_struct *serializer; | ||
| 92 | zval *http_session_vars; | ||
| 93 | zend_bool auto_start; | ||
| 94 | zend_bool use_cookies; | ||
| 95 | zend_bool use_only_cookies; | ||
| 96 | zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ | ||
| 97 | zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ | ||
| 98 | int send_cookie; | ||
| 99 | int define_sid; | ||
| 100 | } php_ps_globals_43_44; | ||
| 101 | |||
| 102 | typedef struct _php_ps_globals_50_51 { | ||
| 103 | char *save_path; | ||
| 104 | char *session_name; | ||
| 105 | char *id; | ||
| 106 | char *extern_referer_chk; | ||
| 107 | char *entropy_file; | ||
| 108 | char *cache_limiter; | ||
| 109 | long entropy_length; | ||
| 110 | long cookie_lifetime; | ||
| 111 | char *cookie_path; | ||
| 112 | char *cookie_domain; | ||
| 113 | zend_bool cookie_secure; | ||
| 114 | ps_module *mod; | ||
| 115 | void *mod_data; | ||
| 116 | php_session_status session_status; | ||
| 117 | long gc_probability; | ||
| 118 | long gc_divisor; | ||
| 119 | long gc_maxlifetime; | ||
| 120 | int module_number; | ||
| 121 | long cache_expire; | ||
| 122 | zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ | ||
| 123 | zend_bool bug_compat_warn; /* Whether to warn about it */ | ||
| 124 | const struct ps_serializer_struct *serializer; | ||
| 125 | zval *http_session_vars; | ||
| 126 | zend_bool auto_start; | ||
| 127 | zend_bool use_cookies; | ||
| 128 | zend_bool use_only_cookies; | ||
| 129 | zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ | ||
| 130 | zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ | ||
| 131 | |||
| 132 | long hash_func; | ||
| 133 | long hash_bits_per_character; | ||
| 134 | int send_cookie; | ||
| 135 | int define_sid; | ||
| 136 | } php_ps_globals_50_51; | ||
| 137 | |||
| 138 | typedef struct _php_ps_globals_52_60 { | ||
| 139 | char *save_path; | ||
| 140 | char *session_name; | ||
| 141 | char *id; | ||
| 142 | char *extern_referer_chk; | ||
| 143 | char *entropy_file; | ||
| 144 | char *cache_limiter; | ||
| 145 | long entropy_length; | ||
| 146 | long cookie_lifetime; | ||
| 147 | char *cookie_path; | ||
| 148 | char *cookie_domain; | ||
| 149 | zend_bool cookie_secure; | ||
| 150 | zend_bool cookie_httponly; | ||
| 151 | ps_module *mod; | ||
| 152 | void *mod_data; | ||
| 153 | php_session_status session_status; | ||
| 154 | long gc_probability; | ||
| 155 | long gc_divisor; | ||
| 156 | long gc_maxlifetime; | ||
| 157 | int module_number; | ||
| 158 | long cache_expire; | ||
| 159 | zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */ | ||
| 160 | zend_bool bug_compat_warn; /* Whether to warn about it */ | ||
| 161 | const struct ps_serializer_struct *serializer; | ||
| 162 | zval *http_session_vars; | ||
| 163 | zend_bool auto_start; | ||
| 164 | zend_bool use_cookies; | ||
| 165 | zend_bool use_only_cookies; | ||
| 166 | zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */ | ||
| 167 | zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */ | ||
| 168 | |||
| 169 | long hash_func; | ||
| 170 | long hash_bits_per_character; | ||
| 171 | int send_cookie; | ||
| 172 | int define_sid; | ||
| 173 | zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ | ||
| 174 | } php_ps_globals_52_60; | ||
| 175 | |||
| 176 | |||
| 177 | #ifdef ZTS | ||
| 178 | static ts_rsrc_id session_globals_id = 0; | ||
| 179 | # if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) | ||
| 180 | # define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_52_60 *, v) | ||
| 181 | # elif (PHP_MAJOR_VERSION == 5) | ||
| 182 | # define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_50_51 *, v) | ||
| 183 | # elif (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION >= 3) | ||
| 184 | # define SESSION_G(v) TSRMG(session_globals_id, php_ps_globals_43_44 *, v) | ||
| 185 | # else | ||
| 186 | UNSUPPORTED PHP VERSION | ||
| 187 | # endif | ||
| 188 | #else | ||
| 189 | # if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) | ||
| 190 | static php_ps_globals_52_60 *session_globals = NULL; | ||
| 191 | # elif (PHP_MAJOR_VERSION == 5) | ||
| 192 | static php_ps_globals_50_51 *session_globals = NULL; | ||
| 193 | # elif (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION >= 3) | ||
| 194 | static php_ps_globals_43_44 *session_globals = NULL; | ||
| 195 | # else | ||
| 196 | UNSUPPORTED PHP VERSION | ||
| 197 | # endif | ||
| 198 | #define SESSION_G(v) (session_globals->v) | ||
| 199 | #endif | ||
| 200 | |||
| 201 | void suhosin_get_ipv4(char *buf TSRMLS_DC) | ||
| 202 | { | ||
| 203 | char *raddr = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); | ||
| 204 | int i; | ||
| 205 | |||
| 206 | |||
| 207 | if (raddr == NULL) { | ||
| 208 | memset(buf, 0, 4); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | |||
| 212 | for (i=0; i<4; i++) { | ||
| 213 | if (raddr[0] == 0) { | ||
| 214 | buf[i] = 0; | ||
| 215 | } else { | ||
| 216 | buf[i] = strtol(raddr, &raddr, 10); | ||
| 217 | if (raddr[0] == '.') { | ||
| 218 | raddr++; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC) | ||
| 225 | { | ||
| 226 | int padded_len, i, slen; | ||
| 227 | unsigned char *crypted, *tmp; | ||
| 228 | unsigned int check = 0x13579BDF; | ||
| 229 | |||
| 230 | if (str == NULL) { | ||
| 231 | return NULL; | ||
| 232 | } | ||
| 233 | if (len == 0) { | ||
| 234 | return estrndup("", 0); | ||
| 235 | } | ||
| 236 | |||
| 237 | |||
| 238 | suhosin_aes_gkey(4,8,key TSRMLS_CC); | ||
| 239 | |||
| 240 | padded_len = ((len+15) & ~0xF); | ||
| 241 | crypted = emalloc(16+padded_len+1); | ||
| 242 | memset(crypted, 0xff, 16+padded_len+1); | ||
| 243 | memcpy(crypted+16, str, len+1); | ||
| 244 | |||
| 245 | /* calculate check value */ | ||
| 246 | for (i = 0; i<vlen; i++) { | ||
| 247 | check = (check << 3) | (check >> (32-3)); | ||
| 248 | check += check << 1; | ||
| 249 | check ^= (unsigned char)var[i]; | ||
| 250 | } | ||
| 251 | for (i = 0; i<len; i++) { | ||
| 252 | check = (check << 3) | (check >> (32-3)); | ||
| 253 | check += check << 1; | ||
| 254 | check ^= (unsigned char)str[i]; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* store ip value */ | ||
| 258 | suhosin_get_ipv4(crypted+4 TSRMLS_CC); | ||
| 259 | |||
| 260 | /* store check value */ | ||
| 261 | crypted[8] = check & 0xff; | ||
| 262 | crypted[9] = (check >> 8) & 0xff; | ||
| 263 | crypted[10] = (check >> 16) & 0xff; | ||
| 264 | crypted[11] = (check >> 24) & 0xff; | ||
| 265 | |||
| 266 | /* store original length */ | ||
| 267 | crypted[12] = len & 0xff; | ||
| 268 | crypted[13] = (len >> 8) & 0xff; | ||
| 269 | crypted[14] = (len >> 16) & 0xff; | ||
| 270 | crypted[15] = (len >> 24) & 0xff; | ||
| 271 | |||
| 272 | for (i=0, tmp=crypted; i<padded_len+16; i+=16, tmp+=16) { | ||
| 273 | if (i > 0) { | ||
| 274 | int j; | ||
| 275 | for (j=0; j<16; j++) tmp[j] ^= tmp[j-16]; | ||
| 276 | } | ||
| 277 | suhosin_aes_encrypt((char *)tmp TSRMLS_CC); | ||
| 278 | } | ||
| 279 | |||
| 280 | tmp = php_base64_encode(crypted, padded_len+16, NULL); | ||
| 281 | efree(crypted); | ||
| 282 | slen=strlen((char *)tmp); | ||
| 283 | for (i=0; i<slen; i++) { | ||
| 284 | switch (tmp[i]) { | ||
| 285 | case '/': tmp[i]='-'; break; | ||
| 286 | case '=': tmp[i]='.'; break; | ||
| 287 | case '+': tmp[i]='_'; break; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | return (char *)tmp; | ||
| 291 | } | ||
| 292 | |||
| 293 | char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, char *key, int *orig_len, int check_ra TSRMLS_DC) | ||
| 294 | { | ||
| 295 | int len, i, o_len, invalid = 0; | ||
| 296 | unsigned char *decrypted, *tmp; | ||
| 297 | unsigned int check = 0x13579BDF; | ||
| 298 | char buf[4]; | ||
| 299 | |||
| 300 | if (str == NULL) { | ||
| 301 | return NULL; | ||
| 302 | } | ||
| 303 | |||
| 304 | if (padded_len == 0) { | ||
| 305 | if (orig_len) { | ||
| 306 | *orig_len = 0; | ||
| 307 | } | ||
| 308 | return estrndup("", 0); | ||
| 309 | } | ||
| 310 | suhosin_aes_gkey(4,8,key TSRMLS_CC); | ||
| 311 | |||
| 312 | for (i=0; i<padded_len; i++) { | ||
| 313 | switch (str[i]) { | ||
| 314 | case '-': str[i]='/'; break; | ||
| 315 | case '.': str[i]='='; break; | ||
| 316 | case '_': str[i]='+'; break; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | decrypted = php_base64_decode((unsigned char *)str, padded_len, &len); | ||
| 321 | if (decrypted == NULL || len < 2*16 || (len % 16) != 0) { | ||
| 322 | error_out: | ||
| 323 | if (decrypted != NULL) { | ||
| 324 | efree(decrypted); | ||
| 325 | } | ||
| 326 | if (orig_len) { | ||
| 327 | *orig_len = 0; | ||
| 328 | } | ||
| 329 | return NULL; | ||
| 330 | } | ||
| 331 | |||
| 332 | for (i=len-16, tmp=decrypted+i; i>=0; i-=16, tmp-=16) { | ||
| 333 | suhosin_aes_decrypt((char *)tmp TSRMLS_CC); | ||
| 334 | if (i > 0) { | ||
| 335 | int j; | ||
| 336 | for (j=0; j<16; j++) tmp[j] ^= tmp[j-16]; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | /* retrieve orig_len */ | ||
| 341 | o_len = decrypted[15]; | ||
| 342 | o_len <<= 8; | ||
| 343 | o_len |= decrypted[14]; | ||
| 344 | o_len <<= 8; | ||
| 345 | o_len |= decrypted[13]; | ||
| 346 | o_len <<= 8; | ||
| 347 | o_len |= decrypted[12]; | ||
| 348 | |||
| 349 | if (o_len < 0 || o_len > len-16) { | ||
| 350 | goto error_out; | ||
| 351 | } | ||
| 352 | |||
| 353 | /* calculate check value */ | ||
| 354 | for (i = 0; i<vlen; i++) { | ||
| 355 | check = (check << 3) | (check >> (32-3)); | ||
| 356 | check += check << 1; | ||
| 357 | check ^= (unsigned char)var[i]; | ||
| 358 | } | ||
| 359 | for (i = 0; i<o_len; i++) { | ||
| 360 | check = (check << 3) | (check >> (32-3)); | ||
| 361 | check += check << 1; | ||
| 362 | check ^= decrypted[16+i]; | ||
| 363 | } | ||
| 364 | |||
| 365 | /* check value */ | ||
| 366 | invalid = (decrypted[8] != (check & 0xff)) || | ||
| 367 | (decrypted[9] != ((check >> 8) & 0xff)) || | ||
| 368 | (decrypted[10] != ((check >> 16) & 0xff)) || | ||
| 369 | (decrypted[11] != ((check >> 24) & 0xff)); | ||
| 370 | |||
| 371 | /* check IP */ | ||
| 372 | if (check_ra > 0) { | ||
| 373 | if (check_ra > 4) { | ||
| 374 | check_ra = 4; | ||
| 375 | } | ||
| 376 | suhosin_get_ipv4(&buf TSRMLS_CC); | ||
| 377 | if (memcmp(buf, decrypted+4, check_ra) != 0) { | ||
| 378 | goto error_out; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | if (invalid) { | ||
| 383 | goto error_out; | ||
| 384 | } | ||
| 385 | |||
| 386 | if (orig_len) { | ||
| 387 | *orig_len = o_len; | ||
| 388 | } | ||
| 389 | |||
| 390 | memmove(decrypted, decrypted+16, o_len); | ||
| 391 | decrypted[o_len] = 0; | ||
| 392 | /* we do not realloc() here because 16 byte less | ||
| 393 | is simply not worth the overhead */ | ||
| 394 | return (char *)decrypted; | ||
| 395 | } | ||
| 396 | |||
| 397 | char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC) | ||
| 398 | { | ||
| 399 | char *_ua = NULL; | ||
| 400 | char *_dr = NULL; | ||
| 401 | char *_ra = NULL; | ||
| 402 | suhosin_SHA256_CTX ctx; | ||
| 403 | |||
| 404 | if (ua) { | ||
| 405 | _ua = sapi_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC); | ||
| 406 | } | ||
| 407 | |||
| 408 | if (dr) { | ||
| 409 | _dr = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); | ||
| 410 | } | ||
| 411 | |||
| 412 | if (raddr > 0) { | ||
| 413 | _ra = sapi_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC); | ||
| 414 | } | ||
| 415 | |||
| 416 | SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra); | ||
| 417 | |||
| 418 | suhosin_SHA256Init(&ctx); | ||
| 419 | if (key == NULL) { | ||
| 420 | suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", sizeof("D3F4UL7")); | ||
| 421 | } else { | ||
| 422 | suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key)); | ||
| 423 | } | ||
| 424 | if (_ua) { | ||
| 425 | suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua)); | ||
| 426 | } | ||
| 427 | if (_dr) { | ||
| 428 | suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr)); | ||
| 429 | } | ||
| 430 | if (_ra) { | ||
| 431 | if (raddr >= 4) { | ||
| 432 | suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra)); | ||
| 433 | } else { | ||
| 434 | long dots = 0; | ||
| 435 | char *tmp = _ra; | ||
| 436 | |||
| 437 | while (*tmp) { | ||
| 438 | if (*tmp == '.') { | ||
| 439 | dots++; | ||
| 440 | if (dots == raddr) { | ||
| 441 | break; | ||
| 442 | } | ||
| 443 | } | ||
| 444 | tmp++; | ||
| 445 | } | ||
| 446 | suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | suhosin_SHA256Final((unsigned char *)cryptkey, &ctx); | ||
| 450 | cryptkey[32] = 0; /* uhmm... not really a string */ | ||
| 451 | |||
| 452 | return cryptkey; | ||
| 453 | } | ||
| 454 | |||
| 455 | |||
| 456 | static int (*old_OnUpdateSaveHandler)(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC) = NULL; | ||
| 457 | static int (*old_SessionRINIT)(INIT_FUNC_ARGS) = NULL; | ||
| 458 | |||
| 459 | static int suhosin_hook_s_read(void **mod_data, const char *key, char **val, int *vallen TSRMLS_DC) | ||
| 460 | { | ||
| 461 | int r; | ||
| 462 | |||
| 463 | int i;char *v,*KEY=(char *)key; | ||
| 464 | |||
| 465 | /* protect session vars */ | ||
| 466 | /* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { | ||
| 467 | SESSION_G(http_session_vars)->refcount++; | ||
| 468 | }*/ | ||
| 469 | |||
| 470 | /* protect dumb session handlers */ | ||
| 471 | if (key == NULL || !key[0] || *mod_data == NULL) { | ||
| 472 | regenerate: | ||
| 473 | SDEBUG("regenerating key is %s", key); | ||
| 474 | KEY = SESSION_G(id) = SESSION_G(mod)->s_create_sid(&SESSION_G(mod_data), NULL TSRMLS_CC); | ||
| 475 | SESSION_G(send_cookie) = 1; | ||
| 476 | } else if (strlen(key) > SUHOSIN_G(session_max_id_length)) { | ||
| 477 | suhosin_log(S_SESSION, "session id ('%s') exceeds maximum length - regenerating", KEY); | ||
| 478 | if (!SUHOSIN_G(simulation)) { | ||
| 479 | goto regenerate; | ||
| 480 | } | ||
| 481 | } | ||
| 482 | #if (PHP_MAJOR_VERSION < 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) | ||
| 483 | else if (strpbrk(KEY, "\r\n\t <>'\"\\")) { | ||
| 484 | suhosin_log(S_SESSION, "session id ('%s') contains invalid chars - regenerating", KEY); | ||
| 485 | if (!SUHOSIN_G(simulation)) { | ||
| 486 | goto regenerate; | ||
| 487 | } | ||
| 488 | } | ||
| 489 | #endif | ||
| 490 | |||
| 491 | r = SUHOSIN_G(old_s_read)(mod_data, KEY, val, vallen TSRMLS_CC); | ||
| 492 | |||
| 493 | if (r == SUCCESS && SUHOSIN_G(session_encrypt) && *vallen > 0) { | ||
| 494 | char cryptkey[33]; | ||
| 495 | |||
| 496 | SUHOSIN_G(do_not_scan) = 1; | ||
| 497 | suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); | ||
| 498 | |||
| 499 | v = *val; | ||
| 500 | i = *vallen; | ||
| 501 | *val = suhosin_decrypt_string(v, i, "", 0, (char *)&cryptkey, vallen, SUHOSIN_G(session_checkraddr) TSRMLS_CC); | ||
| 502 | SUHOSIN_G(do_not_scan) = 0; | ||
| 503 | if (*val == NULL) { | ||
| 504 | *val = estrndup("", 0); | ||
| 505 | *vallen = 0; | ||
| 506 | } | ||
| 507 | efree(v); | ||
| 508 | } | ||
| 509 | |||
| 510 | return r; | ||
| 511 | } | ||
| 512 | |||
| 513 | static int suhosin_hook_s_write(void **mod_data, const char *key, const char *val, const int vallen TSRMLS_DC) | ||
| 514 | { | ||
| 515 | int r; | ||
| 516 | /* int nullify = 0;*/ | ||
| 517 | char *v = (char *)val; | ||
| 518 | |||
| 519 | /* protect dumb session handlers */ | ||
| 520 | if (key == NULL || !key[0] || val == NULL || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { | ||
| 521 | r = FAILURE; | ||
| 522 | goto return_write; | ||
| 523 | } | ||
| 524 | |||
| 525 | r = vallen; | ||
| 526 | |||
| 527 | if (r > 0 && SUHOSIN_G(session_encrypt)) { | ||
| 528 | char cryptkey[33]; | ||
| 529 | |||
| 530 | SUHOSIN_G(do_not_scan) = 1; | ||
| 531 | |||
| 532 | suhosin_generate_key(SUHOSIN_G(session_cryptkey), SUHOSIN_G(session_cryptua), SUHOSIN_G(session_cryptdocroot), SUHOSIN_G(session_cryptraddr), (char *)&cryptkey TSRMLS_CC); | ||
| 533 | |||
| 534 | v = suhosin_encrypt_string(v, vallen, "", 0, (char *)&cryptkey TSRMLS_CC); | ||
| 535 | |||
| 536 | SUHOSIN_G(do_not_scan) = 0; | ||
| 537 | r = strlen(v); | ||
| 538 | } | ||
| 539 | |||
| 540 | r = SUHOSIN_G(old_s_write)(mod_data, key, v, r TSRMLS_CC); | ||
| 541 | |||
| 542 | return_write: | ||
| 543 | /* protect session vars */ | ||
| 544 | /* if (SESSION_G(http_session_vars) && SESSION_G(http_session_vars)->type == IS_ARRAY) { | ||
| 545 | if (SESSION_G(http_session_vars)->refcount==1) { | ||
| 546 | nullify = 1; | ||
| 547 | } | ||
| 548 | zval_ptr_dtor(&SESSION_G(http_session_vars)); | ||
| 549 | if (nullify) { | ||
| 550 | suhosin_log(S_SESSION, "possible session variables double free attack stopped"); | ||
| 551 | SESSION_G(http_session_vars) = NULL; | ||
| 552 | } | ||
| 553 | }*/ | ||
| 554 | |||
| 555 | return r; | ||
| 556 | } | ||
| 557 | |||
| 558 | static int suhosin_hook_s_destroy(void **mod_data, const char *key TSRMLS_DC) | ||
| 559 | { | ||
| 560 | int r; | ||
| 561 | |||
| 562 | /* protect dumb session handlers */ | ||
| 563 | if (key == NULL || !key[0] || strlen(key) > SUHOSIN_G(session_max_id_length) || *mod_data == NULL) { | ||
| 564 | return FAILURE; | ||
| 565 | } | ||
| 566 | |||
| 567 | r = SUHOSIN_G(old_s_destroy)(mod_data, key TSRMLS_CC); | ||
| 568 | |||
| 569 | return r; | ||
| 570 | } | ||
| 571 | |||
| 572 | static void suhosin_hook_session_module(TSRMLS_D) | ||
| 573 | { | ||
| 574 | ps_module *old_mod = SESSION_G(mod), *mod; | ||
| 575 | |||
| 576 | if (old_mod == NULL || SUHOSIN_G(s_module) == old_mod) { | ||
| 577 | return; | ||
| 578 | } | ||
| 579 | if (SUHOSIN_G(s_module) == NULL) { | ||
| 580 | SUHOSIN_G(s_module) = mod = malloc(sizeof(ps_module)); | ||
| 581 | if (mod == NULL) { | ||
| 582 | return; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | mod = SUHOSIN_G(s_module); | ||
| 586 | memcpy(mod, old_mod, sizeof(ps_module)); | ||
| 587 | |||
| 588 | SUHOSIN_G(old_s_read) = mod->s_read; | ||
| 589 | mod->s_read = suhosin_hook_s_read; | ||
| 590 | SUHOSIN_G(old_s_write) = mod->s_write; | ||
| 591 | mod->s_write = suhosin_hook_s_write; | ||
| 592 | SUHOSIN_G(old_s_destroy) = mod->s_destroy; | ||
| 593 | mod->s_destroy = suhosin_hook_s_destroy; | ||
| 594 | |||
| 595 | SESSION_G(mod) = mod; | ||
| 596 | } | ||
| 597 | |||
| 598 | static PHP_INI_MH(suhosin_OnUpdateSaveHandler) | ||
| 599 | { | ||
| 600 | int r; | ||
| 601 | |||
| 602 | r = old_OnUpdateSaveHandler(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); | ||
| 603 | |||
| 604 | suhosin_hook_session_module(TSRMLS_C); | ||
| 605 | |||
| 606 | return r; | ||
| 607 | } | ||
| 608 | |||
| 609 | |||
| 610 | static int suhosin_hook_session_RINIT(INIT_FUNC_ARGS) | ||
| 611 | { | ||
| 612 | if (SESSION_G(mod) == NULL) { | ||
| 613 | char *value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); | ||
| 614 | |||
| 615 | if (value) { | ||
| 616 | suhosin_OnUpdateSaveHandler(NULL, value, strlen(value), NULL, NULL, NULL, 0 TSRMLS_CC); | ||
| 617 | } | ||
| 618 | } | ||
| 619 | return old_SessionRINIT(INIT_FUNC_ARGS_PASSTHRU); | ||
| 620 | } | ||
| 621 | |||
| 622 | void suhosin_hook_session(TSRMLS_D) | ||
| 623 | { | ||
| 624 | zend_ini_entry *ini_entry; | ||
| 625 | zend_module_entry *module; | ||
| 626 | #ifdef ZTS | ||
| 627 | ts_rsrc_id *ps_globals_id_ptr; | ||
| 628 | #endif | ||
| 629 | |||
| 630 | if (zend_hash_find(&module_registry, "session", sizeof("session"), (void**)&module) == FAILURE) { | ||
| 631 | return; | ||
| 632 | } | ||
| 633 | /* retrieve globals from module entry struct if possible */ | ||
| 634 | #if PHP_VERSION_ID >= 50200 | ||
| 635 | #ifdef ZTS | ||
| 636 | if (session_globals_id == 0) { | ||
| 637 | session_globals_id = *module->globals_id_ptr; | ||
| 638 | } | ||
| 639 | #else | ||
| 640 | if (session_globals == NULL) { | ||
| 641 | session_globals = module->globals_ptr; | ||
| 642 | } | ||
| 643 | #endif | ||
| 644 | #else | ||
| 645 | /* retrieve globals from symbols if PHP version is old */ | ||
| 646 | #ifdef ZTS | ||
| 647 | if (session_globals_id == 0) { | ||
| 648 | ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "ps_globals_id"); | ||
| 649 | if (ps_globals_id_ptr == NULL) { | ||
| 650 | ps_globals_id_ptr = DL_FETCH_SYMBOL(module->handle, "_ps_globals_id"); | ||
| 651 | } | ||
| 652 | if (ps_globals_id_ptr == NULL) { | ||
| 653 | return; | ||
| 654 | } | ||
| 655 | |||
| 656 | session_globals_id = *ps_globals_id_ptr; | ||
| 657 | } | ||
| 658 | #else | ||
| 659 | if (session_globals == NULL) { | ||
| 660 | session_globals = DL_FETCH_SYMBOL(module->handle, "ps_globals"); | ||
| 661 | if (session_globals == NULL) { | ||
| 662 | session_globals = DL_FETCH_SYMBOL(module->handle, "_ps_globals"); | ||
| 663 | } | ||
| 664 | if (session_globals == NULL) { | ||
| 665 | return; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | #endif | ||
| 669 | #endif | ||
| 670 | if (old_OnUpdateSaveHandler != NULL) { | ||
| 671 | return; | ||
| 672 | } | ||
| 673 | |||
| 674 | /* hook request startup function of session module */ | ||
| 675 | old_SessionRINIT = module->request_startup_func; | ||
| 676 | module->request_startup_func = suhosin_hook_session_RINIT; | ||
| 677 | |||
| 678 | /* retrieve pointer to session.save_handler ini entry */ | ||
| 679 | if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { | ||
| 680 | return; | ||
| 681 | } | ||
| 682 | SUHOSIN_G(s_module) = NULL; | ||
| 683 | |||
| 684 | /* replace OnUpdateMemoryLimit handler */ | ||
| 685 | old_OnUpdateSaveHandler = ini_entry->on_modify; | ||
| 686 | ini_entry->on_modify = suhosin_OnUpdateSaveHandler; | ||
| 687 | |||
| 688 | suhosin_hook_session_module(TSRMLS_C); | ||
| 689 | } | ||
| 690 | |||
| 691 | void suhosin_unhook_session(TSRMLS_D) | ||
| 692 | { | ||
| 693 | if (old_OnUpdateSaveHandler != NULL) { | ||
| 694 | zend_ini_entry *ini_entry; | ||
| 695 | |||
| 696 | /* retrieve pointer to session.save_handler ini entry */ | ||
| 697 | if (zend_hash_find(EG(ini_directives), "session.save_handler", sizeof("session.save_handler"), (void **) &ini_entry) == FAILURE) { | ||
| 698 | return; | ||
| 699 | } | ||
| 700 | ini_entry->on_modify = old_OnUpdateSaveHandler; | ||
| 701 | |||
| 702 | old_OnUpdateSaveHandler = NULL; | ||
| 703 | } | ||
| 704 | |||
| 705 | } | ||
| 706 | |||
| 707 | /* | ||
| 708 | * Local variables: | ||
| 709 | * tab-width: 4 | ||
| 710 | * c-basic-offset: 4 | ||
| 711 | * End: | ||
| 712 | * vim600: sw=4 ts=4 fdm=marker | ||
| 713 | * vim<600: sw=4 ts=4 | ||
| 714 | */ | ||
diff --git a/sha256.c b/sha256.c new file mode 100644 index 0000000..35715e9 --- /dev/null +++ b/sha256.c | |||
| @@ -0,0 +1,432 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: sha256.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 21 | |||
| 22 | #include <stdio.h> | ||
| 23 | #include "php.h" | ||
| 24 | |||
| 25 | /* This code is heavily based on the PHP md5/sha1 implementations */ | ||
| 26 | |||
| 27 | #include "sha256.h" | ||
| 28 | |||
| 29 | static void make_sha256_digest(char *sha256str, unsigned char *digest) | ||
| 30 | { | ||
| 31 | int i; | ||
| 32 | |||
| 33 | for (i = 0; i < 32; i++) { | ||
| 34 | sprintf(sha256str, "%02x", digest[i]); | ||
| 35 | sha256str += 2; | ||
| 36 | } | ||
| 37 | |||
| 38 | *sha256str = '\0'; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* {{{ proto string sha256(string str [, bool raw_output]) | ||
| 42 | Calculate the sha256 hash of a string */ | ||
| 43 | static PHP_FUNCTION(suhosin_sha256) | ||
| 44 | { | ||
| 45 | char *arg; | ||
| 46 | int arg_len; | ||
| 47 | zend_bool raw_output = 0; | ||
| 48 | char sha256str[65]; | ||
| 49 | suhosin_SHA256_CTX context; | ||
| 50 | unsigned char digest[32]; | ||
| 51 | |||
| 52 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | sha256str[0] = '\0'; | ||
| 57 | suhosin_SHA256Init(&context); | ||
| 58 | suhosin_SHA256Update(&context, (unsigned char *)arg, (unsigned int)arg_len); | ||
| 59 | suhosin_SHA256Final(digest, &context); | ||
| 60 | if (raw_output) { | ||
| 61 | RETURN_STRINGL((char *)digest, 32, 1); | ||
| 62 | } else { | ||
| 63 | make_sha256_digest(sha256str, digest); | ||
| 64 | RETVAL_STRING(sha256str, 1); | ||
| 65 | } | ||
| 66 | |||
| 67 | } | ||
| 68 | |||
| 69 | /* }}} */ | ||
| 70 | |||
| 71 | /* {{{ proto string sha256_file(string filename [, bool raw_output]) | ||
| 72 | Calculate the sha256 hash of given filename */ | ||
| 73 | static PHP_FUNCTION(suhosin_sha256_file) | ||
| 74 | { | ||
| 75 | char *arg; | ||
| 76 | int arg_len; | ||
| 77 | zend_bool raw_output = 0; | ||
| 78 | char sha256str[65]; | ||
| 79 | unsigned char buf[1024]; | ||
| 80 | unsigned char digest[32]; | ||
| 81 | suhosin_SHA256_CTX context; | ||
| 82 | int n; | ||
| 83 | FILE *fp; | ||
| 84 | |||
| 85 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) { | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (PG(safe_mode) && (!php_checkuid(arg, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { | ||
| 90 | RETURN_FALSE; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (php_check_open_basedir(arg TSRMLS_CC)) { | ||
| 94 | RETURN_FALSE; | ||
| 95 | } | ||
| 96 | |||
| 97 | if ((fp = VCWD_FOPEN(arg, "rb")) == NULL) { | ||
| 98 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open file"); | ||
| 99 | RETURN_FALSE; | ||
| 100 | } | ||
| 101 | |||
| 102 | suhosin_SHA256Init(&context); | ||
| 103 | |||
| 104 | while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) { | ||
| 105 | suhosin_SHA256Update(&context, buf, n); | ||
| 106 | } | ||
| 107 | |||
| 108 | suhosin_SHA256Final(digest, &context); | ||
| 109 | |||
| 110 | if (ferror(fp)) { | ||
| 111 | fclose(fp); | ||
| 112 | RETURN_FALSE; | ||
| 113 | } | ||
| 114 | |||
| 115 | fclose(fp); | ||
| 116 | |||
| 117 | if (raw_output) { | ||
| 118 | RETURN_STRINGL((char *)digest, 32, 1); | ||
| 119 | } else { | ||
| 120 | make_sha256_digest(sha256str, digest); | ||
| 121 | RETVAL_STRING(sha256str, 1); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | /* }}} */ | ||
| 125 | |||
| 126 | |||
| 127 | static void SHA256Transform(php_uint32[8], const unsigned char[64]); | ||
| 128 | static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int); | ||
| 129 | static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int); | ||
| 130 | |||
| 131 | static unsigned char PADDING[64] = | ||
| 132 | { | ||
| 133 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 134 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 135 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 136 | }; | ||
| 137 | |||
| 138 | /* F, G, H and I are basic SHA256 functions. | ||
| 139 | */ | ||
| 140 | #define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22)) | ||
| 141 | #define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x)))) | ||
| 142 | #define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25)) | ||
| 143 | #define I(x, y, z) (((x) & (y)) | ((~x) & z)) | ||
| 144 | |||
| 145 | /* ROTATE_RIGHT rotates x right n bits. | ||
| 146 | */ | ||
| 147 | #define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n)))) | ||
| 148 | |||
| 149 | /* W[i] | ||
| 150 | */ | ||
| 151 | #define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \ | ||
| 152 | tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \ | ||
| 153 | (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) ) | ||
| 154 | |||
| 155 | /* ROUND function of sha256 | ||
| 156 | */ | ||
| 157 | |||
| 158 | #define ROUND(a,b,c,d,e,f,g,h,w,k) { \ | ||
| 159 | t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \ | ||
| 160 | (h) = F((a)) + G((a), (b), (c)) + t1; \ | ||
| 161 | (d) += t1; \ | ||
| 162 | } | ||
| 163 | |||
| 164 | |||
| 165 | /* {{{ suhosin_SHA256Init | ||
| 166 | * SHA256 initialization. Begins an SHA256 operation, writing a new context. | ||
| 167 | */ | ||
| 168 | void suhosin_SHA256Init(suhosin_SHA256_CTX * context) | ||
| 169 | { | ||
| 170 | context->count[0] = context->count[1] = 0; | ||
| 171 | /* Load magic initialization constants. | ||
| 172 | */ | ||
| 173 | context->state[0] = 0x6a09e667; | ||
| 174 | context->state[1] = 0xbb67ae85; | ||
| 175 | context->state[2] = 0x3c6ef372; | ||
| 176 | context->state[3] = 0xa54ff53a; | ||
| 177 | context->state[4] = 0x510e527f; | ||
| 178 | context->state[5] = 0x9b05688c; | ||
| 179 | context->state[6] = 0x1f83d9ab; | ||
| 180 | context->state[7] = 0x5be0cd19; | ||
| 181 | } | ||
| 182 | /* }}} */ | ||
| 183 | |||
| 184 | /* {{{ suhosin_SHA256Update | ||
| 185 | SHA256 block update operation. Continues an SHA256 message-digest | ||
| 186 | operation, processing another message block, and updating the | ||
| 187 | context. | ||
| 188 | */ | ||
| 189 | void suhosin_SHA256Update(suhosin_SHA256_CTX * context, const unsigned char *input, | ||
| 190 | unsigned int inputLen) | ||
| 191 | { | ||
| 192 | unsigned int i, index, partLen; | ||
| 193 | |||
| 194 | /* Compute number of bytes mod 64 */ | ||
| 195 | index = (unsigned int) ((context->count[0] >> 3) & 0x3F); | ||
| 196 | |||
| 197 | /* Update number of bits */ | ||
| 198 | if ((context->count[0] += ((php_uint32) inputLen << 3)) | ||
| 199 | < ((php_uint32) inputLen << 3)) | ||
| 200 | context->count[1]++; | ||
| 201 | context->count[1] += ((php_uint32) inputLen >> 29); | ||
| 202 | |||
| 203 | partLen = 64 - index; | ||
| 204 | |||
| 205 | /* Transform as many times as possible. | ||
| 206 | */ | ||
| 207 | if (inputLen >= partLen) { | ||
| 208 | memcpy | ||
| 209 | ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen); | ||
| 210 | SHA256Transform(context->state, context->buffer); | ||
| 211 | |||
| 212 | for (i = partLen; i + 63 < inputLen; i += 64) | ||
| 213 | SHA256Transform(context->state, &input[i]); | ||
| 214 | |||
| 215 | index = 0; | ||
| 216 | } else | ||
| 217 | i = 0; | ||
| 218 | |||
| 219 | /* Buffer remaining input */ | ||
| 220 | memcpy | ||
| 221 | ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], | ||
| 222 | inputLen - i); | ||
| 223 | } | ||
| 224 | /* }}} */ | ||
| 225 | |||
| 226 | /* {{{ suhosin_SHA256Final | ||
| 227 | SHA256 finalization. Ends an SHA256 message-digest operation, writing the | ||
| 228 | the message digest and zeroizing the context. | ||
| 229 | */ | ||
| 230 | void suhosin_SHA256Final(unsigned char digest[32], suhosin_SHA256_CTX * context) | ||
| 231 | { | ||
| 232 | unsigned char bits[8]; | ||
| 233 | unsigned int index, padLen; | ||
| 234 | |||
| 235 | /* Save number of bits */ | ||
| 236 | bits[7] = context->count[0] & 0xFF; | ||
| 237 | bits[6] = (context->count[0] >> 8) & 0xFF; | ||
| 238 | bits[5] = (context->count[0] >> 16) & 0xFF; | ||
| 239 | bits[4] = (context->count[0] >> 24) & 0xFF; | ||
| 240 | bits[3] = context->count[1] & 0xFF; | ||
| 241 | bits[2] = (context->count[1] >> 8) & 0xFF; | ||
| 242 | bits[1] = (context->count[1] >> 16) & 0xFF; | ||
| 243 | bits[0] = (context->count[1] >> 24) & 0xFF; | ||
| 244 | |||
| 245 | /* Pad out to 56 mod 64. | ||
| 246 | */ | ||
| 247 | index = (unsigned int) ((context->count[0] >> 3) & 0x3f); | ||
| 248 | padLen = (index < 56) ? (56 - index) : (120 - index); | ||
| 249 | suhosin_SHA256Update(context, PADDING, padLen); | ||
| 250 | |||
| 251 | /* Append length (before padding) */ | ||
| 252 | suhosin_SHA256Update(context, bits, 8); | ||
| 253 | |||
| 254 | /* Store state in digest */ | ||
| 255 | SHA256Encode(digest, context->state, 32); | ||
| 256 | |||
| 257 | /* Zeroize sensitive information. | ||
| 258 | */ | ||
| 259 | memset((unsigned char*) context, 0, sizeof(*context)); | ||
| 260 | } | ||
| 261 | /* }}} */ | ||
| 262 | |||
| 263 | /* {{{ SHA256Transform | ||
| 264 | * SHA256 basic transformation. Transforms state based on block. | ||
| 265 | */ | ||
| 266 | static void SHA256Transform(state, block) | ||
| 267 | php_uint32 state[8]; | ||
| 268 | const unsigned char block[64]; | ||
| 269 | { | ||
| 270 | php_uint32 a = state[0], b = state[1], c = state[2]; | ||
| 271 | php_uint32 d = state[3], e = state[4], f = state[5]; | ||
| 272 | php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1; | ||
| 273 | |||
| 274 | SHA256Decode(x, block, 64); | ||
| 275 | |||
| 276 | ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98) | ||
| 277 | ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491) | ||
| 278 | ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf) | ||
| 279 | ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5) | ||
| 280 | ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b) | ||
| 281 | ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1) | ||
| 282 | ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4) | ||
| 283 | ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5) | ||
| 284 | ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98) | ||
| 285 | ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01) | ||
| 286 | ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be) | ||
| 287 | ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3) | ||
| 288 | ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74) | ||
| 289 | ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe) | ||
| 290 | ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7) | ||
| 291 | ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174) | ||
| 292 | ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1) | ||
| 293 | ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786) | ||
| 294 | ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6) | ||
| 295 | ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc) | ||
| 296 | ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f) | ||
| 297 | ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa) | ||
| 298 | ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc) | ||
| 299 | ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da) | ||
| 300 | ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152) | ||
| 301 | ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d) | ||
| 302 | ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8) | ||
| 303 | ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7) | ||
| 304 | ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3) | ||
| 305 | ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147) | ||
| 306 | ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351) | ||
| 307 | ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967) | ||
| 308 | ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85) | ||
| 309 | ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138) | ||
| 310 | ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc) | ||
| 311 | ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13) | ||
| 312 | ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354) | ||
| 313 | ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb) | ||
| 314 | ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e) | ||
| 315 | ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85) | ||
| 316 | ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1) | ||
| 317 | ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b) | ||
| 318 | ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70) | ||
| 319 | ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3) | ||
| 320 | ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819) | ||
| 321 | ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624) | ||
| 322 | ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585) | ||
| 323 | ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070) | ||
| 324 | ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116) | ||
| 325 | ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08) | ||
| 326 | ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c) | ||
| 327 | ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5) | ||
| 328 | ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3) | ||
| 329 | ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a) | ||
| 330 | ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f) | ||
| 331 | ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3) | ||
| 332 | ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee) | ||
| 333 | ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f) | ||
| 334 | ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814) | ||
| 335 | ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208) | ||
| 336 | ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa) | ||
| 337 | ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb) | ||
| 338 | ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7) | ||
| 339 | ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2) | ||
| 340 | |||
| 341 | state[0] += a; | ||
| 342 | state[1] += b; | ||
| 343 | state[2] += c; | ||
| 344 | state[3] += d; | ||
| 345 | state[4] += e; | ||
| 346 | state[5] += f; | ||
| 347 | state[6] += g; | ||
| 348 | state[7] += h; | ||
| 349 | |||
| 350 | /* Zeroize sensitive information. */ | ||
| 351 | memset((unsigned char*) x, 0, sizeof(x)); | ||
| 352 | } | ||
| 353 | /* }}} */ | ||
| 354 | |||
| 355 | /* {{{ SHA256Encode | ||
| 356 | Encodes input (php_uint32) into output (unsigned char). Assumes len is | ||
| 357 | a multiple of 4. | ||
| 358 | */ | ||
| 359 | static void SHA256Encode(output, input, len) | ||
| 360 | unsigned char *output; | ||
| 361 | php_uint32 *input; | ||
| 362 | unsigned int len; | ||
| 363 | { | ||
| 364 | unsigned int i, j; | ||
| 365 | |||
| 366 | for (i = 0, j = 0; j < len; i++, j += 4) { | ||
| 367 | output[j] = (unsigned char) ((input[i] >> 24) & 0xff); | ||
| 368 | output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff); | ||
| 369 | output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff); | ||
| 370 | output[j + 3] = (unsigned char) (input[i] & 0xff); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | /* }}} */ | ||
| 374 | |||
| 375 | /* {{{ SHA256Decode | ||
| 376 | Decodes input (unsigned char) into output (php_uint32). Assumes len is | ||
| 377 | a multiple of 4. | ||
| 378 | */ | ||
| 379 | static void SHA256Decode(output, input, len) | ||
| 380 | php_uint32 *output; | ||
| 381 | const unsigned char *input; | ||
| 382 | unsigned int len; | ||
| 383 | { | ||
| 384 | unsigned int i, j; | ||
| 385 | |||
| 386 | for (i = 0, j = 0; j < len; i++, j += 4) | ||
| 387 | output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) | | ||
| 388 | (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24); | ||
| 389 | } | ||
| 390 | /* }}} */ | ||
| 391 | |||
| 392 | |||
| 393 | /* {{{ suhosin_sha256_functions[] | ||
| 394 | */ | ||
| 395 | static function_entry suhosin_sha256_functions[] = { | ||
| 396 | PHP_NAMED_FE(sha256, PHP_FN(suhosin_sha256), NULL) | ||
| 397 | PHP_NAMED_FE(sha256_file, PHP_FN(suhosin_sha256_file), NULL) | ||
| 398 | {NULL, NULL, NULL} | ||
| 399 | }; | ||
| 400 | /* }}} */ | ||
| 401 | |||
| 402 | |||
| 403 | void suhosin_hook_sha256() | ||
| 404 | { | ||
| 405 | TSRMLS_FETCH(); | ||
| 406 | |||
| 407 | /* check if we already have sha256 support */ | ||
| 408 | if (zend_hash_exists(CG(function_table), "sha256", sizeof("sha256"))) { | ||
| 409 | return; | ||
| 410 | } | ||
| 411 | |||
| 412 | /* add the sha256 functions */ | ||
| 413 | #ifndef ZEND_ENGINE_2 | ||
| 414 | zend_register_functions(suhosin_sha256_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); | ||
| 415 | #else | ||
| 416 | zend_register_functions(NULL, suhosin_sha256_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); | ||
| 417 | #endif | ||
| 418 | |||
| 419 | |||
| 420 | |||
| 421 | |||
| 422 | } | ||
| 423 | |||
| 424 | |||
| 425 | /* | ||
| 426 | * Local variables: | ||
| 427 | * tab-width: 4 | ||
| 428 | * c-basic-offset: 4 | ||
| 429 | * End: | ||
| 430 | * vim600: sw=4 ts=4 fdm=marker | ||
| 431 | * vim<600: sw=4 ts=4 | ||
| 432 | */ | ||
diff --git a/sha256.h b/sha256.h new file mode 100644 index 0000000..a078221 --- /dev/null +++ b/sha256.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: sha256.h,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 21 | |||
| 22 | #ifndef SHA256_H | ||
| 23 | #define SHA256_H | ||
| 24 | |||
| 25 | #include "ext/standard/basic_functions.h" | ||
| 26 | |||
| 27 | /* SHA1 context. */ | ||
| 28 | typedef struct { | ||
| 29 | php_uint32 state[8]; /* state (ABCD) */ | ||
| 30 | php_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ | ||
| 31 | unsigned char buffer[64]; /* input buffer */ | ||
| 32 | } suhosin_SHA256_CTX; | ||
| 33 | |||
| 34 | void suhosin_SHA256Init(suhosin_SHA256_CTX *); | ||
| 35 | void suhosin_SHA256Update(suhosin_SHA256_CTX *, const unsigned char *, unsigned int); | ||
| 36 | void suhosin_SHA256Final(unsigned char[32], suhosin_SHA256_CTX *); | ||
| 37 | |||
| 38 | #endif | ||
diff --git a/suhosin.c b/suhosin.c new file mode 100644 index 0000000..202011f --- /dev/null +++ b/suhosin.c | |||
| @@ -0,0 +1,1248 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: suhosin.c,v 1.2 2007-11-28 16:01:50 sesser Exp $ */ | ||
| 21 | |||
| 22 | #ifdef HAVE_CONFIG_H | ||
| 23 | #include "config.h" | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #include "php.h" | ||
| 27 | #include "php_ini.h" | ||
| 28 | #include "zend_extensions.h" | ||
| 29 | #include "ext/standard/info.h" | ||
| 30 | #include "php_syslog.h" | ||
| 31 | #include "php_suhosin.h" | ||
| 32 | #include "zend_llist.h" | ||
| 33 | #include "zend_operators.h" | ||
| 34 | #include "SAPI.h" | ||
| 35 | #include "php_logos.h" | ||
| 36 | #include "suhosin_logo.h" | ||
| 37 | #include "ext/standard/php_string.h" | ||
| 38 | #include "ext/standard/url.h" | ||
| 39 | #include "ext/standard/base64.h" | ||
| 40 | |||
| 41 | ZEND_DECLARE_MODULE_GLOBALS(suhosin) | ||
| 42 | |||
| 43 | static zend_llist_position lp = NULL; | ||
| 44 | static int (*old_startup)(zend_extension *extension) = NULL; | ||
| 45 | static zend_extension *ze = NULL; | ||
| 46 | |||
| 47 | static int suhosin_module_startup(zend_extension *extension); | ||
| 48 | static void suhosin_shutdown(zend_extension *extension); | ||
| 49 | |||
| 50 | |||
| 51 | static void (*orig_op_array_ctor)(zend_op_array *op_array) = NULL; | ||
| 52 | static void (*orig_op_array_dtor)(zend_op_array *op_array) = NULL; | ||
| 53 | static void (*orig_module_shutdown)(zend_extension *extension) = NULL; | ||
| 54 | static int (*orig_module_startup)(zend_extension *extension) = NULL; | ||
| 55 | |||
| 56 | |||
| 57 | static void suhosin_op_array_ctor(zend_op_array *op_array); | ||
| 58 | static void suhosin_op_array_dtor(zend_op_array *op_array); | ||
| 59 | |||
| 60 | STATIC zend_extension suhosin_zend_extension_entry = { | ||
| 61 | "Suhosin", | ||
| 62 | SUHOSIN_EXT_VERSION, | ||
| 63 | "SektionEins GmbH", | ||
| 64 | "http://www.suhosin.org", | ||
| 65 | "Copyright (c) 2007", | ||
| 66 | suhosin_module_startup, | ||
| 67 | suhosin_shutdown, | ||
| 68 | NULL, | ||
| 69 | NULL, | ||
| 70 | NULL, | ||
| 71 | NULL, | ||
| 72 | NULL, | ||
| 73 | NULL, | ||
| 74 | NULL, | ||
| 75 | suhosin_op_array_ctor, | ||
| 76 | suhosin_op_array_dtor, | ||
| 77 | |||
| 78 | STANDARD_ZEND_EXTENSION_PROPERTIES | ||
| 79 | }; | ||
| 80 | |||
| 81 | static void suhosin_op_array_ctor(zend_op_array *op_array) | ||
| 82 | { | ||
| 83 | TSRMLS_FETCH(); | ||
| 84 | |||
| 85 | if (suhosin_zend_extension_entry.resource_number != -1) { | ||
| 86 | |||
| 87 | unsigned long suhosin_flags = 0; | ||
| 88 | |||
| 89 | if (SUHOSIN_G(in_code_type) == SUHOSIN_EVAL) { | ||
| 90 | suhosin_flags |= SUHOSIN_FLAG_CREATED_BY_EVAL; | ||
| 91 | } | ||
| 92 | |||
| 93 | op_array->reserved[suhosin_zend_extension_entry.resource_number] = (void *)suhosin_flags; | ||
| 94 | |||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | |||
| 99 | |||
| 100 | static void suhosin_op_array_dtor(zend_op_array *op_array) | ||
| 101 | { | ||
| 102 | if (suhosin_zend_extension_entry.resource_number != -1) { | ||
| 103 | op_array->reserved[suhosin_zend_extension_entry.resource_number] = NULL; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | /* Stealth Mode functions */ | ||
| 108 | |||
| 109 | static void stealth_op_array_ctor(zend_op_array *op_array) | ||
| 110 | { | ||
| 111 | if (orig_op_array_ctor != NULL) { | ||
| 112 | orig_op_array_ctor(op_array); | ||
| 113 | } | ||
| 114 | suhosin_op_array_ctor(op_array); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void stealth_op_array_dtor(zend_op_array *op_array) | ||
| 118 | { | ||
| 119 | if (orig_op_array_dtor != NULL) { | ||
| 120 | orig_op_array_dtor(op_array); | ||
| 121 | } | ||
| 122 | suhosin_op_array_dtor(op_array); | ||
| 123 | } | ||
| 124 | |||
| 125 | static int stealth_module_startup(zend_extension *extension) | ||
| 126 | { | ||
| 127 | int r = orig_module_startup == NULL ? SUCCESS : orig_module_startup(extension); | ||
| 128 | suhosin_module_startup(extension); | ||
| 129 | return r; | ||
| 130 | } | ||
| 131 | |||
| 132 | static void stealth_module_shutdown(zend_extension *extension) | ||
| 133 | { | ||
| 134 | if (orig_module_shutdown != NULL) { | ||
| 135 | orig_module_shutdown(extension); | ||
| 136 | } | ||
| 137 | suhosin_shutdown(extension); | ||
| 138 | } | ||
| 139 | |||
| 140 | |||
| 141 | static int suhosin_module_startup(zend_extension *extension) | ||
| 142 | { | ||
| 143 | zend_module_entry *module_entry_ptr; | ||
| 144 | int resid; | ||
| 145 | TSRMLS_FETCH(); | ||
| 146 | |||
| 147 | /* zend_register_module(&suhosin_module_entry TSRMLS_CC); */ | ||
| 148 | |||
| 149 | if (zend_hash_find(&module_registry, "suhosin", sizeof("suhosin"), (void **)&module_entry_ptr)==SUCCESS) { | ||
| 150 | |||
| 151 | if (extension) { | ||
| 152 | extension->handle = module_entry_ptr->handle; | ||
| 153 | } else { | ||
| 154 | zend_extension ext; | ||
| 155 | ext = suhosin_zend_extension_entry; | ||
| 156 | ext.handle = module_entry_ptr->handle; | ||
| 157 | /* | ||
| 158 | zend_llist_add_element(&zend_extensions, &ext); | ||
| 159 | extension = zend_llist_get_last(&zend_extensions); | ||
| 160 | */ | ||
| 161 | extension = &suhosin_zend_extension_entry; | ||
| 162 | } | ||
| 163 | module_entry_ptr->handle = NULL; | ||
| 164 | |||
| 165 | } else { | ||
| 166 | return FAILURE; | ||
| 167 | } | ||
| 168 | |||
| 169 | |||
| 170 | |||
| 171 | if (SUHOSIN_G(apc_bug_workaround)) { | ||
| 172 | resid = zend_get_resource_handle(extension); | ||
| 173 | } | ||
| 174 | resid = zend_get_resource_handle(extension); | ||
| 175 | suhosin_zend_extension_entry.resource_number = resid; | ||
| 176 | |||
| 177 | suhosin_hook_treat_data(); | ||
| 178 | suhosin_hook_post_handlers(TSRMLS_C); | ||
| 179 | suhosin_aes_gentables(); | ||
| 180 | suhosin_hook_register_server_variables(); | ||
| 181 | suhosin_hook_header_handler(); | ||
| 182 | suhosin_hook_execute(TSRMLS_C); | ||
| 183 | suhosin_hook_session(TSRMLS_C); | ||
| 184 | |||
| 185 | |||
| 186 | return SUCCESS; | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | static void suhosin_shutdown(zend_extension *extension) | ||
| 191 | { | ||
| 192 | suhosin_unhook_execute(); | ||
| 193 | suhosin_unhook_header_handler(); | ||
| 194 | |||
| 195 | if (ze != NULL) { | ||
| 196 | ze->startup = orig_module_startup; | ||
| 197 | ze->shutdown = orig_module_shutdown; | ||
| 198 | ze->op_array_ctor = orig_op_array_ctor; | ||
| 199 | ze->op_array_dtor = orig_op_array_dtor; | ||
| 200 | } | ||
| 201 | |||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | static int suhosin_startup_wrapper(zend_extension *ext) | ||
| 206 | { | ||
| 207 | int res; | ||
| 208 | zend_extension *ex = &suhosin_zend_extension_entry; | ||
| 209 | char *new_info; | ||
| 210 | int new_info_length; | ||
| 211 | TSRMLS_FETCH(); | ||
| 212 | |||
| 213 | /* Ugly but working hack */ | ||
| 214 | new_info_length = sizeof("%s\n with %s v%s, %s, by %s\n") | ||
| 215 | + strlen(ext->author) | ||
| 216 | + strlen(ex->name) | ||
| 217 | + strlen(ex->version) | ||
| 218 | + strlen(ex->copyright) | ||
| 219 | + strlen(ex->author); | ||
| 220 | |||
| 221 | new_info = (char *) malloc(new_info_length+1); | ||
| 222 | sprintf(new_info, "%s\n with %s v%s, %s, by %s", ext->author, ex->name, ex->version, ex->copyright, ex->author); | ||
| 223 | ext->author = new_info; | ||
| 224 | |||
| 225 | ze->startup = old_startup; | ||
| 226 | |||
| 227 | /* Stealth Mode */ | ||
| 228 | orig_module_startup = ze->startup; | ||
| 229 | orig_module_shutdown = ze->shutdown; | ||
| 230 | orig_op_array_ctor = ze->op_array_ctor; | ||
| 231 | orig_op_array_dtor = ze->op_array_dtor; | ||
| 232 | |||
| 233 | /*if (SUHOSIN_G(stealth) != 0) {*/ | ||
| 234 | ze->startup = stealth_module_startup; | ||
| 235 | ze->shutdown = stealth_module_shutdown; | ||
| 236 | ze->op_array_ctor = stealth_op_array_ctor; | ||
| 237 | ze->op_array_dtor = stealth_op_array_dtor; | ||
| 238 | /*}*/ | ||
| 239 | |||
| 240 | res = old_startup(ext); | ||
| 241 | |||
| 242 | /* ex->name = NULL; | ||
| 243 | ex->author = NULL; | ||
| 244 | ex->copyright = NULL; | ||
| 245 | ex->version = NULL;*/ | ||
| 246 | |||
| 247 | /*zend_extensions.head=NULL;*/ | ||
| 248 | |||
| 249 | suhosin_module_startup(NULL); | ||
| 250 | |||
| 251 | |||
| 252 | return res; | ||
| 253 | } | ||
| 254 | |||
| 255 | /*static zend_extension_version_info extension_version_info = { ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG };*/ | ||
| 256 | |||
| 257 | #define PERDIR_CHECK(upper, lower) \ | ||
| 258 | if (!SUHOSIN_G(lower ## _perdir) && stage == ZEND_INI_STAGE_HTACCESS) { \ | ||
| 259 | return FAILURE; \ | ||
| 260 | } | ||
| 261 | |||
| 262 | #define LOG_PERDIR_CHECK() PERDIR_CHECK(LOG, log) | ||
| 263 | #define EXEC_PERDIR_CHECK() PERDIR_CHECK(EXEC, exec) | ||
| 264 | #define MISC_PERDIR_CHECK() PERDIR_CHECK(MISC, misc) | ||
| 265 | #define GET_PERDIR_CHECK() PERDIR_CHECK(GET, get) | ||
| 266 | #define POST_PERDIR_CHECK() PERDIR_CHECK(POST, post) | ||
| 267 | #define COOKIE_PERDIR_CHECK() PERDIR_CHECK(COOKIE, cookie) | ||
| 268 | #define REQUEST_PERDIR_CHECK() PERDIR_CHECK(REQUEST, request) | ||
| 269 | #define UPLOAD_PERDIR_CHECK() PERDIR_CHECK(UPLOAD, upload) | ||
| 270 | #define SQL_PERDIR_CHECK() PERDIR_CHECK(SQL, sql) | ||
| 271 | |||
| 272 | #define ZEND_INI_MH_PASSTHRU entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC | ||
| 273 | |||
| 274 | |||
| 275 | static ZEND_INI_MH(OnUpdateSuhosin_perdir) | ||
| 276 | { | ||
| 277 | char *tmp; | ||
| 278 | |||
| 279 | if (SUHOSIN_G(perdir)) { | ||
| 280 | pefree(SUHOSIN_G(perdir), 1); | ||
| 281 | } | ||
| 282 | SUHOSIN_G(perdir) = NULL; | ||
| 283 | |||
| 284 | /* Initialize the perdir flags */ | ||
| 285 | SUHOSIN_G(log_perdir) = 0; | ||
| 286 | SUHOSIN_G(exec_perdir) = 0; | ||
| 287 | SUHOSIN_G(get_perdir) = 0; | ||
| 288 | SUHOSIN_G(cookie_perdir) = 0; | ||
| 289 | SUHOSIN_G(post_perdir) = 0; | ||
| 290 | SUHOSIN_G(request_perdir) = 0; | ||
| 291 | SUHOSIN_G(sql_perdir) = 0; | ||
| 292 | SUHOSIN_G(upload_perdir) = 0; | ||
| 293 | SUHOSIN_G(misc_perdir) = 0; | ||
| 294 | |||
| 295 | if (new_value == NULL) { | ||
| 296 | return SUCCESS; | ||
| 297 | } | ||
| 298 | |||
| 299 | tmp = SUHOSIN_G(perdir) = pestrdup(new_value,1); | ||
| 300 | |||
| 301 | /* trim the whitespace */ | ||
| 302 | while (isspace(*tmp)) tmp++; | ||
| 303 | |||
| 304 | /* should we deactivate perdir completely? */ | ||
| 305 | if (*tmp == 0 || *tmp == '0') { | ||
| 306 | return SUCCESS; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* no deactivation so check the flags */ | ||
| 310 | while (*tmp) { | ||
| 311 | switch (*tmp) { | ||
| 312 | case 'l': | ||
| 313 | case 'L': | ||
| 314 | SUHOSIN_G(log_perdir) = 1; | ||
| 315 | break; | ||
| 316 | case 'e': | ||
| 317 | case 'E': | ||
| 318 | SUHOSIN_G(exec_perdir) = 1; | ||
| 319 | break; | ||
| 320 | case 'g': | ||
| 321 | case 'G': | ||
| 322 | SUHOSIN_G(get_perdir) = 1; | ||
| 323 | break; | ||
| 324 | case 'c': | ||
| 325 | case 'C': | ||
| 326 | SUHOSIN_G(cookie_perdir) = 1; | ||
| 327 | break; | ||
| 328 | case 'p': | ||
| 329 | case 'P': | ||
| 330 | SUHOSIN_G(post_perdir) = 1; | ||
| 331 | break; | ||
| 332 | case 'r': | ||
| 333 | case 'R': | ||
| 334 | SUHOSIN_G(request_perdir) = 1; | ||
| 335 | break; | ||
| 336 | case 's': | ||
| 337 | case 'S': | ||
| 338 | SUHOSIN_G(sql_perdir) = 1; | ||
| 339 | break; | ||
| 340 | case 'u': | ||
| 341 | case 'U': | ||
| 342 | SUHOSIN_G(upload_perdir) = 1; | ||
| 343 | break; | ||
| 344 | case 'm': | ||
| 345 | case 'M': | ||
| 346 | SUHOSIN_G(misc_perdir) = 1; | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | tmp++; | ||
| 350 | } | ||
| 351 | return SUCCESS; | ||
| 352 | } | ||
| 353 | |||
| 354 | #define dohandler(handler, name, upper, lower) \ | ||
| 355 | static ZEND_INI_MH(OnUpdate ## name ## handler) \ | ||
| 356 | { \ | ||
| 357 | PERDIR_CHECK(upper, lower) \ | ||
| 358 | return OnUpdate ## handler (ZEND_INI_MH_PASSTHRU); \ | ||
| 359 | } \ | ||
| 360 | |||
| 361 | #define dohandlers(name, upper, lower) \ | ||
| 362 | dohandler(Bool, name, upper, lower) \ | ||
| 363 | dohandler(String, name, upper, lower) \ | ||
| 364 | dohandler(Long, name, upper, lower) \ | ||
| 365 | |||
| 366 | dohandlers(Log, LOG, log) | ||
| 367 | dohandlers(Exec, EXEC, exec) | ||
| 368 | dohandlers(Misc, MISC, misc) | ||
| 369 | dohandlers(Get, GET, get) | ||
| 370 | dohandlers(Post, POST, post) | ||
| 371 | dohandlers(Cookie, COOKIE, cookie) | ||
| 372 | dohandlers(Request, REQUEST, request) | ||
| 373 | dohandlers(Upload, UPLOAD, upload) | ||
| 374 | dohandlers(SQL, SQL, sql) | ||
| 375 | |||
| 376 | static ZEND_INI_MH(OnUpdateSuhosin_log_syslog) | ||
| 377 | { | ||
| 378 | LOG_PERDIR_CHECK() | ||
| 379 | if (!new_value) { | ||
| 380 | SUHOSIN_G(log_syslog) = (S_ALL & ~S_SQL) | S_MEMORY; | ||
| 381 | } else { | ||
| 382 | SUHOSIN_G(log_syslog) = atoi(new_value) | S_MEMORY; | ||
| 383 | } | ||
| 384 | return SUCCESS; | ||
| 385 | } | ||
| 386 | static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_facility) | ||
| 387 | { | ||
| 388 | LOG_PERDIR_CHECK() | ||
| 389 | if (!new_value) { | ||
| 390 | SUHOSIN_G(log_syslog_facility) = LOG_USER; | ||
| 391 | } else { | ||
| 392 | SUHOSIN_G(log_syslog_facility) = atoi(new_value); | ||
| 393 | } | ||
| 394 | return SUCCESS; | ||
| 395 | } | ||
| 396 | static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_priority) | ||
| 397 | { | ||
| 398 | LOG_PERDIR_CHECK() | ||
| 399 | if (!new_value) { | ||
| 400 | SUHOSIN_G(log_syslog_priority) = LOG_ALERT; | ||
| 401 | } else { | ||
| 402 | SUHOSIN_G(log_syslog_priority) = atoi(new_value); | ||
| 403 | } | ||
| 404 | return SUCCESS; | ||
| 405 | } | ||
| 406 | static ZEND_INI_MH(OnUpdateSuhosin_log_sapi) | ||
| 407 | { | ||
| 408 | LOG_PERDIR_CHECK() | ||
| 409 | if (!new_value) { | ||
| 410 | SUHOSIN_G(log_sapi) = (S_ALL & ~S_SQL); | ||
| 411 | } else { | ||
| 412 | SUHOSIN_G(log_sapi) = atoi(new_value); | ||
| 413 | } | ||
| 414 | return SUCCESS; | ||
| 415 | } | ||
| 416 | static ZEND_INI_MH(OnUpdateSuhosin_log_script) | ||
| 417 | { | ||
| 418 | LOG_PERDIR_CHECK() | ||
| 419 | if (!new_value) { | ||
| 420 | SUHOSIN_G(log_script) = S_ALL & ~S_MEMORY; | ||
| 421 | } else { | ||
| 422 | SUHOSIN_G(log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL); | ||
| 423 | } | ||
| 424 | return SUCCESS; | ||
| 425 | } | ||
| 426 | static ZEND_INI_MH(OnUpdateSuhosin_log_scriptname) | ||
| 427 | { | ||
| 428 | LOG_PERDIR_CHECK() | ||
| 429 | if (SUHOSIN_G(log_scriptname)) { | ||
| 430 | pefree(SUHOSIN_G(log_scriptname),1); | ||
| 431 | } | ||
| 432 | SUHOSIN_G(log_scriptname) = NULL; | ||
| 433 | if (new_value) { | ||
| 434 | SUHOSIN_G(log_scriptname) = pestrdup(new_value,1); | ||
| 435 | } | ||
| 436 | return SUCCESS; | ||
| 437 | } | ||
| 438 | static ZEND_INI_MH(OnUpdateSuhosin_log_phpscript) | ||
| 439 | { | ||
| 440 | LOG_PERDIR_CHECK() | ||
| 441 | if (!new_value) { | ||
| 442 | SUHOSIN_G(log_phpscript) = S_ALL & ~S_MEMORY; | ||
| 443 | } else { | ||
| 444 | SUHOSIN_G(log_phpscript) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL); | ||
| 445 | } | ||
| 446 | return SUCCESS; | ||
| 447 | } | ||
| 448 | static ZEND_INI_MH(OnUpdateSuhosin_log_file) | ||
| 449 | { | ||
| 450 | LOG_PERDIR_CHECK() | ||
| 451 | if (!new_value) { | ||
| 452 | SUHOSIN_G(log_file) = S_ALL & ~S_MEMORY; | ||
| 453 | } else { | ||
| 454 | SUHOSIN_G(log_file) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL); | ||
| 455 | } | ||
| 456 | return SUCCESS; | ||
| 457 | } | ||
| 458 | |||
| 459 | static void parse_list(HashTable **ht, char *list, zend_bool lc) | ||
| 460 | { | ||
| 461 | char *s = NULL, *e, *val; | ||
| 462 | unsigned long dummy = 1; | ||
| 463 | |||
| 464 | if (list == NULL) { | ||
| 465 | list_destroy: | ||
| 466 | if (*ht) { | ||
| 467 | zend_hash_destroy(*ht); | ||
| 468 | pefree(*ht, 1); | ||
| 469 | } | ||
| 470 | *ht = NULL; | ||
| 471 | return; | ||
| 472 | } | ||
| 473 | while (*list == ' ' || *list == '\t') list++; | ||
| 474 | if (*list == 0) { | ||
| 475 | goto list_destroy; | ||
| 476 | } | ||
| 477 | |||
| 478 | *ht = pemalloc(sizeof(HashTable), 1); | ||
| 479 | zend_hash_init(*ht, 5, NULL, NULL, 1); | ||
| 480 | |||
| 481 | if (lc) { | ||
| 482 | val = suhosin_str_tolower_dup(list, strlen(list)); | ||
| 483 | } else { | ||
| 484 | val = estrndup(list, strlen(list)); | ||
| 485 | } | ||
| 486 | e = val; | ||
| 487 | |||
| 488 | while (*e) { | ||
| 489 | switch (*e) { | ||
| 490 | case ' ': | ||
| 491 | case ',': | ||
| 492 | if (s) { | ||
| 493 | *e = '\0'; | ||
| 494 | zend_hash_add(*ht, s, e-s+1, &dummy, sizeof(unsigned long), NULL); | ||
| 495 | s = NULL; | ||
| 496 | } | ||
| 497 | break; | ||
| 498 | default: | ||
| 499 | if (!s) { | ||
| 500 | s = e; | ||
| 501 | } | ||
| 502 | break; | ||
| 503 | } | ||
| 504 | e++; | ||
| 505 | } | ||
| 506 | if (s) { | ||
| 507 | zend_hash_add(*ht, s, e-s+1, &dummy, sizeof(unsigned long), NULL); | ||
| 508 | } | ||
| 509 | efree(val); | ||
| 510 | |||
| 511 | } | ||
| 512 | |||
| 513 | static ZEND_INI_MH(OnUpdate_include_blacklist) | ||
| 514 | { | ||
| 515 | EXEC_PERDIR_CHECK() | ||
| 516 | parse_list(&SUHOSIN_G(include_blacklist), new_value, 1); | ||
| 517 | return SUCCESS; | ||
| 518 | } | ||
| 519 | |||
| 520 | static ZEND_INI_MH(OnUpdate_include_whitelist) | ||
| 521 | { | ||
| 522 | EXEC_PERDIR_CHECK() | ||
| 523 | parse_list(&SUHOSIN_G(include_whitelist), new_value, 1); | ||
| 524 | return SUCCESS; | ||
| 525 | } | ||
| 526 | |||
| 527 | static ZEND_INI_MH(OnUpdate_func_blacklist) | ||
| 528 | { | ||
| 529 | EXEC_PERDIR_CHECK() | ||
| 530 | parse_list(&SUHOSIN_G(func_blacklist), new_value, 1); | ||
| 531 | return SUCCESS; | ||
| 532 | } | ||
| 533 | |||
| 534 | static ZEND_INI_MH(OnUpdate_func_whitelist) | ||
| 535 | { | ||
| 536 | EXEC_PERDIR_CHECK() | ||
| 537 | parse_list(&SUHOSIN_G(func_whitelist), new_value, 1); | ||
| 538 | return SUCCESS; | ||
| 539 | } | ||
| 540 | |||
| 541 | static ZEND_INI_MH(OnUpdate_eval_blacklist) | ||
| 542 | { | ||
| 543 | EXEC_PERDIR_CHECK() | ||
| 544 | parse_list(&SUHOSIN_G(eval_blacklist), new_value, 1); | ||
| 545 | return SUCCESS; | ||
| 546 | } | ||
| 547 | |||
| 548 | static ZEND_INI_MH(OnUpdate_eval_whitelist) | ||
| 549 | { | ||
| 550 | EXEC_PERDIR_CHECK() | ||
| 551 | parse_list(&SUHOSIN_G(eval_whitelist), new_value, 1); | ||
| 552 | return SUCCESS; | ||
| 553 | } | ||
| 554 | |||
| 555 | |||
| 556 | static ZEND_INI_MH(OnUpdate_cookie_cryptlist) | ||
| 557 | { | ||
| 558 | parse_list(&SUHOSIN_G(cookie_cryptlist), new_value, 0); | ||
| 559 | return SUCCESS; | ||
| 560 | } | ||
| 561 | |||
| 562 | static ZEND_INI_MH(OnUpdate_cookie_plainlist) | ||
| 563 | { | ||
| 564 | parse_list(&SUHOSIN_G(cookie_plainlist), new_value, 0); | ||
| 565 | return SUCCESS; | ||
| 566 | } | ||
| 567 | |||
| 568 | /* {{{ proto void suhosin_register_cookie_variable(char *var, zval *val, zval *track_vars_array TSRMLS_DC) | ||
| 569 | Registers a cookie in the RAW cookie array */ | ||
| 570 | static void suhosin_register_cookie_variable(char *var, zval *val, zval *track_vars_array TSRMLS_DC) | ||
| 571 | { | ||
| 572 | char *p = NULL; | ||
| 573 | char *ip; /* index pointer */ | ||
| 574 | char *index, *escaped_index = NULL; | ||
| 575 | int var_len, index_len; | ||
| 576 | zval *gpc_element, **gpc_element_p; | ||
| 577 | zend_bool is_array = 0; | ||
| 578 | HashTable *symtable1 = NULL; | ||
| 579 | |||
| 580 | assert(var != NULL); | ||
| 581 | |||
| 582 | symtable1 = Z_ARRVAL_P(track_vars_array); | ||
| 583 | |||
| 584 | /* | ||
| 585 | * Prepare variable name | ||
| 586 | */ | ||
| 587 | |||
| 588 | /* ignore leading spaces in the variable name */ | ||
| 589 | while (*var && *var==' ') { | ||
| 590 | var++; | ||
| 591 | } | ||
| 592 | |||
| 593 | /* ensure that we don't have spaces or dots in the variable name (not binary safe) */ | ||
| 594 | for (p = var; *p; p++) { | ||
| 595 | if (*p == ' ' || *p == '.') { | ||
| 596 | *p='_'; | ||
| 597 | } else if (*p == '[') { | ||
| 598 | is_array = 1; | ||
| 599 | ip = p; | ||
| 600 | *p = 0; | ||
| 601 | break; | ||
| 602 | } | ||
| 603 | } | ||
| 604 | var_len = p - var; | ||
| 605 | |||
| 606 | if (var_len==0) { /* empty variable name, or variable name with a space in it */ | ||
| 607 | zval_dtor(val); | ||
| 608 | return; | ||
| 609 | } | ||
| 610 | |||
| 611 | index = var; | ||
| 612 | index_len = var_len; | ||
| 613 | |||
| 614 | if (is_array) { | ||
| 615 | while (1) { | ||
| 616 | char *index_s; | ||
| 617 | int new_idx_len = 0; | ||
| 618 | |||
| 619 | ip++; | ||
| 620 | index_s = ip; | ||
| 621 | if (isspace(*ip)) { | ||
| 622 | ip++; | ||
| 623 | } | ||
| 624 | if (*ip==']') { | ||
| 625 | index_s = NULL; | ||
| 626 | } else { | ||
| 627 | ip = strchr(ip, ']'); | ||
| 628 | if (!ip) { | ||
| 629 | /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */ | ||
| 630 | *(index_s - 1) = '_'; | ||
| 631 | |||
| 632 | index_len = var_len = 0; | ||
| 633 | if (index) { | ||
| 634 | index_len = var_len = strlen(index); | ||
| 635 | } | ||
| 636 | goto plain_var; | ||
| 637 | return; | ||
| 638 | } | ||
| 639 | *ip = 0; | ||
| 640 | new_idx_len = strlen(index_s); | ||
| 641 | } | ||
| 642 | |||
| 643 | if (!index) { | ||
| 644 | MAKE_STD_ZVAL(gpc_element); | ||
| 645 | array_init(gpc_element); | ||
| 646 | zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); | ||
| 647 | } else { | ||
| 648 | if (PG(magic_quotes_gpc) && (index != var)) { | ||
| 649 | /* no need to addslashes() the index if it's the main variable name */ | ||
| 650 | escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC); | ||
| 651 | } else { | ||
| 652 | escaped_index = index; | ||
| 653 | } | ||
| 654 | if (zend_symtable_find(symtable1, escaped_index, index_len + 1, (void **) &gpc_element_p) == FAILURE | ||
| 655 | || Z_TYPE_PP(gpc_element_p) != IS_ARRAY) { | ||
| 656 | MAKE_STD_ZVAL(gpc_element); | ||
| 657 | array_init(gpc_element); | ||
| 658 | zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); | ||
| 659 | } | ||
| 660 | if (index != escaped_index) { | ||
| 661 | efree(escaped_index); | ||
| 662 | } | ||
| 663 | } | ||
| 664 | symtable1 = Z_ARRVAL_PP(gpc_element_p); | ||
| 665 | /* ip pointed to the '[' character, now obtain the key */ | ||
| 666 | index = index_s; | ||
| 667 | index_len = new_idx_len; | ||
| 668 | |||
| 669 | ip++; | ||
| 670 | if (*ip == '[') { | ||
| 671 | is_array = 1; | ||
| 672 | *ip = 0; | ||
| 673 | } else { | ||
| 674 | goto plain_var; | ||
| 675 | } | ||
| 676 | } | ||
| 677 | } else { | ||
| 678 | plain_var: | ||
| 679 | MAKE_STD_ZVAL(gpc_element); | ||
| 680 | gpc_element->value = val->value; | ||
| 681 | Z_TYPE_P(gpc_element) = Z_TYPE_P(val); | ||
| 682 | if (!index) { | ||
| 683 | zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); | ||
| 684 | } else { | ||
| 685 | if (PG(magic_quotes_gpc)) { | ||
| 686 | escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC); | ||
| 687 | } else { | ||
| 688 | escaped_index = index; | ||
| 689 | } | ||
| 690 | /* | ||
| 691 | * According to rfc2965, more specific paths are listed above the less specific ones. | ||
| 692 | * If we encounter a duplicate cookie name, we should skip it, since it is not possible | ||
| 693 | * to have the same (plain text) cookie name for the same path and we should not overwrite | ||
| 694 | * more specific cookies with the less specific ones. | ||
| 695 | */ | ||
| 696 | if (zend_symtable_exists(symtable1, escaped_index, index_len + 1)) { | ||
| 697 | zval_ptr_dtor(&gpc_element); | ||
| 698 | } else { | ||
| 699 | zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p); | ||
| 700 | } | ||
| 701 | if (escaped_index != index) { | ||
| 702 | efree(escaped_index); | ||
| 703 | } | ||
| 704 | } | ||
| 705 | } | ||
| 706 | } | ||
| 707 | /* }}} */ | ||
| 708 | |||
| 709 | static void suhosin_register_cookie_variable_safe(char *var, char *strval, int str_len, zval *track_vars_array TSRMLS_DC) | ||
| 710 | { | ||
| 711 | zval new_entry; | ||
| 712 | assert(strval != NULL); | ||
| 713 | |||
| 714 | /* Prepare value */ | ||
| 715 | Z_STRLEN(new_entry) = str_len; | ||
| 716 | if (PG(magic_quotes_gpc)) { | ||
| 717 | Z_STRVAL(new_entry) = php_addslashes(strval, Z_STRLEN(new_entry), &Z_STRLEN(new_entry), 0 TSRMLS_CC); | ||
| 718 | } else { | ||
| 719 | Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry)); | ||
| 720 | } | ||
| 721 | Z_TYPE(new_entry) = IS_STRING; | ||
| 722 | |||
| 723 | suhosin_register_cookie_variable(var, &new_entry, track_vars_array TSRMLS_CC); | ||
| 724 | } | ||
| 725 | |||
| 726 | |||
| 727 | /* {{{ proto string suhosin_encrypt_cookie(string name, string value) | ||
| 728 | Encrypts a cookie value according to current cookie encrpytion setting */ | ||
| 729 | static PHP_FUNCTION(suhosin_encrypt_cookie) | ||
| 730 | { | ||
| 731 | char *name, *value; | ||
| 732 | int name_len, value_len; | ||
| 733 | char cryptkey[33]; | ||
| 734 | |||
| 735 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) { | ||
| 736 | return; | ||
| 737 | } | ||
| 738 | |||
| 739 | if (!SUHOSIN_G(cookie_encrypt)) { | ||
| 740 | return_plain: | ||
| 741 | RETURN_STRINGL(value, value_len, 1); | ||
| 742 | } | ||
| 743 | |||
| 744 | if (SUHOSIN_G(cookie_plainlist)) { | ||
| 745 | if (zend_hash_exists(SUHOSIN_G(cookie_plainlist), name, name_len+1)) { | ||
| 746 | goto return_plain; | ||
| 747 | } | ||
| 748 | } else if (SUHOSIN_G(cookie_cryptlist)) { | ||
| 749 | if (!zend_hash_exists(SUHOSIN_G(cookie_cryptlist), name, name_len+1)) { | ||
| 750 | goto return_plain; | ||
| 751 | } | ||
| 752 | } | ||
| 753 | |||
| 754 | suhosin_generate_key(SUHOSIN_G(cookie_cryptkey), SUHOSIN_G(cookie_cryptua), SUHOSIN_G(cookie_cryptdocroot), SUHOSIN_G(cookie_cryptraddr), (char *)&cryptkey TSRMLS_CC); | ||
| 755 | value = suhosin_encrypt_string(value, value_len, name, name_len, (char *)&cryptkey TSRMLS_CC); | ||
| 756 | |||
| 757 | RETVAL_STRING(value, 0); | ||
| 758 | } | ||
| 759 | /* }}} */ | ||
| 760 | |||
| 761 | /* {{{ proto mixed suhosin_get_raw_cookies() | ||
| 762 | Returns an array containing the raw cookie values */ | ||
| 763 | static PHP_FUNCTION(suhosin_get_raw_cookies) | ||
| 764 | { | ||
| 765 | char *var, *val, *res; | ||
| 766 | zval *array_ptr = return_value; | ||
| 767 | char *strtok_buf = NULL; | ||
| 768 | int val_len; | ||
| 769 | |||
| 770 | array_init(array_ptr); | ||
| 771 | |||
| 772 | if (SUHOSIN_G(raw_cookie)) { | ||
| 773 | res = estrdup(SUHOSIN_G(raw_cookie)); | ||
| 774 | } else { | ||
| 775 | return; | ||
| 776 | } | ||
| 777 | |||
| 778 | var = php_strtok_r(res, ";", &strtok_buf); | ||
| 779 | |||
| 780 | while (var) { | ||
| 781 | val = strchr(var, '='); | ||
| 782 | if (val) { /* have a value */ | ||
| 783 | *val++ = '\0'; | ||
| 784 | php_url_decode(var, strlen(var)); | ||
| 785 | val_len = php_url_decode(val, strlen(val)); | ||
| 786 | suhosin_register_cookie_variable_safe(var, val, val_len, array_ptr TSRMLS_CC); | ||
| 787 | } else { | ||
| 788 | php_url_decode(var, strlen(var)); | ||
| 789 | val_len = 0; | ||
| 790 | val = ""; | ||
| 791 | suhosin_register_cookie_variable_safe(var, "", 0, array_ptr TSRMLS_CC); | ||
| 792 | } | ||
| 793 | var = php_strtok_r(NULL, ";", &strtok_buf); | ||
| 794 | } | ||
| 795 | |||
| 796 | efree(res); | ||
| 797 | } | ||
| 798 | /* }}} */ | ||
| 799 | |||
| 800 | |||
| 801 | |||
| 802 | /* {{{ suhosin_functions[] | ||
| 803 | */ | ||
| 804 | zend_function_entry suhosin_functions[] = { | ||
| 805 | PHP_NAMED_FE(suhosin_encrypt_cookie, PHP_FN(suhosin_encrypt_cookie), NULL) | ||
| 806 | PHP_NAMED_FE(suhosin_get_raw_cookies, PHP_FN(suhosin_get_raw_cookies), NULL) | ||
| 807 | {NULL, NULL, NULL} /* Must be the last line in suhosin_functions[] */ | ||
| 808 | }; | ||
| 809 | /* }}} */ | ||
| 810 | |||
| 811 | /* {{{ suhosin_module_entry | ||
| 812 | */ | ||
| 813 | zend_module_entry suhosin_module_entry = { | ||
| 814 | #if ZEND_MODULE_API_NO >= 20010901 | ||
| 815 | STANDARD_MODULE_HEADER, | ||
| 816 | #endif | ||
| 817 | "suhosin", | ||
| 818 | suhosin_functions, | ||
| 819 | PHP_MINIT(suhosin), | ||
| 820 | PHP_MSHUTDOWN(suhosin), | ||
| 821 | PHP_RINIT(suhosin), | ||
| 822 | PHP_RSHUTDOWN(suhosin), | ||
| 823 | PHP_MINFO(suhosin), | ||
| 824 | #if ZEND_MODULE_API_NO >= 20010901 | ||
| 825 | SUHOSIN_EXT_VERSION, /* Replace with version number for your extension */ | ||
| 826 | #endif | ||
| 827 | STANDARD_MODULE_PROPERTIES | ||
| 828 | }; | ||
| 829 | /* }}} */ | ||
| 830 | |||
| 831 | #ifdef COMPILE_DL_SUHOSIN | ||
| 832 | ZEND_GET_MODULE(suhosin) | ||
| 833 | #endif | ||
| 834 | |||
| 835 | /* {{{ PHP_INI | ||
| 836 | */ | ||
| 837 | static zend_ini_entry shared_ini_entries[] = { | ||
| 838 | ZEND_INI_ENTRY("suhosin.log.syslog", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_syslog) | ||
| 839 | ZEND_INI_ENTRY("suhosin.log.syslog.facility", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_syslog_facility) | ||
| 840 | ZEND_INI_ENTRY("suhosin.log.syslog.priority", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_syslog_priority) | ||
| 841 | ZEND_INI_ENTRY("suhosin.log.sapi", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_sapi) | ||
| 842 | ZEND_INI_ENTRY("suhosin.log.script", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_script) | ||
| 843 | ZEND_INI_ENTRY("suhosin.log.script.name", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_scriptname) | ||
| 844 | STD_ZEND_INI_BOOLEAN("suhosin.log.use-x-forwarded-for", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLogBool, log_use_x_forwarded_for, zend_suhosin_globals, suhosin_globals) | ||
| 845 | ZEND_INI_ENTRY("suhosin.log.phpscript", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_phpscript) | ||
| 846 | STD_ZEND_INI_ENTRY("suhosin.log.phpscript.name", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLogString, log_phpscriptname, zend_suhosin_globals, suhosin_globals) | ||
| 847 | ZEND_INI_ENTRY("suhosin.log.file", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSuhosin_log_file) | ||
| 848 | STD_ZEND_INI_ENTRY("suhosin.log.file.name", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLogString, log_filename, zend_suhosin_globals, suhosin_globals) | ||
| 849 | STD_ZEND_INI_BOOLEAN("suhosin.log.phpscript.is_safe", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLogBool, log_phpscript_is_safe, zend_suhosin_globals, suhosin_globals) | ||
| 850 | ZEND_INI_END() | ||
| 851 | |||
| 852 | PHP_INI_BEGIN() | ||
| 853 | ZEND_INI_ENTRY("suhosin.perdir", "0", ZEND_INI_SYSTEM, OnUpdateSuhosin_perdir) | ||
| 854 | STD_ZEND_INI_ENTRY("suhosin.executor.include.max_traversal", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateExecLong, executor_include_max_traversal, zend_suhosin_globals, suhosin_globals) | ||
| 855 | ZEND_INI_ENTRY("suhosin.executor.include.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_include_whitelist) | ||
| 856 | ZEND_INI_ENTRY("suhosin.executor.include.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_include_blacklist) | ||
| 857 | STD_ZEND_INI_BOOLEAN("suhosin.executor.include.allow_writable_files", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateExecBool, executor_include_allow_writable_files, zend_suhosin_globals, suhosin_globals) | ||
| 858 | ZEND_INI_ENTRY("suhosin.executor.eval.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_eval_whitelist) | ||
| 859 | ZEND_INI_ENTRY("suhosin.executor.eval.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_eval_blacklist) | ||
| 860 | ZEND_INI_ENTRY("suhosin.executor.func.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_func_whitelist) | ||
| 861 | ZEND_INI_ENTRY("suhosin.executor.func.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_func_blacklist) | ||
| 862 | STD_ZEND_INI_BOOLEAN("suhosin.executor.disable_eval", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateExecBool, executor_disable_eval, zend_suhosin_globals, suhosin_globals) | ||
| 863 | STD_ZEND_INI_BOOLEAN("suhosin.executor.disable_emodifier", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateExecBool, executor_disable_emod, zend_suhosin_globals, suhosin_globals) | ||
| 864 | |||
| 865 | STD_ZEND_INI_BOOLEAN("suhosin.executor.allow_symlink", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateExecBool, executor_allow_symlink, zend_suhosin_globals, suhosin_globals) | ||
| 866 | STD_ZEND_INI_ENTRY("suhosin.executor.max_depth", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateExecLong, max_execution_depth, zend_suhosin_globals, suhosin_globals) | ||
| 867 | |||
| 868 | |||
| 869 | STD_ZEND_INI_BOOLEAN("suhosin.multiheader", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateMiscBool, allow_multiheader, zend_suhosin_globals, suhosin_globals) | ||
| 870 | STD_ZEND_INI_ENTRY("suhosin.mail.protect", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateMiscLong, mailprotect, zend_suhosin_globals, suhosin_globals) | ||
| 871 | STD_ZEND_INI_ENTRY("suhosin.memory_limit", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateMiscLong, memory_limit, zend_suhosin_globals, suhosin_globals) | ||
| 872 | STD_ZEND_INI_BOOLEAN("suhosin.simulation", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateMiscBool, simulation, zend_suhosin_globals, suhosin_globals) | ||
| 873 | STD_PHP_INI_ENTRY("suhosin.filter.action", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMiscString, filter_action, zend_suhosin_globals, suhosin_globals) | ||
| 874 | |||
| 875 | STD_ZEND_INI_BOOLEAN("suhosin.protectkey", "1", ZEND_INI_SYSTEM, OnUpdateBool, protectkey, zend_suhosin_globals, suhosin_globals) | ||
| 876 | STD_ZEND_INI_BOOLEAN("suhosin.coredump", "0", ZEND_INI_SYSTEM, OnUpdateBool, coredump, zend_suhosin_globals, suhosin_globals) | ||
| 877 | STD_ZEND_INI_BOOLEAN("suhosin.stealth", "1", ZEND_INI_SYSTEM, OnUpdateBool, stealth, zend_suhosin_globals, suhosin_globals) | ||
| 878 | STD_ZEND_INI_BOOLEAN("suhosin.apc_bug_workaround", "0", ZEND_INI_SYSTEM, OnUpdateBool, apc_bug_workaround, zend_suhosin_globals, suhosin_globals) | ||
| 879 | STD_ZEND_INI_BOOLEAN("suhosin.disable.display_errors", "0", ZEND_INI_SYSTEM, OnUpdateBool, disable_display_errors, zend_suhosin_globals, suhosin_globals) | ||
| 880 | |||
| 881 | |||
| 882 | |||
| 883 | STD_PHP_INI_ENTRY("suhosin.request.max_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestLong, max_request_variables, zend_suhosin_globals, suhosin_globals) | ||
| 884 | STD_PHP_INI_ENTRY("suhosin.request.max_varname_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestLong, max_varname_length, zend_suhosin_globals, suhosin_globals) | ||
| 885 | STD_PHP_INI_ENTRY("suhosin.request.max_value_length", "1000000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestLong, max_value_length, zend_suhosin_globals, suhosin_globals) | ||
| 886 | STD_PHP_INI_ENTRY("suhosin.request.max_array_depth", "50", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestLong, max_array_depth, zend_suhosin_globals, suhosin_globals) | ||
| 887 | STD_PHP_INI_ENTRY("suhosin.request.max_totalname_length", "256", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestLong, max_totalname_length, zend_suhosin_globals, suhosin_globals) | ||
| 888 | STD_PHP_INI_ENTRY("suhosin.request.max_array_index_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestLong, max_array_index_length, zend_suhosin_globals, suhosin_globals) | ||
| 889 | STD_PHP_INI_ENTRY("suhosin.request.disallow_nul", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestBool, disallow_nul, zend_suhosin_globals, suhosin_globals) | ||
| 890 | STD_PHP_INI_ENTRY("suhosin.request.disallow_ws", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateRequestBool, disallow_ws, zend_suhosin_globals, suhosin_globals) | ||
| 891 | |||
| 892 | STD_PHP_INI_ENTRY("suhosin.cookie.max_vars", "100", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieLong, max_cookie_vars, zend_suhosin_globals, suhosin_globals) | ||
| 893 | STD_PHP_INI_ENTRY("suhosin.cookie.max_name_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieLong, max_cookie_name_length, zend_suhosin_globals, suhosin_globals) | ||
| 894 | STD_PHP_INI_ENTRY("suhosin.cookie.max_totalname_length", "256", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieLong, max_cookie_totalname_length, zend_suhosin_globals, suhosin_globals) | ||
| 895 | STD_PHP_INI_ENTRY("suhosin.cookie.max_value_length", "10000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieLong, max_cookie_value_length, zend_suhosin_globals, suhosin_globals) | ||
| 896 | STD_PHP_INI_ENTRY("suhosin.cookie.max_array_depth", "50", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieLong, max_cookie_array_depth, zend_suhosin_globals, suhosin_globals) | ||
| 897 | STD_PHP_INI_ENTRY("suhosin.cookie.max_array_index_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieLong, max_cookie_array_index_length, zend_suhosin_globals, suhosin_globals) | ||
| 898 | STD_PHP_INI_ENTRY("suhosin.cookie.disallow_nul", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieBool, disallow_cookie_nul, zend_suhosin_globals, suhosin_globals) | ||
| 899 | STD_PHP_INI_ENTRY("suhosin.cookie.disallow_ws", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateCookieBool, disallow_cookie_ws, zend_suhosin_globals, suhosin_globals) | ||
| 900 | |||
| 901 | STD_PHP_INI_ENTRY("suhosin.get.max_vars", "100", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetLong, max_get_vars, zend_suhosin_globals, suhosin_globals) | ||
| 902 | STD_PHP_INI_ENTRY("suhosin.get.max_name_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetLong, max_get_name_length, zend_suhosin_globals, suhosin_globals) | ||
| 903 | STD_PHP_INI_ENTRY("suhosin.get.max_totalname_length", "256", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetLong, max_get_totalname_length, zend_suhosin_globals, suhosin_globals) | ||
| 904 | STD_PHP_INI_ENTRY("suhosin.get.max_value_length", "512", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetLong, max_get_value_length, zend_suhosin_globals, suhosin_globals) | ||
| 905 | STD_PHP_INI_ENTRY("suhosin.get.max_array_depth", "50", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetLong, max_get_array_depth, zend_suhosin_globals, suhosin_globals) | ||
| 906 | STD_PHP_INI_ENTRY("suhosin.get.max_array_index_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetLong, max_get_array_index_length, zend_suhosin_globals, suhosin_globals) | ||
| 907 | STD_PHP_INI_ENTRY("suhosin.get.disallow_nul", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetBool, disallow_get_nul, zend_suhosin_globals, suhosin_globals) | ||
| 908 | STD_PHP_INI_ENTRY("suhosin.get.disallow_ws", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateGetBool, disallow_get_ws, zend_suhosin_globals, suhosin_globals) | ||
| 909 | |||
| 910 | STD_PHP_INI_ENTRY("suhosin.post.max_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostLong, max_post_vars, zend_suhosin_globals, suhosin_globals) | ||
| 911 | STD_PHP_INI_ENTRY("suhosin.post.max_name_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostLong, max_post_name_length, zend_suhosin_globals, suhosin_globals) | ||
| 912 | STD_PHP_INI_ENTRY("suhosin.post.max_totalname_length", "256", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostLong, max_post_totalname_length, zend_suhosin_globals, suhosin_globals) | ||
| 913 | STD_PHP_INI_ENTRY("suhosin.post.max_value_length", "1000000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostLong, max_post_value_length, zend_suhosin_globals, suhosin_globals) | ||
| 914 | STD_PHP_INI_ENTRY("suhosin.post.max_array_depth", "50", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostLong, max_post_array_depth, zend_suhosin_globals, suhosin_globals) | ||
| 915 | STD_PHP_INI_ENTRY("suhosin.post.max_array_index_length", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostLong, max_post_array_index_length, zend_suhosin_globals, suhosin_globals) | ||
| 916 | STD_PHP_INI_ENTRY("suhosin.post.disallow_nul", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostBool, disallow_post_nul, zend_suhosin_globals, suhosin_globals) | ||
| 917 | STD_PHP_INI_ENTRY("suhosin.post.disallow_ws", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdatePostBool, disallow_post_ws, zend_suhosin_globals, suhosin_globals) | ||
| 918 | |||
| 919 | STD_PHP_INI_ENTRY("suhosin.upload.max_uploads", "25", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadLong, upload_limit, zend_suhosin_globals, suhosin_globals) | ||
| 920 | STD_PHP_INI_ENTRY("suhosin.upload.disallow_elf", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_elf, zend_suhosin_globals, suhosin_globals) | ||
| 921 | STD_PHP_INI_ENTRY("suhosin.upload.disallow_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_binary, zend_suhosin_globals, suhosin_globals) | ||
| 922 | STD_PHP_INI_ENTRY("suhosin.upload.remove_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_remove_binary, zend_suhosin_globals, suhosin_globals) | ||
| 923 | STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) | ||
| 924 | |||
| 925 | |||
| 926 | STD_ZEND_INI_BOOLEAN("suhosin.sql.bailout_on_error", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateSQLBool, sql_bailout_on_error, zend_suhosin_globals, suhosin_globals) | ||
| 927 | STD_PHP_INI_ENTRY("suhosin.sql.user_prefix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_prefix, zend_suhosin_globals, suhosin_globals) | ||
| 928 | STD_PHP_INI_ENTRY("suhosin.sql.user_postfix", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLString, sql_user_postfix, zend_suhosin_globals, suhosin_globals) | ||
| 929 | STD_PHP_INI_ENTRY("suhosin.sql.comment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_comment, zend_suhosin_globals, suhosin_globals) | ||
| 930 | STD_PHP_INI_ENTRY("suhosin.sql.opencomment", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_opencomment, zend_suhosin_globals, suhosin_globals) | ||
| 931 | STD_PHP_INI_ENTRY("suhosin.sql.multiselect", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_mselect, zend_suhosin_globals, suhosin_globals) | ||
| 932 | STD_PHP_INI_ENTRY("suhosin.sql.union", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateSQLLong, sql_union, zend_suhosin_globals, suhosin_globals) | ||
| 933 | |||
| 934 | STD_ZEND_INI_BOOLEAN("suhosin.session.encrypt", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_encrypt, zend_suhosin_globals, suhosin_globals) | ||
| 935 | STD_PHP_INI_ENTRY("suhosin.session.cryptkey", "", PHP_INI_ALL, OnUpdateString, session_cryptkey, zend_suhosin_globals, suhosin_globals) | ||
| 936 | STD_ZEND_INI_BOOLEAN("suhosin.session.cryptua", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_cryptua, zend_suhosin_globals, suhosin_globals) | ||
| 937 | STD_ZEND_INI_BOOLEAN("suhosin.session.cryptdocroot", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, session_cryptdocroot, zend_suhosin_globals, suhosin_globals) | ||
| 938 | STD_PHP_INI_ENTRY("suhosin.session.cryptraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_cryptraddr, zend_suhosin_globals, suhosin_globals) | ||
| 939 | STD_PHP_INI_ENTRY("suhosin.session.checkraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_checkraddr, zend_suhosin_globals, suhosin_globals) | ||
| 940 | STD_PHP_INI_ENTRY("suhosin.session.max_id_length", "128", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, session_max_id_length, zend_suhosin_globals, suhosin_globals) | ||
| 941 | |||
| 942 | |||
| 943 | STD_ZEND_INI_BOOLEAN("suhosin.cookie.encrypt", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, cookie_encrypt, zend_suhosin_globals, suhosin_globals) | ||
| 944 | STD_PHP_INI_ENTRY("suhosin.cookie.cryptkey", "", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, cookie_cryptkey, zend_suhosin_globals, suhosin_globals) | ||
| 945 | STD_ZEND_INI_BOOLEAN("suhosin.cookie.cryptua", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, cookie_cryptua, zend_suhosin_globals, suhosin_globals) | ||
| 946 | STD_ZEND_INI_BOOLEAN("suhosin.cookie.cryptdocroot", "1", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, cookie_cryptdocroot, zend_suhosin_globals, suhosin_globals) | ||
| 947 | STD_PHP_INI_ENTRY("suhosin.cookie.cryptraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, cookie_cryptraddr, zend_suhosin_globals, suhosin_globals) | ||
| 948 | STD_PHP_INI_ENTRY("suhosin.cookie.checkraddr", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, cookie_checkraddr, zend_suhosin_globals, suhosin_globals) | ||
| 949 | ZEND_INI_ENTRY("suhosin.cookie.cryptlist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_cookie_cryptlist) | ||
| 950 | ZEND_INI_ENTRY("suhosin.cookie.plainlist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdate_cookie_plainlist) | ||
| 951 | |||
| 952 | |||
| 953 | STD_ZEND_INI_BOOLEAN("suhosin.server.encode", "1", ZEND_INI_SYSTEM, OnUpdateBool, server_encode,zend_suhosin_globals, suhosin_globals) | ||
| 954 | STD_ZEND_INI_BOOLEAN("suhosin.server.strip", "1", ZEND_INI_SYSTEM, OnUpdateBool, server_strip,zend_suhosin_globals, suhosin_globals) | ||
| 955 | |||
| 956 | STD_ZEND_INI_BOOLEAN("suhosin.srand.ignore", "1", ZEND_INI_SYSTEM|ZEND_INI_PERDIR, OnUpdateMiscBool, srand_ignore,zend_suhosin_globals, suhosin_globals) | ||
| 957 | STD_ZEND_INI_BOOLEAN("suhosin.mt_srand.ignore", "1", ZEND_INI_SYSTEM|ZEND_INI_PERDIR, OnUpdateMiscBool, mt_srand_ignore,zend_suhosin_globals, suhosin_globals) | ||
| 958 | |||
| 959 | PHP_INI_END() | ||
| 960 | /* }}} */ | ||
| 961 | |||
| 962 | |||
| 963 | /* {{{ php_suhosin_init_globals | ||
| 964 | */ | ||
| 965 | void suhosin_bailout(TSRMLS_D) | ||
| 966 | { | ||
| 967 | if (!SUHOSIN_G(simulation)) { | ||
| 968 | zend_bailout(); | ||
| 969 | } | ||
| 970 | } | ||
| 971 | /* }}} */ | ||
| 972 | |||
| 973 | /* {{{ php_suhosin_init_globals | ||
| 974 | */ | ||
| 975 | STATIC void php_suhosin_init_globals(zend_suhosin_globals *suhosin_globals) | ||
| 976 | { | ||
| 977 | memset(suhosin_globals, 0, sizeof(zend_suhosin_globals)); | ||
| 978 | } | ||
| 979 | /* }}} */ | ||
| 980 | |||
| 981 | /* {{{ PHP_MINIT_FUNCTION | ||
| 982 | */ | ||
| 983 | PHP_MINIT_FUNCTION(suhosin) | ||
| 984 | { | ||
| 985 | SDEBUG("(MINIT)"); | ||
| 986 | ZEND_INIT_MODULE_GLOBALS(suhosin, php_suhosin_init_globals, NULL); | ||
| 987 | |||
| 988 | /* only register constants if they have not previously been registered by a possible patched PHP */ | ||
| 989 | |||
| 990 | if (zend_hash_exists(EG(zend_constants), "S_MEMORY", sizeof("S_MEMORY"))==0) { | ||
| 991 | REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS); | ||
| 992 | REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS); | ||
| 993 | REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS); | ||
| 994 | REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS); | ||
| 995 | REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS); | ||
| 996 | REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS); | ||
| 997 | REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS); | ||
| 998 | REGISTER_MAIN_LONG_CONSTANT("S_SESSION", S_SESSION, CONST_PERSISTENT | CONST_CS); | ||
| 999 | REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS); | ||
| 1000 | REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS); | ||
| 1001 | REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /* check if shared ini directives are already known (maybe a patched PHP) */ | ||
| 1005 | if (zend_hash_exists(EG(ini_directives), "suhosin.log.syslog", sizeof("suhosin.log.syslog"))) { | ||
| 1006 | |||
| 1007 | /* and update them */ | ||
| 1008 | zend_ini_entry *p = (zend_ini_entry *)&shared_ini_entries; | ||
| 1009 | |||
| 1010 | while (p->name) { | ||
| 1011 | |||
| 1012 | zend_ini_entry *i; | ||
| 1013 | |||
| 1014 | if (zend_hash_find(EG(ini_directives), p->name, p->name_length, (void **) &i)==FAILURE) { | ||
| 1015 | /* continue registering them */ | ||
| 1016 | zend_register_ini_entries(p, module_number TSRMLS_CC); | ||
| 1017 | break; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | SDEBUG("updating ini %s=%s", i->name, i->value); | ||
| 1021 | |||
| 1022 | #ifdef ZEND_ENGINE_2 | ||
| 1023 | i->modifiable = p->modifiable; | ||
| 1024 | #else | ||
| 1025 | i->modifyable = p->modifyable; | ||
| 1026 | #endif | ||
| 1027 | i->module_number = module_number; | ||
| 1028 | i->on_modify = p->on_modify; | ||
| 1029 | i->mh_arg1 = p->mh_arg1; | ||
| 1030 | i->mh_arg2 = p->mh_arg2; | ||
| 1031 | i->mh_arg3 = p->mh_arg3; | ||
| 1032 | i->on_modify(i, i->value, i->value_length, i->mh_arg1, i->mh_arg2, i->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC); | ||
| 1033 | p++; | ||
| 1034 | } | ||
| 1035 | } else { | ||
| 1036 | |||
| 1037 | /* not registered yet, then simply use the API */ | ||
| 1038 | zend_register_ini_entries((zend_ini_entry *)&shared_ini_entries, module_number TSRMLS_CC); | ||
| 1039 | |||
| 1040 | } | ||
| 1041 | |||
| 1042 | /* and register the rest of the ini entries */ | ||
| 1043 | REGISTER_INI_ENTRIES(); | ||
| 1044 | |||
| 1045 | /* Force display_errors=off */ | ||
| 1046 | if (SUHOSIN_G(disable_display_errors)) { | ||
| 1047 | zend_ini_entry *i; | ||
| 1048 | if (zend_hash_find(EG(ini_directives), "display_errors", sizeof("display_errors"), (void **) &i) == SUCCESS) { | ||
| 1049 | if (i->on_modify) { | ||
| 1050 | i->on_modify(i, "0", sizeof("0"), i->mh_arg1, i->mh_arg2, i->mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC); | ||
| 1051 | i->on_modify = NULL; | ||
| 1052 | } | ||
| 1053 | } | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | /* Load invisible to other Zend Extensions */ | ||
| 1057 | if (zend_llist_count(&zend_extensions)==0 || SUHOSIN_G(stealth)==0) { | ||
| 1058 | zend_extension extension; | ||
| 1059 | extension = suhosin_zend_extension_entry; | ||
| 1060 | extension.handle = NULL; | ||
| 1061 | zend_llist_add_element(&zend_extensions, &extension); | ||
| 1062 | ze = NULL; | ||
| 1063 | } else { | ||
| 1064 | ze = (zend_extension *)zend_llist_get_last_ex(&zend_extensions, &lp); | ||
| 1065 | old_startup = ze->startup; | ||
| 1066 | ze->startup = suhosin_startup_wrapper; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | /* now hook a bunch of stuff */ | ||
| 1070 | suhosin_hook_memory_limit(); | ||
| 1071 | suhosin_hook_crypt(); | ||
| 1072 | suhosin_hook_sha256(); | ||
| 1073 | suhosin_hook_ex_imp(); | ||
| 1074 | |||
| 1075 | /* register the logo for phpinfo */ | ||
| 1076 | php_register_info_logo(SUHOSIN_LOGO_GUID, "image/jpeg", suhosin_logo, sizeof(suhosin_logo)); | ||
| 1077 | |||
| 1078 | #if PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1) | ||
| 1079 | /* perform LFS check */ | ||
| 1080 | /* time_t check = sapi_get_request_time(TSRMLS_C); | ||
| 1081 | if (SG(global_request_time) != check) { | ||
| 1082 | zend_error(E_ERROR, "It seems that PHP and Suhosin were compiled with different binary layouts. " | ||
| 1083 | "This will cause problems like POST not working. Please tell your distributor to fix this."); | ||
| 1084 | }*/ | ||
| 1085 | #endif | ||
| 1086 | return SUCCESS; | ||
| 1087 | } | ||
| 1088 | /* }}} */ | ||
| 1089 | |||
| 1090 | /* {{{ PHP_MSHUTDOWN_FUNCTION | ||
| 1091 | */ | ||
| 1092 | PHP_MSHUTDOWN_FUNCTION(suhosin) | ||
| 1093 | { | ||
| 1094 | SDEBUG("(MSHUTDOWN)"); | ||
| 1095 | UNREGISTER_INI_ENTRIES(); | ||
| 1096 | return SUCCESS; | ||
| 1097 | } | ||
| 1098 | /* }}} */ | ||
| 1099 | |||
| 1100 | |||
| 1101 | /* {{{ PHP_RINIT_FUNCTION | ||
| 1102 | */ | ||
| 1103 | PHP_RINIT_FUNCTION(suhosin) | ||
| 1104 | { | ||
| 1105 | SDEBUG("(RINIT)"); | ||
| 1106 | SUHOSIN_G(in_code_type) = SUHOSIN_NORMAL; | ||
| 1107 | SUHOSIN_G(execution_depth) = 0; | ||
| 1108 | |||
| 1109 | return SUCCESS; | ||
| 1110 | } | ||
| 1111 | /* }}} */ | ||
| 1112 | |||
| 1113 | |||
| 1114 | /* {{{ PHP_RSHUTDOWN_FUNCTION | ||
| 1115 | */ | ||
| 1116 | PHP_RSHUTDOWN_FUNCTION(suhosin) | ||
| 1117 | { | ||
| 1118 | SDEBUG("(RSHUTDOWN)"); | ||
| 1119 | |||
| 1120 | /* We need to clear the input filtering | ||
| 1121 | variables in the request shutdown | ||
| 1122 | because input filtering is done before | ||
| 1123 | RINIT */ | ||
| 1124 | |||
| 1125 | SUHOSIN_G(cur_request_variables) = 0; | ||
| 1126 | SUHOSIN_G(cur_cookie_vars) = 0; | ||
| 1127 | SUHOSIN_G(cur_get_vars) = 0; | ||
| 1128 | SUHOSIN_G(cur_post_vars) = 0; | ||
| 1129 | SUHOSIN_G(num_uploads) = 0; | ||
| 1130 | |||
| 1131 | SUHOSIN_G(no_more_variables) = 0; | ||
| 1132 | SUHOSIN_G(no_more_get_variables) = 0; | ||
| 1133 | SUHOSIN_G(no_more_post_variables) = 0; | ||
| 1134 | SUHOSIN_G(no_more_cookie_variables) = 0; | ||
| 1135 | SUHOSIN_G(no_more_uploads) = 0; | ||
| 1136 | |||
| 1137 | SUHOSIN_G(abort_request) = 0; | ||
| 1138 | |||
| 1139 | if (SUHOSIN_G(decrypted_cookie)) { | ||
| 1140 | efree(SUHOSIN_G(decrypted_cookie)); | ||
| 1141 | SUHOSIN_G(decrypted_cookie)=NULL; | ||
| 1142 | } | ||
| 1143 | if (SUHOSIN_G(raw_cookie)) { | ||
| 1144 | efree(SUHOSIN_G(raw_cookie)); | ||
| 1145 | SUHOSIN_G(raw_cookie)=NULL; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | return SUCCESS; | ||
| 1149 | } | ||
| 1150 | /* }}} */ | ||
| 1151 | |||
| 1152 | /* {{{ suhosin_ini_displayer(zend_ini_entry *ini_entry, int type) | ||
| 1153 | */ | ||
| 1154 | static void suhosin_ini_displayer(zend_ini_entry *ini_entry, int type) | ||
| 1155 | { | ||
| 1156 | TSRMLS_FETCH(); | ||
| 1157 | |||
| 1158 | PHPWRITE("[ protected ]", strlen("[ protected ]")); | ||
| 1159 | } | ||
| 1160 | /* }}} */ | ||
| 1161 | |||
| 1162 | /* {{{ PHP_MINFO_FUNCTION | ||
| 1163 | */ | ||
| 1164 | PHP_MINFO_FUNCTION(suhosin) | ||
| 1165 | { | ||
| 1166 | php_info_print_box_start(0); | ||
| 1167 | if (!sapi_module.phpinfo_as_text) { | ||
| 1168 | if (PG(expose_php)) { | ||
| 1169 | PUTS("<a href=\"http://www.suhosin.org/\"><img border=\"0\" src=\""); | ||
| 1170 | if (SG(request_info).request_uri) { | ||
| 1171 | char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC); | ||
| 1172 | PUTS(elem_esc); | ||
| 1173 | efree(elem_esc); | ||
| 1174 | } | ||
| 1175 | PUTS("?="SUHOSIN_LOGO_GUID"\" alt=\"Suhosin logo\" /></a>\n"); | ||
| 1176 | } else do { | ||
| 1177 | char *enc_logo; | ||
| 1178 | int ret; | ||
| 1179 | zval **agent_name; | ||
| 1180 | |||
| 1181 | #ifdef ZEND_ENGINE_2 | ||
| 1182 | zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); | ||
| 1183 | #endif | ||
| 1184 | if (!PG(http_globals)[TRACK_VARS_SERVER] || | ||
| 1185 | zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"), (void **) &agent_name)==FAILURE) { | ||
| 1186 | break; | ||
| 1187 | } | ||
| 1188 | if (Z_TYPE_PP(agent_name) != IS_STRING) { | ||
| 1189 | break; | ||
| 1190 | } | ||
| 1191 | if (strstr(Z_STRVAL_PP(agent_name), "Gecko") == NULL && strstr(Z_STRVAL_PP(agent_name), "Opera") == NULL) { | ||
| 1192 | break; | ||
| 1193 | } | ||
| 1194 | PUTS("<a href=\"http://www.suhosin.org/\"><img border=\"0\" src=\"data:image/jpeg;base64,"); | ||
| 1195 | enc_logo=(char *)php_base64_encode(suhosin_logo, sizeof(suhosin_logo), &ret); | ||
| 1196 | if (enc_logo) { | ||
| 1197 | PUTS(enc_logo); | ||
| 1198 | efree(enc_logo); | ||
| 1199 | } | ||
| 1200 | PUTS("\" alt=\"Suhosin logo\" /></a>\n"); | ||
| 1201 | } while(0); | ||
| 1202 | } | ||
| 1203 | PUTS("This server is protected with the Suhosin Extension " SUHOSIN_EXT_VERSION); | ||
| 1204 | PUTS(!sapi_module.phpinfo_as_text?"<br /><br />":"\n\n"); | ||
| 1205 | if (sapi_module.phpinfo_as_text) { | ||
| 1206 | PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n"); | ||
| 1207 | PUTS("Copyright (c) 2007-2008 SektionEins GmbH\n"); | ||
| 1208 | } else { | ||
| 1209 | PUTS("Copyright (c) 2006-2007 <a href=\"http://www.hardened-php.net/\">Hardened-PHP Project</a><br />\n"); | ||
| 1210 | PUTS("Copyright (c) 2007-2008 <a href=\"http://www.sektioneins.de/\">SektionEins GmbH</a>\n"); | ||
| 1211 | } | ||
| 1212 | php_info_print_box_end(); | ||
| 1213 | |||
| 1214 | if (SUHOSIN_G(protectkey)) { | ||
| 1215 | zend_ini_entry *i; | ||
| 1216 | |||
| 1217 | if (zend_hash_find(EG(ini_directives), "suhosin.cookie.cryptkey", sizeof("suhosin.cookie.cryptkey"), (void **) &i)==SUCCESS) { | ||
| 1218 | i->displayer = suhosin_ini_displayer; | ||
| 1219 | } | ||
| 1220 | if (zend_hash_find(EG(ini_directives), "suhosin.session.cryptkey", sizeof("suhosin.session.cryptkey"), (void **) &i)==SUCCESS) { | ||
| 1221 | i->displayer = suhosin_ini_displayer; | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | DISPLAY_INI_ENTRIES(); | ||
| 1226 | |||
| 1227 | if (SUHOSIN_G(protectkey)) { | ||
| 1228 | zend_ini_entry *i; | ||
| 1229 | |||
| 1230 | if (zend_hash_find(EG(ini_directives), "suhosin.cookie.cryptkey", sizeof("suhosin.cookie.cryptkey"), (void **) &i)==SUCCESS) { | ||
| 1231 | i->displayer = NULL; | ||
| 1232 | } | ||
| 1233 | if (zend_hash_find(EG(ini_directives), "suhosin.session.cryptkey", sizeof("suhosin.session.cryptkey"), (void **) &i)==SUCCESS) { | ||
| 1234 | i->displayer = NULL; | ||
| 1235 | } | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | } | ||
| 1239 | /* }}} */ | ||
| 1240 | |||
| 1241 | /* | ||
| 1242 | * Local variables: | ||
| 1243 | * tab-width: 4 | ||
| 1244 | * c-basic-offset: 4 | ||
| 1245 | * End: | ||
| 1246 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 1247 | * vim<600: noet sw=4 ts=4 | ||
| 1248 | */ | ||
diff --git a/suhosin.ini b/suhosin.ini new file mode 100644 index 0000000..9696e7b --- /dev/null +++ b/suhosin.ini | |||
| @@ -0,0 +1,444 @@ | |||
| 1 | extension = suhosin.so | ||
| 2 | |||
| 3 | ; ----------------------------------------------------------------------------- | ||
| 4 | ; This file was taken from Mandriva Linux with their permission | ||
| 5 | ; ----------------------------------------------------------------------------- | ||
| 6 | |||
| 7 | [suhosin] | ||
| 8 | |||
| 9 | ; ----------------------------------------------------------------------------- | ||
| 10 | ; Logging Options | ||
| 11 | |||
| 12 | ; Defines what classes of security alerts are logged to the syslog daemon. | ||
| 13 | ; Logging of errors of the class S_MEMORY are always logged to syslog, no | ||
| 14 | ; matter what this configuration says, because a corrupted heap could mean that | ||
| 15 | ; the other logging options will malfunction during the logging process. | ||
| 16 | ;suhosin.log.syslog = | ||
| 17 | |||
| 18 | ; Defines the syslog facility that is used when ALERTs are logged to syslog. | ||
| 19 | ;suhosin.log.syslog.facility = | ||
| 20 | |||
| 21 | ; Defines the syslog priority that is used when ALERTs are logged to syslog. | ||
| 22 | ;suhosin.log.syslog.priority = | ||
| 23 | |||
| 24 | ; Defines what classes of security alerts are logged through the SAPI error log. | ||
| 25 | ;suhosin.log.sapi = | ||
| 26 | |||
| 27 | ; Defines what classes of security alerts are logged through the external | ||
| 28 | ; logging. | ||
| 29 | ;suhosin.log.script = | ||
| 30 | |||
| 31 | ; Defines what classes of security alerts are logged through the defined PHP | ||
| 32 | ; script. | ||
| 33 | ;suhosin.log.phpscript = 0 | ||
| 34 | |||
| 35 | ; Defines the full path to a external logging script. The script is called with | ||
| 36 | ; 2 parameters. The first one is the alert class in string notation and the | ||
| 37 | ; second parameter is the log message. This can be used for example to mail | ||
| 38 | ; failing MySQL queries to your email address, because on a production system | ||
| 39 | ; these things should never happen. | ||
| 40 | ;suhosin.log.script.name = | ||
| 41 | |||
| 42 | ; Defines the full path to a PHP logging script. The script is called with 2 | ||
| 43 | ; variables registered in the current scope: SUHOSIN_ERRORCLASS and | ||
| 44 | ; SUHOSIN_ERROR. The first one is the alert class and the second variable is | ||
| 45 | ; the log message. This can be used for example to mail attempted remote URL | ||
| 46 | ; include attacks to your email address. | ||
| 47 | ;suhosin.log.phpscript.name = | ||
| 48 | |||
| 49 | ; Undocumented | ||
| 50 | ;suhosin.log.phpscript.is_safe = Off | ||
| 51 | |||
| 52 | ; When the Hardening-Patch logs an error the log message also contains the IP | ||
| 53 | ; of the attacker. Usually this IP is retrieved from the REMOTE_ADDR SAPI | ||
| 54 | ; environment variable. With this switch it is possible to change this behavior | ||
| 55 | ; to read the IP from the X-Forwarded-For HTTP header. This is f.e. necessary | ||
| 56 | ; when your PHP server runs behind a reverse proxy. | ||
| 57 | ;suhosin.log.use-x-forwarded-for = Off | ||
| 58 | |||
| 59 | ; ----------------------------------------------------------------------------- | ||
| 60 | ; Executor Options | ||
| 61 | |||
| 62 | ; Defines the maximum stack depth allowed by the executor before it stops the | ||
| 63 | ; script. Without this function an endless recursion in a PHP script could | ||
| 64 | ; crash the PHP executor or trigger the configured memory_limit. A value of | ||
| 65 | ; "0" disables this feature. | ||
| 66 | ;suhosin.executor.max_depth = 0 | ||
| 67 | |||
| 68 | ; Defines how many "../" an include filename needs to contain to be considered | ||
| 69 | ; an attack and stopped. A value of "2" will block "../../etc/passwd", while a | ||
| 70 | ; value of "3" will allow it. Most PHP applications should work flawlessly with | ||
| 71 | ; values "4" or "5". A value of "0" disables this feature. | ||
| 72 | ;suhosin.executor.include.max_traversal = 0 | ||
| 73 | |||
| 74 | ; Comma separated whitelist of URL schemes that are allowed to be included from | ||
| 75 | ; include or require statements. Additionally to URL schemes it is possible to | ||
| 76 | ; specify the beginning of allowed URLs. (f.e.: php://stdin) If no whitelist is | ||
| 77 | ; specified, then the blacklist is evaluated. | ||
| 78 | ;suhosin.executor.include.whitelist = | ||
| 79 | |||
| 80 | ; Comma separated blacklist of URL schemes that are not allowed to be included | ||
| 81 | ; from include or require statements. Additionally to URL schemes it is | ||
| 82 | ; possible to specify the beginning of allowed URLs. (f.e.: php://stdin) If no | ||
| 83 | ; blacklist and no whitelist is specified all URL schemes are forbidden. | ||
| 84 | ;suhosin.executor.include.blacklist = | ||
| 85 | |||
| 86 | ; Defines if PHP is allows to run code from files that are writable by the | ||
| 87 | ; current process. If a file is created or modified by a PHP process, there | ||
| 88 | ; is a potential danger of code injection. Only turn this on if you are sure | ||
| 89 | ; that your application does not require writable PHP files. | ||
| 90 | ;suhosin.executor.include.allow_writable_files = On | ||
| 91 | |||
| 92 | ; Comma separated whitelist of functions that are allowed to be called. If the | ||
| 93 | ; whitelist is empty the blacklist is evaluated, otherwise calling a function | ||
| 94 | ; not in the whitelist will terminate the script and get logged. | ||
| 95 | ;suhosin.executor.func.whitelist = | ||
| 96 | |||
| 97 | ; Comma separated blacklist of functions that are not allowed to be called. If | ||
| 98 | ; no whitelist is given, calling a function within the blacklist will terminate | ||
| 99 | ; the script and get logged. | ||
| 100 | ;suhosin.executor.func.blacklist = | ||
| 101 | |||
| 102 | ; Comma separated whitelist of functions that are allowed to be called from | ||
| 103 | ; within eval(). If the whitelist is empty the blacklist is evaluated, | ||
| 104 | ; otherwise calling a function not in the whitelist will terminate the script | ||
| 105 | ; and get logged. | ||
| 106 | ;suhosin.executor.eval.whitelist = | ||
| 107 | |||
| 108 | ; Comma separated blacklist of functions that are not allowed to be called from | ||
| 109 | ; within eval(). If no whitelist is given, calling a function within the | ||
| 110 | ; blacklist will terminate the script and get logged. | ||
| 111 | ;suhosin.executor.eval.blacklist = | ||
| 112 | |||
| 113 | ; eval() is a very dangerous statement and therefore you might want to disable | ||
| 114 | ; it completely. Deactivating it will however break lots of scripts. Because | ||
| 115 | ; every violation is logged, this allows finding all places where eval() is | ||
| 116 | ; used. | ||
| 117 | ;suhosin.executor.disable_eval = Off | ||
| 118 | |||
| 119 | ; The /e modifier inside preg_replace() allows code execution. Often it is the | ||
| 120 | ; cause for remote code execution exploits. It is wise to deactivate this | ||
| 121 | ; feature and test where in the application it is used. The developer using the | ||
| 122 | ; /e modifier should be made aware that he should use preg_replace_callback() | ||
| 123 | ; instead. | ||
| 124 | ;suhosin.executor.disable_emodifier = Off | ||
| 125 | |||
| 126 | ; This flag reactivates symlink() when open_basedir is used, which is disabled | ||
| 127 | ; by default in Suhosin >= 0.9.6. Allowing symlink() while open_basedir is used | ||
| 128 | ; is actually a security risk. | ||
| 129 | ;suhosin.executor.allow_symlink = Off | ||
| 130 | |||
| 131 | ; ----------------------------------------------------------------------------- | ||
| 132 | ; Misc Options | ||
| 133 | |||
| 134 | ; If you fear that Suhosin breaks your application, you can activate Suhosin's | ||
| 135 | ; simulation mode with this flag. When Suhosin runs in simulation mode, | ||
| 136 | ; violations are logged as usual, but nothing is blocked or removed from the | ||
| 137 | ; request. (Transparent Encryptions are NOT deactivated in simulation mode.) | ||
| 138 | ;suhosin.simulation = Off | ||
| 139 | |||
| 140 | ; APC 3.0.12(p1/p2) uses reserved resources without requesting a resource slot | ||
| 141 | ; first. It always uses resource slot 0. If Suhosin got this slot assigned APC | ||
| 142 | ; will overwrite the information Suhosin stores in this slot. When this flag is | ||
| 143 | ; set Suhosin will request 2 Slots and use the second one. This allows working | ||
| 144 | ; correctly with these buggy APC versions. | ||
| 145 | ;suhosin.apc_bug_workaround = Off | ||
| 146 | |||
| 147 | ; When a SQL Query fails scripts often spit out a bunch of useful information | ||
| 148 | ; for possible attackers. When this configuration directive is turned on, the | ||
| 149 | ; script will silently terminate, after the problem has been logged. (This is | ||
| 150 | ; not yet supported) | ||
| 151 | ;suhosin.sql.bailout_on_error = Off | ||
| 152 | |||
| 153 | ; This is an experimental feature for shared environments. With this | ||
| 154 | ; configuration option it is possible to specify a prefix that is automatically | ||
| 155 | ; prepended to the database username, whenever a database connection is made. | ||
| 156 | ; (Unless the username starts with the prefix) | ||
| 157 | ;suhosin.sql.user_prefix = | ||
| 158 | |||
| 159 | ; This is an experimental feature for shared environments. With this | ||
| 160 | ; configuration option it is possible to specify a postfix that is | ||
| 161 | ; automatically appended to the database username, whenever a database | ||
| 162 | ; connection is made. (Unless the username end with the postfix) | ||
| 163 | ; | ||
| 164 | ; With this feature it is possible for shared hosters to disallow customers to | ||
| 165 | ; connect with the usernames of other customers. This feature is experimental, | ||
| 166 | ; because support for PDO and PostgreSQL are not yet implemented. | ||
| 167 | ;suhosin.sql.user_postfix = | ||
| 168 | |||
| 169 | ; This directive controls if multiple headers are allowed or not in a header() | ||
| 170 | ; call. By default the Hardening-Patch forbids this. (HTTP headers spanning | ||
| 171 | ; multiple lines are still allowed). | ||
| 172 | ;suhosin.multiheader = Off | ||
| 173 | |||
| 174 | ; This directive controls if the mail() header protection is activated or not | ||
| 175 | ; and to what degree it is activated. The appended table lists the possible | ||
| 176 | ; activation levels. | ||
| 177 | suhosin.mail.protect = 1 | ||
| 178 | |||
| 179 | ; As long scripts are not running within safe_mode they are free to change the | ||
| 180 | ; memory_limit to whatever value they want. Suhosin changes this fact and | ||
| 181 | ; disallows setting the memory_limit to a value greater than the one the script | ||
| 182 | ; started with, when this option is left at 0. A value greater than 0 means | ||
| 183 | ; that Suhosin will disallows scripts setting the memory_limit to a value above | ||
| 184 | ; this configured hard limit. This is for example usefull if you want to run | ||
| 185 | ; the script normaly with a limit of 16M but image processing scripts may raise | ||
| 186 | ; it to 20M. | ||
| 187 | ;suhosin.memory_limit = 0 | ||
| 188 | |||
| 189 | ; ----------------------------------------------------------------------------- | ||
| 190 | ; Transparent Encryption Options | ||
| 191 | |||
| 192 | ; Flag that decides if the transparent session encryption is activated or not. | ||
| 193 | ;suhosin.session.encrypt = On | ||
| 194 | |||
| 195 | ; Session data can be encrypted transparently. The encryption key used consists | ||
| 196 | ; of this user defined string (which can be altered by a script via ini_set()) | ||
| 197 | ; and optionally the User-Agent, the Document-Root and 0-4 Octects of the | ||
| 198 | ; REMOTE_ADDR. | ||
| 199 | ;suhosin.session.cryptkey = | ||
| 200 | |||
| 201 | ; Flag that decides if the transparent session encryption key depends on the | ||
| 202 | ; User-Agent field. (When activated this feature transparently adds a little | ||
| 203 | ; bit protection against session fixation/hijacking attacks) | ||
| 204 | ;suhosin.session.cryptua = On | ||
| 205 | |||
| 206 | ; Flag that decides if the transparent session encryption key depends on the | ||
| 207 | ; Documentroot field. | ||
| 208 | ;suhosin.session.cryptdocroot = On | ||
| 209 | |||
| 210 | ; Number of octets (0-4) from the REMOTE_ADDR that the transparent session | ||
| 211 | ; encryption key depends on. Keep in mind that this should not be used on sites | ||
| 212 | ; that have visitors from big ISPs, because their IP address often changes | ||
| 213 | ; during a session. But this feature might be interesting for admin interfaces | ||
| 214 | ; or intranets. When used wisely this is a transparent protection against | ||
| 215 | ; session hijacking/fixation. | ||
| 216 | ;suhosin.session.cryptraddr = 0 | ||
| 217 | |||
| 218 | ; Number of octets (0-4) from the REMOTE_ADDR that have to match to decrypt the | ||
| 219 | ; session. The difference to suhosin.session.cryptaddr is, that the IP is not | ||
| 220 | ; part of the encryption key, so that the same session can be used for | ||
| 221 | ; different areas with different protection levels on the site. | ||
| 222 | ;suhosin.session.checkraddr = 0 | ||
| 223 | |||
| 224 | ; Flag that decides if the transparent cookie encryption is activated or not. | ||
| 225 | ;suhosin.cookie.encrypt = 0 | ||
| 226 | |||
| 227 | ; Cookies can be encrypted transparently. The encryption key used consists of | ||
| 228 | ; this user defined string and optionally the User-Agent, the Document-Root and | ||
| 229 | ; 0-4 Octects of the REMOTE_ADDR. | ||
| 230 | ;suhosin.cookie.cryptkey = | ||
| 231 | |||
| 232 | ; Flag that decides if the transparent session encryption key depends on the | ||
| 233 | ; User-Agent field. (When activated this feature transparently adds a little | ||
| 234 | ; bit protection against session fixation/hijacking attacks (if only session | ||
| 235 | ; cookies are allowed)) | ||
| 236 | ;suhosin.cookie.cryptua = On | ||
| 237 | |||
| 238 | ; Flag that decides if the transparent cookie encryption key depends on the | ||
| 239 | ; Documentroot field. | ||
| 240 | ;suhosin.cookie.cryptdocroot = On | ||
| 241 | |||
| 242 | ; Number of octets (0-4) from the REMOTE_ADDR that the transparent cookie | ||
| 243 | ; encryption key depends on. Keep in mind that this should not be used on sites | ||
| 244 | ; that have visitors from big ISPs, because their IP address often changes | ||
| 245 | ; during a session. But this feature might be interesting for admin interfaces | ||
| 246 | ; or intranets. When used wisely this is a transparent protection against | ||
| 247 | ; session hijacking/fixation. | ||
| 248 | ;suhosin.cookie.cryptraddr = 0 | ||
| 249 | |||
| 250 | ; Number of octets (0-4) from the REMOTE_ADDR that have to match to decrypt the | ||
| 251 | ; cookie. The difference to suhosin.cookie.cryptaddr is, that the IP is not | ||
| 252 | ; part of the encryption key, so that the same cookie can be used for different | ||
| 253 | ; areas with different protection levels on the site. | ||
| 254 | ;suhosin.cookie.checkraddr = 0 | ||
| 255 | |||
| 256 | ; In case not all cookies are supposed to get encrypted this is a comma | ||
| 257 | ; separated list of cookie names that should get encrypted. All other cookies | ||
| 258 | ; will not get touched. | ||
| 259 | ;suhosin.cookie.cryptlist = | ||
| 260 | |||
| 261 | ; In case some cookies should not be crypted this is a comma separated list of | ||
| 262 | ; cookies that do not get encrypted. All other cookies will be encrypted. | ||
| 263 | ;suhosin.cookie.plainlist = | ||
| 264 | |||
| 265 | ; ----------------------------------------------------------------------------- | ||
| 266 | ; Filtering Options | ||
| 267 | |||
| 268 | ; Defines the reaction of Suhosin on a filter violation. | ||
| 269 | ;suhosin.filter.action = | ||
| 270 | |||
| 271 | ; Defines the maximum depth an array variable may have, when registered through | ||
| 272 | ; the COOKIE. | ||
| 273 | ;suhosin.cookie.max_array_depth = 50 | ||
| 274 | |||
| 275 | ; Defines the maximum length of array indices for variables registered through | ||
| 276 | ; the COOKIE. | ||
| 277 | ;suhosin.cookie.max_array_index_length = 64 | ||
| 278 | |||
| 279 | ; Defines the maximum length of variable names for variables registered through | ||
| 280 | ; the COOKIE. For array variables this is the name in front of the indices. | ||
| 281 | ;suhosin.cookie.max_name_length = 64 | ||
| 282 | |||
| 283 | ; Defines the maximum length of the total variable name when registered through | ||
| 284 | ; the COOKIE. For array variables this includes all indices. | ||
| 285 | ;suhosin.cookie.max_totalname_length = 256 | ||
| 286 | |||
| 287 | ; Defines the maximum length of a variable that is registered through the | ||
| 288 | ; COOKIE. | ||
| 289 | ;suhosin.cookie.max_value_length = 10000 | ||
| 290 | |||
| 291 | ; Defines the maximum number of variables that may be registered through the | ||
| 292 | ; COOKIE. | ||
| 293 | ;suhosin.cookie.max_vars = 100 | ||
| 294 | |||
| 295 | ; When set to On ASCIIZ chars are not allowed in variables. | ||
| 296 | ;suhosin.cookie.disallow_nul = 1 | ||
| 297 | |||
| 298 | ; Defines the maximum depth an array variable may have, when registered through | ||
| 299 | ; the URL | ||
| 300 | ;suhosin.get.max_array_depth = 50 | ||
| 301 | |||
| 302 | ; Defines the maximum length of array indices for variables registered through | ||
| 303 | ; the URL | ||
| 304 | ;suhosin.get.max_array_index_length = 64 | ||
| 305 | |||
| 306 | ; Defines the maximum length of variable names for variables registered through | ||
| 307 | ; the URL. For array variables this is the name in front of the indices. | ||
| 308 | ;suhosin.get.max_name_length = 64 | ||
| 309 | |||
| 310 | ; Defines the maximum length of the total variable name when registered through | ||
| 311 | ; the URL. For array variables this includes all indices. | ||
| 312 | ;suhosin.get.max_totalname_length = 256 | ||
| 313 | |||
| 314 | ; Defines the maximum length of a variable that is registered through the URL. | ||
| 315 | ;suhosin.get.max_value_length = 512 | ||
| 316 | |||
| 317 | ; Defines the maximum number of variables that may be registered through the | ||
| 318 | ; URL. | ||
| 319 | ;suhosin.get.max_vars = 100 | ||
| 320 | |||
| 321 | ; When set to On ASCIIZ chars are not allowed in variables. | ||
| 322 | ;suhosin.get.disallow_nul = 1 | ||
| 323 | |||
| 324 | ; Defines the maximum depth an array variable may have, when registered through | ||
| 325 | ; a POST request. | ||
| 326 | ;suhosin.post.max_array_depth = 50 | ||
| 327 | |||
| 328 | ; Defines the maximum length of array indices for variables registered through | ||
| 329 | ; a POST request. | ||
| 330 | ;suhosin.post.max_array_index_length = 64 | ||
| 331 | |||
| 332 | ; Defines the maximum length of variable names for variables registered through | ||
| 333 | ; a POST request. For array variables this is the name in front of the indices. | ||
| 334 | ;suhosin.post.max_name_length = 64 | ||
| 335 | |||
| 336 | ; Defines the maximum length of the total variable name when registered through | ||
| 337 | ; a POST request. For array variables this includes all indices. | ||
| 338 | ;suhosin.post.max_totalname_length = 256 | ||
| 339 | |||
| 340 | ; Defines the maximum length of a variable that is registered through a POST | ||
| 341 | ; request. | ||
| 342 | ;suhosin.post.max_value_length = 1000000 | ||
| 343 | |||
| 344 | ; Defines the maximum number of variables that may be registered through a POST | ||
| 345 | ; request. | ||
| 346 | ;suhosin.post.max_vars = 1000 | ||
| 347 | |||
| 348 | ; When set to On ASCIIZ chars are not allowed in variables. | ||
| 349 | ;suhosin.post.disallow_nul = 1 | ||
| 350 | |||
| 351 | ; Defines the maximum depth an array variable may have, when registered through | ||
| 352 | ; GET , POST or COOKIE. This setting is also an upper limit for the separate | ||
| 353 | ; GET, POST, COOKIE configuration directives. | ||
| 354 | ;suhosin.request.max_array_depth = 50 | ||
| 355 | |||
| 356 | ; Defines the maximum length of array indices for variables registered through | ||
| 357 | ; GET, POST or COOKIE. This setting is also an upper limit for the separate | ||
| 358 | ; GET, POST, COOKIE configuration directives. | ||
| 359 | ;suhosin.request.max_array_index_length = 64 | ||
| 360 | |||
| 361 | ; Defines the maximum length of variable names for variables registered through | ||
| 362 | ; the COOKIE, the URL or through a POST request. This is the complete name | ||
| 363 | ; string, including all indicies. This setting is also an upper limit for the | ||
| 364 | ; separate GET, POST, COOKIE configuration directives. | ||
| 365 | ;suhosin.request.max_totalname_length = 256 | ||
| 366 | |||
| 367 | ; Defines the maximum length of a variable that is registered through the | ||
| 368 | ; COOKIE, the URL or through a POST request. This setting is also an upper | ||
| 369 | ; limit for the variable origin specific configuration directives. | ||
| 370 | ;suhosin.request.max_value_length = 1000000 | ||
| 371 | |||
| 372 | ; Defines the maximum number of variables that may be registered through the | ||
| 373 | ; COOKIE, the URL or through a POST request. This setting is also an upper | ||
| 374 | ; limit for the variable origin specific configuration directives. | ||
| 375 | ;suhosin.request.max_vars = 1000 | ||
| 376 | |||
| 377 | ; Defines the maximum name length (excluding possible array indicies) of | ||
| 378 | ; variables that may be registered through the COOKIE, the URL or through a | ||
| 379 | ; POST request. This setting is also an upper limit for the variable origin | ||
| 380 | ; specific configuration directives. | ||
| 381 | ;suhosin.request.max_varname_length = 64 | ||
| 382 | |||
| 383 | ; When set to On ASCIIZ chars are not allowed in variables. | ||
| 384 | ;suhosin.request.disallow_nul = 1 | ||
| 385 | |||
| 386 | ; When set to On the dangerous characters <>"'` are urlencoded when found | ||
| 387 | ; not encoded in the server variables REQUEST_URI and QUERY_STRING. This | ||
| 388 | ; will protect against some XSS vulnerabilities. | ||
| 389 | ;suhosin.server.encode = 1 | ||
| 390 | |||
| 391 | ; When set to On the dangerous characters <>"'` are replaced with ? in | ||
| 392 | ; the server variables PHP_SELF, PATH_TRANSLATED and PATH_INFO. This will | ||
| 393 | ; protect against some XSS vulnerabilities. | ||
| 394 | ;suhosin.server.strip = 1 | ||
| 395 | |||
| 396 | ; Defines the maximum number of files that may be uploaded with one request. | ||
| 397 | ;suhosin.upload.max_uploads = 25 | ||
| 398 | |||
| 399 | ; When set to On it is not possible to upload ELF executables. | ||
| 400 | ;suhosin.upload.disallow_elf = 1 | ||
| 401 | |||
| 402 | ; When set to On it is not possible to upload binary files. | ||
| 403 | ;suhosin.upload.disallow_binary = 0 | ||
| 404 | |||
| 405 | ; When set to On binary content is removed from the uploaded files. | ||
| 406 | ;suhosin.upload.remove_binary = 0 | ||
| 407 | |||
| 408 | ; This defines the full path to a verification script for uploaded files. The | ||
| 409 | ; script gets the temporary filename supplied and has to decide if the upload | ||
| 410 | ; is allowed. A possible application for this is to scan uploaded files for | ||
| 411 | ; viruses. The called script has to write a 1 as first line to standard output | ||
| 412 | ; to allow the upload. Any other value or no output at all will result in the | ||
| 413 | ; file being deleted. | ||
| 414 | ;suhosin.upload.verification_script = | ||
| 415 | |||
| 416 | ; Specifies the maximum length of the session identifier that is allowed. When | ||
| 417 | ; a longer session identifier is passed a new session identifier will be | ||
| 418 | ; created. This feature is important to fight bufferoverflows in 3rd party | ||
| 419 | ; session handlers. | ||
| 420 | ;suhosin.session.max_id_length = 128 | ||
| 421 | |||
| 422 | ; Undocumented: Controls if suhosin coredumps when the optional suhosin patch | ||
| 423 | ; detects a bufferoverflow, memory corruption or double free. This is only | ||
| 424 | ; for debugging purposes and should not be activated. | ||
| 425 | ;suhosin.coredump = Off | ||
| 426 | |||
| 427 | ; Undocumented: Controls if the encryption keys specified by the configuration | ||
| 428 | ; are shown in the phpinfo() output or if they are hidden from it | ||
| 429 | ;suhosin.protectkey = 1 | ||
| 430 | |||
| 431 | ; Controls if suhosin loads in stealth mode when it is not the only | ||
| 432 | ; zend_extension (Required for full compatibility with certain encoders | ||
| 433 | ; that consider open source untrusted. e.g. ionCube, Zend) | ||
| 434 | ;suhosin.stealth = 1 | ||
| 435 | |||
| 436 | ; Controls if suhosin's ini directives are changeable per directory | ||
| 437 | ; because the admin might want to allow some features to be controlable | ||
| 438 | ; by .htaccess and some not. For example the logging capabilities can | ||
| 439 | ; break safemode and open_basedir restrictions when .htaccess support is | ||
| 440 | ; allowed and the admin forgot to fix their values in httpd.conf | ||
| 441 | ; An empty value or a 0 will result in all directives not allowed in | ||
| 442 | ; .htaccess. The string "legcprsum" will allow logging, execution, get, | ||
| 443 | ; post, cookie, request, sql, upload, misc features in .htaccess | ||
| 444 | ;suhosin.perdir = "0" | ||
diff --git a/suhosin_logo.h b/suhosin_logo.h new file mode 100644 index 0000000..455bd59 --- /dev/null +++ b/suhosin_logo.h | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | #define SUHOSIN_LOGO_GUID "SUHO8567F54-D428-14d2-A769-00DA302A5F18" | ||
| 2 | |||
| 3 | static unsigned char suhosin_logo[] = | ||
| 4 | "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48" | ||
| 5 | "\x00\x48\x00\x00\xff\xe1\x00\x16\x45\x78\x69\x66\x00\x00\x4d\x4d" | ||
| 6 | "\x00\x2a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\xff\xdb\x00\x43" | ||
| 7 | "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 8 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 9 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 10 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 11 | "\x01\xff\xc0\x00\x0b\x08\x00\x27\x00\x71\x01\x01\x22\x00\xff\xc4" | ||
| 12 | "\x00\x1e\x00\x00\x02\x02\x02\x03\x01\x01\x00\x00\x00\x00\x00\x00" | ||
| 13 | "\x00\x00\x00\x00\x09\x06\x08\x05\x07\x02\x03\x0a\x01\x04\xff\xc4" | ||
| 14 | "\x00\x32\x10\x00\x01\x04\x03\x00\x02\x00\x05\x01\x05\x09\x01\x00" | ||
| 15 | "\x00\x00\x00\x05\x02\x03\x04\x06\x01\x07\x08\x00\x09\x11\x12\x13" | ||
| 16 | "\x14\x21\x15\x0a\x16\x31\x56\x96\x17\x18\x19\x23\x32\x41\x58\x98" | ||
| 17 | "\xd4\xd6\xff\xda\x00\x08\x01\x01\x00\x00\x3f\x00\xf4\xc1\xe1\xe5" | ||
| 18 | "\x69\xe9\x3e\xb9\xd1\x7c\x8a\x2e\x9d\x66\xe8\x3b\x29\x4d\x7f\x46" | ||
| 19 | "\xba\x58\x55\x54\x8d\xb1\x5f\xaa\xd9\x8d\x51\x2b\xb6\x27\x5a\x69" | ||
| 20 | "\xd1\x43\xaf\x16\x1a\xf0\xb2\xb1\xe9\x6d\x9f\xc2\xa4\x36\x18\xb5" | ||
| 21 | "\x85\x10\x41\xbe\xfc\x09\xac\x49\x29\x11\xd4\x32\x97\xec\x08\x13" | ||
| 22 | "\xc1\x2d\x20\xc3\x59\xeb\x26\x05\xd8\x6b\x76\x31\x43\x8f\x57\xcf" | ||
| 23 | "\x84\x9f\x14\xa8\x53\x81\x0b\xc3\x64\x80\xa3\x02\x0a\x41\x75\xf8" | ||
| 24 | "\x44\x85\x93\x81\x22\x3c\xd8\x13\xe1\xbe\xf4\x59\x91\x1f\x6a\x44" | ||
| 25 | "\x77\x5c\x69\xc4\x2f\x39\x5f\x0f\x2a\x8d\xeb\xba\xf8\xc3\x56\x6c" | ||
| 26 | "\x3b\x36\xa7\xda\xbd\x4d\xa1\xb5\x4e\xc6\xa7\xa4\x3a\xec\x15\x2d" | ||
| 27 | "\xa5\xb3\xea\x5a\xdc\xac\x46\xac\x01\x60\xd8\x43\xc8\x8e\x8b\xb1" | ||
| 28 | "\x40\x4c\x95\x8b\x34\x41\x28\x52\x91\x28\x43\xd3\xa3\xb6\xa7\x55" | ||
| 29 | "\x15\xe7\x5a\x96\xcb\xf1\xda\xe5\x55\xee\xfe\x1e\xbd\xd9\x41\xd3" | ||
| 30 | "\x28\xfd\x97\xca\x57\x2b\x85\x9c\xa4\x30\x95\xaa\xa5\x57\xa2\x35" | ||
| 31 | "\x15\x86\xcb\x61\x34\x41\xe4\xc7\x80\x20\x18\x21\x17\x09\x85\x0b" | ||
| 32 | "\x14\x9d\x21\x68\x62\x1c\x08\x11\x64\x4b\x92\xf2\xd2\xd3\x2d\x2d" | ||
| 33 | "\x6a\xc2\x73\x6b\x3c\x3c\x8b\x9e\xbc\x52\xaa\xa4\xab\x81\x6c\xf6" | ||
| 34 | "\xfa\xbd\x70\xc5\xc6\x7b\xc2\xaa\x22\x4f\x58\x04\x87\x25\x6a\x27" | ||
| 35 | "\x1d\xa4\x3d\x20\x75\x72\x01\x09\x71\xe5\x1c\x9e\xc3\x2e\x36\xf3" | ||
| 36 | "\xd0\xc6\x35\x2a\x43\x4d\x2d\x0e\x2d\xb4\xa1\x49\xce\x65\x1e\x52" | ||
| 37 | "\x9e\xa1\xf6\x09\xcc\xdc\x63\x66\xa8\x01\xe9\x3b\x0d\xd7\x5a\x85" | ||
| 38 | "\xbb\xc5\x65\xc0\x7b\x2e\x46\xa9\xd9\x56\x1d\x4c\x92\x72\x26\x4e" | ||
| 39 | "\x86\xd5\x68\xae\xc4\xaa\x55\xce\xd7\x83\x59\xb3\x81\xee\xce\x74" | ||
| 40 | "\x39\x39\x31\x9f\x8a\x25\xe8\xa5\xa5\xe5\x81\xf2\x11\x23\xcb\xa1" | ||
| 41 | "\x1e\x43\x12\xe3\xb1\x2a\x2b\xcd\xc8\x8d\x25\x96\xa4\x47\x7d\x95" | ||
| 42 | "\xa5\xc6\x9f\x61\xe4\x25\xc6\x5e\x69\xc4\xe7\x29\x5b\x6e\xb6\xa4" | ||
| 43 | "\xad\x0b\x4e\x72\x95\x25\x58\x56\x33\x9c\x67\xce\xef\x0f\x17\xbf" | ||
| 44 | "\x4c\x7b\x2d\xe6\xfe\x76\x35\x27\x5a\x07\x97\x67\xe8\xae\x8d\x71" | ||
| 45 | "\x0f\xb2\x13\x99\xb9\xbc\x14\xad\xb3\xb7\xe6\x11\x6f\xe0\xda\x58" | ||
| 46 | "\xb1\x08\xac\xa6\x6c\x2d\x7f\x05\xb7\x56\xd2\xe6\xcf\xbb\x4d\x0c" | ||
| 47 | "\xe3\x50\xb2\xec\x91\xf0\x4a\xb8\xd6\x22\xb8\xa7\xf6\x67\xaf\xcf" | ||
| 48 | "\x63\x7e\xd7\xe7\x42\xd8\xbd\xc3\x71\xa1\xf2\x7e\x9b\xa8\x97\x83" | ||
| 49 | "\x6e\xd1\xdc\x4b\x06\x11\x2d\xae\x26\x61\x98\x72\x10\xf4\x42\x5d" | ||
| 50 | "\x20\x4a\xa3\x73\xd7\xf2\xcd\x3c\x48\x32\xe4\x03\x9f\x80\x37\x08" | ||
| 51 | "\x36\x11\xd0\xcb\x97\x6c\x08\xed\x6d\x33\x24\xa2\x1b\xb4\x77\xdf" | ||
| 52 | "\x61\x5d\x5f\xc1\x43\xc2\x82\xeb\x0f\x5d\x84\x08\x68\xaa\xa4\x01" | ||
| 53 | "\xe1\x19\xdf\xbc\x31\x65\xfe\xd1\xf5\x7d\x7a\xb2\x2a\x33\x50\x21" | ||
| 54 | "\x2a\x56\x9d\xb1\x81\xab\xdb\x35\x78\x30\x83\xd9\x89\x1d\x31\xac" | ||
| 55 | "\x96\x14\x07\x61\xbc\x20\x68\x42\x85\x33\x19\xac\xbe\xdb\x34\x56" | ||
| 56 | "\xf1\xd5\xfd\x29\xa9\x28\xdb\xcb\x4c\x5a\x23\xdc\xf5\x96\xc5\x10" | ||
| 57 | "\xa3\x35\x5b\x14\x68\xd3\x61\x62\x64\x76\x26\xcb\x17\x3e\x34\x98" | ||
| 58 | "\x04\xa3\xc4\x20\x38\x90\x92\xe3\xc8\x07\x2c\x36\x74\x66\x26\x0e" | ||
| 59 | "\x29\x02\x64\x29\x2d\x21\xe6\x16\x9c\x6b\xce\xa3\x89\xd9\x4f\xd3" | ||
| 60 | "\xc4\xbd\xc5\x87\x79\x9c\x65\xf6\x39\x45\x60\xe8\xce\x9e\xab\x6d" | ||
| 61 | "\x13\x15\x22\xe1\x5e\x4b\x38\x42\xc4\x1e\xd5\x76\xe0\xc5\xeb\x85" | ||
| 62 | "\x07\x2d\x0f\xb8\xb6\xa6\xd6\x6d\x71\x0d\xa2\x43\x4c\x25\xea\xfa" | ||
| 63 | "\xa1\xae\x4c\xe4\x7d\xbd\x76\xa9\xfb\x06\xc2\x83\x42\xeb\xad\xe7" | ||
| 64 | "\xe9\x5f\x68\x6f\xba\xfb\x2f\x07\xce\xb8\x13\xc1\x9b\xeb\xb0\x76" | ||
| 65 | "\x45\x57\x28\x7b\xea\xbe\x0f\xf4\x30\x7b\xa0\xed\xe4\x22\x93\x21" | ||
| 66 | "\xfc\xbc\xe0\xb9\x75\xc1\x4f\xfc\xef\xb6\xfa\xa1\xfc\x64\xa1\x4a" | ||
| 67 | "\x82\xc7\x33\xad\x75\xed\x82\xbd\x3d\xdb\xf7\xa8\xbe\x5e\xbb\x36" | ||
| 68 | "\x62\x04\x9a\x2e\xc5\xd9\x9e\x9c\x3a\x0b\x98\x0b\x57\xac\xf1\x24" | ||
| 69 | "\x62\x58\x83\x15\x5b\xa6\xf2\xda\x34\x70\x03\xce\x0f\x93\x1b\x12" | ||
| 70 | "\xc7\xce\x54\x87\x33\x15\xd6\x53\x25\x1f\x2a\x90\x87\x12\xe3\x78" | ||
| 71 | "\xef\x55\x77\x4d\x4a\xd8\x7e\xef\xd2\xfd\xd1\xaf\x3a\xaf\x55\xdb" | ||
| 72 | "\x6a\x2d\x3d\x42\xac\x51\x79\xee\x91\xab\xe1\x05\x2d\x3c\x80\xa2" | ||
| 73 | "\x43\xad\x22\x2e\xd5\x33\x13\xa4\x9e\x00\xe0\x04\x10\x84\xc8\xf2" | ||
| 74 | "\x19\x30\x92\x1f\xaa\xc3\x28\xc9\x76\x30\x3f\xe9\x10\x61\x5e\x79" | ||
| 75 | "\xd5\xf7\xdf\xd0\x54\xdb\xae\xb6\xae\xfa\xe8\xa3\x57\xe0\x6c\x2d" | ||
| 76 | "\xf7\xbd\x49\xd6\x6e\x76\x79\xcc\x54\x0c\x5f\xff\x00\xbb\x06\x98" | ||
| 77 | "\xa6\x9e\x89\x61\xb4\x6f\xc3\xe3\x6a\xc2\x4f\x59\x03\xc9\x80\x2c" | ||
| 78 | "\x59\x24\x44\x70\x38\xd5\x96\x6a\x9e\x8b\x81\x64\xe5\xbc\xa0\x3c" | ||
| 79 | "\x33\xaf\x17\x9d\xff\x00\x71\x1a\xd1\x3a\x80\x66\xb3\xd9\x31\x77" | ||
| 80 | "\x0d\x12\xbd\xae\x29\xb5\x6a\xd6\xcf\x8d\x68\x87\x75\xcd\xe8\x65" | ||
| 81 | "\x5a\xbe\x3c\x04\x7b\x34\xdb\x54\x19\xa4\x63\x9c\x2a\x5d\x23\xbe" | ||
| 82 | "\xf4\xb1\x1c\x4d\x90\xec\x92\x2f\x49\x71\xf7\x14\xf2\x97\x9f\x15" | ||
| 83 | "\x57\xed\x13\x21\x2a\xf5\x33\xd1\x2a\x52\x52\xac\xb7\x62\xd1\xcb" | ||
| 84 | "\x46\x73\x8c\x67\x28\x56\x77\x86\xbf\x6f\x2a\x4e\x73\xfe\x95\x65" | ||
| 85 | "\x0b\x5a\x3e\x38\xfc\xfc\xaa\x56\x3f\x86\x73\xe3\xb9\x4a\x52\x84" | ||
| 86 | "\xa5\x08\x4e\x12\x94\x27\x09\x4a\x53\x8c\x61\x29\x4a\x71\xf0\x4a" | ||
| 87 | "\x53\x8c\x7e\x31\x8c\x63\x18\xc6\x31\x8f\xc6\x31\xf8\xc7\x9f\x7c" | ||
| 88 | "\xd5\xbb\xae\x5e\xe2\x1f\xab\x6e\x24\x34\x00\x8a\x25\x83\x70\x40" | ||
| 89 | "\x1c\xcc\xda\x45\x7f\x66\x4e\x30\x2e\x94\x7e\x74\x49\xf0\xe4\x4e" | ||
| 90 | "\x06\x5c\xa8\x2f\x89\x21\x2e\x98\x0e\xd9\x21\xc2\x0b\x21\x0f\xc4" | ||
| 91 | "\x16\x6e\x48\xd9\xe4\xe3\x4a\x19\x1e\x64\x67\x54\xff\x00\x3a\x6d" | ||
| 92 | "\x4f\x62\xb5\x00\x4a\xaa\x51\xfd\x2d\xe8\x0e\x6c\xaf\xc6\x7d\x6d" | ||
| 93 | "\xc8\x88\xc7\x67\xea\x8a\x58\x02\x73\xe3\x65\x4d\xc9\x24\xc0\x3d" | ||
| 94 | "\x57\xa3\x2e\x53\x16\x99\x4f\xe5\xe7\x19\x97\x3e\x3b\xcf\xc9\x4b" | ||
| 95 | "\x99\x7f\x33\x25\xa5\xdf\xba\x77\x2b\xd3\x3e\xc2\x7b\x8b\x94\x07" | ||
| 96 | "\xe9\x52\x5b\x43\x87\x34\x14\x86\x37\xcf\x41\x6b\x8e\x6a\xa5\x22" | ||
| 97 | "\xab\xdb\x96\xa2\xcf\x46\xd8\x9b\x45\x93\xef\xd6\xdf\x3e\x99\x9c" | ||
| 98 | "\x7e\x29\x10\x6b\x6c\xa2\xb8\x43\x05\x09\x44\x70\x8c\xb8\xaa\x54" | ||
| 99 | "\x7c\x30\x36\x5e\x1c\x5e\x5b\x9f\x6c\x0d\x81\xee\xa0\x93\x8d\x67" | ||
| 100 | "\x55\xf3\x87\xaf\xaa\x6b\x58\xf9\xbe\xb2\x36\x07\x42\x6e\xbd\x96" | ||
| 101 | "\xe3\x9f\x1f\x8f\xc9\xf4\x9d\xae\x6a\x7d\x4c\x96\xbe\x5f\xc7\xcd" | ||
| 102 | "\xf3\xb2\xf7\xcd\xf0\xcf\xc3\xe4\xf8\xfe\x37\x4f\x1c\x4d\xf6\x40" | ||
| 103 | "\xf1\x6b\x7c\x4e\xe0\xa6\x71\xad\x56\xa7\x1c\x5c\x15\x6b\xfc\xf3" | ||
| 104 | "\x01\x5d\xac\xf1\x75\x9a\x72\x6b\xaa\x28\xc5\x88\x6d\xfb\x33\x85" | ||
| 105 | "\xe0\x4e\x61\xab\xeb\x31\x2c\x71\x08\x73\x11\x3b\xfc\xb5\xc0\x96" | ||
| 106 | "\xcc\x87\x24\x44\xb5\x9b\x9e\xb3\x71\xba\xe9\xed\xb1\x4e\xd7\x76" | ||
| 107 | "\x6c\xd2\xb6\x05\xb7\x5a\xde\xeb\x34\x5b\x96\x16\xfb\x59\xa9\x5c" | ||
| 108 | "\x4f\x55\xca\x8a\xac\x59\xb0\xe4\x54\x39\x25\xbc\x81\x37\x2a\x09" | ||
| 109 | "\x5f\x9e\x3b\x6b\x7d\x1f\x69\xf3\x34\x85\x39\x84\xa7\x28\x0b\xd3" | ||
| 110 | "\xfd\xfb\x4b\x7a\xea\xe7\xd2\x3c\xd3\xda\x15\x68\xbc\x73\xd3\x22" | ||
| 111 | "\x6f\xd7\x72\x5b\x2b\x66\xee\xa8\x0d\x54\xe8\x5b\xf9\x92\x96\x92" | ||
| 112 | "\x93\xea\x97\x4a\xc7\x43\x10\x46\x35\xc5\xc0\x60\x8a\xe4\xc1\xb5" | ||
| 113 | "\x36\xc6\xae\xed\xf7\x70\xa5\x86\x99\x3d\x91\xf8\xfd\x4e\x53\xeb" | ||
| 114 | "\xbb\xbd\x6d\xec\x8f\xd7\x89\x3d\x31\x7f\xd7\x78\xba\x50\xbb\x74" | ||
| 115 | "\x9d\xf6\xac\x4e\xb9\x03\x9c\x79\xd5\xe1\xbd\x17\x68\xd9\x13\x0b" | ||
| 116 | "\x45\x75\x88\x00\x1d\x1f\xae\x73\x6a\x1d\x5c\x6e\x44\x9f\xa6\xfa" | ||
| 117 | "\x4e\xd8\x25\x8b\xc0\xbc\xb2\x99\xe3\x17\x24\xb3\x23\xe2\x48\x8b" | ||
| 118 | "\xfa\x22\xe7\x7e\x8f\xe6\x3f\x5f\x55\x0d\x75\xd3\x51\x0b\xd7\xed" | ||
| 119 | "\xd3\x6f\x97\x3b\x85\x42\x80\x7e\x5f\xdc\x1b\xd6\xba\xee\xc4\x80" | ||
| 120 | "\xce\x06\xa9\x15\x8c\x97\x5f\x40\x69\xb2\x4d\xc5\xb2\x5c\x1e\x01" | ||
| 121 | "\x87\x7e\xe0\x36\x6d\x78\x80\x4e\x3c\x02\xec\x90\x1d\x11\x81\x74" | ||
| 122 | "\xa5\x8b\xa4\xa0\x56\x06\xd5\x79\x72\x85\x57\x3b\xb2\x2e\xae\x90" | ||
| 123 | "\x18\x8d\x91\xb2\x0e\x44\x19\xaa\xb4\xcc\x08\xed\x46\xfa\xd7\x2b" | ||
| 124 | "\x78\x58\x72\x5d\xbb\x5e\x49\xe7\xee\xf3\x8a\x9d\x22\xa4\x19\xc8" | ||
| 125 | "\xe7\x08\xc3\x90\x9b\x35\x9a\xa4\x25\x8c\x4b\x9b\xa7\xf8\xbf\x81" | ||
| 126 | "\xf5\xdf\x22\x66\xf1\x7e\x9f\x66\x3d\xbb\xfa\x73\x73\x4d\xfd\x67" | ||
| 127 | "\x7b\xf4\xce\xc3\x62\x2e\x6f\xbb\x0c\xa2\xdc\x69\xfc\x8a\x17\x0e" | ||
| 128 | "\x3a\x9e\x83\x46\xd7\xe3\x5e\x65\x86\xc0\x51\x00\xbb\x91\xe3\xe1" | ||
| 129 | "\xc1\x16\xc4\xe9\x65\x5c\x14\x3e\x44\x6a\x6b\xd1\x1e\xb0\x36\xdd" | ||
| 130 | "\x0b\x7d\x8a\xeb\xaf\x58\x5b\x64\x3f\x38\xed\x52\x76\xe8\x46\xf7" | ||
| 131 | "\x86\x84\xb3\x93\xb1\x0b\xe5\xfd\xfd\x0d\xe9\x6d\xe4\xf1\x1b\x1d" | ||
| 132 | "\x56\xb4\x34\xe4\x6a\xf5\xa4\x9c\x2c\xc9\x64\x94\xc1\xf5\x79\x6d" | ||
| 133 | "\x12\x96\xf3\x47\xc5\x48\xa8\xdb\xd8\x95\x64\x29\xcf\xf6\x88\xf1" | ||
| 134 | "\x95\x7a\x98\xe8\xbc\x27\x19\xce\x73\x61\xd1\xb8\xc6\x31\x8c\xe7" | ||
| 135 | "\x39\xce\x77\x9e\xbc\xc6\x31\x8c\x63\xf3\x9c\xe7\x39\xc6\x31\x8f" | ||
| 136 | "\xf7\xce\x7e\x1e\x3b\x7f\x0f\x0f\x0f\x13\x57\xb9\x0a\xe1\x0b\x64" | ||
| 137 | "\x5f\x58\x40\xc6\xc7\x7a\x4b\xf2\x3d\xbc\x71\xf4\xa7\xd2\xca\x14" | ||
| 138 | "\xe2\x98\x1a\x30\x1e\xe0\x26\x5a\x6a\xf0\x9c\x67\x38\x66\x00\xb8" | ||
| 139 | "\x72\xe6\xbe\xac\xfe\x12\xd3\x0b\x56\x73\x8c\x63\xc7\x2b\xe1\xe2" | ||
| 140 | "\xe8\xdd\x7b\xff\x00\xd8\xe5\x23\x6c\xce\xa8\x69\xcf\x5e\x3a\xef" | ||
| 141 | "\x77\xea\xe5\xab\x0e\x82\xdb\xd9\xed\x7a\x9e\xb8\x6d\x51\x32\xdb" | ||
| 142 | "\x79\xc3\x36\x9a\x2d\xa3\x50\x39\x65\x0a\x63\x0e\xe5\xd4\x39\x12" | ||
| 143 | "\xbf\x8b\x98\xa4\xa1\x2d\xad\xb3\xcf\x65\x6a\x43\x78\xb3\x3b\x07" | ||
| 144 | "\xd8\xd5\xea\xae\x76\xad\x6f\xf5\xff\x00\xca\x93\xab\x96\xb0\x64" | ||
| 145 | "\xeb\xd6\x4a\xd5\x87\xba\xec\x24\x60\x97\x06\x76\x03\xe3\x4c\x07" | ||
| 146 | "\x29\x11\x8e\x34\x25\x02\x64\x29\xf0\x25\x48\x85\x3a\x33\x8b\x7a" | ||
| 147 | "\x3c\x86\x1e\x75\xa5\x61\xc6\x97\x9f\x8d\x25\xf5\xc9\xcd\xde\xc9" | ||
| 148 | "\x7d\x77\xf2\xc8\x7e\x70\xaf\x73\x5f\x2d\xec\xa2\x51\x2d\x96\xfb" | ||
| 149 | "\x89\xad\x80\x57\xb2\x36\x1d\x7d\x83\x45\xac\xf3\xdb\xcc\x6c\x31" | ||
| 150 | "\x4f\xcf\x30\x58\xd0\x12\x28\x90\x50\x42\x86\xfb\x48\x16\x3c\xc5" | ||
| 151 | "\x9c\xf8\xe7\xcc\x29\x88\xb3\x4a\x4b\x4e\x6c\xbc\xdb\xc7\xbb\xe9" | ||
| 152 | "\xb6\xa0\x8b\x11\xa1\x7d\x73\xd7\xe9\xbf\x7e\xc2\x6c\x10\x8d\xee" | ||
| 153 | "\x9d\xef\x63\x3a\xe0\xf5\xbe\x8c\x3e\xa1\xc7\xc5\xd1\x00\x44\x1e" | ||
| 154 | "\xf3\x51\xf2\xe2\xb0\xe3\xb5\x13\x7f\x32\xf1\x8c\xa6\x22\xfe\x1f" | ||
| 155 | "\x49\x4d\xbb\xcf\x3a\x5d\xed\x4c\xd2\xfc\x85\xed\x23\xd6\xc7\x50" | ||
| 156 | "\xb6\x5b\x3a\x16\x83\xb8\x6f\xfd\x32\x3f\xaa\x36\x34\xbb\xf5\x96" | ||
| 157 | "\xa9\xab\xcf\x9f\x8f\xac\xc3\xca\xd5\x8b\xd8\x48\x9e\x79\xaa\x30" | ||
| 158 | "\x87\xca\x58\x4d\x59\x96\xb9\x4f\xc5\x1b\x1c\xd2\xda\x5b\xe6\x57" | ||
| 159 | "\x29\xa1\x28\x7a\x2b\x5b\xff\x00\x12\x2f\x5e\x3f\xf3\xbb\x8e\x7f" | ||
| 160 | "\xec\xc6\x98\xff\x00\xed\x3c\xa6\xdd\xa9\xdc\x7e\xa0\xf7\xd6\x99" | ||
| 161 | "\x31\xa2\xf7\xaf\x6b\xe9\x82\x74\x4b\x3d\x8f\x5e\x58\x0b\x33\xab" | ||
| 162 | "\xef\xc3\xaf\x84\x64\xb9\xae\xb6\x25\x5f\x62\x8f\x1c\xe3\xf4\x51" | ||
| 163 | "\xb7\x96\xe3\x0e\x30\x42\xa9\x18\x39\xbf\x9e\x2a\x1f\x74\x19\x02" | ||
| 164 | "\x2d\x43\x93\x06\x63\xb1\xa7\x47\x6a\xfa\x9b\x6c\xeb\xbd\xe9\xae" | ||
| 165 | "\x6a\x7b\x6f\x53\x5a\x60\x5d\xb5\xcd\xe8\x67\xeb\x35\x3b\x48\xc6" | ||
| 166 | "\xa6\xb3\x04\xc8\xdf\xb8\x7e\x26\x64\xb0\xc9\x18\xb0\xa7\x33\xf2" | ||
| 167 | "\x4a\x8b\x22\x3b\x8d\x4b\x89\x1d\xf6\x9d\x65\xc4\x38\xd2\x54\x9c" | ||
| 168 | "\xe3\xcd\x89\xe1\xe1\xe6\x3e\x70\x81\x45\x1d\x18\xf9\x31\x83\xc8" | ||
| 169 | "\xbe\x14\x82\x4b\x87\x7a\x74\x28\xd2\xdd\x12\x55\x30\xe6\x0e\x49" | ||
| 170 | "\x31\x8e\x48\x69\xc5\xc0\x20\x91\xe4\x48\x41\x4c\xd8\xb9\x6a\x4e" | ||
| 171 | "\x21\xce\x99\x1b\x0e\xfd\x09\x4f\xa1\x79\x0f\x0f\x0f\x0f\x0f\x0f" | ||
| 172 | "\x0f\x3f\x3c\xb8\x71\x27\xc7\x72\x24\xe8\xb1\xa6\xc5\x7b\x18\xc3" | ||
| 173 | "\xb1\xa5\xb0\xd4\x98\xee\xe3\x19\xc6\x71\x87\x19\x79\x2b\x6d\x78" | ||
| 174 | "\xc6\x71\x8c\xe3\x0a\x4e\x71\x8c\xe3\x19\xfe\x38\xf2\x3b\xfb\x8b" | ||
| 175 | "\x48\xfe\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe1\xfb\x8b\x48\xfe" | ||
| 176 | "\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe4\x95\x86\x18\x8a\xcb\x31" | ||
| 177 | "\xa3\x32\xd4\x78\xf1\xdb\x43\x2c\x47\x61\xb4\x32\xcb\x2c\xb4\x9c" | ||
| 178 | "\x21\xb6\x99\x69\xbc\x25\xb6\xdb\x6d\x18\xc2\x10\xda\x12\x94\xa1" | ||
| 179 | "\x38\xc2\x53\x8c\x63\x18\xc7\x9d\xbe\x7f\xff\xd9" | ||
| 180 | ; | ||
diff --git a/suhosin_rfc1867.h b/suhosin_rfc1867.h new file mode 100644 index 0000000..1ddaab3 --- /dev/null +++ b/suhosin_rfc1867.h | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* $Id: suhosin_rfc1867.h,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ */ | ||
| 21 | |||
| 22 | #ifndef SUHOSIN_RFC1867_H | ||
| 23 | #define SUHOSIN_RFC1867_H | ||
| 24 | |||
| 25 | #include "rfc1867.h" | ||
| 26 | #include "SAPI.h" | ||
| 27 | |||
| 28 | #define MULTIPART_CONTENT_TYPE "multipart/form-data" | ||
| 29 | #ifdef MULTIPART_EVENT_START | ||
| 30 | #define HAVE_RFC1867_CALLBACK 1 | ||
| 31 | #else | ||
| 32 | #define HAVE_RFC1867_CALLBACK 0 | ||
| 33 | |||
| 34 | #define MULTIPART_EVENT_START 0 | ||
| 35 | #define MULTIPART_EVENT_FORMDATA 1 | ||
| 36 | #define MULTIPART_EVENT_FILE_START 2 | ||
| 37 | #define MULTIPART_EVENT_FILE_DATA 3 | ||
| 38 | #define MULTIPART_EVENT_FILE_END 4 | ||
| 39 | #define MULTIPART_EVENT_END 5 | ||
| 40 | |||
| 41 | typedef struct _multipart_event_start { | ||
| 42 | size_t content_length; | ||
| 43 | } multipart_event_start; | ||
| 44 | |||
| 45 | typedef struct _multipart_event_formdata { | ||
| 46 | size_t post_bytes_processed; | ||
| 47 | char *name; | ||
| 48 | char **value; | ||
| 49 | size_t length; | ||
| 50 | size_t *newlength; | ||
| 51 | } multipart_event_formdata; | ||
| 52 | |||
| 53 | typedef struct _multipart_event_file_start { | ||
| 54 | size_t post_bytes_processed; | ||
| 55 | char *name; | ||
| 56 | char **filename; | ||
| 57 | } multipart_event_file_start; | ||
| 58 | |||
| 59 | typedef struct _multipart_event_file_data { | ||
| 60 | size_t post_bytes_processed; | ||
| 61 | off_t offset; | ||
| 62 | char *data; | ||
| 63 | size_t length; | ||
| 64 | size_t *newlength; | ||
| 65 | } multipart_event_file_data; | ||
| 66 | |||
| 67 | typedef struct _multipart_event_file_end { | ||
| 68 | size_t post_bytes_processed; | ||
| 69 | char *temp_filename; | ||
| 70 | int cancel_upload; | ||
| 71 | } multipart_event_file_end; | ||
| 72 | |||
| 73 | typedef struct _multipart_event_end { | ||
| 74 | size_t post_bytes_processed; | ||
| 75 | } multipart_event_end; | ||
| 76 | |||
| 77 | #endif | ||
| 78 | |||
| 79 | SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler); | ||
| 80 | |||
| 81 | void destroy_uploaded_files_hash(TSRMLS_D); | ||
| 82 | #if !HAVE_RFC1867_CALLBACK | ||
| 83 | extern PHP_SUHOSIN_API int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC); | ||
| 84 | #else | ||
| 85 | extern PHPAPI int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC); | ||
| 86 | #endif | ||
| 87 | |||
| 88 | #endif /* SUHOSIN_RFC1867_H */ | ||
diff --git a/tests/empty.inc b/tests/empty.inc new file mode 100644 index 0000000..35cbf45 --- /dev/null +++ b/tests/empty.inc | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | <?php | ||
| 2 | $value = "value-from-empty.inc"; | ||
| 3 | ?> \ No newline at end of file | ||
diff --git a/tests/executor/disable_emod_off.phpt b/tests/executor/disable_emod_off.phpt new file mode 100644 index 0000000..3c9cb01 --- /dev/null +++ b/tests/executor/disable_emod_off.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing: suhosin.executor.disable_emodifier=0 | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifnotcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=64 | ||
| 7 | suhosin.executor.disable_emodifier=0 | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | $text = "HALLO"; | ||
| 11 | var_dump(preg_replace('/[a-z]/e', "strtoupper('\\0')", $text)); | ||
| 12 | $text = "HalLO"; | ||
| 13 | var_dump(preg_replace('/[a-z]/e', "strtoupper('\\0')", $text)); | ||
| 14 | ?> | ||
| 15 | --EXPECTF-- | ||
| 16 | string(5) "HALLO" | ||
| 17 | string(5) "HALLO" | ||
| 18 | |||
diff --git a/tests/executor/disable_emod_on.phpt b/tests/executor/disable_emod_on.phpt new file mode 100644 index 0000000..6daf82f --- /dev/null +++ b/tests/executor/disable_emod_on.phpt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing: suhosin.executor.disable_emodifier=1 | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifnotcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=64 | ||
| 7 | suhosin.executor.disable_emodifier=1 | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | $text = "HALLO"; | ||
| 11 | var_dump(preg_replace('/[a-z]/e', "strtoupper('\\0')", $text)); | ||
| 12 | $text = "HalLO"; | ||
| 13 | var_dump(preg_replace('/[a-z]/e', "strtoupper('\\0')", $text)); | ||
| 14 | ?> | ||
| 15 | --EXPECTF-- | ||
| 16 | string(5) "HALLO" | ||
| 17 | ALERT - use of preg_replace() with /e modifier is forbidden by configuration (attacker 'REMOTE_ADDR not set', file '%s', line 5) | ||
| 18 | |||
| 19 | Fatal error: SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration in %s(5) : regexp code on line 5 | ||
diff --git a/tests/executor/disable_eval_off.phpt b/tests/executor/disable_eval_off.phpt new file mode 100644 index 0000000..1ee87f5 --- /dev/null +++ b/tests/executor/disable_eval_off.phpt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing: suhosin.executor.disable_eval=0 | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifnotcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=64 | ||
| 7 | suhosin.executor.disable_eval=0 | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | $x = 0; | ||
| 11 | eval('$x = 1;'); | ||
| 12 | var_dump($x); | ||
| 13 | ?> | ||
| 14 | --EXPECTF-- | ||
| 15 | int(1) | ||
diff --git a/tests/executor/disable_eval_on.phpt b/tests/executor/disable_eval_on.phpt new file mode 100644 index 0000000..49f4936 --- /dev/null +++ b/tests/executor/disable_eval_on.phpt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing: suhosin.executor.disable_eval=1 | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifnotcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=64 | ||
| 7 | suhosin.executor.disable_eval=1 | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | $x = 0; | ||
| 11 | eval('$x = 1;'); | ||
| 12 | var_dump($x); | ||
| 13 | ?> | ||
| 14 | --EXPECTF-- | ||
| 15 | ALERT - use of eval is forbidden by configuration (attacker 'REMOTE_ADDR not set', file '%s', line 3) | ||
| 16 | |||
| 17 | Fatal error: SUHOSIN - Use of eval is forbidden by configuration in %s(3) : eval()'d code on line 3 | ||
diff --git a/tests/executor/memory_limit.phpt b/tests/executor/memory_limit.phpt new file mode 100644 index 0000000..404ab19 --- /dev/null +++ b/tests/executor/memory_limit.phpt | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | --TEST-- | ||
| 2 | memory_limit test: set suhosin hard_limit to normal limit | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!function_exists("memory_get_usage")) print "skip PHP not compiled with memory_limit support"; ?> | ||
| 5 | --INI-- | ||
| 6 | memory_limit=16M | ||
| 7 | suhosin.memory_limit=0 | ||
| 8 | suhosin.log.syslog=0 | ||
| 9 | suhosin.log.script=0 | ||
| 10 | suhosin.log.sapi=2 | ||
| 11 | --FILE-- | ||
| 12 | <?php | ||
| 13 | ini_set("memory_limit", "13M"); echo ini_get("memory_limit"), "\n"; | ||
| 14 | ini_set("memory_limit", "14M"); echo ini_get("memory_limit"), "\n"; | ||
| 15 | ini_set("memory_limit", "15M"); echo ini_get("memory_limit"), "\n"; | ||
| 16 | ini_set("memory_limit", "16M"); echo ini_get("memory_limit"), "\n"; | ||
| 17 | ini_set("memory_limit", "17M"); echo ini_get("memory_limit"), "\n"; | ||
| 18 | ini_set("memory_limit", "18M"); echo ini_get("memory_limit"), "\n"; | ||
| 19 | ?> | ||
| 20 | --EXPECTF-- | ||
| 21 | 13M | ||
| 22 | 14M | ||
| 23 | 15M | ||
| 24 | 16M | ||
| 25 | ALERT - script tried to increase memory_limit to 17825792 bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 6) | ||
| 26 | 16M | ||
| 27 | ALERT - script tried to increase memory_limit to 18874368 bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 7) | ||
| 28 | 16M | ||
| 29 | |||
diff --git a/tests/executor/memory_limit_other_hardlimit.phpt b/tests/executor/memory_limit_other_hardlimit.phpt new file mode 100644 index 0000000..cac11dc --- /dev/null +++ b/tests/executor/memory_limit_other_hardlimit.phpt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | --TEST-- | ||
| 2 | memory_limit test: set suhosin hard_limit to normal limit + 1M | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!function_exists("memory_get_usage")) print "skip PHP not compiled with memory_limit support"; ?> | ||
| 5 | --INI-- | ||
| 6 | memory_limit=16M | ||
| 7 | suhosin.memory_limit=17M | ||
| 8 | suhosin.log.syslog=0 | ||
| 9 | suhosin.log.script=0 | ||
| 10 | suhosin.log.sapi=2 | ||
| 11 | --FILE-- | ||
| 12 | <?php | ||
| 13 | ini_set("memory_limit", "13M"); echo ini_get("memory_limit"), "\n"; | ||
| 14 | ini_set("memory_limit", "14M"); echo ini_get("memory_limit"), "\n"; | ||
| 15 | ini_set("memory_limit", "15M"); echo ini_get("memory_limit"), "\n"; | ||
| 16 | ini_set("memory_limit", "16M"); echo ini_get("memory_limit"), "\n"; | ||
| 17 | ini_set("memory_limit", "17M"); echo ini_get("memory_limit"), "\n"; | ||
| 18 | ini_set("memory_limit", "18M"); echo ini_get("memory_limit"), "\n"; | ||
| 19 | ?> | ||
| 20 | --EXPECTF-- | ||
| 21 | 13M | ||
| 22 | 14M | ||
| 23 | 15M | ||
| 24 | 16M | ||
| 25 | 17M | ||
| 26 | ALERT - script tried to increase memory_limit to %d bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 7) | ||
| 27 | 17M | ||
| 28 | |||
diff --git a/tests/executor/negative_memory_limit.phpt b/tests/executor/negative_memory_limit.phpt new file mode 100644 index 0000000..8582cc9 --- /dev/null +++ b/tests/executor/negative_memory_limit.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | memory_limit test: trying to set memory_limit to a negative value | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!function_exists("memory_get_usage")) print "skip PHP not compiled with memory_limit support"; ?> | ||
| 5 | --INI-- | ||
| 6 | memory_limit=16M | ||
| 7 | suhosin.memory_limit=17M | ||
| 8 | suhosin.log.syslog=0 | ||
| 9 | suhosin.log.script=0 | ||
| 10 | suhosin.log.sapi=2 | ||
| 11 | --FILE-- | ||
| 12 | <?php | ||
| 13 | ini_set("memory_limit", "-200000"); echo ini_get("memory_limit"), "\n"; | ||
| 14 | ?> | ||
| 15 | --EXPECTF-- | ||
| 16 | ALERT - script tried to increase memory_limit to %d bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 2) | ||
| 17 | 16M | ||
| 18 | |||
diff --git a/tests/executor/preg_replace.phpt b/tests/executor/preg_replace.phpt new file mode 100644 index 0000000..9060a29 --- /dev/null +++ b/tests/executor/preg_replace.phpt | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing protection against "\0" in preg_replace() first parameter | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipif.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=0 | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | |||
| 10 | $text1 = "One little boy with two dogs, three cats and four birds"; | ||
| 11 | $text2 = "The three cats eat the four birds"; | ||
| 12 | |||
| 13 | $regex_array = array("/one/", "/two/", "/three/"); | ||
| 14 | $regex_array0 = array("/one/\0", "/two/", "/three/"); | ||
| 15 | $replace_array = array("1", "2", "3"); | ||
| 16 | $regex = "/eat/"; | ||
| 17 | $regex0 = "/ea\0t/"; | ||
| 18 | $replace = "play with"; | ||
| 19 | |||
| 20 | var_dump(preg_replace($regex_array, $replace_array, $text1)); | ||
| 21 | var_dump(preg_replace($regex_array0, $replace_array, $text1)); | ||
| 22 | var_dump(preg_replace($regex, $replace, $text2)); | ||
| 23 | var_dump(preg_replace($regex0, $replace, $text2)); | ||
| 24 | |||
| 25 | ?> | ||
| 26 | --EXPECT-- | ||
| 27 | string(49) "One little boy with 2 dogs, 3 cats and four birds" | ||
| 28 | bool(false) | ||
| 29 | string(39) "The three cats play with the four birds" | ||
| 30 | bool(false) | ||
diff --git a/tests/executor/preg_replace_error.phpt b/tests/executor/preg_replace_error.phpt new file mode 100644 index 0000000..39e0aee --- /dev/null +++ b/tests/executor/preg_replace_error.phpt | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing protection against "\0" in preg_replace() first parameter (INCL. SUHOSIN ERROR MESSAGES) | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifnotcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=64 | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | |||
| 10 | $text1 = "One little boy with two dogs, three cats and four birds"; | ||
| 11 | $text2 = "The three cats eat the four birds"; | ||
| 12 | |||
| 13 | $regex_array = array("/one/", "/two/", "/three/"); | ||
| 14 | $regex_array0 = array("/one/\0", "/two/", "/three/"); | ||
| 15 | $replace_array = array("1", "2", "3"); | ||
| 16 | $regex = "/eat/"; | ||
| 17 | $regex0 = "/ea\0t/"; | ||
| 18 | $replace = "play with"; | ||
| 19 | |||
| 20 | var_dump(preg_replace($regex_array, $replace_array, $text1)); | ||
| 21 | var_dump(preg_replace($regex_array0, $replace_array, $text1)); | ||
| 22 | var_dump(preg_replace($regex, $replace, $text2)); | ||
| 23 | var_dump(preg_replace($regex0, $replace, $text2)); | ||
| 24 | |||
| 25 | ?> | ||
| 26 | --EXPECTF-- | ||
| 27 | string(49) "One little boy with 2 dogs, 3 cats and four birds" | ||
| 28 | ALERT - string termination attack on first preg_replace parameter detected (attacker 'REMOTE_ADDR not set', file '%s', line 14) | ||
| 29 | bool(false) | ||
| 30 | string(39) "The three cats play with the four birds" | ||
| 31 | ALERT - string termination attack on first preg_replace parameter detected (attacker 'REMOTE_ADDR not set', file '%s', line 16) | ||
| 32 | bool(false) | ||
diff --git a/tests/executor/recursion_maxdepth.phpt b/tests/executor/recursion_maxdepth.phpt new file mode 100644 index 0000000..31fe9c2 --- /dev/null +++ b/tests/executor/recursion_maxdepth.phpt | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing: suhosin.executor.max_depth | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifnotcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.sapi=64 | ||
| 7 | suhosin.executor.max_depth=13 | ||
| 8 | --FILE-- | ||
| 9 | <?php | ||
| 10 | function rec($level) | ||
| 11 | { | ||
| 12 | echo $level,"\n"; | ||
| 13 | rec(++$level); | ||
| 14 | } | ||
| 15 | |||
| 16 | rec(2); | ||
| 17 | ?> | ||
| 18 | --EXPECTF-- | ||
| 19 | 2 | ||
| 20 | 3 | ||
| 21 | 4 | ||
| 22 | 5 | ||
| 23 | 6 | ||
| 24 | 7 | ||
| 25 | 8 | ||
| 26 | 9 | ||
| 27 | 10 | ||
| 28 | 11 | ||
| 29 | 12 | ||
| 30 | 13 | ||
| 31 | ALERT - maximum execution depth reached - script terminated (attacker 'REMOTE_ADDR not set', file '%s', line 5) | ||
diff --git a/tests/filter/get_globals.phpt b/tests/filter/get_globals.phpt new file mode 100644 index 0000000..f16991b --- /dev/null +++ b/tests/filter/get_globals.phpt | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | --TEST-- | ||
| 2 | Testing: GLOBALS in GET | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=255 | ||
| 9 | suhosin.log.script.name=/tmp/xx | ||
| 10 | --GET-- | ||
| 11 | a=1&b=2&GLOBALS=123&c=3 | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | var_dump($_GET['a']); | ||
| 15 | var_dump($_GET['b']); | ||
| 16 | var_dump($_GET['c']); | ||
| 17 | if (!isset($_GET['GLOBALS'])) var_dump(5); | ||
| 18 | else var_dump(0); | ||
| 19 | ?> | ||
| 20 | --EXPECT-- | ||
| 21 | string(1) "1" | ||
| 22 | string(1) "2" | ||
| 23 | string(1) "3" | ||
| 24 | int(5) | ||
diff --git a/tests/funcs/crypt_blowfish.phpt b/tests/funcs/crypt_blowfish.phpt new file mode 100644 index 0000000..f48e411 --- /dev/null +++ b/tests/funcs/crypt_blowfish.phpt | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | --TEST-- | ||
| 2 | CRYPT_BLOWFISH support | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipif.inc"; ?> | ||
| 5 | --FILE-- | ||
| 6 | <?php | ||
| 7 | var_dump(CRYPT_BLOWFISH); | ||
| 8 | echo crypt('rasmuslerdorf', '$2a$07$rasmuslerd...........$') . "\n"; | ||
| 9 | ?> | ||
| 10 | --EXPECT-- | ||
| 11 | int(1) | ||
| 12 | $2a$07$rasmuslerd............nIdrcHdxcUxWomQX9j6kvERCFjTg7Ra | ||
| 13 | |||
diff --git a/tests/funcs/crypt_ext_des.phpt b/tests/funcs/crypt_ext_des.phpt new file mode 100644 index 0000000..4e2ba73 --- /dev/null +++ b/tests/funcs/crypt_ext_des.phpt | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | --TEST-- | ||
| 2 | CRYPT_EXT_DES support | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (CRYPT_EXT_DES == 0) print 'skip'; ?> | ||
| 5 | --FILE-- | ||
| 6 | <?php | ||
| 7 | echo crypt('rasmuslerdorf', '_J9..rasm') . "\n" | ||
| 8 | ?> | ||
| 9 | --EXPECT-- | ||
| 10 | _J9..rasmBYk8r9AiWNc | ||
| 11 | |||
| 12 | |||
diff --git a/tests/funcs/crypt_md5.phpt b/tests/funcs/crypt_md5.phpt new file mode 100644 index 0000000..fd39d20 --- /dev/null +++ b/tests/funcs/crypt_md5.phpt | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | --TEST-- | ||
| 2 | CRYPT_MD5 support | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (CRYPT_MD5 == 0) print 'skip'; ?> | ||
| 5 | --FILE-- | ||
| 6 | <?php | ||
| 7 | echo crypt('rasmuslerdorf', '$1$rasmusle$') . "\n" | ||
| 8 | ?> | ||
| 9 | --EXPECT-- | ||
| 10 | $1$rasmusle$rISCgZzpwk3UhDidwXvin0 | ||
| 11 | |||
diff --git a/tests/funcs/crypt_std_des.phpt b/tests/funcs/crypt_std_des.phpt new file mode 100644 index 0000000..926ec44 --- /dev/null +++ b/tests/funcs/crypt_std_des.phpt | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | --TEST-- | ||
| 2 | CRYPT_STD_DES support | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (CRYPT_STD_DES == 0) print 'skip'; ?> | ||
| 5 | --FILE-- | ||
| 6 | <?php | ||
| 7 | echo crypt('rasmuslerdorf', 'rl') . "\n" | ||
| 8 | ?> | ||
| 9 | --EXPECT-- | ||
| 10 | rl.3StKT.4T8M | ||
| 11 | |||
diff --git a/tests/funcs/sha256.phpt b/tests/funcs/sha256.phpt new file mode 100644 index 0000000..cb407b1 --- /dev/null +++ b/tests/funcs/sha256.phpt | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | --TEST-- | ||
| 2 | SHA256 support | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipif.inc"; ?> | ||
| 5 | --FILE-- | ||
| 6 | <?php | ||
| 7 | echo sha256("") , "\n"; | ||
| 8 | echo sha256("a"), "\n"; | ||
| 9 | echo sha256(pack("H*", "bd")), "\n"; | ||
| 10 | echo sha256(pack("H*", "5fd4")), "\n"; | ||
| 11 | echo sha256(pack("H*", "b0bd69")), "\n"; | ||
| 12 | echo sha256(pack("H*", "c98c8e55")), "\n"; | ||
| 13 | echo sha256(pack("H*", "81a723d966")), "\n"; | ||
| 14 | echo sha256(pack("H*", "c97a2db566e5")), "\n"; | ||
| 15 | echo sha256(pack("H*", "f53210aa6ed72e")), "\n"; | ||
| 16 | echo sha256(pack("H*", "0df1cd526b5a4edd")), "\n"; | ||
| 17 | echo sha256(pack("H*", "b80233e2c53ab32cc3")), "\n"; | ||
| 18 | echo sha256(pack("H*", "5d54ed5b52d879aeb5dd")), "\n"; | ||
| 19 | echo sha256(pack("H*", "df866ecb67ab00515f6247")), "\n"; | ||
| 20 | echo sha256(pack("H*", "0757de9485a2eaea51126077")), "\n"; | ||
| 21 | echo sha256(pack("H*", "7c66f5d443c11cfb39dd0aa715")), "\n"; | ||
| 22 | echo sha256(pack("H*", "329624fed35639fe54957b7d47a9")), "\n"; | ||
| 23 | ?> | ||
| 24 | --EXPECT-- | ||
| 25 | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 | ||
| 26 | ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb | ||
| 27 | 68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b | ||
| 28 | 7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788 | ||
| 29 | 4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803 | ||
| 30 | 7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504 | ||
| 31 | 7516fb8bb11350df2bf386bc3c33bd0f52cb4c67c6e4745e0488e62c2aea2605 | ||
| 32 | 0eb0281b27a4604709b0513b43ad29fdcff9a7a958554abc689d7fe35af703e4 | ||
| 33 | dee684641421d1ba5a65c71f986a117cbb3d619a052a0b3409306c629575c00f | ||
| 34 | 47f527210d6e8f940b5082fec01b7305908fa2b49ea3ae597c19a3986097153c | ||
| 35 | c60d239cc6da3ad31f4de0c2d58a73ccf3f9279e504fa60ad55a31dcf686f3ca | ||
| 36 | e0164d90dbfcf173bb88044fac596ccd03b8d247c79907aaa5701767fad7b576 | ||
| 37 | dc990ef3109a7bcf626199db9ab7801213ceb0ad2ee398963b5061e39c05c7b5 | ||
| 38 | c1c9a4daadcc8678835872c7f1f8824376ac7b412e1fc2285069b41afd51397e | ||
| 39 | 6840619417b4d8ecaa7902f8eaf2e82be2638dec97cb7e8fcc377007cc176718 | ||
| 40 | 0f5308ff22b828e18bd65afbc427e3c1a678962832519df5f2f803f68f55e10b | ||
diff --git a/tests/include/include_constant.phpt b/tests/include/include_constant.phpt new file mode 100644 index 0000000..180aa69 --- /dev/null +++ b/tests/include/include_constant.phpt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include "Constant URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | include "http://127.0.0.1/"; | ||
| 15 | ?> | ||
| 16 | --EXPECTF-- | ||
| 17 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 2) | ||
diff --git a/tests/include/include_etc_passwd.phpt b/tests/include/include_etc_passwd.phpt new file mode 100644 index 0000000..fb3c4e2 --- /dev/null +++ b/tests/include/include_etc_passwd.phpt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include "../../../../../../../../../../../etc/passwd"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | suhosin.executor.include.max_traversal=3 | ||
| 13 | --FILE-- | ||
| 14 | <?php | ||
| 15 | $var = dirname(__FILE__)."/../empty.inc"; | ||
| 16 | include $var; | ||
| 17 | echo $value,"\n"; | ||
| 18 | $var = dirname(__FILE__)."/../../../../../../../../../../../etc/passwd"; | ||
| 19 | include $var; | ||
| 20 | ?> | ||
| 21 | --EXPECTF-- | ||
| 22 | value-from-empty.inc | ||
| 23 | ALERT - Include filename ('%s../../../../../../../../../../../etc/passwd') contains too many '../' (attacker 'REMOTE_ADDR not set', file '%s', line 6) | ||
diff --git a/tests/include/include_once_constant.phpt b/tests/include/include_once_constant.phpt new file mode 100644 index 0000000..3faac33 --- /dev/null +++ b/tests/include/include_once_constant.phpt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include_once "Constant URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | include_once "http://127.0.0.1/"; | ||
| 15 | ?> | ||
| 16 | --EXPECTF-- | ||
| 17 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 2) | ||
diff --git a/tests/include/include_once_tmpvar.phpt b/tests/include/include_once_tmpvar.phpt new file mode 100644 index 0000000..1f94c5a --- /dev/null +++ b/tests/include/include_once_tmpvar.phpt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include_once "Temp Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | $app = "?"; | ||
| 16 | include_once $var.$app; | ||
| 17 | ?> | ||
| 18 | --EXPECTF-- | ||
| 19 | ALERT - Include filename ('http://127.0.0.1/?') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 4) | ||
diff --git a/tests/include/include_once_var.phpt b/tests/include/include_once_var.phpt new file mode 100644 index 0000000..bf38377 --- /dev/null +++ b/tests/include/include_once_var.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include_once "Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | include_once $var; | ||
| 16 | ?> | ||
| 17 | --EXPECTF-- | ||
| 18 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 3) | ||
diff --git a/tests/include/include_tmpvar.phpt b/tests/include/include_tmpvar.phpt new file mode 100644 index 0000000..8ad26d7 --- /dev/null +++ b/tests/include/include_tmpvar.phpt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include "Temp Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | $app = "?"; | ||
| 16 | include $var.$app; | ||
| 17 | ?> | ||
| 18 | --EXPECTF-- | ||
| 19 | ALERT - Include filename ('http://127.0.0.1/?') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 4) | ||
diff --git a/tests/include/include_var.phpt b/tests/include/include_var.phpt new file mode 100644 index 0000000..7431240 --- /dev/null +++ b/tests/include/include_var.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | Include "Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | include $var; | ||
| 16 | ?> | ||
| 17 | --EXPECTF-- | ||
| 18 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 3) | ||
diff --git a/tests/include/require_constant.phpt b/tests/include/require_constant.phpt new file mode 100644 index 0000000..6ee79fb --- /dev/null +++ b/tests/include/require_constant.phpt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | --TEST-- | ||
| 2 | Require "Constant URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | require "http://127.0.0.1/"; | ||
| 15 | ?> | ||
| 16 | --EXPECTF-- | ||
| 17 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 2) | ||
diff --git a/tests/include/require_once_constant.phpt b/tests/include/require_once_constant.phpt new file mode 100644 index 0000000..43c69c8 --- /dev/null +++ b/tests/include/require_once_constant.phpt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | --TEST-- | ||
| 2 | Require_once "Constant URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | require_once "http://127.0.0.1/"; | ||
| 15 | ?> | ||
| 16 | --EXPECTF-- | ||
| 17 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 2) | ||
diff --git a/tests/include/require_once_tmpvar.phpt b/tests/include/require_once_tmpvar.phpt new file mode 100644 index 0000000..2be24b2 --- /dev/null +++ b/tests/include/require_once_tmpvar.phpt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | --TEST-- | ||
| 2 | Require_once "Temp Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | $app = "?"; | ||
| 16 | require_once $var.$app; | ||
| 17 | ?> | ||
| 18 | --EXPECTF-- | ||
| 19 | ALERT - Include filename ('http://127.0.0.1/?') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 4) | ||
diff --git a/tests/include/require_once_var.phpt b/tests/include/require_once_var.phpt new file mode 100644 index 0000000..b3857f5 --- /dev/null +++ b/tests/include/require_once_var.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | Require_once "Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | require_once $var; | ||
| 16 | ?> | ||
| 17 | --EXPECTF-- | ||
| 18 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 3) | ||
diff --git a/tests/include/require_tmpvar.phpt b/tests/include/require_tmpvar.phpt new file mode 100644 index 0000000..d411067 --- /dev/null +++ b/tests/include/require_tmpvar.phpt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | --TEST-- | ||
| 2 | Require "Temp Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | $app = "?"; | ||
| 16 | require $var.$app; | ||
| 17 | ?> | ||
| 18 | --EXPECTF-- | ||
| 19 | ALERT - Include filename ('http://127.0.0.1/?') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 4) | ||
diff --git a/tests/include/require_var.phpt b/tests/include/require_var.phpt new file mode 100644 index 0000000..20468d4 --- /dev/null +++ b/tests/include/require_var.phpt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | --TEST-- | ||
| 2 | Require "Variable URL"; | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php include "../skipifcli.inc"; ?> | ||
| 5 | --INI-- | ||
| 6 | suhosin.log.syslog=0 | ||
| 7 | suhosin.log.sapi=255 | ||
| 8 | suhosin.log.script=0 | ||
| 9 | suhosin.log.phpscript=0 | ||
| 10 | suhosin.executor.include.whitelist= | ||
| 11 | suhosin.executor.include.blacklist= | ||
| 12 | --FILE-- | ||
| 13 | <?php | ||
| 14 | $var = "http://127.0.0.1/"; | ||
| 15 | require $var; | ||
| 16 | ?> | ||
| 17 | --EXPECTF-- | ||
| 18 | ALERT - Include filename ('http://127.0.0.1/') is an URL that is not allowed (attacker 'REMOTE_ADDR not set', file '%s', line 3) | ||
diff --git a/tests/skipif.inc b/tests/skipif.inc new file mode 100644 index 0000000..fd0598c --- /dev/null +++ b/tests/skipif.inc | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | <?php | ||
| 2 | if(!extension_loaded("suhosin")) | ||
| 3 | print "skip - SUHOSIN extension not available"; | ||
| 4 | ?> | ||
diff --git a/tests/skipifcli.inc b/tests/skipifcli.inc new file mode 100644 index 0000000..63b41ca --- /dev/null +++ b/tests/skipifcli.inc | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | <?php | ||
| 2 | if (php_sapi_name()=='cli') { | ||
| 3 | print 'skip - SAPI == cli'; | ||
| 4 | } else { | ||
| 5 | if(!extension_loaded("suhosin")) | ||
| 6 | print "skip - SUHOSIN extension not available"; | ||
| 7 | } | ||
| 8 | ?> | ||
diff --git a/tests/skipifnotcli.inc b/tests/skipifnotcli.inc new file mode 100644 index 0000000..823cb91 --- /dev/null +++ b/tests/skipifnotcli.inc | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | <?php | ||
| 2 | if (php_sapi_name()!='cli') { | ||
| 3 | print 'skip - SAPI != cli'; | ||
| 4 | } else { | ||
| 5 | if(!extension_loaded("suhosin")) | ||
| 6 | print "skip - SUHOSIN extension not available"; | ||
| 7 | } | ||
| 8 | ?> | ||
diff --git a/treat_data.c b/treat_data.c new file mode 100644 index 0000000..d4af286 --- /dev/null +++ b/treat_data.c | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: treat_data.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "php_suhosin.h" | ||
| 30 | #include "SAPI.h" | ||
| 31 | #include "php_variables.h" | ||
| 32 | #include "ext/standard/url.h" | ||
| 33 | |||
| 34 | SAPI_TREAT_DATA_FUNC(suhosin_treat_data) | ||
| 35 | { | ||
| 36 | char *res = NULL, *var, *val, *separator = NULL; | ||
| 37 | const char *c_var; | ||
| 38 | zval *array_ptr; | ||
| 39 | int free_buffer = 0; | ||
| 40 | char *strtok_buf = NULL; | ||
| 41 | |||
| 42 | /* Mark that we were not yet called */ | ||
| 43 | SUHOSIN_G(already_scanned) = 0; | ||
| 44 | |||
| 45 | switch (arg) { | ||
| 46 | case PARSE_POST: | ||
| 47 | case PARSE_GET: | ||
| 48 | case PARSE_COOKIE: | ||
| 49 | ALLOC_ZVAL(array_ptr); | ||
| 50 | array_init(array_ptr); | ||
| 51 | INIT_PZVAL(array_ptr); | ||
| 52 | switch (arg) { | ||
| 53 | case PARSE_POST: | ||
| 54 | if (PG(http_globals)[TRACK_VARS_POST]) { | ||
| 55 | zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]); | ||
| 56 | } | ||
| 57 | PG(http_globals)[TRACK_VARS_POST] = array_ptr; | ||
| 58 | |||
| 59 | if (SUHOSIN_G(max_request_variables) && (SUHOSIN_G(max_post_vars) == 0 || | ||
| 60 | SUHOSIN_G(max_request_variables) <= SUHOSIN_G(max_post_vars))) { | ||
| 61 | SUHOSIN_G(max_post_vars) = SUHOSIN_G(max_request_variables); | ||
| 62 | } | ||
| 63 | break; | ||
| 64 | case PARSE_GET: | ||
| 65 | if (PG(http_globals)[TRACK_VARS_GET]) { | ||
| 66 | zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]); | ||
| 67 | } | ||
| 68 | PG(http_globals)[TRACK_VARS_GET] = array_ptr; | ||
| 69 | if (SUHOSIN_G(max_request_variables) && (SUHOSIN_G(max_get_vars) == 0 || | ||
| 70 | SUHOSIN_G(max_request_variables) <= SUHOSIN_G(max_get_vars))) { | ||
| 71 | SUHOSIN_G(max_get_vars) = SUHOSIN_G(max_request_variables); | ||
| 72 | } | ||
| 73 | break; | ||
| 74 | case PARSE_COOKIE: | ||
| 75 | if (PG(http_globals)[TRACK_VARS_COOKIE]) { | ||
| 76 | zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]); | ||
| 77 | } | ||
| 78 | PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr; | ||
| 79 | if (SUHOSIN_G(max_request_variables) && (SUHOSIN_G(max_cookie_vars) == 0 || | ||
| 80 | SUHOSIN_G(max_request_variables) <= SUHOSIN_G(max_cookie_vars))) { | ||
| 81 | SUHOSIN_G(max_cookie_vars) = SUHOSIN_G(max_request_variables); | ||
| 82 | } | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | break; | ||
| 86 | default: | ||
| 87 | array_ptr = destArray; | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (arg == PARSE_POST) { | ||
| 92 | sapi_handle_post(array_ptr TSRMLS_CC); | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (arg == PARSE_GET) { /* GET data */ | ||
| 97 | c_var = SG(request_info).query_string; | ||
| 98 | if (c_var && *c_var) { | ||
| 99 | res = (char *) estrdup(c_var); | ||
| 100 | free_buffer = 1; | ||
| 101 | } else { | ||
| 102 | free_buffer = 0; | ||
| 103 | } | ||
| 104 | } else if (arg == PARSE_COOKIE) { /* Cookie data */ | ||
| 105 | c_var = SG(request_info).cookie_data; | ||
| 106 | if (c_var && *c_var) { | ||
| 107 | if (SUHOSIN_G(cookie_encrypt)) { | ||
| 108 | res = (char *) estrdup(suhosin_cookie_decryptor(TSRMLS_C)); | ||
| 109 | } else { | ||
| 110 | res = (char *) estrdup(c_var); | ||
| 111 | } | ||
| 112 | free_buffer = 1; | ||
| 113 | } else { | ||
| 114 | free_buffer = 0; | ||
| 115 | } | ||
| 116 | } else if (arg == PARSE_STRING) { /* String data */ | ||
| 117 | res = str; | ||
| 118 | free_buffer = 1; | ||
| 119 | } | ||
| 120 | |||
| 121 | if (!res) { | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | |||
| 125 | switch (arg) { | ||
| 126 | case PARSE_GET: | ||
| 127 | case PARSE_STRING: | ||
| 128 | separator = (char *) estrdup(PG(arg_separator).input); | ||
| 129 | break; | ||
| 130 | case PARSE_COOKIE: | ||
| 131 | separator = ";\0"; | ||
| 132 | break; | ||
| 133 | } | ||
| 134 | |||
| 135 | var = php_strtok_r(res, separator, &strtok_buf); | ||
| 136 | |||
| 137 | while (var) { | ||
| 138 | /* Overjump plain whitespace */ | ||
| 139 | while (*var && *var == ' ') var++; | ||
| 140 | |||
| 141 | val = strchr(var, '='); | ||
| 142 | if (val) { /* have a value */ | ||
| 143 | int val_len; | ||
| 144 | unsigned int new_val_len; | ||
| 145 | |||
| 146 | *val++ = '\0'; | ||
| 147 | php_url_decode(var, strlen(var)); | ||
| 148 | val_len = php_url_decode(val, strlen(val)); | ||
| 149 | val = estrndup(val, val_len); | ||
| 150 | if (suhosin_input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) { | ||
| 151 | #ifdef ZEND_ENGINE_2 | ||
| 152 | if (sapi_module.input_filter(arg, var, &val, new_val_len, &new_val_len TSRMLS_CC)) { | ||
| 153 | #endif | ||
| 154 | php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); | ||
| 155 | #ifdef ZEND_ENGINE_2 | ||
| 156 | } | ||
| 157 | #endif | ||
| 158 | } else { | ||
| 159 | SUHOSIN_G(abort_request) = 1; | ||
| 160 | } | ||
| 161 | efree(val); | ||
| 162 | } else { | ||
| 163 | int val_len; | ||
| 164 | unsigned int new_val_len; | ||
| 165 | |||
| 166 | php_url_decode(var, strlen(var)); | ||
| 167 | val_len = 0; | ||
| 168 | val = estrndup("", val_len); | ||
| 169 | if (suhosin_input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) { | ||
| 170 | #ifdef ZEND_ENGINE_2 | ||
| 171 | if (sapi_module.input_filter(arg, var, &val, new_val_len, &new_val_len TSRMLS_CC)) { | ||
| 172 | #endif | ||
| 173 | php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); | ||
| 174 | #ifdef ZEND_ENGINE_2 | ||
| 175 | } | ||
| 176 | #endif | ||
| 177 | } else { | ||
| 178 | SUHOSIN_G(abort_request) = 1; | ||
| 179 | } | ||
| 180 | efree(val); | ||
| 181 | } | ||
| 182 | var = php_strtok_r(NULL, separator, &strtok_buf); | ||
| 183 | } | ||
| 184 | |||
| 185 | if (arg != PARSE_COOKIE) { | ||
| 186 | efree(separator); | ||
| 187 | } | ||
| 188 | |||
| 189 | if (free_buffer) { | ||
| 190 | efree(res); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | |||
| 195 | void suhosin_hook_treat_data() | ||
| 196 | { | ||
| 197 | sapi_register_treat_data(suhosin_treat_data); | ||
| 198 | #ifdef ZEND_ENGINE_2 | ||
| 199 | if (old_input_filter == NULL) { | ||
| 200 | old_input_filter = sapi_module.input_filter; | ||
| 201 | } | ||
| 202 | sapi_module.input_filter = suhosin_input_filter_wrapper; | ||
| 203 | #endif | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | /* | ||
| 208 | * Local variables: | ||
| 209 | * tab-width: 4 | ||
| 210 | * c-basic-offset: 4 | ||
| 211 | * End: | ||
| 212 | * vim600: noet sw=4 ts=4 fdm=marker | ||
| 213 | * vim<600: noet sw=4 ts=4 | ||
| 214 | */ | ||
| 215 | |||
| 216 | |||
diff --git a/ufilter.c b/ufilter.c new file mode 100644 index 0000000..c2c64c2 --- /dev/null +++ b/ufilter.c | |||
| @@ -0,0 +1,367 @@ | |||
| 1 | /* | ||
| 2 | +----------------------------------------------------------------------+ | ||
| 3 | | Suhosin Version 1 | | ||
| 4 | +----------------------------------------------------------------------+ | ||
| 5 | | Copyright (c) 2006-2007 The Hardened-PHP Project | | ||
| 6 | | Copyright (c) 2007 SektionEins GmbH | | ||
| 7 | +----------------------------------------------------------------------+ | ||
| 8 | | This source file is subject to version 3.01 of the PHP license, | | ||
| 9 | | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | | available through the world-wide-web at the following url: | | ||
| 11 | | http://www.php.net/license/3_01.txt | | ||
| 12 | | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | | obtain it through the world-wide-web, please send a note to | | ||
| 14 | | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +----------------------------------------------------------------------+ | ||
| 16 | | Author: Stefan Esser <sesser@sektioneins.de> | | ||
| 17 | +----------------------------------------------------------------------+ | ||
| 18 | */ | ||
| 19 | /* | ||
| 20 | $Id: ufilter.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include "config.h" | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #include "php.h" | ||
| 28 | #include "php_ini.h" | ||
| 29 | #include "ext/standard/info.h" | ||
| 30 | #include "php_suhosin.h" | ||
| 31 | #include "php_variables.h" | ||
| 32 | #include "suhosin_rfc1867.h" | ||
| 33 | |||
| 34 | #if !HAVE_RFC1867_CALLBACK | ||
| 35 | PHP_SUHOSIN_API int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC) = NULL; | ||
| 36 | #endif | ||
| 37 | |||
| 38 | static int is_protected_varname(char *var, int var_len) | ||
| 39 | { | ||
| 40 | switch (var_len) { | ||
| 41 | case 18: | ||
| 42 | if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname2; | ||
| 43 | break; | ||
| 44 | case 17: | ||
| 45 | if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname2; | ||
| 46 | break; | ||
| 47 | case 16: | ||
| 48 | if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname2; | ||
| 49 | if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname2; | ||
| 50 | break; | ||
| 51 | case 15: | ||
| 52 | if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname2; | ||
| 53 | break; | ||
| 54 | case 14: | ||
| 55 | if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname2; | ||
| 56 | break; | ||
| 57 | case 13: | ||
| 58 | if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname2; | ||
| 59 | if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname2; | ||
| 60 | break; | ||
| 61 | case 8: | ||
| 62 | if (memcmp(var, "_SESSION", 8)==0) goto protected_varname2; | ||
| 63 | if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname2; | ||
| 64 | break; | ||
| 65 | case 7: | ||
| 66 | if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname2; | ||
| 67 | if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname2; | ||
| 68 | if (memcmp(var, "_SERVER", 7)==0) goto protected_varname2; | ||
| 69 | break; | ||
| 70 | case 6: | ||
| 71 | if (memcmp(var, "_FILES", 6)==0) goto protected_varname2; | ||
| 72 | break; | ||
| 73 | case 5: | ||
| 74 | if (memcmp(var, "_POST", 5)==0) goto protected_varname2; | ||
| 75 | break; | ||
| 76 | case 4: | ||
| 77 | if (memcmp(var, "_ENV", 4)==0) goto protected_varname2; | ||
| 78 | if (memcmp(var, "_GET", 4)==0) goto protected_varname2; | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | protected_varname2: | ||
| 84 | return 1; | ||
| 85 | } | ||
| 86 | |||
| 87 | /* {{{ SAPI_UPLOAD_VARNAME_FILTER_FUNC | ||
| 88 | */ | ||
| 89 | static int check_fileupload_varname(char *varname) | ||
| 90 | { | ||
| 91 | char *index, *prev_index = NULL, *var; | ||
| 92 | unsigned int var_len, total_len, depth = 0; | ||
| 93 | TSRMLS_FETCH(); | ||
| 94 | |||
| 95 | var = estrdup(varname); | ||
| 96 | |||
| 97 | /* Normalize the variable name */ | ||
| 98 | normalize_varname(var); | ||
| 99 | |||
| 100 | /* Find length of variable name */ | ||
| 101 | index = strchr(var, '['); | ||
| 102 | total_len = strlen(var); | ||
| 103 | var_len = index ? index-var : total_len; | ||
| 104 | |||
| 105 | /* Drop this variable if it exceeds the varname/total length limit */ | ||
| 106 | if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) { | ||
| 107 | suhosin_log(S_FILES, "configured request variable name length limit exceeded - dropped variable '%s'", var); | ||
| 108 | if (!SUHOSIN_G(simulation)) { | ||
| 109 | goto return_failure; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | if (SUHOSIN_G(max_totalname_length) && SUHOSIN_G(max_totalname_length) < total_len) { | ||
| 113 | suhosin_log(S_FILES, "configured request variable total name length limit exceeded - dropped variable '%s'", var); | ||
| 114 | if (!SUHOSIN_G(simulation)) { | ||
| 115 | goto return_failure; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | if (SUHOSIN_G(max_post_name_length) && SUHOSIN_G(max_post_name_length) < var_len) { | ||
| 119 | suhosin_log(S_FILES, "configured POST variable name length limit exceeded - dropped variable '%s'", var); | ||
| 120 | if (!SUHOSIN_G(simulation)) { | ||
| 121 | goto return_failure; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < var_len) { | ||
| 125 | suhosin_log(S_FILES, "configured POST variable total name length limit exceeded - dropped variable '%s'", var); | ||
| 126 | if (!SUHOSIN_G(simulation)) { | ||
| 127 | goto return_failure; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Find out array depth */ | ||
| 132 | while (index) { | ||
| 133 | unsigned int index_length; | ||
| 134 | |||
| 135 | depth++; | ||
| 136 | index = strchr(index+1, '['); | ||
| 137 | |||
| 138 | if (prev_index) { | ||
| 139 | index_length = index ? index - 1 - prev_index - 1: strlen(prev_index); | ||
| 140 | |||
| 141 | if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) { | ||
| 142 | suhosin_log(S_FILES, "configured request variable array index length limit exceeded - dropped variable '%s'", var); | ||
| 143 | if (!SUHOSIN_G(simulation)) { | ||
| 144 | goto return_failure; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) { | ||
| 148 | suhosin_log(S_FILES, "configured POST variable array index length limit exceeded - dropped variable '%s'", var); | ||
| 149 | if (!SUHOSIN_G(simulation)) { | ||
| 150 | goto return_failure; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | prev_index = index; | ||
| 154 | } | ||
| 155 | |||
| 156 | } | ||
| 157 | |||
| 158 | /* Drop this variable if it exceeds the array depth limit */ | ||
| 159 | if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) { | ||
| 160 | suhosin_log(S_FILES, "configured request variable array depth limit exceeded - dropped variable '%s'", var); | ||
| 161 | if (!SUHOSIN_G(simulation)) { | ||
| 162 | goto return_failure; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | if (SUHOSIN_G(max_post_array_depth) && SUHOSIN_G(max_post_array_depth) < depth) { | ||
| 166 | suhosin_log(S_FILES, "configured POST variable array depth limit exceeded - dropped variable '%s'", var); | ||
| 167 | if (!SUHOSIN_G(simulation)) { | ||
| 168 | goto return_failure; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | |||
| 173 | /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */ | ||
| 174 | /* This is to protect several silly scripts that do globalizing themself */ | ||
| 175 | |||
| 176 | if (is_protected_varname(var, var_len)) { | ||
| 177 | suhosin_log(S_FILES, "tried to register forbidden variable '%s' through FILE variables", var); | ||
| 178 | if (!SUHOSIN_G(simulation)) { | ||
| 179 | goto return_failure; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | efree(var); | ||
| 184 | return SUCCESS; | ||
| 185 | |||
| 186 | return_failure: | ||
| 187 | efree(var); | ||
| 188 | return FAILURE; | ||
| 189 | } | ||
| 190 | /* }}} */ | ||
| 191 | |||
| 192 | int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC) | ||
| 193 | { | ||
| 194 | int retval = SUCCESS; | ||
| 195 | |||
| 196 | SDEBUG("rfc1867_filter %u", event); | ||
| 197 | |||
| 198 | switch (event) { | ||
| 199 | case MULTIPART_EVENT_START: | ||
| 200 | case MULTIPART_EVENT_FORMDATA: | ||
| 201 | /* nothing todo */ | ||
| 202 | break; | ||
| 203 | |||
| 204 | case MULTIPART_EVENT_FILE_START: | ||
| 205 | { | ||
| 206 | multipart_event_file_start *mefs = (multipart_event_file_start *) event_data; | ||
| 207 | |||
| 208 | /* Drop if no more variables flag is set */ | ||
| 209 | if (SUHOSIN_G(no_more_uploads)) { | ||
| 210 | goto continue_with_failure; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Drop this fileupload if the limit is reached */ | ||
| 214 | if (SUHOSIN_G(upload_limit) && SUHOSIN_G(upload_limit) <= SUHOSIN_G(num_uploads)) { | ||
| 215 | suhosin_log(S_FILES, "configured fileupload limit exceeded - file dropped"); | ||
| 216 | if (!SUHOSIN_G(simulation)) { | ||
| 217 | SUHOSIN_G(no_more_uploads) = 1; | ||
| 218 | goto continue_with_failure; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 223 | if (check_fileupload_varname(mefs->name) == FAILURE) { | ||
| 224 | goto continue_with_failure; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | break; | ||
| 229 | |||
| 230 | case MULTIPART_EVENT_FILE_DATA: | ||
| 231 | |||
| 232 | if (SUHOSIN_G(upload_disallow_elf)) { | ||
| 233 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; | ||
| 234 | |||
| 235 | if (mefd->offset == 0 && mefd->length > 10) { | ||
| 236 | if (mefd->data[0] == 0x7F && mefd->data[1] == 'E' && mefd->data[2] == 'L' && mefd->data[3] == 'F') { | ||
| 237 | suhosin_log(S_FILES, "uploaded file is an ELF executable - file dropped"); | ||
| 238 | if (!SUHOSIN_G(simulation)) { | ||
| 239 | goto continue_with_failure; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | if (SUHOSIN_G(upload_disallow_binary)) { | ||
| 246 | |||
| 247 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; | ||
| 248 | size_t i; | ||
| 249 | |||
| 250 | for (i=0; i<mefd->length; i++) { | ||
| 251 | if (mefd->data[i] < 32 && !isspace(mefd->data[i])) { | ||
| 252 | suhosin_log(S_FILES, "uploaded file contains binary data - file dropped"); | ||
| 253 | if (!SUHOSIN_G(simulation)) { | ||
| 254 | goto continue_with_failure; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | if (SUHOSIN_G(upload_remove_binary)) { | ||
| 261 | |||
| 262 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; | ||
| 263 | size_t i, j; | ||
| 264 | |||
| 265 | for (i=0, j=0; i<mefd->length; i++) { | ||
| 266 | if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { | ||
| 267 | mefd->data[j++] = mefd->data[i]; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | SDEBUG("removing binary %u %u",i,j); | ||
| 271 | /* IMPORTANT FOR DAISY CHAINING */ | ||
| 272 | mefd->length = j; | ||
| 273 | if (mefd->newlength) { | ||
| 274 | *mefd->newlength = j; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | break; | ||
| 279 | |||
| 280 | case MULTIPART_EVENT_FILE_END: | ||
| 281 | |||
| 282 | if (SUHOSIN_G(upload_verification_script)) { | ||
| 283 | multipart_event_file_end *mefe = (multipart_event_file_end *) event_data; | ||
| 284 | char cmd[8192]; | ||
| 285 | FILE *in; | ||
| 286 | int first=1; | ||
| 287 | char *sname = SUHOSIN_G(upload_verification_script); | ||
| 288 | |||
| 289 | /* ignore files that will get deleted anyway */ | ||
| 290 | if (mefe->cancel_upload) { | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* ignore empty scriptnames */ | ||
| 295 | while (isspace(*sname)) ++sname; | ||
| 296 | if (*sname == 0) { | ||
| 297 | SUHOSIN_G(num_uploads)++; | ||
| 298 | break; | ||
| 299 | } | ||
| 300 | |||
| 301 | ap_php_snprintf(cmd, sizeof(cmd), "%s %s", sname, mefe->temp_filename); | ||
| 302 | |||
| 303 | if ((in=VCWD_POPEN(cmd, "r"))==NULL) { | ||
| 304 | suhosin_log(S_FILES, "unable to execute fileupload verification script %s - file dropped", sname); | ||
| 305 | if (!SUHOSIN_G(simulation)) { | ||
| 306 | goto continue_with_failure; | ||
| 307 | } else { | ||
| 308 | goto continue_with_next; | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | retval = FAILURE; | ||
| 313 | |||
| 314 | /* read and forget the result */ | ||
| 315 | while (1) { | ||
| 316 | int readbytes = fread(cmd, 1, sizeof(cmd), in); | ||
| 317 | if (readbytes<=0) { | ||
| 318 | break; | ||
| 319 | } | ||
| 320 | if (first) { | ||
| 321 | retval = atoi(cmd) == 1 ? SUCCESS : FAILURE; | ||
| 322 | first = 0; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | pclose(in); | ||
| 326 | } | ||
| 327 | |||
| 328 | if (retval != SUCCESS) { | ||
| 329 | suhosin_log(S_FILES, "fileupload verification script disallows file - file dropped"); | ||
| 330 | if (!SUHOSIN_G(simulation)) { | ||
| 331 | goto continue_with_failure; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | SUHOSIN_G(num_uploads)++; | ||
| 336 | break; | ||
| 337 | |||
| 338 | case MULTIPART_EVENT_END: | ||
| 339 | /* nothing todo */ | ||
| 340 | break; | ||
| 341 | |||
| 342 | default: | ||
| 343 | /* unknown: return failure */ | ||
| 344 | goto continue_with_failure; | ||
| 345 | } | ||
| 346 | continue_with_next: | ||
| 347 | #if HAVE_RFC1867_CALLBACK | ||
| 348 | if (php_rfc1867_callback != NULL) { | ||
| 349 | return php_rfc1867_callback(event, event_data, extra TSRMLS_CC); | ||
| 350 | } | ||
| 351 | #endif | ||
| 352 | return SUCCESS; | ||
| 353 | continue_with_failure: | ||
| 354 | SUHOSIN_G(abort_request) = 1; | ||
| 355 | return FAILURE; | ||
| 356 | } | ||
| 357 | |||
| 358 | |||
| 359 | |||
| 360 | /* | ||
| 361 | * Local variables: | ||
| 362 | * tab-width: 4 | ||
| 363 | * c-basic-offset: 4 | ||
| 364 | * End: | ||
| 365 | * vim600: sw=4 ts=4 fdm=marker | ||
| 366 | * vim<600: sw=4 ts=4 | ||
| 367 | */ | ||
