summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS2
-rw-r--r--Changelog223
-rw-r--r--aes.c382
-rw-r--r--compat_snprintf.c1001
-rw-r--r--config.m49
-rw-r--r--config.w3211
-rw-r--r--crypt.c214
-rw-r--r--crypt_blowfish.c751
-rw-r--r--crypt_md5.c163
-rw-r--r--crypt_md5.h37
-rw-r--r--crypt_win32.c355
-rw-r--r--crypt_win32.h60
-rw-r--r--ex_imp.c450
-rw-r--r--execute.c1750
-rw-r--r--header.c353
-rw-r--r--ifilter.c732
-rw-r--r--log.c404
-rw-r--r--mbregex.h26
-rw-r--r--mbregex/COPYING.LIB515
-rw-r--r--mbregex/mbregex.h213
-rw-r--r--memory_limit.c90
-rw-r--r--php_suhosin.h420
-rw-r--r--post_handler.c114
-rw-r--r--rfc1867.c1355
-rw-r--r--session.c714
-rw-r--r--sha256.c432
-rw-r--r--sha256.h38
-rw-r--r--suhosin.c1248
-rw-r--r--suhosin.ini444
-rw-r--r--suhosin_logo.h180
-rw-r--r--suhosin_rfc1867.h88
-rw-r--r--tests/empty.inc3
-rw-r--r--tests/executor/disable_emod_off.phpt18
-rw-r--r--tests/executor/disable_emod_on.phpt19
-rw-r--r--tests/executor/disable_eval_off.phpt15
-rw-r--r--tests/executor/disable_eval_on.phpt17
-rw-r--r--tests/executor/memory_limit.phpt29
-rw-r--r--tests/executor/memory_limit_other_hardlimit.phpt28
-rw-r--r--tests/executor/negative_memory_limit.phpt18
-rw-r--r--tests/executor/preg_replace.phpt30
-rw-r--r--tests/executor/preg_replace_error.phpt32
-rw-r--r--tests/executor/recursion_maxdepth.phpt31
-rw-r--r--tests/filter/get_globals.phpt24
-rw-r--r--tests/funcs/crypt_blowfish.phpt13
-rw-r--r--tests/funcs/crypt_ext_des.phpt12
-rw-r--r--tests/funcs/crypt_md5.phpt11
-rw-r--r--tests/funcs/crypt_std_des.phpt11
-rw-r--r--tests/funcs/sha256.phpt40
-rw-r--r--tests/include/include_constant.phpt17
-rw-r--r--tests/include/include_etc_passwd.phpt23
-rw-r--r--tests/include/include_once_constant.phpt17
-rw-r--r--tests/include/include_once_tmpvar.phpt19
-rw-r--r--tests/include/include_once_var.phpt18
-rw-r--r--tests/include/include_tmpvar.phpt19
-rw-r--r--tests/include/include_var.phpt18
-rw-r--r--tests/include/require_constant.phpt17
-rw-r--r--tests/include/require_once_constant.phpt17
-rw-r--r--tests/include/require_once_tmpvar.phpt19
-rw-r--r--tests/include/require_once_var.phpt18
-rw-r--r--tests/include/require_tmpvar.phpt19
-rw-r--r--tests/include/require_var.phpt18
-rw-r--r--tests/skipif.inc4
-rw-r--r--tests/skipifcli.inc8
-rw-r--r--tests/skipifnotcli.inc8
-rw-r--r--treat_data.c216
-rw-r--r--ufilter.c367
66 files changed, 13967 insertions, 0 deletions
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 0000000..db77681
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,2 @@
1suhosin
2Stefan Esser
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..eb90e44
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,223 @@
12009-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
72009-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
152008-08-23 - 0.9.27
16
17 - Fixed typo in replacement rand() / mt_rand() that was hidden by LAZY symbol loading
18
192008-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
292008-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
352008-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
402008-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
452007-12-01 - 0.9.22
46
47 - Removed LFS warning message because it crashed on several systems
48
492007-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
592007-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
692007-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
812007-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
862007-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
992006-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
1112006-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
1172006-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
1252006-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
1312006-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
1382006-11-06 - 0.9.11
139
140 - Fixed input filter for simulation mode
141
1422006-10-26 - 0.9.10
143
144 - Fixed ZTS compile problem in new code
145 - Fixed PHP4 compile problem in new code
146
1472006-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
1592006-10-08 - 0.9.8
160
161 - Fixed a PHP4 ZTS compile problem
162
1632006-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
1732006-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
1782006-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
1832006-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
1912006-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
1972006-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
2032006-09-16 - 0.9.1
204
205 - A bunch of changes to compile and work on Windows
206
2072006-09-09 - BETA
208
209 - Added decryption of HTTP_COOKIE
210 - Fixed a last problem in suhosin_strcasestr() helper function
211
2122006-09-08 - BETA
213
214 - Fixed a problem within suhosin_strcasestr() because it broke
215 URL checks
216
2172006-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
diff --git a/aes.c b/aes.c
new file mode 100644
index 0000000..f8804da
--- /dev/null
+++ b/aes.c
@@ -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
48static BYTE InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
49
50static BYTE fbsub[256];
51static BYTE rbsub[256];
52static BYTE ptab[256],ltab[256];
53static WORD ftable[256];
54static WORD rtable[256];
55static WORD rco[30];
56
57/* Parameter-dependent data */
58
59static int Nk,Nb,Nr;
60
61static 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
66static 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
74static 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
84static 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
90static 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
101static 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
109static 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
126static 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
137void 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
184void 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
256void 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
303void 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/*
351static 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 */
112char *
113ap_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 */
168char *
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 */
261char *
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
294char *
295ap_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
383char *
384ap_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
389char *
390ap_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
400char *
401ap_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 */
479struct buf_area {
480 char *buf_end;
481 char *nextb; /* pointer to next byte to read/write */
482};
483
484typedef 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 */
551static 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 */
942static 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
972int 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
984int 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 @@
1dnl $Id: config.m4,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $
2dnl config.m4 for extension suhosin
3
4PHP_ARG_ENABLE(suhosin, whether to enable suhosin support,
5[ --enable-suhosin Enable suhosin support])
6
7if 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)
9fi
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
4ARG_ENABLE("suhosin", "whether to enable suhosin support", "yes");
5
6if (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}
diff --git a/crypt.c b/crypt.c
new file mode 100644
index 0000000..72a34c8
--- /dev/null
+++ b/crypt.c
@@ -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>
51extern 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
64static MUTEX_T suhosin_crypt_mutex;
65#endif
66
67static int CRYPT_MD5 = 0;
68
69char *suhosin_crypt_blowfish_rn(char *key, char *setting, char *output, int size);
70char *suhosin_crypt_gensalt_blowfish_rn(unsigned long count, char *input, int size, char *output, int output_size);
71
72static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
73
74static 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 */
84static 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 */
146static function_entry suhosin_crypt_functions[] = {
147 PHP_NAMED_FE(crypt, PHP_FN(suhosin_crypt), NULL)
148 {NULL, NULL, NULL}
149};
150/* }}} */
151
152
153void 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
61typedef unsigned int BF_word;
62
63/* Number of Blowfish rounds, this is also hardcoded into a few places */
64#define BF_N 16
65
66typedef BF_word BF_key[BF_N + 2];
67
68typedef 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 */
77static 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 */
85static 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
357static unsigned char BF_itoa64[64 + 1] =
358 "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
359
360static 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 */
372static 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
393static 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
420static 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
452static 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
554static 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
574char *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
727char *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
39static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
40 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
41
42static void to64(char *, php_uint32, int);
43
44static void
45to64(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 */
57char *
58md5_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
24extern "C"
25{
26#endif
27
28#define MD5_MAGIC "$1$"
29#define MD5_MAGIC_LEN 3
30
31char *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
53static char schluessel[16][KS];
54
55
56static 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
69static 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
80static 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
93static 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
106static 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
117static char E[KS];
118
119
120static 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
129static 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
181static void
182perm (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
191static void
192crypt_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
217void
218encrypt (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
243void
244setkey (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
274char *
275des_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
347char *
348crypt (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
46extern "C"
47{
48#endif
49
50#include <_ansi.h>
51
52void _EXFUN(encrypt, (char *block, int edflag));
53void _EXFUN(setkey, (char *key));
54char * _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
44static 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 */
96PHP_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
275static 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 */
351PHP_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 */
414function_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
422void 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
40static void (*old_execute)(zend_op_array *op_array TSRMLS_DC);
41static void suhosin_execute(zend_op_array *op_array TSRMLS_DC);
42static void (*old_execute_ZO)(zend_op_array *op_array, long dummy TSRMLS_DC);
43static void suhosin_execute_ZO(zend_op_array *op_array, long dummy TSRMLS_DC);
44static 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
49static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
50static void (*old_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
51
52extern zend_extension suhosin_zend_extension_entry;
53
54/* {{{ suhosin_strcasestr */
55static char *suhosin_strcasestr(char *haystack, char *needle)
56{
57 unsigned char *t, *h, *n;
58 h = (unsigned char *) haystack;
59conts:
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
92static 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
133SDEBUG("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
238static int (*old_zend_stream_open)(const char *filename, zend_file_handle *fh TSRMLS_DC);
239#else
240static zend_bool (*old_zend_open)(const char *filename, zend_file_handle *fh);
241#endif
242
243#ifdef ZEND_ENGINE_2
244static int suhosin_zend_stream_open(const char *filename, zend_file_handle *fh TSRMLS_DC)
245{
246 zend_execute_data *exd;
247#else
248static 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
302static 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 */
356static 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 }
485not_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
579continue_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 */
593static 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 */
600static 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
611HashTable ihandler_table;
612
613typedef 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
623int 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, &regex, &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 **)&regex_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
668int 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
685int 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
789int 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
949int 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
1023static 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
1040static 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
1068static 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 */
1198static 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
1217static 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 */
1240static 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 */
1260static 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 */
1273static 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 */
1295static 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 */
1327static 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 */
1342static 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 */
1358static 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 */
1371static 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
1391static 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
1410static 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
1429static 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
1452static 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
1475static 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
1487internal_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 */
1549static 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;
1632execute_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 */
1644static 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 */
1663void 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 */
1715void 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
35static int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) = NULL;
36
37char *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)) {
57encrypt_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
90char *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)) {
111decrypt_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);
150skip_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 */
162char *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 */
224int 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 */
325void 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 */
336void 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
34static 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 */
59void 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
118static unsigned char suhosin_hexchars[] = "0123456789ABCDEF";
119
120static 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 */
141static 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 */
162static 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 */
206void 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 */
282unsigned 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 */
313unsigned 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;
699protected_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 */
713void 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
diff --git a/log.c b/log.c
new file mode 100644
index 0000000..d5e3b50
--- /dev/null
+++ b/log.c
@@ -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
52static HANDLE log_source = 0;
53#endif
54
55
56static 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
82static char *month_names[] = {
83 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
84 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
85};
86
87PHP_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
227log_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
260log_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 }
313log_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);
324SDEBUG("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
17freedom to share and change it. By contrast, the GNU General Public
18Licenses are intended to guarantee your freedom to share and change
19free software--to make sure the software is free for all its users.
20
21 This license, the Lesser General Public License, applies to some
22specially designated software packages--typically libraries--of the
23Free Software Foundation and other authors who decide to use it. You
24can use it too, but we suggest you first think carefully about whether
25this license or the ordinary General Public License is the better
26strategy to use in any particular case, based on the explanations
27below.
28
29 When we speak of free software, we are referring to freedom of use,
30not price. Our General Public Licenses are designed to make sure that
31you have the freedom to distribute copies of free software (and charge
32for this service if you wish); that you receive source code or can get
33it if you want it; that you can change the software and use pieces of
34it in new free programs; and that you are informed that you can do
35these things.
36
37 To protect your rights, we need to make restrictions that forbid
38distributors to deny you these rights or to ask you to surrender these
39rights. These restrictions translate to certain responsibilities for
40you 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
43or for a fee, you must give the recipients all the rights that we gave
44you. You must make sure that they, too, receive or can get the source
45code. If you link other code with the library, you must provide
46complete object files to the recipients, so that they can relink them
47with the library after making changes to the library and recompiling
48it. 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
51library, and (2) we offer you this license, which gives you legal
52permission to copy, distribute and/or modify the library.
53
54 To protect each distributor, we want to make it very clear that
55there is no warranty for the free library. Also, if the library is
56modified by someone else and passed on, the recipients should know
57that what they have is not the original version, so that the original
58author's reputation will not be affected by problems that might be
59introduced by others.
60^L
61 Finally, software patents pose a constant threat to the existence of
62any free program. We wish to make sure that a company cannot
63effectively restrict the users of a free program by obtaining a
64restrictive license from a patent holder. Therefore, we insist that
65any patent license obtained for a version of the library must be
66consistent with the full freedom of use specified in this license.
67
68 Most GNU software, including some libraries, is covered by the
69ordinary GNU General Public License. This license, the GNU Lesser
70General Public License, applies to certain designated libraries, and
71is quite different from the ordinary General Public License. We use
72this license for certain libraries in order to permit linking those
73libraries into non-free programs.
74
75 When a program is linked with a library, whether statically or using
76a shared library, the combination of the two is legally speaking a
77combined work, a derivative of the original library. The ordinary
78General Public License therefore permits such linking only if the
79entire combination fits its criteria of freedom. The Lesser General
80Public License permits more lax criteria for linking other code with
81the library.
82
83 We call this license the "Lesser" General Public License because it
84does Less to protect the user's freedom than the ordinary General
85Public License. It also provides other free software developers Less
86of an advantage over competing non-free programs. These disadvantages
87are the reason we use the ordinary General Public License for many
88libraries. However, the Lesser license provides advantages in certain
89special circumstances.
90
91 For example, on rare occasions, there may be a special need to
92encourage the widest possible use of a certain library, so that it
93becomes
94a de-facto standard. To achieve this, non-free programs must be
95allowed to use the library. A more frequent case is that a free
96library does the same job as widely used non-free libraries. In this
97case, there is little to gain by limiting the free library to free
98software only, so we use the Lesser General Public License.
99
100 In other cases, permission to use a particular library in non-free
101programs enables a greater number of people to use a large body of
102free software. For example, permission to use the GNU C Library in
103non-free programs enables many more people to use the whole GNU
104operating system, as well as its variant, the GNU/Linux operating
105system.
106
107 Although the Lesser General Public License is Less protective of the
108users' freedom, it does ensure that the user of a program that is
109linked with the Library has the freedom and the wherewithal to run
110that program using a modified version of the Library.
111
112 The precise terms and conditions for copying, distribution and
113modification follow. Pay close attention to the difference between a
114"work based on the library" and a "work that uses the library". The
115former contains code derived from the library, whereas the latter must
116be 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
122program which contains a notice placed by the copyright holder or
123other authorized party saying it may be distributed under the terms of
124this Lesser General Public License (also called "this License").
125Each licensee is addressed as "you".
126
127 A "library" means a collection of software functions and/or data
128prepared 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
132which has been distributed under these terms. A "work based on the
133Library" means either the Library or any derivative work under
134copyright law: that is to say, a work containing the Library or a
135portion of it, either verbatim or with modifications and/or translated
136straightforwardly into another language. (Hereinafter, translation is
137included without limitation in the term "modification".)
138
139 "Source code" for a work means the preferred form of the work for
140making modifications to it. For a library, complete source code means
141all the source code for all modules it contains, plus any associated
142interface definition files, plus the scripts used to control
143compilation
144and installation of the library.
145
146 Activities other than copying, distribution and modification are not
147covered by this License; they are outside its scope. The act of
148running a program using the Library is not restricted, and output from
149such a program is covered only if its contents constitute a work based
150on the Library (independent of the use of the Library in a tool for
151writing it). Whether that is true depends on what the Library does
152and what the program that uses the Library does.
153
154 1. You may copy and distribute verbatim copies of the Library's
155complete source code as you receive it, in any medium, provided that
156you conspicuously and appropriately publish on each copy an
157appropriate copyright notice and disclaimer of warranty; keep intact
158all the notices that refer to this License and to the absence of any
159warranty; and distribute a copy of this License along with the
160Library.
161
162 You may charge a fee for the physical act of transferring a copy,
163and you may at your option offer warranty protection in exchange for a
164fee.
165
166 2. You may modify your copy or copies of the Library or any portion
167of it, thus forming a work based on the Library, and copy and
168distribute such modifications or work under the terms of Section 1
169above, 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
194These requirements apply to the modified work as a whole. If
195identifiable sections of that work are not derived from the Library,
196and can be reasonably considered independent and separate works in
197themselves, then this License, and its terms, do not apply to those
198sections when you distribute them as separate works. But when you
199distribute the same sections as part of a whole which is a work based
200on the Library, the distribution of the whole must be on the terms of
201this License, whose permissions for other licensees extend to the
202entire whole, and thus to each and every part regardless of who wrote
203it.
204
205Thus, it is not the intent of this section to claim rights or contest
206your rights to work written entirely by you; rather, the intent is to
207exercise the right to control the distribution of derivative or
208collective works based on the Library.
209
210In addition, mere aggregation of another work not based on the Library
211with the Library (or with a work based on the Library) on a volume of
212a storage or distribution medium does not bring the other work under
213the scope of this License.
214
215 3. You may opt to apply the terms of the ordinary GNU General Public
216License instead of this License to a given copy of the Library. To do
217this, you must alter all the notices that refer to this License, so
218that they refer to the ordinary GNU General Public License, version 2,
219instead of to this License. (If a newer version than version 2 of the
220ordinary GNU General Public License has appeared, then you can specify
221that version instead if you wish.) Do not make any other change in
222these notices.
223^L
224 Once this change is made in a given copy, it is irreversible for
225that copy, so the ordinary GNU General Public License applies to all
226subsequent copies and derivative works made from that copy.
227
228 This option is useful when you wish to copy part of the code of
229the Library into a program that is not a library.
230
231 4. You may copy and distribute the Library (or a portion or
232derivative of it, under Section 2) in object code or executable form
233under the terms of Sections 1 and 2 above provided that you accompany
234it with the complete corresponding machine-readable source code, which
235must be distributed under the terms of Sections 1 and 2 above on a
236medium customarily used for software interchange.
237
238 If distribution of object code is made by offering access to copy
239from a designated place, then offering equivalent access to copy the
240source code from the same place satisfies the requirement to
241distribute the source code, even though third parties are not
242compelled to copy the source along with the object code.
243
244 5. A program that contains no derivative of any portion of the
245Library, but is designed to work with the Library by being compiled or
246linked with it, is called a "work that uses the Library". Such a
247work, in isolation, is not a derivative work of the Library, and
248therefore falls outside the scope of this License.
249
250 However, linking a "work that uses the Library" with the Library
251creates an executable that is a derivative of the Library (because it
252contains portions of the Library), rather than a "work that uses the
253library". The executable is therefore covered by this License.
254Section 6 states terms for distribution of such executables.
255
256 When a "work that uses the Library" uses material from a header file
257that is part of the Library, the object code for the work may be a
258derivative work of the Library even though the source code is not.
259Whether this is true is especially significant if the work can be
260linked without the Library, or if the work is itself a library. The
261threshold for this to be true is not precisely defined by law.
262
263 If such an object file uses only numerical parameters, data
264structure layouts and accessors, and small macros and small inline
265functions (ten lines or less in length), then the use of the object
266file is unrestricted, regardless of whether it is legally a derivative
267work. (Executables containing this object code plus portions of the
268Library will still fall under Section 6.)
269
270 Otherwise, if the work is a derivative of the Library, you may
271distribute the object code for the work under the terms of Section 6.
272Any executables containing that work also fall under Section 6,
273whether 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
276link a "work that uses the Library" with the Library to produce a
277work containing portions of the Library, and distribute that work
278under terms of your choice, provided that the terms permit
279modification of the work for the customer's own use and reverse
280engineering for debugging such modifications.
281
282 You must give prominent notice with each copy of the work that the
283Library is used in it and that the Library and its use are covered by
284this License. You must supply a copy of this License. If the work
285during execution displays copyright notices, you must include the
286copyright notice for the Library among them, as well as a reference
287directing the user to the copy of this License. Also, you must do one
288of 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
323Library" must include any data and utility programs needed for
324reproducing the executable from it. However, as a special exception,
325the materials to be distributed need not include anything that is
326normally distributed (in either source or binary form) with the major
327components (compiler, kernel, and so on) of the operating system on
328which the executable runs, unless that component itself accompanies
329the executable.
330
331 It may happen that this requirement contradicts the license
332restrictions of other proprietary libraries that do not normally
333accompany the operating system. Such a contradiction means you cannot
334use both them and the Library together in an executable that you
335distribute.
336^L
337 7. You may place library facilities that are a work based on the
338Library side-by-side in a single library together with other library
339facilities not covered by this License, and distribute such a combined
340library, provided that the separate distribution of the work based on
341the Library and of the other library facilities is otherwise
342permitted, 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
354the Library except as expressly provided under this License. Any
355attempt otherwise to copy, modify, sublicense, link with, or
356distribute the Library is void, and will automatically terminate your
357rights under this License. However, parties who have received copies,
358or rights, from you under this License will not have their licenses
359terminated so long as such parties remain in full compliance.
360
361 9. You are not required to accept this License, since you have not
362signed it. However, nothing else grants you permission to modify or
363distribute the Library or its derivative works. These actions are
364prohibited by law if you do not accept this License. Therefore, by
365modifying or distributing the Library (or any work based on the
366Library), you indicate your acceptance of this License to do so, and
367all its terms and conditions for copying, distributing or modifying
368the Library or works based on it.
369
370 10. Each time you redistribute the Library (or any work based on the
371Library), the recipient automatically receives a license from the
372original licensor to copy, distribute, link with or modify the Library
373subject to these terms and conditions. You may not impose any further
374restrictions on the recipients' exercise of the rights granted herein.
375You are not responsible for enforcing compliance by third parties with
376this License.
377^L
378 11. If, as a consequence of a court judgment or allegation of patent
379infringement or for any other reason (not limited to patent issues),
380conditions are imposed on you (whether by court order, agreement or
381otherwise) that contradict the conditions of this License, they do not
382excuse you from the conditions of this License. If you cannot
383distribute so as to satisfy simultaneously your obligations under this
384License and any other pertinent obligations, then as a consequence you
385may not distribute the Library at all. For example, if a patent
386license would not permit royalty-free redistribution of the Library by
387all those who receive copies directly or indirectly through you, then
388the only way you could satisfy both it and this License would be to
389refrain entirely from distribution of the Library.
390
391If any portion of this section is held invalid or unenforceable under
392any particular circumstance, the balance of the section is intended to
393apply, and the section as a whole is intended to apply in other
394circumstances.
395
396It is not the purpose of this section to induce you to infringe any
397patents or other property right claims or to contest validity of any
398such claims; this section has the sole purpose of protecting the
399integrity of the free software distribution system which is
400implemented by public license practices. Many people have made
401generous contributions to the wide range of software distributed
402through that system in reliance on consistent application of that
403system; it is up to the author/donor to decide if he or she is willing
404to distribute software through any other system and a licensee cannot
405impose that choice.
406
407This section is intended to make thoroughly clear what is believed to
408be a consequence of the rest of this License.
409
410 12. If the distribution and/or use of the Library is restricted in
411certain countries either by patents or by copyrighted interfaces, the
412original copyright holder who places the Library under this License
413may add an explicit geographical distribution limitation excluding those
414countries, so that distribution is permitted only in or among
415countries not thus excluded. In such case, this License incorporates
416the limitation as if written in the body of this License.
417
418 13. The Free Software Foundation may publish revised and/or new
419versions of the Lesser General Public License from time to time.
420Such new versions will be similar in spirit to the present version,
421but may differ in detail to address new problems or concerns.
422
423Each version is given a distinguishing version number. If the Library
424specifies a version number of this License which applies to it and
425"any later version", you have the option of following the terms and
426conditions either of that version or of any later version published by
427the Free Software Foundation. If the Library does not specify a
428license version number, you may choose any version ever published by
429the Free Software Foundation.
430^L
431 14. If you wish to incorporate parts of the Library into other free
432programs whose distribution conditions are incompatible with these,
433write to the author to ask for permission. For software which is
434copyrighted by the Free Software Foundation, write to the Free
435Software Foundation; we sometimes make exceptions for this. Our
436decision will be guided by the two goals of preserving the free status
437of all derivatives of our free software and of promoting the sharing
438and reuse of software generally.
439
440 NO WARRANTY
441
442 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
443WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
444EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
445OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
446KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
447IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
448PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
449LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
450THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
451
452 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
453WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
454AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
455FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
456CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
457LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
458RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
459FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
460SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
461DAMAGES.
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
468possible use to the public, we recommend making it free software that
469everyone can redistribute and change. You can do so by permitting
470redistribution under these terms (or, alternatively, under the terms
471of the ordinary General Public License).
472
473 To apply these terms, attach the following notices to the library.
474It is safest to attach them to the start of each source file to most
475effectively convey the exclusion of warranty; and each file should
476have at least the "copyright" line and a pointer to where the full
477notice is found.
478
479
480 <one line to give the library's name and a brief idea of what it
481does.>
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
498Also add information on how to contact you by electronic and paper
499mail.
500
501You should also get your employer (if you work as a programmer) or
502your
503school, if any, to sign a "copyright disclaimer" for the library, if
504necessary. 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
508Random Hacker.
509
510 <signature of Ty Coon>, 1 April 1990
511 Ty Coon, President of Vice
512
513That'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
80extern __declspec(dllimport)
81#elif defined EXPORT
82extern __declspec(dllexport)
83#else
84extern
85#endif
86const unsigned char *re_mbctab;
87#if defined(__STDC__)
88void re_mbcinit (int);
89#else
90void 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
100typedef 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
111struct 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
148typedef 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
160struct 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. */
170typedef 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. */
175typedef 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
185extern char *mbre_compile_pattern (const char *, int, struct mbre_pattern_buffer *);
186void mbre_free_pattern (struct mbre_pattern_buffer *);
187/* Is this really advertised? */
188extern int mbre_adjust_startpos (struct mbre_pattern_buffer *, const char*, int, int, int);
189extern void mbre_compile_fastmap (struct mbre_pattern_buffer *);
190extern int mbre_search (struct mbre_pattern_buffer *, const char*, int, int, int,
191 struct mbre_registers *);
192extern int mbre_match (struct mbre_pattern_buffer *, const char *, int, int,
193 struct mbre_registers *);
194extern void mbre_set_casetable (const char *table);
195extern void mbre_copy_registers (struct mbre_registers*, struct mbre_registers*);
196extern void mbre_free_registers (struct mbre_registers*);
197
198#else /* !__STDC__ */
199
200extern char *mbre_compile_pattern ();
201void mbre_free_pattern ();
202/* Is this really advertised? */
203extern int mbre_adjust_startpos ();
204extern void mbre_compile_fastmap ();
205extern int mbre_search ();
206extern int mbre_match ();
207extern void mbre_set_casetable ();
208extern void mbre_copy_registers ();
209extern 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 */
35static 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
66void 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
42extern 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
61PHP_MINIT_FUNCTION(suhosin);
62PHP_MSHUTDOWN_FUNCTION(suhosin);
63PHP_RINIT_FUNCTION(suhosin);
64PHP_RSHUTDOWN_FUNCTION(suhosin);
65PHP_MINFO_FUNCTION(suhosin);
66
67#include "ext/standard/basic_functions.h"
68
69ZEND_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
252ZEND_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
293ZEND_EXTERN_MODULE_GLOBALS(suhosin)
294
295static inline char *
296suhosin_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 */
304PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...);
305char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC);
306char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, char *key, int *orig_len, int check_ra TSRMLS_DC);
307char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC);
308char *suhosin_cookie_decryptor(TSRMLS_D);
309void suhosin_hook_post_handlers(TSRMLS_D);
310void suhosin_hook_register_server_variables();
311void suhosin_hook_header_handler();
312void suhosin_unhook_header_handler();
313void suhosin_hook_session(TSRMLS_D);
314void suhosin_unhook_session(TSRMLS_D);
315void suhosin_hook_crypt();
316void suhosin_hook_sha256();
317void suhosin_hook_ex_imp();
318void suhosin_hook_treat_data();
319void suhosin_hook_memory_limit();
320void suhosin_hook_execute(TSRMLS_D);
321void suhosin_unhook_execute();
322void suhosin_aes_gentables();
323void suhosin_aes_gkey(int nb,int nk,char *key TSRMLS_DC);
324void suhosin_aes_encrypt(char *buff TSRMLS_DC);
325void suhosin_aes_decrypt(char *buff TSRMLS_DC);
326unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
327unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
328extern unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
329void normalize_varname(char *varname);
330int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC);
331void 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
371static zend_always_inline zend_uint zval_refcount_p(zval* pz) {
372 return pz->refcount;
373}
374
375static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) {
376 return pz->refcount = rc;
377}
378
379static zend_always_inline zend_uint zval_addref_p(zval* pz) {
380 return ++pz->refcount;
381}
382
383static zend_always_inline zend_uint zval_delref_p(zval* pz) {
384 return --pz->refcount;
385}
386
387static zend_always_inline zend_bool zval_isref_p(zval* pz) {
388 return pz->is_ref;
389}
390
391static zend_always_inline zend_bool zval_set_isref_p(zval* pz) {
392 return pz->is_ref = 1;
393}
394
395static zend_always_inline zend_bool zval_unset_isref_p(zval* pz) {
396 return pz->is_ref = 0;
397}
398
399static 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
36SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler);
37
38
39SAPI_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)))) {
52last_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 */
84static 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
91void 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
42static 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
57static 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
75static 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
86static 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/*
139void 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
152static 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
211static 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
220static 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
227static 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
235static 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
243static 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
253static 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
269typedef 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
285typedef 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*/
295static 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 */
332static 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 */
343static 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 */
378static 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 */
414static 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 */
428static 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 */
440static 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 */
459static 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
516static 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
536static 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
575static 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
606static 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;
628look_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*/
673static 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 */
698static 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*/
745static 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
768SAPI_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 }
915SDEBUG("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)
1213filedone:
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 }
1337fileupload_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
43typedef 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
54typedef 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
63typedef 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
69typedef 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
102typedef 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
138typedef 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
178static 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)
190static php_ps_globals_52_60 *session_globals = NULL;
191# elif (PHP_MAJOR_VERSION == 5)
192static php_ps_globals_50_51 *session_globals = NULL;
193# elif (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION >= 3)
194static 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
201void 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
224char *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
293char *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) {
322error_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
397char *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
456static 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;
457static int (*old_SessionRINIT)(INIT_FUNC_ARGS) = NULL;
458
459static 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) {
472regenerate:
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
513static 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
542return_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
558static 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
572static 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
598static 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
610static 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
622void 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
691void 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
29static 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 */
43static 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 */
73static 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
127static void SHA256Transform(php_uint32[8], const unsigned char[64]);
128static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
129static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
130
131static 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 */
168void 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 */
189void 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 */
230void 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 */
266static void SHA256Transform(state, block)
267php_uint32 state[8];
268const 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 */
359static void SHA256Encode(output, input, len)
360unsigned char *output;
361php_uint32 *input;
362unsigned 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 */
379static void SHA256Decode(output, input, len)
380php_uint32 *output;
381const unsigned char *input;
382unsigned 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 */
395static 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
403void 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. */
28typedef 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
34void suhosin_SHA256Init(suhosin_SHA256_CTX *);
35void suhosin_SHA256Update(suhosin_SHA256_CTX *, const unsigned char *, unsigned int);
36void 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
41ZEND_DECLARE_MODULE_GLOBALS(suhosin)
42
43static zend_llist_position lp = NULL;
44static int (*old_startup)(zend_extension *extension) = NULL;
45static zend_extension *ze = NULL;
46
47static int suhosin_module_startup(zend_extension *extension);
48static void suhosin_shutdown(zend_extension *extension);
49
50
51static void (*orig_op_array_ctor)(zend_op_array *op_array) = NULL;
52static void (*orig_op_array_dtor)(zend_op_array *op_array) = NULL;
53static void (*orig_module_shutdown)(zend_extension *extension) = NULL;
54static int (*orig_module_startup)(zend_extension *extension) = NULL;
55
56
57static void suhosin_op_array_ctor(zend_op_array *op_array);
58static void suhosin_op_array_dtor(zend_op_array *op_array);
59
60STATIC 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
81static 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
100static 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
109static 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
117static 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
125static 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
132static 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
141static 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
190static 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
205static 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
275static 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
366dohandlers(Log, LOG, log)
367dohandlers(Exec, EXEC, exec)
368dohandlers(Misc, MISC, misc)
369dohandlers(Get, GET, get)
370dohandlers(Post, POST, post)
371dohandlers(Cookie, COOKIE, cookie)
372dohandlers(Request, REQUEST, request)
373dohandlers(Upload, UPLOAD, upload)
374dohandlers(SQL, SQL, sql)
375
376static 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}
386static 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}
396static 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}
406static 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}
416static 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}
426static 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}
438static 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}
448static 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
459static 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) {
465list_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
513static 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
520static 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
527static 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
534static 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
541static 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
548static 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
556static ZEND_INI_MH(OnUpdate_cookie_cryptlist)
557{
558 parse_list(&SUHOSIN_G(cookie_cryptlist), new_value, 0);
559 return SUCCESS;
560}
561
562static 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 */
570static 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 {
678plain_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
709static 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 */
729static 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)) {
740return_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 */
763static 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 */
804zend_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 */
813zend_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
832ZEND_GET_MODULE(suhosin)
833#endif
834
835/* {{{ PHP_INI
836 */
837static 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)
850ZEND_INI_END()
851
852PHP_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
959PHP_INI_END()
960/* }}} */
961
962
963/* {{{ php_suhosin_init_globals
964 */
965void suhosin_bailout(TSRMLS_D)
966{
967 if (!SUHOSIN_G(simulation)) {
968 zend_bailout();
969 }
970}
971/* }}} */
972
973/* {{{ php_suhosin_init_globals
974 */
975STATIC 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 */
983PHP_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 */
1092PHP_MSHUTDOWN_FUNCTION(suhosin)
1093{
1094 SDEBUG("(MSHUTDOWN)");
1095 UNREGISTER_INI_ENTRIES();
1096 return SUCCESS;
1097}
1098/* }}} */
1099
1100
1101/* {{{ PHP_RINIT_FUNCTION
1102 */
1103PHP_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 */
1116PHP_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 */
1154static 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 */
1164PHP_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 @@
1extension = 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.
177suhosin.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
3static 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
41typedef struct _multipart_event_start {
42 size_t content_length;
43} multipart_event_start;
44
45typedef 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
53typedef struct _multipart_event_file_start {
54 size_t post_bytes_processed;
55 char *name;
56 char **filename;
57} multipart_event_file_start;
58
59typedef 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
67typedef 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
73typedef struct _multipart_event_end {
74 size_t post_bytes_processed;
75} multipart_event_end;
76
77#endif
78
79SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler);
80
81void destroy_uploaded_files_hash(TSRMLS_D);
82#if !HAVE_RFC1867_CALLBACK
83extern PHP_SUHOSIN_API int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC);
84#else
85extern 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--
2Testing: suhosin.executor.disable_emodifier=0
3--SKIPIF--
4<?php include "../skipifnotcli.inc"; ?>
5--INI--
6suhosin.log.sapi=64
7suhosin.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--
16string(5) "HALLO"
17string(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--
2Testing: suhosin.executor.disable_emodifier=1
3--SKIPIF--
4<?php include "../skipifnotcli.inc"; ?>
5--INI--
6suhosin.log.sapi=64
7suhosin.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--
16string(5) "HALLO"
17ALERT - use of preg_replace() with /e modifier is forbidden by configuration (attacker 'REMOTE_ADDR not set', file '%s', line 5)
18
19Fatal 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--
2Testing: suhosin.executor.disable_eval=0
3--SKIPIF--
4<?php include "../skipifnotcli.inc"; ?>
5--INI--
6suhosin.log.sapi=64
7suhosin.executor.disable_eval=0
8--FILE--
9<?php
10 $x = 0;
11 eval('$x = 1;');
12 var_dump($x);
13?>
14--EXPECTF--
15int(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--
2Testing: suhosin.executor.disable_eval=1
3--SKIPIF--
4<?php include "../skipifnotcli.inc"; ?>
5--INI--
6suhosin.log.sapi=64
7suhosin.executor.disable_eval=1
8--FILE--
9<?php
10 $x = 0;
11 eval('$x = 1;');
12 var_dump($x);
13?>
14--EXPECTF--
15ALERT - use of eval is forbidden by configuration (attacker 'REMOTE_ADDR not set', file '%s', line 3)
16
17Fatal 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--
2memory_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--
6memory_limit=16M
7suhosin.memory_limit=0
8suhosin.log.syslog=0
9suhosin.log.script=0
10suhosin.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--
2113M
2214M
2315M
2416M
25ALERT - script tried to increase memory_limit to 17825792 bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 6)
2616M
27ALERT - script tried to increase memory_limit to 18874368 bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 7)
2816M
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--
2memory_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--
6memory_limit=16M
7suhosin.memory_limit=17M
8suhosin.log.syslog=0
9suhosin.log.script=0
10suhosin.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--
2113M
2214M
2315M
2416M
2517M
26ALERT - script tried to increase memory_limit to %d bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 7)
2717M
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--
2memory_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--
6memory_limit=16M
7suhosin.memory_limit=17M
8suhosin.log.syslog=0
9suhosin.log.script=0
10suhosin.log.sapi=2
11--FILE--
12<?php
13 ini_set("memory_limit", "-200000"); echo ini_get("memory_limit"), "\n";
14?>
15--EXPECTF--
16ALERT - script tried to increase memory_limit to %d bytes which is above the allowed value (attacker 'REMOTE_ADDR not set', file '%s', line 2)
1716M
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--
2Testing protection against "\0" in preg_replace() first parameter
3--SKIPIF--
4<?php include "../skipif.inc"; ?>
5--INI--
6suhosin.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--
27string(49) "One little boy with 2 dogs, 3 cats and four birds"
28bool(false)
29string(39) "The three cats play with the four birds"
30bool(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--
2Testing protection against "\0" in preg_replace() first parameter (INCL. SUHOSIN ERROR MESSAGES)
3--SKIPIF--
4<?php include "../skipifnotcli.inc"; ?>
5--INI--
6suhosin.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--
27string(49) "One little boy with 2 dogs, 3 cats and four birds"
28ALERT - string termination attack on first preg_replace parameter detected (attacker 'REMOTE_ADDR not set', file '%s', line 14)
29bool(false)
30string(39) "The three cats play with the four birds"
31ALERT - string termination attack on first preg_replace parameter detected (attacker 'REMOTE_ADDR not set', file '%s', line 16)
32bool(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--
2Testing: suhosin.executor.max_depth
3--SKIPIF--
4<?php include "../skipifnotcli.inc"; ?>
5--INI--
6suhosin.log.sapi=64
7suhosin.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--
192
203
214
225
236
247
258
269
2710
2811
2912
3013
31ALERT - 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--
2Testing: GLOBALS in GET
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=255
9suhosin.log.script.name=/tmp/xx
10--GET--
11a=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--
21string(1) "1"
22string(1) "2"
23string(1) "3"
24int(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--
2CRYPT_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--
11int(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--
2CRYPT_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--
2CRYPT_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--
2CRYPT_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--
10rl.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--
2SHA256 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--
25e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
26ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
2768325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b
287c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788
294096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803
307abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504
317516fb8bb11350df2bf386bc3c33bd0f52cb4c67c6e4745e0488e62c2aea2605
320eb0281b27a4604709b0513b43ad29fdcff9a7a958554abc689d7fe35af703e4
33dee684641421d1ba5a65c71f986a117cbb3d619a052a0b3409306c629575c00f
3447f527210d6e8f940b5082fec01b7305908fa2b49ea3ae597c19a3986097153c
35c60d239cc6da3ad31f4de0c2d58a73ccf3f9279e504fa60ad55a31dcf686f3ca
36e0164d90dbfcf173bb88044fac596ccd03b8d247c79907aaa5701767fad7b576
37dc990ef3109a7bcf626199db9ab7801213ceb0ad2ee398963b5061e39c05c7b5
38c1c9a4daadcc8678835872c7f1f8824376ac7b412e1fc2285069b41afd51397e
396840619417b4d8ecaa7902f8eaf2e82be2638dec97cb7e8fcc377007cc176718
400f5308ff22b828e18bd65afbc427e3c1a678962832519df5f2f803f68f55e10b
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--
2Include "Constant URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 include "http://127.0.0.1/";
15?>
16--EXPECTF--
17ALERT - 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--
2Include "../../../../../../../../../../../etc/passwd";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12suhosin.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--
22value-from-empty.inc
23ALERT - 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--
2Include_once "Constant URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 include_once "http://127.0.0.1/";
15?>
16--EXPECTF--
17ALERT - 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--
2Include_once "Temp Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 $app = "?";
16 include_once $var.$app;
17?>
18--EXPECTF--
19ALERT - 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--
2Include_once "Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 include_once $var;
16?>
17--EXPECTF--
18ALERT - 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--
2Include "Temp Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 $app = "?";
16 include $var.$app;
17?>
18--EXPECTF--
19ALERT - 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--
2Include "Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 include $var;
16?>
17--EXPECTF--
18ALERT - 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--
2Require "Constant URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 require "http://127.0.0.1/";
15?>
16--EXPECTF--
17ALERT - 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--
2Require_once "Constant URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 require_once "http://127.0.0.1/";
15?>
16--EXPECTF--
17ALERT - 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--
2Require_once "Temp Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 $app = "?";
16 require_once $var.$app;
17?>
18--EXPECTF--
19ALERT - 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--
2Require_once "Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 require_once $var;
16?>
17--EXPECTF--
18ALERT - 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--
2Require "Temp Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 $app = "?";
16 require $var.$app;
17?>
18--EXPECTF--
19ALERT - 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--
2Require "Variable URL";
3--SKIPIF--
4<?php include "../skipifcli.inc"; ?>
5--INI--
6suhosin.log.syslog=0
7suhosin.log.sapi=255
8suhosin.log.script=0
9suhosin.log.phpscript=0
10suhosin.executor.include.whitelist=
11suhosin.executor.include.blacklist=
12--FILE--
13<?php
14 $var = "http://127.0.0.1/";
15 require $var;
16?>
17--EXPECTF--
18ALERT - 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
2if(!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
2if (php_sapi_name()=='cli') {
3 print 'skip - SAPI == cli';
4} else {
5if(!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
2if (php_sapi_name()!='cli') {
3 print 'skip - SAPI != cli';
4} else {
5if(!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
34SAPI_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
195void 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
35PHP_SUHOSIN_API int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC) = NULL;
36#endif
37
38static 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;
83protected_varname2:
84 return 1;
85}
86
87/* {{{ SAPI_UPLOAD_VARNAME_FILTER_FUNC
88 */
89static 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
186return_failure:
187 efree(var);
188 return FAILURE;
189}
190/* }}} */
191
192int 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 }
346continue_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;
353continue_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 */