summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS3
-rw-r--r--aes.c382
-rw-r--r--config.m417
-rw-r--r--config.w3213
-rw-r--r--ifilter.c726
-rw-r--r--memory_limit.c98
-rw-r--r--php_suhosin7.h191
-rw-r--r--sha256.c413
-rw-r--r--sha256.h38
-rw-r--r--suhosin7.c209
-rw-r--r--suhosin7_logo.h180
-rw-r--r--tests/001.phpt21
-rw-r--r--treat_data.c214
13 files changed, 2505 insertions, 0 deletions
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 0000000..3abd99c
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,3 @@
1suhosin7
2Stefan Esser
3Ben Fuhrmannek
diff --git a/aes.c b/aes.c
new file mode 100644
index 0000000..65b6421
--- /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_suhosin7.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 SUHOSIN7_G(fi)[m]=(j+C1)%nb;
207 SUHOSIN7_G(fi)[m+1]=(j+C2)%nb;
208 SUHOSIN7_G(fi)[m+2]=(j+C3)%nb;
209 SUHOSIN7_G(ri)[m]=(nb+j-C1)%nb;
210 SUHOSIN7_G(ri)[m+1]=(nb+j-C2)%nb;
211 SUHOSIN7_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++) SUHOSIN7_G(fkey)[i]=CipherKey[i];
221 for (j=Nk,k=0;j<N;j+=Nk,k++)
222 {
223 SUHOSIN7_G(fkey)[j]=SUHOSIN7_G(fkey)[j-Nk]^SubByte(ROTL24(SUHOSIN7_G(fkey)[j-1]))^rco[k];
224 if (Nk<=6)
225 {
226 for (i=1;i<Nk && (i+j)<N;i++)
227 SUHOSIN7_G(fkey)[i+j]=SUHOSIN7_G(fkey)[i+j-Nk]^SUHOSIN7_G(fkey)[i+j-1];
228 }
229 else
230 {
231 for (i=1;i<4 &&(i+j)<N;i++)
232 SUHOSIN7_G(fkey)[i+j]=SUHOSIN7_G(fkey)[i+j-Nk]^SUHOSIN7_G(fkey)[i+j-1];
233 if ((j+4)<N) SUHOSIN7_G(fkey)[j+4]=SUHOSIN7_G(fkey)[j+4-Nk]^SubByte(SUHOSIN7_G(fkey)[j+3]);
234 for (i=5;i<Nk && (i+j)<N;i++)
235 SUHOSIN7_G(fkey)[i+j]=SUHOSIN7_G(fkey)[i+j-Nk]^SUHOSIN7_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++) SUHOSIN7_G(rkey)[j+N-Nb]=SUHOSIN7_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++) SUHOSIN7_G(rkey)[k+j]=InvMixCol(SUHOSIN7_G(fkey)[i+j]);
247 }
248 for (j=N-Nb;j<N;j++) SUHOSIN7_G(rkey)[j-N+Nb]=SUHOSIN7_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]^=SUHOSIN7_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]=SUHOSIN7_G(fkey)[k++]^ftable[(BYTE)x[j]]^
280 ROTL8(ftable[(BYTE)(x[SUHOSIN7_G(fi)[m]]>>8)])^
281 ROTL16(ftable[(BYTE)(x[SUHOSIN7_G(fi)[m+1]]>>16)])^
282 ROTL24(ftable[x[SUHOSIN7_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]=SUHOSIN7_G(fkey)[k++]^(WORD)fbsub[(BYTE)x[j]]^
291 ROTL8((WORD)fbsub[(BYTE)(x[SUHOSIN7_G(fi)[m]]>>8)])^
292 ROTL16((WORD)fbsub[(BYTE)(x[SUHOSIN7_G(fi)[m+1]]>>16)])^
293 ROTL24((WORD)fbsub[x[SUHOSIN7_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]^=SUHOSIN7_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]=SUHOSIN7_G(rkey)[k++]^rtable[(BYTE)x[j]]^
326 ROTL8(rtable[(BYTE)(x[SUHOSIN7_G(ri)[m]]>>8)])^
327 ROTL16(rtable[(BYTE)(x[SUHOSIN7_G(ri)[m+1]]>>16)])^
328 ROTL24(rtable[x[SUHOSIN7_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]=SUHOSIN7_G(rkey)[k++]^(WORD)rbsub[(BYTE)x[j]]^
337 ROTL8((WORD)rbsub[(BYTE)(x[SUHOSIN7_G(ri)[m]]>>8)])^
338 ROTL16((WORD)rbsub[(BYTE)(x[SUHOSIN7_G(ri)[m+1]]>>16)])^
339 ROTL24((WORD)rbsub[x[SUHOSIN7_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/config.m4 b/config.m4
new file mode 100644
index 0000000..602b2c9
--- /dev/null
+++ b/config.m4
@@ -0,0 +1,17 @@
1dnl $Id$
2dnl config.m4 for extension suhosin7
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(suhosin7, suhosin7.c aes.c ifilter.c memory_limit.c sha256.c treat_data.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
9fi
10
11PHP_ARG_ENABLE(suhosin7-experimental, whether to enable experimental suhosin7 features,
12[ --enable-suhosin7-experimental Enable experimental suhosin7 features], no, no)
13
14if test "$PHP_SUHOSIN7_EXPERIMENTAL" != "no"; then
15 AC_DEFINE(SUHOSIN7_EXPERIMENTAL, 1, [Whether to enable experimental suhosin7 features])
16fi
17
diff --git a/config.w32 b/config.w32
new file mode 100644
index 0000000..686fe73
--- /dev/null
+++ b/config.w32
@@ -0,0 +1,13 @@
1// $Id$
2// vim:ft=javascript
3
4// If your extension references something external, use ARG_WITH
5// ARG_WITH("suhosin7", "for suhosin7 support", "no");
6
7// Otherwise, use ARG_ENABLE
8// ARG_ENABLE("suhosin7", "enable suhosin7 support", "no");
9
10if (PHP_SUHOSIN7 != "no") {
11 EXTENSION("suhosin7", "suhosin7.c", PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
12}
13
diff --git a/ifilter.c b/ifilter.c
new file mode 100644
index 0000000..7160f10
--- /dev/null
+++ b/ifilter.c
@@ -0,0 +1,726 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2015 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_suhosin7.h"
31#include "php_variables.h"
32#include "ext/standard/php_var.h"
33
34
35static void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = NULL;
36
37#if !HAVE_STRNLEN
38static size_t strnlen(const char *s, size_t maxlen) {
39 char *r = memchr(s, '\0', maxlen);
40 return r ? r-s : maxlen;
41}
42#endif
43
44size_t suhosin_strnspn(const char *input, size_t n, const char *accept)
45{
46 size_t count = 0;
47 for (; *input != '\0' && count < n; input++, count++) {
48 if (strchr(accept, *input) == NULL)
49 break;
50 }
51 return count;
52}
53
54size_t suhosin_strncspn(const char *input, size_t n, const char *reject)
55{
56 size_t count = 0;
57 for (; *input != '\0' && count < n; input++, count++) {
58 if (strchr(reject, *input) != NULL)
59 break;
60 }
61 return count;
62}
63
64
65/* {{{ normalize_varname
66 */
67void normalize_varname(char *varname)
68{
69 char *s=varname, *index=NULL, *indexend=NULL, *p;
70
71 /* overjump leading space */
72 while (*s == ' ') {
73 s++;
74 }
75
76 /* and remove it */
77 if (s != varname) {
78 memmove(varname, s, strlen(s)+1);
79 }
80
81 for (p=varname; *p && *p != '['; p++) {
82 switch(*p) {
83 case ' ':
84 case '.':
85 *p='_';
86 break;
87 }
88 }
89
90 /* find index */
91 index = strchr(varname, '[');
92 if (index) {
93 index++;
94 s=index;
95 } else {
96 return;
97 }
98
99 /* done? */
100 while (index) {
101
102 while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
103 index++;
104 }
105 indexend = strchr(index, ']');
106 indexend = indexend ? indexend + 1 : index + strlen(index);
107
108 if (s != index) {
109 memmove(s, index, strlen(index)+1);
110 s += indexend-index;
111 } else {
112 s = indexend;
113 }
114
115 if (*s == '[') {
116 s++;
117 index = s;
118 } else {
119 index = NULL;
120 }
121 }
122 *s++='\0';
123}
124/* }}} */
125
126static unsigned char suhosin_hexchars[] = "0123456789ABCDEF";
127
128static const char suhosin_is_dangerous_char[256] = {
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 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 1, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
145};
146
147/* {{{ suhosin_server_encode
148 */
149static void suhosin_server_strip(HashTable *arr, char *key, int klen)
150{
151 zval **tzval;
152 unsigned char *s, *t;
153
154 if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS &&
155 Z_TYPE_PP(tzval) == IS_STRING) {
156
157 s = t = (unsigned char *)Z_STRVAL_PP(tzval);
158 for (; *t; t++) {
159 if (suhosin_is_dangerous_char[*t]) {
160 *t = '?';
161 }
162 }
163 Z_STRLEN_PP(tzval) = t-s;
164 }
165}
166/* }}} */
167
168/* {{{ suhosin_server_encode
169 */
170static void suhosin_server_encode(HashTable *arr, char *key, int klen)
171{
172 zval **tzval;
173 unsigned char *temp = NULL, *t, *newv, *n;
174 int extra = 0;
175
176 if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS &&
177 Z_TYPE_PP(tzval) == IS_STRING) {
178
179 temp = (unsigned char *)Z_STRVAL_PP(tzval);
180
181 for (t = temp; *t; t++) {
182 if (suhosin_is_dangerous_char[*t]) {
183 extra += 2;
184 }
185 }
186
187 /* no extra bytes required */
188 if (extra == 0) {
189 return;
190 }
191
192 n = newv = emalloc(t - temp + 1 + extra);
193 t = temp;
194 for (t = temp; *t; t++, n++) {
195 if (suhosin_is_dangerous_char[*t]) {
196 *n++ = '%';
197 *n++ = suhosin_hexchars[*t >> 4];
198 *n = suhosin_hexchars[*t & 15];
199 } else {
200 *n = *t;
201 }
202 }
203 *n = 0;
204
205 /* XXX: we leak memory here, but only for the duration of the request */
206 Z_STRVAL_PP(tzval) = (char *)newv;
207 Z_STRLEN_PP(tzval) = n-newv;
208 }
209}
210/* }}} */
211
212/* {{{ suhosin_register_server_variables
213 */
214void suhosin_register_server_variables(zval *track_vars_array TSRMLS_DC)
215{
216 HashTable *svars;
217 int retval = 0, failure = 0;
218
219 orig_register_server_variables(track_vars_array TSRMLS_CC);
220
221 svars = Z_ARRVAL_P(track_vars_array);
222 if (!SUHOSIN_G(simulation)) {
223 retval = zend_hash_del(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"));
224 if (retval == SUCCESS) failure = 1;
225 retval = zend_hash_del(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"));
226 if (retval == SUCCESS) failure = 1;
227 retval = zend_hash_del(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"));
228 if (retval == SUCCESS) failure = 1;
229 retval = zend_hash_del(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"));
230 if (retval == SUCCESS) failure = 1;
231 retval = zend_hash_del(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"));
232 if (retval == SUCCESS) failure = 1;
233 retval = zend_hash_del(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"));
234 if (retval == SUCCESS) failure = 1;
235 retval = zend_hash_del(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"));
236 if (retval == SUCCESS) failure = 1;
237 retval = zend_hash_del(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
238 if (retval == SUCCESS) failure = 1;
239 } else {
240 retval = zend_hash_exists(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"));
241 retval+= zend_hash_exists(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"));
242 retval+= zend_hash_exists(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"));
243 retval+= zend_hash_exists(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"));
244 retval+= zend_hash_exists(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"));
245 retval+= zend_hash_exists(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"));
246 retval+= zend_hash_exists(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"));
247 retval+= zend_hash_exists(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
248 if (retval > 0) failure = 1;
249 }
250
251 if (failure) {
252 suhosin_log(S_VARS, "Attacker tried to overwrite a superglobal through a HTTP header");
253 }
254
255 if (SUHOSIN_G(raw_cookie)) {
256 zval *z;
257 MAKE_STD_ZVAL(z);
258 ZVAL_STRING(z, SUHOSIN_G(raw_cookie), 1);
259 zend_hash_add(svars, "RAW_HTTP_COOKIE", sizeof("RAW_HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL);
260 }
261 if (SUHOSIN_G(decrypted_cookie)) {
262 zval *z;
263 MAKE_STD_ZVAL(z);
264 ZVAL_STRING(z, SUHOSIN_G(decrypted_cookie), 0);
265 zend_hash_update(svars, "HTTP_COOKIE", sizeof("HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL);
266 SUHOSIN_G(decrypted_cookie) = NULL;
267 }
268
269 if (SUHOSIN_G(server_encode)) {
270 /* suhosin_server_encode(svars, "argv", sizeof("argv")); */
271 suhosin_server_encode(svars, "REQUEST_URI", sizeof("REQUEST_URI"));
272 suhosin_server_encode(svars, "QUERY_STRING", sizeof("QUERY_STRING"));
273 }
274 if (SUHOSIN_G(server_strip)) {
275 suhosin_server_strip(svars, "PHP_SELF", sizeof("PHP_SELF"));
276 suhosin_server_strip(svars, "PATH_INFO", sizeof("PATH_INFO"));
277 suhosin_server_strip(svars, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"));
278 suhosin_server_strip(svars, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"));
279 }
280}
281/* }}} */
282
283
284/* Old Input filter */
285unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) = NULL;
286
287/* {{{ suhosin_input_filter_wrapper
288 */
289unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
290{
291 zend_bool already_scanned = SUHOSIN_G(already_scanned);
292 SUHOSIN_G(already_scanned) = 0;
293
294 if (SUHOSIN_G(do_not_scan)) {
295 if (new_val_len) {
296 *new_val_len = val_len;
297 }
298 return 1;
299 }
300
301 if (!already_scanned) {
302 if (suhosin_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC)==0) {
303 SUHOSIN_G(abort_request)=1;
304 return 0;
305 }
306 if (new_val_len) {
307 val_len = *new_val_len;
308 }
309 }
310 if (old_input_filter) {
311 return old_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC);
312 } else {
313 return 1;
314 }
315}
316
317/* {{{ suhosin_input_filter
318 */
319unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
320{
321 char *index, *prev_index = NULL;
322 unsigned int var_len, total_len, depth = 0;
323
324 /* Mark that we were called */
325 SUHOSIN_G(already_scanned) = 1;
326
327 if (new_val_len) {
328 *new_val_len = 0;
329 }
330
331 /* Drop this variable if the limit was reached */
332 switch (arg) {
333 case PARSE_GET:
334 SUHOSIN_G(att_get_vars)++;
335 SUHOSIN_G(att_request_variables)++;
336 if (SUHOSIN_G(no_more_get_variables)) {
337 return 0;
338 }
339 break;
340 case PARSE_POST:
341 SUHOSIN_G(att_post_vars)++;
342 SUHOSIN_G(att_request_variables)++;
343 if (SUHOSIN_G(no_more_post_variables)) {
344 return 0;
345 }
346 break;
347 case PARSE_COOKIE:
348 SUHOSIN_G(att_cookie_vars)++;
349 SUHOSIN_G(att_request_variables)++;
350 if (SUHOSIN_G(no_more_cookie_variables)) {
351 return 0;
352 }
353 break;
354 default: /* we do not want to protect parse_str() and friends */
355 if (new_val_len) {
356 *new_val_len = val_len;
357 }
358 return 1;
359 }
360
361 /* Drop this variable if the limit is now reached */
362 switch (arg) {
363 case PARSE_GET:
364 if (SUHOSIN_G(max_get_vars) && SUHOSIN_G(max_get_vars) <= SUHOSIN_G(cur_get_vars)) {
365 suhosin_log(S_VARS, "configured GET variable limit exceeded - dropped variable '%s' - all further GET variables are dropped", var);
366 if (!SUHOSIN_G(simulation)) {
367 SUHOSIN_G(no_more_get_variables) = 1;
368 return 0;
369 }
370 }
371 break;
372 case PARSE_COOKIE:
373 if (SUHOSIN_G(max_cookie_vars) && SUHOSIN_G(max_cookie_vars) <= SUHOSIN_G(cur_cookie_vars)) {
374 suhosin_log(S_VARS, "configured COOKIE variable limit exceeded - dropped variable '%s' - all further COOKIE variables are dropped", var);
375 if (!SUHOSIN_G(simulation)) {
376 SUHOSIN_G(no_more_cookie_variables) = 1;
377 return 0;
378 }
379 }
380 break;
381 case PARSE_POST:
382 if (SUHOSIN_G(max_post_vars) && SUHOSIN_G(max_post_vars) <= SUHOSIN_G(cur_post_vars)) {
383 suhosin_log(S_VARS, "configured POST variable limit exceeded - dropped variable '%s' - all further POST variables are dropped", var);
384 if (!SUHOSIN_G(simulation)) {
385 SUHOSIN_G(no_more_post_variables) = 1;
386 return 0;
387 }
388 }
389 break;
390 }
391
392 /* Drop this variable if it begins with whitespace which is disallowed */
393 if (isspace(*var)) {
394 if (SUHOSIN_G(disallow_ws)) {
395 suhosin_log(S_VARS, "request variable name begins with disallowed whitespace - dropped variable '%s'", var);
396 if (!SUHOSIN_G(simulation)) {
397 return 0;
398 }
399 }
400 switch (arg) {
401 case PARSE_GET:
402 if (SUHOSIN_G(disallow_get_ws)) {
403 suhosin_log(S_VARS, "GET variable name begins with disallowed whitespace - dropped variable '%s'", var);
404 if (!SUHOSIN_G(simulation)) {
405 return 0;
406 }
407 }
408 break;
409 case PARSE_POST:
410 if (SUHOSIN_G(disallow_post_ws)) {
411 suhosin_log(S_VARS, "POST variable name begins with disallowed whitespace - dropped variable '%s'", var);
412 if (!SUHOSIN_G(simulation)) {
413 return 0;
414 }
415 }
416 break;
417 case PARSE_COOKIE:
418 if (SUHOSIN_G(disallow_cookie_ws)) {
419 suhosin_log(S_VARS, "COOKIE variable name begins with disallowed whitespace - dropped variable '%s'", var);
420 if (!SUHOSIN_G(simulation)) {
421 return 0;
422 }
423 }
424 break;
425 }
426 }
427
428 /* Drop this variable if it exceeds the value length limit */
429 if (SUHOSIN_G(max_value_length) && SUHOSIN_G(max_value_length) < val_len) {
430 suhosin_log(S_VARS, "configured request variable value length limit exceeded - dropped variable '%s'", var);
431 if (!SUHOSIN_G(simulation)) {
432 return 0;
433 }
434 }
435 switch (arg) {
436 case PARSE_GET:
437 if (SUHOSIN_G(max_get_value_length) && SUHOSIN_G(max_get_value_length) < val_len) {
438 suhosin_log(S_VARS, "configured GET variable value length limit exceeded - dropped variable '%s'", var);
439 if (!SUHOSIN_G(simulation)) {
440 return 0;
441 }
442 }
443 break;
444 case PARSE_COOKIE:
445 if (SUHOSIN_G(max_cookie_value_length) && SUHOSIN_G(max_cookie_value_length) < val_len) {
446 suhosin_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped variable '%s'", var);
447 if (!SUHOSIN_G(simulation)) {
448 return 0;
449 }
450 }
451 break;
452 case PARSE_POST:
453 if (SUHOSIN_G(max_post_value_length) && SUHOSIN_G(max_post_value_length) < val_len) {
454 suhosin_log(S_VARS, "configured POST variable value length limit exceeded - dropped variable '%s'", var);
455 if (!SUHOSIN_G(simulation)) {
456 return 0;
457 }
458 }
459 break;
460 }
461
462 /* Normalize the variable name */
463 normalize_varname(var);
464
465 /* Find length of variable name */
466 index = strchr(var, '[');
467 total_len = strlen(var);
468 var_len = index ? index-var : total_len;
469
470 /* Drop this variable if it exceeds the varname/total length limit */
471 if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) {
472 suhosin_log(S_VARS, "configured request variable name length limit exceeded - dropped variable '%s'", var);
473 if (!SUHOSIN_G(simulation)) {
474 return 0;
475 }
476 }
477 if (SUHOSIN_G(max_totalname_length) && SUHOSIN_G(max_totalname_length) < total_len) {
478 suhosin_log(S_VARS, "configured request variable total name length limit exceeded - dropped variable '%s'", var);
479 if (!SUHOSIN_G(simulation)) {
480 return 0;
481 }
482 }
483 switch (arg) {
484 case PARSE_GET:
485 if (SUHOSIN_G(max_get_name_length) && SUHOSIN_G(max_get_name_length) < var_len) {
486 suhosin_log(S_VARS, "configured GET variable name length limit exceeded - dropped variable '%s'", var);
487 if (!SUHOSIN_G(simulation)) {
488 return 0;
489 }
490 }
491 if (SUHOSIN_G(max_get_totalname_length) && SUHOSIN_G(max_get_totalname_length) < total_len) {
492 suhosin_log(S_VARS, "configured GET variable total name length limit exceeded - dropped variable '%s'", var);
493 if (!SUHOSIN_G(simulation)) {
494 return 0;
495 }
496 }
497 break;
498 case PARSE_COOKIE:
499 if (SUHOSIN_G(max_cookie_name_length) && SUHOSIN_G(max_cookie_name_length) < var_len) {
500 suhosin_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped variable '%s'", var);
501 if (!SUHOSIN_G(simulation)) {
502 return 0;
503 }
504 }
505 if (SUHOSIN_G(max_cookie_totalname_length) && SUHOSIN_G(max_cookie_totalname_length) < total_len) {
506 suhosin_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped variable '%s'", var);
507 if (!SUHOSIN_G(simulation)) {
508 return 0;
509 }
510 }
511 break;
512 case PARSE_POST:
513 if (SUHOSIN_G(max_post_name_length) && SUHOSIN_G(max_post_name_length) < var_len) {
514 suhosin_log(S_VARS, "configured POST variable name length limit exceeded - dropped variable '%s'", var);
515 if (!SUHOSIN_G(simulation)) {
516 return 0;
517 }
518 }
519 if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < total_len) {
520 suhosin_log(S_VARS, "configured POST variable total name length limit exceeded - dropped variable '%s'", var);
521 if (!SUHOSIN_G(simulation)) {
522 return 0;
523 }
524 }
525 break;
526 }
527
528 /* Find out array depth */
529 while (index) {
530 char *index_end;
531 unsigned int index_length;
532
533 /* overjump '[' */
534 index++;
535
536 /* increase array depth */
537 depth++;
538
539 index_end = strchr(index, ']');
540 if (index_end == NULL) {
541 index_end = index+strlen(index);
542 }
543
544 index_length = index_end - index;
545
546 /* max. array index length */
547 if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) {
548 suhosin_log(S_VARS, "configured request variable array index length limit exceeded - dropped variable '%s'", var);
549 if (!SUHOSIN_G(simulation)) {
550 return 0;
551 }
552 }
553 switch (arg) {
554 case PARSE_GET:
555 if (SUHOSIN_G(max_get_array_index_length) && SUHOSIN_G(max_get_array_index_length) < index_length) {
556 suhosin_log(S_VARS, "configured GET variable array index length limit exceeded - dropped variable '%s'", var);
557 if (!SUHOSIN_G(simulation)) {
558 return 0;
559 }
560 }
561 break;
562 case PARSE_COOKIE:
563 if (SUHOSIN_G(max_cookie_array_index_length) && SUHOSIN_G(max_cookie_array_index_length) < index_length) {
564 suhosin_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped variable '%s'", var);
565 if (!SUHOSIN_G(simulation)) {
566 return 0;
567 }
568 }
569 break;
570 case PARSE_POST:
571 if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) {
572 suhosin_log(S_VARS, "configured POST variable array index length limit exceeded - dropped variable '%s'", var);
573 if (!SUHOSIN_G(simulation)) {
574 return 0;
575 }
576 }
577 break;
578 }
579
580 /* index whitelist/blacklist */
581 if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) {
582 if (suhosin_strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) {
583 suhosin_log(S_VARS, "array index contains not whitelisted characters - dropped variable '%s'", var);
584 if (!SUHOSIN_G(simulation)) {
585 return 0;
586 }
587 }
588 } else if (SUHOSIN_G(array_index_blacklist) && *(SUHOSIN_G(array_index_blacklist))) {
589 if (suhosin_strncspn(index, index_length, SUHOSIN_G(array_index_blacklist)) != index_length) {
590 suhosin_log(S_VARS, "array index contains blacklisted characters - dropped variable '%s'", var);
591 if (!SUHOSIN_G(simulation)) {
592 return 0;
593 }
594 }
595 }
596
597 index = strchr(index, '[');
598 }
599
600 /* Drop this variable if it exceeds the array depth limit */
601 if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) {
602 suhosin_log(S_VARS, "configured request variable array depth limit exceeded - 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(max_get_array_depth) && SUHOSIN_G(max_get_array_depth) < depth) {
610 suhosin_log(S_VARS, "configured GET variable array depth limit exceeded - dropped variable '%s'", var);
611 if (!SUHOSIN_G(simulation)) {
612 return 0;
613 }
614 }
615 break;
616 case PARSE_COOKIE:
617 if (SUHOSIN_G(max_cookie_array_depth) && SUHOSIN_G(max_cookie_array_depth) < depth) {
618 suhosin_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped variable '%s'", var);
619 if (!SUHOSIN_G(simulation)) {
620 return 0;
621 }
622 }
623 break;
624 case PARSE_POST:
625 if (SUHOSIN_G(max_post_array_depth) && SUHOSIN_G(max_post_array_depth) < depth) {
626 suhosin_log(S_VARS, "configured POST variable array depth limit exceeded - dropped variable '%s'", var);
627 if (!SUHOSIN_G(simulation)) {
628 return 0;
629 }
630 }
631 break;
632 }
633
634 /* Check if variable value is truncated by a \0 */
635
636 if (val && *val && val_len != strnlen(*val, val_len)) {
637
638 if (SUHOSIN_G(disallow_nul)) {
639 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within request variables - dropped variable '%s'", var);
640 if (!SUHOSIN_G(simulation)) {
641 return 0;
642 }
643 }
644 switch (arg) {
645 case PARSE_GET:
646 if (SUHOSIN_G(disallow_get_nul)) {
647 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within GET variables - dropped variable '%s'", var);
648 if (!SUHOSIN_G(simulation)) {
649 return 0;
650 }
651 }
652 break;
653 case PARSE_COOKIE:
654 if (SUHOSIN_G(disallow_cookie_nul)) {
655 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within COOKIE variables - dropped variable '%s'", var);
656 if (!SUHOSIN_G(simulation)) {
657 return 0;
658 }
659 }
660 break;
661 case PARSE_POST:
662 if (SUHOSIN_G(disallow_post_nul)) {
663 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within POST variables - dropped variable '%s'", var);
664 if (!SUHOSIN_G(simulation)) {
665 return 0;
666 }
667 }
668 break;
669 }
670 }
671
672 /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
673 /* This is to protect several silly scripts that do globalizing themself */
674 if (suhosin_is_protected_varname(var, var_len)) {
675 suhosin_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
676 if (!SUHOSIN_G(simulation)) {
677 return 0;
678 }
679 }
680
681 /* Okay let PHP register this variable */
682 SUHOSIN_G(cur_request_variables)++;
683 switch (arg) {
684 case PARSE_GET:
685 SUHOSIN_G(cur_get_vars)++;
686 break;
687 case PARSE_COOKIE:
688 SUHOSIN_G(cur_cookie_vars)++;
689 break;
690 case PARSE_POST:
691 SUHOSIN_G(cur_post_vars)++;
692 break;
693 }
694
695 if (new_val_len) {
696 *new_val_len = val_len;
697 }
698
699 return 1;
700}
701/* }}} */
702
703
704
705/* {{{ suhosin_hook_register_server_variables
706 */
707void suhosin_hook_register_server_variables()
708{
709 if (sapi_module.register_server_variables) {
710 orig_register_server_variables = sapi_module.register_server_variables;
711 sapi_module.register_server_variables = suhosin_register_server_variables;
712 }
713}
714/* }}} */
715
716
717/*
718 * Local variables:
719 * tab-width: 4
720 * c-basic-offset: 4
721 * End:
722 * vim600: noet sw=4 ts=4 fdm=marker
723 * vim<600: noet sw=4 ts=4
724 */
725
726
diff --git a/memory_limit.c b/memory_limit.c
new file mode 100644
index 0000000..fa1683e
--- /dev/null
+++ b/memory_limit.c
@@ -0,0 +1,98 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2015 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 $
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_suhosin7.h"
31
32
33/* {{{ PHP_INI_MH
34 */
35static PHP_INI_MH(suhosin_OnChangeMemoryLimit)
36{
37#if SIZEOF_LONG==8
38 long hard_memory_limit = 0x7fffffffffffffff;
39#elif SIZEOF_LONG==4
40 long hard_memory_limit = 0x7fffffff;
41#endif /* will produce a compile error or SIZEOF_LONG is not 4 or 8 */
42 if (stage == ZEND_INI_STAGE_RUNTIME) {
43 if (SUHOSIN7_G(memory_limit) > 0) {
44 SUHOSIN7_G(hard_memory_limit) = SUHOSIN7_G(memory_limit);
45 } else if (SUHOSIN7_G(hard_memory_limit) == 0) {
46 SUHOSIN7_G(hard_memory_limit) = PG(memory_limit);
47 }
48 hard_memory_limit = SUHOSIN7_G(hard_memory_limit);
49 } else {
50 SUHOSIN7_G(hard_memory_limit) = 0;
51 }
52 if (new_value) {
53 PG(memory_limit) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
54 if (hard_memory_limit > 0) {
55 if (PG(memory_limit) > hard_memory_limit) {
56 suhosin_log(S_MISC, "script tried to increase memory_limit to " ZEND_LONG_FMT " bytes which is above the allowed value", PG(memory_limit));
57 if (!SUHOSIN7_G(simulation)) {
58 PG(memory_limit) = hard_memory_limit;
59 return FAILURE;
60 }
61 } else if (PG(memory_limit) < 0) {
62 suhosin_log(S_MISC, "script tried to disable memory_limit by setting it to a negative value " ZEND_LONG_FMT " bytes which is not allowed", PG(memory_limit));
63 if (!SUHOSIN7_G(simulation)) {
64 PG(memory_limit) = hard_memory_limit;
65 return FAILURE;
66 }
67 }
68 }
69 } else {
70 PG(memory_limit) = hard_memory_limit;
71 }
72 return zend_set_memory_limit(PG(memory_limit));
73}
74/* }}} */
75
76
77void suhosin_hook_memory_limit()
78{
79 zend_ini_entry *ini_entry;
80
81 /* check if we are compiled against memory_limit */
82 if ((ini_entry=zend_hash_str_find_ptr(EG(ini_directives), "memory_limit", sizeof("memory_limit")-1))) {
83 /* replace OnUpdateMemoryLimit handler */
84 ini_entry->on_modify = suhosin_OnChangeMemoryLimit;
85 }
86
87}
88
89
90/*
91 * Local variables:
92 * tab-width: 4
93 * c-basic-offset: 4
94 * End:
95 * vim600: noet sw=4 ts=4 fdm=marker
96 * vim<600: noet sw=4 ts=4
97 */
98
diff --git a/php_suhosin7.h b/php_suhosin7.h
new file mode 100644
index 0000000..805701e
--- /dev/null
+++ b/php_suhosin7.h
@@ -0,0 +1,191 @@
1/*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2015 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$ */
20
21#ifndef PHP_SUHOSIN7_H
22#define PHP_SUHOSIN7_H
23
24extern zend_module_entry suhosin7_module_entry;
25#define phpext_suhosin7_ptr &suhosin7_module_entry
26
27#define SUHOSIN7_EXT_VERSION "0.10.0"
28
29#ifdef PHP_WIN32
30# define PHP_SUHOSIN7_API __declspec(dllexport)
31#elif defined(__GNUC__) && __GNUC__ >= 4
32# define PHP_SUHOSIN7_API __attribute__ ((visibility("default")))
33#else
34# define PHP_SUHOSIN7_API
35#endif
36
37#ifdef ZTS
38#include "TSRM.h"
39#endif
40
41#define BYTE unsigned char /* 8 bits */
42#define WORD unsigned int /* 32 bits */
43
44ZEND_BEGIN_MODULE_GLOBALS(suhosin7)
45 zend_long global_value;
46 char *global_string;
47 zend_bool protectkey;
48
49 zend_bool simulation;
50 zend_bool already_scanned;
51 zend_bool abort_request;
52
53/* request variables */
54 zend_long max_request_variables;
55 zend_long cur_request_variables;
56 zend_long att_request_variables;
57 zend_long max_varname_length;
58 zend_long max_totalname_length;
59 zend_long max_value_length;
60 zend_long max_array_depth;
61 zend_long max_array_index_length;
62 char* array_index_whitelist;
63 char* array_index_blacklist;
64 zend_bool disallow_nul;
65 zend_bool disallow_ws;
66/* cookie variables */
67 zend_long max_cookie_vars;
68 zend_long cur_cookie_vars;
69 zend_long att_cookie_vars;
70 zend_long max_cookie_name_length;
71 zend_long max_cookie_totalname_length;
72 zend_long max_cookie_value_length;
73 zend_long max_cookie_array_depth;
74 zend_long max_cookie_array_index_length;
75 zend_bool disallow_cookie_nul;
76 zend_bool disallow_cookie_ws;
77/* get variables */
78 zend_long max_get_vars;
79 zend_long cur_get_vars;
80 zend_long att_get_vars;
81 zend_long max_get_name_length;
82 zend_long max_get_totalname_length;
83 zend_long max_get_value_length;
84 zend_long max_get_array_depth;
85 zend_long max_get_array_index_length;
86 zend_bool disallow_get_nul;
87 zend_bool disallow_get_ws;
88/* post variables */
89 zend_long max_post_vars;
90 zend_long cur_post_vars;
91 zend_long att_post_vars;
92 zend_long max_post_name_length;
93 zend_long max_post_totalname_length;
94 zend_long max_post_value_length;
95 zend_long max_post_array_depth;
96 zend_long max_post_array_index_length;
97 zend_bool disallow_post_nul;
98 zend_bool disallow_post_ws;
99
100/* fileupload */
101 zend_long upload_limit;
102 zend_long upload_max_newlines;
103 zend_long num_uploads;
104 zend_bool upload_disallow_elf;
105 zend_bool upload_disallow_binary;
106 zend_bool upload_remove_binary;
107#ifdef SUHOSIN_EXPERIMENTAL
108 zend_bool upload_allow_utf8;
109#endif
110 char *upload_verification_script;
111
112 zend_bool no_more_variables;
113 zend_bool no_more_get_variables;
114 zend_bool no_more_post_variables;
115 zend_bool no_more_cookie_variables;
116 zend_bool no_more_uploads;
117
118 BYTE fi[24],ri[24];
119 WORD fkey[120];
120 WORD rkey[120];
121
122/* memory_limit */
123 zend_long memory_limit;
124 zend_long hard_memory_limit;
125
126 char* decrypted_cookie;
127 char* raw_cookie;
128 zend_bool cookie_encrypt;
129 char* cookie_cryptkey;
130 zend_bool cookie_cryptua;
131 zend_bool cookie_cryptdocroot;
132 long cookie_cryptraddr;
133 long cookie_checkraddr;
134 HashTable *cookie_plainlist;
135 HashTable *cookie_cryptlist;
136ZEND_END_MODULE_GLOBALS(suhosin7)
137
138/* Always refer to the globals in your function as SUHOSIN7_G(variable).
139 You are encouraged to rename these macros something shorter, see
140 examples in any other php module directory.
141*/
142#define SUHOSIN7_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(suhosin7, v)
143
144#if defined(ZTS) && defined(COMPILE_DL_SUHOSIN7)
145ZEND_TSRMLS_CACHE_EXTERN();
146#endif
147
148/* Error Constants */
149#ifndef S_MEMORY
150#define S_MEMORY (1<<0L)
151#define S_MISC (1<<1L)
152#define S_VARS (1<<2L)
153#define S_FILES (1<<3L)
154#define S_INCLUDE (1<<4L)
155#define S_SQL (1<<5L)
156#define S_EXECUTOR (1<<6L)
157#define S_MAIL (1<<7L)
158#define S_SESSION (1<<8L)
159#define S_INTERNAL (1<<29L)
160#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR)
161#endif
162
163#ifndef S_GETCALLER
164#define S_GETCALLER (1<<30L)
165#endif
166
167#define SUHOSIN_NORMAL 0
168#define SUHOSIN_EVAL 1
169
170#define SUHOSIN_FLAG_CREATED_BY_EVAL 1
171#define SUHOSIN_FLAG_NOT_EVALED_CODE 2
172
173ZEND_EXTERN_MODULE_GLOBALS(suhosin7)
174
175unsigned int suhosin_input_filter(int arg, char *var, char **val, size_t val_len, size_t *new_val_len);
176unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, size_t val_len, size_t *new_val_len);
177void suhosin_log(int loglevel, char *fmt, ...);
178extern unsigned int (*old_input_filter)(int arg, char *var, char **val, size_t val_len, size_t *new_val_len);
179
180
181#endif /* PHP_SUHOSIN7_H */
182
183
184/*
185 * Local variables:
186 * tab-width: 4
187 * c-basic-offset: 4
188 * End:
189 * vim600: noet sw=4 ts=4 fdm=marker
190 * vim<600: noet sw=4 ts=4
191 */
diff --git a/sha256.c b/sha256.c
new file mode 100644
index 0000000..bf938c4
--- /dev/null
+++ b/sha256.c
@@ -0,0 +1,413 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2015 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 $ */
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);
62 } else {
63 make_sha256_digest(sha256str, digest);
64 RETVAL_STRING(sha256str);
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 php_stream *stream;
84
85 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
86 return;
87 }
88
89 stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
90 if (!stream) {
91 RETURN_FALSE;
92 }
93
94 suhosin_SHA256Init(&context);
95
96 while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
97 suhosin_SHA256Update(&context, buf, n);
98 }
99
100 suhosin_SHA256Final(digest, &context);
101
102 php_stream_close(stream);
103
104 if (n<0) {
105 RETURN_FALSE;
106 }
107
108 if (raw_output) {
109 RETURN_STRINGL((char *)digest, 32);
110 } else {
111 make_sha256_digest(sha256str, digest);
112 RETVAL_STRING(sha256str);
113 }
114}
115/* }}} */
116
117
118static void SHA256Transform(php_uint32[8], const unsigned char[64]);
119static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
120static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
121
122static unsigned char PADDING[64] =
123{
124 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0
127};
128
129/* F, G, H and I are basic SHA256 functions.
130 */
131#define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22))
132#define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x))))
133#define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25))
134#define I(x, y, z) (((x) & (y)) | ((~x) & z))
135
136/* ROTATE_RIGHT rotates x right n bits.
137 */
138#define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
139
140/* W[i]
141 */
142#define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \
143 tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \
144 (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) )
145
146/* ROUND function of sha256
147 */
148
149#define ROUND(a,b,c,d,e,f,g,h,w,k) { \
150 t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \
151 (h) = F((a)) + G((a), (b), (c)) + t1; \
152 (d) += t1; \
153 }
154
155
156/* {{{ suhosin_SHA256Init
157 * SHA256 initialization. Begins an SHA256 operation, writing a new context.
158 */
159void suhosin_SHA256Init(suhosin_SHA256_CTX * context)
160{
161 context->count[0] = context->count[1] = 0;
162 /* Load magic initialization constants.
163 */
164 context->state[0] = 0x6a09e667;
165 context->state[1] = 0xbb67ae85;
166 context->state[2] = 0x3c6ef372;
167 context->state[3] = 0xa54ff53a;
168 context->state[4] = 0x510e527f;
169 context->state[5] = 0x9b05688c;
170 context->state[6] = 0x1f83d9ab;
171 context->state[7] = 0x5be0cd19;
172}
173/* }}} */
174
175/* {{{ suhosin_SHA256Update
176 SHA256 block update operation. Continues an SHA256 message-digest
177 operation, processing another message block, and updating the
178 context.
179 */
180void suhosin_SHA256Update(suhosin_SHA256_CTX * context, const unsigned char *input,
181 unsigned int inputLen)
182{
183 unsigned int i, index, partLen;
184
185 /* Compute number of bytes mod 64 */
186 index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
187
188 /* Update number of bits */
189 if ((context->count[0] += ((php_uint32) inputLen << 3))
190 < ((php_uint32) inputLen << 3))
191 context->count[1]++;
192 context->count[1] += ((php_uint32) inputLen >> 29);
193
194 partLen = 64 - index;
195
196 /* Transform as many times as possible.
197 */
198 if (inputLen >= partLen) {
199 memcpy
200 ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
201 SHA256Transform(context->state, context->buffer);
202
203 for (i = partLen; i + 63 < inputLen; i += 64)
204 SHA256Transform(context->state, &input[i]);
205
206 index = 0;
207 } else
208 i = 0;
209
210 /* Buffer remaining input */
211 memcpy
212 ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
213 inputLen - i);
214}
215/* }}} */
216
217/* {{{ suhosin_SHA256Final
218 SHA256 finalization. Ends an SHA256 message-digest operation, writing the
219 the message digest and zeroizing the context.
220 */
221void suhosin_SHA256Final(unsigned char digest[32], suhosin_SHA256_CTX * context)
222{
223 unsigned char bits[8];
224 unsigned int index, padLen;
225
226 /* Save number of bits */
227 bits[7] = context->count[0] & 0xFF;
228 bits[6] = (context->count[0] >> 8) & 0xFF;
229 bits[5] = (context->count[0] >> 16) & 0xFF;
230 bits[4] = (context->count[0] >> 24) & 0xFF;
231 bits[3] = context->count[1] & 0xFF;
232 bits[2] = (context->count[1] >> 8) & 0xFF;
233 bits[1] = (context->count[1] >> 16) & 0xFF;
234 bits[0] = (context->count[1] >> 24) & 0xFF;
235
236 /* Pad out to 56 mod 64.
237 */
238 index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
239 padLen = (index < 56) ? (56 - index) : (120 - index);
240 suhosin_SHA256Update(context, PADDING, padLen);
241
242 /* Append length (before padding) */
243 suhosin_SHA256Update(context, bits, 8);
244
245 /* Store state in digest */
246 SHA256Encode(digest, context->state, 32);
247
248 /* Zeroize sensitive information.
249 */
250 memset((unsigned char*) context, 0, sizeof(*context));
251}
252/* }}} */
253
254/* {{{ SHA256Transform
255 * SHA256 basic transformation. Transforms state based on block.
256 */
257static void SHA256Transform(state, block)
258php_uint32 state[8];
259const unsigned char block[64];
260{
261 php_uint32 a = state[0], b = state[1], c = state[2];
262 php_uint32 d = state[3], e = state[4], f = state[5];
263 php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1;
264
265 SHA256Decode(x, block, 64);
266
267 ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98)
268 ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491)
269 ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf)
270 ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5)
271 ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b)
272 ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1)
273 ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4)
274 ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5)
275 ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98)
276 ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01)
277 ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be)
278 ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3)
279 ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74)
280 ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe)
281 ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7)
282 ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174)
283 ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1)
284 ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786)
285 ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6)
286 ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc)
287 ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f)
288 ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa)
289 ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc)
290 ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da)
291 ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152)
292 ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d)
293 ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8)
294 ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7)
295 ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3)
296 ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147)
297 ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351)
298 ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967)
299 ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85)
300 ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138)
301 ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc)
302 ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13)
303 ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354)
304 ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb)
305 ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e)
306 ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85)
307 ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1)
308 ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b)
309 ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70)
310 ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3)
311 ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819)
312 ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624)
313 ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585)
314 ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070)
315 ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116)
316 ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08)
317 ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c)
318 ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5)
319 ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3)
320 ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a)
321 ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f)
322 ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3)
323 ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee)
324 ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f)
325 ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814)
326 ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208)
327 ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa)
328 ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb)
329 ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7)
330 ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2)
331
332 state[0] += a;
333 state[1] += b;
334 state[2] += c;
335 state[3] += d;
336 state[4] += e;
337 state[5] += f;
338 state[6] += g;
339 state[7] += h;
340
341 /* Zeroize sensitive information. */
342 memset((unsigned char*) x, 0, sizeof(x));
343}
344/* }}} */
345
346/* {{{ SHA256Encode
347 Encodes input (php_uint32) into output (unsigned char). Assumes len is
348 a multiple of 4.
349 */
350static void SHA256Encode(output, input, len)
351unsigned char *output;
352php_uint32 *input;
353unsigned int len;
354{
355 unsigned int i, j;
356
357 for (i = 0, j = 0; j < len; i++, j += 4) {
358 output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
359 output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
360 output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
361 output[j + 3] = (unsigned char) (input[i] & 0xff);
362 }
363}
364/* }}} */
365
366/* {{{ SHA256Decode
367 Decodes input (unsigned char) into output (php_uint32). Assumes len is
368 a multiple of 4.
369 */
370static void SHA256Decode(output, input, len)
371php_uint32 *output;
372const unsigned char *input;
373unsigned int len;
374{
375 unsigned int i, j;
376
377 for (i = 0, j = 0; j < len; i++, j += 4)
378 output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
379 (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
380}
381/* }}} */
382
383
384/* {{{ suhosin_sha256_functions[]
385 */
386static zend_function_entry suhosin_sha256_functions[] = {
387 PHP_NAMED_FE(sha256, PHP_FN(suhosin_sha256), NULL)
388 PHP_NAMED_FE(sha256_file, PHP_FN(suhosin_sha256_file), NULL)
389 {NULL, NULL, NULL}
390};
391/* }}} */
392
393
394void suhosin_hook_sha256(TSRMLS_D)
395{
396 /* check if we already have sha256 support */
397 if (zend_hash_str_find(CG(function_table), "sha256", sizeof("sha256"))) {
398 return;
399 }
400
401 /* add the sha256 functions */
402 zend_register_functions(NULL, suhosin_sha256_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
403}
404
405
406/*
407 * Local variables:
408 * tab-width: 4
409 * c-basic-offset: 4
410 * End:
411 * vim600: sw=4 ts=4 fdm=marker
412 * vim<600: sw=4 ts=4
413 */
diff --git a/sha256.h b/sha256.h
new file mode 100644
index 0000000..d728506
--- /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-2015 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 $ */
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/suhosin7.c b/suhosin7.c
new file mode 100644
index 0000000..ebea5ab
--- /dev/null
+++ b/suhosin7.c
@@ -0,0 +1,209 @@
1/*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2015 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$ */
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "php.h"
26#include "php_ini.h"
27#include "SAPI.h"
28#include "php_suhosin7.h"
29#include "suhosin7_logo.h"
30#include "ext/standard/base64.h"
31#include "ext/standard/info.h"
32
33
34ZEND_DECLARE_MODULE_GLOBALS(suhosin7)
35
36/* True global resources - no need for thread safety here */
37static int le_suhosin7;
38
39/* {{{ PHP_INI
40 */
41PHP_INI_BEGIN()
42 STD_ZEND_INI_BOOLEAN("suhosin.protectkey", "1", ZEND_INI_SYSTEM, OnUpdateBool, protectkey, zend_suhosin7_globals, suhosin7_globals)
43 STD_ZEND_INI_BOOLEAN("suhosin.cookie.cryptkey", "1", ZEND_INI_SYSTEM, OnUpdateBool, protectkey, zend_suhosin7_globals, suhosin7_globals)
44 STD_PHP_INI_ENTRY("suhosin.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_suhosin7_globals, suhosin7_globals)
45 STD_PHP_INI_ENTRY("suhosin.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_suhosin7_globals, suhosin7_globals)
46PHP_INI_END()
47/* }}} */
48
49
50
51/* {{{ php_suhosin7_init_globals
52 */
53static void php_suhosin7_init_globals(zend_suhosin7_globals *suhosin7_globals)
54{
55 memset(suhosin7_globals, 0, sizeof(zend_suhosin7_globals));
56}
57/* }}} */
58
59
60/* {{{ PHP_MINIT_FUNCTION
61 */
62PHP_MINIT_FUNCTION(suhosin7)
63{
64 REGISTER_INI_ENTRIES();
65 return SUCCESS;
66}
67/* }}} */
68
69/* {{{ PHP_MSHUTDOWN_FUNCTION
70 */
71PHP_MSHUTDOWN_FUNCTION(suhosin7)
72{
73 UNREGISTER_INI_ENTRIES();
74 return SUCCESS;
75}
76/* }}} */
77
78/* Remove if there's nothing to do at request start */
79/* {{{ PHP_RINIT_FUNCTION
80 */
81PHP_RINIT_FUNCTION(suhosin7)
82{
83#if defined(COMPILE_DL_SUHOSIN7) && defined(ZTS)
84 ZEND_TSRMLS_CACHE_UPDATE();
85#endif
86 return SUCCESS;
87}
88/* }}} */
89
90/* Remove if there's nothing to do at request end */
91/* {{{ PHP_RSHUTDOWN_FUNCTION
92 */
93PHP_RSHUTDOWN_FUNCTION(suhosin7)
94{
95 return SUCCESS;
96}
97/* }}} */
98
99/* {{{ suhosin_ini_displayer(zend_ini_entry *ini_entry, int type)
100 */
101static void suhosin_ini_displayer(zend_ini_entry *ini_entry, int type)
102{
103 PHPWRITE("[ protected ]", strlen("[ protected ]"));
104}
105/* }}} */
106
107/* {{{ PHP_MINFO_FUNCTION
108 */
109PHP_MINFO_FUNCTION(suhosin7)
110{
111 php_info_print_box_start(0);
112 if (!sapi_module.phpinfo_as_text) {
113 do {
114 zend_string *enc_logo;
115
116 PUTS("<a href=\"http://www.suhosin.org/\"><img border=\"0\" src=\"data:image/jpeg;base64,");
117 enc_logo = php_base64_encode(suhosin_logo, sizeof(suhosin_logo));
118 if (ZSTR_LEN(enc_logo)) {
119 PHPWRITE(ZSTR_VAL(enc_logo), ZSTR_LEN(enc_logo));
120 }
121 zend_string_free(enc_logo);
122 PUTS("\" alt=\"Suhosin logo\" /></a>\n");
123 } while(0);
124 }
125 PUTS("This server is protected with the Suhosin Extension " SUHOSIN7_EXT_VERSION);
126 PUTS(!sapi_module.phpinfo_as_text?"<br /><br />":"\n\n");
127 if (sapi_module.phpinfo_as_text) {
128 PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n");
129 PUTS("Copyright (c) 2007-2015 SektionEins GmbH\n");
130 } else {
131 PUTS("Copyright (c) 2006-2007 <a href=\"http://www.hardened-php.net/\">Hardened-PHP Project</a><br />\n");
132 PUTS("Copyright (c) 2007-2015 <a href=\"http://www.sektioneins.de/\">SektionEins GmbH</a>\n");
133 }
134 php_info_print_box_end();
135
136 if (SUHOSIN7_G(protectkey)) {
137 zend_ini_entry *i;
138
139 if ((i=zend_hash_str_find_ptr(EG(ini_directives), "suhosin.cookie.cryptkey", sizeof("suhosin.cookie.cryptkey")-1))) {
140 i->displayer = suhosin_ini_displayer;
141 }
142 if ((i=zend_hash_str_find_ptr(EG(ini_directives), "suhosin.session.cryptkey", sizeof("suhosin.session.cryptkey")-1))) {
143 i->displayer = suhosin_ini_displayer;
144 }
145 if ((i=zend_hash_str_find_ptr(EG(ini_directives), "suhosin.rand.seedingkey", sizeof("suhosin.rand.seedingkey")-1))) {
146 i->displayer = suhosin_ini_displayer;
147 }
148 }
149
150 DISPLAY_INI_ENTRIES();
151
152 if (SUHOSIN7_G(protectkey)) {
153 zend_ini_entry *i;
154
155 if ((i=zend_hash_str_find_ptr(EG(ini_directives), "suhosin.cookie.cryptkey", sizeof("suhosin.cookie.cryptkey")))) {
156 i->displayer = NULL;
157 }
158 if ((i=zend_hash_str_find_ptr(EG(ini_directives), "suhosin.session.cryptkey", sizeof("suhosin.session.cryptkey")-1))) {
159 i->displayer = NULL;
160 }
161 if ((i=zend_hash_str_find_ptr(EG(ini_directives), "suhosin.rand.seedingkey", sizeof("suhosin.rand.seedingkey")-1))) {
162 i->displayer = NULL;
163 }
164 }
165
166}
167/* }}} */
168
169/* {{{ suhosin7_functions[]
170 *
171 * Every user visible function must have an entry in suhosin7_functions[].
172 */
173const zend_function_entry suhosin7_functions[] = {
174// PHP_FE(confirm_suhosin7_compiled, NULL) /* For testing, remove later. */
175 PHP_FE_END
176};
177/* }}} */
178
179/* {{{ suhosin7_module_entry
180 */
181zend_module_entry suhosin7_module_entry = {
182 STANDARD_MODULE_HEADER,
183 "suhosin7",
184 suhosin7_functions,
185 PHP_MINIT(suhosin7),
186 PHP_MSHUTDOWN(suhosin7),
187 PHP_RINIT(suhosin7), /* Replace with NULL if there's nothing to do at request start */
188 PHP_RSHUTDOWN(suhosin7), /* Replace with NULL if there's nothing to do at request end */
189 PHP_MINFO(suhosin7),
190 SUHOSIN7_EXT_VERSION,
191 STANDARD_MODULE_PROPERTIES
192};
193/* }}} */
194
195#ifdef COMPILE_DL_SUHOSIN7
196#ifdef ZTS
197ZEND_TSRMLS_CACHE_DEFINE();
198#endif
199ZEND_GET_MODULE(suhosin7)
200#endif
201
202/*
203 * Local variables:
204 * tab-width: 4
205 * c-basic-offset: 4
206 * End:
207 * vim600: noet sw=4 ts=4 fdm=marker
208 * vim<600: noet sw=4 ts=4
209 */
diff --git a/suhosin7_logo.h b/suhosin7_logo.h
new file mode 100644
index 0000000..455bd59
--- /dev/null
+++ b/suhosin7_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/tests/001.phpt b/tests/001.phpt
new file mode 100644
index 0000000..8e68413
--- /dev/null
+++ b/tests/001.phpt
@@ -0,0 +1,21 @@
1--TEST--
2Check for suhosin7 presence
3--SKIPIF--
4<?php if (!extension_loaded("suhosin7")) print "skip"; ?>
5--FILE--
6<?php
7echo "suhosin7 extension is available";
8/*
9 you can add regression tests for your extension here
10
11 the output of your test code has to be equal to the
12 text in the --EXPECT-- section below for the tests
13 to pass, differences between the output and the
14 expected text are interpreted as failure
15
16 see php7/README.TESTING for further information on
17 writing regression tests
18*/
19?>
20--EXPECT--
21suhosin7 extension is available
diff --git a/treat_data.c b/treat_data.c
new file mode 100644
index 0000000..86fcd9f
--- /dev/null
+++ b/treat_data.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-2015 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 $
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_suhosin7.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;
39 int free_buffer = 0;
40 char *strtok_buf = NULL;
41 zend_long count = 0;
42
43 /* Mark that we were not yet called */
44 SUHOSIN7_G(already_scanned) = 0;
45
46 ZVAL_UNDEF(&array);
47 switch (arg) {
48 case PARSE_POST:
49 case PARSE_GET:
50 case PARSE_COOKIE:
51 array_init(&array);
52 switch (arg) {
53 case PARSE_POST:
54 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
55 ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &array);
56 if (SUHOSIN7_G(max_request_variables) && (SUHOSIN7_G(max_post_vars) == 0 ||
57 SUHOSIN7_G(max_request_variables) <= SUHOSIN7_G(max_post_vars))) {
58 SUHOSIN7_G(max_post_vars) = SUHOSIN7_G(max_request_variables);
59 }
60 break;
61 case PARSE_GET:
62 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
63 ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_GET], &array);
64 if (SUHOSIN7_G(max_request_variables) && (SUHOSIN7_G(max_get_vars) == 0 ||
65 SUHOSIN7_G(max_request_variables) <= SUHOSIN7_G(max_get_vars))) {
66 SUHOSIN7_G(max_get_vars) = SUHOSIN7_G(max_request_variables);
67 }
68 break;
69 case PARSE_COOKIE:
70 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
71 ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_COOKIE], &array);
72 if (SUHOSIN7_G(max_request_variables) && (SUHOSIN7_G(max_cookie_vars) == 0 ||
73 SUHOSIN7_G(max_request_variables) <= SUHOSIN7_G(max_cookie_vars))) {
74 SUHOSIN7_G(max_cookie_vars) = SUHOSIN7_G(max_request_variables);
75 }
76 break;
77 }
78 break;
79 default:
80 ZVAL_COPY_VALUE(&array, destArray);
81 break;
82 }
83
84 if (arg == PARSE_POST) {
85 sapi_handle_post(&array);
86 return;
87 }
88
89 if (arg == PARSE_GET) { /* GET data */
90 c_var = SG(request_info).query_string;
91 if (c_var && *c_var) {
92 res = (char *) estrdup(c_var);
93 free_buffer = 1;
94 } else {
95 free_buffer = 0;
96 }
97 } else if (arg == PARSE_COOKIE) { /* Cookie data */
98 c_var = SG(request_info).cookie_data;
99 if (c_var && *c_var) {
100 if (SUHOSIN7_G(cookie_encrypt)) {
101 res = (char *) estrdup(suhosin_cookie_decryptor());
102 } else {
103 res = (char *) estrdup(c_var);
104 }
105 free_buffer = 1;
106 } else {
107 free_buffer = 0;
108 }
109 } else if (arg == PARSE_STRING) { /* String data */
110 res = str;
111 free_buffer = 1;
112 }
113
114 if (!res) {
115 return;
116 }
117
118 switch (arg) {
119 case PARSE_GET:
120 case PARSE_STRING:
121 separator = (char *) estrdup(PG(arg_separator).input);
122 break;
123 case PARSE_COOKIE:
124 separator = ";\0";
125 break;
126 }
127
128 var = php_strtok_r(res, separator, &strtok_buf);
129
130 while (var) {
131 val = strchr(var, '=');
132
133 if (arg == PARSE_COOKIE) {
134 /* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */
135 while (isspace(*var)) {
136 var++;
137 }
138 if (var == val || *var == '\0') {
139 goto next_cookie;
140 }
141 }
142
143 if (++count > PG(max_input_vars)) {
144 php_error_docref(NULL, E_WARNING, "Input variables exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
145 break;
146 }
147
148 if (val) { /* have a value */
149 size_t val_len;
150 size_t new_val_len;
151
152 *val++ = '\0';
153 php_url_decode(var, strlen(var));
154 val_len = php_url_decode(val, strlen(val));
155 val = estrndup(val, val_len);
156 if (suhosin_input_filter(arg, var, &val, val_len, &new_val_len)) {
157 if (sapi_module.input_filter(arg, var, &val, new_val_len, &new_val_len)) {
158 php_register_variable_safe(var, val, new_val_len, &array);
159 }
160 } else {
161 SUHOSIN7_G(abort_request) = 1;
162 }
163 efree(val);
164 } else {
165 size_t val_len;
166 size_t new_val_len;
167
168 php_url_decode(var, strlen(var));
169 val_len = 0;
170 val = estrndup("", val_len);
171 if (suhosin_input_filter(arg, var, &val, val_len, &new_val_len)) {
172 if (sapi_module.input_filter(arg, var, &val, new_val_len, &new_val_len)) {
173 php_register_variable_safe(var, val, new_val_len, &array);
174 }
175 } else {
176 SUHOSIN7_G(abort_request) = 1;
177 }
178 efree(val);
179 }
180next_cookie:
181 var = php_strtok_r(NULL, separator, &strtok_buf);
182 }
183
184 if (arg != PARSE_COOKIE) {
185 efree(separator);
186 }
187
188 if (free_buffer) {
189 efree(res);
190 }
191
192}
193
194
195void suhosin_hook_treat_data()
196{
197 sapi_register_treat_data(suhosin_treat_data);
198
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}
204
205
206/*
207 * Local variables:
208 * tab-width: 4
209 * c-basic-offset: 4
210 * End:
211 * vim600: noet sw=4 ts=4 fdm=marker
212 * vim<600: noet sw=4 ts=4
213 */
214