diff options
| author | Stefan Esser | 2015-12-17 16:35:34 +0100 |
|---|---|---|
| committer | Stefan Esser | 2015-12-17 16:35:34 +0100 |
| commit | c4c9192839ba7842f5da58f5fd525056c77cfe54 (patch) | |
| tree | 810854ddb53e03d7320570ec8d634390a849d6b2 | |
| parent | aee7faf18880573b60606756a61faea32a1bb89a (diff) | |
Continue the actual porting work on GitHub
| -rw-r--r-- | CREDITS | 3 | ||||
| -rw-r--r-- | aes.c | 382 | ||||
| -rw-r--r-- | config.m4 | 17 | ||||
| -rw-r--r-- | config.w32 | 13 | ||||
| -rw-r--r-- | ifilter.c | 726 | ||||
| -rw-r--r-- | memory_limit.c | 98 | ||||
| -rw-r--r-- | php_suhosin7.h | 191 | ||||
| -rw-r--r-- | sha256.c | 413 | ||||
| -rw-r--r-- | sha256.h | 38 | ||||
| -rw-r--r-- | suhosin7.c | 209 | ||||
| -rw-r--r-- | suhosin7_logo.h | 180 | ||||
| -rw-r--r-- | tests/001.phpt | 21 | ||||
| -rw-r--r-- | treat_data.c | 214 |
13 files changed, 2505 insertions, 0 deletions
| @@ -0,0 +1,3 @@ | |||
| 1 | suhosin7 | ||
| 2 | Stefan Esser | ||
| 3 | Ben Fuhrmannek | ||
| @@ -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 | |||
| 48 | static BYTE InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */ | ||
| 49 | |||
| 50 | static BYTE fbsub[256]; | ||
| 51 | static BYTE rbsub[256]; | ||
| 52 | static BYTE ptab[256],ltab[256]; | ||
| 53 | static WORD ftable[256]; | ||
| 54 | static WORD rtable[256]; | ||
| 55 | static WORD rco[30]; | ||
| 56 | |||
| 57 | /* Parameter-dependent data */ | ||
| 58 | |||
| 59 | static int Nk,Nb,Nr; | ||
| 60 | |||
| 61 | static WORD pack(BYTE *b) | ||
| 62 | { /* pack bytes into a 32-bit Word */ | ||
| 63 | return ((WORD)b[3]<<24)|((WORD)b[2]<<16)|((WORD)b[1]<<8)|(WORD)b[0]; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void unpack(WORD a,BYTE *b) | ||
| 67 | { /* unpack bytes from a word */ | ||
| 68 | b[0]=(BYTE)a; | ||
| 69 | b[1]=(BYTE)(a>>8); | ||
| 70 | b[2]=(BYTE)(a>>16); | ||
| 71 | b[3]=(BYTE)(a>>24); | ||
| 72 | } | ||
| 73 | |||
| 74 | static BYTE xtime(BYTE a) | ||
| 75 | { | ||
| 76 | BYTE b; | ||
| 77 | if (a&0x80) b=0x1B; | ||
| 78 | else b=0; | ||
| 79 | a<<=1; | ||
| 80 | a^=b; | ||
| 81 | return a; | ||
| 82 | } | ||
| 83 | |||
| 84 | static BYTE bmul(BYTE x,BYTE y) | ||
| 85 | { /* x.y= AntiLog(Log(x) + Log(y)) */ | ||
| 86 | if (x && y) return ptab[(ltab[x]+ltab[y])%255]; | ||
| 87 | else return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static WORD SubByte(WORD a) | ||
| 91 | { | ||
| 92 | BYTE b[4]; | ||
| 93 | unpack(a,b); | ||
| 94 | b[0]=fbsub[b[0]]; | ||
| 95 | b[1]=fbsub[b[1]]; | ||
| 96 | b[2]=fbsub[b[2]]; | ||
| 97 | b[3]=fbsub[b[3]]; | ||
| 98 | return pack(b); | ||
| 99 | } | ||
| 100 | |||
| 101 | static BYTE product(WORD x,WORD y) | ||
| 102 | { /* dot product of two 4-byte arrays */ | ||
| 103 | BYTE xb[4],yb[4]; | ||
| 104 | unpack(x,xb); | ||
| 105 | unpack(y,yb); | ||
| 106 | return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]); | ||
| 107 | } | ||
| 108 | |||
| 109 | static WORD InvMixCol(WORD x) | ||
| 110 | { /* matrix Multiplication */ | ||
| 111 | WORD y,m; | ||
| 112 | BYTE b[4]; | ||
| 113 | |||
| 114 | m=pack(InCo); | ||
| 115 | b[3]=product(m,x); | ||
| 116 | m=ROTL24(m); | ||
| 117 | b[2]=product(m,x); | ||
| 118 | m=ROTL24(m); | ||
| 119 | b[1]=product(m,x); | ||
| 120 | m=ROTL24(m); | ||
| 121 | b[0]=product(m,x); | ||
| 122 | y=pack(b); | ||
| 123 | return y; | ||
| 124 | } | ||
| 125 | |||
| 126 | static BYTE ByteSub(BYTE x) | ||
| 127 | { | ||
| 128 | BYTE y=ptab[255-ltab[x]]; /* multiplicative inverse */ | ||
| 129 | x=y; x=ROTL(x); | ||
| 130 | y^=x; x=ROTL(x); | ||
| 131 | y^=x; x=ROTL(x); | ||
| 132 | y^=x; x=ROTL(x); | ||
| 133 | y^=x; y^=0x63; | ||
| 134 | return y; | ||
| 135 | } | ||
| 136 | |||
| 137 | void suhosin_aes_gentables() | ||
| 138 | { /* generate tables */ | ||
| 139 | int i; | ||
| 140 | BYTE y,b[4]; | ||
| 141 | |||
| 142 | /* use 3 as primitive root to generate power and log tables */ | ||
| 143 | |||
| 144 | ltab[0]=0; | ||
| 145 | ptab[0]=1; ltab[1]=0; | ||
| 146 | ptab[1]=3; ltab[3]=1; | ||
| 147 | for (i=2;i<256;i++) | ||
| 148 | { | ||
| 149 | ptab[i]=ptab[i-1]^xtime(ptab[i-1]); | ||
| 150 | ltab[ptab[i]]=i; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* affine transformation:- each bit is xored with itself shifted one bit */ | ||
| 154 | |||
| 155 | fbsub[0]=0x63; | ||
| 156 | rbsub[0x63]=0; | ||
| 157 | for (i=1;i<256;i++) | ||
| 158 | { | ||
| 159 | y=ByteSub((BYTE)i); | ||
| 160 | fbsub[i]=y; rbsub[y]=i; | ||
| 161 | } | ||
| 162 | |||
| 163 | for (i=0,y=1;i<30;i++) | ||
| 164 | { | ||
| 165 | rco[i]=y; | ||
| 166 | y=xtime(y); | ||
| 167 | } | ||
| 168 | |||
| 169 | /* calculate forward and reverse tables */ | ||
| 170 | for (i=0;i<256;i++) | ||
| 171 | { | ||
| 172 | y=fbsub[i]; | ||
| 173 | b[3]=y^xtime(y); b[2]=y; | ||
| 174 | b[1]=y; b[0]=xtime(y); | ||
| 175 | ftable[i]=pack(b); | ||
| 176 | |||
| 177 | y=rbsub[i]; | ||
| 178 | b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y); | ||
| 179 | b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y); | ||
| 180 | rtable[i]=pack(b); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | void suhosin_aes_gkey(int nb,int nk,char *key TSRMLS_DC) | ||
| 185 | { /* blocksize=32*nb bits. Key=32*nk bits */ | ||
| 186 | /* currently nb,bk = 4, 6 or 8 */ | ||
| 187 | /* key comes as 4*Nk bytes */ | ||
| 188 | /* Key Scheduler. Create expanded encryption key */ | ||
| 189 | int i,j,k,m,N; | ||
| 190 | int C1,C2,C3; | ||
| 191 | WORD CipherKey[8]; | ||
| 192 | |||
| 193 | Nb=nb; Nk=nk; | ||
| 194 | |||
| 195 | /* Nr is number of rounds */ | ||
| 196 | if (Nb>=Nk) Nr=6+Nb; | ||
| 197 | else Nr=6+Nk; | ||
| 198 | |||
| 199 | C1=1; | ||
| 200 | if (Nb<8) { C2=2; C3=3; } | ||
| 201 | else { C2=3; C3=4; } | ||
| 202 | |||
| 203 | /* pre-calculate forward and reverse increments */ | ||
| 204 | for (m=j=0;j<nb;j++,m+=3) | ||
| 205 | { | ||
| 206 | 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 | |||
| 256 | void suhosin_aes_encrypt(char *buff TSRMLS_DC) | ||
| 257 | { | ||
| 258 | int i,j,k,m; | ||
| 259 | WORD a[8],b[8],*x,*y,*t; | ||
| 260 | |||
| 261 | for (i=j=0;i<Nb;i++,j+=4) | ||
| 262 | { | ||
| 263 | a[i]=pack((BYTE *)&buff[j]); | ||
| 264 | a[i]^=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 | |||
| 303 | void suhosin_aes_decrypt(char *buff TSRMLS_DC) | ||
| 304 | { | ||
| 305 | int i,j,k,m; | ||
| 306 | WORD a[8],b[8],*x,*y,*t; | ||
| 307 | |||
| 308 | for (i=j=0;i<Nb;i++,j+=4) | ||
| 309 | { | ||
| 310 | a[i]=pack((BYTE *)&buff[j]); | ||
| 311 | a[i]^=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 | /* | ||
| 351 | static int main() | ||
| 352 | { | ||
| 353 | int i,nb,nk; | ||
| 354 | char key[32]; | ||
| 355 | char block[32]; | ||
| 356 | |||
| 357 | gentables(); | ||
| 358 | |||
| 359 | for (i=0;i<32;i++) key[i]=0; | ||
| 360 | key[0]=1; | ||
| 361 | for (i=0;i<32;i++) block[i]=i; | ||
| 362 | |||
| 363 | for (nb=4;nb<=8;nb+=2) | ||
| 364 | for (nk=4;nk<=8;nk+=2) | ||
| 365 | { | ||
| 366 | printf("\nBlock Size= %d bits, Key Size= %d bits\n",nb*32,nk*32); | ||
| 367 | gkey(nb,nk,key); | ||
| 368 | printf("Plain= "); | ||
| 369 | for (i=0;i<nb*4;i++) printf("%02x",block[i]); | ||
| 370 | printf("\n"); | ||
| 371 | encrypt(block); | ||
| 372 | printf("Encrypt= "); | ||
| 373 | for (i=0;i<nb*4;i++) printf("%02x",(unsigned char)block[i]); | ||
| 374 | printf("\n"); | ||
| 375 | decrypt(block); | ||
| 376 | printf("Decrypt= "); | ||
| 377 | for (i=0;i<nb*4;i++) printf("%02x",block[i]); | ||
| 378 | printf("\n"); | ||
| 379 | } | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | */ | ||
diff --git a/config.m4 b/config.m4 new file mode 100644 index 0000000..602b2c9 --- /dev/null +++ b/config.m4 | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | dnl $Id$ | ||
| 2 | dnl config.m4 for extension suhosin7 | ||
| 3 | |||
| 4 | PHP_ARG_ENABLE(suhosin, whether to enable suhosin support, | ||
| 5 | [ --enable-suhosin Enable suhosin support]) | ||
| 6 | |||
| 7 | if test "$PHP_SUHOSIN" != "no"; then | ||
| 8 | PHP_NEW_EXTENSION(suhosin7, suhosin7.c aes.c ifilter.c memory_limit.c sha256.c treat_data.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) | ||
| 9 | fi | ||
| 10 | |||
| 11 | PHP_ARG_ENABLE(suhosin7-experimental, whether to enable experimental suhosin7 features, | ||
| 12 | [ --enable-suhosin7-experimental Enable experimental suhosin7 features], no, no) | ||
| 13 | |||
| 14 | if test "$PHP_SUHOSIN7_EXPERIMENTAL" != "no"; then | ||
| 15 | AC_DEFINE(SUHOSIN7_EXPERIMENTAL, 1, [Whether to enable experimental suhosin7 features]) | ||
| 16 | fi | ||
| 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 | |||
| 10 | if (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 | |||
| 35 | static void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = NULL; | ||
| 36 | |||
| 37 | #if !HAVE_STRNLEN | ||
| 38 | static 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 | |||
| 44 | size_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 | |||
| 54 | size_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 | */ | ||
| 67 | void 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 | |||
| 126 | static unsigned char suhosin_hexchars[] = "0123456789ABCDEF"; | ||
| 127 | |||
| 128 | static 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 | */ | ||
| 149 | static 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 | */ | ||
| 170 | static 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 | */ | ||
| 214 | void 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 */ | ||
| 285 | unsigned 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 | */ | ||
| 289 | unsigned 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 | */ | ||
| 319 | unsigned 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 | */ | ||
| 707 | void 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 | */ | ||
| 35 | static 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 | |||
| 77 | void 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 | |||
| 24 | extern 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 | |||
| 44 | ZEND_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; | ||
| 136 | ZEND_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) | ||
| 145 | ZEND_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 | |||
| 173 | ZEND_EXTERN_MODULE_GLOBALS(suhosin7) | ||
| 174 | |||
| 175 | unsigned int suhosin_input_filter(int arg, char *var, char **val, size_t val_len, size_t *new_val_len); | ||
| 176 | unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, size_t val_len, size_t *new_val_len); | ||
| 177 | void suhosin_log(int loglevel, char *fmt, ...); | ||
| 178 | extern 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 | |||
| 29 | static void make_sha256_digest(char *sha256str, unsigned char *digest) | ||
| 30 | { | ||
| 31 | int i; | ||
| 32 | |||
| 33 | for (i = 0; i < 32; i++) { | ||
| 34 | sprintf(sha256str, "%02x", digest[i]); | ||
| 35 | sha256str += 2; | ||
| 36 | } | ||
| 37 | |||
| 38 | *sha256str = '\0'; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* {{{ proto string sha256(string str [, bool raw_output]) | ||
| 42 | Calculate the sha256 hash of a string */ | ||
| 43 | static PHP_FUNCTION(suhosin_sha256) | ||
| 44 | { | ||
| 45 | char *arg; | ||
| 46 | int arg_len; | ||
| 47 | zend_bool raw_output = 0; | ||
| 48 | char sha256str[65]; | ||
| 49 | suhosin_SHA256_CTX context; | ||
| 50 | unsigned char digest[32]; | ||
| 51 | |||
| 52 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | sha256str[0] = '\0'; | ||
| 57 | suhosin_SHA256Init(&context); | ||
| 58 | suhosin_SHA256Update(&context, (unsigned char *)arg, (unsigned int)arg_len); | ||
| 59 | suhosin_SHA256Final(digest, &context); | ||
| 60 | if (raw_output) { | ||
| 61 | RETURN_STRINGL((char *)digest, 32); | ||
| 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 */ | ||
| 73 | static PHP_FUNCTION(suhosin_sha256_file) | ||
| 74 | { | ||
| 75 | char *arg; | ||
| 76 | int arg_len; | ||
| 77 | zend_bool raw_output = 0; | ||
| 78 | char sha256str[65]; | ||
| 79 | unsigned char buf[1024]; | ||
| 80 | unsigned char digest[32]; | ||
| 81 | suhosin_SHA256_CTX context; | ||
| 82 | int n; | ||
| 83 | 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 | |||
| 118 | static void SHA256Transform(php_uint32[8], const unsigned char[64]); | ||
| 119 | static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int); | ||
| 120 | static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int); | ||
| 121 | |||
| 122 | static 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 | */ | ||
| 159 | void 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 | */ | ||
| 180 | void 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 | */ | ||
| 221 | void 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 | */ | ||
| 257 | static void SHA256Transform(state, block) | ||
| 258 | php_uint32 state[8]; | ||
| 259 | const 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 | */ | ||
| 350 | static void SHA256Encode(output, input, len) | ||
| 351 | unsigned char *output; | ||
| 352 | php_uint32 *input; | ||
| 353 | unsigned 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 | */ | ||
| 370 | static void SHA256Decode(output, input, len) | ||
| 371 | php_uint32 *output; | ||
| 372 | const unsigned char *input; | ||
| 373 | unsigned 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 | */ | ||
| 386 | static 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 | |||
| 394 | void 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. */ | ||
| 28 | typedef struct { | ||
| 29 | php_uint32 state[8]; /* state (ABCD) */ | ||
| 30 | php_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ | ||
| 31 | unsigned char buffer[64]; /* input buffer */ | ||
| 32 | } suhosin_SHA256_CTX; | ||
| 33 | |||
| 34 | void suhosin_SHA256Init(suhosin_SHA256_CTX *); | ||
| 35 | void suhosin_SHA256Update(suhosin_SHA256_CTX *, const unsigned char *, unsigned int); | ||
| 36 | void suhosin_SHA256Final(unsigned char[32], suhosin_SHA256_CTX *); | ||
| 37 | |||
| 38 | #endif | ||
diff --git a/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 | |||
| 34 | ZEND_DECLARE_MODULE_GLOBALS(suhosin7) | ||
| 35 | |||
| 36 | /* True global resources - no need for thread safety here */ | ||
| 37 | static int le_suhosin7; | ||
| 38 | |||
| 39 | /* {{{ PHP_INI | ||
| 40 | */ | ||
| 41 | PHP_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) | ||
| 46 | PHP_INI_END() | ||
| 47 | /* }}} */ | ||
| 48 | |||
| 49 | |||
| 50 | |||
| 51 | /* {{{ php_suhosin7_init_globals | ||
| 52 | */ | ||
| 53 | static 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 | */ | ||
| 62 | PHP_MINIT_FUNCTION(suhosin7) | ||
| 63 | { | ||
| 64 | REGISTER_INI_ENTRIES(); | ||
| 65 | return SUCCESS; | ||
| 66 | } | ||
| 67 | /* }}} */ | ||
| 68 | |||
| 69 | /* {{{ PHP_MSHUTDOWN_FUNCTION | ||
| 70 | */ | ||
| 71 | PHP_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 | */ | ||
| 81 | PHP_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 | */ | ||
| 93 | PHP_RSHUTDOWN_FUNCTION(suhosin7) | ||
| 94 | { | ||
| 95 | return SUCCESS; | ||
| 96 | } | ||
| 97 | /* }}} */ | ||
| 98 | |||
| 99 | /* {{{ suhosin_ini_displayer(zend_ini_entry *ini_entry, int type) | ||
| 100 | */ | ||
| 101 | static 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 | */ | ||
| 109 | PHP_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 | */ | ||
| 173 | const 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 | */ | ||
| 181 | zend_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 | ||
| 197 | ZEND_TSRMLS_CACHE_DEFINE(); | ||
| 198 | #endif | ||
| 199 | ZEND_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 | |||
| 3 | static unsigned char suhosin_logo[] = | ||
| 4 | "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48" | ||
| 5 | "\x00\x48\x00\x00\xff\xe1\x00\x16\x45\x78\x69\x66\x00\x00\x4d\x4d" | ||
| 6 | "\x00\x2a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\xff\xdb\x00\x43" | ||
| 7 | "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 8 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 9 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 10 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | ||
| 11 | "\x01\xff\xc0\x00\x0b\x08\x00\x27\x00\x71\x01\x01\x22\x00\xff\xc4" | ||
| 12 | "\x00\x1e\x00\x00\x02\x02\x02\x03\x01\x01\x00\x00\x00\x00\x00\x00" | ||
| 13 | "\x00\x00\x00\x00\x09\x06\x08\x05\x07\x02\x03\x0a\x01\x04\xff\xc4" | ||
| 14 | "\x00\x32\x10\x00\x01\x04\x03\x00\x02\x00\x05\x01\x05\x09\x01\x00" | ||
| 15 | "\x00\x00\x00\x05\x02\x03\x04\x06\x01\x07\x08\x00\x09\x11\x12\x13" | ||
| 16 | "\x14\x21\x15\x0a\x16\x31\x56\x96\x17\x18\x19\x23\x32\x41\x58\x98" | ||
| 17 | "\xd4\xd6\xff\xda\x00\x08\x01\x01\x00\x00\x3f\x00\xf4\xc1\xe1\xe5" | ||
| 18 | "\x69\xe9\x3e\xb9\xd1\x7c\x8a\x2e\x9d\x66\xe8\x3b\x29\x4d\x7f\x46" | ||
| 19 | "\xba\x58\x55\x54\x8d\xb1\x5f\xaa\xd9\x8d\x51\x2b\xb6\x27\x5a\x69" | ||
| 20 | "\xd1\x43\xaf\x16\x1a\xf0\xb2\xb1\xe9\x6d\x9f\xc2\xa4\x36\x18\xb5" | ||
| 21 | "\x85\x10\x41\xbe\xfc\x09\xac\x49\x29\x11\xd4\x32\x97\xec\x08\x13" | ||
| 22 | "\xc1\x2d\x20\xc3\x59\xeb\x26\x05\xd8\x6b\x76\x31\x43\x8f\x57\xcf" | ||
| 23 | "\x84\x9f\x14\xa8\x53\x81\x0b\xc3\x64\x80\xa3\x02\x0a\x41\x75\xf8" | ||
| 24 | "\x44\x85\x93\x81\x22\x3c\xd8\x13\xe1\xbe\xf4\x59\x91\x1f\x6a\x44" | ||
| 25 | "\x77\x5c\x69\xc4\x2f\x39\x5f\x0f\x2a\x8d\xeb\xba\xf8\xc3\x56\x6c" | ||
| 26 | "\x3b\x36\xa7\xda\xbd\x4d\xa1\xb5\x4e\xc6\xa7\xa4\x3a\xec\x15\x2d" | ||
| 27 | "\xa5\xb3\xea\x5a\xdc\xac\x46\xac\x01\x60\xd8\x43\xc8\x8e\x8b\xb1" | ||
| 28 | "\x40\x4c\x95\x8b\x34\x41\x28\x52\x91\x28\x43\xd3\xa3\xb6\xa7\x55" | ||
| 29 | "\x15\xe7\x5a\x96\xcb\xf1\xda\xe5\x55\xee\xfe\x1e\xbd\xd9\x41\xd3" | ||
| 30 | "\x28\xfd\x97\xca\x57\x2b\x85\x9c\xa4\x30\x95\xaa\xa5\x57\xa2\x35" | ||
| 31 | "\x15\x86\xcb\x61\x34\x41\xe4\xc7\x80\x20\x18\x21\x17\x09\x85\x0b" | ||
| 32 | "\x14\x9d\x21\x68\x62\x1c\x08\x11\x64\x4b\x92\xf2\xd2\xd3\x2d\x2d" | ||
| 33 | "\x6a\xc2\x73\x6b\x3c\x3c\x8b\x9e\xbc\x52\xaa\xa4\xab\x81\x6c\xf6" | ||
| 34 | "\xfa\xbd\x70\xc5\xc6\x7b\xc2\xaa\x22\x4f\x58\x04\x87\x25\x6a\x27" | ||
| 35 | "\x1d\xa4\x3d\x20\x75\x72\x01\x09\x71\xe5\x1c\x9e\xc3\x2e\x36\xf3" | ||
| 36 | "\xd0\xc6\x35\x2a\x43\x4d\x2d\x0e\x2d\xb4\xa1\x49\xce\x65\x1e\x52" | ||
| 37 | "\x9e\xa1\xf6\x09\xcc\xdc\x63\x66\xa8\x01\xe9\x3b\x0d\xd7\x5a\x85" | ||
| 38 | "\xbb\xc5\x65\xc0\x7b\x2e\x46\xa9\xd9\x56\x1d\x4c\x92\x72\x26\x4e" | ||
| 39 | "\x86\xd5\x68\xae\xc4\xaa\x55\xce\xd7\x83\x59\xb3\x81\xee\xce\x74" | ||
| 40 | "\x39\x39\x31\x9f\x8a\x25\xe8\xa5\xa5\xe5\x81\xf2\x11\x23\xcb\xa1" | ||
| 41 | "\x1e\x43\x12\xe3\xb1\x2a\x2b\xcd\xc8\x8d\x25\x96\xa4\x47\x7d\x95" | ||
| 42 | "\xa5\xc6\x9f\x61\xe4\x25\xc6\x5e\x69\xc4\xe7\x29\x5b\x6e\xb6\xa4" | ||
| 43 | "\xad\x0b\x4e\x72\x95\x25\x58\x56\x33\x9c\x67\xce\xef\x0f\x17\xbf" | ||
| 44 | "\x4c\x7b\x2d\xe6\xfe\x76\x35\x27\x5a\x07\x97\x67\xe8\xae\x8d\x71" | ||
| 45 | "\x0f\xb2\x13\x99\xb9\xbc\x14\xad\xb3\xb7\xe6\x11\x6f\xe0\xda\x58" | ||
| 46 | "\xb1\x08\xac\xa6\x6c\x2d\x7f\x05\xb7\x56\xd2\xe6\xcf\xbb\x4d\x0c" | ||
| 47 | "\xe3\x50\xb2\xec\x91\xf0\x4a\xb8\xd6\x22\xb8\xa7\xf6\x67\xaf\xcf" | ||
| 48 | "\x63\x7e\xd7\xe7\x42\xd8\xbd\xc3\x71\xa1\xf2\x7e\x9b\xa8\x97\x83" | ||
| 49 | "\x6e\xd1\xdc\x4b\x06\x11\x2d\xae\x26\x61\x98\x72\x10\xf4\x42\x5d" | ||
| 50 | "\x20\x4a\xa3\x73\xd7\xf2\xcd\x3c\x48\x32\xe4\x03\x9f\x80\x37\x08" | ||
| 51 | "\x36\x11\xd0\xcb\x97\x6c\x08\xed\x6d\x33\x24\xa2\x1b\xb4\x77\xdf" | ||
| 52 | "\x61\x5d\x5f\xc1\x43\xc2\x82\xeb\x0f\x5d\x84\x08\x68\xaa\xa4\x01" | ||
| 53 | "\xe1\x19\xdf\xbc\x31\x65\xfe\xd1\xf5\x7d\x7a\xb2\x2a\x33\x50\x21" | ||
| 54 | "\x2a\x56\x9d\xb1\x81\xab\xdb\x35\x78\x30\x83\xd9\x89\x1d\x31\xac" | ||
| 55 | "\x96\x14\x07\x61\xbc\x20\x68\x42\x85\x33\x19\xac\xbe\xdb\x34\x56" | ||
| 56 | "\xf1\xd5\xfd\x29\xa9\x28\xdb\xcb\x4c\x5a\x23\xdc\xf5\x96\xc5\x10" | ||
| 57 | "\xa3\x35\x5b\x14\x68\xd3\x61\x62\x64\x76\x26\xcb\x17\x3e\x34\x98" | ||
| 58 | "\x04\xa3\xc4\x20\x38\x90\x92\xe3\xc8\x07\x2c\x36\x74\x66\x26\x0e" | ||
| 59 | "\x29\x02\x64\x29\x2d\x21\xe6\x16\x9c\x6b\xce\xa3\x89\xd9\x4f\xd3" | ||
| 60 | "\xc4\xbd\xc5\x87\x79\x9c\x65\xf6\x39\x45\x60\xe8\xce\x9e\xab\x6d" | ||
| 61 | "\x13\x15\x22\xe1\x5e\x4b\x38\x42\xc4\x1e\xd5\x76\xe0\xc5\xeb\x85" | ||
| 62 | "\x07\x2d\x0f\xb8\xb6\xa6\xd6\x6d\x71\x0d\xa2\x43\x4c\x25\xea\xfa" | ||
| 63 | "\xa1\xae\x4c\xe4\x7d\xbd\x76\xa9\xfb\x06\xc2\x83\x42\xeb\xad\xe7" | ||
| 64 | "\xe9\x5f\x68\x6f\xba\xfb\x2f\x07\xce\xb8\x13\xc1\x9b\xeb\xb0\x76" | ||
| 65 | "\x45\x57\x28\x7b\xea\xbe\x0f\xf4\x30\x7b\xa0\xed\xe4\x22\x93\x21" | ||
| 66 | "\xfc\xbc\xe0\xb9\x75\xc1\x4f\xfc\xef\xb6\xfa\xa1\xfc\x64\xa1\x4a" | ||
| 67 | "\x82\xc7\x33\xad\x75\xed\x82\xbd\x3d\xdb\xf7\xa8\xbe\x5e\xbb\x36" | ||
| 68 | "\x62\x04\x9a\x2e\xc5\xd9\x9e\x9c\x3a\x0b\x98\x0b\x57\xac\xf1\x24" | ||
| 69 | "\x62\x58\x83\x15\x5b\xa6\xf2\xda\x34\x70\x03\xce\x0f\x93\x1b\x12" | ||
| 70 | "\xc7\xce\x54\x87\x33\x15\xd6\x53\x25\x1f\x2a\x90\x87\x12\xe3\x78" | ||
| 71 | "\xef\x55\x77\x4d\x4a\xd8\x7e\xef\xd2\xfd\xd1\xaf\x3a\xaf\x55\xdb" | ||
| 72 | "\x6a\x2d\x3d\x42\xac\x51\x79\xee\x91\xab\xe1\x05\x2d\x3c\x80\xa2" | ||
| 73 | "\x43\xad\x22\x2e\xd5\x33\x13\xa4\x9e\x00\xe0\x04\x10\x84\xc8\xf2" | ||
| 74 | "\x19\x30\x92\x1f\xaa\xc3\x28\xc9\x76\x30\x3f\xe9\x10\x61\x5e\x79" | ||
| 75 | "\xd5\xf7\xdf\xd0\x54\xdb\xae\xb6\xae\xfa\xe8\xa3\x57\xe0\x6c\x2d" | ||
| 76 | "\xf7\xbd\x49\xd6\x6e\x76\x79\xcc\x54\x0c\x5f\xff\x00\xbb\x06\x98" | ||
| 77 | "\xa6\x9e\x89\x61\xb4\x6f\xc3\xe3\x6a\xc2\x4f\x59\x03\xc9\x80\x2c" | ||
| 78 | "\x59\x24\x44\x70\x38\xd5\x96\x6a\x9e\x8b\x81\x64\xe5\xbc\xa0\x3c" | ||
| 79 | "\x33\xaf\x17\x9d\xff\x00\x71\x1a\xd1\x3a\x80\x66\xb3\xd9\x31\x77" | ||
| 80 | "\x0d\x12\xbd\xae\x29\xb5\x6a\xd6\xcf\x8d\x68\x87\x75\xcd\xe8\x65" | ||
| 81 | "\x5a\xbe\x3c\x04\x7b\x34\xdb\x54\x19\xa4\x63\x9c\x2a\x5d\x23\xbe" | ||
| 82 | "\xf4\xb1\x1c\x4d\x90\xec\x92\x2f\x49\x71\xf7\x14\xf2\x97\x9f\x15" | ||
| 83 | "\x57\xed\x13\x21\x2a\xf5\x33\xd1\x2a\x52\x52\xac\xb7\x62\xd1\xcb" | ||
| 84 | "\x46\x73\x8c\x67\x28\x56\x77\x86\xbf\x6f\x2a\x4e\x73\xfe\x95\x65" | ||
| 85 | "\x0b\x5a\x3e\x38\xfc\xfc\xaa\x56\x3f\x86\x73\xe3\xb9\x4a\x52\x84" | ||
| 86 | "\xa5\x08\x4e\x12\x94\x27\x09\x4a\x53\x8c\x61\x29\x4a\x71\xf0\x4a" | ||
| 87 | "\x53\x8c\x7e\x31\x8c\x63\x18\xc6\x31\x8f\xc6\x31\xf8\xc7\x9f\x7c" | ||
| 88 | "\xd5\xbb\xae\x5e\xe2\x1f\xab\x6e\x24\x34\x00\x8a\x25\x83\x70\x40" | ||
| 89 | "\x1c\xcc\xda\x45\x7f\x66\x4e\x30\x2e\x94\x7e\x74\x49\xf0\xe4\x4e" | ||
| 90 | "\x06\x5c\xa8\x2f\x89\x21\x2e\x98\x0e\xd9\x21\xc2\x0b\x21\x0f\xc4" | ||
| 91 | "\x16\x6e\x48\xd9\xe4\xe3\x4a\x19\x1e\x64\x67\x54\xff\x00\x3a\x6d" | ||
| 92 | "\x4f\x62\xb5\x00\x4a\xaa\x51\xfd\x2d\xe8\x0e\x6c\xaf\xc6\x7d\x6d" | ||
| 93 | "\xc8\x88\xc7\x67\xea\x8a\x58\x02\x73\xe3\x65\x4d\xc9\x24\xc0\x3d" | ||
| 94 | "\x57\xa3\x2e\x53\x16\x99\x4f\xe5\xe7\x19\x97\x3e\x3b\xcf\xc9\x4b" | ||
| 95 | "\x99\x7f\x33\x25\xa5\xdf\xba\x77\x2b\xd3\x3e\xc2\x7b\x8b\x94\x07" | ||
| 96 | "\xe9\x52\x5b\x43\x87\x34\x14\x86\x37\xcf\x41\x6b\x8e\x6a\xa5\x22" | ||
| 97 | "\xab\xdb\x96\xa2\xcf\x46\xd8\x9b\x45\x93\xef\xd6\xdf\x3e\x99\x9c" | ||
| 98 | "\x7e\x29\x10\x6b\x6c\xa2\xb8\x43\x05\x09\x44\x70\x8c\xb8\xaa\x54" | ||
| 99 | "\x7c\x30\x36\x5e\x1c\x5e\x5b\x9f\x6c\x0d\x81\xee\xa0\x93\x8d\x67" | ||
| 100 | "\x55\xf3\x87\xaf\xaa\x6b\x58\xf9\xbe\xb2\x36\x07\x42\x6e\xbd\x96" | ||
| 101 | "\xe3\x9f\x1f\x8f\xc9\xf4\x9d\xae\x6a\x7d\x4c\x96\xbe\x5f\xc7\xcd" | ||
| 102 | "\xf3\xb2\xf7\xcd\xf0\xcf\xc3\xe4\xf8\xfe\x37\x4f\x1c\x4d\xf6\x40" | ||
| 103 | "\xf1\x6b\x7c\x4e\xe0\xa6\x71\xad\x56\xa7\x1c\x5c\x15\x6b\xfc\xf3" | ||
| 104 | "\x01\x5d\xac\xf1\x75\x9a\x72\x6b\xaa\x28\xc5\x88\x6d\xfb\x33\x85" | ||
| 105 | "\xe0\x4e\x61\xab\xeb\x31\x2c\x71\x08\x73\x11\x3b\xfc\xb5\xc0\x96" | ||
| 106 | "\xcc\x87\x24\x44\xb5\x9b\x9e\xb3\x71\xba\xe9\xed\xb1\x4e\xd7\x76" | ||
| 107 | "\x6c\xd2\xb6\x05\xb7\x5a\xde\xeb\x34\x5b\x96\x16\xfb\x59\xa9\x5c" | ||
| 108 | "\x4f\x55\xca\x8a\xac\x59\xb0\xe4\x54\x39\x25\xbc\x81\x37\x2a\x09" | ||
| 109 | "\x5f\x9e\x3b\x6b\x7d\x1f\x69\xf3\x34\x85\x39\x84\xa7\x28\x0b\xd3" | ||
| 110 | "\xfd\xfb\x4b\x7a\xea\xe7\xd2\x3c\xd3\xda\x15\x68\xbc\x73\xd3\x22" | ||
| 111 | "\x6f\xd7\x72\x5b\x2b\x66\xee\xa8\x0d\x54\xe8\x5b\xf9\x92\x96\x92" | ||
| 112 | "\x93\xea\x97\x4a\xc7\x43\x10\x46\x35\xc5\xc0\x60\x8a\xe4\xc1\xb5" | ||
| 113 | "\x36\xc6\xae\xed\xf7\x70\xa5\x86\x99\x3d\x91\xf8\xfd\x4e\x53\xeb" | ||
| 114 | "\xbb\xbd\x6d\xec\x8f\xd7\x89\x3d\x31\x7f\xd7\x78\xba\x50\xbb\x74" | ||
| 115 | "\x9d\xf6\xac\x4e\xb9\x03\x9c\x79\xd5\xe1\xbd\x17\x68\xd9\x13\x0b" | ||
| 116 | "\x45\x75\x88\x00\x1d\x1f\xae\x73\x6a\x1d\x5c\x6e\x44\x9f\xa6\xfa" | ||
| 117 | "\x4e\xd8\x25\x8b\xc0\xbc\xb2\x99\xe3\x17\x24\xb3\x23\xe2\x48\x8b" | ||
| 118 | "\xfa\x22\xe7\x7e\x8f\xe6\x3f\x5f\x55\x0d\x75\xd3\x51\x0b\xd7\xed" | ||
| 119 | "\xd3\x6f\x97\x3b\x85\x42\x80\x7e\x5f\xdc\x1b\xd6\xba\xee\xc4\x80" | ||
| 120 | "\xce\x06\xa9\x15\x8c\x97\x5f\x40\x69\xb2\x4d\xc5\xb2\x5c\x1e\x01" | ||
| 121 | "\x87\x7e\xe0\x36\x6d\x78\x80\x4e\x3c\x02\xec\x90\x1d\x11\x81\x74" | ||
| 122 | "\xa5\x8b\xa4\xa0\x56\x06\xd5\x79\x72\x85\x57\x3b\xb2\x2e\xae\x90" | ||
| 123 | "\x18\x8d\x91\xb2\x0e\x44\x19\xaa\xb4\xcc\x08\xed\x46\xfa\xd7\x2b" | ||
| 124 | "\x78\x58\x72\x5d\xbb\x5e\x49\xe7\xee\xf3\x8a\x9d\x22\xa4\x19\xc8" | ||
| 125 | "\xe7\x08\xc3\x90\x9b\x35\x9a\xa4\x25\x8c\x4b\x9b\xa7\xf8\xbf\x81" | ||
| 126 | "\xf5\xdf\x22\x66\xf1\x7e\x9f\x66\x3d\xbb\xfa\x73\x73\x4d\xfd\x67" | ||
| 127 | "\x7b\xf4\xce\xc3\x62\x2e\x6f\xbb\x0c\xa2\xdc\x69\xfc\x8a\x17\x0e" | ||
| 128 | "\x3a\x9e\x83\x46\xd7\xe3\x5e\x65\x86\xc0\x51\x00\xbb\x91\xe3\xe1" | ||
| 129 | "\xc1\x16\xc4\xe9\x65\x5c\x14\x3e\x44\x6a\x6b\xd1\x1e\xb0\x36\xdd" | ||
| 130 | "\x0b\x7d\x8a\xeb\xaf\x58\x5b\x64\x3f\x38\xed\x52\x76\xe8\x46\xf7" | ||
| 131 | "\x86\x84\xb3\x93\xb1\x0b\xe5\xfd\xfd\x0d\xe9\x6d\xe4\xf1\x1b\x1d" | ||
| 132 | "\x56\xb4\x34\xe4\x6a\xf5\xa4\x9c\x2c\xc9\x64\x94\xc1\xf5\x79\x6d" | ||
| 133 | "\x12\x96\xf3\x47\xc5\x48\xa8\xdb\xd8\x95\x64\x29\xcf\xf6\x88\xf1" | ||
| 134 | "\x95\x7a\x98\xe8\xbc\x27\x19\xce\x73\x61\xd1\xb8\xc6\x31\x8c\xe7" | ||
| 135 | "\x39\xce\x77\x9e\xbc\xc6\x31\x8c\x63\xf3\x9c\xe7\x39\xc6\x31\x8f" | ||
| 136 | "\xf7\xce\x7e\x1e\x3b\x7f\x0f\x0f\x0f\x13\x57\xb9\x0a\xe1\x0b\x64" | ||
| 137 | "\x5f\x58\x40\xc6\xc7\x7a\x4b\xf2\x3d\xbc\x71\xf4\xa7\xd2\xca\x14" | ||
| 138 | "\xe2\x98\x1a\x30\x1e\xe0\x26\x5a\x6a\xf0\x9c\x67\x38\x66\x00\xb8" | ||
| 139 | "\x72\xe6\xbe\xac\xfe\x12\xd3\x0b\x56\x73\x8c\x63\xc7\x2b\xe1\xe2" | ||
| 140 | "\xe8\xdd\x7b\xff\x00\xd8\xe5\x23\x6c\xce\xa8\x69\xcf\x5e\x3a\xef" | ||
| 141 | "\x77\xea\xe5\xab\x0e\x82\xdb\xd9\xed\x7a\x9e\xb8\x6d\x51\x32\xdb" | ||
| 142 | "\x79\xc3\x36\x9a\x2d\xa3\x50\x39\x65\x0a\x63\x0e\xe5\xd4\x39\x12" | ||
| 143 | "\xbf\x8b\x98\xa4\xa1\x2d\xad\xb3\xcf\x65\x6a\x43\x78\xb3\x3b\x07" | ||
| 144 | "\xd8\xd5\xea\xae\x76\xad\x6f\xf5\xff\x00\xca\x93\xab\x96\xb0\x64" | ||
| 145 | "\xeb\xd6\x4a\xd5\x87\xba\xec\x24\x60\x97\x06\x76\x03\xe3\x4c\x07" | ||
| 146 | "\x29\x11\x8e\x34\x25\x02\x64\x29\xf0\x25\x48\x85\x3a\x33\x8b\x7a" | ||
| 147 | "\x3c\x86\x1e\x75\xa5\x61\xc6\x97\x9f\x8d\x25\xf5\xc9\xcd\xde\xc9" | ||
| 148 | "\x7d\x77\xf2\xc8\x7e\x70\xaf\x73\x5f\x2d\xec\xa2\x51\x2d\x96\xfb" | ||
| 149 | "\x89\xad\x80\x57\xb2\x36\x1d\x7d\x83\x45\xac\xf3\xdb\xcc\x6c\x31" | ||
| 150 | "\x4f\xcf\x30\x58\xd0\x12\x28\x90\x50\x42\x86\xfb\x48\x16\x3c\xc5" | ||
| 151 | "\x9c\xf8\xe7\xcc\x29\x88\xb3\x4a\x4b\x4e\x6c\xbc\xdb\xc7\xbb\xe9" | ||
| 152 | "\xb6\xa0\x8b\x11\xa1\x7d\x73\xd7\xe9\xbf\x7e\xc2\x6c\x10\x8d\xee" | ||
| 153 | "\x9d\xef\x63\x3a\xe0\xf5\xbe\x8c\x3e\xa1\xc7\xc5\xd1\x00\x44\x1e" | ||
| 154 | "\xf3\x51\xf2\xe2\xb0\xe3\xb5\x13\x7f\x32\xf1\x8c\xa6\x22\xfe\x1f" | ||
| 155 | "\x49\x4d\xbb\xcf\x3a\x5d\xed\x4c\xd2\xfc\x85\xed\x23\xd6\xc7\x50" | ||
| 156 | "\xb6\x5b\x3a\x16\x83\xb8\x6f\xfd\x32\x3f\xaa\x36\x34\xbb\xf5\x96" | ||
| 157 | "\xa9\xab\xcf\x9f\x8f\xac\xc3\xca\xd5\x8b\xd8\x48\x9e\x79\xaa\x30" | ||
| 158 | "\x87\xca\x58\x4d\x59\x96\xb9\x4f\xc5\x1b\x1c\xd2\xda\x5b\xe6\x57" | ||
| 159 | "\x29\xa1\x28\x7a\x2b\x5b\xff\x00\x12\x2f\x5e\x3f\xf3\xbb\x8e\x7f" | ||
| 160 | "\xec\xc6\x98\xff\x00\xed\x3c\xa6\xdd\xa9\xdc\x7e\xa0\xf7\xd6\x99" | ||
| 161 | "\x31\xa2\xf7\xaf\x6b\xe9\x82\x74\x4b\x3d\x8f\x5e\x58\x0b\x33\xab" | ||
| 162 | "\xef\xc3\xaf\x84\x64\xb9\xae\xb6\x25\x5f\x62\x8f\x1c\xe3\xf4\x51" | ||
| 163 | "\xb7\x96\xe3\x0e\x30\x42\xa9\x18\x39\xbf\x9e\x2a\x1f\x74\x19\x02" | ||
| 164 | "\x2d\x43\x93\x06\x63\xb1\xa7\x47\x6a\xfa\x9b\x6c\xeb\xbd\xe9\xae" | ||
| 165 | "\x6a\x7b\x6f\x53\x5a\x60\x5d\xb5\xcd\xe8\x67\xeb\x35\x3b\x48\xc6" | ||
| 166 | "\xa6\xb3\x04\xc8\xdf\xb8\x7e\x26\x64\xb0\xc9\x18\xb0\xa7\x33\xf2" | ||
| 167 | "\x4a\x8b\x22\x3b\x8d\x4b\x89\x1d\xf6\x9d\x65\xc4\x38\xd2\x54\x9c" | ||
| 168 | "\xe3\xcd\x89\xe1\xe1\xe6\x3e\x70\x81\x45\x1d\x18\xf9\x31\x83\xc8" | ||
| 169 | "\xbe\x14\x82\x4b\x87\x7a\x74\x28\xd2\xdd\x12\x55\x30\xe6\x0e\x49" | ||
| 170 | "\x31\x8e\x48\x69\xc5\xc0\x20\x91\xe4\x48\x41\x4c\xd8\xb9\x6a\x4e" | ||
| 171 | "\x21\xce\x99\x1b\x0e\xfd\x09\x4f\xa1\x79\x0f\x0f\x0f\x0f\x0f\x0f" | ||
| 172 | "\x0f\x3f\x3c\xb8\x71\x27\xc7\x72\x24\xe8\xb1\xa6\xc5\x7b\x18\xc3" | ||
| 173 | "\xb1\xa5\xb0\xd4\x98\xee\xe3\x19\xc6\x71\x87\x19\x79\x2b\x6d\x78" | ||
| 174 | "\xc6\x71\x8c\xe3\x0a\x4e\x71\x8c\xe3\x19\xfe\x38\xf2\x3b\xfb\x8b" | ||
| 175 | "\x48\xfe\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe1\xfb\x8b\x48\xfe" | ||
| 176 | "\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe4\x95\x86\x18\x8a\xcb\x31" | ||
| 177 | "\xa3\x32\xd4\x78\xf1\xdb\x43\x2c\x47\x61\xb4\x32\xcb\x2c\xb4\x9c" | ||
| 178 | "\x21\xb6\x99\x69\xbc\x25\xb6\xdb\x6d\x18\xc2\x10\xda\x12\x94\xa1" | ||
| 179 | "\x38\xc2\x53\x8c\x63\x18\xc7\x9d\xbe\x7f\xff\xd9" | ||
| 180 | ; | ||
diff --git a/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-- | ||
| 2 | Check for suhosin7 presence | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("suhosin7")) print "skip"; ?> | ||
| 5 | --FILE-- | ||
| 6 | <?php | ||
| 7 | echo "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-- | ||
| 21 | suhosin7 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 | |||
| 34 | SAPI_TREAT_DATA_FUNC(suhosin_treat_data) | ||
| 35 | { | ||
| 36 | char *res = NULL, *var, *val, *separator = NULL; | ||
| 37 | const char *c_var; | ||
| 38 | zval array; | ||
| 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 | } | ||
| 180 | next_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 | |||
| 195 | void 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 | |||
