summaryrefslogtreecommitdiff
path: root/0.4.3
diff options
context:
space:
mode:
Diffstat (limited to '0.4.3')
-rw-r--r--0.4.3/.hardening-patch-5.0.5-0.4.3.patch.swpbin0 -> 16384 bytes
-rw-r--r--0.4.3/hardening-patch-4.4.0-0.4.3.patch15043
-rw-r--r--0.4.3/hardening-patch-5.0.5-0.4.3.patch7046
3 files changed, 22089 insertions, 0 deletions
diff --git a/0.4.3/.hardening-patch-5.0.5-0.4.3.patch.swp b/0.4.3/.hardening-patch-5.0.5-0.4.3.patch.swp
new file mode 100644
index 0000000..0679ecb
--- /dev/null
+++ b/0.4.3/.hardening-patch-5.0.5-0.4.3.patch.swp
Binary files differ
diff --git a/0.4.3/hardening-patch-4.4.0-0.4.3.patch b/0.4.3/hardening-patch-4.4.0-0.4.3.patch
new file mode 100644
index 0000000..853680e
--- /dev/null
+++ b/0.4.3/hardening-patch-4.4.0-0.4.3.patch
@@ -0,0 +1,15043 @@
1diff -Nura php-4.4.0/acinclude.m4 hardening-patch-4.4.0-0.4.3/acinclude.m4
2--- php-4.4.0/acinclude.m4 2005-04-30 11:31:09.000000000 +0200
3+++ hardening-patch-4.4.0-0.4.3/acinclude.m4 2005-09-11 23:31:08.000000000 +0200
4@@ -1173,6 +1173,36 @@
5 fi
6 ])
7
8+dnl
9+dnl Check for broken realpath()
10+dnl
11+dnl realpath("/etc/hosts/../passwd",XXX) should not return
12+dnl "/etc/passwd"
13+dnl
14+AC_DEFUN([PHP_AC_BROKEN_REALPATH],[
15+ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[
16+ AC_TRY_RUN([
17+main() {
18+ char buf[4096+1];
19+ buf[0] = 0;
20+ realpath("/etc/hosts/../passwd", buf);
21+ exit(strcmp(buf, "/etc/passwd")==0);
22+}
23+ ],[
24+ ac_cv_broken_realpath=no
25+ ],[
26+ ac_cv_broken_realpath=yes
27+ ],[
28+ ac_cv_broken_realpath=no
29+ ])
30+ ])
31+ if test "$ac_cv_broken_realpath" = "yes"; then
32+ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken])
33+ else
34+ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken])
35+ fi
36+])
37+
38 dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx)
39 dnl
40 dnl Basically sets up the link-stage for building module-name
41diff -Nura php-4.4.0/configure hardening-patch-4.4.0-0.4.3/configure
42--- php-4.4.0/configure 2005-07-11 12:07:33.000000000 +0200
43+++ hardening-patch-4.4.0-0.4.3/configure 2005-09-11 23:31:08.000000000 +0200
44@@ -394,6 +394,16 @@
45 ac_default_prefix=/usr/local
46 # Any additions from configure.in:
47 ac_help="$ac_help
48+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
49+ac_help="$ac_help
50+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
51+ac_help="$ac_help
52+ --disable-hardening-patch-inc-protect Disable include/require protection."
53+ac_help="$ac_help
54+ --disable-hardening-patch-fmt-protect Disable format string protection."
55+ac_help="$ac_help
56+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
57+ac_help="$ac_help
58
59 SAPI modules:
60 "
61@@ -846,6 +856,8 @@
62 ac_help="$ac_help
63 --disable-tokenizer Disable tokenizer support"
64 ac_help="$ac_help
65+ --disable-varfilter Disable Hardening-Patch's variable filter"
66+ac_help="$ac_help
67 --enable-wddx Enable WDDX support."
68 ac_help="$ac_help
69 --disable-xml Disable XML support using bundled expat lib"
70@@ -2682,6 +2694,157 @@
71
72
73
74+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
75+if test "${enable_hardening_patch_mm_protect+set}" = set; then
76+ enableval="$enable_hardening_patch_mm_protect"
77+
78+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
79+
80+else
81+
82+ DO_HARDENING_PATCH_MM_PROTECT=yes
83+
84+fi
85+
86+
87+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
88+if test "${enable_hardening_patch_ll_protect+set}" = set; then
89+ enableval="$enable_hardening_patch_ll_protect"
90+
91+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
92+
93+else
94+
95+ DO_HARDENING_PATCH_LL_PROTECT=yes
96+
97+fi
98+
99+
100+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
101+if test "${enable_hardening_patch_inc_protect+set}" = set; then
102+ enableval="$enable_hardening_patch_inc_protect"
103+
104+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
105+
106+else
107+
108+ DO_HARDENING_PATCH_INC_PROTECT=yes
109+
110+fi
111+
112+
113+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
114+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
115+ enableval="$enable_hardening_patch_fmt_protect"
116+
117+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
118+
119+else
120+
121+ DO_HARDENING_PATCH_FMT_PROTECT=yes
122+
123+fi
124+
125+
126+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
127+if test "${enable_hardening_patch_hash_protect+set}" = set; then
128+ enableval="$enable_hardening_patch_hash_protect"
129+
130+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
131+
132+else
133+
134+ DO_HARDENING_PATCH_HASH_PROTECT=yes
135+
136+fi
137+
138+
139+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
140+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
141+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
142+
143+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
144+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
145+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
146+
147+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
148+echo "configure:2733: checking whether to protect include/require statements" >&5
149+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
150+
151+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
152+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
153+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
154+
155+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
156+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
157+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
158+
159+
160+cat >> confdefs.h <<\EOF
161+#define HARDENING_PATCH 1
162+EOF
163+
164+
165+
166+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
167+ cat >> confdefs.h <<\EOF
168+#define HARDENING_PATCH_MM_PROTECT 1
169+EOF
170+
171+else
172+ cat >> confdefs.h <<\EOF
173+#define HARDENING_PATCH_MM_PROTECT 0
174+EOF
175+
176+fi
177+
178+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
179+ cat >> confdefs.h <<\EOF
180+#define HARDENING_PATCH_LL_PROTECT 1
181+EOF
182+
183+else
184+ cat >> confdefs.h <<\EOF
185+#define HARDENING_PATCH_LL_PROTECT 0
186+EOF
187+
188+fi
189+
190+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
191+ cat >> confdefs.h <<\EOF
192+#define HARDENING_PATCH_INC_PROTECT 1
193+EOF
194+
195+else
196+ cat >> confdefs.h <<\EOF
197+#define HARDENING_PATCH_INC_PROTECT 0
198+EOF
199+
200+fi
201+
202+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
203+ cat >> confdefs.h <<\EOF
204+#define HARDENING_PATCH_FMT_PROTECT 1
205+EOF
206+
207+else
208+ cat >> confdefs.h <<\EOF
209+#define HARDENING_PATCH_FMT_PROTECT 0
210+EOF
211+
212+fi
213+
214+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
215+ cat >> confdefs.h <<\EOF
216+#define HARDENING_PATCH_HASH_PROTECT 1
217+EOF
218+
219+else
220+ cat >> confdefs.h <<\EOF
221+#define HARDENING_PATCH_HASH_PROTECT 0
222+EOF
223+
224+fi
225
226
227
228@@ -15733,6 +15896,62 @@
229 fi
230
231
232+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
233+echo "configure:14928: checking whether realpath is broken" >&5
234+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
235+ echo $ac_n "(cached) $ac_c" 1>&6
236+else
237+
238+ if test "$cross_compiling" = yes; then
239+
240+ ac_cv_broken_realpath=no
241+
242+else
243+ cat > conftest.$ac_ext <<EOF
244+#line 14939 "configure"
245+#include "confdefs.h"
246+
247+main() {
248+ char buf[4096+1];
249+ buf[0] = 0;
250+ realpath("/etc/hosts/../passwd", buf);
251+ exit(strcmp(buf, "/etc/passwd")==0);
252+}
253+
254+EOF
255+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
256+then
257+
258+ ac_cv_broken_realpath=no
259+
260+else
261+ echo "configure: failed program was:" >&5
262+ cat conftest.$ac_ext >&5
263+ rm -fr conftest*
264+
265+ ac_cv_broken_realpath=yes
266+
267+fi
268+rm -fr conftest*
269+fi
270+
271+
272+fi
273+
274+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
275+ if test "$ac_cv_broken_realpath" = "yes"; then
276+ cat >> confdefs.h <<\EOF
277+#define PHP_BROKEN_REALPATH 1
278+EOF
279+
280+ else
281+ cat >> confdefs.h <<\EOF
282+#define PHP_BROKEN_REALPATH 0
283+EOF
284+
285+ fi
286+
287+
288 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
289 echo "configure:15738: checking for declared timezone" >&5
290 if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
291@@ -83268,7 +83487,7 @@
292 if test "$ac_cv_crypt_blowfish" = "yes"; then
293 ac_result=1
294 else
295- ac_result=0
296+ ac_result=1
297 fi
298 cat >> confdefs.h <<EOF
299 #define PHP_BLOWFISH_CRYPT $ac_result
300@@ -83933,7 +84152,7 @@
301 url_scanner.c var.c versioning.c assert.c strnatcmp.c levenshtein.c \
302 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
303 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
304- var_unserializer.c ftok.c aggregation.c sha1.c ; do
305+ var_unserializer.c ftok.c aggregation.c sha1.c sha256.c crypt_blowfish.c ; do
306
307 IFS=.
308 set $ac_src
309@@ -83988,7 +84207,7 @@
310 url_scanner.c var.c versioning.c assert.c strnatcmp.c levenshtein.c \
311 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
312 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
313- var_unserializer.c ftok.c aggregation.c sha1.c ; do
314+ var_unserializer.c ftok.c aggregation.c sha1.c sha256.c crypt_blowfish.c ; do
315
316 IFS=.
317 set $ac_src
318@@ -84073,7 +84292,7 @@
319 url_scanner.c var.c versioning.c assert.c strnatcmp.c levenshtein.c \
320 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
321 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
322- var_unserializer.c ftok.c aggregation.c sha1.c ; do
323+ var_unserializer.c ftok.c aggregation.c sha1.c sha256.c crypt_blowfish.c ; do
324
325 IFS=.
326 set $ac_src
327@@ -84125,7 +84344,7 @@
328 url_scanner.c var.c versioning.c assert.c strnatcmp.c levenshtein.c \
329 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
330 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
331- var_unserializer.c ftok.c aggregation.c sha1.c ; do
332+ var_unserializer.c ftok.c aggregation.c sha1.c sha256.c crypt_blowfish.c ; do
333
334 IFS=.
335 set $ac_src
336@@ -87305,6 +87524,265 @@
337 fi
338
339
340+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
341+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
342+# Check whether --enable-varfilter or --disable-varfilter was given.
343+if test "${enable_varfilter+set}" = set; then
344+ enableval="$enable_varfilter"
345+ PHP_VARFILTER=$enableval
346+else
347+
348+ PHP_VARFILTER=yes
349+
350+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
351+ PHP_VARFILTER=$PHP_ENABLE_ALL
352+ fi
353+
354+fi
355+
356+
357+
358+ext_output="yes, shared"
359+ext_shared=yes
360+case $PHP_VARFILTER in
361+shared,*)
362+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
363+ ;;
364+shared)
365+ PHP_VARFILTER=yes
366+ ;;
367+no)
368+ ext_output=no
369+ ext_shared=no
370+ ;;
371+*)
372+ ext_output=yes
373+ ext_shared=no
374+ ;;
375+esac
376+
377+
378+
379+echo "$ac_t""$ext_output" 1>&6
380+
381+
382+
383+
384+if test "$PHP_VARFILTER" != "no"; then
385+ cat >> confdefs.h <<\EOF
386+#define HAVE_VARFILTER 1
387+EOF
388+
389+
390+ ext_builddir=ext/varfilter
391+ ext_srcdir=$abs_srcdir/ext/varfilter
392+
393+ ac_extra=
394+
395+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
396+
397+
398+
399+ case ext/varfilter in
400+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
401+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
402+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
403+ esac
404+
405+
406+
407+ b_c_pre=$php_c_pre
408+ b_cxx_pre=$php_cxx_pre
409+ b_c_meta=$php_c_meta
410+ b_cxx_meta=$php_cxx_meta
411+ b_c_post=$php_c_post
412+ b_cxx_post=$php_cxx_post
413+ b_lo=$php_lo
414+
415+
416+ old_IFS=$IFS
417+ for ac_src in varfilter.c; do
418+
419+ IFS=.
420+ set $ac_src
421+ ac_obj=$1
422+ IFS=$old_IFS
423+
424+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
425+
426+ case $ac_src in
427+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
428+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
429+ esac
430+
431+ cat >>Makefile.objects<<EOF
432+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
433+ $ac_comp
434+EOF
435+ done
436+
437+
438+ EXT_STATIC="$EXT_STATIC varfilter"
439+ if test "$ext_shared" != "nocli"; then
440+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
441+ fi
442+ else
443+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
444+
445+ case ext/varfilter in
446+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
447+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
448+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
449+ esac
450+
451+
452+
453+ b_c_pre=$shared_c_pre
454+ b_cxx_pre=$shared_cxx_pre
455+ b_c_meta=$shared_c_meta
456+ b_cxx_meta=$shared_cxx_meta
457+ b_c_post=$shared_c_post
458+ b_cxx_post=$shared_cxx_post
459+ b_lo=$shared_lo
460+
461+
462+ old_IFS=$IFS
463+ for ac_src in varfilter.c; do
464+
465+ IFS=.
466+ set $ac_src
467+ ac_obj=$1
468+ IFS=$old_IFS
469+
470+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
471+
472+ case $ac_src in
473+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
474+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
475+ esac
476+
477+ cat >>Makefile.objects<<EOF
478+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
479+ $ac_comp
480+EOF
481+ done
482+
483+
484+ install_modules="install-modules"
485+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
486+
487+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
488+
489+ cat >>Makefile.objects<<EOF
490+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
491+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
492+
493+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
494+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
495+
496+EOF
497+
498+ cat >> confdefs.h <<EOF
499+#define COMPILE_DL_VARFILTER 1
500+EOF
501+
502+ fi
503+ fi
504+
505+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
506+ if test "$PHP_SAPI" = "cgi"; then
507+
508+
509+ case ext/varfilter in
510+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
511+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
512+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
513+ esac
514+
515+
516+
517+ b_c_pre=$php_c_pre
518+ b_cxx_pre=$php_cxx_pre
519+ b_c_meta=$php_c_meta
520+ b_cxx_meta=$php_cxx_meta
521+ b_c_post=$php_c_post
522+ b_cxx_post=$php_cxx_post
523+ b_lo=$php_lo
524+
525+
526+ old_IFS=$IFS
527+ for ac_src in varfilter.c; do
528+
529+ IFS=.
530+ set $ac_src
531+ ac_obj=$1
532+ IFS=$old_IFS
533+
534+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
535+
536+ case $ac_src in
537+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
538+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
539+ esac
540+
541+ cat >>Makefile.objects<<EOF
542+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
543+ $ac_comp
544+EOF
545+ done
546+
547+
548+ EXT_STATIC="$EXT_STATIC varfilter"
549+ else
550+
551+
552+ case ext/varfilter in
553+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
554+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
555+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
556+ esac
557+
558+
559+
560+ b_c_pre=$php_c_pre
561+ b_cxx_pre=$php_cxx_pre
562+ b_c_meta=$php_c_meta
563+ b_cxx_meta=$php_cxx_meta
564+ b_c_post=$php_c_post
565+ b_cxx_post=$php_cxx_post
566+ b_lo=$php_lo
567+
568+
569+ old_IFS=$IFS
570+ for ac_src in varfilter.c; do
571+
572+ IFS=.
573+ set $ac_src
574+ ac_obj=$1
575+ IFS=$old_IFS
576+
577+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
578+
579+ case $ac_src in
580+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
581+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
582+ esac
583+
584+ cat >>Makefile.objects<<EOF
585+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
586+ $ac_comp
587+EOF
588+ done
589+
590+
591+ fi
592+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
593+ fi
594+
595+ BUILD_DIR="$BUILD_DIR $ext_builddir"
596+
597+
598+fi
599
600
601 echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
602@@ -99988,7 +100466,7 @@
603 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
604 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
605 streams.c network.c php_open_temporary_file.c php_logos.c \
606- output.c memory_streams.c user_streams.c; do
607+ output.c memory_streams.c user_streams.c hardening_patch.c; do
608
609 IFS=.
610 set $ac_src
611@@ -100161,7 +100639,7 @@
612 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
613 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
614 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
615- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c; do
616+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c; do
617
618 IFS=.
619 set $ac_src
620diff -Nura php-4.4.0/configure.in hardening-patch-4.4.0-0.4.3/configure.in
621--- php-4.4.0/configure.in 2005-07-11 09:45:09.000000000 +0200
622+++ hardening-patch-4.4.0-0.4.3/configure.in 2005-09-11 23:31:08.000000000 +0200
623@@ -238,7 +238,7 @@
624 sinclude(Zend/acinclude.m4)
625 sinclude(Zend/Zend.m4)
626 sinclude(TSRM/tsrm.m4)
627-
628+sinclude(main/hardening_patch.m4)
629
630
631 divert(2)
632@@ -612,6 +612,7 @@
633 AC_FUNC_ALLOCA
634 dnl PHP_AC_BROKEN_SPRINTF
635 dnl PHP_AC_BROKEN_SNPRINTF
636+PHP_AC_BROKEN_REALPATH
637 PHP_DECLARED_TIMEZONE
638 PHP_TIME_R_TYPE
639 PHP_READDIR_R_TYPE
640@@ -1241,7 +1242,7 @@
641 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
642 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
643 streams.c network.c php_open_temporary_file.c php_logos.c \
644- output.c memory_streams.c user_streams.c)
645+ output.c memory_streams.c user_streams.c hardening_patch.c)
646 PHP_ADD_SOURCES(/main, internal_functions.c,, sapi)
647 PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli)
648
649@@ -1254,7 +1255,7 @@
650 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
651 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
652 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
653- zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c)
654+ zend_ini.c zend_qsort.c zend_multibyte.c zend_strtod.c zend_canary.c )
655
656 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
657 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c)
658diff -Nura php-4.4.0/ext/fbsql/php_fbsql.c hardening-patch-4.4.0-0.4.3/ext/fbsql/php_fbsql.c
659--- php-4.4.0/ext/fbsql/php_fbsql.c 2005-02-09 20:33:32.000000000 +0100
660+++ hardening-patch-4.4.0-0.4.3/ext/fbsql/php_fbsql.c 2005-09-11 23:31:08.000000000 +0200
661@@ -1797,8 +1797,24 @@
662 }
663 else if (fbcmdErrorsFound(md))
664 {
665+#if HARDENING_PATCH
666+ char* query_copy;
667+ int i;
668+#endif
669 FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
670 char* emg = fbcemdAllErrorMessages(emd);
671+#if HARDENING_PATCH
672+ query_copy=estrdup(query_copy);
673+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
674+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
675+ efree(query_copy);
676+ if (HG(hphp_sql_bailout_on_error)) {
677+ free(emg);
678+ fbcemdRelease(emd);
679+ result = 0;
680+ zend_bailout();
681+ }
682+#endif
683 if (FB_SQL_G(generateWarnings))
684 {
685 if (emg)
686diff -Nura php-4.4.0/ext/mbstring/mbstring.c hardening-patch-4.4.0-0.4.3/ext/mbstring/mbstring.c
687--- php-4.4.0/ext/mbstring/mbstring.c 2005-02-21 09:03:47.000000000 +0100
688+++ hardening-patch-4.4.0-0.4.3/ext/mbstring/mbstring.c 2005-09-11 23:31:08.000000000 +0200
689@@ -1487,6 +1487,7 @@
690 char *strtok_buf = NULL, **val_list;
691 zval *array_ptr = (zval *) arg;
692 int n, num, val_len, *len_list;
693+ unsigned int new_val_len;
694 enum mbfl_no_encoding from_encoding;
695 mbfl_string string, resvar, resval;
696 mbfl_encoding_detector *identd = NULL;
697@@ -1609,8 +1610,14 @@
698 val_len = len_list[n];
699 }
700 n++;
701- /* add variable to symbol table */
702- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
703+ /* we need val to be emalloc()ed */
704+ val = estrndup(val, val_len);
705+ if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) {
706+ /* add variable to symbol table */
707+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
708+ }
709+ efree(val);
710+
711 if (convd != NULL){
712 mbfl_string_clear(&resvar);
713 mbfl_string_clear(&resval);
714diff -Nura php-4.4.0/ext/mysql/php_mysql.c hardening-patch-4.4.0-0.4.3/ext/mysql/php_mysql.c
715--- php-4.4.0/ext/mysql/php_mysql.c 2005-04-08 00:23:01.000000000 +0200
716+++ hardening-patch-4.4.0-0.4.3/ext/mysql/php_mysql.c 2005-09-11 23:31:08.000000000 +0200
717@@ -1218,6 +1218,8 @@
718 {
719 php_mysql_conn *mysql;
720 MYSQL_RES *mysql_result;
721+ char *copy_query;
722+ int i;
723
724 ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
725
726@@ -1268,6 +1270,13 @@
727 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
728 }
729 }
730+ copy_query = estrdup(Z_STRVAL_PP(query));
731+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
732+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
733+ efree(copy_query);
734+ if (HG(hphp_sql_bailout_on_error)) {
735+ zend_bailout();
736+ }
737 RETURN_FALSE;
738 }
739 #else
740@@ -1275,12 +1284,20 @@
741 /* check possible error */
742 if (MySG(trace_mode)){
743 if (mysql_errno(&mysql->conn)){
744- php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, mysql_error(&mysql->conn));
745+ php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
746 }
747 }
748+ copy_query = estrdup(Z_STRVAL_PP(query));
749+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
750+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
751+ efree(copy_query);
752+ if (HG(hphp_sql_bailout_on_error)) {
753+ zend_bailout();
754+ }
755 RETURN_FALSE;
756 }
757 #endif
758+
759 if(use_store == MYSQL_USE_RESULT) {
760 mysql_result=mysql_use_result(&mysql->conn);
761 } else {
762diff -Nura php-4.4.0/ext/pgsql/pgsql.c hardening-patch-4.4.0-0.4.3/ext/pgsql/pgsql.c
763--- php-4.4.0/ext/pgsql/pgsql.c 2005-07-05 14:50:03.000000000 +0200
764+++ hardening-patch-4.4.0-0.4.3/ext/pgsql/pgsql.c 2005-09-11 23:31:08.000000000 +0200
765@@ -1001,10 +1001,28 @@
766 case PGRES_EMPTY_QUERY:
767 case PGRES_BAD_RESPONSE:
768 case PGRES_NONFATAL_ERROR:
769- case PGRES_FATAL_ERROR:
770- PHP_PQ_ERROR("Query failed: %s", pgsql);
771- PQclear(pgsql_result);
772- RETURN_FALSE;
773+ case PGRES_FATAL_ERROR:
774+ {
775+#if HARDENING_PATCH
776+ int i;
777+ char *query_copy;
778+#endif
779+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
780+ PQclear(pgsql_result);
781+#if HARDENING_PATCH
782+ query_copy = estrdup(Z_STRVAL_PP(query));
783+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
784+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
785+ efree(query_copy);
786+ if (HG(hphp_sql_bailout_on_error)) {
787+ efree(msgbuf);
788+ zend_bailout();
789+ }
790+#endif
791+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
792+ efree(msgbuf);
793+ RETURN_FALSE;
794+ }
795 break;
796 case PGRES_COMMAND_OK: /* successful command that did not return rows */
797 default:
798diff -Nura php-4.4.0/ext/standard/array.c hardening-patch-4.4.0-0.4.3/ext/standard/array.c
799--- php-4.4.0/ext/standard/array.c 2005-06-21 14:11:19.000000000 +0200
800+++ hardening-patch-4.4.0-0.4.3/ext/standard/array.c 2005-09-11 23:31:08.000000000 +0200
801@@ -1162,6 +1162,32 @@
802 }
803 }
804 }
805+
806+ if (var_name[0] == 'H') {
807+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
808+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
809+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
810+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
811+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
812+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
813+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
814+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
815+ return 0;
816+ }
817+ } else if (var_name[0] == '_') {
818+ if ((strcmp(var_name, "_COOKIE")==0)||
819+ (strcmp(var_name, "_ENV")==0)||
820+ (strcmp(var_name, "_FILES")==0)||
821+ (strcmp(var_name, "_GET")==0)||
822+ (strcmp(var_name, "_POST")==0)||
823+ (strcmp(var_name, "_REQUEST")==0)||
824+ (strcmp(var_name, "_SESSION")==0)||
825+ (strcmp(var_name, "_SERVER")==0)) {
826+ return 0;
827+ }
828+ } else if (strcmp(var_name, "GLOBALS")==0) {
829+ return 0;
830+ }
831
832 return 1;
833 }
834diff -Nura php-4.4.0/ext/standard/basic_functions.c hardening-patch-4.4.0-0.4.3/ext/standard/basic_functions.c
835--- php-4.4.0/ext/standard/basic_functions.c 2005-05-16 10:55:31.000000000 +0200
836+++ hardening-patch-4.4.0-0.4.3/ext/standard/basic_functions.c 2005-09-11 23:31:08.000000000 +0200
837@@ -118,12 +118,14 @@
838 typedef struct _php_shutdown_function_entry {
839 zval **arguments;
840 int arg_count;
841+ zend_bool created_by_eval;
842 } php_shutdown_function_entry;
843
844 typedef struct _user_tick_function_entry {
845 zval **arguments;
846 int arg_count;
847 int calling;
848+ zend_bool created_by_eval;
849 } user_tick_function_entry;
850
851 /* some prototypes for local functions */
852@@ -306,6 +308,8 @@
853 PHP_FE(get_html_translation_table, NULL)
854 PHP_FE(sha1, NULL)
855 PHP_FE(sha1_file, NULL)
856+ PHP_FE(sha256, NULL)
857+ PHP_FE(sha256_file, NULL)
858 PHP_NAMED_FE(md5,php_if_md5, NULL)
859 PHP_NAMED_FE(md5_file,php_if_md5_file, NULL)
860 PHP_NAMED_FE(crc32,php_if_crc32, NULL)
861@@ -687,7 +691,7 @@
862 PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
863
864 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
865- PHP_FE(realpath, NULL)
866+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
867 #endif
868
869 #ifdef HAVE_FNMATCH
870@@ -2104,6 +2108,13 @@
871 {
872 zval retval;
873 char *function_name = NULL;
874+#if HARDENING_PATCH
875+ zend_uint orig_code_type = EG(in_code_type);
876+
877+ if (shutdown_function_entry->created_by_eval) {
878+ EG(in_code_type) = ZEND_EVAL_CODE;
879+ }
880+#endif
881
882 if (!zend_is_callable(shutdown_function_entry->arguments[0], 0, &function_name)) {
883 php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", function_name);
884@@ -2119,6 +2130,9 @@
885 if (function_name) {
886 efree(function_name);
887 }
888+#if HARDENING_PATCH
889+ EG(in_code_type) = orig_code_type;
890+#endif
891 return 0;
892 }
893
894@@ -2126,6 +2140,13 @@
895 {
896 zval retval;
897 zval *function = tick_fe->arguments[0];
898+#if HARDENING_PATCH
899+ zend_uint orig_code_type = EG(in_code_type);
900+
901+ if (tick_fe->created_by_eval) {
902+ EG(in_code_type) = ZEND_EVAL_CODE;
903+ }
904+#endif
905
906 /* Prevent reentrant calls to the same user ticks function */
907 if (! tick_fe->calling) {
908@@ -2157,6 +2178,9 @@
909
910 tick_fe->calling = 0;
911 }
912+#if HARDENING_PATCH
913+ EG(in_code_type) = orig_code_type;
914+#endif
915 }
916
917 static void run_user_tick_functions(int tick_count)
918@@ -2224,6 +2248,13 @@
919 if (zend_get_parameters_array(ht, shutdown_function_entry.arg_count, shutdown_function_entry.arguments) == FAILURE) {
920 RETURN_FALSE;
921 }
922+#if HARDENING_PATCH
923+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
924+ shutdown_function_entry.created_by_eval = 1;
925+ } else {
926+ shutdown_function_entry.created_by_eval = 0;
927+ }
928+#endif
929
930 /* Prevent entering of anything but valid callback (syntax check only!) */
931 if (!zend_is_callable(shutdown_function_entry.arguments[0], 1, &function_name)) {
932@@ -2761,6 +2792,13 @@
933 }
934
935 tick_fe.arguments = (zval **) safe_emalloc(sizeof(zval *), tick_fe.arg_count, 0);
936+#if HARDENING_PATCH
937+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
938+ tick_fe.created_by_eval = 1;
939+ } else {
940+ tick_fe.created_by_eval = 0;
941+ }
942+#endif
943
944 if (zend_get_parameters_array(ht, tick_fe.arg_count, tick_fe.arguments) == FAILURE) {
945 RETURN_FALSE;
946@@ -3044,6 +3082,35 @@
947 memcpy(new_key, prefix, prefix_len);
948 memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength);
949
950+ if (new_key[0] == 'H') {
951+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
952+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
953+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
954+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
955+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
956+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
957+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
958+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
959+ efree(new_key);
960+ return 0;
961+ }
962+ } else if (new_key[0] == '_') {
963+ if ((strcmp(new_key, "_COOKIE")==0)||
964+ (strcmp(new_key, "_ENV")==0)||
965+ (strcmp(new_key, "_FILES")==0)||
966+ (strcmp(new_key, "_GET")==0)||
967+ (strcmp(new_key, "_POST")==0)||
968+ (strcmp(new_key, "_REQUEST")==0)||
969+ (strcmp(new_key, "_SESSION")==0)||
970+ (strcmp(new_key, "_SERVER")==0)) {
971+ efree(new_key);
972+ return 0;
973+ }
974+ } else if (strcmp(new_key, "GLOBALS")==0) {
975+ efree(new_key);
976+ return 0;
977+ }
978+
979 zend_hash_del(&EG(symbol_table), new_key, new_key_len);
980 ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
981
982diff -Nura php-4.4.0/ext/standard/config.m4 hardening-patch-4.4.0-0.4.3/ext/standard/config.m4
983--- php-4.4.0/ext/standard/config.m4 2004-12-30 08:02:18.000000000 +0100
984+++ hardening-patch-4.4.0-0.4.3/ext/standard/config.m4 2005-09-11 23:31:08.000000000 +0200
985@@ -203,7 +203,7 @@
986 if test "$ac_cv_crypt_blowfish" = "yes"; then
987 ac_result=1
988 else
989- ac_result=0
990+ ac_result=1
991 fi
992 AC_DEFINE_UNQUOTED(PHP_BLOWFISH_CRYPT, $ac_result, [Whether the system supports BlowFish salt])
993 ])
994@@ -419,6 +419,6 @@
995 url_scanner.c var.c versioning.c assert.c strnatcmp.c levenshtein.c \
996 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
997 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
998- var_unserializer.c ftok.c aggregation.c sha1.c )
999+ var_unserializer.c ftok.c aggregation.c sha1.c sha256.c crypt_blowfish.c )
1000
1001 PHP_ADD_MAKEFILE_FRAGMENT
1002diff -Nura php-4.4.0/ext/standard/crypt_blowfish.c hardening-patch-4.4.0-0.4.3/ext/standard/crypt_blowfish.c
1003--- php-4.4.0/ext/standard/crypt_blowfish.c 1970-01-01 01:00:00.000000000 +0100
1004+++ hardening-patch-4.4.0-0.4.3/ext/standard/crypt_blowfish.c 2005-09-11 23:31:08.000000000 +0200
1005@@ -0,0 +1,748 @@
1006+/*
1007+ * This code comes from John the Ripper password cracker, with reentrant
1008+ * and crypt(3) interfaces added, but optimizations specific to password
1009+ * cracking removed.
1010+ *
1011+ * Written by Solar Designer <solar at openwall.com> in 1998-2002 and
1012+ * placed in the public domain.
1013+ *
1014+ * There's absolutely no warranty.
1015+ *
1016+ * It is my intent that you should be able to use this on your system,
1017+ * as a part of a software package, or anywhere else to improve security,
1018+ * ensure compatibility, or for any other purpose. I would appreciate
1019+ * it if you give credit where it is due and keep your modifications in
1020+ * the public domain as well, but I don't require that in order to let
1021+ * you place this code and any modifications you make under a license
1022+ * of your choice.
1023+ *
1024+ * This implementation is compatible with OpenBSD bcrypt.c (version 2a)
1025+ * by Niels Provos <provos at citi.umich.edu>, and uses some of his
1026+ * ideas. The password hashing algorithm was designed by David Mazieres
1027+ * <dm at lcs.mit.edu>.
1028+ *
1029+ * There's a paper on the algorithm that explains its design decisions:
1030+ *
1031+ * http://www.usenix.org/events/usenix99/provos.html
1032+ *
1033+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
1034+ * Blowfish library (I can't be sure if I would think of something if I
1035+ * hadn't seen his code).
1036+ */
1037+
1038+#include <string.h>
1039+
1040+#include <errno.h>
1041+#ifndef __set_errno
1042+#define __set_errno(val) errno = (val)
1043+#endif
1044+
1045+#undef __CONST
1046+#ifdef __GNUC__
1047+#define __CONST __const
1048+#else
1049+#define __CONST
1050+#endif
1051+
1052+#ifdef __i386__
1053+#define BF_ASM 0
1054+#define BF_SCALE 1
1055+#elif defined(__alpha__) || defined(__hppa__)
1056+#define BF_ASM 0
1057+#define BF_SCALE 1
1058+#else
1059+#define BF_ASM 0
1060+#define BF_SCALE 0
1061+#endif
1062+
1063+typedef unsigned int BF_word;
1064+
1065+/* Number of Blowfish rounds, this is also hardcoded into a few places */
1066+#define BF_N 16
1067+
1068+typedef BF_word BF_key[BF_N + 2];
1069+
1070+typedef struct {
1071+ BF_word S[4][0x100];
1072+ BF_key P;
1073+} BF_ctx;
1074+
1075+/*
1076+ * Magic IV for 64 Blowfish encryptions that we do at the end.
1077+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
1078+ */
1079+static BF_word BF_magic_w[6] = {
1080+ 0x4F727068, 0x65616E42, 0x65686F6C,
1081+ 0x64657253, 0x63727944, 0x6F756274
1082+};
1083+
1084+/*
1085+ * P-box and S-box tables initialized with digits of Pi.
1086+ */
1087+static BF_ctx BF_init_state = {
1088+ {
1089+ {
1090+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
1091+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
1092+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
1093+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
1094+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
1095+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
1096+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
1097+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
1098+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
1099+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
1100+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
1101+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
1102+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
1103+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
1104+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
1105+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
1106+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
1107+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
1108+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
1109+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
1110+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
1111+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
1112+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
1113+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
1114+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
1115+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
1116+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
1117+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
1118+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
1119+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
1120+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
1121+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
1122+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
1123+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
1124+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
1125+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
1126+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
1127+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
1128+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
1129+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
1130+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
1131+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
1132+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
1133+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
1134+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
1135+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
1136+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
1137+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
1138+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
1139+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
1140+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
1141+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
1142+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
1143+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
1144+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
1145+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
1146+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
1147+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
1148+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
1149+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
1150+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
1151+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
1152+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
1153+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
1154+ }, {
1155+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
1156+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
1157+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
1158+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
1159+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
1160+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
1161+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
1162+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
1163+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
1164+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
1165+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
1166+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
1167+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
1168+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
1169+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
1170+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
1171+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
1172+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
1173+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
1174+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
1175+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
1176+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
1177+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
1178+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
1179+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
1180+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
1181+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
1182+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
1183+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
1184+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
1185+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
1186+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
1187+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
1188+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
1189+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
1190+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
1191+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
1192+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
1193+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
1194+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
1195+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
1196+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
1197+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
1198+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
1199+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
1200+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
1201+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
1202+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
1203+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
1204+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
1205+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
1206+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
1207+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
1208+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
1209+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
1210+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
1211+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
1212+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
1213+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
1214+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
1215+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
1216+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
1217+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
1218+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
1219+ }, {
1220+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
1221+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
1222+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
1223+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
1224+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
1225+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
1226+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
1227+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
1228+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
1229+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
1230+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
1231+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
1232+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
1233+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
1234+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
1235+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
1236+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
1237+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
1238+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
1239+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
1240+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
1241+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
1242+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
1243+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
1244+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
1245+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
1246+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
1247+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
1248+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
1249+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
1250+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
1251+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
1252+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
1253+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
1254+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
1255+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
1256+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
1257+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
1258+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
1259+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
1260+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
1261+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
1262+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
1263+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
1264+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
1265+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
1266+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
1267+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
1268+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
1269+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
1270+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
1271+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
1272+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
1273+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
1274+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
1275+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
1276+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
1277+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
1278+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
1279+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
1280+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
1281+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
1282+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
1283+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
1284+ }, {
1285+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
1286+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
1287+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
1288+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
1289+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
1290+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
1291+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
1292+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
1293+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
1294+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
1295+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
1296+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
1297+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
1298+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
1299+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
1300+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
1301+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
1302+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
1303+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
1304+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
1305+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
1306+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
1307+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
1308+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
1309+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
1310+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
1311+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
1312+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
1313+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
1314+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
1315+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
1316+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
1317+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
1318+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
1319+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
1320+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
1321+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
1322+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
1323+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
1324+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
1325+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
1326+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
1327+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
1328+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
1329+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
1330+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
1331+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
1332+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
1333+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
1334+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
1335+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
1336+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
1337+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
1338+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
1339+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
1340+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
1341+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
1342+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
1343+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
1344+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
1345+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
1346+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
1347+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
1348+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
1349+ }
1350+ }, {
1351+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
1352+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
1353+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
1354+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
1355+ 0x9216d5d9, 0x8979fb1b
1356+ }
1357+};
1358+
1359+static unsigned char BF_itoa64[64 + 1] =
1360+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1361+
1362+static unsigned char BF_atoi64[0x60] = {
1363+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
1364+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
1365+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1366+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
1367+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
1368+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
1369+};
1370+
1371+/*
1372+ * This may be optimized out if built with function inlining and no BF_ASM.
1373+ */
1374+static void clean(void *data, int size)
1375+{
1376+#if BF_ASM
1377+ extern void _BF_clean(void *data);
1378+#endif
1379+ memset(data, 0, size);
1380+#if BF_ASM
1381+ _BF_clean(data);
1382+#endif
1383+}
1384+
1385+#define BF_safe_atoi64(dst, src) \
1386+{ \
1387+ tmp = (unsigned char)(src); \
1388+ if (tmp == '$') break; \
1389+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
1390+ tmp = BF_atoi64[tmp]; \
1391+ if (tmp > 63) return -1; \
1392+ (dst) = tmp; \
1393+}
1394+
1395+static int BF_decode(BF_word *dst, __CONST char *src, int size)
1396+{
1397+ unsigned char *dptr = (unsigned char *)dst;
1398+ unsigned char *end = dptr + size;
1399+ unsigned char *sptr = (unsigned char *)src;
1400+ unsigned int tmp, c1, c2, c3, c4;
1401+
1402+ do {
1403+ BF_safe_atoi64(c1, *sptr++);
1404+ BF_safe_atoi64(c2, *sptr++);
1405+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
1406+ if (dptr >= end) break;
1407+
1408+ BF_safe_atoi64(c3, *sptr++);
1409+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
1410+ if (dptr >= end) break;
1411+
1412+ BF_safe_atoi64(c4, *sptr++);
1413+ *dptr++ = ((c3 & 0x03) << 6) | c4;
1414+ } while (dptr < end);
1415+
1416+ while (dptr < end)
1417+ *dptr++ = 0;
1418+
1419+ return 0;
1420+}
1421+
1422+static void BF_encode(char *dst, __CONST BF_word *src, int size)
1423+{
1424+ unsigned char *sptr = (unsigned char *)src;
1425+ unsigned char *end = sptr + size;
1426+ unsigned char *dptr = (unsigned char *)dst;
1427+ unsigned int c1, c2;
1428+
1429+ do {
1430+ c1 = *sptr++;
1431+ *dptr++ = BF_itoa64[c1 >> 2];
1432+ c1 = (c1 & 0x03) << 4;
1433+ if (sptr >= end) {
1434+ *dptr++ = BF_itoa64[c1];
1435+ break;
1436+ }
1437+
1438+ c2 = *sptr++;
1439+ c1 |= c2 >> 4;
1440+ *dptr++ = BF_itoa64[c1];
1441+ c1 = (c2 & 0x0f) << 2;
1442+ if (sptr >= end) {
1443+ *dptr++ = BF_itoa64[c1];
1444+ break;
1445+ }
1446+
1447+ c2 = *sptr++;
1448+ c1 |= c2 >> 6;
1449+ *dptr++ = BF_itoa64[c1];
1450+ *dptr++ = BF_itoa64[c2 & 0x3f];
1451+ } while (sptr < end);
1452+}
1453+
1454+static void BF_swap(BF_word *x, int count)
1455+{
1456+ static int endianness_check = 1;
1457+ char *is_little_endian = (char *)&endianness_check;
1458+ BF_word tmp;
1459+
1460+ if (*is_little_endian)
1461+ do {
1462+ tmp = *x;
1463+ tmp = (tmp << 16) | (tmp >> 16);
1464+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
1465+ } while (--count);
1466+}
1467+
1468+#if BF_SCALE
1469+/* Architectures which can shift addresses left by 2 bits with no extra cost */
1470+#define BF_ROUND(L, R, N) \
1471+ tmp1 = L & 0xFF; \
1472+ tmp2 = L >> 8; \
1473+ tmp2 &= 0xFF; \
1474+ tmp3 = L >> 16; \
1475+ tmp3 &= 0xFF; \
1476+ tmp4 = L >> 24; \
1477+ tmp1 = data.ctx.S[3][tmp1]; \
1478+ tmp2 = data.ctx.S[2][tmp2]; \
1479+ tmp3 = data.ctx.S[1][tmp3]; \
1480+ tmp3 += data.ctx.S[0][tmp4]; \
1481+ tmp3 ^= tmp2; \
1482+ R ^= data.ctx.P[N + 1]; \
1483+ tmp3 += tmp1; \
1484+ R ^= tmp3;
1485+#else
1486+/* Architectures with no complicated addressing modes supported */
1487+#define BF_INDEX(S, i) \
1488+ (*((BF_word *)(((unsigned char *)S) + (i))))
1489+#define BF_ROUND(L, R, N) \
1490+ tmp1 = L & 0xFF; \
1491+ tmp1 <<= 2; \
1492+ tmp2 = L >> 6; \
1493+ tmp2 &= 0x3FC; \
1494+ tmp3 = L >> 14; \
1495+ tmp3 &= 0x3FC; \
1496+ tmp4 = L >> 22; \
1497+ tmp4 &= 0x3FC; \
1498+ tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
1499+ tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
1500+ tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
1501+ tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
1502+ tmp3 ^= tmp2; \
1503+ R ^= data.ctx.P[N + 1]; \
1504+ tmp3 += tmp1; \
1505+ R ^= tmp3;
1506+#endif
1507+
1508+/*
1509+ * Encrypt one block, BF_N is hardcoded here.
1510+ */
1511+#define BF_ENCRYPT \
1512+ L ^= data.ctx.P[0]; \
1513+ BF_ROUND(L, R, 0); \
1514+ BF_ROUND(R, L, 1); \
1515+ BF_ROUND(L, R, 2); \
1516+ BF_ROUND(R, L, 3); \
1517+ BF_ROUND(L, R, 4); \
1518+ BF_ROUND(R, L, 5); \
1519+ BF_ROUND(L, R, 6); \
1520+ BF_ROUND(R, L, 7); \
1521+ BF_ROUND(L, R, 8); \
1522+ BF_ROUND(R, L, 9); \
1523+ BF_ROUND(L, R, 10); \
1524+ BF_ROUND(R, L, 11); \
1525+ BF_ROUND(L, R, 12); \
1526+ BF_ROUND(R, L, 13); \
1527+ BF_ROUND(L, R, 14); \
1528+ BF_ROUND(R, L, 15); \
1529+ tmp4 = R; \
1530+ R = L; \
1531+ L = tmp4 ^ data.ctx.P[BF_N + 1];
1532+
1533+#if BF_ASM
1534+#define BF_body() \
1535+ _BF_body_r(&data.ctx);
1536+#else
1537+#define BF_body() \
1538+ L = R = 0; \
1539+ ptr = data.ctx.P; \
1540+ do { \
1541+ ptr += 2; \
1542+ BF_ENCRYPT; \
1543+ *(ptr - 2) = L; \
1544+ *(ptr - 1) = R; \
1545+ } while (ptr < &data.ctx.P[BF_N + 2]); \
1546+\
1547+ ptr = data.ctx.S[0]; \
1548+ do { \
1549+ ptr += 2; \
1550+ BF_ENCRYPT; \
1551+ *(ptr - 2) = L; \
1552+ *(ptr - 1) = R; \
1553+ } while (ptr < &data.ctx.S[3][0xFF]);
1554+#endif
1555+
1556+static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial)
1557+{
1558+ __CONST char *ptr = key;
1559+ int i, j;
1560+ BF_word tmp;
1561+
1562+ for (i = 0; i < BF_N + 2; i++) {
1563+ tmp = 0;
1564+ for (j = 0; j < 4; j++) {
1565+ tmp <<= 8;
1566+ tmp |= *ptr;
1567+
1568+ if (!*ptr) ptr = key; else ptr++;
1569+ }
1570+
1571+ expanded[i] = tmp;
1572+ initial[i] = BF_init_state.P[i] ^ tmp;
1573+ }
1574+}
1575+
1576+char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
1577+ char *output, int size)
1578+{
1579+#if BF_ASM
1580+ extern void _BF_body_r(BF_ctx *ctx);
1581+#endif
1582+ struct {
1583+ BF_ctx ctx;
1584+ BF_key expanded_key;
1585+ union {
1586+ BF_word salt[4];
1587+ BF_word output[6];
1588+ } binary;
1589+ } data;
1590+ BF_word L, R;
1591+ BF_word tmp1, tmp2, tmp3, tmp4;
1592+ BF_word *ptr;
1593+ BF_word count;
1594+ int i;
1595+
1596+ if (size < 7 + 22 + 31 + 1) {
1597+ __set_errno(ERANGE);
1598+ return NULL;
1599+ }
1600+
1601+ if (setting[0] != '$' ||
1602+ setting[1] != '2' ||
1603+ setting[2] != 'a' ||
1604+ setting[3] != '$' ||
1605+ setting[4] < '0' || setting[4] > '3' ||
1606+ setting[5] < '0' || setting[5] > '9' ||
1607+ setting[6] != '$') {
1608+ __set_errno(EINVAL);
1609+ return NULL;
1610+ }
1611+
1612+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
1613+ if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) {
1614+ clean(data.binary.salt, sizeof(data.binary.salt));
1615+ __set_errno(EINVAL);
1616+ return NULL;
1617+ }
1618+
1619+ BF_swap(data.binary.salt, 4);
1620+
1621+ BF_set_key(key, data.expanded_key, data.ctx.P);
1622+
1623+ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
1624+
1625+ L = R = 0;
1626+ for (i = 0; i < BF_N + 2; i += 2) {
1627+ L ^= data.binary.salt[i & 2];
1628+ R ^= data.binary.salt[(i & 2) + 1];
1629+ BF_ENCRYPT;
1630+ data.ctx.P[i] = L;
1631+ data.ctx.P[i + 1] = R;
1632+ }
1633+
1634+ ptr = data.ctx.S[0];
1635+ do {
1636+ ptr += 4;
1637+ L ^= data.binary.salt[(BF_N + 2) & 3];
1638+ R ^= data.binary.salt[(BF_N + 3) & 3];
1639+ BF_ENCRYPT;
1640+ *(ptr - 4) = L;
1641+ *(ptr - 3) = R;
1642+
1643+ L ^= data.binary.salt[(BF_N + 4) & 3];
1644+ R ^= data.binary.salt[(BF_N + 5) & 3];
1645+ BF_ENCRYPT;
1646+ *(ptr - 2) = L;
1647+ *(ptr - 1) = R;
1648+ } while (ptr < &data.ctx.S[3][0xFF]);
1649+
1650+ do {
1651+ data.ctx.P[0] ^= data.expanded_key[0];
1652+ data.ctx.P[1] ^= data.expanded_key[1];
1653+ data.ctx.P[2] ^= data.expanded_key[2];
1654+ data.ctx.P[3] ^= data.expanded_key[3];
1655+ data.ctx.P[4] ^= data.expanded_key[4];
1656+ data.ctx.P[5] ^= data.expanded_key[5];
1657+ data.ctx.P[6] ^= data.expanded_key[6];
1658+ data.ctx.P[7] ^= data.expanded_key[7];
1659+ data.ctx.P[8] ^= data.expanded_key[8];
1660+ data.ctx.P[9] ^= data.expanded_key[9];
1661+ data.ctx.P[10] ^= data.expanded_key[10];
1662+ data.ctx.P[11] ^= data.expanded_key[11];
1663+ data.ctx.P[12] ^= data.expanded_key[12];
1664+ data.ctx.P[13] ^= data.expanded_key[13];
1665+ data.ctx.P[14] ^= data.expanded_key[14];
1666+ data.ctx.P[15] ^= data.expanded_key[15];
1667+ data.ctx.P[16] ^= data.expanded_key[16];
1668+ data.ctx.P[17] ^= data.expanded_key[17];
1669+
1670+ BF_body();
1671+
1672+ tmp1 = data.binary.salt[0];
1673+ tmp2 = data.binary.salt[1];
1674+ tmp3 = data.binary.salt[2];
1675+ tmp4 = data.binary.salt[3];
1676+ data.ctx.P[0] ^= tmp1;
1677+ data.ctx.P[1] ^= tmp2;
1678+ data.ctx.P[2] ^= tmp3;
1679+ data.ctx.P[3] ^= tmp4;
1680+ data.ctx.P[4] ^= tmp1;
1681+ data.ctx.P[5] ^= tmp2;
1682+ data.ctx.P[6] ^= tmp3;
1683+ data.ctx.P[7] ^= tmp4;
1684+ data.ctx.P[8] ^= tmp1;
1685+ data.ctx.P[9] ^= tmp2;
1686+ data.ctx.P[10] ^= tmp3;
1687+ data.ctx.P[11] ^= tmp4;
1688+ data.ctx.P[12] ^= tmp1;
1689+ data.ctx.P[13] ^= tmp2;
1690+ data.ctx.P[14] ^= tmp3;
1691+ data.ctx.P[15] ^= tmp4;
1692+ data.ctx.P[16] ^= tmp1;
1693+ data.ctx.P[17] ^= tmp2;
1694+
1695+ BF_body();
1696+ } while (--count);
1697+
1698+ for (i = 0; i < 6; i += 2) {
1699+ L = BF_magic_w[i];
1700+ R = BF_magic_w[i + 1];
1701+
1702+ count = 64;
1703+ do {
1704+ BF_ENCRYPT;
1705+ } while (--count);
1706+
1707+ data.binary.output[i] = L;
1708+ data.binary.output[i + 1] = R;
1709+ }
1710+
1711+ memcpy(output, setting, 7 + 22 - 1);
1712+ output[7 + 22 - 1] = BF_itoa64[(int)
1713+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
1714+
1715+/* This has to be bug-compatible with the original implementation, so
1716+ * only encode 23 of the 24 bytes. :-) */
1717+ BF_swap(data.binary.output, 6);
1718+ BF_encode(&output[7 + 22], data.binary.output, 23);
1719+ output[7 + 22 + 31] = '\0';
1720+
1721+/* Overwrite the most obvious sensitive data we have on the stack. Note
1722+ * that this does not guarantee there's no sensitive data left on the
1723+ * stack and/or in registers; I'm not aware of portable code that does. */
1724+ clean(&data, sizeof(data));
1725+
1726+ return output;
1727+}
1728+
1729+char *_crypt_gensalt_blowfish_rn(unsigned long count,
1730+ __CONST char *input, int size, char *output, int output_size)
1731+{
1732+ if (size < 16 || output_size < 7 + 22 + 1 ||
1733+ (count && (count < 4 || count > 31))) {
1734+ if (output_size > 0) output[0] = '\0';
1735+ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
1736+ return NULL;
1737+ }
1738+
1739+ if (!count) count = 5;
1740+
1741+ output[0] = '$';
1742+ output[1] = '2';
1743+ output[2] = 'a';
1744+ output[3] = '$';
1745+ output[4] = '0' + count / 10;
1746+ output[5] = '0' + count % 10;
1747+ output[6] = '$';
1748+
1749+ BF_encode(&output[7], (BF_word *)input, 16);
1750+ output[7 + 22] = '\0';
1751+
1752+ return output;
1753+}
1754diff -Nura php-4.4.0/ext/standard/crypt.c hardening-patch-4.4.0-0.4.3/ext/standard/crypt.c
1755--- php-4.4.0/ext/standard/crypt.c 2004-01-19 04:16:04.000000000 +0100
1756+++ hardening-patch-4.4.0-0.4.3/ext/standard/crypt.c 2005-09-11 23:31:08.000000000 +0200
1757@@ -100,6 +100,8 @@
1758 return SUCCESS;
1759 }
1760
1761+char *_crypt_blowfish_rn(char *key, char *setting, char *output, int size);
1762+char *_crypt_gensalt_blowfish_rn(unsigned long count, char *input, int size, char *output, int output_size);
1763
1764 static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1765
1766@@ -135,7 +137,14 @@
1767
1768 /* The automatic salt generation only covers standard DES and md5-crypt */
1769 if(!*salt) {
1770-#if PHP_MD5_CRYPT
1771+#if PHP_BLOWFISH_CRYPT
1772+ char randat[16];
1773+ int i;
1774+
1775+ for (i=0; i<16; i++) randat[i] = PHP_CRYPT_RAND;
1776+
1777+ _crypt_gensalt_blowfish_rn(5, randat, sizeof(randat), salt, sizeof(salt));
1778+#elif PHP_MD5_CRYPT
1779 strcpy(salt, "$1$");
1780 php_to64(&salt[3], PHP_CRYPT_RAND, 4);
1781 php_to64(&salt[7], PHP_CRYPT_RAND, 4);
1782@@ -145,8 +154,24 @@
1783 salt[2] = '\0';
1784 #endif
1785 }
1786-
1787- RETVAL_STRING(crypt(str, salt), 1);
1788+
1789+ if (salt[0] == '$' &&
1790+ salt[1] == '2' &&
1791+ salt[2] == 'a' &&
1792+ salt[3] == '$' &&
1793+ salt[4] >= '0' && salt[4] <= '3' &&
1794+ salt[5] >= '0' && salt[5] <= '9' &&
1795+ salt[6] == '$') {
1796+
1797+ char output[PHP_MAX_SALT_LEN+1];
1798+
1799+ output[0] = 0;
1800+ _crypt_blowfish_rn(str, salt, output, sizeof(output));
1801+ RETVAL_STRING(output, 1);
1802+
1803+ } else {
1804+ RETVAL_STRING(crypt(str, salt), 1);
1805+ }
1806 }
1807 /* }}} */
1808 #endif
1809diff -Nura php-4.4.0/ext/standard/dl.c hardening-patch-4.4.0-0.4.3/ext/standard/dl.c
1810--- php-4.4.0/ext/standard/dl.c 2003-01-29 16:40:24.000000000 +0100
1811+++ hardening-patch-4.4.0-0.4.3/ext/standard/dl.c 2005-09-11 23:31:08.000000000 +0200
1812@@ -182,8 +182,35 @@
1813 RETURN_FALSE;
1814 }
1815 module_entry = get_module();
1816+
1817+ /* check if Hardening-Patch is installed */
1818+ if (module_entry->zend_api < 1000000000) {
1819+ php_error_docref(NULL TSRMLS_CC, error_type,
1820+ "%s: Unable to initialize module\n"
1821+ "Module compiled without Hardening-Patch, module API=%d, debug=%d, thread-safety=%d\n"
1822+ "PHP compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
1823+ "These options need to match\n",
1824+ module_entry->name, module_entry->zend_api, module_entry->zend_debug, module_entry->zts,
1825+ HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS);
1826+ DL_UNLOAD(handle);
1827+ RETURN_FALSE;
1828+ }
1829+
1830+ /* check if correct Hardening-Patch is installed */
1831+ if (module_entry->zend_api != HARDENING_PATCH_ZEND_MODULE_API_NO) {
1832+ php_error_docref(NULL TSRMLS_CC, error_type,
1833+ "%s: Unable to initialize module\n"
1834+ "Module compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
1835+ "PHP compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
1836+ "These options need to match\n",
1837+ module_entry->name, module_entry->zend_api, module_entry->real_zend_api, module_entry->zend_debug, module_entry->zts,
1838+ HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS);
1839+ DL_UNLOAD(handle);
1840+ RETURN_FALSE;
1841+ }
1842+
1843 if ((module_entry->zend_debug != ZEND_DEBUG) || (module_entry->zts != USING_ZTS)
1844- || (module_entry->zend_api != ZEND_MODULE_API_NO)) {
1845+ || (module_entry->real_zend_api != ZEND_MODULE_API_NO)) {
1846 /* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */
1847 struct pre_4_1_0_module_entry {
1848 char *name;
1849@@ -217,7 +244,7 @@
1850 zts = ((struct pre_4_1_0_module_entry *)module_entry)->zts;
1851 } else {
1852 name = module_entry->name;
1853- zend_api = module_entry->zend_api;
1854+ zend_api = module_entry->real_zend_api;
1855 zend_debug = module_entry->zend_debug;
1856 zts = module_entry->zts;
1857 }
1858diff -Nura php-4.4.0/ext/standard/file.c hardening-patch-4.4.0-0.4.3/ext/standard/file.c
1859--- php-4.4.0/ext/standard/file.c 2005-03-27 17:53:59.000000000 +0200
1860+++ hardening-patch-4.4.0-0.4.3/ext/standard/file.c 2005-09-11 23:31:08.000000000 +0200
1861@@ -2469,7 +2469,7 @@
1862 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
1863 /* {{{ proto string realpath(string path)
1864 Return the resolved path */
1865-PHP_FUNCTION(realpath)
1866+PHP_FUNCTION(real_path)
1867 {
1868 zval **path;
1869 char resolved_path_buff[MAXPATHLEN];
1870diff -Nura php-4.4.0/ext/standard/file.h hardening-patch-4.4.0-0.4.3/ext/standard/file.h
1871--- php-4.4.0/ext/standard/file.h 2004-06-21 21:33:47.000000000 +0200
1872+++ hardening-patch-4.4.0-0.4.3/ext/standard/file.h 2005-09-11 23:31:08.000000000 +0200
1873@@ -64,7 +64,7 @@
1874 PHP_FUNCTION(fd_set);
1875 PHP_FUNCTION(fd_isset);
1876 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
1877-PHP_FUNCTION(realpath);
1878+PHP_FUNCTION(real_path);
1879 #endif
1880 #ifdef HAVE_FNMATCH
1881 PHP_FUNCTION(fnmatch);
1882diff -Nura php-4.4.0/ext/standard/head.c hardening-patch-4.4.0-0.4.3/ext/standard/head.c
1883--- php-4.4.0/ext/standard/head.c 2005-01-07 22:14:23.000000000 +0100
1884+++ hardening-patch-4.4.0-0.4.3/ext/standard/head.c 2005-09-11 23:31:08.000000000 +0200
1885@@ -45,10 +45,31 @@
1886 {
1887 zend_bool rep = 1;
1888 sapi_header_line ctr = {0};
1889+#if HARDENING_PATCH
1890+ int i;
1891+#endif
1892
1893 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
1894 &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
1895 return;
1896+
1897+#if HARDENING_PATCH
1898+ if (!HG(hphp_multiheader)) {
1899+ for (i=0; i<ctr.line_len; i++) {
1900+ if (ctr.line[i]==0) {
1901+ php_security_log(S_MISC, "header(): headerline truncated by an ASCII-NUL char");
1902+ ctr.line_len=i;
1903+ break;
1904+ } else if (ctr.line[i]=='\n') {
1905+ if (i>0 && (i<ctr.line_len-1) && (ctr.line[i+1]==' ' || ctr.line[i+1]=='\t')) {
1906+ continue;
1907+ }
1908+ php_security_log(S_MISC, "header(): headerline contains more than one header");
1909+ ctr.line_len=i;
1910+ }
1911+ }
1912+ }
1913+#endif
1914
1915 sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
1916 }
1917diff -Nura php-4.4.0/ext/standard/info.c hardening-patch-4.4.0-0.4.3/ext/standard/info.c
1918--- php-4.4.0/ext/standard/info.c 2005-06-07 15:37:33.000000000 +0200
1919+++ hardening-patch-4.4.0-0.4.3/ext/standard/info.c 2005-09-11 23:31:08.000000000 +0200
1920@@ -397,7 +397,7 @@
1921
1922 if (flag & PHP_INFO_GENERAL) {
1923 char *zend_version = get_zend_version();
1924- char temp_api[9];
1925+ char temp_api[11];
1926
1927 php_uname = php_get_uname('a');
1928
1929@@ -419,11 +419,22 @@
1930 }
1931 }
1932
1933+#if HARDENING_PATCH
1934+ if (!sapi_module.phpinfo_as_text) {
1935+ php_printf("<h1 class=\"p\">PHP Version %s with Hardening-Patch %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
1936+ } else {
1937+ char temp_ver[40];
1938+
1939+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
1940+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
1941+ }
1942+#else
1943 if (!sapi_module.phpinfo_as_text) {
1944 php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
1945 } else {
1946 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1947 }
1948+#endif
1949 php_info_print_box_end();
1950 php_info_print_table_start();
1951 php_info_print_table_row(2, "System", php_uname );
1952diff -Nura php-4.4.0/ext/standard/php_standard.h hardening-patch-4.4.0-0.4.3/ext/standard/php_standard.h
1953--- php-4.4.0/ext/standard/php_standard.h 2002-12-31 17:35:33.000000000 +0100
1954+++ hardening-patch-4.4.0-0.4.3/ext/standard/php_standard.h 2005-09-11 23:31:08.000000000 +0200
1955@@ -28,6 +28,7 @@
1956 #include "php_mail.h"
1957 #include "md5.h"
1958 #include "sha1.h"
1959+#include "sha256.h"
1960 #include "html.h"
1961 #include "exec.h"
1962 #include "file.h"
1963diff -Nura php-4.4.0/ext/standard/sha256.c hardening-patch-4.4.0-0.4.3/ext/standard/sha256.c
1964--- php-4.4.0/ext/standard/sha256.c 1970-01-01 01:00:00.000000000 +0100
1965+++ hardening-patch-4.4.0-0.4.3/ext/standard/sha256.c 2005-09-11 23:31:08.000000000 +0200
1966@@ -0,0 +1,398 @@
1967+/*
1968+ +----------------------------------------------------------------------+
1969+ | PHP Version 5 |
1970+ +----------------------------------------------------------------------+
1971+ | Copyright (c) 1997-2004 The PHP Group |
1972+ +----------------------------------------------------------------------+
1973+ | This source file is subject to version 3.0 of the PHP license, |
1974+ | that is bundled with this package in the file LICENSE, and is |
1975+ | available through the world-wide-web at the following url: |
1976+ | http://www.php.net/license/3_0.txt. |
1977+ | If you did not receive a copy of the PHP license and are unable to |
1978+ | obtain it through the world-wide-web, please send a note to |
1979+ | license@php.net so we can mail you a copy immediately. |
1980+ +----------------------------------------------------------------------+
1981+ | Author: Stefan Esser <sesser@php.net> |
1982+ +----------------------------------------------------------------------+
1983+*/
1984+
1985+/* $Id: sha256.c,v 1.9 2004/01/08 08:17:34 andi Exp $ */
1986+
1987+#include <stdio.h>
1988+#include "php.h"
1989+
1990+/* This code is heavily based on the PHP md5/sha1 implementations */
1991+
1992+#include "sha256.h"
1993+
1994+PHPAPI void make_sha256_digest(char *sha256str, unsigned char *digest)
1995+{
1996+ int i;
1997+
1998+ for (i = 0; i < 32; i++) {
1999+ sprintf(sha256str, "%02x", digest[i]);
2000+ sha256str += 2;
2001+ }
2002+
2003+ *sha256str = '\0';
2004+}
2005+
2006+/* {{{ proto string sha256(string str [, bool raw_output])
2007+ Calculate the sha256 hash of a string */
2008+PHP_FUNCTION(sha256)
2009+{
2010+ char *arg;
2011+ int arg_len;
2012+ zend_bool raw_output = 0;
2013+ char sha256str[65];
2014+ PHP_SHA256_CTX context;
2015+ unsigned char digest[32];
2016+
2017+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
2018+ return;
2019+ }
2020+
2021+ sha256str[0] = '\0';
2022+ PHP_SHA256Init(&context);
2023+ PHP_SHA256Update(&context, arg, arg_len);
2024+ PHP_SHA256Final(digest, &context);
2025+ if (raw_output) {
2026+ RETURN_STRINGL(digest, 32, 1);
2027+ } else {
2028+ make_sha256_digest(sha256str, digest);
2029+ RETVAL_STRING(sha256str, 1);
2030+ }
2031+
2032+}
2033+
2034+/* }}} */
2035+
2036+/* {{{ proto string sha256_file(string filename [, bool raw_output])
2037+ Calculate the sha256 hash of given filename */
2038+PHP_FUNCTION(sha256_file)
2039+{
2040+ char *arg;
2041+ int arg_len;
2042+ zend_bool raw_output = 0;
2043+ char sha256str[65];
2044+ unsigned char buf[1024];
2045+ unsigned char digest[32];
2046+ PHP_SHA256_CTX context;
2047+ int n;
2048+ FILE *fp;
2049+
2050+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
2051+ return;
2052+ }
2053+
2054+ if (PG(safe_mode) && (!php_checkuid(arg, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
2055+ RETURN_FALSE;
2056+ }
2057+
2058+ if (php_check_open_basedir(arg TSRMLS_CC)) {
2059+ RETURN_FALSE;
2060+ }
2061+
2062+ if ((fp = VCWD_FOPEN(arg, "rb")) == NULL) {
2063+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open file");
2064+ RETURN_FALSE;
2065+ }
2066+
2067+ PHP_SHA256Init(&context);
2068+
2069+ while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
2070+ PHP_SHA256Update(&context, buf, n);
2071+ }
2072+
2073+ PHP_SHA256Final(digest, &context);
2074+
2075+ if (ferror(fp)) {
2076+ fclose(fp);
2077+ RETURN_FALSE;
2078+ }
2079+
2080+ fclose(fp);
2081+
2082+ if (raw_output) {
2083+ RETURN_STRINGL(digest, 32, 1);
2084+ } else {
2085+ make_sha256_digest(sha256str, digest);
2086+ RETVAL_STRING(sha256str, 1);
2087+ }
2088+}
2089+/* }}} */
2090+
2091+
2092+static void SHA256Transform(php_uint32[8], const unsigned char[64]);
2093+static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
2094+static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
2095+
2096+static unsigned char PADDING[64] =
2097+{
2098+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2099+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2100+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2101+};
2102+
2103+/* F, G, H and I are basic SHA256 functions.
2104+ */
2105+#define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22))
2106+#define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x))))
2107+#define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25))
2108+#define I(x, y, z) (((x) & (y)) | ((~x) & z))
2109+
2110+/* ROTATE_RIGHT rotates x right n bits.
2111+ */
2112+#define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
2113+
2114+/* W[i]
2115+ */
2116+#define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \
2117+ tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \
2118+ (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) )
2119+
2120+/* ROUND function of sha256
2121+ */
2122+
2123+#define ROUND(a,b,c,d,e,f,g,h,w,k) { \
2124+ t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \
2125+ (h) = F((a)) + G((a), (b), (c)) + t1; \
2126+ (d) += t1; \
2127+ }
2128+
2129+
2130+/* {{{ PHP_SHA256Init
2131+ * SHA256 initialization. Begins an SHA256 operation, writing a new context.
2132+ */
2133+PHPAPI void PHP_SHA256Init(PHP_SHA256_CTX * context)
2134+{
2135+ context->count[0] = context->count[1] = 0;
2136+ /* Load magic initialization constants.
2137+ */
2138+ context->state[0] = 0x6a09e667;
2139+ context->state[1] = 0xbb67ae85;
2140+ context->state[2] = 0x3c6ef372;
2141+ context->state[3] = 0xa54ff53a;
2142+ context->state[4] = 0x510e527f;
2143+ context->state[5] = 0x9b05688c;
2144+ context->state[6] = 0x1f83d9ab;
2145+ context->state[7] = 0x5be0cd19;
2146+}
2147+/* }}} */
2148+
2149+/* {{{ PHP_SHA256Update
2150+ SHA256 block update operation. Continues an SHA256 message-digest
2151+ operation, processing another message block, and updating the
2152+ context.
2153+ */
2154+PHPAPI void PHP_SHA256Update(PHP_SHA256_CTX * context, const unsigned char *input,
2155+ unsigned int inputLen)
2156+{
2157+ unsigned int i, index, partLen;
2158+
2159+ /* Compute number of bytes mod 64 */
2160+ index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
2161+
2162+ /* Update number of bits */
2163+ if ((context->count[0] += ((php_uint32) inputLen << 3))
2164+ < ((php_uint32) inputLen << 3))
2165+ context->count[1]++;
2166+ context->count[1] += ((php_uint32) inputLen >> 29);
2167+
2168+ partLen = 64 - index;
2169+
2170+ /* Transform as many times as possible.
2171+ */
2172+ if (inputLen >= partLen) {
2173+ memcpy
2174+ ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
2175+ SHA256Transform(context->state, context->buffer);
2176+
2177+ for (i = partLen; i + 63 < inputLen; i += 64)
2178+ SHA256Transform(context->state, &input[i]);
2179+
2180+ index = 0;
2181+ } else
2182+ i = 0;
2183+
2184+ /* Buffer remaining input */
2185+ memcpy
2186+ ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
2187+ inputLen - i);
2188+}
2189+/* }}} */
2190+
2191+/* {{{ PHP_SHA256Final
2192+ SHA256 finalization. Ends an SHA256 message-digest operation, writing the
2193+ the message digest and zeroizing the context.
2194+ */
2195+PHPAPI void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * context)
2196+{
2197+ unsigned char bits[8];
2198+ unsigned int index, padLen;
2199+
2200+ /* Save number of bits */
2201+ bits[7] = context->count[0] & 0xFF;
2202+ bits[6] = (context->count[0] >> 8) & 0xFF;
2203+ bits[5] = (context->count[0] >> 16) & 0xFF;
2204+ bits[4] = (context->count[0] >> 24) & 0xFF;
2205+ bits[3] = context->count[1] & 0xFF;
2206+ bits[2] = (context->count[1] >> 8) & 0xFF;
2207+ bits[1] = (context->count[1] >> 16) & 0xFF;
2208+ bits[0] = (context->count[1] >> 24) & 0xFF;
2209+
2210+ /* Pad out to 56 mod 64.
2211+ */
2212+ index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
2213+ padLen = (index < 56) ? (56 - index) : (120 - index);
2214+ PHP_SHA256Update(context, PADDING, padLen);
2215+
2216+ /* Append length (before padding) */
2217+ PHP_SHA256Update(context, bits, 8);
2218+
2219+ /* Store state in digest */
2220+ SHA256Encode(digest, context->state, 32);
2221+
2222+ /* Zeroize sensitive information.
2223+ */
2224+ memset((unsigned char*) context, 0, sizeof(*context));
2225+}
2226+/* }}} */
2227+
2228+/* {{{ SHA256Transform
2229+ * SHA256 basic transformation. Transforms state based on block.
2230+ */
2231+static void SHA256Transform(state, block)
2232+php_uint32 state[8];
2233+const unsigned char block[64];
2234+{
2235+ php_uint32 a = state[0], b = state[1], c = state[2];
2236+ php_uint32 d = state[3], e = state[4], f = state[5];
2237+ php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1;
2238+
2239+ SHA256Decode(x, block, 64);
2240+
2241+ ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98)
2242+ ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491)
2243+ ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf)
2244+ ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5)
2245+ ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b)
2246+ ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1)
2247+ ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4)
2248+ ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5)
2249+ ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98)
2250+ ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01)
2251+ ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be)
2252+ ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3)
2253+ ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74)
2254+ ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe)
2255+ ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7)
2256+ ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174)
2257+ ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1)
2258+ ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786)
2259+ ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6)
2260+ ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc)
2261+ ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f)
2262+ ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa)
2263+ ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc)
2264+ ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da)
2265+ ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152)
2266+ ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d)
2267+ ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8)
2268+ ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7)
2269+ ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3)
2270+ ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147)
2271+ ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351)
2272+ ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967)
2273+ ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85)
2274+ ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138)
2275+ ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc)
2276+ ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13)
2277+ ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354)
2278+ ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb)
2279+ ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e)
2280+ ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85)
2281+ ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1)
2282+ ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b)
2283+ ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70)
2284+ ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3)
2285+ ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819)
2286+ ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624)
2287+ ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585)
2288+ ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070)
2289+ ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116)
2290+ ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08)
2291+ ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c)
2292+ ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5)
2293+ ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3)
2294+ ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a)
2295+ ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f)
2296+ ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3)
2297+ ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee)
2298+ ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f)
2299+ ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814)
2300+ ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208)
2301+ ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa)
2302+ ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb)
2303+ ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7)
2304+ ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2)
2305+
2306+ state[0] += a;
2307+ state[1] += b;
2308+ state[2] += c;
2309+ state[3] += d;
2310+ state[4] += e;
2311+ state[5] += f;
2312+ state[6] += g;
2313+ state[7] += h;
2314+
2315+ /* Zeroize sensitive information. */
2316+ memset((unsigned char*) x, 0, sizeof(x));
2317+}
2318+/* }}} */
2319+
2320+/* {{{ SHA256Encode
2321+ Encodes input (php_uint32) into output (unsigned char). Assumes len is
2322+ a multiple of 4.
2323+ */
2324+static void SHA256Encode(output, input, len)
2325+unsigned char *output;
2326+php_uint32 *input;
2327+unsigned int len;
2328+{
2329+ unsigned int i, j;
2330+
2331+ for (i = 0, j = 0; j < len; i++, j += 4) {
2332+ output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
2333+ output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
2334+ output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
2335+ output[j + 3] = (unsigned char) (input[i] & 0xff);
2336+ }
2337+}
2338+/* }}} */
2339+
2340+/* {{{ SHA256Decode
2341+ Decodes input (unsigned char) into output (php_uint32). Assumes len is
2342+ a multiple of 4.
2343+ */
2344+static void SHA256Decode(output, input, len)
2345+php_uint32 *output;
2346+const unsigned char *input;
2347+unsigned int len;
2348+{
2349+ unsigned int i, j;
2350+
2351+ for (i = 0, j = 0; j < len; i++, j += 4)
2352+ output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
2353+ (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
2354+}
2355+/* }}} */
2356+
2357+/*
2358+ * Local variables:
2359+ * tab-width: 4
2360+ * c-basic-offset: 4
2361+ * End:
2362+ * vim600: sw=4 ts=4 fdm=marker
2363+ * vim<600: sw=4 ts=4
2364+ */
2365diff -Nura php-4.4.0/ext/standard/sha256.h hardening-patch-4.4.0-0.4.3/ext/standard/sha256.h
2366--- php-4.4.0/ext/standard/sha256.h 1970-01-01 01:00:00.000000000 +0100
2367+++ hardening-patch-4.4.0-0.4.3/ext/standard/sha256.h 2005-09-11 23:31:08.000000000 +0200
2368@@ -0,0 +1,40 @@
2369+/*
2370+ +----------------------------------------------------------------------+
2371+ | PHP Version 5 |
2372+ +----------------------------------------------------------------------+
2373+ | Copyright (c) 1997-2004 The PHP Group |
2374+ +----------------------------------------------------------------------+
2375+ | This source file is subject to version 3.0 of the PHP license, |
2376+ | that is bundled with this package in the file LICENSE, and is |
2377+ | available through the world-wide-web at the following url: |
2378+ | http://www.php.net/license/3_0.txt. |
2379+ | If you did not receive a copy of the PHP license and are unable to |
2380+ | obtain it through the world-wide-web, please send a note to |
2381+ | license@php.net so we can mail you a copy immediately. |
2382+ +----------------------------------------------------------------------+
2383+ | Author: Stefan Esser <sesser@php.net> |
2384+ +----------------------------------------------------------------------+
2385+*/
2386+
2387+/* $Id: sha256.h,v 1.4 2004/01/08 17:32:52 sniper Exp $ */
2388+
2389+#ifndef SHA256_H
2390+#define SHA256_H
2391+
2392+#include "ext/standard/basic_functions.h"
2393+
2394+/* SHA1 context. */
2395+typedef struct {
2396+ php_uint32 state[8]; /* state (ABCD) */
2397+ php_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */
2398+ unsigned char buffer[64]; /* input buffer */
2399+} PHP_SHA256_CTX;
2400+
2401+PHPAPI void PHP_SHA256Init(PHP_SHA256_CTX *);
2402+PHPAPI void PHP_SHA256Update(PHP_SHA256_CTX *, const unsigned char *, unsigned int);
2403+PHPAPI void PHP_SHA256Final(unsigned char[32], PHP_SHA256_CTX *);
2404+
2405+PHP_FUNCTION(sha256);
2406+PHP_FUNCTION(sha256_file);
2407+
2408+#endif
2409diff -Nura php-4.4.0/ext/standard/syslog.c hardening-patch-4.4.0-0.4.3/ext/standard/syslog.c
2410--- php-4.4.0/ext/standard/syslog.c 2004-07-30 16:38:29.000000000 +0200
2411+++ hardening-patch-4.4.0-0.4.3/ext/standard/syslog.c 2005-09-11 23:31:08.000000000 +0200
2412@@ -42,6 +42,8 @@
2413 */
2414 PHP_MINIT_FUNCTION(syslog)
2415 {
2416+
2417+#if !HARDENING_PATCH
2418 /* error levels */
2419 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
2420 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
2421@@ -97,7 +99,7 @@
2422 /* AIX doesn't have LOG_PERROR */
2423 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
2424 #endif
2425-
2426+#endif
2427 return SUCCESS;
2428 }
2429 /* }}} */
2430diff -Nura php-4.4.0/ext/varfilter/config.m4 hardening-patch-4.4.0-0.4.3/ext/varfilter/config.m4
2431--- php-4.4.0/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
2432+++ hardening-patch-4.4.0-0.4.3/ext/varfilter/config.m4 2005-09-11 23:31:08.000000000 +0200
2433@@ -0,0 +1,11 @@
2434+dnl
2435+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
2436+dnl
2437+
2438+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
2439+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
2440+
2441+if test "$PHP_VARFILTER" != "no"; then
2442+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
2443+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
2444+fi
2445diff -Nura php-4.4.0/ext/varfilter/CREDITS hardening-patch-4.4.0-0.4.3/ext/varfilter/CREDITS
2446--- php-4.4.0/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
2447+++ hardening-patch-4.4.0-0.4.3/ext/varfilter/CREDITS 2005-09-11 23:31:08.000000000 +0200
2448@@ -0,0 +1,2 @@
2449+varfilter
2450+Stefan Esser
2451\ Kein Zeilenumbruch am Dateiende.
2452diff -Nura php-4.4.0/ext/varfilter/php_varfilter.h hardening-patch-4.4.0-0.4.3/ext/varfilter/php_varfilter.h
2453--- php-4.4.0/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
2454+++ hardening-patch-4.4.0-0.4.3/ext/varfilter/php_varfilter.h 2005-09-12 18:15:08.000000000 +0200
2455@@ -0,0 +1,112 @@
2456+/*
2457+ +----------------------------------------------------------------------+
2458+ | Hardened-PHP Project's varfilter extension |
2459+ +----------------------------------------------------------------------+
2460+ | Copyright (c) 2004-2005 Stefan Esser |
2461+ +----------------------------------------------------------------------+
2462+ | This source file is subject to version 2.02 of the PHP license, |
2463+ | that is bundled with this package in the file LICENSE, and is |
2464+ | available at through the world-wide-web at |
2465+ | http://www.php.net/license/2_02.txt. |
2466+ | If you did not receive a copy of the PHP license and are unable to |
2467+ | obtain it through the world-wide-web, please send a note to |
2468+ | license@php.net so we can mail you a copy immediately. |
2469+ +----------------------------------------------------------------------+
2470+ | Author: Stefan Esser <sesser@hardened-php.net> |
2471+ +----------------------------------------------------------------------+
2472+
2473+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
2474+*/
2475+
2476+#ifndef PHP_VARFILTER_H
2477+#define PHP_VARFILTER_H
2478+
2479+extern zend_module_entry varfilter_module_entry;
2480+#define phpext_varfilter_ptr &varfilter_module_entry
2481+
2482+#ifdef PHP_WIN32
2483+#define PHP_VARFILTER_API __declspec(dllexport)
2484+#else
2485+#define PHP_VARFILTER_API
2486+#endif
2487+
2488+#ifdef ZTS
2489+#include "TSRM.h"
2490+#endif
2491+
2492+#include "SAPI.h"
2493+
2494+#include "php_variables.h"
2495+
2496+
2497+PHP_MINIT_FUNCTION(varfilter);
2498+PHP_MSHUTDOWN_FUNCTION(varfilter);
2499+PHP_RINIT_FUNCTION(varfilter);
2500+PHP_RSHUTDOWN_FUNCTION(varfilter);
2501+PHP_MINFO_FUNCTION(varfilter);
2502+
2503+
2504+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
2505+/* request variables */
2506+ long max_request_variables;
2507+ long cur_request_variables;
2508+ long max_varname_length;
2509+ long max_totalname_length;
2510+ long max_value_length;
2511+ long max_array_depth;
2512+ long max_array_index_length;
2513+/* cookie variables */
2514+ long max_cookie_vars;
2515+ long cur_cookie_vars;
2516+ long max_cookie_name_length;
2517+ long max_cookie_totalname_length;
2518+ long max_cookie_value_length;
2519+ long max_cookie_array_depth;
2520+ long max_cookie_array_index_length;
2521+/* get variables */
2522+ long max_get_vars;
2523+ long cur_get_vars;
2524+ long max_get_name_length;
2525+ long max_get_totalname_length;
2526+ long max_get_value_length;
2527+ long max_get_array_depth;
2528+ long max_get_array_index_length;
2529+/* post variables */
2530+ long max_post_vars;
2531+ long cur_post_vars;
2532+ long max_post_name_length;
2533+ long max_post_totalname_length;
2534+ long max_post_value_length;
2535+ long max_post_array_depth;
2536+ long max_post_array_index_length;
2537+/* fileupload */
2538+ long max_uploads;
2539+ long cur_uploads;
2540+ zend_bool disallow_elf_files;
2541+ char *verification_script;
2542+
2543+ZEND_END_MODULE_GLOBALS(varfilter)
2544+
2545+
2546+#ifdef ZTS
2547+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
2548+#else
2549+#define VARFILTER_G(v) (varfilter_globals.v)
2550+#endif
2551+
2552+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
2553+SAPI_UPLOAD_VARNAME_FILTER_FUNC(varfilter_upload_varname_filter);
2554+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
2555+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
2556+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
2557+
2558+#endif /* PHP_VARFILTER_H */
2559+
2560+
2561+/*
2562+ * Local variables:
2563+ * tab-width: 4
2564+ * c-basic-offset: 4
2565+ * indent-tabs-mode: t
2566+ * End:
2567+ */
2568diff -Nura php-4.4.0/ext/varfilter/varfilter.c hardening-patch-4.4.0-0.4.3/ext/varfilter/varfilter.c
2569--- php-4.4.0/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
2570+++ hardening-patch-4.4.0-0.4.3/ext/varfilter/varfilter.c 2005-09-12 18:15:08.000000000 +0200
2571@@ -0,0 +1,726 @@
2572+/*
2573+ +----------------------------------------------------------------------+
2574+ | Hardened-PHP Project's varfilter extension |
2575+ +----------------------------------------------------------------------+
2576+ | Copyright (c) 2004-2005 Stefan Esser |
2577+ +----------------------------------------------------------------------+
2578+ | This source file is subject to version 2.02 of the PHP license, |
2579+ | that is bundled with this package in the file LICENSE, and is |
2580+ | available at through the world-wide-web at |
2581+ | http://www.php.net/license/2_02.txt. |
2582+ | If you did not receive a copy of the PHP license and are unable to |
2583+ | obtain it through the world-wide-web, please send a note to |
2584+ | license@php.net so we can mail you a copy immediately. |
2585+ +----------------------------------------------------------------------+
2586+ | Author: Stefan Esser <sesser@hardened-php.net> |
2587+ +----------------------------------------------------------------------+
2588+
2589+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
2590+*/
2591+
2592+#ifdef HAVE_CONFIG_H
2593+#include "config.h"
2594+#endif
2595+
2596+#include "php.h"
2597+#include "php_ini.h"
2598+#include "ext/standard/info.h"
2599+#include "php_varfilter.h"
2600+#include "hardening_patch.h"
2601+
2602+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
2603+
2604+/* True global resources - no need for thread safety here */
2605+static int le_varfilter;
2606+
2607+/* {{{ varfilter_module_entry
2608+ */
2609+zend_module_entry varfilter_module_entry = {
2610+#if ZEND_MODULE_API_NO >= 20010901
2611+ STANDARD_MODULE_HEADER,
2612+#endif
2613+ "varfilter",
2614+ NULL,
2615+ PHP_MINIT(varfilter),
2616+ PHP_MSHUTDOWN(varfilter),
2617+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
2618+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
2619+ PHP_MINFO(varfilter),
2620+#if ZEND_MODULE_API_NO >= 20010901
2621+ "0.3.2", /* Replace with version number for your extension */
2622+#endif
2623+ STANDARD_MODULE_PROPERTIES
2624+};
2625+/* }}} */
2626+
2627+#ifdef COMPILE_DL_VARFILTER
2628+ZEND_GET_MODULE(varfilter)
2629+#endif
2630+
2631+/* {{{ PHP_INI
2632+ */
2633+PHP_INI_BEGIN()
2634+ /* for backward compatibility */
2635+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
2636+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
2637+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
2638+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
2639+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
2640+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
2641+
2642+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
2643+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
2644+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
2645+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
2646+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
2647+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
2648+
2649+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
2650+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
2651+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
2652+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
2653+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
2654+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
2655+
2656+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
2657+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
2658+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
2659+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
2660+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
2661+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
2662+
2663+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
2664+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
2665+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
2666+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
2667+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
2668+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
2669+
2670+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
2671+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
2672+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
2673+
2674+
2675+PHP_INI_END()
2676+/* }}} */
2677+
2678+/* {{{ php_varfilter_init_globals
2679+ */
2680+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
2681+{
2682+ varfilter_globals->max_request_variables = 200;
2683+ varfilter_globals->max_varname_length = 64;
2684+ varfilter_globals->max_value_length = 10000;
2685+ varfilter_globals->max_array_depth = 100;
2686+ varfilter_globals->max_totalname_length = 256;
2687+ varfilter_globals->max_array_index_length = 64;
2688+
2689+ varfilter_globals->max_cookie_vars = 100;
2690+ varfilter_globals->max_cookie_name_length = 64;
2691+ varfilter_globals->max_cookie_totalname_length = 256;
2692+ varfilter_globals->max_cookie_value_length = 10000;
2693+ varfilter_globals->max_cookie_array_depth = 100;
2694+ varfilter_globals->max_cookie_array_index_length = 64;
2695+
2696+ varfilter_globals->max_get_vars = 100;
2697+ varfilter_globals->max_get_name_length = 64;
2698+ varfilter_globals->max_get_totalname_length = 256;
2699+ varfilter_globals->max_get_value_length = 512;
2700+ varfilter_globals->max_get_array_depth = 50;
2701+ varfilter_globals->max_get_array_index_length = 64;
2702+
2703+ varfilter_globals->max_post_vars = 200;
2704+ varfilter_globals->max_post_name_length = 64;
2705+ varfilter_globals->max_post_totalname_length = 256;
2706+ varfilter_globals->max_post_value_length = 65000;
2707+ varfilter_globals->max_post_array_depth = 100;
2708+ varfilter_globals->max_post_array_index_length = 64;
2709+
2710+ varfilter_globals->max_uploads = 25;
2711+ varfilter_globals->disallow_elf_files = 1;
2712+ varfilter_globals->verification_script = NULL;
2713+}
2714+/* }}} */
2715+
2716+/* {{{ PHP_MINIT_FUNCTION
2717+ */
2718+PHP_MINIT_FUNCTION(varfilter)
2719+{
2720+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
2721+ REGISTER_INI_ENTRIES();
2722+
2723+ sapi_register_input_filter(varfilter_input_filter);
2724+ sapi_register_upload_varname_filter(varfilter_upload_varname_filter);
2725+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
2726+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
2727+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
2728+
2729+ return SUCCESS;
2730+}
2731+/* }}} */
2732+
2733+/* {{{ PHP_MSHUTDOWN_FUNCTION
2734+ */
2735+PHP_MSHUTDOWN_FUNCTION(varfilter)
2736+{
2737+ UNREGISTER_INI_ENTRIES();
2738+
2739+ return SUCCESS;
2740+}
2741+/* }}} */
2742+
2743+/* Remove if there's nothing to do at request start */
2744+/* {{{ PHP_RINIT_FUNCTION
2745+ */
2746+PHP_RINIT_FUNCTION(varfilter)
2747+{
2748+ VARFILTER_G(cur_request_variables) = 0;
2749+ VARFILTER_G(cur_get_vars) = 0;
2750+ VARFILTER_G(cur_post_vars) = 0;
2751+ VARFILTER_G(cur_cookie_vars) = 0;
2752+
2753+ VARFILTER_G(cur_uploads) = 0;
2754+
2755+ return SUCCESS;
2756+}
2757+/* }}} */
2758+
2759+/* Remove if there's nothing to do at request end */
2760+/* {{{ PHP_RSHUTDOWN_FUNCTION
2761+ */
2762+PHP_RSHUTDOWN_FUNCTION(varfilter)
2763+{
2764+ return SUCCESS;
2765+}
2766+/* }}} */
2767+
2768+/* {{{ PHP_MINFO_FUNCTION
2769+ */
2770+PHP_MINFO_FUNCTION(varfilter)
2771+{
2772+ php_info_print_table_start();
2773+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
2774+ php_info_print_table_end();
2775+
2776+ DISPLAY_INI_ENTRIES();
2777+}
2778+/* }}} */
2779+
2780+/* {{{ normalize_varname
2781+ */
2782+static void normalize_varname(char *varname)
2783+{
2784+ char *s=varname, *index=NULL, *indexend=NULL, *p;
2785+
2786+ /* overjump leading space */
2787+ while (*s == ' ') {
2788+ s++;
2789+ }
2790+
2791+ /* and remove it */
2792+ if (s != varname) {
2793+ memmove(varname, s, strlen(s)+1);
2794+ }
2795+
2796+ for (p=varname; *p && *p != '['; p++) {
2797+ switch(*p) {
2798+ case ' ':
2799+ case '.':
2800+ *p='_';
2801+ break;
2802+ }
2803+ }
2804+
2805+ /* find index */
2806+ index = strchr(varname, '[');
2807+ if (index) {
2808+ index++;
2809+ s=index;
2810+ } else {
2811+ return;
2812+ }
2813+
2814+ /* done? */
2815+ while (index) {
2816+
2817+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
2818+ index++;
2819+ }
2820+ indexend = strchr(index, ']');
2821+ indexend = indexend ? indexend + 1 : index + strlen(index);
2822+
2823+ if (s != index) {
2824+ memmove(s, index, strlen(index)+1);
2825+ s += indexend-index;
2826+ } else {
2827+ s = indexend;
2828+ }
2829+
2830+ if (*s == '[') {
2831+ s++;
2832+ index = s;
2833+ } else {
2834+ index = NULL;
2835+ }
2836+ }
2837+ *s++='\0';
2838+}
2839+/* }}} */
2840+
2841+/* {{{ SAPI_UPLOAD_VARNAME_FILTER_FUNC
2842+ */
2843+SAPI_UPLOAD_VARNAME_FILTER_FUNC(varfilter_upload_varname_filter)
2844+{
2845+ char *index, *prev_index = NULL, *var;
2846+ unsigned int var_len, total_len, depth = 0;
2847+
2848+ var = estrdup(varname);
2849+
2850+ /* Normalize the variable name */
2851+ normalize_varname(var);
2852+
2853+ /* Find length of variable name */
2854+ index = strchr(var, '[');
2855+ total_len = strlen(var);
2856+ var_len = index ? index-var : total_len;
2857+
2858+ /* Drop this variable if it exceeds the varname/total length limit */
2859+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
2860+ php_security_log(S_FILES, "configured request variable name length limit exceeded - dropped %s", var);
2861+ goto return_failure;
2862+ }
2863+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
2864+ php_security_log(S_FILES, "configured request variable total name length limit exceeded - dropped %s", var);
2865+ goto return_failure;
2866+ }
2867+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
2868+ php_security_log(S_FILES, "configured POST variable name length limit exceeded - dropped %s", var);
2869+ goto return_failure;
2870+ }
2871+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
2872+ php_security_log(S_FILES, "configured POST variable total name length limit exceeded - dropped %s", var);
2873+ goto return_failure;
2874+ }
2875+
2876+ /* Find out array depth */
2877+ while (index) {
2878+ unsigned int index_length;
2879+
2880+ depth++;
2881+ index = strchr(index+1, '[');
2882+
2883+ if (prev_index) {
2884+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
2885+
2886+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
2887+ php_security_log(S_FILES, "configured request variable array index length limit exceeded - dropped %s", var);
2888+ goto return_failure;
2889+ }
2890+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
2891+ php_security_log(S_FILES, "configured POST variable array index length limit exceeded - dropped %s", var);
2892+ goto return_failure;
2893+ }
2894+ prev_index = index;
2895+ }
2896+
2897+ }
2898+
2899+ /* Drop this variable if it exceeds the array depth limit */
2900+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
2901+ php_security_log(S_FILES, "configured request variable array depth limit exceeded - dropped %s", var);
2902+ goto return_failure;
2903+ }
2904+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
2905+ php_security_log(S_FILES, "configured POST variable array depth limit exceeded - dropped %s", var);
2906+ goto return_failure;
2907+ }
2908+
2909+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
2910+ /* This is to protect several silly scripts that do globalizing themself */
2911+
2912+ switch (var_len) {
2913+ case 18:
2914+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname2;
2915+ break;
2916+ case 17:
2917+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname2;
2918+ break;
2919+ case 16:
2920+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname2;
2921+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname2;
2922+ break;
2923+ case 15:
2924+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname2;
2925+ break;
2926+ case 14:
2927+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname2;
2928+ break;
2929+ case 13:
2930+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname2;
2931+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname2;
2932+ break;
2933+ case 8:
2934+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname2;
2935+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname2;
2936+ break;
2937+ case 7:
2938+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname2;
2939+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname2;
2940+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname2;
2941+ break;
2942+ case 6:
2943+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname2;
2944+ break;
2945+ case 5:
2946+ if (memcmp(var, "_POST", 5)==0) goto protected_varname2;
2947+ break;
2948+ case 4:
2949+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname2;
2950+ if (memcmp(var, "_GET", 4)==0) goto protected_varname2;
2951+ break;
2952+ }
2953+
2954+ efree(var);
2955+ return SUCCESS;
2956+protected_varname2:
2957+ php_security_log(S_FILES, "tried to register forbidden variable '%s' through FILE variables", var);
2958+return_failure:
2959+ efree(var);
2960+ return FAILURE;
2961+}
2962+/* }}} */
2963+
2964+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
2965+ */
2966+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
2967+{
2968+ /* Drop this fileupload if the limit is reached */
2969+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
2970+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
2971+ return FAILURE;
2972+ }
2973+
2974+ return SUCCESS;
2975+}
2976+/* }}} */
2977+
2978+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
2979+ */
2980+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
2981+{
2982+
2983+ if (VARFILTER_G(disallow_elf_files)) {
2984+
2985+ if (offset == 0 && buffer_len > 10) {
2986+
2987+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
2988+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
2989+ return FAILURE;
2990+ }
2991+ }
2992+
2993+ }
2994+
2995+ return SUCCESS;
2996+}
2997+/* }}} */
2998+
2999+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
3000+ */
3001+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
3002+{
3003+ int retval = SUCCESS;
3004+
3005+ if (VARFILTER_G(verification_script)) {
3006+ char cmd[8192];
3007+ FILE *in;
3008+ int first=1;
3009+
3010+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
3011+
3012+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
3013+ php_security_log(S_FILES, "unable to execute fileupload verification script %s - file dropped", VARFILTER_G(verification_script));
3014+ return FAILURE;
3015+ }
3016+
3017+ retval = FAILURE;
3018+
3019+ /* read and forget the result */
3020+ while (1) {
3021+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
3022+ if (readbytes<=0) {
3023+ break;
3024+ }
3025+ if (first) {
3026+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
3027+ first = 0;
3028+ }
3029+ }
3030+ pclose(in);
3031+ }
3032+
3033+ if (retval != SUCCESS) {
3034+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
3035+ return FAILURE;
3036+ }
3037+
3038+ VARFILTER_G(cur_uploads)++;
3039+ return SUCCESS;
3040+}
3041+/* }}} */
3042+
3043+/* {{{ SAPI_INPUT_FILTER_FUNC
3044+ */
3045+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
3046+{
3047+ char *index, *prev_index = NULL;
3048+ unsigned int var_len, total_len, depth = 0;
3049+
3050+ /* Drop this variable if the limit is reached */
3051+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
3052+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
3053+ return 0;
3054+ }
3055+ switch (arg) {
3056+ case PARSE_GET:
3057+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
3058+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
3059+ return 0;
3060+ }
3061+ break;
3062+ case PARSE_COOKIE:
3063+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
3064+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
3065+ return 0;
3066+ }
3067+ break;
3068+ case PARSE_POST:
3069+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
3070+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
3071+ return 0;
3072+ }
3073+ break;
3074+ }
3075+
3076+
3077+ /* Drop this variable if it exceeds the value length limit */
3078+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
3079+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
3080+ return 0;
3081+ }
3082+ switch (arg) {
3083+ case PARSE_GET:
3084+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
3085+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
3086+ return 0;
3087+ }
3088+ break;
3089+ case PARSE_COOKIE:
3090+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
3091+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
3092+ return 0;
3093+ }
3094+ break;
3095+ case PARSE_POST:
3096+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
3097+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
3098+ return 0;
3099+ }
3100+ break;
3101+ }
3102+
3103+ /* Normalize the variable name */
3104+ normalize_varname(var);
3105+
3106+ /* Find length of variable name */
3107+ index = strchr(var, '[');
3108+ total_len = strlen(var);
3109+ var_len = index ? index-var : total_len;
3110+
3111+ /* Drop this variable if it exceeds the varname/total length limit */
3112+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
3113+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
3114+ return 0;
3115+ }
3116+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
3117+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
3118+ return 0;
3119+ }
3120+ switch (arg) {
3121+ case PARSE_GET:
3122+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
3123+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
3124+ return 0;
3125+ }
3126+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
3127+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
3128+ return 0;
3129+ }
3130+ break;
3131+ case PARSE_COOKIE:
3132+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
3133+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
3134+ return 0;
3135+ }
3136+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
3137+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
3138+ return 0;
3139+ }
3140+ break;
3141+ case PARSE_POST:
3142+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
3143+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
3144+ return 0;
3145+ }
3146+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
3147+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
3148+ return 0;
3149+ }
3150+ break;
3151+ }
3152+
3153+ /* Find out array depth */
3154+ while (index) {
3155+ unsigned int index_length;
3156+
3157+ depth++;
3158+ index = strchr(index+1, '[');
3159+
3160+ if (prev_index) {
3161+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
3162+
3163+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
3164+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
3165+ return 0;
3166+ }
3167+ switch (arg) {
3168+ case PARSE_GET:
3169+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
3170+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
3171+ return 0;
3172+ }
3173+ break;
3174+ case PARSE_COOKIE:
3175+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
3176+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
3177+ return 0;
3178+ }
3179+ break;
3180+ case PARSE_POST:
3181+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
3182+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
3183+ return 0;
3184+ }
3185+ break;
3186+ }
3187+ prev_index = index;
3188+ }
3189+
3190+ }
3191+
3192+ /* Drop this variable if it exceeds the array depth limit */
3193+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
3194+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
3195+ return 0;
3196+ }
3197+ switch (arg) {
3198+ case PARSE_GET:
3199+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
3200+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
3201+ return 0;
3202+ }
3203+ break;
3204+ case PARSE_COOKIE:
3205+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
3206+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
3207+ return 0;
3208+ }
3209+ break;
3210+ case PARSE_POST:
3211+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
3212+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
3213+ return 0;
3214+ }
3215+ break;
3216+ }
3217+
3218+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
3219+ /* This is to protect several silly scripts that do globalizing themself */
3220+
3221+ switch (var_len) {
3222+ case 18:
3223+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
3224+ break;
3225+ case 17:
3226+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
3227+ break;
3228+ case 16:
3229+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
3230+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
3231+ break;
3232+ case 15:
3233+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
3234+ break;
3235+ case 14:
3236+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
3237+ break;
3238+ case 13:
3239+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
3240+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
3241+ break;
3242+ case 8:
3243+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
3244+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
3245+ break;
3246+ case 7:
3247+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
3248+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
3249+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
3250+ break;
3251+ case 6:
3252+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
3253+ break;
3254+ case 5:
3255+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
3256+ break;
3257+ case 4:
3258+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
3259+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
3260+ break;
3261+ }
3262+
3263+ /* Okay let PHP register this variable */
3264+ VARFILTER_G(cur_request_variables)++;
3265+ switch (arg) {
3266+ case PARSE_GET:
3267+ VARFILTER_G(cur_get_vars)++;
3268+ break;
3269+ case PARSE_COOKIE:
3270+ VARFILTER_G(cur_cookie_vars)++;
3271+ break;
3272+ case PARSE_POST:
3273+ VARFILTER_G(cur_post_vars)++;
3274+ break;
3275+ }
3276+
3277+ if (new_val_len) {
3278+ *new_val_len = val_len;
3279+ }
3280+
3281+ return 1;
3282+protected_varname:
3283+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
3284+ return 0;
3285+}
3286+/* }}} */
3287+
3288+/*
3289+ * Local variables:
3290+ * tab-width: 4
3291+ * c-basic-offset: 4
3292+ * End:
3293+ * vim600: noet sw=4 ts=4 fdm=marker
3294+ * vim<600: noet sw=4 ts=4
3295+ */
3296+
3297+
3298diff -Nura php-4.4.0/main/fopen_wrappers.c hardening-patch-4.4.0-0.4.3/main/fopen_wrappers.c
3299--- php-4.4.0/main/fopen_wrappers.c 2005-02-03 00:44:07.000000000 +0100
3300+++ hardening-patch-4.4.0-0.4.3/main/fopen_wrappers.c 2005-09-11 23:31:08.000000000 +0200
3301@@ -166,6 +166,21 @@
3302 char *pathbuf;
3303 char *ptr;
3304 char *end;
3305+ char path_copy[MAXPATHLEN];
3306+ int path_len;
3307+
3308+ /* Special case path ends with a trailing slash */
3309+ path_len = strlen(path);
3310+ if (path_len >= MAXPATHLEN) {
3311+ errno = EPERM; /* we deny permission to open it */
3312+ return -1;
3313+ }
3314+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
3315+ memcpy(path_copy, path, path_len+1);
3316+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
3317+ path_copy[path_len] = '\0';
3318+ path = (const char *)&path_copy;
3319+ }
3320
3321 pathbuf = estrdup(PG(open_basedir));
3322
3323diff -Nura php-4.4.0/main/hardened_globals.h hardening-patch-4.4.0-0.4.3/main/hardened_globals.h
3324--- php-4.4.0/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
3325+++ hardening-patch-4.4.0-0.4.3/main/hardened_globals.h 2005-09-12 18:15:08.000000000 +0200
3326@@ -0,0 +1,62 @@
3327+/*
3328+ +----------------------------------------------------------------------+
3329+ | Hardening-Patch for PHP |
3330+ +----------------------------------------------------------------------+
3331+ | Copyright (c) 2004-2005 Stefan Esser |
3332+ +----------------------------------------------------------------------+
3333+ | This source file is subject to version 2.02 of the PHP license, |
3334+ | that is bundled with this package in the file LICENSE, and is |
3335+ | available at through the world-wide-web at |
3336+ | http://www.php.net/license/2_02.txt. |
3337+ | If you did not receive a copy of the PHP license and are unable to |
3338+ | obtain it through the world-wide-web, please send a note to |
3339+ | license@php.net so we can mail you a copy immediately. |
3340+ +----------------------------------------------------------------------+
3341+ | Author: Stefan Esser <sesser@hardened-php.net> |
3342+ +----------------------------------------------------------------------+
3343+ */
3344+
3345+#ifndef HARDENED_GLOBALS_H
3346+#define HARDENED_GLOBALS_H
3347+
3348+typedef struct _hardened_globals hardened_globals_struct;
3349+
3350+#ifdef ZTS
3351+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
3352+extern int hardened_globals_id;
3353+#else
3354+# define HG(v) (hardened_globals.v)
3355+extern struct _hardened_globals hardened_globals;
3356+#endif
3357+
3358+
3359+struct _hardened_globals {
3360+#if HARDENING_PATCH_MM_PROTECT
3361+ unsigned int canary_1;
3362+ unsigned int canary_2;
3363+#endif
3364+#if HARDENING_PATCH_LL_PROTECT
3365+ unsigned int canary_3;
3366+ unsigned int canary_4;
3367+ unsigned int ll_canary_inited;
3368+#endif
3369+ zend_bool hphp_sql_bailout_on_error;
3370+ zend_bool hphp_multiheader;
3371+ HashTable *eval_whitelist;
3372+ HashTable *eval_blacklist;
3373+ HashTable *func_whitelist;
3374+ HashTable *func_blacklist;
3375+ HashTable *include_whitelist;
3376+ HashTable *include_blacklist;
3377+ unsigned int dummy;
3378+};
3379+
3380+
3381+#endif /* HARDENED_GLOBALS_H */
3382+
3383+/*
3384+ * Local variables:
3385+ * tab-width: 4
3386+ * c-basic-offset: 4
3387+ * End:
3388+ */
3389diff -Nura php-4.4.0/main/hardening_patch.c hardening-patch-4.4.0-0.4.3/main/hardening_patch.c
3390--- php-4.4.0/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
3391+++ hardening-patch-4.4.0-0.4.3/main/hardening_patch.c 2005-09-12 18:15:08.000000000 +0200
3392@@ -0,0 +1,424 @@
3393+/*
3394+ +----------------------------------------------------------------------+
3395+ | Hardening Patch for PHP |
3396+ +----------------------------------------------------------------------+
3397+ | Copyright (c) 2004-2005 Stefan Esser |
3398+ +----------------------------------------------------------------------+
3399+ | This source file is subject to version 2.02 of the PHP license, |
3400+ | that is bundled with this package in the file LICENSE, and is |
3401+ | available at through the world-wide-web at |
3402+ | http://www.php.net/license/2_02.txt. |
3403+ | If you did not receive a copy of the PHP license and are unable to |
3404+ | obtain it through the world-wide-web, please send a note to |
3405+ | license@php.net so we can mail you a copy immediately. |
3406+ +----------------------------------------------------------------------+
3407+ | Author: Stefan Esser <sesser@hardened-php.net> |
3408+ +----------------------------------------------------------------------+
3409+ */
3410+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
3411+
3412+#include "php.h"
3413+
3414+#include <stdio.h>
3415+#include <stdlib.h>
3416+
3417+#if HAVE_UNISTD_H
3418+#include <unistd.h>
3419+#endif
3420+#include "SAPI.h"
3421+#include "php_globals.h"
3422+
3423+#if HARDENING_PATCH
3424+
3425+#ifdef HAVE_SYS_SOCKET_H
3426+#include <sys/socket.h>
3427+#endif
3428+
3429+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
3430+#undef AF_UNIX
3431+#endif
3432+
3433+#if defined(AF_UNIX)
3434+#include <sys/un.h>
3435+#endif
3436+
3437+#define SYSLOG_PATH "/dev/log"
3438+
3439+#include "snprintf.h"
3440+
3441+#include "hardening_patch.h"
3442+
3443+#ifdef ZTS
3444+#include "hardened_globals.h"
3445+int hardened_globals_id;
3446+#else
3447+struct _hardened_globals hardened_globals;
3448+#endif
3449+
3450+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
3451+{
3452+ memset(hardened_globals, 0, sizeof(*hardened_globals));
3453+}
3454+
3455+
3456+PHPAPI void hardened_startup()
3457+{
3458+#ifdef ZTS
3459+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
3460+#else
3461+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
3462+#endif
3463+}
3464+
3465+char *loglevel2string(int loglevel)
3466+{
3467+ switch (loglevel) {
3468+ case S_FILES:
3469+ return "FILES";
3470+ case S_INCLUDE:
3471+ return "INCLUDE";
3472+ case S_MEMORY:
3473+ return "MEMORY";
3474+ case S_MISC:
3475+ return "MISC";
3476+ case S_SQL:
3477+ return "SQL";
3478+ case S_EXECUTOR:
3479+ return "EXECUTOR";
3480+ case S_VARS:
3481+ return "VARS";
3482+ default:
3483+ return "UNKNOWN";
3484+ }
3485+}
3486+
3487+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
3488+{
3489+#if defined(AF_UNIX)
3490+ int s, r, i=0;
3491+ struct sockaddr_un saun;
3492+ char buf[4096+64];
3493+ char error[4096+100];
3494+ char *ip_address;
3495+ char *fname;
3496+ int lineno;
3497+ va_list ap;
3498+ TSRMLS_FETCH();
3499+
3500+ if (EG(hphp_log_use_x_forwarded_for)) {
3501+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
3502+ if (ip_address == NULL) {
3503+ ip_address = "X-FORWARDED-FOR not set";
3504+ }
3505+ } else {
3506+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
3507+ if (ip_address == NULL) {
3508+ ip_address = "REMOTE_ADDR not set";
3509+ }
3510+ }
3511+
3512+
3513+ va_start(ap, fmt);
3514+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
3515+ va_end(ap);
3516+ while (error[i]) {
3517+ if (error[i] < 32) error[i] = '.';
3518+ i++;
3519+ }
3520+
3521+ if (zend_is_executing(TSRMLS_C)) {
3522+ lineno = zend_get_executed_lineno(TSRMLS_C);
3523+ fname = zend_get_executed_filename(TSRMLS_C);
3524+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
3525+ } else {
3526+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
3527+ if (fname==NULL) {
3528+ fname = "unknown";
3529+ }
3530+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
3531+ }
3532+
3533+ /* Syslog-Logging disabled? */
3534+ if ((EG(hphp_log_syslog) & loglevel)==0) {
3535+ goto log_sapi;
3536+ }
3537+
3538+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
3539+
3540+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
3541+ if (s == -1) {
3542+ goto log_sapi;
3543+ }
3544+
3545+ memset(&saun, 0, sizeof(saun));
3546+ saun.sun_family = AF_UNIX;
3547+ strcpy(saun.sun_path, SYSLOG_PATH);
3548+ /*saun.sun_len = sizeof(saun);*/
3549+
3550+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
3551+ if (r) {
3552+ close(s);
3553+ s = socket(AF_UNIX, SOCK_STREAM, 0);
3554+ if (s == -1) {
3555+ goto log_sapi;
3556+ }
3557+
3558+ memset(&saun, 0, sizeof(saun));
3559+ saun.sun_family = AF_UNIX;
3560+ strcpy(saun.sun_path, SYSLOG_PATH);
3561+ /*saun.sun_len = sizeof(saun);*/
3562+
3563+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
3564+ if (r) {
3565+ close(s);
3566+ goto log_sapi;
3567+ }
3568+ }
3569+ send(s, error, strlen(error), 0);
3570+
3571+ close(s);
3572+
3573+log_sapi:
3574+ /* SAPI Logging activated? */
3575+ if ((EG(hphp_log_syslog) & loglevel)!=0) {
3576+ sapi_module.log_message(buf);
3577+ }
3578+
3579+log_script:
3580+ /* script logging activaed? */
3581+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
3582+ char cmd[8192], *cmdpos, *bufpos;
3583+ FILE *in;
3584+ int space;
3585+
3586+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
3587+ space = sizeof(cmd) - strlen(cmd);
3588+ cmdpos = cmd + strlen(cmd);
3589+ bufpos = buf;
3590+ if (space <= 1) return;
3591+ while (space > 2 && *bufpos) {
3592+ if (*bufpos == '\'') {
3593+ if (space<=5) break;
3594+ *cmdpos++ = '\'';
3595+ *cmdpos++ = '\\';
3596+ *cmdpos++ = '\'';
3597+ *cmdpos++ = '\'';
3598+ bufpos++;
3599+ space-=4;
3600+ } else {
3601+ *cmdpos++ = *bufpos++;
3602+ space--;
3603+ }
3604+ }
3605+ *cmdpos++ = '\'';
3606+ *cmdpos = 0;
3607+
3608+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
3609+ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", EG(hphp_log_scriptname));
3610+ return;
3611+ }
3612+ /* read and forget the result */
3613+ while (1) {
3614+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
3615+ if (readbytes<=0) {
3616+ break;
3617+ }
3618+ }
3619+ pclose(in);
3620+ }
3621+
3622+#endif
3623+}
3624+#endif
3625+
3626+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
3627+
3628+/* will be replaced later with more compatible method */
3629+PHPAPI unsigned int php_canary()
3630+{
3631+ time_t t;
3632+ unsigned int canary;
3633+ int fd;
3634+
3635+ fd = open("/dev/urandom", 0);
3636+ if (fd != -1) {
3637+ int r = read(fd, &canary, sizeof(canary));
3638+ close(fd);
3639+ if (r == sizeof(canary)) {
3640+ return (canary);
3641+ }
3642+ }
3643+ /* not good but we never want to do this */
3644+ time(&t);
3645+ canary = *(unsigned int *)&t + getpid() << 16;
3646+ return (canary);
3647+}
3648+#endif
3649+
3650+#if HARDENING_PATCH_INC_PROTECT
3651+
3652+PHPAPI int php_is_valid_include(zval *z)
3653+{
3654+ char *filename;
3655+ int len, i;
3656+ TSRMLS_FETCH();
3657+
3658+ /* must be of type string */
3659+ if (z->type != IS_STRING || z->value.str.val == NULL) {
3660+ return (0);
3661+ }
3662+
3663+ /* short cut */
3664+ filename = z->value.str.val;
3665+ len = z->value.str.len;
3666+
3667+ /* 1. must be shorter than MAXPATHLEN */
3668+ if (len > MAXPATHLEN) {
3669+ char *fname = estrndup(filename, len);
3670+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
3671+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
3672+ efree(fname);
3673+ return (0);
3674+ }
3675+
3676+ /* 2. must not be cutted */
3677+ if (len != strlen(filename)) {
3678+ char *fname = estrndup(filename, len);
3679+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
3680+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
3681+ efree(fname);
3682+ return (0);
3683+ }
3684+
3685+ /* 3. when it is an URL first check black/whitelist if both are empty disallow all URLs */
3686+ if (strstr(filename, "://")) {
3687+ char *fname = estrndup(filename, len);
3688+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
3689+
3690+ /* no black or whitelist then disallow all */
3691+ if (HG(include_whitelist)==NULL && HG(include_blacklist)==NULL) {
3692+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
3693+ efree(fname);
3694+ return (0);
3695+ }
3696+
3697+ /* whitelist is stronger than blacklist */
3698+ if (HG(include_whitelist)) {
3699+ char *s, *t, *h, *index;
3700+ uint indexlen;
3701+ ulong numindex;
3702+
3703+ s = filename;
3704+
3705+ do {
3706+ zend_bool isOk = 0;
3707+ int tlen;
3708+
3709+ t = h = strstr(s, "://");
3710+ if (h == NULL) break;
3711+
3712+
3713+ while (t > s && (isalpha(t[-1]) || t[-1]=='_')) {
3714+ t--;
3715+ }
3716+
3717+ tlen = strlen(t);
3718+
3719+ zend_hash_internal_pointer_reset(HG(include_whitelist));
3720+ do {
3721+ int r = zend_hash_get_current_key_ex(HG(include_whitelist), &index, &indexlen, &numindex, 0, NULL);
3722+
3723+ if (r==HASH_KEY_NON_EXISTANT) {
3724+ break;
3725+ }
3726+ if (r==HASH_KEY_IS_STRING) {
3727+ if (h-t <= indexlen-1 && tlen>=indexlen-1) {
3728+ if (strncmp(t, index, indexlen-1)==0) {
3729+ isOk = 1;
3730+ break;
3731+ }
3732+ }
3733+ }
3734+
3735+ zend_hash_move_forward(HG(include_whitelist));
3736+ } while (1);
3737+
3738+ /* not found in whitelist */
3739+ if (!isOk) {
3740+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL that is not allowed in whitelist", fname);
3741+ efree(fname);
3742+ return 0;
3743+ }
3744+
3745+ s = h + 3;
3746+ } while (1);
3747+ } else {
3748+ /* okay then handle the blacklist */
3749+ char *s, *t, *h, *index;
3750+ uint indexlen;
3751+ ulong numindex;
3752+
3753+ s = filename;
3754+
3755+ do {
3756+ int tlen;
3757+
3758+ t = h = strstr(s, "://");
3759+ if (h == NULL) break;
3760+
3761+
3762+ while (t > s) {
3763+ if (isalpha(t[-1]) || t[-1]=='_') t--;
3764+ }
3765+
3766+ tlen = strlen(t);
3767+
3768+ zend_hash_internal_pointer_reset(HG(include_blacklist));
3769+ do {
3770+ int r = zend_hash_get_current_key_ex(HG(include_blacklist), &index, &indexlen, &numindex, 0, NULL);
3771+
3772+ if (r==HASH_KEY_NON_EXISTANT) {
3773+ break;
3774+ }
3775+ if (r==HASH_KEY_IS_STRING) {
3776+ if (h-t <= indexlen-1 && tlen>=indexlen-1) {
3777+ if (strncmp(t, index, indexlen-1)==0) {
3778+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL that is forbidden by the blacklist", fname);
3779+ efree(fname);
3780+ return 0;
3781+ }
3782+ }
3783+ }
3784+
3785+ zend_hash_move_forward(HG(include_blacklist));
3786+ } while (1);
3787+
3788+ s = h + 3;
3789+ } while (1);
3790+ }
3791+
3792+ efree(fname);
3793+ }
3794+
3795+ /* 4. must not be an uploaded file */
3796+ if (SG(rfc1867_uploaded_files)) {
3797+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
3798+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
3799+ return (0);
3800+ }
3801+ }
3802+
3803+ /* passed all tests */
3804+ return (1);
3805+}
3806+
3807+#endif
3808+
3809+/*
3810+ * Local variables:
3811+ * tab-width: 4
3812+ * c-basic-offset: 4
3813+ * End:
3814+ * vim600: sw=4 ts=4 fdm=marker
3815+ * vim<600: sw=4 ts=4
3816+ */
3817diff -Nura php-4.4.0/main/hardening_patch.h hardening-patch-4.4.0-0.4.3/main/hardening_patch.h
3818--- php-4.4.0/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
3819+++ hardening-patch-4.4.0-0.4.3/main/hardening_patch.h 2005-09-12 18:15:08.000000000 +0200
3820@@ -0,0 +1,46 @@
3821+/*
3822+ +----------------------------------------------------------------------+
3823+ | Hardening Patch for PHP |
3824+ +----------------------------------------------------------------------+
3825+ | Copyright (c) 2004-2005 Stefan Esser |
3826+ +----------------------------------------------------------------------+
3827+ | This source file is subject to version 2.02 of the PHP license, |
3828+ | that is bundled with this package in the file LICENSE, and is |
3829+ | available at through the world-wide-web at |
3830+ | http://www.php.net/license/2_02.txt. |
3831+ | If you did not receive a copy of the PHP license and are unable to |
3832+ | obtain it through the world-wide-web, please send a note to |
3833+ | license@php.net so we can mail you a copy immediately. |
3834+ +----------------------------------------------------------------------+
3835+ | Author: Stefan Esser <sesser@hardened-php.net> |
3836+ +----------------------------------------------------------------------+
3837+ */
3838+
3839+#ifndef HARDENING_PATCH_H
3840+#define HARDENING_PATCH_H
3841+
3842+#include "zend.h"
3843+
3844+#if HARDENING_PATCH
3845+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
3846+PHPAPI void hardened_startup();
3847+#define HARDENING_PATCH_VERSION "0.4.3"
3848+
3849+#endif
3850+
3851+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
3852+PHPAPI unsigned int php_canary();
3853+#endif
3854+
3855+#if HARDENING_PATCH_INC_PROTECT
3856+PHPAPI int php_is_valid_include(zval *z);
3857+#endif
3858+
3859+#endif /* HARDENING_PATCH_H */
3860+
3861+/*
3862+ * Local variables:
3863+ * tab-width: 4
3864+ * c-basic-offset: 4
3865+ * End:
3866+ */
3867diff -Nura php-4.4.0/main/hardening_patch.m4 hardening-patch-4.4.0-0.4.3/main/hardening_patch.m4
3868--- php-4.4.0/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
3869+++ hardening-patch-4.4.0-0.4.3/main/hardening_patch.m4 2005-09-11 23:31:08.000000000 +0200
3870@@ -0,0 +1,95 @@
3871+dnl
3872+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
3873+dnl
3874+dnl This file contains Hardening Patch for PHP specific autoconf functions.
3875+dnl
3876+
3877+AC_ARG_ENABLE(hardening-patch-mm-protect,
3878+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
3879+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
3880+],[
3881+ DO_HARDENING_PATCH_MM_PROTECT=yes
3882+])
3883+
3884+AC_ARG_ENABLE(hardening-patch-ll-protect,
3885+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
3886+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
3887+],[
3888+ DO_HARDENING_PATCH_LL_PROTECT=yes
3889+])
3890+
3891+AC_ARG_ENABLE(hardening-patch-inc-protect,
3892+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
3893+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
3894+],[
3895+ DO_HARDENING_PATCH_INC_PROTECT=yes
3896+])
3897+
3898+AC_ARG_ENABLE(hardening-patch-fmt-protect,
3899+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
3900+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
3901+],[
3902+ DO_HARDENING_PATCH_FMT_PROTECT=yes
3903+])
3904+
3905+AC_ARG_ENABLE(hardening-patch-hash-protect,
3906+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
3907+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
3908+],[
3909+ DO_HARDENING_PATCH_HASH_PROTECT=yes
3910+])
3911+
3912+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
3913+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
3914+
3915+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
3916+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
3917+
3918+AC_MSG_CHECKING(whether to protect include/require statements)
3919+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
3920+
3921+AC_MSG_CHECKING(whether to protect PHP Format String functions)
3922+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
3923+
3924+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
3925+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
3926+
3927+
3928+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3929+
3930+
3931+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
3932+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3933+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
3934+else
3935+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
3936+fi
3937+
3938+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
3939+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3940+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
3941+else
3942+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
3943+fi
3944+
3945+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
3946+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3947+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
3948+else
3949+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
3950+fi
3951+
3952+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
3953+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3954+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
3955+else
3956+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
3957+fi
3958+
3959+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
3960+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3961+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
3962+else
3963+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
3964+fi
3965+
3966diff -Nura php-4.4.0/main/main.c hardening-patch-4.4.0-0.4.3/main/main.c
3967--- php-4.4.0/main/main.c 2005-06-20 21:59:43.000000000 +0200
3968+++ hardening-patch-4.4.0-0.4.3/main/main.c 2005-09-11 23:31:08.000000000 +0200
3969@@ -100,6 +100,10 @@
3970 PHPAPI int core_globals_id;
3971 #endif
3972
3973+#if HARDENING_PATCH
3974+#include "hardened_globals.h"
3975+#endif
3976+
3977 #define ERROR_BUF_LEN 1024
3978
3979 typedef struct {
3980@@ -150,10 +154,33 @@
3981 */
3982 static PHP_INI_MH(OnChangeMemoryLimit)
3983 {
3984+#if HARDENING_PATCH
3985+ long orig_memory_limit;
3986+
3987+ if (entry->modified) {
3988+ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length);
3989+ } else {
3990+ orig_memory_limit = 1<<30;
3991+ }
3992+ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) {
3993+ orig_memory_limit = 1<<30;
3994+ }
3995+#endif
3996 if (new_value) {
3997 PG(memory_limit) = zend_atoi(new_value, new_value_length);
3998+#if HARDENING_PATCH
3999+ if (PG(memory_limit) > orig_memory_limit) {
4000+ PG(memory_limit) = orig_memory_limit;
4001+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
4002+ return FAILURE;
4003+ }
4004+#endif
4005 } else {
4006+#if HARDENING_PATCH
4007+ PG(memory_limit) = orig_memory_limit;
4008+#else
4009 PG(memory_limit) = 1<<30; /* effectively, no limit */
4010+#endif
4011 }
4012 return zend_set_memory_limit(PG(memory_limit));
4013 }
4014@@ -1096,6 +1123,10 @@
4015 tsrm_ls = ts_resource(0);
4016 #endif
4017
4018+#if HARDENING_PATCH
4019+ hardened_startup();
4020+#endif
4021+
4022 sapi_initialize_empty_request(TSRMLS_C);
4023 sapi_activate(TSRMLS_C);
4024
4025@@ -1108,6 +1139,12 @@
4026 php_output_startup();
4027 php_output_activate(TSRMLS_C);
4028
4029+#if HARDENING_PATCH_INC_PROTECT
4030+ zuf.is_valid_include = php_is_valid_include;
4031+#endif
4032+#if HARDENING_PATCH
4033+ zuf.security_log_function = php_security_log;
4034+#endif
4035 zuf.error_function = php_error_cb;
4036 zuf.printf_function = php_printf;
4037 zuf.write_function = php_body_write_wrapper;
4038@@ -1209,6 +1246,10 @@
4039 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS);
4040 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
4041 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
4042+#if HARDENING_PATCH
4043+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
4044+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
4045+#endif
4046 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
4047 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
4048 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
4049@@ -1316,7 +1357,7 @@
4050 */
4051 static inline void php_register_server_variables(TSRMLS_D)
4052 {
4053- zval *array_ptr=NULL;
4054+ zval *array_ptr=NULL, *vptr;
4055
4056 ALLOC_ZVAL(array_ptr);
4057 array_init(array_ptr);
4058@@ -1326,6 +1367,16 @@
4059 /* Server variables */
4060 if (sapi_module.register_server_variables) {
4061 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
4062+ if (zend_hash_find(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), (void **)&vptr)==SUCCESS) {
4063+ char *str;
4064+ if (vptr->type != IS_STRING) {
4065+ str = "Array";
4066+ } else {
4067+ str = vptr->value.str.val;
4068+ }
4069+ php_security_log(S_VARS, "Attacker tried to overwrite HTTP_RAW_POST_DATA with '%s' through a HTTP header", str);
4070+ zend_hash_del(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
4071+ }
4072 }
4073
4074 /* PHP Authentication support */
4075diff -Nura php-4.4.0/main/php_config.h.in hardening-patch-4.4.0-0.4.3/main/php_config.h.in
4076--- php-4.4.0/main/php_config.h.in 2005-07-11 12:07:41.000000000 +0200
4077+++ hardening-patch-4.4.0-0.4.3/main/php_config.h.in 2005-09-11 23:31:08.000000000 +0200
4078@@ -860,6 +860,39 @@
4079 /* Enabling BIND8 compatibility for Panther */
4080 #undef BIND_8_COMPAT
4081
4082+/* Hardening-Patch */
4083+#undef HARDENING_PATCH
4084+
4085+/* Memory Manager Protection */
4086+#undef HARDENING_PATCH_MM_PROTECT
4087+
4088+/* Memory Manager Protection */
4089+#undef HARDENING_PATCH_MM_PROTECT
4090+
4091+/* Linked List Protection */
4092+#undef HARDENING_PATCH_LL_PROTECT
4093+
4094+/* Linked List Protection */
4095+#undef HARDENING_PATCH_LL_PROTECT
4096+
4097+/* Include/Require Protection */
4098+#undef HARDENING_PATCH_INC_PROTECT
4099+
4100+/* Include/Require Protection */
4101+#undef HARDENING_PATCH_INC_PROTECT
4102+
4103+/* Fmt String Protection */
4104+#undef HARDENING_PATCH_FMT_PROTECT
4105+
4106+/* Fmt String Protection */
4107+#undef HARDENING_PATCH_FMT_PROTECT
4108+
4109+/* HashTable DTOR Protection */
4110+#undef HARDENING_PATCH_HASH_PROTECT
4111+
4112+/* HashTable DTOR Protection */
4113+#undef HARDENING_PATCH_HASH_PROTECT
4114+
4115 /* Whether you have AOLserver */
4116 #undef HAVE_AOLSERVER
4117
4118@@ -1143,6 +1176,12 @@
4119 /* Define if you have the getaddrinfo function */
4120 #undef HAVE_GETADDRINFO
4121
4122+/* Whether realpath is broken */
4123+#undef PHP_BROKEN_REALPATH
4124+
4125+/* Whether realpath is broken */
4126+#undef PHP_BROKEN_REALPATH
4127+
4128 /* Whether system headers declare timezone */
4129 #undef HAVE_DECLARED_TIMEZONE
4130
4131diff -Nura php-4.4.0/main/php_content_types.c hardening-patch-4.4.0-0.4.3/main/php_content_types.c
4132--- php-4.4.0/main/php_content_types.c 2002-12-31 17:26:14.000000000 +0100
4133+++ hardening-patch-4.4.0-0.4.3/main/php_content_types.c 2005-09-11 23:31:08.000000000 +0200
4134@@ -77,6 +77,7 @@
4135 sapi_register_post_entries(php_post_entries);
4136 sapi_register_default_post_reader(php_default_post_reader);
4137 sapi_register_treat_data(php_default_treat_data);
4138+ sapi_register_input_filter(php_default_input_filter);
4139 return SUCCESS;
4140 }
4141 /* }}} */
4142diff -Nura php-4.4.0/main/php.h hardening-patch-4.4.0-0.4.3/main/php.h
4143--- php-4.4.0/main/php.h 2005-04-17 15:37:29.000000000 +0200
4144+++ hardening-patch-4.4.0-0.4.3/main/php.h 2005-09-11 23:31:08.000000000 +0200
4145@@ -35,11 +35,19 @@
4146 #include "zend_qsort.h"
4147 #include "php_compat.h"
4148
4149+
4150 #include "zend_API.h"
4151
4152 #undef sprintf
4153 #define sprintf php_sprintf
4154
4155+#if HARDENING_PATCH
4156+#if HAVE_REALPATH
4157+#undef realpath
4158+#define realpath php_realpath
4159+#endif
4160+#endif
4161+
4162 /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
4163 #undef PHP_DEBUG
4164 #define PHP_DEBUG ZEND_DEBUG
4165@@ -435,6 +443,10 @@
4166 #endif
4167 #endif /* !XtOffsetOf */
4168
4169+#if HARDENING_PATCH
4170+#include "hardening_patch.h"
4171+#endif
4172+
4173 #endif
4174
4175 /*
4176diff -Nura php-4.4.0/main/php_variables.c hardening-patch-4.4.0-0.4.3/main/php_variables.c
4177--- php-4.4.0/main/php_variables.c 2005-05-17 20:42:35.000000000 +0200
4178+++ hardening-patch-4.4.0-0.4.3/main/php_variables.c 2005-09-11 23:31:08.000000000 +0200
4179@@ -225,17 +225,28 @@
4180 while (var) {
4181 val = strchr(var, '=');
4182 if (val) { /* have a value */
4183- int val_len;
4184+ unsigned int val_len, new_val_len;
4185
4186 *val++ = '\0';
4187 php_url_decode(var, strlen(var));
4188 val_len = php_url_decode(val, strlen(val));
4189- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
4190+ val = estrndup(val, val_len);
4191+ if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
4192+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
4193+ }
4194+ efree(val);
4195 }
4196 var = php_strtok_r(NULL, "&", &strtok_buf);
4197 }
4198 }
4199
4200+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
4201+{
4202+ /* TODO: check .ini setting here and apply user-defined input filter */
4203+ *new_val_len = val_len;
4204+ return 1;
4205+}
4206+
4207 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
4208 {
4209 char *res = NULL, *var, *val, *separator=NULL;
4210@@ -313,15 +324,26 @@
4211 while (var) {
4212 val = strchr(var, '=');
4213 if (val) { /* have a value */
4214- int val_len;
4215+ unsigned int val_len, new_val_len;
4216
4217 *val++ = '\0';
4218 php_url_decode(var, strlen(var));
4219 val_len = php_url_decode(val, strlen(val));
4220- php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
4221+ val = estrndup(val, val_len);
4222+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
4223+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
4224+ }
4225+ efree(val);
4226 } else {
4227+ unsigned int val_len, new_val_len;
4228+
4229 php_url_decode(var, strlen(var));
4230- php_register_variable_safe(var, "", 0, array_ptr TSRMLS_CC);
4231+ val_len = 0;
4232+ val = estrndup("", 0);
4233+ if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
4234+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
4235+ }
4236+ efree(val);
4237 }
4238 var = php_strtok_r(NULL, separator, &strtok_buf);
4239 }
4240diff -Nura php-4.4.0/main/rfc1867.c hardening-patch-4.4.0-0.4.3/main/rfc1867.c
4241--- php-4.4.0/main/rfc1867.c 2005-04-04 16:59:58.000000000 +0200
4242+++ hardening-patch-4.4.0-0.4.3/main/rfc1867.c 2005-09-12 18:15:08.000000000 +0200
4243@@ -127,6 +127,7 @@
4244 #define UPLOAD_ERROR_C 3 /* Partially uploaded */
4245 #define UPLOAD_ERROR_D 4 /* No file uploaded */
4246 #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
4247+#define UPLOAD_ERROR_F 7 /* Filter forbids upload */
4248
4249 void php_rfc1867_register_constants(TSRMLS_D)
4250 {
4251@@ -136,6 +137,7 @@
4252 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL", UPLOAD_ERROR_C, CONST_CS | CONST_PERSISTENT);
4253 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
4254 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
4255+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
4256 }
4257
4258 static void normalize_protected_variable(char *varname TSRMLS_DC)
4259@@ -844,6 +846,7 @@
4260 char buff[FILLUNIT];
4261 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
4262 int blen=0, wlen=0;
4263+ unsigned long offset;
4264
4265 zend_llist_clean(&header);
4266
4267@@ -891,21 +894,24 @@
4268 if (!filename && param) {
4269
4270 char *value = multipart_buffer_read_body(mbuff TSRMLS_CC);
4271+ unsigned int new_val_len; /* Dummy variable */
4272
4273 if (!value) {
4274 value = estrdup("");
4275 }
4276
4277+ if (sapi_module.input_filter(PARSE_POST, param, &value, strlen(value), &new_val_len TSRMLS_CC)) {
4278 #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
4279- if (php_mb_encoding_translation(TSRMLS_C)) {
4280- php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
4281- &num_vars, &num_vars_max TSRMLS_CC);
4282- } else {
4283- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
4284- }
4285+ if (php_mb_encoding_translation(TSRMLS_C)) {
4286+ php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
4287+ &num_vars, &num_vars_max TSRMLS_CC);
4288+ } else {
4289+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
4290+ }
4291 #else
4292- safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
4293+ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
4294 #endif
4295+ }
4296 if (!strcasecmp(param, "MAX_FILE_SIZE")) {
4297 max_file_size = atol(value);
4298 }
4299@@ -957,7 +963,11 @@
4300 tmp++;
4301 }
4302 }
4303-
4304+
4305+ if (sapi_module.upload_varname_filter && sapi_module.upload_varname_filter(param TSRMLS_CC)==FAILURE) {
4306+ skip_upload = 1;
4307+ }
4308+
4309 total_bytes = cancel_upload = 0;
4310
4311 if (!skip_upload) {
4312@@ -981,6 +991,11 @@
4313 cancel_upload = UPLOAD_ERROR_D;
4314 }
4315
4316+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
4317+ cancel_upload = UPLOAD_ERROR_F;
4318+ }
4319+
4320+ offset = 0;
4321 while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC)))
4322 {
4323 if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) {
4324@@ -990,6 +1005,11 @@
4325 sapi_module.sapi_error(E_WARNING, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
4326 cancel_upload = UPLOAD_ERROR_B;
4327 } else if (blen > 0) {
4328+
4329+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
4330+ cancel_upload = UPLOAD_ERROR_F;
4331+ }
4332+
4333 wlen = write(fd, buff, blen);
4334
4335 if (wlen < blen) {
4336@@ -997,6 +1017,7 @@
4337 cancel_upload = UPLOAD_ERROR_C;
4338 } else {
4339 total_bytes += wlen;
4340+ offset += wlen;
4341 }
4342 }
4343 }
4344@@ -1011,6 +1032,10 @@
4345 }
4346 #endif
4347
4348+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
4349+ cancel_upload = UPLOAD_ERROR_F;
4350+ }
4351+
4352 if (cancel_upload) {
4353 if (temp_filename) {
4354 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
4355diff -Nura php-4.4.0/main/SAPI.c hardening-patch-4.4.0-0.4.3/main/SAPI.c
4356--- php-4.4.0/main/SAPI.c 2005-02-22 15:46:24.000000000 +0100
4357+++ hardening-patch-4.4.0-0.4.3/main/SAPI.c 2005-09-12 18:15:08.000000000 +0200
4358@@ -831,6 +831,37 @@
4359 return SUCCESS;
4360 }
4361
4362+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
4363+{
4364+ sapi_module.input_filter = input_filter;
4365+ return SUCCESS;
4366+}
4367+
4368+SAPI_API int sapi_register_upload_varname_filter(unsigned int (*upload_varname_filter)(char *varname TSRMLS_DC))
4369+{
4370+ sapi_module.upload_varname_filter = upload_varname_filter;
4371+ return SUCCESS;
4372+}
4373+
4374+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
4375+{
4376+ sapi_module.pre_upload_filter = pre_upload_filter;
4377+ return SUCCESS;
4378+}
4379+
4380+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
4381+{
4382+ sapi_module.upload_content_filter = upload_content_filter;
4383+ return SUCCESS;
4384+}
4385+
4386+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
4387+{
4388+ sapi_module.post_upload_filter = post_upload_filter;
4389+ return SUCCESS;
4390+}
4391+
4392+
4393
4394 SAPI_API int sapi_flush(TSRMLS_D)
4395 {
4396diff -Nura php-4.4.0/main/SAPI.h hardening-patch-4.4.0-0.4.3/main/SAPI.h
4397--- php-4.4.0/main/SAPI.h 2003-04-09 22:27:55.000000000 +0200
4398+++ hardening-patch-4.4.0-0.4.3/main/SAPI.h 2005-09-12 22:51:45.000000000 +0200
4399@@ -101,9 +101,10 @@
4400 char *current_user;
4401 int current_user_length;
4402
4403- /* this is necessary for CLI module */
4404- int argc;
4405- char **argv;
4406+ /* this is necessary for CLI module */
4407+ int argc;
4408+ char **argv;
4409+
4410 } sapi_request_info;
4411
4412
4413@@ -177,6 +178,10 @@
4414 SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry);
4415 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
4416 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
4417+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
4418+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
4419+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
4420+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
4421
4422 SAPI_API int sapi_flush(TSRMLS_D);
4423 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
4424@@ -238,8 +243,16 @@
4425 int (*get_target_uid)(uid_t * TSRMLS_DC);
4426 int (*get_target_gid)(gid_t * TSRMLS_DC);
4427
4428+ unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
4429+
4430+ unsigned int (*upload_varname_filter)(char *varname TSRMLS_DC);
4431+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
4432+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
4433+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
4434+
4435 void (*ini_defaults)(HashTable *configuration_hash);
4436 int phpinfo_as_text;
4437+
4438 };
4439
4440
4441@@ -262,16 +275,27 @@
4442
4443 #define SAPI_DEFAULT_MIMETYPE "text/html"
4444 #define SAPI_DEFAULT_CHARSET ""
4445+
4446+#if HARDENING_PATCH
4447+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
4448+#else
4449 #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
4450+#endif
4451
4452 #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
4453 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
4454
4455 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
4456+#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
4457+#define SAPI_UPLOAD_VARNAME_FILTER_FUNC(upload_varname_filter) unsigned int upload_varname_filter(char *varname TSRMLS_DC)
4458+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
4459+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
4460+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
4461
4462 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
4463 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
4464 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data);
4465+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter);
4466
4467 #define STANDARD_SAPI_MODULE_PROPERTIES
4468
4469diff -Nura php-4.4.0/main/snprintf.c hardening-patch-4.4.0-0.4.3/main/snprintf.c
4470--- php-4.4.0/main/snprintf.c 2005-04-08 07:44:53.000000000 +0200
4471+++ hardening-patch-4.4.0-0.4.3/main/snprintf.c 2005-09-11 23:31:08.000000000 +0200
4472@@ -1013,7 +1013,11 @@
4473
4474
4475 case 'n':
4476+#if HARDENING_PATCH_FMT_PROTECT
4477+ php_security_log(S_MISC, "'n' specifier within format string");
4478+#else
4479 *(va_arg(ap, int *)) = cc;
4480+#endif
4481 break;
4482
4483 /*
4484diff -Nura php-4.4.0/main/spprintf.c hardening-patch-4.4.0-0.4.3/main/spprintf.c
4485--- php-4.4.0/main/spprintf.c 2005-04-08 07:44:53.000000000 +0200
4486+++ hardening-patch-4.4.0-0.4.3/main/spprintf.c 2005-09-11 23:31:08.000000000 +0200
4487@@ -630,7 +630,11 @@
4488
4489
4490 case 'n':
4491+#if HARDENING_PATCH_FMT_PROTECT
4492+ php_security_log(S_MISC, "'n' specifier within format string");
4493+#else
4494 *(va_arg(ap, int *)) = xbuf->len;
4495+#endif
4496 break;
4497
4498 /*
4499diff -Nura php-4.4.0/pear/go-pear-list.php hardening-patch-4.4.0-0.4.3/pear/go-pear-list.php
4500--- php-4.4.0/pear/go-pear-list.php 2005-07-01 11:41:04.000000000 +0200
4501+++ hardening-patch-4.4.0-0.4.3/pear/go-pear-list.php 2005-09-11 23:31:08.000000000 +0200
4502@@ -8,7 +8,7 @@
4503 $packages = array(
4504 // required packages for the installer
4505 "PEAR" => "1.3.5",
4506-"XML_RPC" => "1.3.1",
4507+"XML_RPC" => "1.4.0",
4508 "Console_Getopt" => "1.2",
4509 "Archive_Tar" => "1.3.1",
4510
4511diff -Nura php-4.4.0/pear/packages/XML_RPC-1.3.1.tar hardening-patch-4.4.0-0.4.3/pear/packages/XML_RPC-1.3.1.tar
4512--- php-4.4.0/pear/packages/XML_RPC-1.3.1.tar 2005-07-01 11:42:14.000000000 +0200
4513+++ hardening-patch-4.4.0-0.4.3/pear/packages/XML_RPC-1.3.1.tar 1970-01-01 01:00:00.000000000 +0100
4514@@ -1,3733 +0,0 @@
4515-package2.xml
4516-<package packagerversion="1.4.0a12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
4517- <name>XML_RPC</name>
4518- <channel>pear.php.net</channel>
4519- <summary>PHP implementation of the XML-RPC protocol</summary>
4520- <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
4521-
4522-It has support for HTTP/HTTPS transport, proxies and authentication.</description>
4523- <lead>
4524- <name>Stig Bakken</name>
4525- <user>ssb</user>
4526- <email>stig@php.net</email>
4527- <active>no</active>
4528- </lead>
4529- <lead>
4530- <name>Daniel Convissor</name>
4531- <user>danielc</user>
4532- <email>danielc@php.net</email>
4533- <active>yes</active>
4534- </lead>
4535- <date>2005-06-29</date>
4536- <time>15:09:18</time>
4537- <version>
4538- <release>1.3.1</release>
4539- <api>1.3.0</api>
4540- </version>
4541- <stability>
4542- <release>stable</release>
4543- <api>stable</api>
4544- </stability>
4545- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4546- <notes>* Security fix. Update highly recommended!</notes>
4547- <contents>
4548- <dir name="/">
4549- <file md5sum="9b06c053e8e534f8d731eb90de2d0681" name="tests/protoport.php" role="test">
4550- <tasks:replace from="@package_version@" to="version" type="package-info" />
4551- </file>
4552- <file md5sum="74d1c90ae551d28bd40030fcc0b0f38d" name="tests/test_Dump.php" role="test">
4553- <tasks:replace from="@package_version@" to="version" type="package-info" />
4554- </file>
4555- <file baseinstalldir="XML/RPC" md5sum="5e2dfc5771116965655e07b4665563ce" name="Dump.php" role="php">
4556- <tasks:replace from="@package_version@" to="version" type="package-info" />
4557- </file>
4558- <file baseinstalldir="XML" md5sum="1e79cf06ae3ada5a6603c003ac0521e3" name="RPC.php" role="php">
4559- <tasks:replace from="@package_version@" to="version" type="package-info" />
4560- </file>
4561- <file baseinstalldir="XML/RPC" md5sum="6a750e3517d25ca01e685e8afe3976d6" name="Server.php" role="php">
4562- <tasks:replace from="@package_version@" to="version" type="package-info" />
4563- </file>
4564- </dir>
4565- </contents>
4566- <compatible>
4567- <name>PEAR</name>
4568- <channel>pear.php.net</channel>
4569- <min>1.4.0a1</min>
4570- <max>1.4.0a12</max>
4571- </compatible>
4572- <dependencies>
4573- <required>
4574- <php>
4575- <min>4.2.0</min>
4576- <max>6.0.0</max>
4577- </php>
4578- <pearinstaller>
4579- <min>1.4.0a1</min>
4580- </pearinstaller>
4581- </required>
4582- </dependencies>
4583- <phprelease />
4584- <changelog>
4585- <release>
4586- <version>
4587- <release>1.3.0RC3</release>
4588- <api>1.3.0</api>
4589- </version>
4590- <stability>
4591- <release>beta</release>
4592- <api>stable</api>
4593- </stability>
4594- <date>2005-05-10</date>
4595- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4596- <notes>* When verifying requests against function signatures, if the number of parameters don&apos;t match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
4597-* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
4598-* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
4599-* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
4600-* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
4601-* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().</notes>
4602- </release>
4603- <release>
4604- <version>
4605- <release>1.3.0RC2</release>
4606- <api>1.3.0</api>
4607- </version>
4608- <stability>
4609- <release>beta</release>
4610- <api>beta</api>
4611- </stability>
4612- <date>2005-05-05</date>
4613- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4614- <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
4615-* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
4616-* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
4617-* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.</notes>
4618- </release>
4619- <release>
4620- <version>
4621- <release>1.3.0RC1</release>
4622- <api>1.3.0</api>
4623- </version>
4624- <stability>
4625- <release>beta</release>
4626- <api>beta</api>
4627- </stability>
4628- <date>2005-04-07</date>
4629- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4630- <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
4631-* Add Fault Code 6: &quot;The requested method didn&apos;t return an XML_RPC_Response object.&quot; Request 4032.
4632-* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
4633-* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
4634-* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
4635-* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.</notes>
4636- </release>
4637- <release>
4638- <version>
4639- <release>1.2.2</release>
4640- <api>1.2.0</api>
4641- </version>
4642- <stability>
4643- <release>stable</release>
4644- <api>stable</api>
4645- </stability>
4646- <date>2005-03-07</date>
4647- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4648- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
4649- </release>
4650- <release>
4651- <version>
4652- <release>1.2.1</release>
4653- <api>1.2.0</api>
4654- </version>
4655- <stability>
4656- <release>stable</release>
4657- <api>stable</api>
4658- </stability>
4659- <date>2005-03-01</date>
4660- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4661- <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
4662- </release>
4663- <release>
4664- <version>
4665- <release>1.2.0</release>
4666- <api>1.2.0</api>
4667- </version>
4668- <stability>
4669- <release>stable</release>
4670- <api>stable</api>
4671- </stability>
4672- <date>2005-02-27</date>
4673- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4674- <notes>* Provide the &quot;stable&quot; release.
4675-* Add package2.xml for compatibility with PEAR 1.4.0.
4676-* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
4677- </release>
4678- <release>
4679- <version>
4680- <release>1.2.0RC7</release>
4681- <api>1.2.0RC7</api>
4682- </version>
4683- <stability>
4684- <release>beta</release>
4685- <api>beta</api>
4686- </stability>
4687- <date>2005-02-22</date>
4688- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4689- <notes>* Add the setSendEncoding() method and $send_encoding
4690- property to XML_RPC_Message. Request 3537.
4691-* Allow class methods to be mapped using either syntax:
4692- &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
4693- or
4694- &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
4695- Bug 3363.
4696-* Use 8192 instead of 32768 for bytes in fread()
4697- in parseResponseFile(). Bug 3340.</notes>
4698- </release>
4699- <release>
4700- <version>
4701- <release>1.2.0RC6</release>
4702- <api>1.2.0RC6</api>
4703- </version>
4704- <stability>
4705- <release>beta</release>
4706- <api>beta</api>
4707- </stability>
4708- <date>2005-01-25</date>
4709- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4710- <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
4711- </release>
4712- <release>
4713- <version>
4714- <release>1.2.0RC5</release>
4715- <api>1.2.0RC5</api>
4716- </version>
4717- <stability>
4718- <release>beta</release>
4719- <api>beta</api>
4720- </stability>
4721- <date>2005-01-24</date>
4722- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4723- <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
4724- </release>
4725- <release>
4726- <version>
4727- <release>1.2.0RC4</release>
4728- <api>1.2.0RC4</api>
4729- </version>
4730- <stability>
4731- <release>beta</release>
4732- <api>beta</api>
4733- </stability>
4734- <date>2005-01-24</date>
4735- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4736- <notes>* When a connection attempt fails, have the method return 0. (danielc)
4737-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
4738-* Add tests for setting the client properties. (danielc)
4739-* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
4740-* Bundle the tests with the package. (danielc)</notes>
4741- </release>
4742- <release>
4743- <version>
4744- <release>1.2.0RC3</release>
4745- <api>1.2.0RC3</api>
4746- </version>
4747- <stability>
4748- <release>beta</release>
4749- <api>beta</api>
4750- </stability>
4751- <date>2005-01-19</date>
4752- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4753- <notes>* ssl uses port 443, not 445.</notes>
4754- </release>
4755- <release>
4756- <version>
4757- <release>1.2.0RC2</release>
4758- <api>1.2.0RC2</api>
4759- </version>
4760- <stability>
4761- <release>beta</release>
4762- <api>beta</api>
4763- </stability>
4764- <date>2005-01-11</date>
4765- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4766- <notes>* Handle ssl:// in the $server string. (danielc)
4767-* Also default to port 445 for ssl:// requests as well. (danielc)
4768-* Enhance debugging in the server. (danielc)</notes>
4769- </release>
4770- <release>
4771- <version>
4772- <release>1.2.0RC1</release>
4773- <api>1.2.0RC1</api>
4774- </version>
4775- <stability>
4776- <release>beta</release>
4777- <api>beta</api>
4778- </stability>
4779- <date>2004-12-30</date>
4780- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4781- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
4782-* Allow array function callbacks (Matt Kane)
4783-* Some minor speed-ups (Matt Kane)
4784-* Add Dump.php to the package (Christian Weiske)
4785-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
4786-* Silence fsockopen() errors. Bug 1714. (danielc)
4787-* Encode empty arrays as an array. Bug 1493. (danielc)
4788-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
4789-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
4790-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
4791-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
4792-* Allow raiseError() to be called statically. (danielc)
4793-* Stop double escaping of character entities. Bug 987. (danielc)
4794- NOTICE: the following have been removed:
4795- * XML_RPC_dh()
4796- * $GLOBALS[&apos;XML_RPC_entities&apos;]
4797- * XML_RPC_entity_decode()
4798- * XML_RPC_lookup_entity()
4799-* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
4800- </release>
4801- <release>
4802- <version>
4803- <release>1.1.0</release>
4804- <api>1.1.0</api>
4805- </version>
4806- <stability>
4807- <release>stable</release>
4808- <api>stable</api>
4809- </stability>
4810- <date>2004-03-15</date>
4811- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4812- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
4813-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
4814-* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
4815-* Replace echo and error_log() with raiseError() (mroch)
4816-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
4817-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
4818-* Silent notice even in the error log (pierre)
4819-* fix include of shared xml extension on win32 (pierre)</notes>
4820- </release>
4821- <release>
4822- <version>
4823- <release>1.0.4</release>
4824- <api>1.0.4</api>
4825- </version>
4826- <stability>
4827- <release>stable</release>
4828- <api>stable</api>
4829- </stability>
4830- <date>2002-10-02</date>
4831- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4832- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
4833- </release>
4834- <release>
4835- <version>
4836- <release>1.0.3</release>
4837- <api>1.0.3</api>
4838- </version>
4839- <stability>
4840- <release>stable</release>
4841- <api>stable</api>
4842- </stability>
4843- <date>2002-05-19</date>
4844- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4845- <notes>* fix bug when parsing responses with boolean types</notes>
4846- </release>
4847- <release>
4848- <version>
4849- <release>1.0.2</release>
4850- <api>1.0.2</api>
4851- </version>
4852- <stability>
4853- <release>stable</release>
4854- <api>stable</api>
4855- </stability>
4856- <date>2002-04-16</date>
4857- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4858- <notes>* E_ALL fixes
4859-* fix HTTP response header parsing</notes>
4860- </release>
4861- <release>
4862- <version>
4863- <release>1.0.1</release>
4864- <api>1.0.1</api>
4865- </version>
4866- <stability>
4867- <release>stable</release>
4868- <api>stable</api>
4869- </stability>
4870- <date>2001-09-25</date>
4871- <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
4872- <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
4873-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
4874- </release>
4875- </changelog>
4876-</package>
4877-
4878-
4879-/**
4880- * Tests that properties of XML_RPC_Client get properly set
4881- *
4882- * Any individual tests that fail will have their name, expected result
4883- * and actual result printed out. So seeing no output when executing
4884- * this file is a good thing.
4885- *
4886- * Can be run via CLI or a web server.
4887- *
4888- * PHP versions 4 and 5
4889- *
4890- * LICENSE: This source file is subject to version 3.0 of the PHP license
4891- * that is available through the world-wide-web at the following URI:
4892- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
4893- * the PHP License and are unable to obtain it through the web, please
4894- * send a note to license@php.net so we can mail you a copy immediately.
4895- *
4896- * @category Web Services
4897- * @package XML_RPC
4898- * @author Daniel Convissor <danielc@php.net>
4899- * @copyright 2005 The PHP Group
4900- * @license http://www.php.net/license/3_0.txt PHP License
4901- * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
4902- * @link http://pear.php.net/package/XML_RPC
4903- * @since File available since Release 1.2
4904- */
4905-
4906-/*
4907- * If the package version number is found in the left hand
4908- * portion of the if() expression below, that means this file has
4909- * come from the PEAR installer. Therefore, let's test the
4910- * installed version of XML_RPC which should be in the include path.
4911- *
4912- * If the version has not been substituted in the if() expression,
4913- * this file has likely come from a CVS checkout or a .tar file.
4914- * Therefore, we'll assume the tests should use the version of
4915- * XML_RPC that has come from there as well.
4916- */
4917-if ('1.3.1' != '@'.'package_version'.'@') {
4918- /**
4919- * Get the needed class from the PEAR installation
4920- */
4921- require_once 'XML/RPC.php';
4922-} else {
4923- /**
4924- * Get the needed class from the parent directory
4925- */
4926- require_once '../RPC.php';
4927-}
4928-
4929-/**
4930- * Compare the test result to the expected result
4931- *
4932- * If the test fails, echo out the results.
4933- *
4934- * @param array $expect the array of object properties you expect
4935- * from the test
4936- * @param object $actual the object results from the test
4937- * @param string $test_name the name of the test
4938- *
4939- * @return void
4940- */
4941-function compare($expect, $actual, $test_name) {
4942- $actual = get_object_vars($actual);
4943- if (count(array_diff($actual, $expect))) {
4944- echo "$test_name failed.\nExpect: ";
4945- print_r($expect);
4946- echo "Actual: ";
4947- print_r($actual);
4948- echo "\n";
4949- }
4950-}
4951-
4952-if (php_sapi_name() != 'cli') {
4953- echo "<pre>\n";
4954-}
4955-
4956-
4957-$x = array(
4958- 'path' => 'thepath',
4959- 'server' => 'theserver',
4960- 'protocol' => 'http://',
4961- 'port' => 80,
4962- 'proxy' => '',
4963- 'proxy_protocol' => 'http://',
4964- 'proxy_port' => 8080,
4965- 'proxy_user' => '',
4966- 'proxy_pass' => '',
4967- 'errno' => 0,
4968- 'errstring' => '',
4969- 'debug' => 0,
4970- 'username' => '',
4971- 'password' => '',
4972-);
4973-$c = new XML_RPC_Client('thepath', 'theserver');
4974-compare($x, $c, 'defaults');
4975-
4976-$x = array(
4977- 'path' => 'thepath',
4978- 'server' => 'theserver',
4979- 'protocol' => 'http://',
4980- 'port' => 80,
4981- 'proxy' => '',
4982- 'proxy_protocol' => 'http://',
4983- 'proxy_port' => 8080,
4984- 'proxy_user' => '',
4985- 'proxy_pass' => '',
4986- 'errno' => 0,
4987- 'errstring' => '',
4988- 'debug' => 0,
4989- 'username' => '',
4990- 'password' => '',
4991-);
4992-$c = new XML_RPC_Client('thepath', 'http://theserver');
4993-compare($x, $c, 'defaults with http');
4994-
4995-$x = array(
4996- 'path' => 'thepath',
4997- 'server' => 'theserver',
4998- 'protocol' => 'ssl://',
4999- 'port' => 443,
5000- 'proxy' => '',
5001- 'proxy_protocol' => 'http://',
5002- 'proxy_port' => 8080,
5003- 'proxy_user' => '',
5004- 'proxy_pass' => '',
5005- 'errno' => 0,
5006- 'errstring' => '',
5007- 'debug' => 0,
5008- 'username' => '',
5009- 'password' => '',
5010-);
5011-$c = new XML_RPC_Client('thepath', 'https://theserver');
5012-compare($x, $c, 'defaults with https');
5013-
5014-$x = array(
5015- 'path' => 'thepath',
5016- 'server' => 'theserver',
5017- 'protocol' => 'ssl://',
5018- 'port' => 443,
5019- 'proxy' => '',
5020- 'proxy_protocol' => 'http://',
5021- 'proxy_port' => 8080,
5022- 'proxy_user' => '',
5023- 'proxy_pass' => '',
5024- 'errno' => 0,
5025- 'errstring' => '',
5026- 'debug' => 0,
5027- 'username' => '',
5028- 'password' => '',
5029-);
5030-$c = new XML_RPC_Client('thepath', 'ssl://theserver');
5031-compare($x, $c, 'defaults with ssl');
5032-
5033-
5034-$x = array(
5035- 'path' => 'thepath',
5036- 'server' => 'theserver',
5037- 'protocol' => 'http://',
5038- 'port' => 65,
5039- 'proxy' => '',
5040- 'proxy_protocol' => 'http://',
5041- 'proxy_port' => 8080,
5042- 'proxy_user' => '',
5043- 'proxy_pass' => '',
5044- 'errno' => 0,
5045- 'errstring' => '',
5046- 'debug' => 0,
5047- 'username' => '',
5048- 'password' => '',
5049-);
5050-$c = new XML_RPC_Client('thepath', 'theserver', 65);
5051-compare($x, $c, 'port 65');
5052-
5053-$x = array(
5054- 'path' => 'thepath',
5055- 'server' => 'theserver',
5056- 'protocol' => 'http://',
5057- 'port' => 65,
5058- 'proxy' => '',
5059- 'proxy_protocol' => 'http://',
5060- 'proxy_port' => 8080,
5061- 'proxy_user' => '',
5062- 'proxy_pass' => '',
5063- 'errno' => 0,
5064- 'errstring' => '',
5065- 'debug' => 0,
5066- 'username' => '',
5067- 'password' => '',
5068-);
5069-$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
5070-compare($x, $c, 'port 65 with http');
5071-
5072-$x = array(
5073- 'path' => 'thepath',
5074- 'server' => 'theserver',
5075- 'protocol' => 'ssl://',
5076- 'port' => 65,
5077- 'proxy' => '',
5078- 'proxy_protocol' => 'http://',
5079- 'proxy_port' => 8080,
5080- 'proxy_user' => '',
5081- 'proxy_pass' => '',
5082- 'errno' => 0,
5083- 'errstring' => '',
5084- 'debug' => 0,
5085- 'username' => '',
5086- 'password' => '',
5087-);
5088-$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
5089-compare($x, $c, 'port 65 with https');
5090-
5091-$x = array(
5092- 'path' => 'thepath',
5093- 'server' => 'theserver',
5094- 'protocol' => 'ssl://',
5095- 'port' => 65,
5096- 'proxy' => '',
5097- 'proxy_protocol' => 'http://',
5098- 'proxy_port' => 8080,
5099- 'proxy_user' => '',
5100- 'proxy_pass' => '',
5101- 'errno' => 0,
5102- 'errstring' => '',
5103- 'debug' => 0,
5104- 'username' => '',
5105- 'password' => '',
5106-);
5107-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
5108-compare($x, $c, 'port 65 with ssl');
5109-
5110-
5111-$x = array(
5112- 'path' => 'thepath',
5113- 'server' => 'theserver',
5114- 'protocol' => 'http://',
5115- 'port' => 80,
5116- 'proxy' => 'theproxy',
5117- 'proxy_protocol' => 'http://',
5118- 'proxy_port' => 8080,
5119- 'proxy_user' => '',
5120- 'proxy_pass' => '',
5121- 'errno' => 0,
5122- 'errstring' => '',
5123- 'debug' => 0,
5124- 'username' => '',
5125- 'password' => '',
5126-);
5127-$c = new XML_RPC_Client('thepath', 'theserver', 0,
5128- 'theproxy');
5129-compare($x, $c, 'defaults proxy');
5130-
5131-$x = array(
5132- 'path' => 'thepath',
5133- 'server' => 'theserver',
5134- 'protocol' => 'http://',
5135- 'port' => 80,
5136- 'proxy' => 'theproxy',
5137- 'proxy_protocol' => 'http://',
5138- 'proxy_port' => 8080,
5139- 'proxy_user' => '',
5140- 'proxy_pass' => '',
5141- 'errno' => 0,
5142- 'errstring' => '',
5143- 'debug' => 0,
5144- 'username' => '',
5145- 'password' => '',
5146-);
5147-$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
5148- 'http://theproxy');
5149-compare($x, $c, 'defaults with http proxy');
5150-
5151-$x = array(
5152- 'path' => 'thepath',
5153- 'server' => 'theserver',
5154- 'protocol' => 'ssl://',
5155- 'port' => 443,
5156- 'proxy' => 'theproxy',
5157- 'proxy_protocol' => 'ssl://',
5158- 'proxy_port' => 443,
5159- 'proxy_user' => '',
5160- 'proxy_pass' => '',
5161- 'errno' => 0,
5162- 'errstring' => '',
5163- 'debug' => 0,
5164- 'username' => '',
5165- 'password' => '',
5166-);
5167-$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
5168- 'https://theproxy');
5169-compare($x, $c, 'defaults with https proxy');
5170-
5171-$x = array(
5172- 'path' => 'thepath',
5173- 'server' => 'theserver',
5174- 'protocol' => 'ssl://',
5175- 'port' => 443,
5176- 'proxy' => 'theproxy',
5177- 'proxy_protocol' => 'ssl://',
5178- 'proxy_port' => 443,
5179- 'proxy_user' => '',
5180- 'proxy_pass' => '',
5181- 'errno' => 0,
5182- 'errstring' => '',
5183- 'debug' => 0,
5184- 'username' => '',
5185- 'password' => '',
5186-);
5187-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
5188- 'ssl://theproxy');
5189-compare($x, $c, 'defaults with ssl proxy');
5190-
5191-
5192-$x = array(
5193- 'path' => 'thepath',
5194- 'server' => 'theserver',
5195- 'protocol' => 'http://',
5196- 'port' => 65,
5197- 'proxy' => 'theproxy',
5198- 'proxy_protocol' => 'http://',
5199- 'proxy_port' => 6565,
5200- 'proxy_user' => '',
5201- 'proxy_pass' => '',
5202- 'errno' => 0,
5203- 'errstring' => '',
5204- 'debug' => 0,
5205- 'username' => '',
5206- 'password' => '',
5207-);
5208-$c = new XML_RPC_Client('thepath', 'theserver', 65,
5209- 'theproxy', 6565);
5210-compare($x, $c, 'port 65 proxy 6565');
5211-
5212-$x = array(
5213- 'path' => 'thepath',
5214- 'server' => 'theserver',
5215- 'protocol' => 'http://',
5216- 'port' => 65,
5217- 'proxy' => 'theproxy',
5218- 'proxy_protocol' => 'http://',
5219- 'proxy_port' => 6565,
5220- 'proxy_user' => '',
5221- 'proxy_pass' => '',
5222- 'errno' => 0,
5223- 'errstring' => '',
5224- 'debug' => 0,
5225- 'username' => '',
5226- 'password' => '',
5227-);
5228-$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
5229- 'http://theproxy', 6565);
5230-compare($x, $c, 'port 65 with http proxy 6565');
5231-
5232-$x = array(
5233- 'path' => 'thepath',
5234- 'server' => 'theserver',
5235- 'protocol' => 'ssl://',
5236- 'port' => 65,
5237- 'proxy' => 'theproxy',
5238- 'proxy_protocol' => 'ssl://',
5239- 'proxy_port' => 6565,
5240- 'proxy_user' => '',
5241- 'proxy_pass' => '',
5242- 'errno' => 0,
5243- 'errstring' => '',
5244- 'debug' => 0,
5245- 'username' => '',
5246- 'password' => '',
5247-);
5248-$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
5249- 'https://theproxy', 6565);
5250-compare($x, $c, 'port 65 with https proxy 6565');
5251-
5252-$x = array(
5253- 'path' => 'thepath',
5254- 'server' => 'theserver',
5255- 'protocol' => 'ssl://',
5256- 'port' => 65,
5257- 'proxy' => 'theproxy',
5258- 'proxy_protocol' => 'ssl://',
5259- 'proxy_port' => 6565,
5260- 'proxy_user' => '',
5261- 'proxy_pass' => '',
5262- 'errno' => 0,
5263- 'errstring' => '',
5264- 'debug' => 0,
5265- 'username' => '',
5266- 'password' => '',
5267-);
5268-$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
5269- 'ssl://theproxy', 6565);
5270-compare($x, $c, 'port 65 with ssl proxy 6565');
5271-
5272-
5273-$x = array(
5274- 'path' => 'thepath',
5275- 'server' => 'theserver',
5276- 'protocol' => 'ssl://',
5277- 'port' => 443,
5278- 'proxy' => 'theproxy',
5279- 'proxy_protocol' => 'ssl://',
5280- 'proxy_port' => 443,
5281- 'proxy_user' => '',
5282- 'proxy_pass' => '',
5283- 'errno' => 0,
5284- 'errstring' => '',
5285- 'debug' => 0,
5286- 'username' => '',
5287- 'password' => '',
5288-);
5289-$c = new XML_RPC_Client('thepath', 'theserver', 443,
5290- 'theproxy', 443);
5291-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
5292-
5293-$x = array(
5294- 'path' => 'thepath',
5295- 'server' => 'theserver',
5296- 'protocol' => 'http://',
5297- 'port' => 80,
5298- 'proxy' => 'theproxy',
5299- 'proxy_protocol' => 'ssl://',
5300- 'proxy_port' => 6565,
5301- 'proxy_user' => '',
5302- 'proxy_pass' => '',
5303- 'errno' => 0,
5304- 'errstring' => '',
5305- 'debug' => 0,
5306- 'username' => '',
5307- 'password' => '',
5308-);
5309-$c = new XML_RPC_Client('thepath', 'theserver', 0,
5310- 'ssl://theproxy', 6565);
5311-compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
5312-
5313-
5314-/*
5315- * If the package version number is found in the left hand
5316- * portion of the if() expression below, that means this file has
5317- * come from the PEAR installer. Therefore, let's test the
5318- * installed version of XML_RPC which should be in the include path.
5319- *
5320- * If the version has not been substituted in the if() expression,
5321- * this file has likely come from a CVS checkout or a .tar file.
5322- * Therefore, we'll assume the tests should use the version of
5323- * XML_RPC that has come from there as well.
5324- */
5325-if ('1.3.1' != '@'.'package_version'.'@') {
5326- /**
5327- * Get the needed class from the PEAR installation
5328- */
5329- require_once 'XML/RPC/Dump.php';
5330-} else {
5331- /**
5332- * Get the needed class from the parent directory
5333- */
5334- require_once '../Dump.php';
5335-}
5336-
5337-$val = new XML_RPC_Value(array(
5338- 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
5339- 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
5340- 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
5341- 'error' =>'string',
5342- 'arkey' => new XML_RPC_Value( array(
5343- new XML_RPC_Value('simple string'),
5344- new XML_RPC_Value(12345, 'int')
5345- ), 'array')
5346- )
5347- ,'struct');
5348-
5349-XML_RPC_Dump($val);
5350-
5351-echo '==============' . "\r\n";
5352-$val2 = new XML_RPC_Value(44353, 'int');
5353-XML_RPC_Dump($val2);
5354-
5355-echo '==============' . "\r\n";
5356-$val3 = new XML_RPC_Value('this should be a string', 'string');
5357-XML_RPC_Dump($val3);
5358-
5359-echo '==============' . "\r\n";
5360-$val4 = new XML_RPC_Value(true, 'boolean');
5361-XML_RPC_Dump($val4);
5362-
5363-
5364-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5365-
5366-/**
5367- * Function and class to dump XML_RPC_Value objects in a nice way
5368- *
5369- * Should be helpful as a normal var_dump(..) displays all internals which
5370- * doesn't really give you an overview due to too much information.
5371- *
5372- * @category Web Services
5373- * @package XML_RPC
5374- * @author Christian Weiske <cweiske@php.net>
5375- * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
5376- * @link http://pear.php.net/package/XML_RPC
5377- */
5378-
5379-
5380-/**
5381- * Pull in the XML_RPC class
5382- */
5383-require_once 'XML/RPC.php';
5384-
5385-
5386-/**
5387- * Generates the dump of the XML_RPC_Value and echoes it
5388- *
5389- * @param object $value the XML_RPC_Value object to dump
5390- *
5391- * @return void
5392- */
5393-function XML_RPC_Dump($value)
5394-{
5395- $dumper = new XML_RPC_Dump();
5396- echo $dumper->generateDump($value);
5397-}
5398-
5399-
5400-/**
5401- * Class which generates a dump of a XML_RPC_Value object
5402- *
5403- * @category Web Services
5404- * @package XML_RPC
5405- * @author Christian Weiske <cweiske@php.net>
5406- * @version Release: 1.3.1
5407- * @link http://pear.php.net/package/XML_RPC
5408- */
5409-class XML_RPC_Dump
5410-{
5411- /**
5412- * The indentation array cache
5413- * @var array
5414- */
5415- var $arIndent = array();
5416-
5417- /**
5418- * The spaces used for indenting the XML
5419- * @var string
5420- */
5421- var $strBaseIndent = ' ';
5422-
5423- /**
5424- * Returns the dump in XML format without printing it out
5425- *
5426- * @param object $value the XML_RPC_Value object to dump
5427- * @param int $nLevel the level of indentation
5428- *
5429- * @return string the dump
5430- */
5431- function generateDump($value, $nLevel = 0)
5432- {
5433- if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
5434- require_once 'PEAR.php';
5435- PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
5436- 0, PEAR_ERROR_PRINT);
5437- if (is_object($value)) {
5438- $strType = get_class($value);
5439- } else {
5440- $strType = gettype($value);
5441- }
5442- return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
5443- . $strType . "\r\n";
5444- }
5445-
5446- switch ($value->kindOf()) {
5447- case 'struct':
5448- $ret = $this->genStruct($value, $nLevel);
5449- break;
5450- case 'array':
5451- $ret = $this->genArray($value, $nLevel);
5452- break;
5453- case 'scalar':
5454- $ret = $this->genScalar($value->scalarval(), $nLevel);
5455- break;
5456- default:
5457- require_once 'PEAR.php';
5458- PEAR::raiseError('Illegal type "' . $value->kindOf()
5459- . '" in XML_RPC_Value' . "\r\n", 0,
5460- PEAR_ERROR_PRINT);
5461- }
5462-
5463- return $ret;
5464- }
5465-
5466- /**
5467- * Returns the scalar value dump
5468- *
5469- * @param object $value the scalar XML_RPC_Value object to dump
5470- * @param int $nLevel the level of indentation
5471- *
5472- * @return string Dumped version of the scalar value
5473- */
5474- function genScalar($value, $nLevel)
5475- {
5476- if (gettype($value) == 'object') {
5477- $strClass = ' ' . get_class($value);
5478- } else {
5479- $strClass = '';
5480- }
5481- return $this->getIndent($nLevel) . gettype($value) . $strClass
5482- . ' ' . $value . "\r\n";
5483- }
5484-
5485- /**
5486- * Returns the dump of a struct
5487- *
5488- * @param object $value the struct XML_RPC_Value object to dump
5489- * @param int $nLevel the level of indentation
5490- *
5491- * @return string Dumped version of the scalar value
5492- */
5493- function genStruct($value, $nLevel)
5494- {
5495- $value->structreset();
5496- $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
5497- while (list($key, $keyval) = $value->structeach()) {
5498- $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
5499- $strOutput .= $this->generateDump($keyval, $nLevel + 2);
5500- }
5501- return $strOutput;
5502- }
5503-
5504- /**
5505- * Returns the dump of an array
5506- *
5507- * @param object $value the array XML_RPC_Value object to dump
5508- * @param int $nLevel the level of indentation
5509- *
5510- * @return string Dumped version of the scalar value
5511- */
5512- function genArray($value, $nLevel)
5513- {
5514- $nSize = $value->arraysize();
5515- $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
5516- for($nA = 0; $nA < $nSize; $nA++) {
5517- $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
5518- $strOutput .= $this->generateDump($value->arraymem($nA),
5519- $nLevel + 2);
5520- }
5521- return $strOutput;
5522- }
5523-
5524- /**
5525- * Returns the indent for a specific level and caches it for faster use
5526- *
5527- * @param int $nLevel the level
5528- *
5529- * @return string the indented string
5530- */
5531- function getIndent($nLevel)
5532- {
5533- if (!isset($this->arIndent[$nLevel])) {
5534- $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
5535- }
5536- return $this->arIndent[$nLevel];
5537- }
5538-}
5539-
5540-/*
5541- * Local variables:
5542- * tab-width: 4
5543- * c-basic-offset: 4
5544- * c-hanging-comment-ender-p: nil
5545- * End:
5546- */
5547-
5548-?>
5549-
5550-
5551-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5552-
5553-/**
5554- * PHP implementation of the XML-RPC protocol
5555- *
5556- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
5557- * It has support for HTTP transport, proxies and authentication.
5558- *
5559- * PHP versions 4 and 5
5560- *
5561- * LICENSE: License is granted to use or modify this software
5562- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
5563- * copyright of the author is preserved in any distributed or derivative work.
5564- *
5565- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
5566- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5567- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5568- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5569- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5570- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5571- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5572- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5573- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5574- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5575- *
5576- * @category Web Services
5577- * @package XML_RPC
5578- * @author Edd Dumbill <edd@usefulinc.com>
5579- * @author Stig Bakken <stig@php.net>
5580- * @author Martin Jansen <mj@php.net>
5581- * @author Daniel Convissor <danielc@php.net>
5582- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
5583- * @version CVS: $Id: RPC.php,v 1.74 2005/05/09 20:51:54 danielc Exp $
5584- * @link http://pear.php.net/package/XML_RPC
5585- */
5586-
5587-
5588-if (!function_exists('xml_parser_create')) {
5589- PEAR::loadExtension('xml');
5590-}
5591-
5592-/**#@+
5593- * Error constants
5594- */
5595-/**
5596- * Parameter values don't match parameter types
5597- */
5598-define('XML_RPC_ERROR_INVALID_TYPE', 101);
5599-/**
5600- * Parameter declared to be numeric but the values are not
5601- */
5602-define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
5603-/**
5604- * Communication error
5605- */
5606-define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
5607-/**
5608- * The array or struct has already been started
5609- */
5610-define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
5611-/**
5612- * Incorrect parameters submitted
5613- */
5614-define('XML_RPC_ERROR_INCORRECT_PARAMS', 105);
5615-/**
5616- * Programming error by developer
5617- */
5618-define('XML_RPC_ERROR_PROGRAMMING', 106);
5619-/**#@-*/
5620-
5621-
5622-/**
5623- * Data types
5624- * @global string $GLOBALS['XML_RPC_I4']
5625- */
5626-$GLOBALS['XML_RPC_I4'] = 'i4';
5627-
5628-/**
5629- * Data types
5630- * @global string $GLOBALS['XML_RPC_Int']
5631- */
5632-$GLOBALS['XML_RPC_Int'] = 'int';
5633-
5634-/**
5635- * Data types
5636- * @global string $GLOBALS['XML_RPC_Boolean']
5637- */
5638-$GLOBALS['XML_RPC_Boolean'] = 'boolean';
5639-
5640-/**
5641- * Data types
5642- * @global string $GLOBALS['XML_RPC_Double']
5643- */
5644-$GLOBALS['XML_RPC_Double'] = 'double';
5645-
5646-/**
5647- * Data types
5648- * @global string $GLOBALS['XML_RPC_String']
5649- */
5650-$GLOBALS['XML_RPC_String'] = 'string';
5651-
5652-/**
5653- * Data types
5654- * @global string $GLOBALS['XML_RPC_DateTime']
5655- */
5656-$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
5657-
5658-/**
5659- * Data types
5660- * @global string $GLOBALS['XML_RPC_Base64']
5661- */
5662-$GLOBALS['XML_RPC_Base64'] = 'base64';
5663-
5664-/**
5665- * Data types
5666- * @global string $GLOBALS['XML_RPC_Array']
5667- */
5668-$GLOBALS['XML_RPC_Array'] = 'array';
5669-
5670-/**
5671- * Data types
5672- * @global string $GLOBALS['XML_RPC_Struct']
5673- */
5674-$GLOBALS['XML_RPC_Struct'] = 'struct';
5675-
5676-
5677-/**
5678- * Data type meta-types
5679- * @global array $GLOBALS['XML_RPC_Types']
5680- */
5681-$GLOBALS['XML_RPC_Types'] = array(
5682- $GLOBALS['XML_RPC_I4'] => 1,
5683- $GLOBALS['XML_RPC_Int'] => 1,
5684- $GLOBALS['XML_RPC_Boolean'] => 1,
5685- $GLOBALS['XML_RPC_String'] => 1,
5686- $GLOBALS['XML_RPC_Double'] => 1,
5687- $GLOBALS['XML_RPC_DateTime'] => 1,
5688- $GLOBALS['XML_RPC_Base64'] => 1,
5689- $GLOBALS['XML_RPC_Array'] => 2,
5690- $GLOBALS['XML_RPC_Struct'] => 3,
5691-);
5692-
5693-
5694-/**
5695- * Error message numbers
5696- * @global array $GLOBALS['XML_RPC_err']
5697- */
5698-$GLOBALS['XML_RPC_err'] = array(
5699- 'unknown_method' => 1,
5700- 'invalid_return' => 2,
5701- 'incorrect_params' => 3,
5702- 'introspect_unknown' => 4,
5703- 'http_error' => 5,
5704- 'not_response_object' => 6,
5705-);
5706-
5707-/**
5708- * Error message strings
5709- * @global array $GLOBALS['XML_RPC_str']
5710- */
5711-$GLOBALS['XML_RPC_str'] = array(
5712- 'unknown_method' => 'Unknown method',
5713- 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
5714- 'incorrect_params' => 'Incorrect parameters passed to method',
5715- 'introspect_unknown' => 'Can\'t introspect: method unknown',
5716- 'http_error' => 'Didn\'t receive 200 OK from remote server.',
5717- 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.',
5718-);
5719-
5720-
5721-/**
5722- * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
5723- * @global string $GLOBALS['XML_RPC_defencoding']
5724- */
5725-$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
5726-
5727-/**
5728- * User error codes start at 800
5729- * @global int $GLOBALS['XML_RPC_erruser']
5730- */
5731-$GLOBALS['XML_RPC_erruser'] = 800;
5732-
5733-/**
5734- * XML parse error codes start at 100
5735- * @global int $GLOBALS['XML_RPC_errxml']
5736- */
5737-$GLOBALS['XML_RPC_errxml'] = 100;
5738-
5739-
5740-/**
5741- * Compose backslashes for escaping regexp
5742- * @global string $GLOBALS['XML_RPC_backslash']
5743- */
5744-$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
5745-
5746-
5747-/**
5748- * Stores state during parsing
5749- *
5750- * quick explanation of components:
5751- * + st = builds up a string for evaluation
5752- * + ac = accumulates values
5753- * + qt = decides if quotes are needed for evaluation
5754- * + cm = denotes struct or array (comma needed)
5755- * + isf = indicates a fault
5756- * + lv = indicates "looking for a value": implements the logic
5757- * to allow values with no types to be strings
5758- * + params = stores parameters in method calls
5759- * + method = stores method name
5760- *
5761- * @global array $GLOBALS['XML_RPC_xh']
5762- */
5763-$GLOBALS['XML_RPC_xh'] = array();
5764-
5765-
5766-/**
5767- * Start element handler for the XML parser
5768- *
5769- * @return void
5770- */
5771-function XML_RPC_se($parser_resource, $name, $attrs)
5772-{
5773- global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
5774- $parser = (int) $parser_resource;
5775-
5776- switch ($name) {
5777- case 'STRUCT':
5778- case 'ARRAY':
5779- $XML_RPC_xh[$parser]['st'] .= 'array(';
5780- $XML_RPC_xh[$parser]['cm']++;
5781- // this last line turns quoting off
5782- // this means if we get an empty array we'll
5783- // simply get a bit of whitespace in the eval
5784- $XML_RPC_xh[$parser]['qt'] = 0;
5785- break;
5786-
5787- case 'NAME':
5788- $XML_RPC_xh[$parser]['st'] .= '"';
5789- $XML_RPC_xh[$parser]['ac'] = '';
5790- break;
5791-
5792- case 'FAULT':
5793- $XML_RPC_xh[$parser]['isf'] = 1;
5794- break;
5795-
5796- case 'PARAM':
5797- $XML_RPC_xh[$parser]['st'] = '';
5798- break;
5799-
5800- case 'VALUE':
5801- $XML_RPC_xh[$parser]['st'] .= 'new XML_RPC_Value(';
5802- $XML_RPC_xh[$parser]['lv'] = 1;
5803- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
5804- $XML_RPC_xh[$parser]['ac'] = '';
5805- $XML_RPC_xh[$parser]['qt'] = 0;
5806- // look for a value: if this is still 1 by the
5807- // time we reach the first data segment then the type is string
5808- // by implication and we need to add in a quote
5809- break;
5810-
5811- case 'I4':
5812- case 'INT':
5813- case 'STRING':
5814- case 'BOOLEAN':
5815- case 'DOUBLE':
5816- case 'DATETIME.ISO8601':
5817- case 'BASE64':
5818- $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
5819-
5820- if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
5821- $XML_RPC_xh[$parser]['qt'] = 1;
5822-
5823- if ($name == 'DATETIME.ISO8601') {
5824- $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
5825- }
5826-
5827- } elseif ($name == 'BASE64') {
5828- $XML_RPC_xh[$parser]['qt'] = 2;
5829- } else {
5830- // No quoting is required here -- but
5831- // at the end of the element we must check
5832- // for data format errors.
5833- $XML_RPC_xh[$parser]['qt'] = 0;
5834- }
5835- break;
5836-
5837- case 'MEMBER':
5838- $XML_RPC_xh[$parser]['ac'] = '';
5839- }
5840-
5841- if ($name != 'VALUE') {
5842- $XML_RPC_xh[$parser]['lv'] = 0;
5843- }
5844-}
5845-
5846-/**
5847- * End element handler for the XML parser
5848- *
5849- * @return void
5850- */
5851-function XML_RPC_ee($parser_resource, $name)
5852-{
5853- global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
5854- $parser = (int) $parser_resource;
5855-
5856- switch ($name) {
5857- case 'STRUCT':
5858- case 'ARRAY':
5859- if ($XML_RPC_xh[$parser]['cm']
5860- && substr($XML_RPC_xh[$parser]['st'], -1) == ',')
5861- {
5862- $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'], 0, -1);
5863- }
5864-
5865- $XML_RPC_xh[$parser]['st'] .= ')';
5866- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
5867- $XML_RPC_xh[$parser]['cm']--;
5868- break;
5869-
5870- case 'NAME':
5871- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . '" => ';
5872- break;
5873-
5874- case 'BOOLEAN':
5875- // special case here: we translate boolean 1 or 0 into PHP
5876- // constants true or false
5877- if ($XML_RPC_xh[$parser]['ac'] == '1') {
5878- $XML_RPC_xh[$parser]['ac'] = 'true';
5879- } else {
5880- $XML_RPC_xh[$parser]['ac'] = 'false';
5881- }
5882-
5883- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
5884- // Drop through intentionally.
5885-
5886- case 'I4':
5887- case 'INT':
5888- case 'STRING':
5889- case 'DOUBLE':
5890- case 'DATETIME.ISO8601':
5891- case 'BASE64':
5892- if ($XML_RPC_xh[$parser]['qt'] == 1) {
5893- // we use double quotes rather than single so backslashification works OK
5894- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
5895- } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
5896- $XML_RPC_xh[$parser]['st'] .= 'base64_decode("'
5897- . $XML_RPC_xh[$parser]['ac'] . '")';
5898- } elseif ($name == 'BOOLEAN') {
5899- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
5900- } else {
5901- // we have an I4, INT or a DOUBLE
5902- // we must check that only 0123456789-.<space> are characters here
5903- if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
5904- XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
5905- XML_RPC_ERROR_NON_NUMERIC_FOUND);
5906- $XML_RPC_xh[$parser]['st'] .= 'XML_RPC_ERROR_NON_NUMERIC_FOUND';
5907- } else {
5908- // it's ok, add it on
5909- $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
5910- }
5911- }
5912-
5913- $XML_RPC_xh[$parser]['ac'] = '';
5914- $XML_RPC_xh[$parser]['qt'] = 0;
5915- $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
5916- break;
5917-
5918- case 'VALUE':
5919- // deal with a string value
5920- if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
5921- $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
5922-
5923- $XML_RPC_xh[$parser]['st'] .= '"' . $XML_RPC_xh[$parser]['ac'] . '"';
5924- }
5925-
5926- // This if () detects if no scalar was inside <VALUE></VALUE>
5927- // and pads an empty "".
5928- if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
5929- $XML_RPC_xh[$parser]['st'] .= '""';
5930- }
5931- $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
5932- if ($XML_RPC_xh[$parser]['cm']) {
5933- $XML_RPC_xh[$parser]['st'] .= ',';
5934- }
5935- break;
5936-
5937- case 'MEMBER':
5938- $XML_RPC_xh[$parser]['ac'] = '';
5939- $XML_RPC_xh[$parser]['qt'] = 0;
5940- break;
5941-
5942- case 'DATA':
5943- $XML_RPC_xh[$parser]['ac'] = '';
5944- $XML_RPC_xh[$parser]['qt'] = 0;
5945- break;
5946-
5947- case 'PARAM':
5948- $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
5949- break;
5950-
5951- case 'METHODNAME':
5952- case 'RPCMETHODNAME':
5953- $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
5954- $XML_RPC_xh[$parser]['ac']);
5955- break;
5956- }
5957-
5958- // if it's a valid type name, set the type
5959- if (isset($XML_RPC_Types[strtolower($name)])) {
5960- $XML_RPC_xh[$parser]['vt'] = strtolower($name);
5961- }
5962-}
5963-
5964-/**
5965- * Character data handler for the XML parser
5966- *
5967- * @return void
5968- */
5969-function XML_RPC_cd($parser_resource, $data)
5970-{
5971- global $XML_RPC_xh, $XML_RPC_backslash;
5972- $parser = (int) $parser_resource;
5973-
5974- if ($XML_RPC_xh[$parser]['lv'] != 3) {
5975- // "lookforvalue==3" means that we've found an entire value
5976- // and should discard any further character data
5977-
5978- if ($XML_RPC_xh[$parser]['lv'] == 1) {
5979- // if we've found text and we're just in a <value> then
5980- // turn quoting on, as this will be a string
5981- $XML_RPC_xh[$parser]['qt'] = 1;
5982- // and say we've found a value
5983- $XML_RPC_xh[$parser]['lv'] = 2;
5984- }
5985-
5986- // replace characters that eval would
5987- // do special things with
5988- if (!isset($XML_RPC_xh[$parser]['ac'])) {
5989- $XML_RPC_xh[$parser]['ac'] = '';
5990- }
5991- $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
5992- str_replace('"', '\"', str_replace(chr(92),
5993- $XML_RPC_backslash, $data)));
5994- }
5995-}
5996-
5997-/**
5998- * The common methods and properties for all of the XML_RPC classes
5999- *
6000- * @category Web Services
6001- * @package XML_RPC
6002- * @author Edd Dumbill <edd@usefulinc.com>
6003- * @author Stig Bakken <stig@php.net>
6004- * @author Martin Jansen <mj@php.net>
6005- * @author Daniel Convissor <danielc@php.net>
6006- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
6007- * @version Release: 1.3.1
6008- * @link http://pear.php.net/package/XML_RPC
6009- */
6010-class XML_RPC_Base {
6011-
6012- /**
6013- * PEAR Error handling
6014- *
6015- * @return object PEAR_Error object
6016- */
6017- function raiseError($msg, $code)
6018- {
6019- include_once 'PEAR.php';
6020- if (is_object(@$this)) {
6021- return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
6022- } else {
6023- return PEAR::raiseError('XML_RPC: ' . $msg, $code);
6024- }
6025- }
6026-
6027- /**
6028- * Tell whether something is a PEAR_Error object
6029- *
6030- * @param mixed $value the item to check
6031- *
6032- * @return bool whether $value is a PEAR_Error object or not
6033- *
6034- * @access public
6035- */
6036- function isError($value)
6037- {
6038- return is_a($value, 'PEAR_Error');
6039- }
6040-}
6041-
6042-/**
6043- * The methods and properties for submitting XML RPC requests
6044- *
6045- * @category Web Services
6046- * @package XML_RPC
6047- * @author Edd Dumbill <edd@usefulinc.com>
6048- * @author Stig Bakken <stig@php.net>
6049- * @author Martin Jansen <mj@php.net>
6050- * @author Daniel Convissor <danielc@php.net>
6051- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
6052- * @version Release: 1.3.1
6053- * @link http://pear.php.net/package/XML_RPC
6054- */
6055-class XML_RPC_Client extends XML_RPC_Base {
6056-
6057- /**
6058- * The path and name of the RPC server script you want the request to go to
6059- * @var string
6060- */
6061- var $path = '';
6062-
6063- /**
6064- * The name of the remote server to connect to
6065- * @var string
6066- */
6067- var $server = '';
6068-
6069- /**
6070- * The protocol to use in contacting the remote server
6071- * @var string
6072- */
6073- var $protocol = 'http://';
6074-
6075- /**
6076- * The port for connecting to the remote server
6077- *
6078- * The default is 80 for http:// connections
6079- * and 443 for https:// and ssl:// connections.
6080- *
6081- * @var integer
6082- */
6083- var $port = 80;
6084-
6085- /**
6086- * A user name for accessing the RPC server
6087- * @var string
6088- * @see XML_RPC_Client::setCredentials()
6089- */
6090- var $username = '';
6091-
6092- /**
6093- * A password for accessing the RPC server
6094- * @var string
6095- * @see XML_RPC_Client::setCredentials()
6096- */
6097- var $password = '';
6098-
6099- /**
6100- * The name of the proxy server to use, if any
6101- * @var string
6102- */
6103- var $proxy = '';
6104-
6105- /**
6106- * The protocol to use in contacting the proxy server, if any
6107- * @var string
6108- */
6109- var $proxy_protocol = 'http://';
6110-
6111- /**
6112- * The port for connecting to the proxy server
6113- *
6114- * The default is 8080 for http:// connections
6115- * and 443 for https:// and ssl:// connections.
6116- *
6117- * @var integer
6118- */
6119- var $proxy_port = 8080;
6120-
6121- /**
6122- * A user name for accessing the proxy server
6123- * @var string
6124- */
6125- var $proxy_user = '';
6126-
6127- /**
6128- * A password for accessing the proxy server
6129- * @var string
6130- */
6131- var $proxy_pass = '';
6132-
6133- /**
6134- * The error number, if any
6135- * @var integer
6136- */
6137- var $errno = 0;
6138-
6139- /**
6140- * The error message, if any
6141- * @var string
6142- */
6143- var $errstring = '';
6144-
6145- /**
6146- * The current debug mode (1 = on, 0 = off)
6147- * @var integer
6148- */
6149- var $debug = 0;
6150-
6151- /**
6152- * The HTTP headers for the current request.
6153- * @var string
6154- */
6155- var $headers = '';
6156-
6157-
6158- /**
6159- * Sets the object's properties
6160- *
6161- * @param string $path the path and name of the RPC server script
6162- * you want the request to go to
6163- * @param string $server the URL of the remote server to connect to.
6164- * If this parameter doesn't specify a
6165- * protocol and $port is 443, ssl:// is
6166- * assumed.
6167- * @param integer $port a port for connecting to the remote server.
6168- * Defaults to 80 for http:// connections and
6169- * 443 for https:// and ssl:// connections.
6170- * @param string $proxy the URL of the proxy server to use, if any.
6171- * If this parameter doesn't specify a
6172- * protocol and $port is 443, ssl:// is
6173- * assumed.
6174- * @param integer $proxy_port a port for connecting to the remote server.
6175- * Defaults to 8080 for http:// connections and
6176- * 443 for https:// and ssl:// connections.
6177- * @param string $proxy_user a user name for accessing the proxy server
6178- * @param string $proxy_pass a password for accessing the proxy server
6179- *
6180- * @return void
6181- */
6182- function XML_RPC_Client($path, $server, $port = 0,
6183- $proxy = '', $proxy_port = 0,
6184- $proxy_user = '', $proxy_pass = '')
6185- {
6186- $this->path = $path;
6187- $this->proxy_user = $proxy_user;
6188- $this->proxy_pass = $proxy_pass;
6189-
6190- preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
6191- if ($match[1] == '') {
6192- if ($port == 443) {
6193- $this->server = $match[2];
6194- $this->protocol = 'ssl://';
6195- $this->port = 443;
6196- } else {
6197- $this->server = $match[2];
6198- if ($port) {
6199- $this->port = $port;
6200- }
6201- }
6202- } elseif ($match[1] == 'http://') {
6203- $this->server = $match[2];
6204- if ($port) {
6205- $this->port = $port;
6206- }
6207- } else {
6208- $this->server = $match[2];
6209- $this->protocol = 'ssl://';
6210- if ($port) {
6211- $this->port = $port;
6212- } else {
6213- $this->port = 443;
6214- }
6215- }
6216-
6217- if ($proxy) {
6218- preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
6219- if ($match[1] == '') {
6220- if ($proxy_port == 443) {
6221- $this->proxy = $match[2];
6222- $this->proxy_protocol = 'ssl://';
6223- $this->proxy_port = 443;
6224- } else {
6225- $this->proxy = $match[2];
6226- if ($proxy_port) {
6227- $this->proxy_port = $proxy_port;
6228- }
6229- }
6230- } elseif ($match[1] == 'http://') {
6231- $this->proxy = $match[2];
6232- if ($proxy_port) {
6233- $this->proxy_port = $proxy_port;
6234- }
6235- } else {
6236- $this->proxy = $match[2];
6237- $this->proxy_protocol = 'ssl://';
6238- if ($proxy_port) {
6239- $this->proxy_port = $proxy_port;
6240- } else {
6241- $this->proxy_port = 443;
6242- }
6243- }
6244- }
6245- }
6246-
6247- /**
6248- * Change the current debug mode
6249- *
6250- * @param int $in where 1 = on, 0 = off
6251- *
6252- * @return void
6253- */
6254- function setDebug($in)
6255- {
6256- if ($in) {
6257- $this->debug = 1;
6258- } else {
6259- $this->debug = 0;
6260- }
6261- }
6262-
6263- /**
6264- * Set username and password properties for connecting to the RPC server
6265- *
6266- * @param string $u the user name
6267- * @param string $p the password
6268- *
6269- * @return void
6270- *
6271- * @see XML_RPC_Client::$username, XML_RPC_Client::$password
6272- */
6273- function setCredentials($u, $p)
6274- {
6275- $this->username = $u;
6276- $this->password = $p;
6277- }
6278-
6279- /**
6280- * Transmit the RPC request via HTTP 1.0 protocol
6281- *
6282- * @param object $msg the XML_RPC_Message object
6283- * @param int $timeout how many seconds to wait for the request
6284- *
6285- * @return object an XML_RPC_Response object. 0 is returned if any
6286- * problems happen.
6287- *
6288- * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
6289- * XML_RPC_Client::setCredentials()
6290- */
6291- function send($msg, $timeout = 0)
6292- {
6293- if (strtolower(get_class($msg)) != 'xml_rpc_message') {
6294- $this->errstr = 'send()\'s $msg parameter must be an'
6295- . ' XML_RPC_Message object.';
6296- $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING);
6297- return 0;
6298- }
6299- $msg->debug = $this->debug;
6300- return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
6301- $timeout, $this->username,
6302- $this->password);
6303- }
6304-
6305- /**
6306- * Transmit the RPC request via HTTP 1.0 protocol
6307- *
6308- * Requests should be sent using XML_RPC_Client send() rather than
6309- * calling this method directly.
6310- *
6311- * @param object $msg the XML_RPC_Message object
6312- * @param string $server the server to send the request to
6313- * @param int $port the server port send the request to
6314- * @param int $timeout how many seconds to wait for the request
6315- * before giving up
6316- * @param string $username a user name for accessing the RPC server
6317- * @param string $password a password for accessing the RPC server
6318- *
6319- * @return object an XML_RPC_Response object. 0 is returned if any
6320- * problems happen.
6321- *
6322- * @access protected
6323- * @see XML_RPC_Client::send()
6324- */
6325- function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
6326- $username = '', $password = '')
6327- {
6328- /*
6329- * If we're using a proxy open a socket to the proxy server
6330- * instead to the xml-rpc server
6331- */
6332- if ($this->proxy) {
6333- if ($this->proxy_protocol == 'http://') {
6334- $protocol = '';
6335- } else {
6336- $protocol = $this->proxy_protocol;
6337- }
6338- if ($timeout > 0) {
6339- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
6340- $this->errno, $this->errstr, $timeout);
6341- } else {
6342- $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
6343- $this->errno, $this->errstr);
6344- }
6345- } else {
6346- if ($this->protocol == 'http://') {
6347- $protocol = '';
6348- } else {
6349- $protocol = $this->protocol;
6350- }
6351- if ($timeout > 0) {
6352- $fp = @fsockopen($protocol . $server, $port,
6353- $this->errno, $this->errstr, $timeout);
6354- } else {
6355- $fp = @fsockopen($protocol . $server, $port,
6356- $this->errno, $this->errstr);
6357- }
6358- }
6359-
6360- /*
6361- * Just raising the error without returning it is strange,
6362- * but keep it here for backwards compatibility.
6363- */
6364- if (!$fp && $this->proxy) {
6365- $this->raiseError('Connection to proxy server '
6366- . $this->proxy . ':' . $this->proxy_port
6367- . ' failed. ' . $this->errstr,
6368- XML_RPC_ERROR_CONNECTION_FAILED);
6369- return 0;
6370- } elseif (!$fp) {
6371- $this->raiseError('Connection to RPC server '
6372- . $server . ':' . $port
6373- . ' failed. ' . $this->errstr,
6374- XML_RPC_ERROR_CONNECTION_FAILED);
6375- return 0;
6376- }
6377-
6378- if ($timeout) {
6379- stream_set_timeout($fp, $timeout);
6380- }
6381-
6382- // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly
6383- if ($username != $this->username) {
6384- $this->setCredentials($username, $password);
6385- }
6386-
6387- // Only create the payload if it was not created previously
6388- if (empty($msg->payload)) {
6389- $msg->createPayload();
6390- }
6391- $this->createHeaders($msg);
6392-
6393- $op = $this->headers . "\r\n\r\n";
6394- $op .= $msg->payload;
6395-
6396- if (!fputs($fp, $op, strlen($op))) {
6397- $this->errstr = 'Write error';
6398- return 0;
6399- }
6400- $resp = $msg->parseResponseFile($fp);
6401-
6402- $meta = stream_get_meta_data($fp);
6403- if ($meta['timed_out']) {
6404- fclose($fp);
6405- $this->errstr = 'RPC server did not send response before timeout.';
6406- $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED);
6407- return 0;
6408- }
6409-
6410- fclose($fp);
6411- return $resp;
6412- }
6413-
6414- /**
6415- * Determines the HTTP headers and puts it in the $headers property
6416- *
6417- * @param object $msg the XML_RPC_Message object
6418- *
6419- * @return boolean TRUE if okay, FALSE if the message payload isn't set.
6420- *
6421- * @access protected
6422- */
6423- function createHeaders($msg)
6424- {
6425- if (empty($msg->payload)) {
6426- return false;
6427- }
6428- if ($this->proxy) {
6429- $this->headers = 'POST ' . $this->protocol . $this->server;
6430- if ($this->proxy_port) {
6431- $this->headers .= ':' . $this->port;
6432- }
6433- } else {
6434- $this->headers = 'POST ';
6435- }
6436- $this->headers .= $this->path. " HTTP/1.0\r\n";
6437-
6438- $this->headers .= "User-Agent: PEAR XML_RPC\r\n";
6439- $this->headers .= 'Host: ' . $this->server . "\r\n";
6440-
6441- if ($this->proxy && $this->proxy_user) {
6442- $this->headers .= 'Proxy-Authorization: Basic '
6443- . base64_encode("$this->proxy_user:$this->proxy_pass")
6444- . "\r\n";
6445- }
6446-
6447- // thanks to Grant Rauscher <grant7@firstworld.net> for this
6448- if ($this->username) {
6449- $this->headers .= 'Authorization: Basic '
6450- . base64_encode("$this->username:$this->password")
6451- . "\r\n";
6452- }
6453-
6454- $this->headers .= "Content-Type: text/xml\r\n";
6455- $this->headers .= 'Content-Length: ' . strlen($msg->payload);
6456- return true;
6457- }
6458-}
6459-
6460-/**
6461- * The methods and properties for interpreting responses to XML RPC requests
6462- *
6463- * @category Web Services
6464- * @package XML_RPC
6465- * @author Edd Dumbill <edd@usefulinc.com>
6466- * @author Stig Bakken <stig@php.net>
6467- * @author Martin Jansen <mj@php.net>
6468- * @author Daniel Convissor <danielc@php.net>
6469- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
6470- * @version Release: 1.3.1
6471- * @link http://pear.php.net/package/XML_RPC
6472- */
6473-class XML_RPC_Response extends XML_RPC_Base
6474-{
6475- var $xv;
6476- var $fn;
6477- var $fs;
6478- var $hdrs;
6479-
6480- /**
6481- * @return void
6482- */
6483- function XML_RPC_Response($val, $fcode = 0, $fstr = '')
6484- {
6485- if ($fcode != 0) {
6486- $this->fn = $fcode;
6487- $this->fs = htmlspecialchars($fstr);
6488- } else {
6489- $this->xv = $val;
6490- }
6491- }
6492-
6493- /**
6494- * @return int the error code
6495- */
6496- function faultCode()
6497- {
6498- if (isset($this->fn)) {
6499- return $this->fn;
6500- } else {
6501- return 0;
6502- }
6503- }
6504-
6505- /**
6506- * @return string the error string
6507- */
6508- function faultString()
6509- {
6510- return $this->fs;
6511- }
6512-
6513- /**
6514- * @return mixed the value
6515- */
6516- function value()
6517- {
6518- return $this->xv;
6519- }
6520-
6521- /**
6522- * @return string the error message in XML format
6523- */
6524- function serialize()
6525- {
6526- $rs = "<methodResponse>\n";
6527- if ($this->fn) {
6528- $rs .= "<fault>
6529- <value>
6530- <struct>
6531- <member>
6532- <name>faultCode</name>
6533- <value><int>" . $this->fn . "</int></value>
6534- </member>
6535- <member>
6536- <name>faultString</name>
6537- <value><string>" . $this->fs . "</string></value>
6538- </member>
6539- </struct>
6540- </value>
6541-</fault>";
6542- } else {
6543- $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
6544- "</param>\n</params>";
6545- }
6546- $rs .= "\n</methodResponse>";
6547- return $rs;
6548- }
6549-}
6550-
6551-/**
6552- * The methods and properties for composing XML RPC messages
6553- *
6554- * @category Web Services
6555- * @package XML_RPC
6556- * @author Edd Dumbill <edd@usefulinc.com>
6557- * @author Stig Bakken <stig@php.net>
6558- * @author Martin Jansen <mj@php.net>
6559- * @author Daniel Convissor <danielc@php.net>
6560- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
6561- * @version Release: 1.3.1
6562- * @link http://pear.php.net/package/XML_RPC
6563- */
6564-class XML_RPC_Message extends XML_RPC_Base
6565-{
6566- /**
6567- * The current debug mode (1 = on, 0 = off)
6568- * @var integer
6569- */
6570- var $debug = 0;
6571-
6572- /**
6573- * The encoding to be used for outgoing messages
6574- *
6575- * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
6576- *
6577- * @var string
6578- * @see XML_RPC_Message::setSendEncoding(),
6579- * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
6580- */
6581- var $send_encoding = '';
6582-
6583- /**
6584- * The method presently being evaluated
6585- * @var string
6586- */
6587- var $methodname = '';
6588-
6589- /**
6590- * @var array
6591- */
6592- var $params = array();
6593-
6594- /**
6595- * The XML message being generated
6596- * @var string
6597- */
6598- var $payload = '';
6599-
6600- /**
6601- * @return void
6602- */
6603- function XML_RPC_Message($meth, $pars = 0)
6604- {
6605- $this->methodname = $meth;
6606- if (is_array($pars) && sizeof($pars) > 0) {
6607- for ($i = 0; $i < sizeof($pars); $i++) {
6608- $this->addParam($pars[$i]);
6609- }
6610- }
6611- }
6612-
6613- /**
6614- * Produces the XML declaration including the encoding attribute
6615- *
6616- * The encoding is determined by this class' <var>$send_encoding</var>
6617- * property. If the <var>$send_encoding</var> property is not set, use
6618- * <var>$GLOBALS['XML_RPC_defencoding']</var>.
6619- *
6620- * @return string the XML declaration and <methodCall> element
6621- *
6622- * @see XML_RPC_Message::setSendEncoding(),
6623- * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
6624- */
6625- function xml_header()
6626- {
6627- global $XML_RPC_defencoding;
6628- if (!$this->send_encoding) {
6629- $this->send_encoding = $XML_RPC_defencoding;
6630- }
6631- return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
6632- . "\n<methodCall>\n";
6633- }
6634-
6635- /**
6636- * @return string the closing </methodCall> tag
6637- */
6638- function xml_footer()
6639- {
6640- return "</methodCall>\n";
6641- }
6642-
6643- /**
6644- * @return void
6645- *
6646- * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
6647- */
6648- function createPayload()
6649- {
6650- $this->payload = $this->xml_header();
6651- $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
6652- $this->payload .= "<params>\n";
6653- for ($i = 0; $i < sizeof($this->params); $i++) {
6654- $p = $this->params[$i];
6655- $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
6656- }
6657- $this->payload .= "</params>\n";
6658- $this->payload .= $this->xml_footer();
6659- $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
6660- }
6661-
6662- /**
6663- * @return string the name of the method
6664- */
6665- function method($meth = '')
6666- {
6667- if ($meth != '') {
6668- $this->methodname = $meth;
6669- }
6670- return $this->methodname;
6671- }
6672-
6673- /**
6674- * @return string the payload
6675- */
6676- function serialize()
6677- {
6678- $this->createPayload();
6679- return $this->payload;
6680- }
6681-
6682- /**
6683- * @return void
6684- */
6685- function addParam($par)
6686- {
6687- $this->params[] = $par;
6688- }
6689-
6690- /**
6691- * Obtains an XML_RPC_Value object for the given parameter
6692- *
6693- * @param int $i the index number of the parameter to obtain
6694- *
6695- * @return object the XML_RPC_Value object.
6696- * If the parameter doesn't exist, an XML_RPC_Response object.
6697- *
6698- * @since Returns XML_RPC_Response object on error since Release 1.3.0
6699- */
6700- function getParam($i)
6701- {
6702- global $XML_RPC_err, $XML_RPC_str;
6703-
6704- if (isset($this->params[$i])) {
6705- return $this->params[$i];
6706- } else {
6707- $this->raiseError('The submitted request did not contain this parameter',
6708- XML_RPC_ERROR_INCORRECT_PARAMS);
6709- return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
6710- $XML_RPC_str['incorrect_params']);
6711- }
6712- }
6713-
6714- /**
6715- * @return int the number of parameters
6716- */
6717- function getNumParams()
6718- {
6719- return sizeof($this->params);
6720- }
6721-
6722- /**
6723- * Sets the XML declaration's encoding attribute
6724- *
6725- * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
6726- *
6727- * @return void
6728- *
6729- * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
6730- * @since Method available since Release 1.2.0
6731- */
6732- function setSendEncoding($type)
6733- {
6734- $this->send_encoding = $type;
6735- }
6736-
6737- /**
6738- * Determine the XML's encoding via the encoding attribute
6739- * in the XML declaration
6740- *
6741- * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
6742- * or US-ASCII, $XML_RPC_defencoding will be returned.
6743- *
6744- * @param string $data the XML that will be parsed
6745- *
6746- * @return string the encoding to be used
6747- *
6748- * @link http://php.net/xml_parser_create
6749- * @since Method available since Release 1.2.0
6750- */
6751- function getEncoding($data)
6752- {
6753- global $XML_RPC_defencoding;
6754-
6755- if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
6756- $data, $match))
6757- {
6758- $match[1] = trim(strtoupper($match[1]));
6759- switch ($match[1]) {
6760- case 'ISO-8859-1':
6761- case 'UTF-8':
6762- case 'US-ASCII':
6763- return $match[1];
6764- break;
6765-
6766- default:
6767- return $XML_RPC_defencoding;
6768- }
6769- } else {
6770- return $XML_RPC_defencoding;
6771- }
6772- }
6773-
6774- /**
6775- * @return object a new XML_RPC_Response object
6776- */
6777- function parseResponseFile($fp)
6778- {
6779- $ipd = '';
6780- while ($data = @fread($fp, 8192)) {
6781- $ipd .= $data;
6782- }
6783- return $this->parseResponse($ipd);
6784- }
6785-
6786- /**
6787- * @return object a new XML_RPC_Response object
6788- */
6789- function parseResponse($data = '')
6790- {
6791- global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
6792-
6793- $encoding = $this->getEncoding($data);
6794- $parser_resource = xml_parser_create($encoding);
6795- $parser = (int) $parser_resource;
6796-
6797- $XML_RPC_xh[$parser] = array();
6798-
6799- $XML_RPC_xh[$parser]['st'] = '';
6800- $XML_RPC_xh[$parser]['cm'] = 0;
6801- $XML_RPC_xh[$parser]['isf'] = 0;
6802- $XML_RPC_xh[$parser]['ac'] = '';
6803- $XML_RPC_xh[$parser]['qt'] = '';
6804-
6805- xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
6806- xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
6807- xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
6808-
6809- $hdrfnd = 0;
6810- if ($this->debug) {
6811- print "<PRE>---GOT---\n";
6812- print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
6813- print "\n---END---\n</PRE>";
6814- }
6815-
6816- // See if response is a 200 or a 100 then a 200, else raise error.
6817- // But only do this if we're using the HTTP protocol.
6818- if (ereg('^HTTP', $data) &&
6819- !ereg('^HTTP/[0-9\.]+ 200 ', $data) &&
6820- !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Za-z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data))
6821- {
6822- $errstr = substr($data, 0, strpos($data, "\n") - 1);
6823- error_log('HTTP error, got response: ' . $errstr);
6824- $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
6825- $XML_RPC_str['http_error'] . ' (' .
6826- $errstr . ')');
6827- xml_parser_free($parser_resource);
6828- return $r;
6829- }
6830- // gotta get rid of headers here
6831-
6832-
6833- if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) {
6834- $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
6835- $data = substr($data, $brpos + 4);
6836- $hdrfnd = 1;
6837- }
6838-
6839- /*
6840- * be tolerant of junk after methodResponse
6841- * (e.g. javascript automatically inserted by free hosts)
6842- * thanks to Luca Mariano <luca.mariano@email.it>
6843- */
6844- $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
6845-
6846- if (!xml_parse($parser_resource, $data, sizeof($data))) {
6847- // thanks to Peter Kocks <peter.kocks@baygate.com>
6848- if (xml_get_current_line_number($parser_resource) == 1) {
6849- $errstr = 'XML error at line 1, check URL';
6850- } else {
6851- $errstr = sprintf('XML error: %s at line %d',
6852- xml_error_string(xml_get_error_code($parser_resource)),
6853- xml_get_current_line_number($parser_resource));
6854- }
6855- error_log($errstr);
6856- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
6857- $XML_RPC_str['invalid_return']);
6858- xml_parser_free($parser_resource);
6859- return $r;
6860- }
6861- xml_parser_free($parser_resource);
6862- if ($this->debug) {
6863- print '<PRE>---EVALING---[' .
6864- strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
6865- htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
6866- }
6867- if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
6868- // then something odd has happened
6869- // and it's time to generate a client side error
6870- // indicating something odd went on
6871- $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
6872- $XML_RPC_str['invalid_return']);
6873- } else {
6874- eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
6875- if ($XML_RPC_xh[$parser]['isf']) {
6876- $f = $v->structmem('faultCode');
6877- $fs = $v->structmem('faultString');
6878- $r = new XML_RPC_Response($v, $f->scalarval(),
6879- $fs->scalarval());
6880- } else {
6881- $r = new XML_RPC_Response($v);
6882- }
6883- }
6884- $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
6885- return $r;
6886- }
6887-}
6888-
6889-/**
6890- * The methods and properties that represent data in XML RPC format
6891- *
6892- * @category Web Services
6893- * @package XML_RPC
6894- * @author Edd Dumbill <edd@usefulinc.com>
6895- * @author Stig Bakken <stig@php.net>
6896- * @author Martin Jansen <mj@php.net>
6897- * @author Daniel Convissor <danielc@php.net>
6898- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
6899- * @version Release: 1.3.1
6900- * @link http://pear.php.net/package/XML_RPC
6901- */
6902-class XML_RPC_Value extends XML_RPC_Base
6903-{
6904- var $me = array();
6905- var $mytype = 0;
6906-
6907- /**
6908- * @return void
6909- */
6910- function XML_RPC_Value($val = -1, $type = '')
6911- {
6912- global $XML_RPC_Types;
6913- $this->me = array();
6914- $this->mytype = 0;
6915- if ($val != -1 || $type != '') {
6916- if ($type == '') {
6917- $type = 'string';
6918- }
6919- if (!array_key_exists($type, $XML_RPC_Types)) {
6920- // XXX
6921- // need some way to report this error
6922- } elseif ($XML_RPC_Types[$type] == 1) {
6923- $this->addScalar($val, $type);
6924- } elseif ($XML_RPC_Types[$type] == 2) {
6925- $this->addArray($val);
6926- } elseif ($XML_RPC_Types[$type] == 3) {
6927- $this->addStruct($val);
6928- }
6929- }
6930- }
6931-
6932- /**
6933- * @return int returns 1 if successful or 0 if there are problems
6934- */
6935- function addScalar($val, $type = 'string')
6936- {
6937- global $XML_RPC_Types, $XML_RPC_Boolean;
6938-
6939- if ($this->mytype == 1) {
6940- $this->raiseError('Scalar can have only one value',
6941- XML_RPC_ERROR_INVALID_TYPE);
6942- return 0;
6943- }
6944- $typeof = $XML_RPC_Types[$type];
6945- if ($typeof != 1) {
6946- $this->raiseError("Not a scalar type (${typeof})",
6947- XML_RPC_ERROR_INVALID_TYPE);
6948- return 0;
6949- }
6950-
6951- if ($type == $XML_RPC_Boolean) {
6952- if (strcasecmp($val, 'true') == 0
6953- || $val == 1
6954- || ($val == true && strcasecmp($val, 'false')))
6955- {
6956- $val = 1;
6957- } else {
6958- $val = 0;
6959- }
6960- }
6961-
6962- if ($this->mytype == 2) {
6963- // we're adding to an array here
6964- $ar = $this->me['array'];
6965- $ar[] = new XML_RPC_Value($val, $type);
6966- $this->me['array'] = $ar;
6967- } else {
6968- // a scalar, so set the value and remember we're scalar
6969- $this->me[$type] = $val;
6970- $this->mytype = $typeof;
6971- }
6972- return 1;
6973- }
6974-
6975- /**
6976- * @return int returns 1 if successful or 0 if there are problems
6977- */
6978- function addArray($vals)
6979- {
6980- global $XML_RPC_Types;
6981- if ($this->mytype != 0) {
6982- $this->raiseError(
6983- 'Already initialized as a [' . $this->kindOf() . ']',
6984- XML_RPC_ERROR_ALREADY_INITIALIZED);
6985- return 0;
6986- }
6987- $this->mytype = $XML_RPC_Types['array'];
6988- $this->me['array'] = $vals;
6989- return 1;
6990- }
6991-
6992- /**
6993- * @return int returns 1 if successful or 0 if there are problems
6994- */
6995- function addStruct($vals)
6996- {
6997- global $XML_RPC_Types;
6998- if ($this->mytype != 0) {
6999- $this->raiseError(
7000- 'Already initialized as a [' . $this->kindOf() . ']',
7001- XML_RPC_ERROR_ALREADY_INITIALIZED);
7002- return 0;
7003- }
7004- $this->mytype = $XML_RPC_Types['struct'];
7005- $this->me['struct'] = $vals;
7006- return 1;
7007- }
7008-
7009- /**
7010- * @return void
7011- */
7012- function dump($ar)
7013- {
7014- reset($ar);
7015- foreach ($ar as $key => $val) {
7016- echo "$key => $val<br />";
7017- if ($key == 'array') {
7018- foreach ($val as $key2 => $val2) {
7019- echo "-- $key2 => $val2<br />";
7020- }
7021- }
7022- }
7023- }
7024-
7025- /**
7026- * @return string the data type of the current value
7027- */
7028- function kindOf()
7029- {
7030- switch ($this->mytype) {
7031- case 3:
7032- return 'struct';
7033-
7034- case 2:
7035- return 'array';
7036-
7037- case 1:
7038- return 'scalar';
7039-
7040- default:
7041- return 'undef';
7042- }
7043- }
7044-
7045- /**
7046- * @return string the data in XML format
7047- */
7048- function serializedata($typ, $val)
7049- {
7050- $rs = '';
7051- global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
7052- if (!array_key_exists($typ, $XML_RPC_Types)) {
7053- // XXX
7054- // need some way to report this error
7055- return;
7056- }
7057- switch ($XML_RPC_Types[$typ]) {
7058- case 3:
7059- // struct
7060- $rs .= "<struct>\n";
7061- reset($val);
7062- foreach ($val as $key2 => $val2) {
7063- $rs .= "<member><name>${key2}</name>\n";
7064- $rs .= $this->serializeval($val2);
7065- $rs .= "</member>\n";
7066- }
7067- $rs .= '</struct>';
7068- break;
7069-
7070- case 2:
7071- // array
7072- $rs .= "<array>\n<data>\n";
7073- for ($i = 0; $i < sizeof($val); $i++) {
7074- $rs .= $this->serializeval($val[$i]);
7075- }
7076- $rs .= "</data>\n</array>";
7077- break;
7078-
7079- case 1:
7080- switch ($typ) {
7081- case $XML_RPC_Base64:
7082- $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
7083- break;
7084- case $XML_RPC_Boolean:
7085- $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
7086- break;
7087- case $XML_RPC_String:
7088- $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
7089- break;
7090- default:
7091- $rs .= "<${typ}>${val}</${typ}>";
7092- }
7093- }
7094- return $rs;
7095- }
7096-
7097- /**
7098- * @return string the data in XML format
7099- */
7100- function serialize()
7101- {
7102- return $this->serializeval($this);
7103- }
7104-
7105- /**
7106- * @return string the data in XML format
7107- */
7108- function serializeval($o)
7109- {
7110- $rs = '';
7111- $ar = $o->me;
7112- reset($ar);
7113- list($typ, $val) = each($ar);
7114- $rs .= '<value>';
7115- $rs .= $this->serializedata($typ, $val);
7116- $rs .= "</value>\n";
7117- return $rs;
7118- }
7119-
7120- /**
7121- * @return mixed the contents of the element requested
7122- */
7123- function structmem($m)
7124- {
7125- return $this->me['struct'][$m];
7126- }
7127-
7128- /**
7129- * @return void
7130- */
7131- function structreset()
7132- {
7133- reset($this->me['struct']);
7134- }
7135-
7136- /**
7137- * @return the key/value pair of the struct's current element
7138- */
7139- function structeach()
7140- {
7141- return each($this->me['struct']);
7142- }
7143-
7144- /**
7145- * @return mixed the current value
7146- */
7147- function getval()
7148- {
7149- // UNSTABLE
7150- global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
7151-
7152- reset($this->me);
7153- $b = current($this->me);
7154-
7155- // contributed by I Sofer, 2001-03-24
7156- // add support for nested arrays to scalarval
7157- // i've created a new method here, so as to
7158- // preserve back compatibility
7159-
7160- if (is_array($b)) {
7161- foreach ($b as $id => $cont) {
7162- $b[$id] = $cont->scalarval();
7163- }
7164- }
7165-
7166- // add support for structures directly encoding php objects
7167- if (is_object($b)) {
7168- $t = get_object_vars($b);
7169- foreach ($t as $id => $cont) {
7170- $t[$id] = $cont->scalarval();
7171- }
7172- foreach ($t as $id => $cont) {
7173- eval('$b->'.$id.' = $cont;');
7174- }
7175- }
7176-
7177- // end contrib
7178- return $b;
7179- }
7180-
7181- /**
7182- * @return mixed
7183- */
7184- function scalarval()
7185- {
7186- global $XML_RPC_Boolean, $XML_RPC_Base64;
7187- reset($this->me);
7188- return current($this->me);
7189- }
7190-
7191- /**
7192- * @return string
7193- */
7194- function scalartyp()
7195- {
7196- global $XML_RPC_I4, $XML_RPC_Int;
7197- reset($this->me);
7198- $a = key($this->me);
7199- if ($a == $XML_RPC_I4) {
7200- $a = $XML_RPC_Int;
7201- }
7202- return $a;
7203- }
7204-
7205- /**
7206- * @return mixed the struct's current element
7207- */
7208- function arraymem($m)
7209- {
7210- return $this->me['array'][$m];
7211- }
7212-
7213- /**
7214- * @return int the number of elements in the array
7215- */
7216- function arraysize()
7217- {
7218- reset($this->me);
7219- list($a, $b) = each($this->me);
7220- return sizeof($b);
7221- }
7222-
7223- /**
7224- * Determines if the item submitted is an XML_RPC_Value object
7225- *
7226- * @param mixed $val the variable to be evaluated
7227- *
7228- * @return bool TRUE if the item is an XML_RPC_Value object
7229- *
7230- * @static
7231- * @since Method available since Release 1.3.0
7232- */
7233- function isValue($val)
7234- {
7235- return (strtolower(get_class($val)) == 'xml_rpc_value');
7236- }
7237-}
7238-
7239-/**
7240- * Return an ISO8601 encoded string
7241- *
7242- * While timezones ought to be supported, the XML-RPC spec says:
7243- *
7244- * "Don't assume a timezone. It should be specified by the server in its
7245- * documentation what assumptions it makes about timezones."
7246- *
7247- * This routine always assumes localtime unless $utc is set to 1, in which
7248- * case UTC is assumed and an adjustment for locale is made when encoding.
7249- *
7250- * @return string the formatted date
7251- */
7252-function XML_RPC_iso8601_encode($timet, $utc = 0)
7253-{
7254- if (!$utc) {
7255- $t = strftime('%Y%m%dT%H:%M:%S', $timet);
7256- } else {
7257- if (function_exists('gmstrftime')) {
7258- // gmstrftime doesn't exist in some versions
7259- // of PHP
7260- $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
7261- } else {
7262- $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
7263- }
7264- }
7265- return $t;
7266-}
7267-
7268-/**
7269- * Convert a datetime string into a Unix timestamp
7270- *
7271- * While timezones ought to be supported, the XML-RPC spec says:
7272- *
7273- * "Don't assume a timezone. It should be specified by the server in its
7274- * documentation what assumptions it makes about timezones."
7275- *
7276- * This routine always assumes localtime unless $utc is set to 1, in which
7277- * case UTC is assumed and an adjustment for locale is made when encoding.
7278- *
7279- * @return int the unix timestamp of the date submitted
7280- */
7281-function XML_RPC_iso8601_decode($idate, $utc = 0)
7282-{
7283- $t = 0;
7284- if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
7285- if ($utc) {
7286- $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
7287- } else {
7288- $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
7289- }
7290- }
7291- return $t;
7292-}
7293-
7294-/**
7295- * Converts an XML_RPC_Value object into native PHP types
7296- *
7297- * @param object $XML_RPC_val the XML_RPC_Value object to decode
7298- *
7299- * @return mixed the PHP values
7300- */
7301-function XML_RPC_decode($XML_RPC_val)
7302-{
7303- $kind = $XML_RPC_val->kindOf();
7304-
7305- if ($kind == 'scalar') {
7306- return $XML_RPC_val->scalarval();
7307-
7308- } elseif ($kind == 'array') {
7309- $size = $XML_RPC_val->arraysize();
7310- $arr = array();
7311- for ($i = 0; $i < $size; $i++) {
7312- $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
7313- }
7314- return $arr;
7315-
7316- } elseif ($kind == 'struct') {
7317- $XML_RPC_val->structreset();
7318- $arr = array();
7319- while (list($key, $value) = $XML_RPC_val->structeach()) {
7320- $arr[$key] = XML_RPC_decode($value);
7321- }
7322- return $arr;
7323- }
7324-}
7325-
7326-/**
7327- * Converts native PHP types into an XML_RPC_Value object
7328- *
7329- * @param mixed $php_val the PHP value or variable you want encoded
7330- *
7331- * @return object the XML_RPC_Value object
7332- */
7333-function XML_RPC_encode($php_val)
7334-{
7335- global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
7336- $XML_RPC_Array, $XML_RPC_Struct;
7337-
7338- $type = gettype($php_val);
7339- $XML_RPC_val = new XML_RPC_Value;
7340-
7341- switch ($type) {
7342- case 'array':
7343- if (empty($php_val)) {
7344- $XML_RPC_val->addArray($php_val);
7345- break;
7346- }
7347- $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
7348- if (empty($tmp)) {
7349- $arr = array();
7350- foreach ($php_val as $k => $v) {
7351- $arr[$k] = XML_RPC_encode($v);
7352- }
7353- $XML_RPC_val->addArray($arr);
7354- break;
7355- }
7356- // fall though if it's not an enumerated array
7357-
7358- case 'object':
7359- $arr = array();
7360- foreach ($php_val as $k => $v) {
7361- $arr[$k] = XML_RPC_encode($v);
7362- }
7363- $XML_RPC_val->addStruct($arr);
7364- break;
7365-
7366- case 'integer':
7367- $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
7368- break;
7369-
7370- case 'double':
7371- $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
7372- break;
7373-
7374- case 'string':
7375- case 'NULL':
7376- $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
7377- break;
7378-
7379- case 'boolean':
7380- // Add support for encoding/decoding of booleans, since they
7381- // are supported in PHP
7382- // by <G_Giunta_2001-02-29>
7383- $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
7384- break;
7385-
7386- case 'unknown type':
7387- default:
7388- $XML_RPC_val = false;
7389- }
7390- return $XML_RPC_val;
7391-}
7392-
7393-/*
7394- * Local variables:
7395- * tab-width: 4
7396- * c-basic-offset: 4
7397- * c-hanging-comment-ender-p: nil
7398- * End:
7399- */
7400-
7401-?>
7402-
7403-
7404-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
7405-
7406-/**
7407- * Server commands for our PHP implementation of the XML-RPC protocol
7408- *
7409- * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
7410- * It has support for HTTP transport, proxies and authentication.
7411- *
7412- * PHP versions 4 and 5
7413- *
7414- * LICENSE: License is granted to use or modify this software
7415- * ("XML-RPC for PHP") for commercial or non-commercial use provided the
7416- * copyright of the author is preserved in any distributed or derivative work.
7417- *
7418- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
7419- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
7420- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
7421- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
7422- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
7423- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7424- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7425- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7426- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
7427- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7428- *
7429- * @category Web Services
7430- * @package XML_RPC
7431- * @author Edd Dumbill <edd@usefulinc.com>
7432- * @author Stig Bakken <stig@php.net>
7433- * @author Martin Jansen <mj@php.net>
7434- * @author Daniel Convissor <danielc@php.net>
7435- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7436- * @version CVS: $Id: Server.php,v 1.26 2005/05/09 21:39:47 danielc Exp $
7437- * @link http://pear.php.net/package/XML_RPC
7438- */
7439-
7440-
7441-/**
7442- * Pull in the XML_RPC class
7443- */
7444-require_once 'XML/RPC.php';
7445-
7446-
7447-/**
7448- * signature for system.listMethods: return = array,
7449- * parameters = a string or nothing
7450- * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
7451- */
7452-$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
7453- array($GLOBALS['XML_RPC_Array'],
7454- $GLOBALS['XML_RPC_String']
7455- ),
7456- array($GLOBALS['XML_RPC_Array'])
7457-);
7458-
7459-/**
7460- * docstring for system.listMethods
7461- * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
7462- */
7463-$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
7464- . ' methods that the XML-RPC server knows how to dispatch';
7465-
7466-/**
7467- * signature for system.methodSignature: return = array,
7468- * parameters = string
7469- * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
7470- */
7471-$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
7472- array($GLOBALS['XML_RPC_Array'],
7473- $GLOBALS['XML_RPC_String']
7474- )
7475-);
7476-
7477-/**
7478- * docstring for system.methodSignature
7479- * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
7480- */
7481-$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
7482- . ' signatures (an array of arrays) for the method name passed. If'
7483- . ' no signatures are known, returns a none-array (test for type !='
7484- . ' array to detect missing signature)';
7485-
7486-/**
7487- * signature for system.methodHelp: return = string,
7488- * parameters = string
7489- * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
7490- */
7491-$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
7492- array($GLOBALS['XML_RPC_String'],
7493- $GLOBALS['XML_RPC_String']
7494- )
7495-);
7496-
7497-/**
7498- * docstring for methodHelp
7499- * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
7500- */
7501-$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
7502- . ' for the method passed, otherwise returns an empty string';
7503-
7504-/**
7505- * dispatch map for the automatically declared XML-RPC methods.
7506- * @global array $GLOBALS['XML_RPC_Server_dmap']
7507- */
7508-$GLOBALS['XML_RPC_Server_dmap'] = array(
7509- 'system.listMethods' => array(
7510- 'function' => 'XML_RPC_Server_listMethods',
7511- 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
7512- 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
7513- ),
7514- 'system.methodHelp' => array(
7515- 'function' => 'XML_RPC_Server_methodHelp',
7516- 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
7517- 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
7518- ),
7519- 'system.methodSignature' => array(
7520- 'function' => 'XML_RPC_Server_methodSignature',
7521- 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
7522- 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
7523- )
7524-);
7525-
7526-/**
7527- * @global string $GLOBALS['XML_RPC_Server_debuginfo']
7528- */
7529-$GLOBALS['XML_RPC_Server_debuginfo'] = '';
7530-
7531-
7532-/**
7533- * Lists all the methods that the XML-RPC server knows how to dispatch
7534- *
7535- * @return object a new XML_RPC_Response object
7536- */
7537-function XML_RPC_Server_listMethods($server, $m)
7538-{
7539- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
7540-
7541- $v = new XML_RPC_Value();
7542- $outAr = array();
7543- foreach ($server->dmap as $key => $val) {
7544- $outAr[] = new XML_RPC_Value($key, 'string');
7545- }
7546- foreach ($XML_RPC_Server_dmap as $key => $val) {
7547- $outAr[] = new XML_RPC_Value($key, 'string');
7548- }
7549- $v->addArray($outAr);
7550- return new XML_RPC_Response($v);
7551-}
7552-
7553-/**
7554- * Returns an array of known signatures (an array of arrays)
7555- * for the given method
7556- *
7557- * If no signatures are known, returns a none-array
7558- * (test for type != array to detect missing signature)
7559- *
7560- * @return object a new XML_RPC_Response object
7561- */
7562-function XML_RPC_Server_methodSignature($server, $m)
7563-{
7564- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
7565-
7566- $methName = $m->getParam(0);
7567- $methName = $methName->scalarval();
7568- if (strpos($methName, 'system.') === 0) {
7569- $dmap = $XML_RPC_Server_dmap;
7570- $sysCall = 1;
7571- } else {
7572- $dmap = $server->dmap;
7573- $sysCall = 0;
7574- }
7575- // print "<!-- ${methName} -->\n";
7576- if (isset($dmap[$methName])) {
7577- if ($dmap[$methName]['signature']) {
7578- $sigs = array();
7579- $thesigs = $dmap[$methName]['signature'];
7580- for ($i = 0; $i < sizeof($thesigs); $i++) {
7581- $cursig = array();
7582- $inSig = $thesigs[$i];
7583- for ($j = 0; $j < sizeof($inSig); $j++) {
7584- $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
7585- }
7586- $sigs[] = new XML_RPC_Value($cursig, 'array');
7587- }
7588- $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
7589- } else {
7590- $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
7591- }
7592- } else {
7593- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
7594- $XML_RPC_str['introspect_unknown']);
7595- }
7596- return $r;
7597-}
7598-
7599-/**
7600- * Returns help text if defined for the method passed, otherwise returns
7601- * an empty string
7602- *
7603- * @return object a new XML_RPC_Response object
7604- */
7605-function XML_RPC_Server_methodHelp($server, $m)
7606-{
7607- global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
7608-
7609- $methName = $m->getParam(0);
7610- $methName = $methName->scalarval();
7611- if (strpos($methName, 'system.') === 0) {
7612- $dmap = $XML_RPC_Server_dmap;
7613- $sysCall = 1;
7614- } else {
7615- $dmap = $server->dmap;
7616- $sysCall = 0;
7617- }
7618- // print "<!-- ${methName} -->\n";
7619- if (isset($dmap[$methName])) {
7620- if ($dmap[$methName]['docstring']) {
7621- $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
7622- 'string');
7623- } else {
7624- $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
7625- }
7626- } else {
7627- $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
7628- $XML_RPC_str['introspect_unknown']);
7629- }
7630- return $r;
7631-}
7632-
7633-/**
7634- * @return void
7635- */
7636-function XML_RPC_Server_debugmsg($m)
7637-{
7638- global $XML_RPC_Server_debuginfo;
7639- $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
7640-}
7641-
7642-
7643-/**
7644- * A server for receiving and replying to XML RPC requests
7645- *
7646- * <code>
7647- * $server = new XML_RPC_Server(
7648- * array(
7649- * 'isan8' =>
7650- * array(
7651- * 'function' => 'is_8',
7652- * 'signature' =>
7653- * array(
7654- * array('boolean', 'int'),
7655- * array('boolean', 'int', 'boolean'),
7656- * array('boolean', 'string'),
7657- * array('boolean', 'string', 'boolean'),
7658- * ),
7659- * 'docstring' => 'Is the value an 8?'
7660- * ),
7661- * ),
7662- * 1,
7663- * 0
7664- * );
7665- * </code>
7666- *
7667- * @category Web Services
7668- * @package XML_RPC
7669- * @author Edd Dumbill <edd@usefulinc.com>
7670- * @author Stig Bakken <stig@php.net>
7671- * @author Martin Jansen <mj@php.net>
7672- * @author Daniel Convissor <danielc@php.net>
7673- * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
7674- * @version Release: 1.3.1
7675- * @link http://pear.php.net/package/XML_RPC
7676- */
7677-class XML_RPC_Server
7678-{
7679- /**
7680- * The dispatch map, listing the methods this server provides.
7681- * @var array
7682- */
7683- var $dmap = array();
7684-
7685- /**
7686- * The present response's encoding
7687- * @var string
7688- * @see XML_RPC_Message::getEncoding()
7689- */
7690- var $encoding = '';
7691-
7692- /**
7693- * Debug mode (0 = off, 1 = on)
7694- * @var integer
7695- */
7696- var $debug = 0;
7697-
7698- /**
7699- * The response's HTTP headers
7700- * @var string
7701- */
7702- var $server_headers = '';
7703-
7704- /**
7705- * The response's XML payload
7706- * @var string
7707- */
7708- var $server_payload = '';
7709-
7710-
7711- /**
7712- * Constructor for the XML_RPC_Server class
7713- *
7714- * @param array $dispMap the dispatch map. An associative array
7715- * explaining each function. The keys of the main
7716- * array are the procedure names used by the
7717- * clients. The value is another associative array
7718- * that contains up to three elements:
7719- * + The 'function' element's value is the name
7720- * of the function or method that gets called.
7721- * To define a class' method: 'class::method'.
7722- * + The 'signature' element (optional) is an
7723- * array describing the return values and
7724- * parameters
7725- * + The 'docstring' element (optional) is a
7726- * string describing what the method does
7727- * @param int $serviceNow should the HTTP response be sent now?
7728- * (1 = yes, 0 = no)
7729- * @param int $debug should debug output be displayed?
7730- * (1 = yes, 0 = no)
7731- *
7732- * @return void
7733- */
7734- function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
7735- {
7736- global $HTTP_RAW_POST_DATA;
7737-
7738- if ($debug) {
7739- $this->debug = 1;
7740- } else {
7741- $this->debug = 0;
7742- }
7743-
7744- $this->dmap = $dispMap;
7745-
7746- if ($serviceNow) {
7747- $this->service();
7748- } else {
7749- $this->createServerPayload();
7750- $this->createServerHeaders();
7751- }
7752- }
7753-
7754- /**
7755- * @return string the debug information if debug debug mode is on
7756- */
7757- function serializeDebug()
7758- {
7759- global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
7760-
7761- if ($this->debug) {
7762- XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
7763- . $HTTP_RAW_POST_DATA
7764- . "\n" . '^^^ END POST DATA ^^^');
7765- }
7766-
7767- if ($XML_RPC_Server_debuginfo != '') {
7768- return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
7769- . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
7770- . "-->\n";
7771- } else {
7772- return '';
7773- }
7774- }
7775-
7776- /**
7777- * Sends the response
7778- *
7779- * The encoding and content-type are determined by
7780- * XML_RPC_Message::getEncoding()
7781- *
7782- * @return void
7783- *
7784- * @uses XML_RPC_Server::createServerPayload(),
7785- * XML_RPC_Server::createServerHeaders()
7786- */
7787- function service()
7788- {
7789- $this->createServerPayload();
7790- $this->createServerHeaders();
7791- header($this->server_headers);
7792- print $this->server_payload;
7793- }
7794-
7795- /**
7796- * Generates the payload and puts it in the $server_payload property
7797- *
7798- * @return void
7799- *
7800- * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding,
7801- * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug()
7802- */
7803- function createServerPayload()
7804- {
7805- $r = $this->parseRequest();
7806- $this->server_payload = '<?xml version="1.0" encoding="'
7807- . $this->encoding . '"?>' . "\n"
7808- . $this->serializeDebug()
7809- . $r->serialize();
7810- }
7811-
7812- /**
7813- * Determines the HTTP headers and puts them in the $server_headers
7814- * property
7815- *
7816- * @return boolean TRUE if okay, FALSE if $server_payload isn't set.
7817- *
7818- * @uses XML_RPC_Server::createServerPayload(),
7819- * XML_RPC_Server::$server_headers
7820- */
7821- function createServerHeaders()
7822- {
7823- if (!$this->server_payload) {
7824- return false;
7825- }
7826- $this->server_headers = 'Content-Length: '
7827- . strlen($this->server_payload) . "\r\n"
7828- . 'Content-Type: text/xml;'
7829- . ' charset=' . $this->encoding;
7830- return true;
7831- }
7832-
7833- /**
7834- * @return array
7835- */
7836- function verifySignature($in, $sig)
7837- {
7838- for ($i = 0; $i < sizeof($sig); $i++) {
7839- // check each possible signature in turn
7840- $cursig = $sig[$i];
7841- if (sizeof($cursig) == $in->getNumParams() + 1) {
7842- $itsOK = 1;
7843- for ($n = 0; $n < $in->getNumParams(); $n++) {
7844- $p = $in->getParam($n);
7845- // print "<!-- $p -->\n";
7846- if ($p->kindOf() == 'scalar') {
7847- $pt = $p->scalartyp();
7848- } else {
7849- $pt = $p->kindOf();
7850- }
7851- // $n+1 as first type of sig is return type
7852- if ($pt != $cursig[$n+1]) {
7853- $itsOK = 0;
7854- $pno = $n+1;
7855- $wanted = $cursig[$n+1];
7856- $got = $pt;
7857- break;
7858- }
7859- }
7860- if ($itsOK) {
7861- return array(1);
7862- }
7863- }
7864- }
7865- if (isset($wanted)) {
7866- return array(0, "Wanted ${wanted}, got ${got} at param ${pno}");
7867- } else {
7868- $allowed = array();
7869- foreach ($sig as $val) {
7870- end($val);
7871- $allowed[] = key($val);
7872- }
7873- $allowed = array_unique($allowed);
7874- $last = count($allowed) - 1;
7875- if ($last > 0) {
7876- $allowed[$last] = 'or ' . $allowed[$last];
7877- }
7878- return array(0,
7879- 'Signature permits ' . implode(', ', $allowed)
7880- . ' parameters but the request had '
7881- . $in->getNumParams());
7882- }
7883- }
7884-
7885- /**
7886- * @return object a new XML_RPC_Response object
7887- *
7888- * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding
7889- */
7890- function parseRequest($data = '')
7891- {
7892- global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
7893- $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
7894- $XML_RPC_defencoding, $XML_RPC_Server_dmap;
7895-
7896- if ($data == '') {
7897- $data = $HTTP_RAW_POST_DATA;
7898- }
7899-
7900- $this->encoding = XML_RPC_Message::getEncoding($data);
7901- $parser_resource = xml_parser_create($this->encoding);
7902- $parser = (int) $parser_resource;
7903-
7904- $XML_RPC_xh[$parser] = array();
7905- $XML_RPC_xh[$parser]['st'] = '';
7906- $XML_RPC_xh[$parser]['cm'] = 0;
7907- $XML_RPC_xh[$parser]['isf'] = 0;
7908- $XML_RPC_xh[$parser]['params'] = array();
7909- $XML_RPC_xh[$parser]['method'] = '';
7910-
7911- $plist = '';
7912-
7913- // decompose incoming XML into request structure
7914-
7915- xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
7916- xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
7917- xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
7918- if (!xml_parse($parser_resource, $data, 1)) {
7919- // return XML error as a faultCode
7920- $r = new XML_RPC_Response(0,
7921- $XML_RPC_errxml+xml_get_error_code($parser_resource),
7922- sprintf('XML error: %s at line %d',
7923- xml_error_string(xml_get_error_code($parser_resource)),
7924- xml_get_current_line_number($parser_resource)));
7925- xml_parser_free($parser_resource);
7926- } else {
7927- xml_parser_free($parser_resource);
7928- $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
7929- // now add parameters in
7930- for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
7931- // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
7932- $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
7933- eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ');');
7934- }
7935- XML_RPC_Server_debugmsg($plist);
7936-
7937- // now to deal with the method
7938- $methName = $XML_RPC_xh[$parser]['method'];
7939- if (strpos($methName, 'system.') === 0) {
7940- $dmap = $XML_RPC_Server_dmap;
7941- $sysCall = 1;
7942- } else {
7943- $dmap = $this->dmap;
7944- $sysCall = 0;
7945- }
7946-
7947- if (isset($dmap[$methName]['function'])
7948- && is_string($dmap[$methName]['function'])
7949- && strpos($dmap[$methName]['function'], '::') !== false)
7950- {
7951- $dmap[$methName]['function'] =
7952- explode('::', $dmap[$methName]['function']);
7953- }
7954-
7955- if (isset($dmap[$methName]['function'])
7956- && is_callable($dmap[$methName]['function']))
7957- {
7958- // dispatch if exists
7959- if (isset($dmap[$methName]['signature'])) {
7960- $sr = $this->verifySignature($m,
7961- $dmap[$methName]['signature'] );
7962- }
7963- if (!isset($dmap[$methName]['signature']) || $sr[0]) {
7964- // if no signature or correct signature
7965- if ($sysCall) {
7966- $r = call_user_func($dmap[$methName]['function'], $this, $m);
7967- } else {
7968- $r = call_user_func($dmap[$methName]['function'], $m);
7969- }
7970- if (!is_a($r, 'XML_RPC_Response')) {
7971- $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'],
7972- $XML_RPC_str['not_response_object']);
7973- }
7974- } else {
7975- $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
7976- $XML_RPC_str['incorrect_params']
7977- . ': ' . $sr[1]);
7978- }
7979- } else {
7980- // else prepare error response
7981- $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
7982- $XML_RPC_str['unknown_method']);
7983- }
7984- }
7985- return $r;
7986- }
7987-
7988- /**
7989- * Echos back the input packet as a string value
7990- *
7991- * @return void
7992- *
7993- * Useful for debugging.
7994- */
7995- function echoInput()
7996- {
7997- global $HTTP_RAW_POST_DATA;
7998-
7999- $r = new XML_RPC_Response(0);
8000- $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
8001- print $r->serialize();
8002- }
8003-}
8004-
8005-/*
8006- * Local variables:
8007- * tab-width: 4
8008- * c-basic-offset: 4
8009- * c-hanging-comment-ender-p: nil
8010- * End:
8011- */
8012-
8013-?>
8014-
8015-<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
8016-<package version="1.0" packagerversion="1.4.0a12">
8017- <name>XML_RPC</name>
8018- <summary>PHP implementation of the XML-RPC protocol</summary>
8019- <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
8020-
8021-It has support for HTTP/HTTPS transport, proxies and authentication.
8022- </description>
8023- <maintainers>
8024- <maintainer>
8025- <user>ssb</user>
8026- <name>Stig Bakken</name>
8027- <email>stig@php.net</email>
8028- <role>lead</role>
8029- </maintainer>
8030- <maintainer>
8031- <user>danielc</user>
8032- <name>Daniel Convissor</name>
8033- <email>danielc@php.net</email>
8034- <role>lead</role>
8035- </maintainer>
8036- </maintainers>
8037- <release>
8038- <version>1.3.1</version>
8039- <date>2005-06-29</date>
8040- <license>PHP License</license>
8041- <state>stable</state>
8042- <notes>* Security fix. Update highly recommended!
8043- </notes>
8044- <filelist>
8045- <file role="php" baseinstalldir="XML" name="RPC.php">
8046- <replace from="@package_version@" to="version" type="package-info"/>
8047- </file>
8048- <file role="php" baseinstalldir="XML/RPC" name="Server.php">
8049- <replace from="@package_version@" to="version" type="package-info"/>
8050- </file>
8051- <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
8052- <replace from="@package_version@" to="version" type="package-info"/>
8053- </file>
8054- <file role="test" name="tests/protoport.php">
8055- <replace from="@package_version@" to="version" type="package-info"/>
8056- </file>
8057- <file role="test" name="tests/test_Dump.php">
8058- <replace from="@package_version@" to="version" type="package-info"/>
8059- </file>
8060- </filelist>
8061- </release>
8062- <changelog>
8063- <release>
8064- <version>1.3.0RC3</version>
8065- <date>2005-05-10</date>
8066- <state>beta</state>
8067- <notes>* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
8068-* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
8069-* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
8070-* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
8071-* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
8072-* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().
8073- </notes>
8074- </release>
8075- <release>
8076- <version>1.3.0RC2</version>
8077- <date>2005-05-05</date>
8078- <state>beta</state>
8079- <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
8080-* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
8081-* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
8082-* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.
8083- </notes>
8084- </release>
8085- <release>
8086- <version>1.3.0RC1</version>
8087- <date>2005-04-07</date>
8088- <state>beta</state>
8089- <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
8090-* Add Fault Code 6: &quot;The requested method didn't return an XML_RPC_Response object.&quot; Request 4032.
8091-* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
8092-* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
8093-* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
8094-* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
8095- </notes>
8096- </release>
8097- <release>
8098- <version>1.2.2</version>
8099- <date>2005-03-07</date>
8100- <state>stable</state>
8101- <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
8102- </notes>
8103- </release>
8104- <release>
8105- <version>1.2.1</version>
8106- <date>2005-03-01</date>
8107- <state>stable</state>
8108- <notes>* Add isset() check before examining the dispatch map. Bug 3658.
8109- </notes>
8110- </release>
8111- <release>
8112- <version>1.2.0</version>
8113- <date>2005-02-27</date>
8114- <state>stable</state>
8115- <notes>* Provide the &quot;stable&quot; release.
8116-* Add package2.xml for compatibility with PEAR 1.4.0.
8117-* For changes since 1.1.0, see the changelogs for the various RC releases.
8118- </notes>
8119- </release>
8120- <release>
8121- <version>1.2.0RC7</version>
8122- <date>2005-02-22</date>
8123- <state>beta</state>
8124- <notes>* Add the setSendEncoding() method and $send_encoding
8125- property to XML_RPC_Message. Request 3537.
8126-* Allow class methods to be mapped using either syntax:
8127- 'function' =&gt; 'hello::sayHello',
8128- or
8129- 'function' =&gt; array('hello', 'sayhello'),
8130- Bug 3363.
8131-* Use 8192 instead of 32768 for bytes in fread()
8132- in parseResponseFile(). Bug 3340.
8133- </notes>
8134- </release>
8135- <release>
8136- <version>1.2.0RC6</version>
8137- <date>2005-01-25</date>
8138- <state>beta</state>
8139- <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
8140- </notes>
8141- </release>
8142- <release>
8143- <version>1.2.0RC5</version>
8144- <date>2005-01-24</date>
8145- <state>beta</state>
8146- <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
8147- </notes>
8148- </release>
8149- <release>
8150- <version>1.2.0RC4</version>
8151- <date>2005-01-24</date>
8152- <state>beta</state>
8153- <notes>* When a connection attempt fails, have the method return 0. (danielc)
8154-* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
8155-* Add tests for setting the client properties. (danielc)
8156-* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
8157-* Bundle the tests with the package. (danielc)
8158- </notes>
8159- </release>
8160- <release>
8161- <version>1.2.0RC3</version>
8162- <date>2005-01-19</date>
8163- <state>beta</state>
8164- <notes>* ssl uses port 443, not 445.
8165- </notes>
8166- </release>
8167- <release>
8168- <version>1.2.0RC2</version>
8169- <date>2005-01-11</date>
8170- <state>beta</state>
8171- <notes>* Handle ssl:// in the $server string. (danielc)
8172-* Also default to port 445 for ssl:// requests as well. (danielc)
8173-* Enhance debugging in the server. (danielc)
8174- </notes>
8175- </release>
8176- <release>
8177- <version>1.2.0RC1</version>
8178- <date>2004-12-30</date>
8179- <state>beta</state>
8180- <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
8181-* Allow array function callbacks (Matt Kane)
8182-* Some minor speed-ups (Matt Kane)
8183-* Add Dump.php to the package (Christian Weiske)
8184-* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
8185-* Silence fsockopen() errors. Bug 1714. (danielc)
8186-* Encode empty arrays as an array. Bug 1493. (danielc)
8187-* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
8188-* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
8189-* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
8190-* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
8191-* Allow raiseError() to be called statically. (danielc)
8192-* Stop double escaping of character entities. Bug 987. (danielc)
8193- NOTICE: the following have been removed:
8194- * XML_RPC_dh()
8195- * $GLOBALS['XML_RPC_entities']
8196- * XML_RPC_entity_decode()
8197- * XML_RPC_lookup_entity()
8198-* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
8199- </notes>
8200- </release>
8201- <release>
8202- <version>1.1.0</version>
8203- <date>2004-03-15</date>
8204- <state>stable</state>
8205- <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
8206-* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
8207-* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
8208-* Replace echo and error_log() with raiseError() (mroch)
8209-* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
8210-* be tolerant of junk after methodResponse (Luca Mariano, mroch)
8211-* Silent notice even in the error log (pierre)
8212-* fix include of shared xml extension on win32 (pierre)
8213- </notes>
8214- </release>
8215- <release>
8216- <version>1.0.4</version>
8217- <date>2002-10-02</date>
8218- <state>stable</state>
8219- <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
8220- </notes>
8221- </release>
8222- <release>
8223- <version>1.0.3</version>
8224- <date>2002-05-19</date>
8225- <state>stable</state>
8226- <notes>* fix bug when parsing responses with boolean types
8227- </notes>
8228- </release>
8229- <release>
8230- <version>1.0.2</version>
8231- <date>2002-04-16</date>
8232- <state>stable</state>
8233- <notes>* E_ALL fixes
8234-* fix HTTP response header parsing
8235- </notes>
8236- </release>
8237- <release>
8238- <version>1.0.1</version>
8239- <date>2001-09-25</date>
8240- <state>stable</state>
8241- <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
8242-Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
8243- </notes>
8244- </release>
8245- </changelog>
8246-</package>
8247-
8248\ Kein Zeilenumbruch am Dateiende.
8249diff -Nura php-4.4.0/pear/packages/XML_RPC-1.4.0.tar hardening-patch-4.4.0-0.4.3/pear/packages/XML_RPC-1.4.0.tar
8250--- php-4.4.0/pear/packages/XML_RPC-1.4.0.tar 1970-01-01 01:00:00.000000000 +0100
8251+++ hardening-patch-4.4.0-0.4.3/pear/packages/XML_RPC-1.4.0.tar 2005-09-11 23:31:08.000000000 +0200
8252@@ -0,0 +1,3933 @@
8253+package2.xml
8254+<package packagerversion="1.4.0a12" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
8255+ <name>XML_RPC</name>
8256+ <channel>pear.php.net</channel>
8257+ <summary>PHP implementation of the XML-RPC protocol</summary>
8258+ <description>A PEAR-ified version of Useful Inc&apos;s XML-RPC for PHP.
8259+
8260+It has support for HTTP/HTTPS transport, proxies and authentication.</description>
8261+ <lead>
8262+ <name>Stig Bakken</name>
8263+ <user>ssb</user>
8264+ <email>stig@php.net</email>
8265+ <active>no</active>
8266+ </lead>
8267+ <lead>
8268+ <name>Daniel Convissor</name>
8269+ <user>danielc</user>
8270+ <email>danielc@php.net</email>
8271+ <active>yes</active>
8272+ </lead>
8273+ <date>2005-08-14</date>
8274+ <time>16:30:30</time>
8275+ <version>
8276+ <release>1.4.0</release>
8277+ <api>1.4.0</api>
8278+ </version>
8279+ <stability>
8280+ <release>stable</release>
8281+ <api>stable</api>
8282+ </stability>
8283+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8284+ <notes>* MAJOR SECURITY FIX: eliminate use of eval().
8285+* Using socket_get_status() because stream_get_meta_data() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.</notes>
8286+ <contents>
8287+ <dir name="/">
8288+ <file md5sum="952733184950487ec0cee78cf05bedc4" name="tests/protoport.php" role="test">
8289+ <tasks:replace from="@package_version@" to="version" type="package-info" />
8290+ </file>
8291+ <file md5sum="239a5b407054852b6f470f043a44d8be" name="tests/test_Dump.php" role="test">
8292+ <tasks:replace from="@package_version@" to="version" type="package-info" />
8293+ </file>
8294+ <file baseinstalldir="XML/RPC" md5sum="80df8443b5e6c2919de012df1f1d7997" name="Dump.php" role="php">
8295+ <tasks:replace from="@package_version@" to="version" type="package-info" />
8296+ </file>
8297+ <file baseinstalldir="XML" md5sum="5c26e8fae482ba8c123c71c2c8c3fabc" name="RPC.php" role="php">
8298+ <tasks:replace from="@package_version@" to="version" type="package-info" />
8299+ </file>
8300+ <file baseinstalldir="XML/RPC" md5sum="8bded286786fb010879abdf88493ecca" name="Server.php" role="php">
8301+ <tasks:replace from="@package_version@" to="version" type="package-info" />
8302+ </file>
8303+ </dir>
8304+ </contents>
8305+ <compatible>
8306+ <name>PEAR</name>
8307+ <channel>pear.php.net</channel>
8308+ <min>1.4.0a1</min>
8309+ <max>1.4.0a12</max>
8310+ </compatible>
8311+ <dependencies>
8312+ <required>
8313+ <php>
8314+ <min>4.2.0</min>
8315+ <max>6.0.0</max>
8316+ </php>
8317+ <pearinstaller>
8318+ <min>1.4.0a1</min>
8319+ </pearinstaller>
8320+ </required>
8321+ </dependencies>
8322+ <phprelease />
8323+ <changelog>
8324+ <release>
8325+ <version>
8326+ <release>1.3.3</release>
8327+ <api>1.3.0</api>
8328+ </version>
8329+ <stability>
8330+ <release>stable</release>
8331+ <api>stable</api>
8332+ </stability>
8333+ <date>2005-07-15</date>
8334+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8335+ <notes>* Eliminate memory leak by resetting $XML_RPC_xh each time parseResponse() is called. Bug 4780.
8336+* Using socket_set_timeout() because stream_set_timeout() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.</notes>
8337+ </release>
8338+ <release>
8339+ <version>
8340+ <release>1.3.2</release>
8341+ <api>1.3.0</api>
8342+ </version>
8343+ <stability>
8344+ <release>stable</release>
8345+ <api>stable</api>
8346+ </stability>
8347+ <date>2005-07-07</date>
8348+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8349+ <notes>* Eliminate path disclosure vulnerabilities by suppressing error messages when eval()&apos;ing.
8350+* Eliminate path disclosure vulnerability by catching bogus parameters submitted to XML_RPC_Value::serializeval().
8351+* In XML_RPC_Server::service(), only call createServerPayload() and createServerHeaders() if necessary. Fixes compatibility issue introduced in Release 1.3.0RC1 for users who set the $serviceNow parameter of XML_RPC_Server() to 0. Bug 4757.
8352+* Change &quot;var $errstring&quot; to &quot;var $errstr&quot;. Bug 4582. Was put into CVS version 1.75 of RPC.php but didn&apos;t make it into RELEASE_1_3_1.</notes>
8353+ </release>
8354+ <release>
8355+ <version>
8356+ <release>1.3.1</release>
8357+ <api>1.3.0</api>
8358+ </version>
8359+ <stability>
8360+ <release>stable</release>
8361+ <api>stable</api>
8362+ </stability>
8363+ <date>2005-06-29</date>
8364+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8365+ <notes>* Security fix. Update highly recommended!</notes>
8366+ </release>
8367+ <release>
8368+ <version>
8369+ <release>1.3.0</release>
8370+ <api>1.3.0</api>
8371+ </version>
8372+ <stability>
8373+ <release>stable</release>
8374+ <api>stable</api>
8375+ </stability>
8376+ <date>2005-06-13</date>
8377+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8378+ <notes>* Stable release. See earlier releases for changes since 1.2.2.</notes>
8379+ </release>
8380+ <release>
8381+ <version>
8382+ <release>1.3.0RC3</release>
8383+ <api>1.3.0</api>
8384+ </version>
8385+ <stability>
8386+ <release>beta</release>
8387+ <api>stable</api>
8388+ </stability>
8389+ <date>2005-05-10</date>
8390+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8391+ <notes>* When verifying requests against function signatures, if the number of parameters don&apos;t match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
8392+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
8393+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
8394+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
8395+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
8396+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().</notes>
8397+ </release>
8398+ <release>
8399+ <version>
8400+ <release>1.3.0RC2</release>
8401+ <api>1.3.0</api>
8402+ </version>
8403+ <stability>
8404+ <release>beta</release>
8405+ <api>beta</api>
8406+ </stability>
8407+ <date>2005-05-05</date>
8408+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8409+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
8410+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
8411+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
8412+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.</notes>
8413+ </release>
8414+ <release>
8415+ <version>
8416+ <release>1.3.0RC1</release>
8417+ <api>1.3.0</api>
8418+ </version>
8419+ <stability>
8420+ <release>beta</release>
8421+ <api>beta</api>
8422+ </stability>
8423+ <date>2005-04-07</date>
8424+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8425+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
8426+* Add Fault Code 6: &quot;The requested method didn&apos;t return an XML_RPC_Response object.&quot; Request 4032.
8427+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
8428+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
8429+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
8430+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.</notes>
8431+ </release>
8432+ <release>
8433+ <version>
8434+ <release>1.2.2</release>
8435+ <api>1.2.0</api>
8436+ </version>
8437+ <stability>
8438+ <release>stable</release>
8439+ <api>stable</api>
8440+ </stability>
8441+ <date>2005-03-07</date>
8442+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8443+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.</notes>
8444+ </release>
8445+ <release>
8446+ <version>
8447+ <release>1.2.1</release>
8448+ <api>1.2.0</api>
8449+ </version>
8450+ <stability>
8451+ <release>stable</release>
8452+ <api>stable</api>
8453+ </stability>
8454+ <date>2005-03-01</date>
8455+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8456+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.</notes>
8457+ </release>
8458+ <release>
8459+ <version>
8460+ <release>1.2.0</release>
8461+ <api>1.2.0</api>
8462+ </version>
8463+ <stability>
8464+ <release>stable</release>
8465+ <api>stable</api>
8466+ </stability>
8467+ <date>2005-02-27</date>
8468+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8469+ <notes>* Provide the &quot;stable&quot; release.
8470+* Add package2.xml for compatibility with PEAR 1.4.0.
8471+* For changes since 1.1.0, see the changelogs for the various RC releases.</notes>
8472+ </release>
8473+ <release>
8474+ <version>
8475+ <release>1.2.0RC7</release>
8476+ <api>1.2.0RC7</api>
8477+ </version>
8478+ <stability>
8479+ <release>beta</release>
8480+ <api>beta</api>
8481+ </stability>
8482+ <date>2005-02-22</date>
8483+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8484+ <notes>* Add the setSendEncoding() method and $send_encoding
8485+ property to XML_RPC_Message. Request 3537.
8486+* Allow class methods to be mapped using either syntax:
8487+ &apos;function&apos; =&gt; &apos;hello::sayHello&apos;,
8488+ or
8489+ &apos;function&apos; =&gt; array(&apos;hello&apos;, &apos;sayhello&apos;),
8490+ Bug 3363.
8491+* Use 8192 instead of 32768 for bytes in fread()
8492+ in parseResponseFile(). Bug 3340.</notes>
8493+ </release>
8494+ <release>
8495+ <version>
8496+ <release>1.2.0RC6</release>
8497+ <api>1.2.0RC6</api>
8498+ </version>
8499+ <stability>
8500+ <release>beta</release>
8501+ <api>beta</api>
8502+ </stability>
8503+ <date>2005-01-25</date>
8504+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8505+ <notes>* Don&apos;t put the protocol in the Host field of the POST data. (danielc)</notes>
8506+ </release>
8507+ <release>
8508+ <version>
8509+ <release>1.2.0RC5</release>
8510+ <api>1.2.0RC5</api>
8511+ </version>
8512+ <stability>
8513+ <release>beta</release>
8514+ <api>beta</api>
8515+ </stability>
8516+ <date>2005-01-24</date>
8517+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8518+ <notes>* If $port is 443 but a protocol isn&apos;t specified in $server, assume ssl:// is the protocol.</notes>
8519+ </release>
8520+ <release>
8521+ <version>
8522+ <release>1.2.0RC4</release>
8523+ <api>1.2.0RC4</api>
8524+ </version>
8525+ <stability>
8526+ <release>beta</release>
8527+ <api>beta</api>
8528+ </stability>
8529+ <date>2005-01-24</date>
8530+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8531+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
8532+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
8533+* Add tests for setting the client properties. (danielc)
8534+* Remove $GLOBALS[&apos;XML_RPC_twoslash&apos;] since it&apos;s not used. (danielc)
8535+* Bundle the tests with the package. (danielc)</notes>
8536+ </release>
8537+ <release>
8538+ <version>
8539+ <release>1.2.0RC3</release>
8540+ <api>1.2.0RC3</api>
8541+ </version>
8542+ <stability>
8543+ <release>beta</release>
8544+ <api>beta</api>
8545+ </stability>
8546+ <date>2005-01-19</date>
8547+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8548+ <notes>* ssl uses port 443, not 445.</notes>
8549+ </release>
8550+ <release>
8551+ <version>
8552+ <release>1.2.0RC2</release>
8553+ <api>1.2.0RC2</api>
8554+ </version>
8555+ <stability>
8556+ <release>beta</release>
8557+ <api>beta</api>
8558+ </stability>
8559+ <date>2005-01-11</date>
8560+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8561+ <notes>* Handle ssl:// in the $server string. (danielc)
8562+* Also default to port 445 for ssl:// requests as well. (danielc)
8563+* Enhance debugging in the server. (danielc)</notes>
8564+ </release>
8565+ <release>
8566+ <version>
8567+ <release>1.2.0RC1</release>
8568+ <api>1.2.0RC1</api>
8569+ </version>
8570+ <stability>
8571+ <release>beta</release>
8572+ <api>beta</api>
8573+ </stability>
8574+ <date>2004-12-30</date>
8575+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8576+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
8577+* Allow array function callbacks (Matt Kane)
8578+* Some minor speed-ups (Matt Kane)
8579+* Add Dump.php to the package (Christian Weiske)
8580+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
8581+* Silence fsockopen() errors. Bug 1714. (danielc)
8582+* Encode empty arrays as an array. Bug 1493. (danielc)
8583+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
8584+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
8585+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()&apos;ing error messages. (danielc)
8586+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
8587+* Allow raiseError() to be called statically. (danielc)
8588+* Stop double escaping of character entities. Bug 987. (danielc)
8589+ NOTICE: the following have been removed:
8590+ * XML_RPC_dh()
8591+ * $GLOBALS[&apos;XML_RPC_entities&apos;]
8592+ * XML_RPC_entity_decode()
8593+ * XML_RPC_lookup_entity()
8594+* Determine the XML&apos;s encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)</notes>
8595+ </release>
8596+ <release>
8597+ <version>
8598+ <release>1.1.0</release>
8599+ <api>1.1.0</api>
8600+ </version>
8601+ <stability>
8602+ <release>stable</release>
8603+ <api>stable</api>
8604+ </stability>
8605+ <date>2004-03-15</date>
8606+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8607+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
8608+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
8609+* Remove &quot;require_once &apos;PEAR.php&apos;&quot;, include only when needed to raise an error
8610+* Replace echo and error_log() with raiseError() (mroch)
8611+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
8612+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
8613+* Silent notice even in the error log (pierre)
8614+* fix include of shared xml extension on win32 (pierre)</notes>
8615+ </release>
8616+ <release>
8617+ <version>
8618+ <release>1.0.4</release>
8619+ <api>1.0.4</api>
8620+ </version>
8621+ <stability>
8622+ <release>stable</release>
8623+ <api>stable</api>
8624+ </stability>
8625+ <date>2002-10-02</date>
8626+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8627+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)</notes>
8628+ </release>
8629+ <release>
8630+ <version>
8631+ <release>1.0.3</release>
8632+ <api>1.0.3</api>
8633+ </version>
8634+ <stability>
8635+ <release>stable</release>
8636+ <api>stable</api>
8637+ </stability>
8638+ <date>2002-05-19</date>
8639+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8640+ <notes>* fix bug when parsing responses with boolean types</notes>
8641+ </release>
8642+ <release>
8643+ <version>
8644+ <release>1.0.2</release>
8645+ <api>1.0.2</api>
8646+ </version>
8647+ <stability>
8648+ <release>stable</release>
8649+ <api>stable</api>
8650+ </stability>
8651+ <date>2002-04-16</date>
8652+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8653+ <notes>* E_ALL fixes
8654+* fix HTTP response header parsing</notes>
8655+ </release>
8656+ <release>
8657+ <version>
8658+ <release>1.0.1</release>
8659+ <api>1.0.1</api>
8660+ </version>
8661+ <stability>
8662+ <release>stable</release>
8663+ <api>stable</api>
8664+ </stability>
8665+ <date>2001-09-25</date>
8666+ <license uri="http://www.php.net/license/3_0.txt">PHP License</license>
8667+ <notes>This is a PEAR-ified version of Useful Inc&apos;s 1.0.1 release.
8668+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.</notes>
8669+ </release>
8670+ </changelog>
8671+</package>
8672+
8673+
8674+/**
8675+ * Tests that properties of XML_RPC_Client get properly set
8676+ *
8677+ * Any individual tests that fail will have their name, expected result
8678+ * and actual result printed out. So seeing no output when executing
8679+ * this file is a good thing.
8680+ *
8681+ * Can be run via CLI or a web server.
8682+ *
8683+ * PHP versions 4 and 5
8684+ *
8685+ * LICENSE: This source file is subject to version 3.0 of the PHP license
8686+ * that is available through the world-wide-web at the following URI:
8687+ * http://www.php.net/license/3_0.txt. If you did not receive a copy of
8688+ * the PHP License and are unable to obtain it through the web, please
8689+ * send a note to license@php.net so we can mail you a copy immediately.
8690+ *
8691+ * @category Web Services
8692+ * @package XML_RPC
8693+ * @author Daniel Convissor <danielc@php.net>
8694+ * @copyright 2005 The PHP Group
8695+ * @license http://www.php.net/license/3_0.txt PHP License
8696+ * @version CVS: $Id: protoport.php,v 1.4 2005/01/24 17:48:47 danielc Exp $
8697+ * @link http://pear.php.net/package/XML_RPC
8698+ * @since File available since Release 1.2
8699+ */
8700+
8701+/*
8702+ * If the package version number is found in the left hand
8703+ * portion of the if() expression below, that means this file has
8704+ * come from the PEAR installer. Therefore, let's test the
8705+ * installed version of XML_RPC which should be in the include path.
8706+ *
8707+ * If the version has not been substituted in the if() expression,
8708+ * this file has likely come from a CVS checkout or a .tar file.
8709+ * Therefore, we'll assume the tests should use the version of
8710+ * XML_RPC that has come from there as well.
8711+ */
8712+if ('1.4.0' != '@'.'package_version'.'@') {
8713+ /**
8714+ * Get the needed class from the PEAR installation
8715+ */
8716+ require_once 'XML/RPC.php';
8717+} else {
8718+ /**
8719+ * Get the needed class from the parent directory
8720+ */
8721+ require_once '../RPC.php';
8722+}
8723+
8724+/**
8725+ * Compare the test result to the expected result
8726+ *
8727+ * If the test fails, echo out the results.
8728+ *
8729+ * @param array $expect the array of object properties you expect
8730+ * from the test
8731+ * @param object $actual the object results from the test
8732+ * @param string $test_name the name of the test
8733+ *
8734+ * @return void
8735+ */
8736+function compare($expect, $actual, $test_name) {
8737+ $actual = get_object_vars($actual);
8738+ if (count(array_diff($actual, $expect))) {
8739+ echo "$test_name failed.\nExpect: ";
8740+ print_r($expect);
8741+ echo "Actual: ";
8742+ print_r($actual);
8743+ echo "\n";
8744+ }
8745+}
8746+
8747+if (php_sapi_name() != 'cli') {
8748+ echo "<pre>\n";
8749+}
8750+
8751+
8752+$x = array(
8753+ 'path' => 'thepath',
8754+ 'server' => 'theserver',
8755+ 'protocol' => 'http://',
8756+ 'port' => 80,
8757+ 'proxy' => '',
8758+ 'proxy_protocol' => 'http://',
8759+ 'proxy_port' => 8080,
8760+ 'proxy_user' => '',
8761+ 'proxy_pass' => '',
8762+ 'errno' => 0,
8763+ 'errstring' => '',
8764+ 'debug' => 0,
8765+ 'username' => '',
8766+ 'password' => '',
8767+);
8768+$c = new XML_RPC_Client('thepath', 'theserver');
8769+compare($x, $c, 'defaults');
8770+
8771+$x = array(
8772+ 'path' => 'thepath',
8773+ 'server' => 'theserver',
8774+ 'protocol' => 'http://',
8775+ 'port' => 80,
8776+ 'proxy' => '',
8777+ 'proxy_protocol' => 'http://',
8778+ 'proxy_port' => 8080,
8779+ 'proxy_user' => '',
8780+ 'proxy_pass' => '',
8781+ 'errno' => 0,
8782+ 'errstring' => '',
8783+ 'debug' => 0,
8784+ 'username' => '',
8785+ 'password' => '',
8786+);
8787+$c = new XML_RPC_Client('thepath', 'http://theserver');
8788+compare($x, $c, 'defaults with http');
8789+
8790+$x = array(
8791+ 'path' => 'thepath',
8792+ 'server' => 'theserver',
8793+ 'protocol' => 'ssl://',
8794+ 'port' => 443,
8795+ 'proxy' => '',
8796+ 'proxy_protocol' => 'http://',
8797+ 'proxy_port' => 8080,
8798+ 'proxy_user' => '',
8799+ 'proxy_pass' => '',
8800+ 'errno' => 0,
8801+ 'errstring' => '',
8802+ 'debug' => 0,
8803+ 'username' => '',
8804+ 'password' => '',
8805+);
8806+$c = new XML_RPC_Client('thepath', 'https://theserver');
8807+compare($x, $c, 'defaults with https');
8808+
8809+$x = array(
8810+ 'path' => 'thepath',
8811+ 'server' => 'theserver',
8812+ 'protocol' => 'ssl://',
8813+ 'port' => 443,
8814+ 'proxy' => '',
8815+ 'proxy_protocol' => 'http://',
8816+ 'proxy_port' => 8080,
8817+ 'proxy_user' => '',
8818+ 'proxy_pass' => '',
8819+ 'errno' => 0,
8820+ 'errstring' => '',
8821+ 'debug' => 0,
8822+ 'username' => '',
8823+ 'password' => '',
8824+);
8825+$c = new XML_RPC_Client('thepath', 'ssl://theserver');
8826+compare($x, $c, 'defaults with ssl');
8827+
8828+
8829+$x = array(
8830+ 'path' => 'thepath',
8831+ 'server' => 'theserver',
8832+ 'protocol' => 'http://',
8833+ 'port' => 65,
8834+ 'proxy' => '',
8835+ 'proxy_protocol' => 'http://',
8836+ 'proxy_port' => 8080,
8837+ 'proxy_user' => '',
8838+ 'proxy_pass' => '',
8839+ 'errno' => 0,
8840+ 'errstring' => '',
8841+ 'debug' => 0,
8842+ 'username' => '',
8843+ 'password' => '',
8844+);
8845+$c = new XML_RPC_Client('thepath', 'theserver', 65);
8846+compare($x, $c, 'port 65');
8847+
8848+$x = array(
8849+ 'path' => 'thepath',
8850+ 'server' => 'theserver',
8851+ 'protocol' => 'http://',
8852+ 'port' => 65,
8853+ 'proxy' => '',
8854+ 'proxy_protocol' => 'http://',
8855+ 'proxy_port' => 8080,
8856+ 'proxy_user' => '',
8857+ 'proxy_pass' => '',
8858+ 'errno' => 0,
8859+ 'errstring' => '',
8860+ 'debug' => 0,
8861+ 'username' => '',
8862+ 'password' => '',
8863+);
8864+$c = new XML_RPC_Client('thepath', 'http://theserver', 65);
8865+compare($x, $c, 'port 65 with http');
8866+
8867+$x = array(
8868+ 'path' => 'thepath',
8869+ 'server' => 'theserver',
8870+ 'protocol' => 'ssl://',
8871+ 'port' => 65,
8872+ 'proxy' => '',
8873+ 'proxy_protocol' => 'http://',
8874+ 'proxy_port' => 8080,
8875+ 'proxy_user' => '',
8876+ 'proxy_pass' => '',
8877+ 'errno' => 0,
8878+ 'errstring' => '',
8879+ 'debug' => 0,
8880+ 'username' => '',
8881+ 'password' => '',
8882+);
8883+$c = new XML_RPC_Client('thepath', 'https://theserver', 65);
8884+compare($x, $c, 'port 65 with https');
8885+
8886+$x = array(
8887+ 'path' => 'thepath',
8888+ 'server' => 'theserver',
8889+ 'protocol' => 'ssl://',
8890+ 'port' => 65,
8891+ 'proxy' => '',
8892+ 'proxy_protocol' => 'http://',
8893+ 'proxy_port' => 8080,
8894+ 'proxy_user' => '',
8895+ 'proxy_pass' => '',
8896+ 'errno' => 0,
8897+ 'errstring' => '',
8898+ 'debug' => 0,
8899+ 'username' => '',
8900+ 'password' => '',
8901+);
8902+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65);
8903+compare($x, $c, 'port 65 with ssl');
8904+
8905+
8906+$x = array(
8907+ 'path' => 'thepath',
8908+ 'server' => 'theserver',
8909+ 'protocol' => 'http://',
8910+ 'port' => 80,
8911+ 'proxy' => 'theproxy',
8912+ 'proxy_protocol' => 'http://',
8913+ 'proxy_port' => 8080,
8914+ 'proxy_user' => '',
8915+ 'proxy_pass' => '',
8916+ 'errno' => 0,
8917+ 'errstring' => '',
8918+ 'debug' => 0,
8919+ 'username' => '',
8920+ 'password' => '',
8921+);
8922+$c = new XML_RPC_Client('thepath', 'theserver', 0,
8923+ 'theproxy');
8924+compare($x, $c, 'defaults proxy');
8925+
8926+$x = array(
8927+ 'path' => 'thepath',
8928+ 'server' => 'theserver',
8929+ 'protocol' => 'http://',
8930+ 'port' => 80,
8931+ 'proxy' => 'theproxy',
8932+ 'proxy_protocol' => 'http://',
8933+ 'proxy_port' => 8080,
8934+ 'proxy_user' => '',
8935+ 'proxy_pass' => '',
8936+ 'errno' => 0,
8937+ 'errstring' => '',
8938+ 'debug' => 0,
8939+ 'username' => '',
8940+ 'password' => '',
8941+);
8942+$c = new XML_RPC_Client('thepath', 'http://theserver', 0,
8943+ 'http://theproxy');
8944+compare($x, $c, 'defaults with http proxy');
8945+
8946+$x = array(
8947+ 'path' => 'thepath',
8948+ 'server' => 'theserver',
8949+ 'protocol' => 'ssl://',
8950+ 'port' => 443,
8951+ 'proxy' => 'theproxy',
8952+ 'proxy_protocol' => 'ssl://',
8953+ 'proxy_port' => 443,
8954+ 'proxy_user' => '',
8955+ 'proxy_pass' => '',
8956+ 'errno' => 0,
8957+ 'errstring' => '',
8958+ 'debug' => 0,
8959+ 'username' => '',
8960+ 'password' => '',
8961+);
8962+$c = new XML_RPC_Client('thepath', 'https://theserver', 0,
8963+ 'https://theproxy');
8964+compare($x, $c, 'defaults with https proxy');
8965+
8966+$x = array(
8967+ 'path' => 'thepath',
8968+ 'server' => 'theserver',
8969+ 'protocol' => 'ssl://',
8970+ 'port' => 443,
8971+ 'proxy' => 'theproxy',
8972+ 'proxy_protocol' => 'ssl://',
8973+ 'proxy_port' => 443,
8974+ 'proxy_user' => '',
8975+ 'proxy_pass' => '',
8976+ 'errno' => 0,
8977+ 'errstring' => '',
8978+ 'debug' => 0,
8979+ 'username' => '',
8980+ 'password' => '',
8981+);
8982+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 0,
8983+ 'ssl://theproxy');
8984+compare($x, $c, 'defaults with ssl proxy');
8985+
8986+
8987+$x = array(
8988+ 'path' => 'thepath',
8989+ 'server' => 'theserver',
8990+ 'protocol' => 'http://',
8991+ 'port' => 65,
8992+ 'proxy' => 'theproxy',
8993+ 'proxy_protocol' => 'http://',
8994+ 'proxy_port' => 6565,
8995+ 'proxy_user' => '',
8996+ 'proxy_pass' => '',
8997+ 'errno' => 0,
8998+ 'errstring' => '',
8999+ 'debug' => 0,
9000+ 'username' => '',
9001+ 'password' => '',
9002+);
9003+$c = new XML_RPC_Client('thepath', 'theserver', 65,
9004+ 'theproxy', 6565);
9005+compare($x, $c, 'port 65 proxy 6565');
9006+
9007+$x = array(
9008+ 'path' => 'thepath',
9009+ 'server' => 'theserver',
9010+ 'protocol' => 'http://',
9011+ 'port' => 65,
9012+ 'proxy' => 'theproxy',
9013+ 'proxy_protocol' => 'http://',
9014+ 'proxy_port' => 6565,
9015+ 'proxy_user' => '',
9016+ 'proxy_pass' => '',
9017+ 'errno' => 0,
9018+ 'errstring' => '',
9019+ 'debug' => 0,
9020+ 'username' => '',
9021+ 'password' => '',
9022+);
9023+$c = new XML_RPC_Client('thepath', 'http://theserver', 65,
9024+ 'http://theproxy', 6565);
9025+compare($x, $c, 'port 65 with http proxy 6565');
9026+
9027+$x = array(
9028+ 'path' => 'thepath',
9029+ 'server' => 'theserver',
9030+ 'protocol' => 'ssl://',
9031+ 'port' => 65,
9032+ 'proxy' => 'theproxy',
9033+ 'proxy_protocol' => 'ssl://',
9034+ 'proxy_port' => 6565,
9035+ 'proxy_user' => '',
9036+ 'proxy_pass' => '',
9037+ 'errno' => 0,
9038+ 'errstring' => '',
9039+ 'debug' => 0,
9040+ 'username' => '',
9041+ 'password' => '',
9042+);
9043+$c = new XML_RPC_Client('thepath', 'https://theserver', 65,
9044+ 'https://theproxy', 6565);
9045+compare($x, $c, 'port 65 with https proxy 6565');
9046+
9047+$x = array(
9048+ 'path' => 'thepath',
9049+ 'server' => 'theserver',
9050+ 'protocol' => 'ssl://',
9051+ 'port' => 65,
9052+ 'proxy' => 'theproxy',
9053+ 'proxy_protocol' => 'ssl://',
9054+ 'proxy_port' => 6565,
9055+ 'proxy_user' => '',
9056+ 'proxy_pass' => '',
9057+ 'errno' => 0,
9058+ 'errstring' => '',
9059+ 'debug' => 0,
9060+ 'username' => '',
9061+ 'password' => '',
9062+);
9063+$c = new XML_RPC_Client('thepath', 'ssl://theserver', 65,
9064+ 'ssl://theproxy', 6565);
9065+compare($x, $c, 'port 65 with ssl proxy 6565');
9066+
9067+
9068+$x = array(
9069+ 'path' => 'thepath',
9070+ 'server' => 'theserver',
9071+ 'protocol' => 'ssl://',
9072+ 'port' => 443,
9073+ 'proxy' => 'theproxy',
9074+ 'proxy_protocol' => 'ssl://',
9075+ 'proxy_port' => 443,
9076+ 'proxy_user' => '',
9077+ 'proxy_pass' => '',
9078+ 'errno' => 0,
9079+ 'errstring' => '',
9080+ 'debug' => 0,
9081+ 'username' => '',
9082+ 'password' => '',
9083+);
9084+$c = new XML_RPC_Client('thepath', 'theserver', 443,
9085+ 'theproxy', 443);
9086+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
9087+
9088+$x = array(
9089+ 'path' => 'thepath',
9090+ 'server' => 'theserver',
9091+ 'protocol' => 'http://',
9092+ 'port' => 80,
9093+ 'proxy' => 'theproxy',
9094+ 'proxy_protocol' => 'ssl://',
9095+ 'proxy_port' => 6565,
9096+ 'proxy_user' => '',
9097+ 'proxy_pass' => '',
9098+ 'errno' => 0,
9099+ 'errstring' => '',
9100+ 'debug' => 0,
9101+ 'username' => '',
9102+ 'password' => '',
9103+);
9104+$c = new XML_RPC_Client('thepath', 'theserver', 0,
9105+ 'ssl://theproxy', 6565);
9106+compare($x, $c, 'port 443 no protocol and proxy port 443 no protocol');
9107+
9108+
9109+/*
9110+ * If the package version number is found in the left hand
9111+ * portion of the if() expression below, that means this file has
9112+ * come from the PEAR installer. Therefore, let's test the
9113+ * installed version of XML_RPC which should be in the include path.
9114+ *
9115+ * If the version has not been substituted in the if() expression,
9116+ * this file has likely come from a CVS checkout or a .tar file.
9117+ * Therefore, we'll assume the tests should use the version of
9118+ * XML_RPC that has come from there as well.
9119+ */
9120+if ('1.4.0' != '@'.'package_version'.'@') {
9121+ /**
9122+ * Get the needed class from the PEAR installation
9123+ */
9124+ require_once 'XML/RPC/Dump.php';
9125+} else {
9126+ /**
9127+ * Get the needed class from the parent directory
9128+ */
9129+ require_once '../Dump.php';
9130+}
9131+
9132+$val = new XML_RPC_Value(array(
9133+ 'title' =>new XML_RPC_Value('das ist der Titel', 'string'),
9134+ 'startDate'=>new XML_RPC_Value(mktime(0,0,0,13,11,2004), 'dateTime.iso8601'),
9135+ 'endDate' =>new XML_RPC_Value(mktime(0,0,0,15,11,2004), 'dateTime.iso8601'),
9136+ 'error' =>'string',
9137+ 'arkey' => new XML_RPC_Value( array(
9138+ new XML_RPC_Value('simple string'),
9139+ new XML_RPC_Value(12345, 'int')
9140+ ), 'array')
9141+ )
9142+ ,'struct');
9143+
9144+XML_RPC_Dump($val);
9145+
9146+echo '==============' . "\r\n";
9147+$val2 = new XML_RPC_Value(44353, 'int');
9148+XML_RPC_Dump($val2);
9149+
9150+echo '==============' . "\r\n";
9151+$val3 = new XML_RPC_Value('this should be a string', 'string');
9152+XML_RPC_Dump($val3);
9153+
9154+echo '==============' . "\r\n";
9155+$val4 = new XML_RPC_Value(true, 'boolean');
9156+XML_RPC_Dump($val4);
9157+
9158+
9159+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
9160+
9161+/**
9162+ * Function and class to dump XML_RPC_Value objects in a nice way
9163+ *
9164+ * Should be helpful as a normal var_dump(..) displays all internals which
9165+ * doesn't really give you an overview due to too much information.
9166+ *
9167+ * @category Web Services
9168+ * @package XML_RPC
9169+ * @author Christian Weiske <cweiske@php.net>
9170+ * @version CVS: $Id: Dump.php,v 1.7 2005/01/24 03:47:55 danielc Exp $
9171+ * @link http://pear.php.net/package/XML_RPC
9172+ */
9173+
9174+
9175+/**
9176+ * Pull in the XML_RPC class
9177+ */
9178+require_once 'XML/RPC.php';
9179+
9180+
9181+/**
9182+ * Generates the dump of the XML_RPC_Value and echoes it
9183+ *
9184+ * @param object $value the XML_RPC_Value object to dump
9185+ *
9186+ * @return void
9187+ */
9188+function XML_RPC_Dump($value)
9189+{
9190+ $dumper = new XML_RPC_Dump();
9191+ echo $dumper->generateDump($value);
9192+}
9193+
9194+
9195+/**
9196+ * Class which generates a dump of a XML_RPC_Value object
9197+ *
9198+ * @category Web Services
9199+ * @package XML_RPC
9200+ * @author Christian Weiske <cweiske@php.net>
9201+ * @version Release: 1.4.0
9202+ * @link http://pear.php.net/package/XML_RPC
9203+ */
9204+class XML_RPC_Dump
9205+{
9206+ /**
9207+ * The indentation array cache
9208+ * @var array
9209+ */
9210+ var $arIndent = array();
9211+
9212+ /**
9213+ * The spaces used for indenting the XML
9214+ * @var string
9215+ */
9216+ var $strBaseIndent = ' ';
9217+
9218+ /**
9219+ * Returns the dump in XML format without printing it out
9220+ *
9221+ * @param object $value the XML_RPC_Value object to dump
9222+ * @param int $nLevel the level of indentation
9223+ *
9224+ * @return string the dump
9225+ */
9226+ function generateDump($value, $nLevel = 0)
9227+ {
9228+ if (!is_object($value) && get_class($value) != 'xml_rpc_value') {
9229+ require_once 'PEAR.php';
9230+ PEAR::raiseError('Tried to dump non-XML_RPC_Value variable' . "\r\n",
9231+ 0, PEAR_ERROR_PRINT);
9232+ if (is_object($value)) {
9233+ $strType = get_class($value);
9234+ } else {
9235+ $strType = gettype($value);
9236+ }
9237+ return $this->getIndent($nLevel) . 'NOT A XML_RPC_Value: '
9238+ . $strType . "\r\n";
9239+ }
9240+
9241+ switch ($value->kindOf()) {
9242+ case 'struct':
9243+ $ret = $this->genStruct($value, $nLevel);
9244+ break;
9245+ case 'array':
9246+ $ret = $this->genArray($value, $nLevel);
9247+ break;
9248+ case 'scalar':
9249+ $ret = $this->genScalar($value->scalarval(), $nLevel);
9250+ break;
9251+ default:
9252+ require_once 'PEAR.php';
9253+ PEAR::raiseError('Illegal type "' . $value->kindOf()
9254+ . '" in XML_RPC_Value' . "\r\n", 0,
9255+ PEAR_ERROR_PRINT);
9256+ }
9257+
9258+ return $ret;
9259+ }
9260+
9261+ /**
9262+ * Returns the scalar value dump
9263+ *
9264+ * @param object $value the scalar XML_RPC_Value object to dump
9265+ * @param int $nLevel the level of indentation
9266+ *
9267+ * @return string Dumped version of the scalar value
9268+ */
9269+ function genScalar($value, $nLevel)
9270+ {
9271+ if (gettype($value) == 'object') {
9272+ $strClass = ' ' . get_class($value);
9273+ } else {
9274+ $strClass = '';
9275+ }
9276+ return $this->getIndent($nLevel) . gettype($value) . $strClass
9277+ . ' ' . $value . "\r\n";
9278+ }
9279+
9280+ /**
9281+ * Returns the dump of a struct
9282+ *
9283+ * @param object $value the struct XML_RPC_Value object to dump
9284+ * @param int $nLevel the level of indentation
9285+ *
9286+ * @return string Dumped version of the scalar value
9287+ */
9288+ function genStruct($value, $nLevel)
9289+ {
9290+ $value->structreset();
9291+ $strOutput = $this->getIndent($nLevel) . 'struct' . "\r\n";
9292+ while (list($key, $keyval) = $value->structeach()) {
9293+ $strOutput .= $this->getIndent($nLevel + 1) . $key . "\r\n";
9294+ $strOutput .= $this->generateDump($keyval, $nLevel + 2);
9295+ }
9296+ return $strOutput;
9297+ }
9298+
9299+ /**
9300+ * Returns the dump of an array
9301+ *
9302+ * @param object $value the array XML_RPC_Value object to dump
9303+ * @param int $nLevel the level of indentation
9304+ *
9305+ * @return string Dumped version of the scalar value
9306+ */
9307+ function genArray($value, $nLevel)
9308+ {
9309+ $nSize = $value->arraysize();
9310+ $strOutput = $this->getIndent($nLevel) . 'array' . "\r\n";
9311+ for($nA = 0; $nA < $nSize; $nA++) {
9312+ $strOutput .= $this->getIndent($nLevel + 1) . $nA . "\r\n";
9313+ $strOutput .= $this->generateDump($value->arraymem($nA),
9314+ $nLevel + 2);
9315+ }
9316+ return $strOutput;
9317+ }
9318+
9319+ /**
9320+ * Returns the indent for a specific level and caches it for faster use
9321+ *
9322+ * @param int $nLevel the level
9323+ *
9324+ * @return string the indented string
9325+ */
9326+ function getIndent($nLevel)
9327+ {
9328+ if (!isset($this->arIndent[$nLevel])) {
9329+ $this->arIndent[$nLevel] = str_repeat($this->strBaseIndent, $nLevel);
9330+ }
9331+ return $this->arIndent[$nLevel];
9332+ }
9333+}
9334+
9335+/*
9336+ * Local variables:
9337+ * tab-width: 4
9338+ * c-basic-offset: 4
9339+ * c-hanging-comment-ender-p: nil
9340+ * End:
9341+ */
9342+
9343+?>
9344+
9345+
9346+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
9347+
9348+/**
9349+ * PHP implementation of the XML-RPC protocol
9350+ *
9351+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
9352+ * It has support for HTTP transport, proxies and authentication.
9353+ *
9354+ * PHP versions 4 and 5
9355+ *
9356+ * LICENSE: License is granted to use or modify this software
9357+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
9358+ * copyright of the author is preserved in any distributed or derivative work.
9359+ *
9360+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
9361+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
9362+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9363+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
9364+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9365+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
9366+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
9367+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
9368+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
9369+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9370+ *
9371+ * @category Web Services
9372+ * @package XML_RPC
9373+ * @author Edd Dumbill <edd@usefulinc.com>
9374+ * @author Stig Bakken <stig@php.net>
9375+ * @author Martin Jansen <mj@php.net>
9376+ * @author Daniel Convissor <danielc@php.net>
9377+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9378+ * @version CVS: $Id: RPC.php,v 1.83 2005/08/14 20:25:35 danielc Exp $
9379+ * @link http://pear.php.net/package/XML_RPC
9380+ */
9381+
9382+
9383+if (!function_exists('xml_parser_create')) {
9384+ PEAR::loadExtension('xml');
9385+}
9386+
9387+/**#@+
9388+ * Error constants
9389+ */
9390+/**
9391+ * Parameter values don't match parameter types
9392+ */
9393+define('XML_RPC_ERROR_INVALID_TYPE', 101);
9394+/**
9395+ * Parameter declared to be numeric but the values are not
9396+ */
9397+define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102);
9398+/**
9399+ * Communication error
9400+ */
9401+define('XML_RPC_ERROR_CONNECTION_FAILED', 103);
9402+/**
9403+ * The array or struct has already been started
9404+ */
9405+define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
9406+/**
9407+ * Incorrect parameters submitted
9408+ */
9409+define('XML_RPC_ERROR_INCORRECT_PARAMS', 105);
9410+/**
9411+ * Programming error by developer
9412+ */
9413+define('XML_RPC_ERROR_PROGRAMMING', 106);
9414+/**#@-*/
9415+
9416+
9417+/**
9418+ * Data types
9419+ * @global string $GLOBALS['XML_RPC_I4']
9420+ */
9421+$GLOBALS['XML_RPC_I4'] = 'i4';
9422+
9423+/**
9424+ * Data types
9425+ * @global string $GLOBALS['XML_RPC_Int']
9426+ */
9427+$GLOBALS['XML_RPC_Int'] = 'int';
9428+
9429+/**
9430+ * Data types
9431+ * @global string $GLOBALS['XML_RPC_Boolean']
9432+ */
9433+$GLOBALS['XML_RPC_Boolean'] = 'boolean';
9434+
9435+/**
9436+ * Data types
9437+ * @global string $GLOBALS['XML_RPC_Double']
9438+ */
9439+$GLOBALS['XML_RPC_Double'] = 'double';
9440+
9441+/**
9442+ * Data types
9443+ * @global string $GLOBALS['XML_RPC_String']
9444+ */
9445+$GLOBALS['XML_RPC_String'] = 'string';
9446+
9447+/**
9448+ * Data types
9449+ * @global string $GLOBALS['XML_RPC_DateTime']
9450+ */
9451+$GLOBALS['XML_RPC_DateTime'] = 'dateTime.iso8601';
9452+
9453+/**
9454+ * Data types
9455+ * @global string $GLOBALS['XML_RPC_Base64']
9456+ */
9457+$GLOBALS['XML_RPC_Base64'] = 'base64';
9458+
9459+/**
9460+ * Data types
9461+ * @global string $GLOBALS['XML_RPC_Array']
9462+ */
9463+$GLOBALS['XML_RPC_Array'] = 'array';
9464+
9465+/**
9466+ * Data types
9467+ * @global string $GLOBALS['XML_RPC_Struct']
9468+ */
9469+$GLOBALS['XML_RPC_Struct'] = 'struct';
9470+
9471+
9472+/**
9473+ * Data type meta-types
9474+ * @global array $GLOBALS['XML_RPC_Types']
9475+ */
9476+$GLOBALS['XML_RPC_Types'] = array(
9477+ $GLOBALS['XML_RPC_I4'] => 1,
9478+ $GLOBALS['XML_RPC_Int'] => 1,
9479+ $GLOBALS['XML_RPC_Boolean'] => 1,
9480+ $GLOBALS['XML_RPC_String'] => 1,
9481+ $GLOBALS['XML_RPC_Double'] => 1,
9482+ $GLOBALS['XML_RPC_DateTime'] => 1,
9483+ $GLOBALS['XML_RPC_Base64'] => 1,
9484+ $GLOBALS['XML_RPC_Array'] => 2,
9485+ $GLOBALS['XML_RPC_Struct'] => 3,
9486+);
9487+
9488+
9489+/**
9490+ * Error message numbers
9491+ * @global array $GLOBALS['XML_RPC_err']
9492+ */
9493+$GLOBALS['XML_RPC_err'] = array(
9494+ 'unknown_method' => 1,
9495+ 'invalid_return' => 2,
9496+ 'incorrect_params' => 3,
9497+ 'introspect_unknown' => 4,
9498+ 'http_error' => 5,
9499+ 'not_response_object' => 6,
9500+ 'invalid_request' => 7,
9501+);
9502+
9503+/**
9504+ * Error message strings
9505+ * @global array $GLOBALS['XML_RPC_str']
9506+ */
9507+$GLOBALS['XML_RPC_str'] = array(
9508+ 'unknown_method' => 'Unknown method',
9509+ 'invalid_return' => 'Invalid return payload: enable debugging to examine incoming payload',
9510+ 'incorrect_params' => 'Incorrect parameters passed to method',
9511+ 'introspect_unknown' => 'Can\'t introspect: method unknown',
9512+ 'http_error' => 'Didn\'t receive 200 OK from remote server.',
9513+ 'not_response_object' => 'The requested method didn\'t return an XML_RPC_Response object.',
9514+ 'invalid_request' => 'Invalid request payload',
9515+);
9516+
9517+
9518+/**
9519+ * Default XML encoding (ISO-8859-1, UTF-8 or US-ASCII)
9520+ * @global string $GLOBALS['XML_RPC_defencoding']
9521+ */
9522+$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
9523+
9524+/**
9525+ * User error codes start at 800
9526+ * @global int $GLOBALS['XML_RPC_erruser']
9527+ */
9528+$GLOBALS['XML_RPC_erruser'] = 800;
9529+
9530+/**
9531+ * XML parse error codes start at 100
9532+ * @global int $GLOBALS['XML_RPC_errxml']
9533+ */
9534+$GLOBALS['XML_RPC_errxml'] = 100;
9535+
9536+
9537+/**
9538+ * Compose backslashes for escaping regexp
9539+ * @global string $GLOBALS['XML_RPC_backslash']
9540+ */
9541+$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
9542+
9543+
9544+/**
9545+ * Valid parents of XML elements
9546+ * @global array $GLOBALS['XML_RPC_valid_parents']
9547+ */
9548+$GLOBALS['XML_RPC_valid_parents'] = array(
9549+ 'BOOLEAN' => array('VALUE'),
9550+ 'I4' => array('VALUE'),
9551+ 'INT' => array('VALUE'),
9552+ 'STRING' => array('VALUE'),
9553+ 'DOUBLE' => array('VALUE'),
9554+ 'DATETIME.ISO8601' => array('VALUE'),
9555+ 'BASE64' => array('VALUE'),
9556+ 'ARRAY' => array('VALUE'),
9557+ 'STRUCT' => array('VALUE'),
9558+ 'PARAM' => array('PARAMS'),
9559+ 'METHODNAME' => array('METHODCALL'),
9560+ 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
9561+ 'MEMBER' => array('STRUCT'),
9562+ 'NAME' => array('MEMBER'),
9563+ 'DATA' => array('ARRAY'),
9564+ 'FAULT' => array('METHODRESPONSE'),
9565+ 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'),
9566+);
9567+
9568+
9569+/**
9570+ * Stores state during parsing
9571+ *
9572+ * quick explanation of components:
9573+ * + ac = accumulates values
9574+ * + qt = decides if quotes are needed for evaluation
9575+ * + cm = denotes struct or array (comma needed)
9576+ * + isf = indicates a fault
9577+ * + lv = indicates "looking for a value": implements the logic
9578+ * to allow values with no types to be strings
9579+ * + params = stores parameters in method calls
9580+ * + method = stores method name
9581+ *
9582+ * @global array $GLOBALS['XML_RPC_xh']
9583+ */
9584+$GLOBALS['XML_RPC_xh'] = array();
9585+
9586+
9587+/**
9588+ * Start element handler for the XML parser
9589+ *
9590+ * @return void
9591+ */
9592+function XML_RPC_se($parser_resource, $name, $attrs)
9593+{
9594+ global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String, $XML_RPC_valid_parents;
9595+ $parser = (int) $parser_resource;
9596+
9597+ // if invalid xmlrpc already detected, skip all processing
9598+ if ($XML_RPC_xh[$parser]['isf'] >= 2) {
9599+ return;
9600+ }
9601+
9602+ // check for correct element nesting
9603+ // top level element can only be of 2 types
9604+ if (count($XML_RPC_xh[$parser]['stack']) == 0) {
9605+ if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') {
9606+ $XML_RPC_xh[$parser]['isf'] = 2;
9607+ $XML_RPC_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element';
9608+ return;
9609+ }
9610+ } else {
9611+ // not top level element: see if parent is OK
9612+ if (!in_array($XML_RPC_xh[$parser]['stack'][0], $XML_RPC_valid_parents[$name])) {
9613+ $name = preg_replace('[^a-zA-Z0-9._-]', '', $name);
9614+ $XML_RPC_xh[$parser]['isf'] = 2;
9615+ $XML_RPC_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$XML_RPC_xh[$parser]['stack'][0]}";
9616+ return;
9617+ }
9618+ }
9619+
9620+ switch ($name) {
9621+ case 'STRUCT':
9622+ $XML_RPC_xh[$parser]['cm']++;
9623+
9624+ // turn quoting off
9625+ $XML_RPC_xh[$parser]['qt'] = 0;
9626+
9627+ $cur_val = array();
9628+ $cur_val['value'] = array();
9629+ $cur_val['members'] = 1;
9630+ array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val);
9631+ break;
9632+
9633+ case 'ARRAY':
9634+ $XML_RPC_xh[$parser]['cm']++;
9635+
9636+ // turn quoting off
9637+ $XML_RPC_xh[$parser]['qt'] = 0;
9638+
9639+ $cur_val = array();
9640+ $cur_val['value'] = array();
9641+ $cur_val['members'] = 0;
9642+ array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val);
9643+ break;
9644+
9645+ case 'NAME':
9646+ $XML_RPC_xh[$parser]['ac'] = '';
9647+ break;
9648+
9649+ case 'FAULT':
9650+ $XML_RPC_xh[$parser]['isf'] = 1;
9651+ break;
9652+
9653+ case 'PARAM':
9654+ $XML_RPC_xh[$parser]['valuestack'] = array();
9655+ break;
9656+
9657+ case 'VALUE':
9658+ $XML_RPC_xh[$parser]['lv'] = 1;
9659+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
9660+ $XML_RPC_xh[$parser]['ac'] = '';
9661+ $XML_RPC_xh[$parser]['qt'] = 0;
9662+ // look for a value: if this is still 1 by the
9663+ // time we reach the first data segment then the type is string
9664+ // by implication and we need to add in a quote
9665+ break;
9666+
9667+ case 'I4':
9668+ case 'INT':
9669+ case 'STRING':
9670+ case 'BOOLEAN':
9671+ case 'DOUBLE':
9672+ case 'DATETIME.ISO8601':
9673+ case 'BASE64':
9674+ $XML_RPC_xh[$parser]['ac'] = ''; // reset the accumulator
9675+
9676+ if ($name == 'DATETIME.ISO8601' || $name == 'STRING') {
9677+ $XML_RPC_xh[$parser]['qt'] = 1;
9678+
9679+ if ($name == 'DATETIME.ISO8601') {
9680+ $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
9681+ }
9682+
9683+ } elseif ($name == 'BASE64') {
9684+ $XML_RPC_xh[$parser]['qt'] = 2;
9685+ } else {
9686+ // No quoting is required here -- but
9687+ // at the end of the element we must check
9688+ // for data format errors.
9689+ $XML_RPC_xh[$parser]['qt'] = 0;
9690+ }
9691+ break;
9692+
9693+ case 'MEMBER':
9694+ $XML_RPC_xh[$parser]['ac'] = '';
9695+ break;
9696+
9697+ case 'DATA':
9698+ case 'METHODCALL':
9699+ case 'METHODNAME':
9700+ case 'METHODRESPONSE':
9701+ case 'PARAMS':
9702+ // valid elements that add little to processing
9703+ break;
9704+ }
9705+
9706+
9707+ // Save current element to stack
9708+ array_unshift($XML_RPC_xh[$parser]['stack'], $name);
9709+
9710+ if ($name != 'VALUE') {
9711+ $XML_RPC_xh[$parser]['lv'] = 0;
9712+ }
9713+}
9714+
9715+/**
9716+ * End element handler for the XML parser
9717+ *
9718+ * @return void
9719+ */
9720+function XML_RPC_ee($parser_resource, $name)
9721+{
9722+ global $XML_RPC_xh, $XML_RPC_Types, $XML_RPC_String;
9723+ $parser = (int) $parser_resource;
9724+
9725+ if ($XML_RPC_xh[$parser]['isf'] >= 2) {
9726+ return;
9727+ }
9728+
9729+ // push this element from stack
9730+ // NB: if XML validates, correct opening/closing is guaranteed and
9731+ // we do not have to check for $name == $curr_elem.
9732+ // we also checked for proper nesting at start of elements...
9733+ $curr_elem = array_shift($XML_RPC_xh[$parser]['stack']);
9734+
9735+ switch ($name) {
9736+ case 'STRUCT':
9737+ case 'ARRAY':
9738+ $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']);
9739+ $XML_RPC_xh[$parser]['value'] = $cur_val['value'];
9740+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
9741+ $XML_RPC_xh[$parser]['cm']--;
9742+ break;
9743+
9744+ case 'NAME':
9745+ $XML_RPC_xh[$parser]['valuestack'][0]['name'] = $XML_RPC_xh[$parser]['ac'];
9746+ break;
9747+
9748+ case 'BOOLEAN':
9749+ // special case here: we translate boolean 1 or 0 into PHP
9750+ // constants true or false
9751+ if ($XML_RPC_xh[$parser]['ac'] == '1') {
9752+ $XML_RPC_xh[$parser]['ac'] = 'true';
9753+ } else {
9754+ $XML_RPC_xh[$parser]['ac'] = 'false';
9755+ }
9756+
9757+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
9758+ // Drop through intentionally.
9759+
9760+ case 'I4':
9761+ case 'INT':
9762+ case 'STRING':
9763+ case 'DOUBLE':
9764+ case 'DATETIME.ISO8601':
9765+ case 'BASE64':
9766+ if ($XML_RPC_xh[$parser]['qt'] == 1) {
9767+ // we use double quotes rather than single so backslashification works OK
9768+ $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac'];
9769+ } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
9770+ $XML_RPC_xh[$parser]['value'] = base64_decode($XML_RPC_xh[$parser]['ac']);
9771+ } elseif ($name == 'BOOLEAN') {
9772+ $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac'];
9773+ } else {
9774+ // we have an I4, INT or a DOUBLE
9775+ // we must check that only 0123456789-.<space> are characters here
9776+ if (!ereg("^[+-]?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
9777+ XML_RPC_Base::raiseError('Non-numeric value received in INT or DOUBLE',
9778+ XML_RPC_ERROR_NON_NUMERIC_FOUND);
9779+ $XML_RPC_xh[$parser]['value'] = XML_RPC_ERROR_NON_NUMERIC_FOUND;
9780+ } else {
9781+ // it's ok, add it on
9782+ $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac'];
9783+ }
9784+ }
9785+
9786+ $XML_RPC_xh[$parser]['ac'] = '';
9787+ $XML_RPC_xh[$parser]['qt'] = 0;
9788+ $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
9789+ break;
9790+
9791+ case 'VALUE':
9792+ // deal with a string value
9793+ if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
9794+ $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
9795+ $XML_RPC_xh[$parser]['value'] = $XML_RPC_xh[$parser]['ac'];
9796+ }
9797+
9798+ $temp = new XML_RPC_Value($XML_RPC_xh[$parser]['value'], $XML_RPC_xh[$parser]['vt']);
9799+
9800+ $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']);
9801+ if (is_array($cur_val)) {
9802+ if ($cur_val['members']==0) {
9803+ $cur_val['value'][] = $temp;
9804+ } else {
9805+ $XML_RPC_xh[$parser]['value'] = $temp;
9806+ }
9807+ array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val);
9808+ } else {
9809+ $XML_RPC_xh[$parser]['value'] = $temp;
9810+ }
9811+ break;
9812+
9813+ case 'MEMBER':
9814+ $XML_RPC_xh[$parser]['ac'] = '';
9815+ $XML_RPC_xh[$parser]['qt'] = 0;
9816+
9817+ $cur_val = array_shift($XML_RPC_xh[$parser]['valuestack']);
9818+ if (is_array($cur_val)) {
9819+ if ($cur_val['members']==1) {
9820+ $cur_val['value'][$cur_val['name']] = $XML_RPC_xh[$parser]['value'];
9821+ }
9822+ array_unshift($XML_RPC_xh[$parser]['valuestack'], $cur_val);
9823+ }
9824+ break;
9825+
9826+ case 'DATA':
9827+ $XML_RPC_xh[$parser]['ac'] = '';
9828+ $XML_RPC_xh[$parser]['qt'] = 0;
9829+ break;
9830+
9831+ case 'PARAM':
9832+ $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['value'];
9833+ break;
9834+
9835+ case 'METHODNAME':
9836+ case 'RPCMETHODNAME':
9837+ $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", '',
9838+ $XML_RPC_xh[$parser]['ac']);
9839+ break;
9840+ }
9841+
9842+ // if it's a valid type name, set the type
9843+ if (isset($XML_RPC_Types[strtolower($name)])) {
9844+ $XML_RPC_xh[$parser]['vt'] = strtolower($name);
9845+ }
9846+}
9847+
9848+/**
9849+ * Character data handler for the XML parser
9850+ *
9851+ * @return void
9852+ */
9853+function XML_RPC_cd($parser_resource, $data)
9854+{
9855+ global $XML_RPC_xh, $XML_RPC_backslash;
9856+ $parser = (int) $parser_resource;
9857+
9858+ if ($XML_RPC_xh[$parser]['lv'] != 3) {
9859+ // "lookforvalue==3" means that we've found an entire value
9860+ // and should discard any further character data
9861+
9862+ if ($XML_RPC_xh[$parser]['lv'] == 1) {
9863+ // if we've found text and we're just in a <value> then
9864+ // turn quoting on, as this will be a string
9865+ $XML_RPC_xh[$parser]['qt'] = 1;
9866+ // and say we've found a value
9867+ $XML_RPC_xh[$parser]['lv'] = 2;
9868+ }
9869+
9870+ // replace characters that eval would
9871+ // do special things with
9872+ if (!isset($XML_RPC_xh[$parser]['ac'])) {
9873+ $XML_RPC_xh[$parser]['ac'] = '';
9874+ }
9875+ $XML_RPC_xh[$parser]['ac'] .= $data;
9876+ }
9877+}
9878+
9879+/**
9880+ * The common methods and properties for all of the XML_RPC classes
9881+ *
9882+ * @category Web Services
9883+ * @package XML_RPC
9884+ * @author Edd Dumbill <edd@usefulinc.com>
9885+ * @author Stig Bakken <stig@php.net>
9886+ * @author Martin Jansen <mj@php.net>
9887+ * @author Daniel Convissor <danielc@php.net>
9888+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9889+ * @version Release: 1.4.0
9890+ * @link http://pear.php.net/package/XML_RPC
9891+ */
9892+class XML_RPC_Base {
9893+
9894+ /**
9895+ * PEAR Error handling
9896+ *
9897+ * @return object PEAR_Error object
9898+ */
9899+ function raiseError($msg, $code)
9900+ {
9901+ include_once 'PEAR.php';
9902+ if (is_object(@$this)) {
9903+ return PEAR::raiseError(get_class($this) . ': ' . $msg, $code);
9904+ } else {
9905+ return PEAR::raiseError('XML_RPC: ' . $msg, $code);
9906+ }
9907+ }
9908+
9909+ /**
9910+ * Tell whether something is a PEAR_Error object
9911+ *
9912+ * @param mixed $value the item to check
9913+ *
9914+ * @return bool whether $value is a PEAR_Error object or not
9915+ *
9916+ * @access public
9917+ */
9918+ function isError($value)
9919+ {
9920+ return is_a($value, 'PEAR_Error');
9921+ }
9922+}
9923+
9924+/**
9925+ * The methods and properties for submitting XML RPC requests
9926+ *
9927+ * @category Web Services
9928+ * @package XML_RPC
9929+ * @author Edd Dumbill <edd@usefulinc.com>
9930+ * @author Stig Bakken <stig@php.net>
9931+ * @author Martin Jansen <mj@php.net>
9932+ * @author Daniel Convissor <danielc@php.net>
9933+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
9934+ * @version Release: 1.4.0
9935+ * @link http://pear.php.net/package/XML_RPC
9936+ */
9937+class XML_RPC_Client extends XML_RPC_Base {
9938+
9939+ /**
9940+ * The path and name of the RPC server script you want the request to go to
9941+ * @var string
9942+ */
9943+ var $path = '';
9944+
9945+ /**
9946+ * The name of the remote server to connect to
9947+ * @var string
9948+ */
9949+ var $server = '';
9950+
9951+ /**
9952+ * The protocol to use in contacting the remote server
9953+ * @var string
9954+ */
9955+ var $protocol = 'http://';
9956+
9957+ /**
9958+ * The port for connecting to the remote server
9959+ *
9960+ * The default is 80 for http:// connections
9961+ * and 443 for https:// and ssl:// connections.
9962+ *
9963+ * @var integer
9964+ */
9965+ var $port = 80;
9966+
9967+ /**
9968+ * A user name for accessing the RPC server
9969+ * @var string
9970+ * @see XML_RPC_Client::setCredentials()
9971+ */
9972+ var $username = '';
9973+
9974+ /**
9975+ * A password for accessing the RPC server
9976+ * @var string
9977+ * @see XML_RPC_Client::setCredentials()
9978+ */
9979+ var $password = '';
9980+
9981+ /**
9982+ * The name of the proxy server to use, if any
9983+ * @var string
9984+ */
9985+ var $proxy = '';
9986+
9987+ /**
9988+ * The protocol to use in contacting the proxy server, if any
9989+ * @var string
9990+ */
9991+ var $proxy_protocol = 'http://';
9992+
9993+ /**
9994+ * The port for connecting to the proxy server
9995+ *
9996+ * The default is 8080 for http:// connections
9997+ * and 443 for https:// and ssl:// connections.
9998+ *
9999+ * @var integer
10000+ */
10001+ var $proxy_port = 8080;
10002+
10003+ /**
10004+ * A user name for accessing the proxy server
10005+ * @var string
10006+ */
10007+ var $proxy_user = '';
10008+
10009+ /**
10010+ * A password for accessing the proxy server
10011+ * @var string
10012+ */
10013+ var $proxy_pass = '';
10014+
10015+ /**
10016+ * The error number, if any
10017+ * @var integer
10018+ */
10019+ var $errno = 0;
10020+
10021+ /**
10022+ * The error message, if any
10023+ * @var string
10024+ */
10025+ var $errstr = '';
10026+
10027+ /**
10028+ * The current debug mode (1 = on, 0 = off)
10029+ * @var integer
10030+ */
10031+ var $debug = 0;
10032+
10033+ /**
10034+ * The HTTP headers for the current request.
10035+ * @var string
10036+ */
10037+ var $headers = '';
10038+
10039+
10040+ /**
10041+ * Sets the object's properties
10042+ *
10043+ * @param string $path the path and name of the RPC server script
10044+ * you want the request to go to
10045+ * @param string $server the URL of the remote server to connect to.
10046+ * If this parameter doesn't specify a
10047+ * protocol and $port is 443, ssl:// is
10048+ * assumed.
10049+ * @param integer $port a port for connecting to the remote server.
10050+ * Defaults to 80 for http:// connections and
10051+ * 443 for https:// and ssl:// connections.
10052+ * @param string $proxy the URL of the proxy server to use, if any.
10053+ * If this parameter doesn't specify a
10054+ * protocol and $port is 443, ssl:// is
10055+ * assumed.
10056+ * @param integer $proxy_port a port for connecting to the remote server.
10057+ * Defaults to 8080 for http:// connections and
10058+ * 443 for https:// and ssl:// connections.
10059+ * @param string $proxy_user a user name for accessing the proxy server
10060+ * @param string $proxy_pass a password for accessing the proxy server
10061+ *
10062+ * @return void
10063+ */
10064+ function XML_RPC_Client($path, $server, $port = 0,
10065+ $proxy = '', $proxy_port = 0,
10066+ $proxy_user = '', $proxy_pass = '')
10067+ {
10068+ $this->path = $path;
10069+ $this->proxy_user = $proxy_user;
10070+ $this->proxy_pass = $proxy_pass;
10071+
10072+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $server, $match);
10073+ if ($match[1] == '') {
10074+ if ($port == 443) {
10075+ $this->server = $match[2];
10076+ $this->protocol = 'ssl://';
10077+ $this->port = 443;
10078+ } else {
10079+ $this->server = $match[2];
10080+ if ($port) {
10081+ $this->port = $port;
10082+ }
10083+ }
10084+ } elseif ($match[1] == 'http://') {
10085+ $this->server = $match[2];
10086+ if ($port) {
10087+ $this->port = $port;
10088+ }
10089+ } else {
10090+ $this->server = $match[2];
10091+ $this->protocol = 'ssl://';
10092+ if ($port) {
10093+ $this->port = $port;
10094+ } else {
10095+ $this->port = 443;
10096+ }
10097+ }
10098+
10099+ if ($proxy) {
10100+ preg_match('@^(http://|https://|ssl://)?(.*)$@', $proxy, $match);
10101+ if ($match[1] == '') {
10102+ if ($proxy_port == 443) {
10103+ $this->proxy = $match[2];
10104+ $this->proxy_protocol = 'ssl://';
10105+ $this->proxy_port = 443;
10106+ } else {
10107+ $this->proxy = $match[2];
10108+ if ($proxy_port) {
10109+ $this->proxy_port = $proxy_port;
10110+ }
10111+ }
10112+ } elseif ($match[1] == 'http://') {
10113+ $this->proxy = $match[2];
10114+ if ($proxy_port) {
10115+ $this->proxy_port = $proxy_port;
10116+ }
10117+ } else {
10118+ $this->proxy = $match[2];
10119+ $this->proxy_protocol = 'ssl://';
10120+ if ($proxy_port) {
10121+ $this->proxy_port = $proxy_port;
10122+ } else {
10123+ $this->proxy_port = 443;
10124+ }
10125+ }
10126+ }
10127+ }
10128+
10129+ /**
10130+ * Change the current debug mode
10131+ *
10132+ * @param int $in where 1 = on, 0 = off
10133+ *
10134+ * @return void
10135+ */
10136+ function setDebug($in)
10137+ {
10138+ if ($in) {
10139+ $this->debug = 1;
10140+ } else {
10141+ $this->debug = 0;
10142+ }
10143+ }
10144+
10145+ /**
10146+ * Set username and password properties for connecting to the RPC server
10147+ *
10148+ * @param string $u the user name
10149+ * @param string $p the password
10150+ *
10151+ * @return void
10152+ *
10153+ * @see XML_RPC_Client::$username, XML_RPC_Client::$password
10154+ */
10155+ function setCredentials($u, $p)
10156+ {
10157+ $this->username = $u;
10158+ $this->password = $p;
10159+ }
10160+
10161+ /**
10162+ * Transmit the RPC request via HTTP 1.0 protocol
10163+ *
10164+ * @param object $msg the XML_RPC_Message object
10165+ * @param int $timeout how many seconds to wait for the request
10166+ *
10167+ * @return object an XML_RPC_Response object. 0 is returned if any
10168+ * problems happen.
10169+ *
10170+ * @see XML_RPC_Message, XML_RPC_Client::XML_RPC_Client(),
10171+ * XML_RPC_Client::setCredentials()
10172+ */
10173+ function send($msg, $timeout = 0)
10174+ {
10175+ if (strtolower(get_class($msg)) != 'xml_rpc_message') {
10176+ $this->errstr = 'send()\'s $msg parameter must be an'
10177+ . ' XML_RPC_Message object.';
10178+ $this->raiseError($this->errstr, XML_RPC_ERROR_PROGRAMMING);
10179+ return 0;
10180+ }
10181+ $msg->debug = $this->debug;
10182+ return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
10183+ $timeout, $this->username,
10184+ $this->password);
10185+ }
10186+
10187+ /**
10188+ * Transmit the RPC request via HTTP 1.0 protocol
10189+ *
10190+ * Requests should be sent using XML_RPC_Client send() rather than
10191+ * calling this method directly.
10192+ *
10193+ * @param object $msg the XML_RPC_Message object
10194+ * @param string $server the server to send the request to
10195+ * @param int $port the server port send the request to
10196+ * @param int $timeout how many seconds to wait for the request
10197+ * before giving up
10198+ * @param string $username a user name for accessing the RPC server
10199+ * @param string $password a password for accessing the RPC server
10200+ *
10201+ * @return object an XML_RPC_Response object. 0 is returned if any
10202+ * problems happen.
10203+ *
10204+ * @access protected
10205+ * @see XML_RPC_Client::send()
10206+ */
10207+ function sendPayloadHTTP10($msg, $server, $port, $timeout = 0,
10208+ $username = '', $password = '')
10209+ {
10210+ /*
10211+ * If we're using a proxy open a socket to the proxy server
10212+ * instead to the xml-rpc server
10213+ */
10214+ if ($this->proxy) {
10215+ if ($this->proxy_protocol == 'http://') {
10216+ $protocol = '';
10217+ } else {
10218+ $protocol = $this->proxy_protocol;
10219+ }
10220+ if ($timeout > 0) {
10221+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
10222+ $this->errno, $this->errstr, $timeout);
10223+ } else {
10224+ $fp = @fsockopen($protocol . $this->proxy, $this->proxy_port,
10225+ $this->errno, $this->errstr);
10226+ }
10227+ } else {
10228+ if ($this->protocol == 'http://') {
10229+ $protocol = '';
10230+ } else {
10231+ $protocol = $this->protocol;
10232+ }
10233+ if ($timeout > 0) {
10234+ $fp = @fsockopen($protocol . $server, $port,
10235+ $this->errno, $this->errstr, $timeout);
10236+ } else {
10237+ $fp = @fsockopen($protocol . $server, $port,
10238+ $this->errno, $this->errstr);
10239+ }
10240+ }
10241+
10242+ /*
10243+ * Just raising the error without returning it is strange,
10244+ * but keep it here for backwards compatibility.
10245+ */
10246+ if (!$fp && $this->proxy) {
10247+ $this->raiseError('Connection to proxy server '
10248+ . $this->proxy . ':' . $this->proxy_port
10249+ . ' failed. ' . $this->errstr,
10250+ XML_RPC_ERROR_CONNECTION_FAILED);
10251+ return 0;
10252+ } elseif (!$fp) {
10253+ $this->raiseError('Connection to RPC server '
10254+ . $server . ':' . $port
10255+ . ' failed. ' . $this->errstr,
10256+ XML_RPC_ERROR_CONNECTION_FAILED);
10257+ return 0;
10258+ }
10259+
10260+ if ($timeout) {
10261+ /*
10262+ * Using socket_set_timeout() because stream_set_timeout()
10263+ * was introduced in 4.3.0, but we need to support 4.2.0.
10264+ */
10265+ socket_set_timeout($fp, $timeout);
10266+ }
10267+
10268+ // Pre-emptive BC hacks for fools calling sendPayloadHTTP10() directly
10269+ if ($username != $this->username) {
10270+ $this->setCredentials($username, $password);
10271+ }
10272+
10273+ // Only create the payload if it was not created previously
10274+ if (empty($msg->payload)) {
10275+ $msg->createPayload();
10276+ }
10277+ $this->createHeaders($msg);
10278+
10279+ $op = $this->headers . "\r\n\r\n";
10280+ $op .= $msg->payload;
10281+
10282+ if (!fputs($fp, $op, strlen($op))) {
10283+ $this->errstr = 'Write error';
10284+ return 0;
10285+ }
10286+ $resp = $msg->parseResponseFile($fp);
10287+
10288+ $meta = socket_get_status($fp);
10289+ if ($meta['timed_out']) {
10290+ fclose($fp);
10291+ $this->errstr = 'RPC server did not send response before timeout.';
10292+ $this->raiseError($this->errstr, XML_RPC_ERROR_CONNECTION_FAILED);
10293+ return 0;
10294+ }
10295+
10296+ fclose($fp);
10297+ return $resp;
10298+ }
10299+
10300+ /**
10301+ * Determines the HTTP headers and puts it in the $headers property
10302+ *
10303+ * @param object $msg the XML_RPC_Message object
10304+ *
10305+ * @return boolean TRUE if okay, FALSE if the message payload isn't set.
10306+ *
10307+ * @access protected
10308+ */
10309+ function createHeaders($msg)
10310+ {
10311+ if (empty($msg->payload)) {
10312+ return false;
10313+ }
10314+ if ($this->proxy) {
10315+ $this->headers = 'POST ' . $this->protocol . $this->server;
10316+ if ($this->proxy_port) {
10317+ $this->headers .= ':' . $this->port;
10318+ }
10319+ } else {
10320+ $this->headers = 'POST ';
10321+ }
10322+ $this->headers .= $this->path. " HTTP/1.0\r\n";
10323+
10324+ $this->headers .= "User-Agent: PEAR XML_RPC\r\n";
10325+ $this->headers .= 'Host: ' . $this->server . "\r\n";
10326+
10327+ if ($this->proxy && $this->proxy_user) {
10328+ $this->headers .= 'Proxy-Authorization: Basic '
10329+ . base64_encode("$this->proxy_user:$this->proxy_pass")
10330+ . "\r\n";
10331+ }
10332+
10333+ // thanks to Grant Rauscher <grant7@firstworld.net> for this
10334+ if ($this->username) {
10335+ $this->headers .= 'Authorization: Basic '
10336+ . base64_encode("$this->username:$this->password")
10337+ . "\r\n";
10338+ }
10339+
10340+ $this->headers .= "Content-Type: text/xml\r\n";
10341+ $this->headers .= 'Content-Length: ' . strlen($msg->payload);
10342+ return true;
10343+ }
10344+}
10345+
10346+/**
10347+ * The methods and properties for interpreting responses to XML RPC requests
10348+ *
10349+ * @category Web Services
10350+ * @package XML_RPC
10351+ * @author Edd Dumbill <edd@usefulinc.com>
10352+ * @author Stig Bakken <stig@php.net>
10353+ * @author Martin Jansen <mj@php.net>
10354+ * @author Daniel Convissor <danielc@php.net>
10355+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
10356+ * @version Release: 1.4.0
10357+ * @link http://pear.php.net/package/XML_RPC
10358+ */
10359+class XML_RPC_Response extends XML_RPC_Base
10360+{
10361+ var $xv;
10362+ var $fn;
10363+ var $fs;
10364+ var $hdrs;
10365+
10366+ /**
10367+ * @return void
10368+ */
10369+ function XML_RPC_Response($val, $fcode = 0, $fstr = '')
10370+ {
10371+ if ($fcode != 0) {
10372+ $this->fn = $fcode;
10373+ $this->fs = htmlspecialchars($fstr);
10374+ } else {
10375+ $this->xv = $val;
10376+ }
10377+ }
10378+
10379+ /**
10380+ * @return int the error code
10381+ */
10382+ function faultCode()
10383+ {
10384+ if (isset($this->fn)) {
10385+ return $this->fn;
10386+ } else {
10387+ return 0;
10388+ }
10389+ }
10390+
10391+ /**
10392+ * @return string the error string
10393+ */
10394+ function faultString()
10395+ {
10396+ return $this->fs;
10397+ }
10398+
10399+ /**
10400+ * @return mixed the value
10401+ */
10402+ function value()
10403+ {
10404+ return $this->xv;
10405+ }
10406+
10407+ /**
10408+ * @return string the error message in XML format
10409+ */
10410+ function serialize()
10411+ {
10412+ $rs = "<methodResponse>\n";
10413+ if ($this->fn) {
10414+ $rs .= "<fault>
10415+ <value>
10416+ <struct>
10417+ <member>
10418+ <name>faultCode</name>
10419+ <value><int>" . $this->fn . "</int></value>
10420+ </member>
10421+ <member>
10422+ <name>faultString</name>
10423+ <value><string>" . $this->fs . "</string></value>
10424+ </member>
10425+ </struct>
10426+ </value>
10427+</fault>";
10428+ } else {
10429+ $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
10430+ "</param>\n</params>";
10431+ }
10432+ $rs .= "\n</methodResponse>";
10433+ return $rs;
10434+ }
10435+}
10436+
10437+/**
10438+ * The methods and properties for composing XML RPC messages
10439+ *
10440+ * @category Web Services
10441+ * @package XML_RPC
10442+ * @author Edd Dumbill <edd@usefulinc.com>
10443+ * @author Stig Bakken <stig@php.net>
10444+ * @author Martin Jansen <mj@php.net>
10445+ * @author Daniel Convissor <danielc@php.net>
10446+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
10447+ * @version Release: 1.4.0
10448+ * @link http://pear.php.net/package/XML_RPC
10449+ */
10450+class XML_RPC_Message extends XML_RPC_Base
10451+{
10452+ /**
10453+ * The current debug mode (1 = on, 0 = off)
10454+ * @var integer
10455+ */
10456+ var $debug = 0;
10457+
10458+ /**
10459+ * The encoding to be used for outgoing messages
10460+ *
10461+ * Defaults to the value of <var>$GLOBALS['XML_RPC_defencoding']</var>
10462+ *
10463+ * @var string
10464+ * @see XML_RPC_Message::setSendEncoding(),
10465+ * $GLOBALS['XML_RPC_defencoding'], XML_RPC_Message::xml_header()
10466+ */
10467+ var $send_encoding = '';
10468+
10469+ /**
10470+ * The method presently being evaluated
10471+ * @var string
10472+ */
10473+ var $methodname = '';
10474+
10475+ /**
10476+ * @var array
10477+ */
10478+ var $params = array();
10479+
10480+ /**
10481+ * The XML message being generated
10482+ * @var string
10483+ */
10484+ var $payload = '';
10485+
10486+ /**
10487+ * @return void
10488+ */
10489+ function XML_RPC_Message($meth, $pars = 0)
10490+ {
10491+ $this->methodname = $meth;
10492+ if (is_array($pars) && sizeof($pars) > 0) {
10493+ for ($i = 0; $i < sizeof($pars); $i++) {
10494+ $this->addParam($pars[$i]);
10495+ }
10496+ }
10497+ }
10498+
10499+ /**
10500+ * Produces the XML declaration including the encoding attribute
10501+ *
10502+ * The encoding is determined by this class' <var>$send_encoding</var>
10503+ * property. If the <var>$send_encoding</var> property is not set, use
10504+ * <var>$GLOBALS['XML_RPC_defencoding']</var>.
10505+ *
10506+ * @return string the XML declaration and <methodCall> element
10507+ *
10508+ * @see XML_RPC_Message::setSendEncoding(),
10509+ * XML_RPC_Message::$send_encoding, $GLOBALS['XML_RPC_defencoding']
10510+ */
10511+ function xml_header()
10512+ {
10513+ global $XML_RPC_defencoding;
10514+ if (!$this->send_encoding) {
10515+ $this->send_encoding = $XML_RPC_defencoding;
10516+ }
10517+ return '<?xml version="1.0" encoding="' . $this->send_encoding . '"?>'
10518+ . "\n<methodCall>\n";
10519+ }
10520+
10521+ /**
10522+ * @return string the closing </methodCall> tag
10523+ */
10524+ function xml_footer()
10525+ {
10526+ return "</methodCall>\n";
10527+ }
10528+
10529+ /**
10530+ * @return void
10531+ *
10532+ * @uses XML_RPC_Message::xml_header(), XML_RPC_Message::xml_footer()
10533+ */
10534+ function createPayload()
10535+ {
10536+ $this->payload = $this->xml_header();
10537+ $this->payload .= '<methodName>' . $this->methodname . "</methodName>\n";
10538+ $this->payload .= "<params>\n";
10539+ for ($i = 0; $i < sizeof($this->params); $i++) {
10540+ $p = $this->params[$i];
10541+ $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
10542+ }
10543+ $this->payload .= "</params>\n";
10544+ $this->payload .= $this->xml_footer();
10545+ $this->payload = ereg_replace("[\r\n]+", "\r\n", $this->payload);
10546+ }
10547+
10548+ /**
10549+ * @return string the name of the method
10550+ */
10551+ function method($meth = '')
10552+ {
10553+ if ($meth != '') {
10554+ $this->methodname = $meth;
10555+ }
10556+ return $this->methodname;
10557+ }
10558+
10559+ /**
10560+ * @return string the payload
10561+ */
10562+ function serialize()
10563+ {
10564+ $this->createPayload();
10565+ return $this->payload;
10566+ }
10567+
10568+ /**
10569+ * @return void
10570+ */
10571+ function addParam($par)
10572+ {
10573+ $this->params[] = $par;
10574+ }
10575+
10576+ /**
10577+ * Obtains an XML_RPC_Value object for the given parameter
10578+ *
10579+ * @param int $i the index number of the parameter to obtain
10580+ *
10581+ * @return object the XML_RPC_Value object.
10582+ * If the parameter doesn't exist, an XML_RPC_Response object.
10583+ *
10584+ * @since Returns XML_RPC_Response object on error since Release 1.3.0
10585+ */
10586+ function getParam($i)
10587+ {
10588+ global $XML_RPC_err, $XML_RPC_str;
10589+
10590+ if (isset($this->params[$i])) {
10591+ return $this->params[$i];
10592+ } else {
10593+ $this->raiseError('The submitted request did not contain this parameter',
10594+ XML_RPC_ERROR_INCORRECT_PARAMS);
10595+ return new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
10596+ $XML_RPC_str['incorrect_params']);
10597+ }
10598+ }
10599+
10600+ /**
10601+ * @return int the number of parameters
10602+ */
10603+ function getNumParams()
10604+ {
10605+ return sizeof($this->params);
10606+ }
10607+
10608+ /**
10609+ * Sets the XML declaration's encoding attribute
10610+ *
10611+ * @param string $type the encoding type (ISO-8859-1, UTF-8 or US-ASCII)
10612+ *
10613+ * @return void
10614+ *
10615+ * @see XML_RPC_Message::$send_encoding, XML_RPC_Message::xml_header()
10616+ * @since Method available since Release 1.2.0
10617+ */
10618+ function setSendEncoding($type)
10619+ {
10620+ $this->send_encoding = $type;
10621+ }
10622+
10623+ /**
10624+ * Determine the XML's encoding via the encoding attribute
10625+ * in the XML declaration
10626+ *
10627+ * If the encoding parameter is not set or is not ISO-8859-1, UTF-8
10628+ * or US-ASCII, $XML_RPC_defencoding will be returned.
10629+ *
10630+ * @param string $data the XML that will be parsed
10631+ *
10632+ * @return string the encoding to be used
10633+ *
10634+ * @link http://php.net/xml_parser_create
10635+ * @since Method available since Release 1.2.0
10636+ */
10637+ function getEncoding($data)
10638+ {
10639+ global $XML_RPC_defencoding;
10640+
10641+ if (preg_match('/<\?xml[^>]*\s*encoding\s*=\s*[\'"]([^"\']*)[\'"]/i',
10642+ $data, $match))
10643+ {
10644+ $match[1] = trim(strtoupper($match[1]));
10645+ switch ($match[1]) {
10646+ case 'ISO-8859-1':
10647+ case 'UTF-8':
10648+ case 'US-ASCII':
10649+ return $match[1];
10650+ break;
10651+
10652+ default:
10653+ return $XML_RPC_defencoding;
10654+ }
10655+ } else {
10656+ return $XML_RPC_defencoding;
10657+ }
10658+ }
10659+
10660+ /**
10661+ * @return object a new XML_RPC_Response object
10662+ */
10663+ function parseResponseFile($fp)
10664+ {
10665+ $ipd = '';
10666+ while ($data = @fread($fp, 8192)) {
10667+ $ipd .= $data;
10668+ }
10669+ return $this->parseResponse($ipd);
10670+ }
10671+
10672+ /**
10673+ * @return object a new XML_RPC_Response object
10674+ */
10675+ function parseResponse($data = '')
10676+ {
10677+ global $XML_RPC_xh, $XML_RPC_err, $XML_RPC_str, $XML_RPC_defencoding;
10678+
10679+ $encoding = $this->getEncoding($data);
10680+ $parser_resource = xml_parser_create($encoding);
10681+ $parser = (int) $parser_resource;
10682+
10683+ $XML_RPC_xh = array();
10684+ $XML_RPC_xh[$parser] = array();
10685+
10686+ $XML_RPC_xh[$parser]['cm'] = 0;
10687+ $XML_RPC_xh[$parser]['isf'] = 0;
10688+ $XML_RPC_xh[$parser]['ac'] = '';
10689+ $XML_RPC_xh[$parser]['qt'] = '';
10690+ $XML_RPC_xh[$parser]['stack'] = array();
10691+ $XML_RPC_xh[$parser]['valuestack'] = array();
10692+
10693+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
10694+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
10695+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
10696+
10697+ $hdrfnd = 0;
10698+ if ($this->debug) {
10699+ print "\n<pre>---GOT---\n";
10700+ print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
10701+ print "\n---END---</pre>\n";
10702+ }
10703+
10704+ // See if response is a 200 or a 100 then a 200, else raise error.
10705+ // But only do this if we're using the HTTP protocol.
10706+ if (ereg('^HTTP', $data) &&
10707+ !ereg('^HTTP/[0-9\.]+ 200 ', $data) &&
10708+ !preg_match('@^HTTP/[0-9\.]+ 10[0-9]([A-Za-z ]+)?[\r\n]+HTTP/[0-9\.]+ 200@', $data))
10709+ {
10710+ $errstr = substr($data, 0, strpos($data, "\n") - 1);
10711+ error_log('HTTP error, got response: ' . $errstr);
10712+ $r = new XML_RPC_Response(0, $XML_RPC_err['http_error'],
10713+ $XML_RPC_str['http_error'] . ' (' .
10714+ $errstr . ')');
10715+ xml_parser_free($parser_resource);
10716+ return $r;
10717+ }
10718+
10719+ // gotta get rid of headers here
10720+ if (!$hdrfnd && ($brpos = strpos($data,"\r\n\r\n"))) {
10721+ $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
10722+ $data = substr($data, $brpos + 4);
10723+ $hdrfnd = 1;
10724+ }
10725+
10726+ /*
10727+ * be tolerant of junk after methodResponse
10728+ * (e.g. javascript automatically inserted by free hosts)
10729+ * thanks to Luca Mariano <luca.mariano@email.it>
10730+ */
10731+ $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
10732+
10733+ if (!xml_parse($parser_resource, $data, sizeof($data))) {
10734+ // thanks to Peter Kocks <peter.kocks@baygate.com>
10735+ if (xml_get_current_line_number($parser_resource) == 1) {
10736+ $errstr = 'XML error at line 1, check URL';
10737+ } else {
10738+ $errstr = sprintf('XML error: %s at line %d',
10739+ xml_error_string(xml_get_error_code($parser_resource)),
10740+ xml_get_current_line_number($parser_resource));
10741+ }
10742+ error_log($errstr);
10743+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
10744+ $XML_RPC_str['invalid_return']);
10745+ xml_parser_free($parser_resource);
10746+ return $r;
10747+ }
10748+
10749+ xml_parser_free($parser_resource);
10750+
10751+ if ($this->debug) {
10752+ print "\n<pre>---PARSED---\n";
10753+ var_dump($XML_RPC_xh[$parser]['value']);
10754+ print "---END---</pre>\n";
10755+ }
10756+
10757+ if ($XML_RPC_xh[$parser]['isf'] > 1) {
10758+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
10759+ $XML_RPC_str['invalid_return'].' '.$XML_RPC_xh[$parser]['isf_reason']);
10760+ } elseif (!is_object($XML_RPC_xh[$parser]['value'])) {
10761+ // then something odd has happened
10762+ // and it's time to generate a client side error
10763+ // indicating something odd went on
10764+ $r = new XML_RPC_Response(0, $XML_RPC_err['invalid_return'],
10765+ $XML_RPC_str['invalid_return']);
10766+ } else {
10767+ $v = $XML_RPC_xh[$parser]['value'];
10768+ $allOK=1;
10769+ if ($XML_RPC_xh[$parser]['isf']) {
10770+ $f = $v->structmem('faultCode');
10771+ $fs = $v->structmem('faultString');
10772+ $r = new XML_RPC_Response($v, $f->scalarval(),
10773+ $fs->scalarval());
10774+ } else {
10775+ $r = new XML_RPC_Response($v);
10776+ }
10777+ }
10778+ $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
10779+ return $r;
10780+ }
10781+}
10782+
10783+/**
10784+ * The methods and properties that represent data in XML RPC format
10785+ *
10786+ * @category Web Services
10787+ * @package XML_RPC
10788+ * @author Edd Dumbill <edd@usefulinc.com>
10789+ * @author Stig Bakken <stig@php.net>
10790+ * @author Martin Jansen <mj@php.net>
10791+ * @author Daniel Convissor <danielc@php.net>
10792+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
10793+ * @version Release: 1.4.0
10794+ * @link http://pear.php.net/package/XML_RPC
10795+ */
10796+class XML_RPC_Value extends XML_RPC_Base
10797+{
10798+ var $me = array();
10799+ var $mytype = 0;
10800+
10801+ /**
10802+ * @return void
10803+ */
10804+ function XML_RPC_Value($val = -1, $type = '')
10805+ {
10806+ global $XML_RPC_Types;
10807+ $this->me = array();
10808+ $this->mytype = 0;
10809+ if ($val != -1 || $type != '') {
10810+ if ($type == '') {
10811+ $type = 'string';
10812+ }
10813+ if (!array_key_exists($type, $XML_RPC_Types)) {
10814+ // XXX
10815+ // need some way to report this error
10816+ } elseif ($XML_RPC_Types[$type] == 1) {
10817+ $this->addScalar($val, $type);
10818+ } elseif ($XML_RPC_Types[$type] == 2) {
10819+ $this->addArray($val);
10820+ } elseif ($XML_RPC_Types[$type] == 3) {
10821+ $this->addStruct($val);
10822+ }
10823+ }
10824+ }
10825+
10826+ /**
10827+ * @return int returns 1 if successful or 0 if there are problems
10828+ */
10829+ function addScalar($val, $type = 'string')
10830+ {
10831+ global $XML_RPC_Types, $XML_RPC_Boolean;
10832+
10833+ if ($this->mytype == 1) {
10834+ $this->raiseError('Scalar can have only one value',
10835+ XML_RPC_ERROR_INVALID_TYPE);
10836+ return 0;
10837+ }
10838+ $typeof = $XML_RPC_Types[$type];
10839+ if ($typeof != 1) {
10840+ $this->raiseError("Not a scalar type (${typeof})",
10841+ XML_RPC_ERROR_INVALID_TYPE);
10842+ return 0;
10843+ }
10844+
10845+ if ($type == $XML_RPC_Boolean) {
10846+ if (strcasecmp($val, 'true') == 0
10847+ || $val == 1
10848+ || ($val == true && strcasecmp($val, 'false')))
10849+ {
10850+ $val = 1;
10851+ } else {
10852+ $val = 0;
10853+ }
10854+ }
10855+
10856+ if ($this->mytype == 2) {
10857+ // we're adding to an array here
10858+ $ar = $this->me['array'];
10859+ $ar[] = new XML_RPC_Value($val, $type);
10860+ $this->me['array'] = $ar;
10861+ } else {
10862+ // a scalar, so set the value and remember we're scalar
10863+ $this->me[$type] = $val;
10864+ $this->mytype = $typeof;
10865+ }
10866+ return 1;
10867+ }
10868+
10869+ /**
10870+ * @return int returns 1 if successful or 0 if there are problems
10871+ */
10872+ function addArray($vals)
10873+ {
10874+ global $XML_RPC_Types;
10875+ if ($this->mytype != 0) {
10876+ $this->raiseError(
10877+ 'Already initialized as a [' . $this->kindOf() . ']',
10878+ XML_RPC_ERROR_ALREADY_INITIALIZED);
10879+ return 0;
10880+ }
10881+ $this->mytype = $XML_RPC_Types['array'];
10882+ $this->me['array'] = $vals;
10883+ return 1;
10884+ }
10885+
10886+ /**
10887+ * @return int returns 1 if successful or 0 if there are problems
10888+ */
10889+ function addStruct($vals)
10890+ {
10891+ global $XML_RPC_Types;
10892+ if ($this->mytype != 0) {
10893+ $this->raiseError(
10894+ 'Already initialized as a [' . $this->kindOf() . ']',
10895+ XML_RPC_ERROR_ALREADY_INITIALIZED);
10896+ return 0;
10897+ }
10898+ $this->mytype = $XML_RPC_Types['struct'];
10899+ $this->me['struct'] = $vals;
10900+ return 1;
10901+ }
10902+
10903+ /**
10904+ * @return void
10905+ */
10906+ function dump($ar)
10907+ {
10908+ reset($ar);
10909+ foreach ($ar as $key => $val) {
10910+ echo "$key => $val<br />";
10911+ if ($key == 'array') {
10912+ foreach ($val as $key2 => $val2) {
10913+ echo "-- $key2 => $val2<br />";
10914+ }
10915+ }
10916+ }
10917+ }
10918+
10919+ /**
10920+ * @return string the data type of the current value
10921+ */
10922+ function kindOf()
10923+ {
10924+ switch ($this->mytype) {
10925+ case 3:
10926+ return 'struct';
10927+
10928+ case 2:
10929+ return 'array';
10930+
10931+ case 1:
10932+ return 'scalar';
10933+
10934+ default:
10935+ return 'undef';
10936+ }
10937+ }
10938+
10939+ /**
10940+ * @return string the data in XML format
10941+ */
10942+ function serializedata($typ, $val)
10943+ {
10944+ $rs = '';
10945+ global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
10946+ if (!array_key_exists($typ, $XML_RPC_Types)) {
10947+ // XXX
10948+ // need some way to report this error
10949+ return;
10950+ }
10951+ switch ($XML_RPC_Types[$typ]) {
10952+ case 3:
10953+ // struct
10954+ $rs .= "<struct>\n";
10955+ reset($val);
10956+ foreach ($val as $key2 => $val2) {
10957+ $rs .= "<member><name>${key2}</name>\n";
10958+ $rs .= $this->serializeval($val2);
10959+ $rs .= "</member>\n";
10960+ }
10961+ $rs .= '</struct>';
10962+ break;
10963+
10964+ case 2:
10965+ // array
10966+ $rs .= "<array>\n<data>\n";
10967+ for ($i = 0; $i < sizeof($val); $i++) {
10968+ $rs .= $this->serializeval($val[$i]);
10969+ }
10970+ $rs .= "</data>\n</array>";
10971+ break;
10972+
10973+ case 1:
10974+ switch ($typ) {
10975+ case $XML_RPC_Base64:
10976+ $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
10977+ break;
10978+ case $XML_RPC_Boolean:
10979+ $rs .= "<${typ}>" . ($val ? '1' : '0') . "</${typ}>";
10980+ break;
10981+ case $XML_RPC_String:
10982+ $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
10983+ break;
10984+ default:
10985+ $rs .= "<${typ}>${val}</${typ}>";
10986+ }
10987+ }
10988+ return $rs;
10989+ }
10990+
10991+ /**
10992+ * @return string the data in XML format
10993+ */
10994+ function serialize()
10995+ {
10996+ return $this->serializeval($this);
10997+ }
10998+
10999+ /**
11000+ * @return string the data in XML format
11001+ */
11002+ function serializeval($o)
11003+ {
11004+ if (!is_object($o) || empty($o->me) || !is_array($o->me)) {
11005+ return '';
11006+ }
11007+ $ar = $o->me;
11008+ reset($ar);
11009+ list($typ, $val) = each($ar);
11010+ return '<value>' . $this->serializedata($typ, $val) . "</value>\n";
11011+ }
11012+
11013+ /**
11014+ * @return mixed the contents of the element requested
11015+ */
11016+ function structmem($m)
11017+ {
11018+ return $this->me['struct'][$m];
11019+ }
11020+
11021+ /**
11022+ * @return void
11023+ */
11024+ function structreset()
11025+ {
11026+ reset($this->me['struct']);
11027+ }
11028+
11029+ /**
11030+ * @return the key/value pair of the struct's current element
11031+ */
11032+ function structeach()
11033+ {
11034+ return each($this->me['struct']);
11035+ }
11036+
11037+ /**
11038+ * @return mixed the current value
11039+ */
11040+ function getval()
11041+ {
11042+ // UNSTABLE
11043+ global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
11044+
11045+ reset($this->me);
11046+ $b = current($this->me);
11047+
11048+ // contributed by I Sofer, 2001-03-24
11049+ // add support for nested arrays to scalarval
11050+ // i've created a new method here, so as to
11051+ // preserve back compatibility
11052+
11053+ if (is_array($b)) {
11054+ foreach ($b as $id => $cont) {
11055+ $b[$id] = $cont->scalarval();
11056+ }
11057+ }
11058+
11059+ // add support for structures directly encoding php objects
11060+ if (is_object($b)) {
11061+ $t = get_object_vars($b);
11062+ foreach ($t as $id => $cont) {
11063+ $t[$id] = $cont->scalarval();
11064+ }
11065+ foreach ($t as $id => $cont) {
11066+ $b->$id = $cont;
11067+ }
11068+ }
11069+
11070+ // end contrib
11071+ return $b;
11072+ }
11073+
11074+ /**
11075+ * @return mixed
11076+ */
11077+ function scalarval()
11078+ {
11079+ global $XML_RPC_Boolean, $XML_RPC_Base64;
11080+ reset($this->me);
11081+ return current($this->me);
11082+ }
11083+
11084+ /**
11085+ * @return string
11086+ */
11087+ function scalartyp()
11088+ {
11089+ global $XML_RPC_I4, $XML_RPC_Int;
11090+ reset($this->me);
11091+ $a = key($this->me);
11092+ if ($a == $XML_RPC_I4) {
11093+ $a = $XML_RPC_Int;
11094+ }
11095+ return $a;
11096+ }
11097+
11098+ /**
11099+ * @return mixed the struct's current element
11100+ */
11101+ function arraymem($m)
11102+ {
11103+ return $this->me['array'][$m];
11104+ }
11105+
11106+ /**
11107+ * @return int the number of elements in the array
11108+ */
11109+ function arraysize()
11110+ {
11111+ reset($this->me);
11112+ list($a, $b) = each($this->me);
11113+ return sizeof($b);
11114+ }
11115+
11116+ /**
11117+ * Determines if the item submitted is an XML_RPC_Value object
11118+ *
11119+ * @param mixed $val the variable to be evaluated
11120+ *
11121+ * @return bool TRUE if the item is an XML_RPC_Value object
11122+ *
11123+ * @static
11124+ * @since Method available since Release 1.3.0
11125+ */
11126+ function isValue($val)
11127+ {
11128+ return (strtolower(get_class($val)) == 'xml_rpc_value');
11129+ }
11130+}
11131+
11132+/**
11133+ * Return an ISO8601 encoded string
11134+ *
11135+ * While timezones ought to be supported, the XML-RPC spec says:
11136+ *
11137+ * "Don't assume a timezone. It should be specified by the server in its
11138+ * documentation what assumptions it makes about timezones."
11139+ *
11140+ * This routine always assumes localtime unless $utc is set to 1, in which
11141+ * case UTC is assumed and an adjustment for locale is made when encoding.
11142+ *
11143+ * @return string the formatted date
11144+ */
11145+function XML_RPC_iso8601_encode($timet, $utc = 0)
11146+{
11147+ if (!$utc) {
11148+ $t = strftime('%Y%m%dT%H:%M:%S', $timet);
11149+ } else {
11150+ if (function_exists('gmstrftime')) {
11151+ // gmstrftime doesn't exist in some versions
11152+ // of PHP
11153+ $t = gmstrftime('%Y%m%dT%H:%M:%S', $timet);
11154+ } else {
11155+ $t = strftime('%Y%m%dT%H:%M:%S', $timet - date('Z'));
11156+ }
11157+ }
11158+ return $t;
11159+}
11160+
11161+/**
11162+ * Convert a datetime string into a Unix timestamp
11163+ *
11164+ * While timezones ought to be supported, the XML-RPC spec says:
11165+ *
11166+ * "Don't assume a timezone. It should be specified by the server in its
11167+ * documentation what assumptions it makes about timezones."
11168+ *
11169+ * This routine always assumes localtime unless $utc is set to 1, in which
11170+ * case UTC is assumed and an adjustment for locale is made when encoding.
11171+ *
11172+ * @return int the unix timestamp of the date submitted
11173+ */
11174+function XML_RPC_iso8601_decode($idate, $utc = 0)
11175+{
11176+ $t = 0;
11177+ if (ereg('([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})', $idate, $regs)) {
11178+ if ($utc) {
11179+ $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
11180+ } else {
11181+ $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
11182+ }
11183+ }
11184+ return $t;
11185+}
11186+
11187+/**
11188+ * Converts an XML_RPC_Value object into native PHP types
11189+ *
11190+ * @param object $XML_RPC_val the XML_RPC_Value object to decode
11191+ *
11192+ * @return mixed the PHP values
11193+ */
11194+function XML_RPC_decode($XML_RPC_val)
11195+{
11196+ $kind = $XML_RPC_val->kindOf();
11197+
11198+ if ($kind == 'scalar') {
11199+ return $XML_RPC_val->scalarval();
11200+
11201+ } elseif ($kind == 'array') {
11202+ $size = $XML_RPC_val->arraysize();
11203+ $arr = array();
11204+ for ($i = 0; $i < $size; $i++) {
11205+ $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
11206+ }
11207+ return $arr;
11208+
11209+ } elseif ($kind == 'struct') {
11210+ $XML_RPC_val->structreset();
11211+ $arr = array();
11212+ while (list($key, $value) = $XML_RPC_val->structeach()) {
11213+ $arr[$key] = XML_RPC_decode($value);
11214+ }
11215+ return $arr;
11216+ }
11217+}
11218+
11219+/**
11220+ * Converts native PHP types into an XML_RPC_Value object
11221+ *
11222+ * @param mixed $php_val the PHP value or variable you want encoded
11223+ *
11224+ * @return object the XML_RPC_Value object
11225+ */
11226+function XML_RPC_encode($php_val)
11227+{
11228+ global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double, $XML_RPC_String,
11229+ $XML_RPC_Array, $XML_RPC_Struct;
11230+
11231+ $type = gettype($php_val);
11232+ $XML_RPC_val = new XML_RPC_Value;
11233+
11234+ switch ($type) {
11235+ case 'array':
11236+ if (empty($php_val)) {
11237+ $XML_RPC_val->addArray($php_val);
11238+ break;
11239+ }
11240+ $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1));
11241+ if (empty($tmp)) {
11242+ $arr = array();
11243+ foreach ($php_val as $k => $v) {
11244+ $arr[$k] = XML_RPC_encode($v);
11245+ }
11246+ $XML_RPC_val->addArray($arr);
11247+ break;
11248+ }
11249+ // fall though if it's not an enumerated array
11250+
11251+ case 'object':
11252+ $arr = array();
11253+ foreach ($php_val as $k => $v) {
11254+ $arr[$k] = XML_RPC_encode($v);
11255+ }
11256+ $XML_RPC_val->addStruct($arr);
11257+ break;
11258+
11259+ case 'integer':
11260+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
11261+ break;
11262+
11263+ case 'double':
11264+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
11265+ break;
11266+
11267+ case 'string':
11268+ case 'NULL':
11269+ $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
11270+ break;
11271+
11272+ case 'boolean':
11273+ // Add support for encoding/decoding of booleans, since they
11274+ // are supported in PHP
11275+ // by <G_Giunta_2001-02-29>
11276+ $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
11277+ break;
11278+
11279+ case 'unknown type':
11280+ default:
11281+ $XML_RPC_val = false;
11282+ }
11283+ return $XML_RPC_val;
11284+}
11285+
11286+/*
11287+ * Local variables:
11288+ * tab-width: 4
11289+ * c-basic-offset: 4
11290+ * c-hanging-comment-ender-p: nil
11291+ * End:
11292+ */
11293+
11294+?>
11295+
11296+
11297+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
11298+
11299+/**
11300+ * Server commands for our PHP implementation of the XML-RPC protocol
11301+ *
11302+ * This is a PEAR-ified version of Useful inc's XML-RPC for PHP.
11303+ * It has support for HTTP transport, proxies and authentication.
11304+ *
11305+ * PHP versions 4 and 5
11306+ *
11307+ * LICENSE: License is granted to use or modify this software
11308+ * ("XML-RPC for PHP") for commercial or non-commercial use provided the
11309+ * copyright of the author is preserved in any distributed or derivative work.
11310+ *
11311+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR
11312+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
11313+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11314+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
11315+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
11316+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11317+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11318+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
11319+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
11320+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11321+ *
11322+ * @category Web Services
11323+ * @package XML_RPC
11324+ * @author Edd Dumbill <edd@usefulinc.com>
11325+ * @author Stig Bakken <stig@php.net>
11326+ * @author Martin Jansen <mj@php.net>
11327+ * @author Daniel Convissor <danielc@php.net>
11328+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
11329+ * @version CVS: $Id: Server.php,v 1.29 2005/08/14 20:25:35 danielc Exp $
11330+ * @link http://pear.php.net/package/XML_RPC
11331+ */
11332+
11333+
11334+/**
11335+ * Pull in the XML_RPC class
11336+ */
11337+require_once 'XML/RPC.php';
11338+
11339+
11340+/**
11341+ * signature for system.listMethods: return = array,
11342+ * parameters = a string or nothing
11343+ * @global array $GLOBALS['XML_RPC_Server_listMethods_sig']
11344+ */
11345+$GLOBALS['XML_RPC_Server_listMethods_sig'] = array(
11346+ array($GLOBALS['XML_RPC_Array'],
11347+ $GLOBALS['XML_RPC_String']
11348+ ),
11349+ array($GLOBALS['XML_RPC_Array'])
11350+);
11351+
11352+/**
11353+ * docstring for system.listMethods
11354+ * @global string $GLOBALS['XML_RPC_Server_listMethods_doc']
11355+ */
11356+$GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the'
11357+ . ' methods that the XML-RPC server knows how to dispatch';
11358+
11359+/**
11360+ * signature for system.methodSignature: return = array,
11361+ * parameters = string
11362+ * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig']
11363+ */
11364+$GLOBALS['XML_RPC_Server_methodSignature_sig'] = array(
11365+ array($GLOBALS['XML_RPC_Array'],
11366+ $GLOBALS['XML_RPC_String']
11367+ )
11368+);
11369+
11370+/**
11371+ * docstring for system.methodSignature
11372+ * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc']
11373+ */
11374+$GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known'
11375+ . ' signatures (an array of arrays) for the method name passed. If'
11376+ . ' no signatures are known, returns a none-array (test for type !='
11377+ . ' array to detect missing signature)';
11378+
11379+/**
11380+ * signature for system.methodHelp: return = string,
11381+ * parameters = string
11382+ * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig']
11383+ */
11384+$GLOBALS['XML_RPC_Server_methodHelp_sig'] = array(
11385+ array($GLOBALS['XML_RPC_String'],
11386+ $GLOBALS['XML_RPC_String']
11387+ )
11388+);
11389+
11390+/**
11391+ * docstring for methodHelp
11392+ * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc']
11393+ */
11394+$GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined'
11395+ . ' for the method passed, otherwise returns an empty string';
11396+
11397+/**
11398+ * dispatch map for the automatically declared XML-RPC methods.
11399+ * @global array $GLOBALS['XML_RPC_Server_dmap']
11400+ */
11401+$GLOBALS['XML_RPC_Server_dmap'] = array(
11402+ 'system.listMethods' => array(
11403+ 'function' => 'XML_RPC_Server_listMethods',
11404+ 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'],
11405+ 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc']
11406+ ),
11407+ 'system.methodHelp' => array(
11408+ 'function' => 'XML_RPC_Server_methodHelp',
11409+ 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
11410+ 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc']
11411+ ),
11412+ 'system.methodSignature' => array(
11413+ 'function' => 'XML_RPC_Server_methodSignature',
11414+ 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
11415+ 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc']
11416+ )
11417+);
11418+
11419+/**
11420+ * @global string $GLOBALS['XML_RPC_Server_debuginfo']
11421+ */
11422+$GLOBALS['XML_RPC_Server_debuginfo'] = '';
11423+
11424+
11425+/**
11426+ * Lists all the methods that the XML-RPC server knows how to dispatch
11427+ *
11428+ * @return object a new XML_RPC_Response object
11429+ */
11430+function XML_RPC_Server_listMethods($server, $m)
11431+{
11432+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
11433+
11434+ $v = new XML_RPC_Value();
11435+ $outAr = array();
11436+ foreach ($server->dmap as $key => $val) {
11437+ $outAr[] = new XML_RPC_Value($key, 'string');
11438+ }
11439+ foreach ($XML_RPC_Server_dmap as $key => $val) {
11440+ $outAr[] = new XML_RPC_Value($key, 'string');
11441+ }
11442+ $v->addArray($outAr);
11443+ return new XML_RPC_Response($v);
11444+}
11445+
11446+/**
11447+ * Returns an array of known signatures (an array of arrays)
11448+ * for the given method
11449+ *
11450+ * If no signatures are known, returns a none-array
11451+ * (test for type != array to detect missing signature)
11452+ *
11453+ * @return object a new XML_RPC_Response object
11454+ */
11455+function XML_RPC_Server_methodSignature($server, $m)
11456+{
11457+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
11458+
11459+ $methName = $m->getParam(0);
11460+ $methName = $methName->scalarval();
11461+ if (strpos($methName, 'system.') === 0) {
11462+ $dmap = $XML_RPC_Server_dmap;
11463+ $sysCall = 1;
11464+ } else {
11465+ $dmap = $server->dmap;
11466+ $sysCall = 0;
11467+ }
11468+ // print "<!-- ${methName} -->\n";
11469+ if (isset($dmap[$methName])) {
11470+ if ($dmap[$methName]['signature']) {
11471+ $sigs = array();
11472+ $thesigs = $dmap[$methName]['signature'];
11473+ for ($i = 0; $i < sizeof($thesigs); $i++) {
11474+ $cursig = array();
11475+ $inSig = $thesigs[$i];
11476+ for ($j = 0; $j < sizeof($inSig); $j++) {
11477+ $cursig[] = new XML_RPC_Value($inSig[$j], 'string');
11478+ }
11479+ $sigs[] = new XML_RPC_Value($cursig, 'array');
11480+ }
11481+ $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array'));
11482+ } else {
11483+ $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string'));
11484+ }
11485+ } else {
11486+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
11487+ $XML_RPC_str['introspect_unknown']);
11488+ }
11489+ return $r;
11490+}
11491+
11492+/**
11493+ * Returns help text if defined for the method passed, otherwise returns
11494+ * an empty string
11495+ *
11496+ * @return object a new XML_RPC_Response object
11497+ */
11498+function XML_RPC_Server_methodHelp($server, $m)
11499+{
11500+ global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
11501+
11502+ $methName = $m->getParam(0);
11503+ $methName = $methName->scalarval();
11504+ if (strpos($methName, 'system.') === 0) {
11505+ $dmap = $XML_RPC_Server_dmap;
11506+ $sysCall = 1;
11507+ } else {
11508+ $dmap = $server->dmap;
11509+ $sysCall = 0;
11510+ }
11511+
11512+ if (isset($dmap[$methName])) {
11513+ if ($dmap[$methName]['docstring']) {
11514+ $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']),
11515+ 'string');
11516+ } else {
11517+ $r = new XML_RPC_Response(new XML_RPC_Value('', 'string'));
11518+ }
11519+ } else {
11520+ $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'],
11521+ $XML_RPC_str['introspect_unknown']);
11522+ }
11523+ return $r;
11524+}
11525+
11526+/**
11527+ * @return void
11528+ */
11529+function XML_RPC_Server_debugmsg($m)
11530+{
11531+ global $XML_RPC_Server_debuginfo;
11532+ $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
11533+}
11534+
11535+
11536+/**
11537+ * A server for receiving and replying to XML RPC requests
11538+ *
11539+ * <code>
11540+ * $server = new XML_RPC_Server(
11541+ * array(
11542+ * 'isan8' =>
11543+ * array(
11544+ * 'function' => 'is_8',
11545+ * 'signature' =>
11546+ * array(
11547+ * array('boolean', 'int'),
11548+ * array('boolean', 'int', 'boolean'),
11549+ * array('boolean', 'string'),
11550+ * array('boolean', 'string', 'boolean'),
11551+ * ),
11552+ * 'docstring' => 'Is the value an 8?'
11553+ * ),
11554+ * ),
11555+ * 1,
11556+ * 0
11557+ * );
11558+ * </code>
11559+ *
11560+ * @category Web Services
11561+ * @package XML_RPC
11562+ * @author Edd Dumbill <edd@usefulinc.com>
11563+ * @author Stig Bakken <stig@php.net>
11564+ * @author Martin Jansen <mj@php.net>
11565+ * @author Daniel Convissor <danielc@php.net>
11566+ * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group
11567+ * @version Release: 1.4.0
11568+ * @link http://pear.php.net/package/XML_RPC
11569+ */
11570+class XML_RPC_Server
11571+{
11572+ /**
11573+ * The dispatch map, listing the methods this server provides.
11574+ * @var array
11575+ */
11576+ var $dmap = array();
11577+
11578+ /**
11579+ * The present response's encoding
11580+ * @var string
11581+ * @see XML_RPC_Message::getEncoding()
11582+ */
11583+ var $encoding = '';
11584+
11585+ /**
11586+ * Debug mode (0 = off, 1 = on)
11587+ * @var integer
11588+ */
11589+ var $debug = 0;
11590+
11591+ /**
11592+ * The response's HTTP headers
11593+ * @var string
11594+ */
11595+ var $server_headers = '';
11596+
11597+ /**
11598+ * The response's XML payload
11599+ * @var string
11600+ */
11601+ var $server_payload = '';
11602+
11603+
11604+ /**
11605+ * Constructor for the XML_RPC_Server class
11606+ *
11607+ * @param array $dispMap the dispatch map. An associative array
11608+ * explaining each function. The keys of the main
11609+ * array are the procedure names used by the
11610+ * clients. The value is another associative array
11611+ * that contains up to three elements:
11612+ * + The 'function' element's value is the name
11613+ * of the function or method that gets called.
11614+ * To define a class' method: 'class::method'.
11615+ * + The 'signature' element (optional) is an
11616+ * array describing the return values and
11617+ * parameters
11618+ * + The 'docstring' element (optional) is a
11619+ * string describing what the method does
11620+ * @param int $serviceNow should the HTTP response be sent now?
11621+ * (1 = yes, 0 = no)
11622+ * @param int $debug should debug output be displayed?
11623+ * (1 = yes, 0 = no)
11624+ *
11625+ * @return void
11626+ */
11627+ function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0)
11628+ {
11629+ global $HTTP_RAW_POST_DATA;
11630+
11631+ if ($debug) {
11632+ $this->debug = 1;
11633+ } else {
11634+ $this->debug = 0;
11635+ }
11636+
11637+ $this->dmap = $dispMap;
11638+
11639+ if ($serviceNow) {
11640+ $this->service();
11641+ } else {
11642+ $this->createServerPayload();
11643+ $this->createServerHeaders();
11644+ }
11645+ }
11646+
11647+ /**
11648+ * @return string the debug information if debug debug mode is on
11649+ */
11650+ function serializeDebug()
11651+ {
11652+ global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA;
11653+
11654+ if ($this->debug) {
11655+ XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n"
11656+ . $HTTP_RAW_POST_DATA
11657+ . "\n" . '^^^ END POST DATA ^^^');
11658+ }
11659+
11660+ if ($XML_RPC_Server_debuginfo != '') {
11661+ return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n"
11662+ . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo)
11663+ . "-->\n";
11664+ } else {
11665+ return '';
11666+ }
11667+ }
11668+
11669+ /**
11670+ * Sends the response
11671+ *
11672+ * The encoding and content-type are determined by
11673+ * XML_RPC_Message::getEncoding()
11674+ *
11675+ * @return void
11676+ *
11677+ * @uses XML_RPC_Server::createServerPayload(),
11678+ * XML_RPC_Server::createServerHeaders()
11679+ */
11680+ function service()
11681+ {
11682+ if (!$this->server_payload) {
11683+ $this->createServerPayload();
11684+ }
11685+ if (!$this->server_headers) {
11686+ $this->createServerHeaders();
11687+ }
11688+ header($this->server_headers);
11689+ print $this->server_payload;
11690+ }
11691+
11692+ /**
11693+ * Generates the payload and puts it in the $server_payload property
11694+ *
11695+ * @return void
11696+ *
11697+ * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding,
11698+ * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug()
11699+ */
11700+ function createServerPayload()
11701+ {
11702+ $r = $this->parseRequest();
11703+ $this->server_payload = '<?xml version="1.0" encoding="'
11704+ . $this->encoding . '"?>' . "\n"
11705+ . $this->serializeDebug()
11706+ . $r->serialize();
11707+ }
11708+
11709+ /**
11710+ * Determines the HTTP headers and puts them in the $server_headers
11711+ * property
11712+ *
11713+ * @return boolean TRUE if okay, FALSE if $server_payload isn't set.
11714+ *
11715+ * @uses XML_RPC_Server::createServerPayload(),
11716+ * XML_RPC_Server::$server_headers
11717+ */
11718+ function createServerHeaders()
11719+ {
11720+ if (!$this->server_payload) {
11721+ return false;
11722+ }
11723+ $this->server_headers = 'Content-Length: '
11724+ . strlen($this->server_payload) . "\r\n"
11725+ . 'Content-Type: text/xml;'
11726+ . ' charset=' . $this->encoding;
11727+ return true;
11728+ }
11729+
11730+ /**
11731+ * @return array
11732+ */
11733+ function verifySignature($in, $sig)
11734+ {
11735+ for ($i = 0; $i < sizeof($sig); $i++) {
11736+ // check each possible signature in turn
11737+ $cursig = $sig[$i];
11738+ if (sizeof($cursig) == $in->getNumParams() + 1) {
11739+ $itsOK = 1;
11740+ for ($n = 0; $n < $in->getNumParams(); $n++) {
11741+ $p = $in->getParam($n);
11742+ // print "<!-- $p -->\n";
11743+ if ($p->kindOf() == 'scalar') {
11744+ $pt = $p->scalartyp();
11745+ } else {
11746+ $pt = $p->kindOf();
11747+ }
11748+ // $n+1 as first type of sig is return type
11749+ if ($pt != $cursig[$n+1]) {
11750+ $itsOK = 0;
11751+ $pno = $n+1;
11752+ $wanted = $cursig[$n+1];
11753+ $got = $pt;
11754+ break;
11755+ }
11756+ }
11757+ if ($itsOK) {
11758+ return array(1);
11759+ }
11760+ }
11761+ }
11762+ if (isset($wanted)) {
11763+ return array(0, "Wanted ${wanted}, got ${got} at param ${pno}");
11764+ } else {
11765+ $allowed = array();
11766+ foreach ($sig as $val) {
11767+ end($val);
11768+ $allowed[] = key($val);
11769+ }
11770+ $allowed = array_unique($allowed);
11771+ $last = count($allowed) - 1;
11772+ if ($last > 0) {
11773+ $allowed[$last] = 'or ' . $allowed[$last];
11774+ }
11775+ return array(0,
11776+ 'Signature permits ' . implode(', ', $allowed)
11777+ . ' parameters but the request had '
11778+ . $in->getNumParams());
11779+ }
11780+ }
11781+
11782+ /**
11783+ * @return object a new XML_RPC_Response object
11784+ *
11785+ * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding
11786+ */
11787+ function parseRequest($data = '')
11788+ {
11789+ global $XML_RPC_xh, $HTTP_RAW_POST_DATA,
11790+ $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
11791+ $XML_RPC_defencoding, $XML_RPC_Server_dmap;
11792+
11793+ if ($data == '') {
11794+ $data = $HTTP_RAW_POST_DATA;
11795+ }
11796+
11797+ $this->encoding = XML_RPC_Message::getEncoding($data);
11798+ $parser_resource = xml_parser_create($this->encoding);
11799+ $parser = (int) $parser_resource;
11800+
11801+ $XML_RPC_xh[$parser] = array();
11802+ $XML_RPC_xh[$parser]['cm'] = 0;
11803+ $XML_RPC_xh[$parser]['isf'] = 0;
11804+ $XML_RPC_xh[$parser]['params'] = array();
11805+ $XML_RPC_xh[$parser]['method'] = '';
11806+ $XML_RPC_xh[$parser]['stack'] = array();
11807+ $XML_RPC_xh[$parser]['valuestack'] = array();
11808+
11809+ $plist = '';
11810+
11811+ // decompose incoming XML into request structure
11812+
11813+ xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true);
11814+ xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee');
11815+ xml_set_character_data_handler($parser_resource, 'XML_RPC_cd');
11816+ if (!xml_parse($parser_resource, $data, 1)) {
11817+ // return XML error as a faultCode
11818+ $r = new XML_RPC_Response(0,
11819+ $XML_RPC_errxml+xml_get_error_code($parser_resource),
11820+ sprintf('XML error: %s at line %d',
11821+ xml_error_string(xml_get_error_code($parser_resource)),
11822+ xml_get_current_line_number($parser_resource)));
11823+ xml_parser_free($parser_resource);
11824+ } elseif ($XML_RPC_xh[$parser]['isf']>1) {
11825+ $r = new XML_RPC_Response(0,
11826+ $XML_RPC_err['invalid_request'],
11827+ $XML_RPC_str['invalid_request']
11828+ . ': '
11829+ . $XML_RPC_xh[$parser]['isf_reason']);
11830+ xml_parser_free($parser_resource);
11831+ } else {
11832+ xml_parser_free($parser_resource);
11833+ $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
11834+ // now add parameters in
11835+ for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
11836+ // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
11837+ $plist .= "$i - " . var_export($XML_RPC_xh[$parser]['params'][$i], true) . " \n";
11838+ $m->addParam($XML_RPC_xh[$parser]['params'][$i]);
11839+ }
11840+ XML_RPC_Server_debugmsg($plist);
11841+
11842+ // now to deal with the method
11843+ $methName = $XML_RPC_xh[$parser]['method'];
11844+ if (strpos($methName, 'system.') === 0) {
11845+ $dmap = $XML_RPC_Server_dmap;
11846+ $sysCall = 1;
11847+ } else {
11848+ $dmap = $this->dmap;
11849+ $sysCall = 0;
11850+ }
11851+
11852+ if (isset($dmap[$methName]['function'])
11853+ && is_string($dmap[$methName]['function'])
11854+ && strpos($dmap[$methName]['function'], '::') !== false)
11855+ {
11856+ $dmap[$methName]['function'] =
11857+ explode('::', $dmap[$methName]['function']);
11858+ }
11859+
11860+ if (isset($dmap[$methName]['function'])
11861+ && is_callable($dmap[$methName]['function']))
11862+ {
11863+ // dispatch if exists
11864+ if (isset($dmap[$methName]['signature'])) {
11865+ $sr = $this->verifySignature($m,
11866+ $dmap[$methName]['signature'] );
11867+ }
11868+ if (!isset($dmap[$methName]['signature']) || $sr[0]) {
11869+ // if no signature or correct signature
11870+ if ($sysCall) {
11871+ $r = call_user_func($dmap[$methName]['function'], $this, $m);
11872+ } else {
11873+ $r = call_user_func($dmap[$methName]['function'], $m);
11874+ }
11875+ if (!is_a($r, 'XML_RPC_Response')) {
11876+ $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'],
11877+ $XML_RPC_str['not_response_object']);
11878+ }
11879+ } else {
11880+ $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'],
11881+ $XML_RPC_str['incorrect_params']
11882+ . ': ' . $sr[1]);
11883+ }
11884+ } else {
11885+ // else prepare error response
11886+ $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'],
11887+ $XML_RPC_str['unknown_method']);
11888+ }
11889+ }
11890+ return $r;
11891+ }
11892+
11893+ /**
11894+ * Echos back the input packet as a string value
11895+ *
11896+ * @return void
11897+ *
11898+ * Useful for debugging.
11899+ */
11900+ function echoInput()
11901+ {
11902+ global $HTTP_RAW_POST_DATA;
11903+
11904+ $r = new XML_RPC_Response(0);
11905+ $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string');
11906+ print $r->serialize();
11907+ }
11908+}
11909+
11910+/*
11911+ * Local variables:
11912+ * tab-width: 4
11913+ * c-basic-offset: 4
11914+ * c-hanging-comment-ender-p: nil
11915+ * End:
11916+ */
11917+
11918+?>
11919+
11920+<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
11921+<package version="1.0" packagerversion="1.4.0a12">
11922+ <name>XML_RPC</name>
11923+ <summary>PHP implementation of the XML-RPC protocol</summary>
11924+ <description>A PEAR-ified version of Useful Inc's XML-RPC for PHP.
11925+
11926+It has support for HTTP/HTTPS transport, proxies and authentication.
11927+ </description>
11928+ <maintainers>
11929+ <maintainer>
11930+ <user>ssb</user>
11931+ <name>Stig Bakken</name>
11932+ <email>stig@php.net</email>
11933+ <role>lead</role>
11934+ </maintainer>
11935+ <maintainer>
11936+ <user>danielc</user>
11937+ <name>Daniel Convissor</name>
11938+ <email>danielc@php.net</email>
11939+ <role>lead</role>
11940+ </maintainer>
11941+ </maintainers>
11942+ <release>
11943+ <version>1.4.0</version>
11944+ <date>2005-08-14</date>
11945+ <license>PHP License</license>
11946+ <state>stable</state>
11947+ <notes>* MAJOR SECURITY FIX: eliminate use of eval().
11948+* Using socket_get_status() because stream_get_meta_data() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.
11949+ </notes>
11950+ <filelist>
11951+ <file role="php" baseinstalldir="XML" name="RPC.php">
11952+ <replace from="@package_version@" to="version" type="package-info"/>
11953+ </file>
11954+ <file role="php" baseinstalldir="XML/RPC" name="Server.php">
11955+ <replace from="@package_version@" to="version" type="package-info"/>
11956+ </file>
11957+ <file role="php" baseinstalldir="XML/RPC" name="Dump.php">
11958+ <replace from="@package_version@" to="version" type="package-info"/>
11959+ </file>
11960+ <file role="test" name="tests/protoport.php">
11961+ <replace from="@package_version@" to="version" type="package-info"/>
11962+ </file>
11963+ <file role="test" name="tests/test_Dump.php">
11964+ <replace from="@package_version@" to="version" type="package-info"/>
11965+ </file>
11966+ </filelist>
11967+ </release>
11968+ <changelog>
11969+ <release>
11970+ <version>1.3.3</version>
11971+ <date>2005-07-15</date>
11972+ <state>stable</state>
11973+ <notes>* Eliminate memory leak by resetting $XML_RPC_xh each time parseResponse() is called. Bug 4780.
11974+* Using socket_set_timeout() because stream_set_timeout() was introduced in 4.3.0, but we need to support 4.2.0. Bug 4805.
11975+ </notes>
11976+ </release>
11977+ <release>
11978+ <version>1.3.2</version>
11979+ <date>2005-07-07</date>
11980+ <state>stable</state>
11981+ <notes>* Eliminate path disclosure vulnerabilities by suppressing error messages when eval()'ing.
11982+* Eliminate path disclosure vulnerability by catching bogus parameters submitted to XML_RPC_Value::serializeval().
11983+* In XML_RPC_Server::service(), only call createServerPayload() and createServerHeaders() if necessary. Fixes compatibility issue introduced in Release 1.3.0RC1 for users who set the $serviceNow parameter of XML_RPC_Server() to 0. Bug 4757.
11984+* Change &quot;var $errstring&quot; to &quot;var $errstr&quot;. Bug 4582. Was put into CVS version 1.75 of RPC.php but didn't make it into RELEASE_1_3_1.
11985+ </notes>
11986+ </release>
11987+ <release>
11988+ <version>1.3.1</version>
11989+ <date>2005-06-29</date>
11990+ <state>stable</state>
11991+ <notes>* Security fix. Update highly recommended!
11992+ </notes>
11993+ </release>
11994+ <release>
11995+ <version>1.3.0</version>
11996+ <date>2005-06-13</date>
11997+ <state>stable</state>
11998+ <notes>* Stable release. See earlier releases for changes since 1.2.2.
11999+ </notes>
12000+ </release>
12001+ <release>
12002+ <version>1.3.0RC3</version>
12003+ <date>2005-05-10</date>
12004+ <state>beta</state>
12005+ <notes>* When verifying requests against function signatures, if the number of parameters don't match, provide an appropriate message. NOTE: this resolves a path disclosure vulnerability. (Refines the changes made in the last commit.) Bug 4231.
12006+* XML_RPC_Message::getParam() now returns an XML_RPC_Response object upon error. Changed from Release 1.3.0RC2.
12007+* Add the XML_RPC_Value::isValue() method. For testing if an item is an XML_RPC_Value object.
12008+* If XML_RPC_Client::send() is given an incorrect $msg parameter, raise an error with the new XML_RPC_ERROR_PROGRAMMING code and return 0.
12009+* Improve cross-platform operation by using PEAR::loadExtension() instead of dl().
12010+* Use &lt;br /&gt; instead of &lt;br&gt; in XML_RPC_Value::dump().
12011+ </notes>
12012+ </release>
12013+ <release>
12014+ <version>1.3.0RC2</version>
12015+ <date>2005-05-05</date>
12016+ <state>beta</state>
12017+ <notes>* If XML_RPC_Message::getParam() is given an incorrect parameter, raise an error with the new XML_RPC_ERROR_INCORRECT_PARAMS code and return FALSE.
12018+* Handle improper requests to XML_RPC_Server::verifySignature(). Bug 4231.
12019+* Try to allow HTTP 100 responses if followed by a 200 response. Bug 4116.
12020+* Help Delphi users by making RPCMETHODNAME an alias for METHODNAME. Request 4205.
12021+ </notes>
12022+ </release>
12023+ <release>
12024+ <version>1.3.0RC1</version>
12025+ <date>2005-04-07</date>
12026+ <state>beta</state>
12027+ <notes>* Improve timeout handling for situations where connection to server is made but no response is not received in time. Accomplished via stream_set_timeout(). Request 3963.
12028+* Add Fault Code 6: &quot;The requested method didn't return an XML_RPC_Response object.&quot; Request 4032.
12029+* Add the createServerPayload() and createServerHeaders() methods and the $server_payload and $server_headers properties. Request 3121.
12030+* As in earlier versions, if the $serviceNow parameter to XML_RPC_Server() is 0, no data will be returned, but now the new $server_payload and $server_headers properties will be set.
12031+* Convert the parser handle to an integer before using it as an index for $XML_RPC_xh[$parser]. Reduces E_STRICT notices. Bug 3782.
12032+* Add createHeaders() method and $headers property to XML_RPC_Client to make testing easier.
12033+ </notes>
12034+ </release>
12035+ <release>
12036+ <version>1.2.2</version>
12037+ <date>2005-03-07</date>
12038+ <state>stable</state>
12039+ <notes>* When using a proxy, add the protocol to the Request-URI, making it an &quot;absoluteURI&quot; as per the HTTP 1.0 spec. Bug 3679.
12040+ </notes>
12041+ </release>
12042+ <release>
12043+ <version>1.2.1</version>
12044+ <date>2005-03-01</date>
12045+ <state>stable</state>
12046+ <notes>* Add isset() check before examining the dispatch map. Bug 3658.
12047+ </notes>
12048+ </release>
12049+ <release>
12050+ <version>1.2.0</version>
12051+ <date>2005-02-27</date>
12052+ <state>stable</state>
12053+ <notes>* Provide the &quot;stable&quot; release.
12054+* Add package2.xml for compatibility with PEAR 1.4.0.
12055+* For changes since 1.1.0, see the changelogs for the various RC releases.
12056+ </notes>
12057+ </release>
12058+ <release>
12059+ <version>1.2.0RC7</version>
12060+ <date>2005-02-22</date>
12061+ <state>beta</state>
12062+ <notes>* Add the setSendEncoding() method and $send_encoding
12063+ property to XML_RPC_Message. Request 3537.
12064+* Allow class methods to be mapped using either syntax:
12065+ 'function' =&gt; 'hello::sayHello',
12066+ or
12067+ 'function' =&gt; array('hello', 'sayhello'),
12068+ Bug 3363.
12069+* Use 8192 instead of 32768 for bytes in fread()
12070+ in parseResponseFile(). Bug 3340.
12071+ </notes>
12072+ </release>
12073+ <release>
12074+ <version>1.2.0RC6</version>
12075+ <date>2005-01-25</date>
12076+ <state>beta</state>
12077+ <notes>* Don't put the protocol in the Host field of the POST data. (danielc)
12078+ </notes>
12079+ </release>
12080+ <release>
12081+ <version>1.2.0RC5</version>
12082+ <date>2005-01-24</date>
12083+ <state>beta</state>
12084+ <notes>* If $port is 443 but a protocol isn't specified in $server, assume ssl:// is the protocol.
12085+ </notes>
12086+ </release>
12087+ <release>
12088+ <version>1.2.0RC4</version>
12089+ <date>2005-01-24</date>
12090+ <state>beta</state>
12091+ <notes>* When a connection attempt fails, have the method return 0. (danielc)
12092+* Move the protocol/port checking/switching and the property settings from sendPayloadHTTP10() to the XML_RPC_Client constructor. (danielc)
12093+* Add tests for setting the client properties. (danielc)
12094+* Remove $GLOBALS['XML_RPC_twoslash'] since it's not used. (danielc)
12095+* Bundle the tests with the package. (danielc)
12096+ </notes>
12097+ </release>
12098+ <release>
12099+ <version>1.2.0RC3</version>
12100+ <date>2005-01-19</date>
12101+ <state>beta</state>
12102+ <notes>* ssl uses port 443, not 445.
12103+ </notes>
12104+ </release>
12105+ <release>
12106+ <version>1.2.0RC2</version>
12107+ <date>2005-01-11</date>
12108+ <state>beta</state>
12109+ <notes>* Handle ssl:// in the $server string. (danielc)
12110+* Also default to port 445 for ssl:// requests as well. (danielc)
12111+* Enhance debugging in the server. (danielc)
12112+ </notes>
12113+ </release>
12114+ <release>
12115+ <version>1.2.0RC1</version>
12116+ <date>2004-12-30</date>
12117+ <state>beta</state>
12118+ <notes>* Make things work with SSL. Bug 2489. (nkukard lbsd net)
12119+* Allow array function callbacks (Matt Kane)
12120+* Some minor speed-ups (Matt Kane)
12121+* Add Dump.php to the package (Christian Weiske)
12122+* Replace all line endings with \r\n. Had only done replacements on \n. Bug 2521. (danielc)
12123+* Silence fsockopen() errors. Bug 1714. (danielc)
12124+* Encode empty arrays as an array. Bug 1493. (danielc)
12125+* Eliminate undefined index notice when submitting empty arrays to XML_RPC_Encode(). Bug 1819. (danielc)
12126+* Speed up check for enumerated arrays in XML_RPC_Encode(). (danielc)
12127+* Prepend &quot;XML_RPC_&quot; to ERROR_NON_NUMERIC_FOUND, eliminating problem when eval()'ing error messages. (danielc)
12128+* Use XML_RPC_Base::raiseError() instead of PEAR::raiseError() in XML_RPC_ee() because PEAR.php is lazy loaded. (danielc)
12129+* Allow raiseError() to be called statically. (danielc)
12130+* Stop double escaping of character entities. Bug 987. (danielc)
12131+ NOTICE: the following have been removed:
12132+ * XML_RPC_dh()
12133+ * $GLOBALS['XML_RPC_entities']
12134+ * XML_RPC_entity_decode()
12135+ * XML_RPC_lookup_entity()
12136+* Determine the XML's encoding via the encoding attribute in the XML declaration. Bug 52. (danielc)
12137+ </notes>
12138+ </release>
12139+ <release>
12140+ <version>1.1.0</version>
12141+ <date>2004-03-15</date>
12142+ <state>stable</state>
12143+ <notes>* Added support for sequential arrays to XML_RPC_encode() (mroch)
12144+* Cleaned up new XML_RPC_encode() changes a bit (mroch, pierre)
12145+* Remove &quot;require_once 'PEAR.php'&quot;, include only when needed to raise an error
12146+* Replace echo and error_log() with raiseError() (mroch)
12147+* Make all classes extend XML_RPC_Base, which will handle common functions (mroch)
12148+* be tolerant of junk after methodResponse (Luca Mariano, mroch)
12149+* Silent notice even in the error log (pierre)
12150+* fix include of shared xml extension on win32 (pierre)
12151+ </notes>
12152+ </release>
12153+ <release>
12154+ <version>1.0.4</version>
12155+ <date>2002-10-02</date>
12156+ <state>stable</state>
12157+ <notes>* added HTTP proxy authorization support (thanks to Arnaud Limbourg)
12158+ </notes>
12159+ </release>
12160+ <release>
12161+ <version>1.0.3</version>
12162+ <date>2002-05-19</date>
12163+ <state>stable</state>
12164+ <notes>* fix bug when parsing responses with boolean types
12165+ </notes>
12166+ </release>
12167+ <release>
12168+ <version>1.0.2</version>
12169+ <date>2002-04-16</date>
12170+ <state>stable</state>
12171+ <notes>* E_ALL fixes
12172+* fix HTTP response header parsing
12173+ </notes>
12174+ </release>
12175+ <release>
12176+ <version>1.0.1</version>
12177+ <date>2001-09-25</date>
12178+ <state>stable</state>
12179+ <notes>This is a PEAR-ified version of Useful Inc's 1.0.1 release.
12180+Includes an urgent security fix identified by Dan Libby &lt;dan@libby.com&gt;.
12181+ </notes>
12182+ </release>
12183+ </changelog>
12184+</package>
12185+
12186\ Kein Zeilenumbruch am Dateiende.
12187diff -Nura php-4.4.0/php.ini-dist hardening-patch-4.4.0-0.4.3/php.ini-dist
12188--- php-4.4.0/php.ini-dist 2005-04-28 15:14:45.000000000 +0200
12189+++ hardening-patch-4.4.0-0.4.3/php.ini-dist 2005-09-12 23:44:36.000000000 +0200
12190@@ -1112,6 +1112,197 @@
12191 ;exif.decode_jis_motorola = JIS
12192 ;exif.decode_jis_intel = JIS
12193
12194+[hardening-patch]
12195+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12196+; Hardening-Patch's logging ;
12197+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12198+
12199+;
12200+; hphp.log.syslog - Configures level for alerts reported through syslog
12201+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
12202+; hphp.log.script - Configures level for alerts reported through external script
12203+;
12204+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
12205+; Or each number up to get desired Hardening-Patch's reporting level
12206+;
12207+; S_ALL - All alerts
12208+; S_MEMORY - All canary violations and the safe unlink protection use this class
12209+; S_VARS - All variable filters trigger this class
12210+; S_FILES - All violation of uploaded files filter use this class
12211+; S_INCLUDE - The protection against malicious include filenames use this class
12212+; S_SQL - Failed SQL queries in MySQL are logged with this class
12213+; S_EXECUTOR - The execution depth protection uses this logging class
12214+; S_MISC - All other log messages (f.e. format string protection) use this class
12215+;
12216+; Example:
12217+;
12218+; - Report all alerts (except memory alerts) to the SAPI errorlog,
12219+; memory alerts through syslog and SQL+Include alerts fo the script
12220+;
12221+;hphp.log.syslog = S_MEMORY
12222+;hphp.log.sapi = S_ALL & ~S_MEMORY
12223+;hphp.log.script = S_INCLUDE | S_SQL
12224+;
12225+; Syslog logging:
12226+;
12227+; - Facility configuration: one of the following facilities
12228+;
12229+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
12230+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
12231+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
12232+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
12233+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
12234+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
12235+; LOG_PERROR
12236+;
12237+; - Priority configuration: one of the followinf priorities
12238+;
12239+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
12240+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
12241+;
12242+hphp.log.syslog.priority = LOG_ALERT
12243+hphp.log.syslog.facility = LOG_USER
12244+;
12245+; Script logging:
12246+;
12247+;hphp.log.script.name = /home/hphp/log_script
12248+;
12249+; Alert configuration:
12250+;
12251+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
12252+;
12253+;hphp.log.use-x-forwarded-for = On
12254+;
12255+
12256+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12257+; Hardening-Patch's Executor options ;
12258+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12259+
12260+; Execution depth limit
12261+;hphp.executor.max_depth = 8000
12262+
12263+; White-/blacklist for function calls during normal execution
12264+;hphp.executor.func.whitelist = ord,chr
12265+;hphp.executor.func.blacklist = system,shell_exec,popen,proc_open,exec,passthru
12266+
12267+; White-/blacklist for function calls during eval() execution
12268+;hphp.executor.eval.whitelist = ord,chr
12269+;hphp.executor.eval.blacklist = system,shell_exec,popen,proc_open,exec,passthru
12270+
12271+; White-/blacklist for URLs allowes in include filenames
12272+;
12273+; - When both options are not set all URLs are forbidden
12274+;
12275+; - When both options are set whitelist is taken and blacklist ignored
12276+;
12277+; - An entry in the lists is either a URL sheme like: http, https
12278+; or the beginning of an URL like: php://input
12279+;
12280+;hphp.executor.include.whitelist = cookietest
12281+;hphp.executor.include.blacklist = http, https, ftp, ftps, php://input, file
12282+
12283+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12284+; Hardening-Patch's REQUEST variable filters ;
12285+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12286+
12287+; Limits the number of REQUEST variables
12288+hphp.request.max_vars = 200
12289+
12290+; Limits the length of variable names (without indices)
12291+hphp.request.max_varname_length = 64
12292+
12293+; Limits the length of complete variable names (with indices)
12294+hphp.request.max_totalname_length = 256
12295+
12296+; Limits the length of array indices
12297+hphp.request.max_array_index_length = 64
12298+
12299+; Limits the depth of arrays
12300+hphp.request.max_array_depth = 100
12301+
12302+; Limits the length of variable values
12303+hphp.request.max_value_length = 65000
12304+
12305+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12306+; Hardening-Patch's COOKIE variable filters ;
12307+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12308+
12309+; Limits the number of COOKIE variables
12310+hphp.cookie.max_vars = 100
12311+
12312+; Limits the length of variable names (without indices)
12313+hphp.cookie.max_name_length = 64
12314+
12315+; Limits the length of complete variable names (with indices)
12316+hphp.cookie.max_totalname_length = 256
12317+
12318+; Limits the length of array indices
12319+hphp.cookie.max_array_index_length = 64
12320+
12321+; Limits the depth of arrays
12322+hphp.cookie.max_array_depth = 100
12323+
12324+; Limits the length of variable values
12325+hphp.cookie.max_value_length = 10000
12326+
12327+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12328+; Hardening-Patch's GET variable filters ;
12329+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12330+
12331+; Limits the number of COOKIE variables
12332+hphp.get.max_vars = 100
12333+
12334+; Limits the length of variable names (without indices)
12335+hphp.get.max_name_length = 64
12336+
12337+; Limits the length of complete variable names (with indices)
12338+hphp.get.max_totalname_length = 256
12339+
12340+; Limits the length of array indices
12341+hphp.get.max_array_index_length = 64
12342+
12343+; Limits the depth of arrays
12344+hphp.get.max_array_depth = 50
12345+
12346+; Limits the length of variable values
12347+hphp.get.max_value_length = 512
12348+
12349+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12350+; Hardening-Patch's POST variable filters ;
12351+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12352+
12353+; Limits the number of POST variables
12354+hphp.post.max_vars = 200
12355+
12356+; Limits the length of variable names (without indices)
12357+hphp.post.max_name_length = 64
12358+
12359+; Limits the length of complete variable names (with indices)
12360+hphp.post.max_totalname_length = 256
12361+
12362+; Limits the length of array indices
12363+hphp.post.max_array_index_length = 64
12364+
12365+; Limits the depth of arrays
12366+hphp.post.max_array_depth = 100
12367+
12368+; Limits the length of variable values
12369+hphp.post.max_value_length = 65000
12370+
12371+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12372+; Hardening-Patch's fileupload variable filters ;
12373+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12374+
12375+; Limits the number of uploadable files
12376+hphp.upload.max_uploads = 25
12377+
12378+; Filter out the upload of ELF executables
12379+hphp.upload.disallow_elf_files = On
12380+
12381+; External filterscript for upload verification
12382+;hphp.upload.verification_script = /home/hphp/verify_script
12383+
12384+
12385 ; Local Variables:
12386 ; tab-width: 4
12387 ; End:
12388diff -Nura php-4.4.0/php.ini-recommended hardening-patch-4.4.0-0.4.3/php.ini-recommended
12389--- php-4.4.0/php.ini-recommended 2005-04-28 15:14:46.000000000 +0200
12390+++ hardening-patch-4.4.0-0.4.3/php.ini-recommended 2005-09-12 23:45:36.000000000 +0200
12391@@ -1110,6 +1110,197 @@
12392 ;exif.decode_jis_motorola = JIS
12393 ;exif.decode_jis_intel = JIS
12394
12395+[hardening-patch]
12396+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12397+; Hardening-Patch's logging ;
12398+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12399+
12400+;
12401+; hphp.log.syslog - Configures level for alerts reported through syslog
12402+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
12403+; hphp.log.script - Configures level for alerts reported through external script
12404+;
12405+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
12406+; Or each number up to get desired Hardening-Patch's reporting level
12407+;
12408+; S_ALL - All alerts
12409+; S_MEMORY - All canary violations and the safe unlink protection use this class
12410+; S_VARS - All variable filters trigger this class
12411+; S_FILES - All violation of uploaded files filter use this class
12412+; S_INCLUDE - The protection against malicious include filenames use this class
12413+; S_SQL - Failed SQL queries in MySQL are logged with this class
12414+; S_EXECUTOR - The execution depth protection uses this logging class
12415+; S_MISC - All other log messages (f.e. format string protection) use this class
12416+;
12417+; Example:
12418+;
12419+; - Report all alerts (except memory alerts) to the SAPI errorlog,
12420+; memory alerts through syslog and SQL+Include alerts fo the script
12421+;
12422+;hphp.log.syslog = S_MEMORY
12423+;hphp.log.sapi = S_ALL & ~S_MEMORY
12424+;hphp.log.script = S_INCLUDE | S_SQL
12425+;
12426+; Syslog logging:
12427+;
12428+; - Facility configuration: one of the following facilities
12429+;
12430+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
12431+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
12432+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
12433+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
12434+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
12435+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
12436+; LOG_PERROR
12437+;
12438+; - Priority configuration: one of the followinf priorities
12439+;
12440+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
12441+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
12442+;
12443+hphp.log.syslog.priority = LOG_ALERT
12444+hphp.log.syslog.facility = LOG_USER
12445+;
12446+; Script logging:
12447+;
12448+;hphp.log.script.name = /home/hphp/log_script
12449+;
12450+; Alert configuration:
12451+;
12452+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
12453+;
12454+;hphp.log.use-x-forwarded-for = On
12455+;
12456+
12457+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12458+; Hardening-Patch's Executor options ;
12459+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12460+
12461+; Execution depth limit
12462+;hphp.executor.max_depth = 8000
12463+
12464+; White-/blacklist for function calls during normal execution
12465+;hphp.executor.func.whitelist = ord,chr
12466+;hphp.executor.func.blacklist = system,shell_exec,popen,proc_open,exec,passthru
12467+
12468+; White-/blacklist for function calls during eval() execution
12469+;hphp.executor.eval.whitelist = ord,chr
12470+;hphp.executor.eval.blacklist = system,shell_exec,popen,proc_open,exec,passthru
12471+
12472+; White-/blacklist for URLs allowes in include filenames
12473+;
12474+; - When both options are not set all URLs are forbidden
12475+;
12476+; - When both options are set whitelist is taken and blacklist ignored
12477+;
12478+; - An entry in the lists is either a URL sheme like: http, https
12479+; or the beginning of an URL like: php://input
12480+;
12481+;hphp.executor.include.whitelist = cookietest
12482+;hphp.executor.include.blacklist = http, https, ftp, ftps, php://input, file
12483+
12484+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12485+; Hardening-Patch's REQUEST variable filters ;
12486+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12487+
12488+; Limits the number of REQUEST variables
12489+hphp.request.max_vars = 200
12490+
12491+; Limits the length of variable names (without indices)
12492+hphp.request.max_varname_length = 64
12493+
12494+; Limits the length of complete variable names (with indices)
12495+hphp.request.max_totalname_length = 256
12496+
12497+; Limits the length of array indices
12498+hphp.request.max_array_index_length = 64
12499+
12500+; Limits the depth of arrays
12501+hphp.request.max_array_depth = 100
12502+
12503+; Limits the length of variable values
12504+hphp.request.max_value_length = 65000
12505+
12506+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12507+; Hardening-Patch's COOKIE variable filters ;
12508+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12509+
12510+; Limits the number of COOKIE variables
12511+hphp.cookie.max_vars = 100
12512+
12513+; Limits the length of variable names (without indices)
12514+hphp.cookie.max_name_length = 64
12515+
12516+; Limits the length of complete variable names (with indices)
12517+hphp.cookie.max_totalname_length = 256
12518+
12519+; Limits the length of array indices
12520+hphp.cookie.max_array_index_length = 64
12521+
12522+; Limits the depth of arrays
12523+hphp.cookie.max_array_depth = 100
12524+
12525+; Limits the length of variable values
12526+hphp.cookie.max_value_length = 10000
12527+
12528+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12529+; Hardening-Patch's GET variable filters ;
12530+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12531+
12532+; Limits the number of COOKIE variables
12533+hphp.get.max_vars = 100
12534+
12535+; Limits the length of variable names (without indices)
12536+hphp.get.max_name_length = 64
12537+
12538+; Limits the length of complete variable names (with indices)
12539+hphp.get.max_totalname_length = 256
12540+
12541+; Limits the length of array indices
12542+hphp.get.max_array_index_length = 64
12543+
12544+; Limits the depth of arrays
12545+hphp.get.max_array_depth = 50
12546+
12547+; Limits the length of variable values
12548+hphp.get.max_value_length = 512
12549+
12550+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12551+; Hardening-Patch's POST variable filters ;
12552+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12553+
12554+; Limits the number of POST variables
12555+hphp.post.max_vars = 200
12556+
12557+; Limits the length of variable names (without indices)
12558+hphp.post.max_name_length = 64
12559+
12560+; Limits the length of complete variable names (with indices)
12561+hphp.post.max_totalname_length = 256
12562+
12563+; Limits the length of array indices
12564+hphp.post.max_array_index_length = 64
12565+
12566+; Limits the depth of arrays
12567+hphp.post.max_array_depth = 100
12568+
12569+; Limits the length of variable values
12570+hphp.post.max_value_length = 65000
12571+
12572+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12573+; Hardening-Patch's fileupload variable filters ;
12574+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12575+
12576+; Limits the number of uploadable files
12577+hphp.upload.max_uploads = 25
12578+
12579+; Filter out the upload of ELF executables
12580+hphp.upload.disallow_elf_files = On
12581+
12582+; External filterscript for upload verification
12583+;hphp.upload.verification_script = /home/hphp/verify_script
12584+
12585+
12586 ; Local Variables:
12587 ; tab-width: 4
12588 ; End:
12589diff -Nura php-4.4.0/README.input_filter hardening-patch-4.4.0-0.4.3/README.input_filter
12590--- php-4.4.0/README.input_filter 1970-01-01 01:00:00.000000000 +0100
12591+++ hardening-patch-4.4.0-0.4.3/README.input_filter 2005-09-11 23:31:08.000000000 +0200
12592@@ -0,0 +1,193 @@
12593+Input Filter Support ported from PHP 5
12594+--------------------------------------
12595+
12596+XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
12597+and can be quite difficult to prevent. Whenever you accept user data
12598+and somehow display this data back to users, you are likely vulnerable
12599+to XSS hacks.
12600+
12601+The Input Filter support in PHP 5 is aimed at providing the framework
12602+through which a company-wide or site-wide security policy can be
12603+enforced. It is implemented as a SAPI hook and is called from the
12604+treat_data and post handler functions. To implement your own security
12605+policy you will need to write a standard PHP extension.
12606+
12607+A simple implementation might look like the following. This stores the
12608+original raw user data and adds a my_get_raw() function while the normal
12609+$_POST, $_GET and $_COOKIE arrays are only populated with stripped
12610+data. In this simple example all I am doing is calling strip_tags() on
12611+the data. If register_globals is turned on, the default globals that
12612+are created will be stripped ($foo) while a $RAW_foo is created with the
12613+original user input.
12614+
12615+ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
12616+ zval *post_array;
12617+ zval *get_array;
12618+ zval *cookie_array;
12619+ZEND_END_MODULE_GLOBALS(my_input_filter)
12620+
12621+#ifdef ZTS
12622+#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
12623+#else
12624+#define IF_G(v) (my_input_filter_globals.v)
12625+#endif
12626+
12627+ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
12628+
12629+function_entry my_input_filter_functions[] = {
12630+ PHP_FE(my_get_raw, NULL)
12631+ {NULL, NULL, NULL}
12632+};
12633+
12634+zend_module_entry my_input_filter_module_entry = {
12635+ STANDARD_MODULE_HEADER,
12636+ "my_input_filter",
12637+ my_input_filter_functions,
12638+ PHP_MINIT(my_input_filter),
12639+ PHP_MSHUTDOWN(my_input_filter),
12640+ NULL,
12641+ PHP_RSHUTDOWN(my_input_filter),
12642+ PHP_MINFO(my_input_filter),
12643+ "0.1",
12644+ STANDARD_MODULE_PROPERTIES
12645+};
12646+
12647+PHP_MINIT_FUNCTION(my_input_filter)
12648+{
12649+ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
12650+
12651+ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
12652+ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
12653+ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
12654+
12655+ sapi_register_input_filter(my_sapi_input_filter);
12656+ return SUCCESS;
12657+}
12658+
12659+PHP_RSHUTDOWN_FUNCTION(my_input_filter)
12660+{
12661+ if(IF_G(get_array)) {
12662+ zval_ptr_dtor(&IF_G(get_array));
12663+ IF_G(get_array) = NULL;
12664+ }
12665+ if(IF_G(post_array)) {
12666+ zval_ptr_dtor(&IF_G(post_array));
12667+ IF_G(post_array) = NULL;
12668+ }
12669+ if(IF_G(cookie_array)) {
12670+ zval_ptr_dtor(&IF_G(cookie_array));
12671+ IF_G(cookie_array) = NULL;
12672+ }
12673+ return SUCCESS;
12674+}
12675+
12676+PHP_MINFO_FUNCTION(my_input_filter)
12677+{
12678+ php_info_print_table_start();
12679+ php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
12680+ php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $");
12681+ php_info_print_table_end();
12682+}
12683+
12684+/* The filter handler. If you return 1 from it, then PHP also registers the
12685+ * (modified) variable. Returning 0 prevents PHP from registering the variable;
12686+ * you can use this if your filter already registers the variable under a
12687+ * different name, or if you just don't want the variable registered at all. */
12688+SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
12689+{
12690+ zval new_var;
12691+ zval *array_ptr = NULL;
12692+ char *raw_var;
12693+ int var_len;
12694+
12695+ assert(*val != NULL);
12696+
12697+ switch(arg) {
12698+ case PARSE_GET:
12699+ if(!IF_G(get_array)) {
12700+ ALLOC_ZVAL(array_ptr);
12701+ array_init(array_ptr);
12702+ INIT_PZVAL(array_ptr);
12703+ }
12704+ IF_G(get_array) = array_ptr;
12705+ break;
12706+ case PARSE_POST:
12707+ if(!IF_G(post_array)) {
12708+ ALLOC_ZVAL(array_ptr);
12709+ array_init(array_ptr);
12710+ INIT_PZVAL(array_ptr);
12711+ }
12712+ IF_G(post_array) = array_ptr;
12713+ break;
12714+ case PARSE_COOKIE:
12715+ if(!IF_G(cookie_array)) {
12716+ ALLOC_ZVAL(array_ptr);
12717+ array_init(array_ptr);
12718+ INIT_PZVAL(array_ptr);
12719+ }
12720+ IF_G(cookie_array) = array_ptr;
12721+ break;
12722+ }
12723+ Z_STRLEN(new_var) = val_len;
12724+ Z_STRVAL(new_var) = estrndup(*val, val_len);
12725+ Z_TYPE(new_var) = IS_STRING;
12726+
12727+ var_len = strlen(var);
12728+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
12729+ strcpy(raw_var, "RAW_");
12730+ strlcat(raw_var,var,var_len+5);
12731+
12732+ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
12733+
12734+ php_strip_tags(*val, val_len, NULL, NULL, 0);
12735+
12736+ *new_val_len = strlen(*val);
12737+ return 1;
12738+}
12739+
12740+PHP_FUNCTION(my_get_raw)
12741+{
12742+ long arg;
12743+ char *var;
12744+ int var_len;
12745+ zval **tmp;
12746+ zval *array_ptr = NULL;
12747+ HashTable *hash_ptr;
12748+ char *raw_var;
12749+
12750+ if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
12751+ return;
12752+ }
12753+
12754+ switch(arg) {
12755+ case PARSE_GET:
12756+ array_ptr = IF_G(get_array);
12757+ break;
12758+ case PARSE_POST:
12759+ array_ptr = IF_G(post_array);
12760+ break;
12761+ case PARSE_COOKIE:
12762+ array_ptr = IF_G(post_array);
12763+ break;
12764+ }
12765+
12766+ if(!array_ptr) RETURN_FALSE;
12767+
12768+ /*
12769+ * I'm changing the variable name here because when running with register_globals on,
12770+ * the variable will end up in the global symbol table
12771+ */
12772+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
12773+ strcpy(raw_var, "RAW_");
12774+ strlcat(raw_var,var,var_len+5);
12775+ hash_ptr = HASH_OF(array_ptr);
12776+
12777+ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
12778+ *return_value = **tmp;
12779+ zval_copy_ctor(return_value);
12780+ } else {
12781+ RETVAL_FALSE;
12782+ }
12783+ efree(raw_var);
12784+}
12785+
12786diff -Nura php-4.4.0/sapi/apache/mod_php4.c hardening-patch-4.4.0-0.4.3/sapi/apache/mod_php4.c
12787--- php-4.4.0/sapi/apache/mod_php4.c 2005-05-19 18:14:46.000000000 +0200
12788+++ hardening-patch-4.4.0-0.4.3/sapi/apache/mod_php4.c 2005-09-11 23:31:08.000000000 +0200
12789@@ -452,7 +452,7 @@
12790 sapi_apache_get_fd,
12791 sapi_apache_force_http_10,
12792 sapi_apache_get_target_uid,
12793- sapi_apache_get_target_gid
12794+ sapi_apache_get_target_gid,
12795 };
12796 /* }}} */
12797
12798@@ -898,7 +898,11 @@
12799 {
12800 TSRMLS_FETCH();
12801 if (PG(expose_php)) {
12802+#if HARDENING_PATCH
12803+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
12804+#else
12805 ap_add_version_component("PHP/" PHP_VERSION);
12806+#endif
12807 }
12808 }
12809 #endif
12810diff -Nura php-4.4.0/sapi/apache2filter/sapi_apache2.c hardening-patch-4.4.0-0.4.3/sapi/apache2filter/sapi_apache2.c
12811--- php-4.4.0/sapi/apache2filter/sapi_apache2.c 2005-04-08 22:35:02.000000000 +0200
12812+++ hardening-patch-4.4.0-0.4.3/sapi/apache2filter/sapi_apache2.c 2005-09-11 23:31:08.000000000 +0200
12813@@ -556,7 +556,11 @@
12814 {
12815 TSRMLS_FETCH();
12816 if (PG(expose_php)) {
12817+#if HARDENING_PATCH
12818+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
12819+#else
12820 ap_add_version_component(p, "PHP/" PHP_VERSION);
12821+#endif
12822 }
12823 }
12824
12825diff -Nura php-4.4.0/sapi/apache2handler/sapi_apache2.c hardening-patch-4.4.0-0.4.3/sapi/apache2handler/sapi_apache2.c
12826--- php-4.4.0/sapi/apache2handler/sapi_apache2.c 2005-04-08 22:35:02.000000000 +0200
12827+++ hardening-patch-4.4.0-0.4.3/sapi/apache2handler/sapi_apache2.c 2005-09-11 23:31:08.000000000 +0200
12828@@ -340,7 +340,11 @@
12829 {
12830 TSRMLS_FETCH();
12831 if (PG(expose_php)) {
12832+#if HARDENING_PATCH
12833+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
12834+#else
12835 ap_add_version_component(p, "PHP/" PHP_VERSION);
12836+#endif
12837 }
12838 }
12839
12840diff -Nura php-4.4.0/sapi/cgi/cgi_main.c hardening-patch-4.4.0-0.4.3/sapi/cgi/cgi_main.c
12841--- php-4.4.0/sapi/cgi/cgi_main.c 2005-04-28 16:24:47.000000000 +0200
12842+++ hardening-patch-4.4.0-0.4.3/sapi/cgi/cgi_main.c 2005-09-11 23:31:08.000000000 +0200
12843@@ -1440,11 +1440,19 @@
12844 SG(headers_sent) = 1;
12845 SG(request_info).no_headers = 1;
12846 }
12847+#if HARDENING_PATCH
12848+#if ZEND_DEBUG
12849+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12850+#else
12851+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12852+#endif
12853+#else
12854 #if ZEND_DEBUG
12855 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12856 #else
12857 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12858 #endif
12859+#endif
12860 php_end_ob_buffers(1 TSRMLS_CC);
12861 exit(1);
12862 break;
12863diff -Nura php-4.4.0/sapi/cli/php_cli.c hardening-patch-4.4.0-0.4.3/sapi/cli/php_cli.c
12864--- php-4.4.0/sapi/cli/php_cli.c 2005-03-22 16:09:36.000000000 +0100
12865+++ hardening-patch-4.4.0-0.4.3/sapi/cli/php_cli.c 2005-09-11 23:31:08.000000000 +0200
12866@@ -652,11 +652,19 @@
12867 if (php_request_startup(TSRMLS_C)==FAILURE) {
12868 goto err;
12869 }
12870+#if HARDENING_PATCH
12871+#if ZEND_DEBUG
12872+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12873+#else
12874+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12875+#endif
12876+#else
12877 #if ZEND_DEBUG
12878 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12879 #else
12880 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
12881 #endif
12882+#endif
12883 php_end_ob_buffers(1 TSRMLS_CC);
12884 exit_status=1;
12885 goto out;
12886diff -Nura php-4.4.0/TSRM/TSRM.h hardening-patch-4.4.0-0.4.3/TSRM/TSRM.h
12887--- php-4.4.0/TSRM/TSRM.h 2005-02-11 04:34:04.000000000 +0100
12888+++ hardening-patch-4.4.0-0.4.3/TSRM/TSRM.h 2005-09-11 23:31:08.000000000 +0200
12889@@ -33,6 +33,13 @@
12890 # define TSRM_API
12891 #endif
12892
12893+#if HARDENING_PATCH
12894+# if HAVE_REALPATH
12895+# undef realpath
12896+# define realpath php_realpath
12897+# endif
12898+#endif
12899+
12900 /* Only compile multi-threading functions if we're in ZTS mode */
12901 #ifdef ZTS
12902
12903@@ -90,6 +97,7 @@
12904
12905 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
12906
12907+
12908 #ifdef __cplusplus
12909 extern "C" {
12910 #endif
12911diff -Nura php-4.4.0/TSRM/tsrm_virtual_cwd.c hardening-patch-4.4.0-0.4.3/TSRM/tsrm_virtual_cwd.c
12912--- php-4.4.0/TSRM/tsrm_virtual_cwd.c 2005-02-11 04:34:04.000000000 +0100
12913+++ hardening-patch-4.4.0-0.4.3/TSRM/tsrm_virtual_cwd.c 2005-09-11 23:31:08.000000000 +0200
12914@@ -192,6 +192,165 @@
12915 return p;
12916 }
12917
12918+#if HARDENING_PATCH
12919+CWD_API char *php_realpath(const char *path, char *resolved)
12920+{
12921+ struct stat sb;
12922+ char *p, *q, *s;
12923+ size_t left_len, resolved_len;
12924+ unsigned symlinks;
12925+ int serrno, slen;
12926+ int is_dir = 1;
12927+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
12928+
12929+ serrno = errno;
12930+ symlinks = 0;
12931+ if (path[0] == '/') {
12932+ resolved[0] = '/';
12933+ resolved[1] = '\0';
12934+ if (path[1] == '\0')
12935+ return (resolved);
12936+ resolved_len = 1;
12937+ left_len = strlcpy(left, path + 1, sizeof(left));
12938+ } else {
12939+ if (getcwd(resolved, PATH_MAX) == NULL) {
12940+ strlcpy(resolved, ".", PATH_MAX);
12941+ return (NULL);
12942+ }
12943+ resolved_len = strlen(resolved);
12944+ left_len = strlcpy(left, path, sizeof(left));
12945+ }
12946+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
12947+ errno = ENAMETOOLONG;
12948+ return (NULL);
12949+ }
12950+
12951+ /*
12952+ * Iterate over path components in `left'.
12953+ */
12954+ while (left_len != 0) {
12955+ /*
12956+ * Extract the next path component and adjust `left'
12957+ * and its length.
12958+ */
12959+ p = strchr(left, '/');
12960+ s = p ? p : left + left_len;
12961+ if (s - left >= sizeof(next_token)) {
12962+ errno = ENAMETOOLONG;
12963+ return (NULL);
12964+ }
12965+ memcpy(next_token, left, s - left);
12966+ next_token[s - left] = '\0';
12967+ left_len -= s - left;
12968+ if (p != NULL)
12969+ memmove(left, s + 1, left_len + 1);
12970+ if (resolved[resolved_len - 1] != '/') {
12971+ if (resolved_len + 1 >= PATH_MAX) {
12972+ errno = ENAMETOOLONG;
12973+ return (NULL);
12974+ }
12975+ resolved[resolved_len++] = '/';
12976+ resolved[resolved_len] = '\0';
12977+ }
12978+ if (next_token[0] == '\0')
12979+ continue;
12980+ else if (strcmp(next_token, ".") == 0)
12981+ continue;
12982+ else if (strcmp(next_token, "..") == 0) {
12983+ /*
12984+ * Strip the last path component except when we have
12985+ * single "/"
12986+ */
12987+ if (!is_dir) {
12988+ errno = ENOENT;
12989+ return (NULL);
12990+ }
12991+ if (resolved_len > 1) {
12992+ resolved[resolved_len - 1] = '\0';
12993+ q = strrchr(resolved, '/');
12994+ *q = '\0';
12995+ resolved_len = q - resolved;
12996+ }
12997+ continue;
12998+ }
12999+
13000+ /*
13001+ * Append the next path component and lstat() it. If
13002+ * lstat() fails we still can return successfully if
13003+ * there are no more path components left.
13004+ */
13005+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
13006+ if (resolved_len >= PATH_MAX) {
13007+ errno = ENAMETOOLONG;
13008+ return (NULL);
13009+ }
13010+ if (lstat(resolved, &sb) != 0) {
13011+ if (errno == ENOENT && p == NULL) {
13012+ errno = serrno;
13013+ return (resolved);
13014+ }
13015+ return (NULL);
13016+ }
13017+ if (S_ISLNK(sb.st_mode)) {
13018+ if (symlinks++ > MAXSYMLINKS) {
13019+ errno = ELOOP;
13020+ return (NULL);
13021+ }
13022+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
13023+ if (slen < 0)
13024+ return (NULL);
13025+ symlink[slen] = '\0';
13026+ if (symlink[0] == '/') {
13027+ resolved[1] = 0;
13028+ resolved_len = 1;
13029+ } else if (resolved_len > 1) {
13030+ /* Strip the last path component. */
13031+ resolved[resolved_len - 1] = '\0';
13032+ q = strrchr(resolved, '/');
13033+ *q = '\0';
13034+ resolved_len = q - resolved;
13035+ }
13036+
13037+ /*
13038+ * If there are any path components left, then
13039+ * append them to symlink. The result is placed
13040+ * in `left'.
13041+ */
13042+ if (p != NULL) {
13043+ if (symlink[slen - 1] != '/') {
13044+ if (slen + 1 >= sizeof(symlink)) {
13045+ errno = ENAMETOOLONG;
13046+ return (NULL);
13047+ }
13048+ symlink[slen] = '/';
13049+ symlink[slen + 1] = 0;
13050+ }
13051+ left_len = strlcat(symlink, left, sizeof(left));
13052+ if (left_len >= sizeof(left)) {
13053+ errno = ENAMETOOLONG;
13054+ return (NULL);
13055+ }
13056+ }
13057+ left_len = strlcpy(left, symlink, sizeof(left));
13058+ } else {
13059+ if (S_ISDIR(sb.st_mode)) {
13060+ is_dir = 1;
13061+ } else {
13062+ is_dir = 0;
13063+ }
13064+ }
13065+ }
13066+
13067+ /*
13068+ * Remove trailing slash except when the resolved pathname
13069+ * is a single "/".
13070+ */
13071+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
13072+ resolved[resolved_len - 1] = '\0';
13073+ return (resolved);
13074+}
13075+#endif
13076+
13077 CWD_API void virtual_cwd_startup(void)
13078 {
13079 char cwd[MAXPATHLEN];
13080@@ -314,8 +473,7 @@
13081 path = resolved_path;
13082 path_length = strlen(path);
13083 } else {
13084- /* disable for now
13085- return 1; */
13086+ return 1;
13087 }
13088 }
13089 } else { /* Concat current directory with relative path and then run realpath() on it */
13090@@ -341,9 +499,8 @@
13091 path = resolved_path;
13092 path_length = strlen(path);
13093 } else {
13094- /* disable for now
13095 free(tmp);
13096- return 1; */
13097+ return 1;
13098 }
13099 }
13100 free(tmp);
13101diff -Nura php-4.4.0/TSRM/tsrm_virtual_cwd.h hardening-patch-4.4.0-0.4.3/TSRM/tsrm_virtual_cwd.h
13102--- php-4.4.0/TSRM/tsrm_virtual_cwd.h 2005-02-11 04:34:04.000000000 +0100
13103+++ hardening-patch-4.4.0-0.4.3/TSRM/tsrm_virtual_cwd.h 2005-09-11 23:31:08.000000000 +0200
13104@@ -128,6 +128,22 @@
13105
13106 typedef int (*verify_path_func)(const cwd_state *);
13107
13108+#ifndef HAVE_STRLCPY
13109+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
13110+#undef strlcpy
13111+#define strlcpy php_strlcpy
13112+#endif
13113+
13114+#ifndef HAVE_STRLCAT
13115+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
13116+#undef strlcat
13117+#define strlcat php_strlcat
13118+#endif
13119+
13120+
13121+#if HARDENING_PATCH
13122+CWD_API char *php_realpath(const char *path, char *resolved);
13123+#endif
13124 CWD_API void virtual_cwd_startup(void);
13125 CWD_API void virtual_cwd_shutdown(void);
13126 CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
13127diff -Nura php-4.4.0/Zend/zend_alloc.c hardening-patch-4.4.0-0.4.3/Zend/zend_alloc.c
13128--- php-4.4.0/Zend/zend_alloc.c 2005-04-07 22:54:33.000000000 +0200
13129+++ hardening-patch-4.4.0-0.4.3/Zend/zend_alloc.c 2005-09-11 23:31:08.000000000 +0200
13130@@ -56,6 +56,11 @@
13131 # define END_MAGIC_SIZE 0
13132 #endif
13133
13134+#if HARDENING_PATCH_MM_PROTECT
13135+# define CANARY_SIZE sizeof(unsigned int)
13136+#else
13137+# define CANARY_SIZE 0
13138+#endif
13139
13140 # if MEMORY_LIMIT
13141 # if ZEND_DEBUG
13142@@ -95,9 +100,17 @@
13143 if (p==AG(head)) { \
13144 AG(head) = p->pNext; \
13145 } else { \
13146+ if (p != p->pLast->pNext) { \
13147+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
13148+ exit(1); \
13149+ } \
13150 p->pLast->pNext = p->pNext; \
13151 } \
13152 if (p->pNext) { \
13153+ if (p != p->pNext->pLast) { \
13154+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
13155+ exit(1); \
13156+ } \
13157 p->pNext->pLast = p->pLast; \
13158 }
13159
13160@@ -129,6 +142,12 @@
13161 DECLARE_CACHE_VARS();
13162 TSRMLS_FETCH();
13163
13164+#if HARDENING_PATCH_MM_PROTECT
13165+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
13166+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
13167+ exit(1);
13168+ }
13169+#endif
13170 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
13171
13172 if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) {
13173@@ -146,6 +165,10 @@
13174 AG(cache_stats)[CACHE_INDEX][1]++;
13175 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
13176 #endif
13177+#if HARDENING_PATCH_MM_PROTECT
13178+ p->canary = HG(canary_1);
13179+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
13180+#endif
13181 p->cached = 0;
13182 p->size = size;
13183 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
13184@@ -161,7 +184,7 @@
13185 AG(allocated_memory_peak) = AG(allocated_memory);
13186 }
13187 #endif
13188- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
13189+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
13190 }
13191
13192 HANDLE_BLOCK_INTERRUPTIONS();
13193@@ -191,7 +214,10 @@
13194 # endif
13195 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
13196 #endif
13197-
13198+#if HARDENING_PATCH_MM_PROTECT
13199+ p->canary = HG(canary_1);
13200+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
13201+#endif
13202 HANDLE_UNBLOCK_INTERRUPTIONS();
13203 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
13204 }
13205@@ -218,17 +244,36 @@
13206 return emalloc_rel(lval + offset);
13207 }
13208 }
13209-
13210+
13211+#if HARDENING_PATCH
13212+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
13213+#endif
13214 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset);
13215 return 0;
13216 }
13217
13218 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
13219 {
13220+#if HARDENING_PATCH_MM_PROTECT
13221+ unsigned int canary_2;
13222+#endif
13223 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
13224 DECLARE_CACHE_VARS();
13225 TSRMLS_FETCH();
13226
13227+#if HARDENING_PATCH_MM_PROTECT
13228+ if (p->canary != HG(canary_1)) goto efree_canary_mismatch;
13229+ memcpy(&canary_2, (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), CANARY_SIZE);
13230+ if (canary_2 != HG(canary_2)) {
13231+efree_canary_mismatch:
13232+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
13233+ exit(1);
13234+ }
13235+ /* to catch double efree()s */
13236+ memset((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), 0, CANARY_SIZE);
13237+ p->canary = 0;
13238+#endif
13239+
13240 #if defined(ZTS) && TSRM_DEBUG
13241 if (p->thread_id != tsrm_thread_id()) {
13242 tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring",
13243@@ -273,6 +318,9 @@
13244 size_t _size = nmemb * size;
13245
13246 if (nmemb && (_size/nmemb!=size)) {
13247+#if HARDENING_PATCH
13248+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
13249+#endif
13250 fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
13251 #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
13252 kill(getpid(), SIGSEGV);
13253@@ -292,6 +340,9 @@
13254
13255 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
13256 {
13257+#if HARDENING_PATCH_MM_PROTECT
13258+ unsigned int canary_2;
13259+#endif
13260 zend_mem_header *p;
13261 zend_mem_header *orig;
13262 DECLARE_CACHE_VARS();
13263@@ -303,6 +354,16 @@
13264
13265 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
13266
13267+#if HARDENING_PATCH_MM_PROTECT
13268+ if (p->canary != HG(canary_1)) goto erealloc_canary_mismatch;
13269+ memcpy(&canary_2, (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), CANARY_SIZE);
13270+ if (canary_2 != HG(canary_2)) {
13271+erealloc_canary_mismatch:
13272+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
13273+ exit(1);
13274+ }
13275+#endif
13276+
13277 #if defined(ZTS) && TSRM_DEBUG
13278 if (p->thread_id != tsrm_thread_id()) {
13279 void *new_p;
13280@@ -326,7 +387,7 @@
13281 }
13282 #endif
13283 REMOVE_POINTER_FROM_LIST(p);
13284- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
13285+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
13286 if (!p) {
13287 if (!allow_failure) {
13288 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
13289@@ -348,6 +409,9 @@
13290 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
13291 #endif
13292
13293+#if HARDENING_PATCH_MM_PROTECT
13294+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
13295+#endif
13296 p->size = size;
13297
13298 HANDLE_UNBLOCK_INTERRUPTIONS();
13299@@ -422,6 +486,10 @@
13300 {
13301 AG(head) = NULL;
13302
13303+#if HARDENING_PATCH_MM_PROTECT
13304+ HG(canary_1) = zend_canary();
13305+ HG(canary_2) = zend_canary();
13306+#endif
13307 #if MEMORY_LIMIT
13308 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
13309 AG(allocated_memory) = 0;
13310diff -Nura php-4.4.0/Zend/zend_alloc.h hardening-patch-4.4.0-0.4.3/Zend/zend_alloc.h
13311--- php-4.4.0/Zend/zend_alloc.h 2005-06-07 15:37:33.000000000 +0200
13312+++ hardening-patch-4.4.0-0.4.3/Zend/zend_alloc.h 2005-09-11 23:31:08.000000000 +0200
13313@@ -32,6 +32,9 @@
13314 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
13315
13316 typedef struct _zend_mem_header {
13317+#if HARDENING_PATCH_MM_PROTECT
13318+ unsigned int canary;
13319+#endif
13320 #if ZEND_DEBUG
13321 long magic;
13322 char *filename;
13323diff -Nura php-4.4.0/Zend/zend_builtin_functions.c hardening-patch-4.4.0-0.4.3/Zend/zend_builtin_functions.c
13324--- php-4.4.0/Zend/zend_builtin_functions.c 2005-06-23 14:20:47.000000000 +0200
13325+++ hardening-patch-4.4.0-0.4.3/Zend/zend_builtin_functions.c 2005-09-11 23:31:08.000000000 +0200
13326@@ -49,6 +49,9 @@
13327 static ZEND_FUNCTION(crash);
13328 #endif
13329 #endif
13330+#if HARDENING_PATCH_MM_PROTECT_DEBUG
13331+static ZEND_FUNCTION(heap_overflow);
13332+#endif
13333 static ZEND_FUNCTION(get_included_files);
13334 static ZEND_FUNCTION(is_subclass_of);
13335 static ZEND_FUNCTION(is_a);
13336@@ -101,6 +104,9 @@
13337 ZEND_FE(crash, NULL)
13338 #endif
13339 #endif
13340+#if HARDENING_PATCH_MM_PROTECT_DEBUG
13341+ ZEND_FE(heap_overflow, NULL)
13342+#endif
13343 ZEND_FE(get_included_files, NULL)
13344 ZEND_FALIAS(get_required_files, get_included_files, NULL)
13345 ZEND_FE(is_subclass_of, NULL)
13346@@ -805,6 +811,19 @@
13347
13348 #endif /* ZEND_DEBUG */
13349
13350+
13351+#if HARDENING_PATCH_MM_PROTECT_DEBUG
13352+ZEND_FUNCTION(heap_overflow)
13353+{
13354+ char *nowhere = emalloc(10);
13355+
13356+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
13357+
13358+ efree(nowhere);
13359+}
13360+#endif
13361+
13362+
13363 /* {{{ proto array get_included_files(void)
13364 Returns an array with the file names that were include_once()'d */
13365 ZEND_FUNCTION(get_included_files)
13366diff -Nura php-4.4.0/Zend/zend.c hardening-patch-4.4.0-0.4.3/Zend/zend.c
13367--- php-4.4.0/Zend/zend.c 2005-06-09 12:14:25.000000000 +0200
13368+++ hardening-patch-4.4.0-0.4.3/Zend/zend.c 2005-09-12 18:15:08.000000000 +0200
13369@@ -53,6 +53,12 @@
13370 ZEND_API void (*zend_unblock_interruptions)(void);
13371 ZEND_API void (*zend_ticks_function)(int ticks);
13372 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
13373+#if HARDENING_PATCH
13374+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
13375+#endif
13376+#if HARDENING_PATCH_INC_PROTECT
13377+ZEND_API int (*zend_is_valid_include)(zval *z);
13378+#endif
13379
13380 void (*zend_on_timeout)(int seconds TSRMLS_DC);
13381
13382@@ -70,9 +76,391 @@
13383 return SUCCESS;
13384 }
13385
13386+#if HARDENING_PATCH
13387+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
13388+{
13389+ if (!new_value) {
13390+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY | S_INTERNAL;
13391+ } else {
13392+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY | S_INTERNAL;
13393+ }
13394+ return SUCCESS;
13395+}
13396+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
13397+{
13398+ if (!new_value) {
13399+ EG(hphp_log_syslog_facility) = LOG_USER;
13400+ } else {
13401+ EG(hphp_log_syslog_facility) = atoi(new_value);
13402+ }
13403+ return SUCCESS;
13404+}
13405+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
13406+{
13407+ if (!new_value) {
13408+ EG(hphp_log_syslog_priority) = LOG_ALERT;
13409+ } else {
13410+ EG(hphp_log_syslog_priority) = atoi(new_value);
13411+ }
13412+ return SUCCESS;
13413+}
13414+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
13415+{
13416+ if (!new_value) {
13417+ EG(hphp_log_sapi) = S_ALL & ~S_SQL | S_INTERNAL;
13418+ } else {
13419+ EG(hphp_log_sapi) = atoi(new_value) | S_INTERNAL;
13420+ }
13421+ return SUCCESS;
13422+}
13423+static ZEND_INI_MH(OnUpdateHPHP_log_script)
13424+{
13425+ if (!new_value) {
13426+ EG(hphp_log_script) = S_ALL & (~S_MEMORY) & (~S_INTERNAL);
13427+ } else {
13428+ EG(hphp_log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
13429+ }
13430+ return SUCCESS;
13431+}
13432+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
13433+{
13434+ if (!new_value) {
13435+ EG(hphp_log_scriptname) = NULL;
13436+ } else {
13437+ if (EG(hphp_log_scriptname)) {
13438+ pefree(EG(hphp_log_scriptname),1);
13439+ }
13440+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
13441+ }
13442+ return SUCCESS;
13443+}
13444+
13445+static ZEND_INI_MH(OnUpdateHPHP_include_whitelist)
13446+{
13447+ char *s = NULL, *e, *val;
13448+ unsigned long dummy = 1;
13449+
13450+ if (!new_value) {
13451+include_whitelist_destroy:
13452+ if (HG(include_whitelist)) {
13453+ zend_hash_destroy(HG(include_whitelist));
13454+ efree(HG(include_whitelist));
13455+ }
13456+ HG(include_whitelist) = NULL;
13457+ return SUCCESS;
13458+ }
13459+ if (!(*new_value)) {
13460+ goto include_whitelist_destroy;
13461+ }
13462+
13463+ ALLOC_HASHTABLE(HG(include_whitelist));
13464+ zend_hash_init(HG(include_whitelist), 5, NULL, NULL, 0);
13465+
13466+ val = zend_str_tolower_dup(new_value, strlen(new_value));
13467+ e = val;
13468+
13469+ while (*e) {
13470+ switch (*e) {
13471+ case ' ':
13472+ case ',':
13473+ if (s) {
13474+ *e = '\0';
13475+ zend_hash_add(HG(include_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13476+ s = NULL;
13477+ }
13478+ break;
13479+ default:
13480+ if (!s) {
13481+ s = e;
13482+ }
13483+ break;
13484+ }
13485+ e++;
13486+ }
13487+ if (s) {
13488+ zend_hash_add(HG(include_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13489+ }
13490+ efree(val);
13491+
13492+ return SUCCESS;
13493+}
13494+
13495+static ZEND_INI_MH(OnUpdateHPHP_include_blacklist)
13496+{
13497+ char *s = NULL, *e, *val;
13498+ unsigned long dummy = 1;
13499+
13500+ if (!new_value) {
13501+include_blacklist_destroy:
13502+ if (HG(include_blacklist)) {
13503+ zend_hash_destroy(HG(include_blacklist));
13504+ efree(HG(include_blacklist));
13505+ }
13506+ HG(include_blacklist) = NULL;
13507+ return SUCCESS;
13508+ }
13509+ if (!(*new_value)) {
13510+ goto include_blacklist_destroy;
13511+ }
13512+
13513+ ALLOC_HASHTABLE(HG(include_blacklist));
13514+ zend_hash_init(HG(include_blacklist), 5, NULL, NULL, 0);
13515+
13516+ val = zend_str_tolower_dup(new_value, strlen(new_value));
13517+ e = val;
13518+
13519+ while (*e) {
13520+ switch (*e) {
13521+ case ' ':
13522+ case ',':
13523+ if (s) {
13524+ *e = '\0';
13525+ zend_hash_add(HG(include_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13526+ s = NULL;
13527+ }
13528+ break;
13529+ default:
13530+ if (!s) {
13531+ s = e;
13532+ }
13533+ break;
13534+ }
13535+ e++;
13536+ }
13537+ if (s) {
13538+ zend_hash_add(HG(include_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13539+ }
13540+ efree(val);
13541+
13542+ return SUCCESS;
13543+}
13544+
13545+static ZEND_INI_MH(OnUpdateHPHP_eval_whitelist)
13546+{
13547+ char *s = NULL, *e, *val;
13548+ unsigned long dummy = 1;
13549+
13550+ if (!new_value) {
13551+eval_whitelist_destroy:
13552+ if (HG(eval_whitelist)) {
13553+ zend_hash_destroy(HG(eval_whitelist));
13554+ efree(HG(eval_whitelist));
13555+ }
13556+ HG(eval_whitelist) = NULL;
13557+ return SUCCESS;
13558+ }
13559+ if (!(*new_value)) {
13560+ goto eval_whitelist_destroy;
13561+ }
13562+
13563+ ALLOC_HASHTABLE(HG(eval_whitelist));
13564+ zend_hash_init(HG(eval_whitelist), 5, NULL, NULL, 0);
13565+
13566+ val = zend_str_tolower_dup(new_value, strlen(new_value));
13567+ e = val;
13568+
13569+ while (*e) {
13570+ switch (*e) {
13571+ case ' ':
13572+ case ',':
13573+ if (s) {
13574+ *e = '\0';
13575+ zend_hash_add(HG(eval_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13576+ s = NULL;
13577+ }
13578+ break;
13579+ default:
13580+ if (!s) {
13581+ s = e;
13582+ }
13583+ break;
13584+ }
13585+ e++;
13586+ }
13587+ if (s) {
13588+ zend_hash_add(HG(eval_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13589+ }
13590+ efree(val);
13591+
13592+ return SUCCESS;
13593+}
13594+
13595+static ZEND_INI_MH(OnUpdateHPHP_eval_blacklist)
13596+{
13597+ char *s = NULL, *e, *val;
13598+ unsigned long dummy = 1;
13599+
13600+ if (!new_value) {
13601+eval_blacklist_destroy:
13602+ if (HG(eval_blacklist)) {
13603+ zend_hash_destroy(HG(eval_blacklist));
13604+ efree(HG(eval_blacklist));
13605+ }
13606+ HG(eval_blacklist) = NULL;
13607+ return SUCCESS;
13608+ }
13609+ if (!(*new_value)) {
13610+ goto eval_blacklist_destroy;
13611+ }
13612+
13613+ ALLOC_HASHTABLE(HG(eval_blacklist));
13614+ zend_hash_init(HG(eval_blacklist), 5, NULL, NULL, 0);
13615+
13616+ val = zend_str_tolower_dup(new_value, strlen(new_value));
13617+ e = val;
13618+
13619+ while (*e) {
13620+ switch (*e) {
13621+ case ' ':
13622+ case ',':
13623+ if (s) {
13624+ *e = '\0';
13625+ zend_hash_add(HG(eval_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13626+ s = NULL;
13627+ }
13628+ break;
13629+ default:
13630+ if (!s) {
13631+ s = e;
13632+ }
13633+ break;
13634+ }
13635+ e++;
13636+ }
13637+ if (s) {
13638+ zend_hash_add(HG(eval_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13639+ }
13640+ efree(val);
13641+
13642+
13643+ return SUCCESS;
13644+}
13645+
13646+static ZEND_INI_MH(OnUpdateHPHP_func_whitelist)
13647+{
13648+ char *s = NULL, *e, *val;
13649+ unsigned long dummy = 1;
13650+
13651+ if (!new_value) {
13652+func_whitelist_destroy:
13653+ if (HG(func_whitelist)) {
13654+ zend_hash_destroy(HG(func_whitelist));
13655+ efree(HG(func_whitelist));
13656+ }
13657+ HG(func_whitelist) = NULL;
13658+ return SUCCESS;
13659+ }
13660+ if (!(*new_value)) {
13661+ goto func_whitelist_destroy;
13662+ }
13663+
13664+ ALLOC_HASHTABLE(HG(func_whitelist));
13665+ zend_hash_init(HG(func_whitelist), 5, NULL, NULL, 0);
13666+
13667+ val = zend_str_tolower_dup(new_value, strlen(new_value));
13668+ e = val;
13669+
13670+ while (*e) {
13671+ switch (*e) {
13672+ case ' ':
13673+ case ',':
13674+ if (s) {
13675+ *e = '\0';
13676+ zend_hash_add(HG(func_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13677+ s = NULL;
13678+ }
13679+ break;
13680+ default:
13681+ if (!s) {
13682+ s = e;
13683+ }
13684+ break;
13685+ }
13686+ e++;
13687+ }
13688+ if (s) {
13689+ zend_hash_add(HG(func_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13690+ }
13691+ efree(val);
13692+
13693+ return SUCCESS;
13694+}
13695+
13696+static ZEND_INI_MH(OnUpdateHPHP_func_blacklist)
13697+{
13698+ char *s = NULL, *e, *val;
13699+ unsigned long dummy = 1;
13700+
13701+ if (!new_value) {
13702+func_blacklist_destroy:
13703+ if (HG(func_blacklist)) {
13704+ zend_hash_destroy(HG(func_blacklist));
13705+ efree(HG(func_blacklist));
13706+ }
13707+ HG(func_blacklist) = NULL;
13708+ return SUCCESS;
13709+ }
13710+ if (!(*new_value)) {
13711+ goto func_blacklist_destroy;
13712+ }
13713+
13714+ ALLOC_HASHTABLE(HG(func_blacklist));
13715+ zend_hash_init(HG(func_blacklist), 5, NULL, NULL, 0);
13716+
13717+ val = zend_str_tolower_dup(new_value, strlen(new_value));
13718+ e = val;
13719+
13720+ while (*e) {
13721+ switch (*e) {
13722+ case ' ':
13723+ case ',':
13724+ if (s) {
13725+ *e = '\0';
13726+ zend_hash_add(HG(func_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13727+ s = NULL;
13728+ }
13729+ break;
13730+ default:
13731+ if (!s) {
13732+ s = e;
13733+ }
13734+ break;
13735+ }
13736+ e++;
13737+ }
13738+ if (s) {
13739+ zend_hash_add(HG(func_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
13740+ }
13741+ efree(val);
13742+
13743+
13744+ return SUCCESS;
13745+}
13746+
13747+#endif
13748
13749 ZEND_INI_BEGIN()
13750 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
13751+#if HARDENING_PATCH
13752+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
13753+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
13754+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
13755+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
13756+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
13757+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
13758+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
13759+
13760+ ZEND_INI_ENTRY("hphp.executor.include.whitelist", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_include_whitelist)
13761+ ZEND_INI_ENTRY("hphp.executor.include.blacklist", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_include_blacklist)
13762+ ZEND_INI_ENTRY("hphp.executor.eval.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_eval_whitelist)
13763+ ZEND_INI_ENTRY("hphp.executor.eval.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_eval_blacklist)
13764+ ZEND_INI_ENTRY("hphp.executor.func.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_func_whitelist)
13765+ ZEND_INI_ENTRY("hphp.executor.func.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_func_blacklist)
13766+
13767+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
13768+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
13769+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
13770+#endif
13771 ZEND_INI_END()
13772
13773
13774@@ -354,6 +742,7 @@
13775 zend_init_rsrc_plist(TSRMLS_C);
13776 EG(lambda_count)=0;
13777 EG(user_error_handler) = NULL;
13778+ EG(in_code_type) = 0;
13779 EG(in_execution) = 0;
13780 EG(current_execute_data) = NULL;
13781 }
13782@@ -420,6 +809,14 @@
13783 extern zend_scanner_globals language_scanner_globals;
13784 #endif
13785
13786+ /* Set up Hardening-Patch utility functions first */
13787+#if HARDENING_PATCH
13788+ zend_security_log = utility_functions->security_log_function;
13789+#endif
13790+#if HARDENING_PATCH_INC_PROTECT
13791+ zend_is_valid_include = utility_functions->is_valid_include;
13792+#endif
13793+
13794 #ifdef ZTS
13795 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
13796 #else
13797@@ -623,6 +1020,7 @@
13798 }
13799 CG(unclean_shutdown) = 1;
13800 CG(in_compilation) = EG(in_execution) = 0;
13801+ EG(in_code_type) = 0;
13802 EG(current_execute_data) = NULL;
13803 longjmp(EG(bailout), FAILURE);
13804 }
13805diff -Nura php-4.4.0/Zend/zend_canary.c hardening-patch-4.4.0-0.4.3/Zend/zend_canary.c
13806--- php-4.4.0/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
13807+++ hardening-patch-4.4.0-0.4.3/Zend/zend_canary.c 2005-09-11 23:31:08.000000000 +0200
13808@@ -0,0 +1,58 @@
13809+/*
13810+ +----------------------------------------------------------------------+
13811+ | Hardening-Patch for PHP |
13812+ +----------------------------------------------------------------------+
13813+ | Copyright (c) 2004-2005 Stefan Esser |
13814+ +----------------------------------------------------------------------+
13815+ | This source file is subject to version 2.02 of the PHP license, |
13816+ | that is bundled with this package in the file LICENSE, and is |
13817+ | available at through the world-wide-web at |
13818+ | http://www.php.net/license/2_02.txt. |
13819+ | If you did not receive a copy of the PHP license and are unable to |
13820+ | obtain it through the world-wide-web, please send a note to |
13821+ | license@php.net so we can mail you a copy immediately. |
13822+ +----------------------------------------------------------------------+
13823+ | Author: Stefan Esser <sesser@hardened-php.net> |
13824+ +----------------------------------------------------------------------+
13825+ */
13826+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
13827+
13828+#include "zend.h"
13829+
13830+#include <stdio.h>
13831+#include <stdlib.h>
13832+
13833+
13834+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
13835+
13836+/* will be replaced later with more compatible method */
13837+ZEND_API unsigned int zend_canary()
13838+{
13839+ time_t t;
13840+ unsigned int canary;
13841+ int fd;
13842+
13843+ fd = open("/dev/urandom", 0);
13844+ if (fd != -1) {
13845+ int r = read(fd, &canary, sizeof(canary));
13846+ close(fd);
13847+ if (r == sizeof(canary)) {
13848+ return (canary);
13849+ }
13850+ }
13851+ /* not good but we never want to do this */
13852+ time(&t);
13853+ canary = *(unsigned int *)&t + getpid() << 16;
13854+ return (canary);
13855+}
13856+#endif
13857+
13858+
13859+/*
13860+ * Local variables:
13861+ * tab-width: 4
13862+ * c-basic-offset: 4
13863+ * End:
13864+ * vim600: sw=4 ts=4 fdm=marker
13865+ * vim<600: sw=4 ts=4
13866+ */
13867diff -Nura php-4.4.0/Zend/zend_compile.c hardening-patch-4.4.0-0.4.3/Zend/zend_compile.c
13868--- php-4.4.0/Zend/zend_compile.c 2005-06-24 13:48:30.000000000 +0200
13869+++ hardening-patch-4.4.0-0.4.3/Zend/zend_compile.c 2005-09-11 23:31:08.000000000 +0200
13870@@ -763,6 +763,13 @@
13871 op_array.function_name = name;
13872 op_array.arg_types = NULL;
13873 op_array.return_reference = return_reference;
13874+#if HARDENING_PATCH
13875+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
13876+ op_array.created_by_eval = 1;
13877+ } else {
13878+ op_array.created_by_eval = 0;
13879+ }
13880+#endif
13881
13882 if (is_method) {
13883 if (zend_hash_add(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
13884diff -Nura php-4.4.0/Zend/zend_compile.h hardening-patch-4.4.0-0.4.3/Zend/zend_compile.h
13885--- php-4.4.0/Zend/zend_compile.h 2005-06-06 11:30:09.000000000 +0200
13886+++ hardening-patch-4.4.0-0.4.3/Zend/zend_compile.h 2005-09-11 23:31:08.000000000 +0200
13887@@ -106,6 +106,9 @@
13888 char *filename;
13889
13890 void *reserved[ZEND_MAX_RESERVED_RESOURCES];
13891+#if HARDENING_PATCH
13892+ zend_bool created_by_eval;
13893+#endif
13894 };
13895
13896
13897@@ -549,6 +552,7 @@
13898 #define ZEND_USER_FUNCTION 2
13899 #define ZEND_OVERLOADED_FUNCTION 3
13900 #define ZEND_EVAL_CODE 4
13901+#define ZEND_SANDBOX_CODE 6
13902
13903 #define ZEND_INTERNAL_CLASS 1
13904 #define ZEND_USER_CLASS 2
13905diff -Nura php-4.4.0/Zend/zend_constants.c hardening-patch-4.4.0-0.4.3/Zend/zend_constants.c
13906--- php-4.4.0/Zend/zend_constants.c 2004-07-13 21:29:45.000000000 +0200
13907+++ hardening-patch-4.4.0-0.4.3/Zend/zend_constants.c 2005-09-11 23:31:08.000000000 +0200
13908@@ -111,6 +111,73 @@
13909 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
13910
13911 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
13912+#if HARDENING_PATCH
13913+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
13914+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
13915+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS);
13916+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
13917+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
13918+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
13919+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
13920+ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS);
13921+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
13922+
13923+ /* error levels */
13924+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
13925+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
13926+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
13927+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
13928+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
13929+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
13930+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
13931+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
13932+ /* facility: type of program logging the message */
13933+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
13934+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
13935+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
13936+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
13937+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
13938+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
13939+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
13940+#ifdef LOG_NEWS
13941+ /* No LOG_NEWS on HP-UX */
13942+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
13943+#endif
13944+#ifdef LOG_UUCP
13945+ /* No LOG_UUCP on HP-UX */
13946+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
13947+#endif
13948+#ifdef LOG_CRON
13949+ /* apparently some systems don't have this one */
13950+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
13951+#endif
13952+#ifdef LOG_AUTHPRIV
13953+ /* AIX doesn't have LOG_AUTHPRIV */
13954+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
13955+#endif
13956+#if !defined(PHP_WIN32) && !defined(NETWARE)
13957+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
13958+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
13959+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
13960+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
13961+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
13962+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
13963+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
13964+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
13965+#endif
13966+ /* options */
13967+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
13968+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
13969+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
13970+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
13971+#ifdef LOG_NOWAIT
13972+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
13973+#endif
13974+#ifdef LOG_PERROR
13975+ /* AIX doesn't have LOG_PERROR */
13976+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
13977+#endif
13978+#endif
13979
13980 /* true/false constants */
13981 {
13982diff -Nura php-4.4.0/Zend/zend_errors.h hardening-patch-4.4.0-0.4.3/Zend/zend_errors.h
13983--- php-4.4.0/Zend/zend_errors.h 2002-12-31 17:22:59.000000000 +0100
13984+++ hardening-patch-4.4.0-0.4.3/Zend/zend_errors.h 2005-09-11 23:31:08.000000000 +0200
13985@@ -36,5 +36,17 @@
13986 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
13987 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
13988
13989+#if HARDENING_PATCH
13990+#define S_MEMORY (1<<0L)
13991+#define S_VARS (1<<1L)
13992+#define S_FILES (1<<2L)
13993+#define S_INCLUDE (1<<3L)
13994+#define S_SQL (1<<4L)
13995+#define S_EXECUTOR (1<<5L)
13996+#define S_MISC (1<<30L)
13997+#define S_INTERNAL (1<<29L)
13998+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MISC | S_SQL | S_EXECUTOR)
13999+#endif
14000+
14001 #endif /* ZEND_ERRORS_H */
14002
14003diff -Nura php-4.4.0/Zend/zend_execute_API.c hardening-patch-4.4.0-0.4.3/Zend/zend_execute_API.c
14004--- php-4.4.0/Zend/zend_execute_API.c 2005-05-18 19:58:09.000000000 +0200
14005+++ hardening-patch-4.4.0-0.4.3/Zend/zend_execute_API.c 2005-09-11 23:31:08.000000000 +0200
14006@@ -142,6 +142,7 @@
14007 EG(class_table) = CG(class_table);
14008
14009 EG(in_execution) = 0;
14010+ EG(in_code_type) = 0;
14011
14012 zend_ptr_stack_init(&EG(argument_stack));
14013
14014@@ -431,12 +432,14 @@
14015 zend_execute_data execute_data;
14016
14017 /* Initialize execute_data */
14018+ memset(&execute_data, 0, sizeof(execute_data));
14019 EX(fbc) = NULL;
14020 EX(object).ptr = NULL;
14021 EX(ce) = NULL;
14022 EX(Ts) = NULL;
14023 EX(op_array) = NULL;
14024 EX(opline) = NULL;
14025+ EX(execute_depth) = 0;
14026
14027 *retval_ptr_ptr = NULL;
14028
14029@@ -494,6 +497,39 @@
14030 zval_dtor(&function_name_copy);
14031 return FAILURE;
14032 }
14033+#if HARDENING_PATCH
14034+ if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
14035+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
14036+ if (HG(eval_whitelist) != NULL) {
14037+ if (!zend_hash_exists(HG(eval_whitelist), function_name_copy.value.str.val, function_name_copy.value.str.len+1)) {
14038+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", function_name_copy.value.str.val);
14039+ zval_dtor(&function_name_copy);
14040+ zend_bailout();
14041+ }
14042+ } else if (HG(eval_blacklist) != NULL) {
14043+ if (zend_hash_exists(HG(eval_blacklist), function_name_copy.value.str.val, function_name_copy.value.str.len+1)) {
14044+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", function_name_copy.value.str.val);
14045+ zval_dtor(&function_name_copy);
14046+ zend_bailout();
14047+ }
14048+ }
14049+ }
14050+
14051+ if (HG(func_whitelist) != NULL) {
14052+ if (!zend_hash_exists(HG(func_whitelist), function_name_copy.value.str.val, function_name_copy.value.str.len+1)) {
14053+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", function_name_copy.value.str.val);
14054+ zval_dtor(&function_name_copy);
14055+ zend_bailout();
14056+ }
14057+ } else if (HG(func_blacklist) != NULL) {
14058+ if (zend_hash_exists(HG(func_blacklist), function_name_copy.value.str.val, function_name_copy.value.str.len+1)) {
14059+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", function_name_copy.value.str.val);
14060+ zval_dtor(&function_name_copy);
14061+ zend_bailout();
14062+ }
14063+ }
14064+ }
14065+#endif
14066 zval_dtor(&function_name_copy);
14067
14068 for (i=0; i<param_count; i++) {
14069@@ -606,8 +642,7 @@
14070 return SUCCESS;
14071 }
14072
14073-
14074-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
14075+ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
14076 {
14077 zval pv;
14078 zend_op_array *new_op_array;
14079@@ -640,6 +675,7 @@
14080 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
14081 zend_op **original_opline_ptr = EG(opline_ptr);
14082
14083+ new_op_array->type = type;
14084 EG(return_value_ptr_ptr) = &local_retval_ptr;
14085 EG(active_op_array) = new_op_array;
14086 EG(no_extensions)=1;
14087@@ -673,6 +709,10 @@
14088 return retval;
14089 }
14090
14091+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
14092+{
14093+ return (zend_eval_string_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
14094+}
14095
14096 void execute_new_code(TSRMLS_D)
14097 {
14098diff -Nura php-4.4.0/Zend/zend_execute.c hardening-patch-4.4.0-0.4.3/Zend/zend_execute.c
14099--- php-4.4.0/Zend/zend_execute.c 2005-06-27 08:15:48.000000000 +0200
14100+++ hardening-patch-4.4.0-0.4.3/Zend/zend_execute.c 2005-09-11 23:31:08.000000000 +0200
14101@@ -1042,6 +1042,7 @@
14102 zend_execute_data execute_data;
14103
14104 /* Initialize execute_data */
14105+ memset(&execute_data, 0, sizeof(execute_data));
14106 EX(fbc) = NULL;
14107 EX(ce) = NULL;
14108 EX(object).ptr = NULL;
14109@@ -1053,9 +1054,21 @@
14110 }
14111 EX(prev_execute_data) = EG(current_execute_data);
14112 EX(original_in_execution)=EG(in_execution);
14113+ EX(original_in_code_type)=EG(in_code_type);
14114
14115 EG(current_execute_data) = &execute_data;
14116
14117+#if HARDENING_PATCH
14118+ EX(execute_depth) = 0;
14119+
14120+ if ((op_array->type == ZEND_EVAL_CODE || op_array->created_by_eval) && EG(in_code_type) != ZEND_SANDBOX_CODE) {
14121+ EG(in_code_type) = ZEND_EVAL_CODE;
14122+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
14123+ EG(in_code_type) = ZEND_SANDBOX_CODE;
14124+ op_array->type = ZEND_EVAL_CODE;
14125+ }
14126+#endif
14127+
14128 EG(in_execution) = 1;
14129 if (op_array->start_op) {
14130 EX(opline) = op_array->start_op;
14131@@ -1087,6 +1100,19 @@
14132 }
14133 }
14134
14135+#if HARDENING_PATCH
14136+ if (EX(prev_execute_data) == NULL) {
14137+ EX(execute_depth) = 0;
14138+ } else {
14139+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
14140+ }
14141+
14142+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
14143+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
14144+ zend_bailout();
14145+ }
14146+#endif
14147+
14148 while (1) {
14149 #ifdef ZEND_WIN32
14150 if (EG(timed_out)) {
14151@@ -1631,6 +1657,36 @@
14152 if (zend_hash_find(active_function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function)==FAILURE) {
14153 zend_error(E_ERROR, "Call to undefined function: %s()", function_name->value.str.val);
14154 }
14155+#if HARDENING_PATCH
14156+ if (active_function_table == EG(function_table)) {
14157+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
14158+ if (HG(eval_whitelist) != NULL) {
14159+ if (!zend_hash_exists(HG(eval_whitelist), function_name->value.str.val, function_name->value.str.len+1)) {
14160+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", function_name->value.str.val);
14161+ zend_bailout();
14162+ }
14163+ } else if (HG(eval_blacklist) != NULL) {
14164+ if (zend_hash_exists(HG(eval_blacklist), function_name->value.str.val, function_name->value.str.len+1)) {
14165+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", function_name->value.str.val);
14166+ zend_bailout();
14167+ }
14168+ }
14169+ }
14170+
14171+ if (HG(func_whitelist) != NULL) {
14172+ if (!zend_hash_exists(HG(func_whitelist), function_name->value.str.val, function_name->value.str.len+1)) {
14173+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", function_name->value.str.val);
14174+ zend_bailout();
14175+ }
14176+ } else if (HG(func_blacklist) != NULL) {
14177+ if (zend_hash_exists(HG(func_blacklist), function_name->value.str.val, function_name->value.str.len+1)) {
14178+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", function_name->value.str.val);
14179+ zend_bailout();
14180+ }
14181+ }
14182+ }
14183+#endif
14184+
14185 zval_dtor(&tmp);
14186 EX(fbc) = function;
14187 overloaded_function_call_cont:
14188@@ -1646,6 +1702,35 @@
14189 if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
14190 zend_error(E_ERROR, "Unknown function: %s()", fname->value.str.val);
14191 }
14192+#if HARDENING_PATCH
14193+ if (EX(function_state).function->type==ZEND_INTERNAL_FUNCTION) {
14194+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
14195+ if (HG(eval_whitelist) != NULL) {
14196+ if (!zend_hash_exists(HG(eval_whitelist), fname->value.str.val, fname->value.str.len+1)) {
14197+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", fname->value.str.val);
14198+ zend_bailout();
14199+ }
14200+ } else if (HG(eval_blacklist) != NULL) {
14201+ if (zend_hash_exists(HG(eval_blacklist), fname->value.str.val, fname->value.str.len+1)) {
14202+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", fname->value.str.val);
14203+ zend_bailout();
14204+ }
14205+ }
14206+ }
14207+
14208+ if (HG(func_whitelist) != NULL) {
14209+ if (!zend_hash_exists(HG(func_whitelist), fname->value.str.val, fname->value.str.len+1)) {
14210+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", fname->value.str.val);
14211+ zend_bailout();
14212+ }
14213+ } else if (HG(func_blacklist) != NULL) {
14214+ if (zend_hash_exists(HG(func_blacklist), fname->value.str.val, fname->value.str.len+1)) {
14215+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", fname->value.str.val);
14216+ zend_bailout();
14217+ }
14218+ }
14219+ }
14220+#endif
14221 FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
14222 zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(object).ptr, EX(ce));
14223 EX(object).ptr = NULL;
14224@@ -1816,6 +1901,7 @@
14225 efree(EX(Ts));
14226 }
14227 EG(in_execution) = EX(original_in_execution);
14228+ EG(in_code_type) = EX(original_in_code_type);
14229 EG(current_execute_data) = EX(prev_execute_data);
14230 return;
14231 }
14232@@ -2195,7 +2281,12 @@
14233 int dummy = 1;
14234 zend_file_handle file_handle = {0};
14235
14236+#if HARDENING_PATCH_INC_PROTECT
14237+ if (zend_is_valid_include(inc_filename)
14238+ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
14239+#else
14240 if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
14241+#endif
14242 && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
14243
14244 file_handle.filename = inc_filename->value.str.val;
14245@@ -2224,6 +2315,11 @@
14246 break;
14247 case ZEND_INCLUDE:
14248 case ZEND_REQUIRE:
14249+#if HARDENING_PATCH_INC_PROTECT
14250+ if (!zend_is_valid_include(inc_filename)) {
14251+ break;
14252+ }
14253+#endif
14254 new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
14255 break;
14256 case ZEND_EVAL: {
14257diff -Nura php-4.4.0/Zend/zend_execute_globals.h hardening-patch-4.4.0-0.4.3/Zend/zend_execute_globals.h
14258--- php-4.4.0/Zend/zend_execute_globals.h 2005-06-06 11:30:09.000000000 +0200
14259+++ hardening-patch-4.4.0-0.4.3/Zend/zend_execute_globals.h 2005-09-11 23:31:08.000000000 +0200
14260@@ -60,6 +60,8 @@
14261 object_info object;
14262 temp_variable *Ts;
14263 zend_bool original_in_execution;
14264+ zend_uint original_in_code_type;
14265+ zend_uint execute_depth;
14266 zend_op_array *op_array;
14267 struct _zend_execute_data *prev_execute_data;
14268 } zend_execute_data;
14269diff -Nura php-4.4.0/Zend/zend_extensions.c hardening-patch-4.4.0-0.4.3/Zend/zend_extensions.c
14270--- php-4.4.0/Zend/zend_extensions.c 2003-03-19 19:00:57.000000000 +0100
14271+++ hardening-patch-4.4.0-0.4.3/Zend/zend_extensions.c 2005-09-11 23:31:08.000000000 +0200
14272@@ -54,23 +54,44 @@
14273 return FAILURE;
14274 }
14275
14276+ /* check if module is compiled against Hardening-Patch */
14277+ if (extension_version_info->zend_extension_api_no < 1000000000) {
14278+ fprintf(stderr, "%s is not compiled with Hardening-Patch.\n"
14279+ "The Hardening-Patch version %d is installed.\n\n",
14280+ new_extension->name,
14281+ HARDENING_PATCH_ZEND_EXTENSION_API_NO);
14282+ DL_UNLOAD(handle);
14283+ return FAILURE;
14284+ }
14285+
14286+
14287+ /* check if module is compiled against correct Hardening-Patch version */
14288+ if (extension_version_info->zend_extension_api_no != HARDENING_PATCH_ZEND_EXTENSION_API_NO) {
14289+ fprintf(stderr, "%s requires Hardening-Patch version %d.\n"
14290+ "The Hardening-Patch version %d is installed.\n\n",
14291+ new_extension->name,
14292+ extension_version_info->zend_extension_api_no,
14293+ HARDENING_PATCH_ZEND_EXTENSION_API_NO);
14294+ DL_UNLOAD(handle);
14295+ return FAILURE;
14296+ }
14297
14298 /* allow extension to proclaim compatibility with any Zend version */
14299- if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
14300- if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
14301+ if (extension_version_info->real_zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
14302+ if (extension_version_info->real_zend_extension_api_no > ZEND_EXTENSION_API_NO) {
14303 fprintf(stderr, "%s requires Zend Engine API version %d.\n"
14304 "The Zend Engine API version %d which is installed, is outdated.\n\n",
14305 new_extension->name,
14306- extension_version_info->zend_extension_api_no,
14307+ extension_version_info->real_zend_extension_api_no,
14308 ZEND_EXTENSION_API_NO);
14309 DL_UNLOAD(handle);
14310 return FAILURE;
14311- } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
14312+ } else if (extension_version_info->real_zend_extension_api_no < ZEND_EXTENSION_API_NO) {
14313 fprintf(stderr, "%s requires Zend Engine API version %d.\n"
14314 "The Zend Engine API version %d which is installed, is newer.\n"
14315 "Contact %s at %s for a later version of %s.\n\n",
14316 new_extension->name,
14317- extension_version_info->zend_extension_api_no,
14318+ extension_version_info->real_zend_extension_api_no,
14319 ZEND_EXTENSION_API_NO,
14320 new_extension->author,
14321 new_extension->URL,
14322diff -Nura php-4.4.0/Zend/zend_extensions.h hardening-patch-4.4.0-0.4.3/Zend/zend_extensions.h
14323--- php-4.4.0/Zend/zend_extensions.h 2005-06-06 11:44:59.000000000 +0200
14324+++ hardening-patch-4.4.0-0.4.3/Zend/zend_extensions.h 2005-09-11 23:31:08.000000000 +0200
14325@@ -23,6 +23,9 @@
14326
14327 #include "zend_compile.h"
14328
14329+/* Create own API version number for Hardening-Patch */
14330+
14331+#define HARDENING_PATCH_ZEND_EXTENSION_API_NO 1001050805
14332 #define ZEND_EXTENSION_API_NO 20050606
14333
14334 typedef struct _zend_extension_version_info {
14335@@ -30,6 +33,7 @@
14336 char *required_zend_version;
14337 unsigned char thread_safe;
14338 unsigned char debug;
14339+ int real_zend_extension_api_no;
14340 } zend_extension_version_info;
14341
14342
14343@@ -96,7 +100,7 @@
14344
14345
14346 #define ZEND_EXTENSION() \
14347- ZEND_EXT_API zend_extension_version_info extension_version_info = { ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG }
14348+ ZEND_EXT_API zend_extension_version_info extension_version_info = { HARDENING_PATCH_ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG, ZEND_EXTENSION_API_NO }
14349
14350 #define STANDARD_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1
14351 #define COMPAT_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1
14352diff -Nura php-4.4.0/Zend/zend_globals.h hardening-patch-4.4.0-0.4.3/Zend/zend_globals.h
14353--- php-4.4.0/Zend/zend_globals.h 2004-11-04 00:15:05.000000000 +0100
14354+++ hardening-patch-4.4.0-0.4.3/Zend/zend_globals.h 2005-09-11 23:31:08.000000000 +0200
14355@@ -163,6 +163,16 @@
14356
14357 int error_reporting;
14358 int orig_error_reporting;
14359+#if HARDENING_PATCH
14360+ int hphp_log_syslog;
14361+ int hphp_log_syslog_facility;
14362+ int hphp_log_syslog_priority;
14363+ int hphp_log_sapi;
14364+ int hphp_log_script;
14365+ char *hphp_log_scriptname;
14366+ zend_bool hphp_log_use_x_forwarded_for;
14367+ long hphp_executor_max_depth;
14368+#endif
14369 int exit_status;
14370
14371 zend_op_array *active_op_array;
14372@@ -176,6 +186,7 @@
14373 int ticks_count;
14374
14375 zend_bool in_execution;
14376+ zend_uint in_code_type;
14377 zend_bool bailout_set;
14378 zend_bool full_tables_cleanup;
14379
14380diff -Nura php-4.4.0/Zend/zend.h hardening-patch-4.4.0-0.4.3/Zend/zend.h
14381--- php-4.4.0/Zend/zend.h 2005-01-25 14:08:41.000000000 +0100
14382+++ hardening-patch-4.4.0-0.4.3/Zend/zend.h 2005-09-11 23:31:08.000000000 +0200
14383@@ -275,9 +275,10 @@
14384 struct _zval_struct {
14385 /* Variable information */
14386 zvalue_value value; /* value */
14387+ zend_uint refcount;
14388+ zend_ushort flags;
14389 zend_uchar type; /* active type */
14390 zend_uchar is_ref;
14391- zend_ushort refcount;
14392 };
14393
14394
14395@@ -338,6 +339,12 @@
14396 void (*ticks_function)(int ticks);
14397 void (*on_timeout)(int seconds TSRMLS_DC);
14398 zend_bool (*open_function)(const char *filename, struct _zend_file_handle *);
14399+#if HARDENING_PATCH
14400+ void (*security_log_function)(int loglevel, char *fmt, ...);
14401+#endif
14402+#if HARDENING_PATCH_INC_PROTECT
14403+ int (*is_valid_include)(zval *z);
14404+#endif
14405 } zend_utility_functions;
14406
14407
14408@@ -469,7 +476,16 @@
14409 extern ZEND_API void (*zend_ticks_function)(int ticks);
14410 extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
14411 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
14412+#if HARDENING_PATCH
14413+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
14414+#endif
14415+#if HARDENING_PATCH_INC_PROTECT
14416+extern ZEND_API int (*zend_is_valid_include)(zval *z);
14417+#endif
14418
14419+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
14420+ZEND_API unsigned int zend_canary(void);
14421+#endif
14422
14423 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3);
14424
14425@@ -576,6 +592,11 @@
14426
14427 #define ZEND_MAX_RESERVED_RESOURCES 4
14428
14429+#if HARDENING_PATCH
14430+#include "hardened_globals.h"
14431+#include "php_syslog.h"
14432+#endif
14433+
14434 #endif /* ZEND_H */
14435
14436 /*
14437diff -Nura php-4.4.0/Zend/zend_hash.c hardening-patch-4.4.0-0.4.3/Zend/zend_hash.c
14438--- php-4.4.0/Zend/zend_hash.c 2005-04-28 09:34:32.000000000 +0200
14439+++ hardening-patch-4.4.0-0.4.3/Zend/zend_hash.c 2005-09-11 23:31:08.000000000 +0200
14440@@ -26,6 +26,17 @@
14441 # include <stdlib.h>
14442 #endif
14443
14444+#if HARDENING_PATCH_HASH_PROTECT
14445+ unsigned int zend_hash_canary = 0x1234567;
14446+ zend_bool zend_hash_canary_inited = 0;
14447+#endif
14448+
14449+#define CHECK_HASH_CANARY(hash) \
14450+ if (zend_hash_canary != (hash)->canary) { \
14451+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
14452+ exit(1); \
14453+ }
14454+
14455 #define HANDLE_NUMERIC(key, length, func) { \
14456 register char *tmp=key; \
14457 \
14458@@ -175,6 +186,9 @@
14459 {
14460 uint i = 3;
14461 Bucket **tmp;
14462+#if HARDENING_PATCH_HASH_PROTECT
14463+ TSRMLS_FETCH();
14464+#endif
14465
14466 SET_INCONSISTENT(HT_OK);
14467
14468@@ -184,6 +198,13 @@
14469
14470 ht->nTableSize = 1 << i;
14471 ht->nTableMask = ht->nTableSize - 1;
14472+#if HARDENING_PATCH_HASH_PROTECT
14473+ if (zend_hash_canary_inited==0) {
14474+ zend_hash_canary = zend_canary();
14475+ zend_hash_canary_inited = 1;
14476+ }
14477+ ht->canary = zend_hash_canary;
14478+#endif
14479 ht->pDestructor = pDestructor;
14480 ht->pListHead = NULL;
14481 ht->pListTail = NULL;
14482@@ -259,6 +280,9 @@
14483 }
14484 #endif
14485 if (ht->pDestructor) {
14486+#if HARDENING_PATCH_HASH_PROTECT
14487+ CHECK_HASH_CANARY(ht);
14488+#endif
14489 ht->pDestructor(p->pData);
14490 }
14491 UPDATE_DATA(ht, p, pData, nDataSize);
14492@@ -327,6 +351,9 @@
14493 }
14494 #endif
14495 if (ht->pDestructor) {
14496+#if HARDENING_PATCH_HASH_PROTECT
14497+ CHECK_HASH_CANARY(ht);
14498+#endif
14499 ht->pDestructor(p->pData);
14500 }
14501 UPDATE_DATA(ht, p, pData, nDataSize);
14502@@ -402,6 +429,9 @@
14503 }
14504 #endif
14505 if (ht->pDestructor) {
14506+#if HARDENING_PATCH_HASH_PROTECT
14507+ CHECK_HASH_CANARY(ht);
14508+#endif
14509 ht->pDestructor(p->pData);
14510 }
14511 UPDATE_DATA(ht, p, pData, nDataSize);
14512@@ -450,7 +480,7 @@
14513 IS_CONSISTENT(ht);
14514
14515 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
14516- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
14517+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
14518 if (t) {
14519 HANDLE_BLOCK_INTERRUPTIONS();
14520 ht->arBuckets = t;
14521@@ -460,6 +490,7 @@
14522 HANDLE_UNBLOCK_INTERRUPTIONS();
14523 return SUCCESS;
14524 }
14525+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
14526 return FAILURE;
14527 }
14528 return SUCCESS;
14529@@ -524,6 +555,9 @@
14530 ht->pInternalPointer = p->pListNext;
14531 }
14532 if (ht->pDestructor) {
14533+#if HARDENING_PATCH_HASH_PROTECT
14534+ CHECK_HASH_CANARY(ht);
14535+#endif
14536 ht->pDestructor(p->pData);
14537 }
14538 if (!p->pDataPtr) {
14539@@ -553,6 +587,9 @@
14540 q = p;
14541 p = p->pListNext;
14542 if (ht->pDestructor) {
14543+#if HARDENING_PATCH_HASH_PROTECT
14544+ CHECK_HASH_CANARY(ht);
14545+#endif
14546 ht->pDestructor(q->pData);
14547 }
14548 if (!q->pDataPtr && q->pData) {
14549@@ -579,6 +616,9 @@
14550 q = p;
14551 p = p->pListNext;
14552 if (ht->pDestructor) {
14553+#if HARDENING_PATCH_HASH_PROTECT
14554+ CHECK_HASH_CANARY(ht);
14555+#endif
14556 ht->pDestructor(q->pData);
14557 }
14558 if (!q->pDataPtr && q->pData) {
14559@@ -608,6 +648,9 @@
14560 HANDLE_BLOCK_INTERRUPTIONS();
14561
14562 if (ht->pDestructor) {
14563+#if HARDENING_PATCH_HASH_PROTECT
14564+ CHECK_HASH_CANARY(ht);
14565+#endif
14566 ht->pDestructor(p->pData);
14567 }
14568 if (!p->pDataPtr) {
14569diff -Nura php-4.4.0/Zend/zend_hash.h hardening-patch-4.4.0-0.4.3/Zend/zend_hash.h
14570--- php-4.4.0/Zend/zend_hash.h 2002-12-31 17:23:03.000000000 +0100
14571+++ hardening-patch-4.4.0-0.4.3/Zend/zend_hash.h 2005-09-11 23:31:08.000000000 +0200
14572@@ -54,6 +54,9 @@
14573 } Bucket;
14574
14575 typedef struct _hashtable {
14576+#if HARDENING_PATCH_HASH_PROTECT
14577+ unsigned int canary;
14578+#endif
14579 uint nTableSize;
14580 uint nTableMask;
14581 uint nNumOfElements;
14582diff -Nura php-4.4.0/Zend/zend_ini.h hardening-patch-4.4.0-0.4.3/Zend/zend_ini.h
14583--- php-4.4.0/Zend/zend_ini.h 2005-01-09 18:00:16.000000000 +0100
14584+++ hardening-patch-4.4.0-0.4.3/Zend/zend_ini.h 2005-09-11 23:31:08.000000000 +0200
14585@@ -174,6 +174,7 @@
14586 /* Standard message handlers */
14587 BEGIN_EXTERN_C()
14588 ZEND_API ZEND_INI_MH(OnUpdateBool);
14589+#define OnUpdateLong OnUpdateInt
14590 ZEND_API ZEND_INI_MH(OnUpdateInt);
14591 ZEND_API ZEND_INI_MH(OnUpdateReal);
14592 ZEND_API ZEND_INI_MH(OnUpdateString);
14593diff -Nura php-4.4.0/Zend/zend_language_scanner.l hardening-patch-4.4.0-0.4.3/Zend/zend_language_scanner.l
14594--- php-4.4.0/Zend/zend_language_scanner.l 2005-03-09 16:07:19.000000000 +0100
14595+++ hardening-patch-4.4.0-0.4.3/Zend/zend_language_scanner.l 2005-09-11 23:31:08.000000000 +0200
14596@@ -393,6 +393,13 @@
14597 compilation_successful=0;
14598 } else {
14599 init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
14600+#if HARDENING_PATCH
14601+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
14602+ op_array->created_by_eval = 1;
14603+ } else {
14604+ op_array->created_by_eval = 0;
14605+ }
14606+#endif
14607 CG(in_compilation) = 1;
14608 CG(active_op_array) = op_array;
14609 compiler_result = zendparse(TSRMLS_C);
14610diff -Nura php-4.4.0/Zend/zend_language_scanner.c hardening-patch-4.4.0-0.4.3/Zend/zend_language_scanner.c
14611--- php-4.4.0/Zend/zend_language_scanner.c 2005-07-11 12:07:41.000000000 +0200
14612+++ hardening-patch-4.4.0-0.4.3/Zend/zend_language_scanner.c 2005-09-11 23:31:08.000000000 +0200
14613@@ -3121,6 +3121,13 @@
14614 compilation_successful=0;
14615 } else {
14616 init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
14617+#if HARDENING_PATCH
14618+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
14619+ op_array->created_by_eval = 1;
14620+ } else {
14621+ op_array->created_by_eval = 0;
14622+ }
14623+#endif
14624 CG(in_compilation) = 1;
14625 CG(active_op_array) = op_array;
14626 compiler_result = zendparse(TSRMLS_C);
14627diff -Nura php-4.4.0/Zend/zend_llist.c hardening-patch-4.4.0-0.4.3/Zend/zend_llist.c
14628--- php-4.4.0/Zend/zend_llist.c 2002-12-31 17:23:04.000000000 +0100
14629+++ hardening-patch-4.4.0-0.4.3/Zend/zend_llist.c 2005-09-11 23:31:08.000000000 +0200
14630@@ -21,9 +21,34 @@
14631 #include "zend.h"
14632 #include "zend_llist.h"
14633 #include "zend_qsort.h"
14634+#include "zend_globals.h"
14635+
14636+#define CHECK_LIST_CANARY(list) \
14637+ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \
14638+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
14639+ exit(1); \
14640+ }
14641+
14642+#define CHECK_LISTELEMENT_CANARY(elem) \
14643+ if (HG(canary_3) != (elem)->canary) { \
14644+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
14645+ exit(1); \
14646+ }
14647+
14648
14649 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
14650 {
14651+#if HARDENING_PATCH_LL_PROTECT
14652+ TSRMLS_FETCH();
14653+
14654+ if (!HG(ll_canary_inited)) {
14655+ HG(canary_3) = zend_canary();
14656+ HG(canary_4) = zend_canary();
14657+ HG(ll_canary_inited) = 1;
14658+ }
14659+ l->canary_h = HG(canary_3);
14660+ l->canary_t = HG(canary_4);
14661+#endif
14662 l->head = NULL;
14663 l->tail = NULL;
14664 l->count = 0;
14665@@ -37,6 +62,11 @@
14666 {
14667 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
14668
14669+#if HARDENING_PATCH_LL_PROTECT
14670+ TSRMLS_FETCH();
14671+ CHECK_LIST_CANARY(l)
14672+ tmp->canary = HG(canary_3);
14673+#endif
14674 tmp->prev = l->tail;
14675 tmp->next = NULL;
14676 if (l->tail) {
14677@@ -55,6 +85,11 @@
14678 {
14679 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
14680
14681+#if HARDENING_PATCH_LL_PROTECT
14682+ TSRMLS_FETCH();
14683+ CHECK_LIST_CANARY(l)
14684+ tmp->canary = HG(canary_3);
14685+#endif
14686 tmp->next = l->head;
14687 tmp->prev = NULL;
14688 if (l->head) {
14689@@ -91,10 +126,20 @@
14690 zend_llist_element *current=l->head;
14691 zend_llist_element *next;
14692
14693+#if HARDENING_PATCH_LL_PROTECT
14694+ TSRMLS_FETCH();
14695+ CHECK_LIST_CANARY(l)
14696+#endif
14697 while (current) {
14698+#if HARDENING_PATCH_LL_PROTECT
14699+ CHECK_LISTELEMENT_CANARY(current)
14700+#endif
14701 next = current->next;
14702 if (compare(current->data, element)) {
14703 DEL_LLIST_ELEMENT(current, l);
14704+#if HARDENING_PATCH_LL_PROTECT
14705+ current->canary = 0;
14706+#endif
14707 break;
14708 }
14709 current = next;
14710@@ -106,7 +151,14 @@
14711 {
14712 zend_llist_element *current=l->head, *next;
14713
14714+#if HARDENING_PATCH_LL_PROTECT
14715+ TSRMLS_FETCH();
14716+ CHECK_LIST_CANARY(l)
14717+#endif
14718 while (current) {
14719+#if HARDENING_PATCH_LL_PROTECT
14720+ CHECK_LISTELEMENT_CANARY(current)
14721+#endif
14722 next = current->next;
14723 if (l->dtor) {
14724 l->dtor(current->data);
14725@@ -131,7 +183,14 @@
14726 zend_llist_element *old_tail;
14727 void *data;
14728
14729+#if HARDENING_PATCH_LL_PROTECT
14730+ TSRMLS_FETCH();
14731+ CHECK_LIST_CANARY(l)
14732+#endif
14733 if ((old_tail = l->tail)) {
14734+#if HARDENING_PATCH_LL_PROTECT
14735+ CHECK_LISTELEMENT_CANARY(old_tail)
14736+#endif
14737 if (l->tail->prev) {
14738 l->tail->prev->next = NULL;
14739 }
14740@@ -157,9 +216,16 @@
14741 {
14742 zend_llist_element *ptr;
14743
14744+#if HARDENING_PATCH_LL_PROTECT
14745+ TSRMLS_FETCH();
14746+ CHECK_LIST_CANARY(src)
14747+#endif
14748 zend_llist_init(dst, src->size, src->dtor, src->persistent);
14749 ptr = src->head;
14750 while (ptr) {
14751+#if HARDENING_PATCH_LL_PROTECT
14752+ CHECK_LISTELEMENT_CANARY(ptr)
14753+#endif
14754 zend_llist_add_element(dst, ptr->data);
14755 ptr = ptr->next;
14756 }
14757@@ -170,11 +236,21 @@
14758 {
14759 zend_llist_element *element, *next;
14760
14761+#if HARDENING_PATCH_LL_PROTECT
14762+ TSRMLS_FETCH();
14763+ CHECK_LIST_CANARY(l)
14764+#endif
14765 element=l->head;
14766 while (element) {
14767+#if HARDENING_PATCH_LL_PROTECT
14768+ CHECK_LISTELEMENT_CANARY(element)
14769+#endif
14770 next = element->next;
14771 if (func(element->data)) {
14772 DEL_LLIST_ELEMENT(element, l);
14773+#if HARDENING_PATCH_LL_PROTECT
14774+ element->canary = 0;
14775+#endif
14776 }
14777 element = next;
14778 }
14779@@ -185,7 +261,13 @@
14780 {
14781 zend_llist_element *element;
14782
14783+#if HARDENING_PATCH_LL_PROTECT
14784+ CHECK_LIST_CANARY(l)
14785+#endif
14786 for (element=l->head; element; element=element->next) {
14787+#if HARDENING_PATCH_LL_PROTECT
14788+ CHECK_LISTELEMENT_CANARY(element)
14789+#endif
14790 func(element->data TSRMLS_CC);
14791 }
14792 }
14793@@ -197,6 +279,9 @@
14794 zend_llist_element **elements;
14795 zend_llist_element *element, **ptr;
14796
14797+#if HARDENING_PATCH_LL_PROTECT
14798+ CHECK_LIST_CANARY(l)
14799+#endif
14800 if (l->count <= 0) {
14801 return;
14802 }
14803@@ -206,6 +291,9 @@
14804 ptr = &elements[0];
14805
14806 for (element=l->head; element; element=element->next) {
14807+#if HARDENING_PATCH_LL_PROTECT
14808+ CHECK_LISTELEMENT_CANARY(element)
14809+#endif
14810 *ptr++ = element;
14811 }
14812
14813@@ -228,7 +316,13 @@
14814 {
14815 zend_llist_element *element;
14816
14817+#if HARDENING_PATCH_LL_PROTECT
14818+ CHECK_LIST_CANARY(l)
14819+#endif
14820 for (element=l->head; element; element=element->next) {
14821+#if HARDENING_PATCH_LL_PROTECT
14822+ CHECK_LISTELEMENT_CANARY(element)
14823+#endif
14824 func(element->data, arg TSRMLS_CC);
14825 }
14826 }
14827@@ -239,8 +333,14 @@
14828 zend_llist_element *element;
14829 va_list args;
14830
14831+#if HARDENING_PATCH_LL_PROTECT
14832+ CHECK_LIST_CANARY(l)
14833+#endif
14834 va_start(args, num_args);
14835 for (element=l->head; element; element=element->next) {
14836+#if HARDENING_PATCH_LL_PROTECT
14837+ CHECK_LISTELEMENT_CANARY(element)
14838+#endif
14839 func(element->data, num_args, args TSRMLS_CC);
14840 }
14841 va_end(args);
14842@@ -249,6 +349,10 @@
14843
14844 ZEND_API int zend_llist_count(zend_llist *l)
14845 {
14846+#if HARDENING_PATCH_LL_PROTECT
14847+ TSRMLS_FETCH();
14848+ CHECK_LIST_CANARY(l)
14849+#endif
14850 return l->count;
14851 }
14852
14853@@ -256,8 +360,15 @@
14854 {
14855 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
14856
14857+#if HARDENING_PATCH_LL_PROTECT
14858+ TSRMLS_FETCH();
14859+ CHECK_LIST_CANARY(l)
14860+#endif
14861 *current = l->head;
14862 if (*current) {
14863+#if HARDENING_PATCH_LL_PROTECT
14864+ CHECK_LISTELEMENT_CANARY(*current)
14865+#endif
14866 return (*current)->data;
14867 } else {
14868 return NULL;
14869@@ -269,8 +380,15 @@
14870 {
14871 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
14872
14873+#if HARDENING_PATCH_LL_PROTECT
14874+ TSRMLS_FETCH();
14875+ CHECK_LIST_CANARY(l)
14876+#endif
14877 *current = l->tail;
14878 if (*current) {
14879+#if HARDENING_PATCH_LL_PROTECT
14880+ CHECK_LISTELEMENT_CANARY(*current)
14881+#endif
14882 return (*current)->data;
14883 } else {
14884 return NULL;
14885@@ -282,9 +400,19 @@
14886 {
14887 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
14888
14889+#if HARDENING_PATCH_LL_PROTECT
14890+ TSRMLS_FETCH();
14891+ CHECK_LIST_CANARY(l)
14892+#endif
14893 if (*current) {
14894+#if HARDENING_PATCH_LL_PROTECT
14895+ CHECK_LISTELEMENT_CANARY(*current)
14896+#endif
14897 *current = (*current)->next;
14898 if (*current) {
14899+#if HARDENING_PATCH_LL_PROTECT
14900+ CHECK_LISTELEMENT_CANARY(*current)
14901+#endif
14902 return (*current)->data;
14903 }
14904 }
14905@@ -296,9 +424,19 @@
14906 {
14907 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
14908
14909+#if HARDENING_PATCH_LL_PROTECT
14910+ TSRMLS_FETCH();
14911+ CHECK_LIST_CANARY(l)
14912+#endif
14913 if (*current) {
14914+#if HARDENING_PATCH_LL_PROTECT
14915+ CHECK_LISTELEMENT_CANARY(*current)
14916+#endif
14917 *current = (*current)->prev;
14918 if (*current) {
14919+#if HARDENING_PATCH_LL_PROTECT
14920+ CHECK_LISTELEMENT_CANARY(*current)
14921+#endif
14922 return (*current)->data;
14923 }
14924 }
14925diff -Nura php-4.4.0/Zend/zend_llist.h hardening-patch-4.4.0-0.4.3/Zend/zend_llist.h
14926--- php-4.4.0/Zend/zend_llist.h 2002-12-31 17:23:04.000000000 +0100
14927+++ hardening-patch-4.4.0-0.4.3/Zend/zend_llist.h 2005-09-11 23:31:08.000000000 +0200
14928@@ -24,6 +24,9 @@
14929 #include <stdlib.h>
14930
14931 typedef struct _zend_llist_element {
14932+#if HARDENING_PATCH_LL_PROTECT
14933+ unsigned int canary;
14934+#endif
14935 struct _zend_llist_element *next;
14936 struct _zend_llist_element *prev;
14937 char data[1]; /* Needs to always be last in the struct */
14938@@ -36,6 +39,9 @@
14939 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
14940
14941 typedef struct _zend_llist {
14942+#if HARDENING_PATCH_LL_PROTECT
14943+ unsigned int canary_h; /* head */
14944+#endif
14945 zend_llist_element *head;
14946 zend_llist_element *tail;
14947 size_t size;
14948@@ -43,6 +49,9 @@
14949 llist_dtor_func_t dtor;
14950 unsigned char persistent;
14951 zend_llist_element *traverse_ptr;
14952+#if HARDENING_PATCH_LL_PROTECT
14953+ unsigned int canary_t; /* tail */
14954+#endif
14955 } zend_llist;
14956
14957 typedef zend_llist_element* zend_llist_position;
14958diff -Nura php-4.4.0/Zend/zend_modules.h hardening-patch-4.4.0-0.4.3/Zend/zend_modules.h
14959--- php-4.4.0/Zend/zend_modules.h 2002-12-31 17:23:04.000000000 +0100
14960+++ hardening-patch-4.4.0-0.4.3/Zend/zend_modules.h 2005-09-12 22:59:33.000000000 +0200
14961@@ -34,6 +34,7 @@
14962 ZEND_API extern unsigned char second_arg_force_ref[];
14963 ZEND_API extern unsigned char third_arg_force_ref[];
14964
14965+#define HARDENING_PATCH_ZEND_MODULE_API_NO 1001050912
14966 #define ZEND_MODULE_API_NO 20020429
14967 #ifdef ZTS
14968 #define USING_ZTS 1
14969@@ -41,9 +42,9 @@
14970 #define USING_ZTS 0
14971 #endif
14972
14973-#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
14974+#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
14975
14976-#define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0
14977+#define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0, ZEND_MODULE_API_NO
14978
14979 #define STANDARD_MODULE_PROPERTIES \
14980 NULL, NULL, STANDARD_MODULE_PROPERTIES_EX
14981@@ -75,6 +76,7 @@
14982 unsigned char type;
14983 void *handle;
14984 int module_number;
14985+ unsigned int real_zend_api;
14986 };
14987
14988
14989diff -Nura php-4.4.0/Zend/zend_opcode.c hardening-patch-4.4.0-0.4.3/Zend/zend_opcode.c
14990--- php-4.4.0/Zend/zend_opcode.c 2002-12-31 17:23:04.000000000 +0100
14991+++ hardening-patch-4.4.0-0.4.3/Zend/zend_opcode.c 2005-09-11 23:31:08.000000000 +0200
14992@@ -88,6 +88,9 @@
14993 op_array->done_pass_two = 0;
14994
14995 op_array->start_op = NULL;
14996+#if HARDENING_PATCH
14997+ op_array->created_by_eval = 0;
14998+#endif
14999
15000 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
15001 }
15002diff -Nura php-4.4.0/Zend/zend_operators.c hardening-patch-4.4.0-0.4.3/Zend/zend_operators.c
15003--- php-4.4.0/Zend/zend_operators.c 2005-03-31 10:18:39.000000000 +0200
15004+++ hardening-patch-4.4.0-0.4.3/Zend/zend_operators.c 2005-09-11 23:31:08.000000000 +0200
15005@@ -1604,6 +1604,20 @@
15006 return (op->value.lval ? 1 : 0);
15007 }
15008
15009+ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length)
15010+{
15011+ register unsigned char *str = (unsigned char*)source;
15012+ register unsigned char *result = (unsigned char*)dest;
15013+ register unsigned char *end = str + length;
15014+
15015+ while (str < end) {
15016+ *result++ = tolower((int)*str++);
15017+ }
15018+ *result = *end;
15019+
15020+ return dest;
15021+}
15022+
15023 ZEND_API void zend_str_tolower(char *str, unsigned int length)
15024 {
15025 register char *p=str, *end=p+length;
15026diff -Nura php-4.4.0/Zend/zend_operators.h hardening-patch-4.4.0-0.4.3/Zend/zend_operators.h
15027--- php-4.4.0/Zend/zend_operators.h 2005-03-31 10:18:40.000000000 +0200
15028+++ hardening-patch-4.4.0-0.4.3/Zend/zend_operators.h 2005-09-11 23:31:08.000000000 +0200
15029@@ -174,6 +174,14 @@
15030 #endif
15031
15032 ZEND_API void zend_str_tolower(char *str, unsigned int length);
15033+ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
15034+
15035+static inline char *
15036+zend_str_tolower_dup(const char *source, unsigned int length)
15037+{
15038+ return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
15039+}
15040+
15041 ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2);
15042 ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
15043 ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2);
diff --git a/0.4.3/hardening-patch-5.0.5-0.4.3.patch b/0.4.3/hardening-patch-5.0.5-0.4.3.patch
new file mode 100644
index 0000000..70c37a6
--- /dev/null
+++ b/0.4.3/hardening-patch-5.0.5-0.4.3.patch
@@ -0,0 +1,7046 @@
1diff -Nura php-5.0.5/acinclude.m4 hardening-patch-5.0.5-0.4.3/acinclude.m4
2--- php-5.0.5/acinclude.m4 2005-07-26 00:31:07.000000000 +0200
3+++ hardening-patch-5.0.5-0.4.3/acinclude.m4 2005-09-11 23:30:52.000000000 +0200
4@@ -1182,6 +1182,36 @@
5 fi
6 ])
7
8+dnl
9+dnl Check for broken realpath()
10+dnl
11+dnl realpath("/etc/hosts/../passwd",XXX) should not return
12+dnl "/etc/passwd"
13+dnl
14+AC_DEFUN([PHP_AC_BROKEN_REALPATH],[
15+ AC_CACHE_CHECK(whether realpath is broken, ac_cv_broken_realpath,[
16+ AC_TRY_RUN([
17+main() {
18+ char buf[4096+1];
19+ buf[0] = 0;
20+ realpath("/etc/hosts/../passwd", buf);
21+ exit(strcmp(buf, "/etc/passwd")==0);
22+}
23+ ],[
24+ ac_cv_broken_realpath=no
25+ ],[
26+ ac_cv_broken_realpath=yes
27+ ],[
28+ ac_cv_broken_realpath=no
29+ ])
30+ ])
31+ if test "$ac_cv_broken_realpath" = "yes"; then
32+ AC_DEFINE(PHP_BROKEN_REALPATH, 1, [Whether realpath is broken])
33+ else
34+ AC_DEFINE(PHP_BROKEN_REALPATH, 0, [Whether realpath is broken])
35+ fi
36+])
37+
38 dnl PHP_SHARED_MODULE(module-name, object-var, build-dir, cxx)
39 dnl
40 dnl Basically sets up the link-stage for building module-name
41diff -Nura php-5.0.5/configure hardening-patch-5.0.5-0.4.3/configure
42--- php-5.0.5/configure 2005-09-05 13:16:17.000000000 +0200
43+++ hardening-patch-5.0.5-0.4.3/configure 2005-09-11 23:30:52.000000000 +0200
44@@ -404,6 +404,16 @@
45 ac_default_prefix=/usr/local
46 # Any additions from configure.in:
47 ac_help="$ac_help
48+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
49+ac_help="$ac_help
50+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
51+ac_help="$ac_help
52+ --disable-hardening-patch-inc-protect Disable include/require protection."
53+ac_help="$ac_help
54+ --disable-hardening-patch-fmt-protect Disable format string protection."
55+ac_help="$ac_help
56+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
57+ac_help="$ac_help
58
59 SAPI modules:
60 "
61@@ -860,6 +870,8 @@
62 ac_help="$ac_help
63 --disable-tokenizer Disable tokenizer support"
64 ac_help="$ac_help
65+ --disable-varfilter Disable Hardening-Patch's variable filter"
66+ac_help="$ac_help
67 --enable-wddx Enable WDDX support."
68 ac_help="$ac_help
69 --disable-xml Disable XML support."
70@@ -2834,6 +2846,157 @@
71
72
73
74+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
75+if test "${enable_hardening_patch_mm_protect+set}" = set; then
76+ enableval="$enable_hardening_patch_mm_protect"
77+
78+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
79+
80+else
81+
82+ DO_HARDENING_PATCH_MM_PROTECT=yes
83+
84+fi
85+
86+
87+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
88+if test "${enable_hardening_patch_ll_protect+set}" = set; then
89+ enableval="$enable_hardening_patch_ll_protect"
90+
91+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
92+
93+else
94+
95+ DO_HARDENING_PATCH_LL_PROTECT=yes
96+
97+fi
98+
99+
100+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
101+if test "${enable_hardening_patch_inc_protect+set}" = set; then
102+ enableval="$enable_hardening_patch_inc_protect"
103+
104+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
105+
106+else
107+
108+ DO_HARDENING_PATCH_INC_PROTECT=yes
109+
110+fi
111+
112+
113+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
114+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
115+ enableval="$enable_hardening_patch_fmt_protect"
116+
117+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
118+
119+else
120+
121+ DO_HARDENING_PATCH_FMT_PROTECT=yes
122+
123+fi
124+
125+
126+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
127+if test "${enable_hardening_patch_hash_protect+set}" = set; then
128+ enableval="$enable_hardening_patch_hash_protect"
129+
130+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
131+
132+else
133+
134+ DO_HARDENING_PATCH_HASH_PROTECT=yes
135+
136+fi
137+
138+
139+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
140+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
141+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
142+
143+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
144+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
145+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
146+
147+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
148+echo "configure:2733: checking whether to protect include/require statements" >&5
149+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
150+
151+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
152+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
153+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
154+
155+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
156+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
157+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
158+
159+
160+cat >> confdefs.h <<\EOF
161+#define HARDENING_PATCH 1
162+EOF
163+
164+
165+
166+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
167+ cat >> confdefs.h <<\EOF
168+#define HARDENING_PATCH_MM_PROTECT 1
169+EOF
170+
171+else
172+ cat >> confdefs.h <<\EOF
173+#define HARDENING_PATCH_MM_PROTECT 0
174+EOF
175+
176+fi
177+
178+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
179+ cat >> confdefs.h <<\EOF
180+#define HARDENING_PATCH_LL_PROTECT 1
181+EOF
182+
183+else
184+ cat >> confdefs.h <<\EOF
185+#define HARDENING_PATCH_LL_PROTECT 0
186+EOF
187+
188+fi
189+
190+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
191+ cat >> confdefs.h <<\EOF
192+#define HARDENING_PATCH_INC_PROTECT 1
193+EOF
194+
195+else
196+ cat >> confdefs.h <<\EOF
197+#define HARDENING_PATCH_INC_PROTECT 0
198+EOF
199+
200+fi
201+
202+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
203+ cat >> confdefs.h <<\EOF
204+#define HARDENING_PATCH_FMT_PROTECT 1
205+EOF
206+
207+else
208+ cat >> confdefs.h <<\EOF
209+#define HARDENING_PATCH_FMT_PROTECT 0
210+EOF
211+
212+fi
213+
214+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
215+ cat >> confdefs.h <<\EOF
216+#define HARDENING_PATCH_HASH_PROTECT 1
217+EOF
218+
219+else
220+ cat >> confdefs.h <<\EOF
221+#define HARDENING_PATCH_HASH_PROTECT 0
222+EOF
223+
224+fi
225
226
227
228@@ -17473,6 +17636,62 @@
229 fi
230
231
232+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
233+echo "configure:14928: checking whether realpath is broken" >&5
234+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
235+ echo $ac_n "(cached) $ac_c" 1>&6
236+else
237+
238+ if test "$cross_compiling" = yes; then
239+
240+ ac_cv_broken_realpath=no
241+
242+else
243+ cat > conftest.$ac_ext <<EOF
244+#line 14939 "configure"
245+#include "confdefs.h"
246+
247+main() {
248+ char buf[4096+1];
249+ buf[0] = 0;
250+ realpath("/etc/hosts/../passwd", buf);
251+ exit(strcmp(buf, "/etc/passwd")==0);
252+}
253+
254+EOF
255+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
256+then
257+
258+ ac_cv_broken_realpath=no
259+
260+else
261+ echo "configure: failed program was:" >&5
262+ cat conftest.$ac_ext >&5
263+ rm -fr conftest*
264+
265+ ac_cv_broken_realpath=yes
266+
267+fi
268+rm -fr conftest*
269+fi
270+
271+
272+fi
273+
274+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
275+ if test "$ac_cv_broken_realpath" = "yes"; then
276+ cat >> confdefs.h <<\EOF
277+#define PHP_BROKEN_REALPATH 1
278+EOF
279+
280+ else
281+ cat >> confdefs.h <<\EOF
282+#define PHP_BROKEN_REALPATH 0
283+EOF
284+
285+ fi
286+
287+
288 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
289 echo "configure:17478: checking for declared timezone" >&5
290 if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
291@@ -88634,7 +88853,7 @@
292 if test "$ac_cv_crypt_blowfish" = "yes"; then
293 ac_result=1
294 else
295- ac_result=0
296+ ac_result=1
297 fi
298 cat >> confdefs.h <<EOF
299 #define PHP_BLOWFISH_CRYPT $ac_result
300@@ -91230,7 +91449,7 @@
301 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
302 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
303 var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
304- filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c; do
305+ filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
306
307 IFS=.
308 set $ac_src
309@@ -91288,7 +91507,7 @@
310 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
311 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
312 var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
313- filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c; do
314+ filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
315
316 IFS=.
317 set $ac_src
318@@ -91480,7 +91699,7 @@
319 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
320 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
321 var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
322- filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c; do
323+ filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
324
325 IFS=.
326 set $ac_src
327@@ -91535,7 +91754,7 @@
328 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
329 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
330 var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
331- filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c; do
332+ filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
333
334 IFS=.
335 set $ac_src
336@@ -95503,6 +95722,265 @@
337 fi
338
339
340+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
341+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
342+# Check whether --enable-varfilter or --disable-varfilter was given.
343+if test "${enable_varfilter+set}" = set; then
344+ enableval="$enable_varfilter"
345+ PHP_VARFILTER=$enableval
346+else
347+
348+ PHP_VARFILTER=yes
349+
350+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
351+ PHP_VARFILTER=$PHP_ENABLE_ALL
352+ fi
353+
354+fi
355+
356+
357+
358+ext_output="yes, shared"
359+ext_shared=yes
360+case $PHP_VARFILTER in
361+shared,*)
362+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
363+ ;;
364+shared)
365+ PHP_VARFILTER=yes
366+ ;;
367+no)
368+ ext_output=no
369+ ext_shared=no
370+ ;;
371+*)
372+ ext_output=yes
373+ ext_shared=no
374+ ;;
375+esac
376+
377+
378+
379+echo "$ac_t""$ext_output" 1>&6
380+
381+
382+
383+
384+if test "$PHP_VARFILTER" != "no"; then
385+ cat >> confdefs.h <<\EOF
386+#define HAVE_VARFILTER 1
387+EOF
388+
389+
390+ ext_builddir=ext/varfilter
391+ ext_srcdir=$abs_srcdir/ext/varfilter
392+
393+ ac_extra=
394+
395+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
396+
397+
398+
399+ case ext/varfilter in
400+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
401+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
402+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
403+ esac
404+
405+
406+
407+ b_c_pre=$php_c_pre
408+ b_cxx_pre=$php_cxx_pre
409+ b_c_meta=$php_c_meta
410+ b_cxx_meta=$php_cxx_meta
411+ b_c_post=$php_c_post
412+ b_cxx_post=$php_cxx_post
413+ b_lo=$php_lo
414+
415+
416+ old_IFS=$IFS
417+ for ac_src in varfilter.c; do
418+
419+ IFS=.
420+ set $ac_src
421+ ac_obj=$1
422+ IFS=$old_IFS
423+
424+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
425+
426+ case $ac_src in
427+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
428+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
429+ esac
430+
431+ cat >>Makefile.objects<<EOF
432+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
433+ $ac_comp
434+EOF
435+ done
436+
437+
438+ EXT_STATIC="$EXT_STATIC varfilter"
439+ if test "$ext_shared" != "nocli"; then
440+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
441+ fi
442+ else
443+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
444+
445+ case ext/varfilter in
446+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
447+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
448+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
449+ esac
450+
451+
452+
453+ b_c_pre=$shared_c_pre
454+ b_cxx_pre=$shared_cxx_pre
455+ b_c_meta=$shared_c_meta
456+ b_cxx_meta=$shared_cxx_meta
457+ b_c_post=$shared_c_post
458+ b_cxx_post=$shared_cxx_post
459+ b_lo=$shared_lo
460+
461+
462+ old_IFS=$IFS
463+ for ac_src in varfilter.c; do
464+
465+ IFS=.
466+ set $ac_src
467+ ac_obj=$1
468+ IFS=$old_IFS
469+
470+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
471+
472+ case $ac_src in
473+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
474+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
475+ esac
476+
477+ cat >>Makefile.objects<<EOF
478+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
479+ $ac_comp
480+EOF
481+ done
482+
483+
484+ install_modules="install-modules"
485+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
486+
487+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
488+
489+ cat >>Makefile.objects<<EOF
490+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
491+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
492+
493+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
494+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
495+
496+EOF
497+
498+ cat >> confdefs.h <<EOF
499+#define COMPILE_DL_VARFILTER 1
500+EOF
501+
502+ fi
503+ fi
504+
505+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
506+ if test "$PHP_SAPI" = "cgi"; then
507+
508+
509+ case ext/varfilter in
510+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
511+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
512+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
513+ esac
514+
515+
516+
517+ b_c_pre=$php_c_pre
518+ b_cxx_pre=$php_cxx_pre
519+ b_c_meta=$php_c_meta
520+ b_cxx_meta=$php_cxx_meta
521+ b_c_post=$php_c_post
522+ b_cxx_post=$php_cxx_post
523+ b_lo=$php_lo
524+
525+
526+ old_IFS=$IFS
527+ for ac_src in varfilter.c; do
528+
529+ IFS=.
530+ set $ac_src
531+ ac_obj=$1
532+ IFS=$old_IFS
533+
534+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
535+
536+ case $ac_src in
537+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
538+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
539+ esac
540+
541+ cat >>Makefile.objects<<EOF
542+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
543+ $ac_comp
544+EOF
545+ done
546+
547+
548+ EXT_STATIC="$EXT_STATIC varfilter"
549+ else
550+
551+
552+ case ext/varfilter in
553+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
554+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
555+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
556+ esac
557+
558+
559+
560+ b_c_pre=$php_c_pre
561+ b_cxx_pre=$php_cxx_pre
562+ b_c_meta=$php_c_meta
563+ b_cxx_meta=$php_cxx_meta
564+ b_c_post=$php_c_post
565+ b_cxx_post=$php_cxx_post
566+ b_lo=$php_lo
567+
568+
569+ old_IFS=$IFS
570+ for ac_src in varfilter.c; do
571+
572+ IFS=.
573+ set $ac_src
574+ ac_obj=$1
575+ IFS=$old_IFS
576+
577+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
578+
579+ case $ac_src in
580+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
581+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
582+ esac
583+
584+ cat >>Makefile.objects<<EOF
585+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
586+ $ac_comp
587+EOF
588+ done
589+
590+
591+ fi
592+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
593+ fi
594+
595+ BUILD_DIR="$BUILD_DIR $ext_builddir"
596+
597+
598+fi
599
600
601 echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
602@@ -106554,7 +107032,7 @@
603 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
604 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
605 network.c php_open_temporary_file.c php_logos.c \
606- output.c ; do
607+ output.c hardening_patch.c ; do
608
609 IFS=.
610 set $ac_src
611@@ -106795,7 +107273,7 @@
612 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
613 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
614 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
615- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c; do
616+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c; do
617
618 IFS=.
619 set $ac_src
620diff -Nura php-5.0.5/configure.in hardening-patch-5.0.5-0.4.3/configure.in
621--- php-5.0.5/configure.in 2005-09-05 12:41:12.000000000 +0200
622+++ hardening-patch-5.0.5-0.4.3/configure.in 2005-09-11 23:30:52.000000000 +0200
623@@ -247,7 +247,7 @@
624 sinclude(Zend/acinclude.m4)
625 sinclude(Zend/Zend.m4)
626 sinclude(TSRM/tsrm.m4)
627-
628+sinclude(main/hardening_patch.m4)
629
630
631 divert(2)
632@@ -631,6 +631,7 @@
633 AC_FUNC_ALLOCA
634 dnl PHP_AC_BROKEN_SPRINTF
635 dnl PHP_AC_BROKEN_SNPRINTF
636+PHP_AC_BROKEN_REALPATH
637 PHP_DECLARED_TIMEZONE
638 PHP_TIME_R_TYPE
639 PHP_READDIR_R_TYPE
640@@ -1284,7 +1285,7 @@
641 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
642 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
643 network.c php_open_temporary_file.c php_logos.c \
644- output.c )
645+ output.c hardening_patch.c )
646
647 PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
648 plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c)
649@@ -1311,7 +1312,7 @@
650 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
651 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
652 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
653- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c)
654+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c )
655
656 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
657 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c \
658diff -Nura php-5.0.5/ext/fbsql/php_fbsql.c hardening-patch-5.0.5-0.4.3/ext/fbsql/php_fbsql.c
659--- php-5.0.5/ext/fbsql/php_fbsql.c 2005-02-09 20:32:45.000000000 +0100
660+++ hardening-patch-5.0.5-0.4.3/ext/fbsql/php_fbsql.c 2005-09-11 23:30:52.000000000 +0200
661@@ -1852,8 +1852,24 @@
662 }
663 else if (fbcmdErrorsFound(md))
664 {
665+#if HARDENING_PATCH
666+ char* query_copy;
667+ int i;
668+#endif
669 FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
670 char* emg = fbcemdAllErrorMessages(emd);
671+#if HARDENING_PATCH
672+ query_copy=estrdup(query_copy);
673+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
674+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
675+ efree(query_copy);
676+ if (HG(hphp_sql_bailout_on_error)) {
677+ free(emg);
678+ fbcemdRelease(emd);
679+ result = 0;
680+ zend_bailout();
681+ }
682+#endif
683 if (FB_SQL_G(generateWarnings))
684 {
685 if (emg)
686diff -Nura php-5.0.5/ext/mysql/php_mysql.c hardening-patch-5.0.5-0.4.3/ext/mysql/php_mysql.c
687--- php-5.0.5/ext/mysql/php_mysql.c 2005-04-08 00:23:28.000000000 +0200
688+++ hardening-patch-5.0.5-0.4.3/ext/mysql/php_mysql.c 2005-09-11 23:30:52.000000000 +0200
689@@ -1224,6 +1224,8 @@
690 {
691 php_mysql_conn *mysql;
692 MYSQL_RES *mysql_result;
693+ char *copy_query;
694+ int i;
695
696 ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
697
698@@ -1274,6 +1276,13 @@
699 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
700 }
701 }
702+ copy_query = estrdup(Z_STRVAL_PP(query));
703+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
704+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
705+ efree(copy_query);
706+ if (HG(hphp_sql_bailout_on_error)) {
707+ zend_bailout();
708+ }
709 RETURN_FALSE;
710 }
711 #else
712@@ -1284,6 +1293,13 @@
713 php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
714 }
715 }
716+ copy_query = estrdup(Z_STRVAL_PP(query));
717+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
718+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
719+ efree(copy_query);
720+ if (HG(hphp_sql_bailout_on_error)) {
721+ zend_bailout();
722+ }
723 RETURN_FALSE;
724 }
725 #endif
726diff -Nura php-5.0.5/ext/mysqli/mysqli_nonapi.c hardening-patch-5.0.5-0.4.3/ext/mysqli/mysqli_nonapi.c
727--- php-5.0.5/ext/mysqli/mysqli_nonapi.c 2005-08-06 18:56:06.000000000 +0200
728+++ hardening-patch-5.0.5-0.4.3/ext/mysqli/mysqli_nonapi.c 2005-09-11 23:30:52.000000000 +0200
729@@ -229,6 +229,17 @@
730 if (mysql_real_query(mysql->mysql, query, query_len)) {
731 char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
732 unsigned int s_errno;
733+#if HARDENING_PATCH
734+ char *query_copy = estrdup(query);
735+ int i;
736+
737+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
738+ php_security_log(S_SQL, "MySQLi error: %s - query: %s", mysql->mysql->net.last_errno, query_copy);
739+ efree(query_copy);
740+ if (HG(hphp_sql_bailout_on_error)) {
741+ zend_bailout();
742+ }
743+#endif
744 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
745
746 /* we have to save error information, cause
747@@ -278,6 +289,17 @@
748 MYSQLI_DISABLE_MQ;
749
750 if (mysql_real_query(mysql->mysql, query, query_len)) {
751+#if HARDENING_PATCH
752+ char *query_copy = estrdup(query);
753+ int i;
754+
755+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
756+ php_security_log(S_SQL, "MySQLi error: %s - query: %s", mysql->mysql->net.last_errno, query_copy);
757+ efree(query_copy);
758+ if (HG(hphp_sql_bailout_on_error)) {
759+ zend_bailout();
760+ }
761+#endif
762 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
763 RETURN_FALSE;
764 }
765diff -Nura php-5.0.5/ext/pgsql/pgsql.c hardening-patch-5.0.5-0.4.3/ext/pgsql/pgsql.c
766--- php-5.0.5/ext/pgsql/pgsql.c 2005-07-05 14:47:06.000000000 +0200
767+++ hardening-patch-5.0.5-0.4.3/ext/pgsql/pgsql.c 2005-09-11 23:30:52.000000000 +0200
768@@ -1080,10 +1080,28 @@
769 case PGRES_EMPTY_QUERY:
770 case PGRES_BAD_RESPONSE:
771 case PGRES_NONFATAL_ERROR:
772- case PGRES_FATAL_ERROR:
773- PHP_PQ_ERROR("Query failed: %s", pgsql);
774- PQclear(pgsql_result);
775- RETURN_FALSE;
776+ case PGRES_FATAL_ERROR:
777+ {
778+#if HARDENING_PATCH
779+ int i;
780+ char *query_copy;
781+#endif
782+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
783+ PQclear(pgsql_result);
784+#if HARDENING_PATCH
785+ query_copy = estrdup(Z_STRVAL_PP(query));
786+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
787+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
788+ efree(query_copy);
789+ if (HG(hphp_sql_bailout_on_error)) {
790+ efree(msgbuf);
791+ zend_bailout();
792+ }
793+#endif
794+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
795+ efree(msgbuf);
796+ RETURN_FALSE;
797+ }
798 break;
799 case PGRES_COMMAND_OK: /* successful command that did not return rows */
800 default:
801diff -Nura php-5.0.5/ext/sqlite/sqlite.c hardening-patch-5.0.5-0.4.3/ext/sqlite/sqlite.c
802--- php-5.0.5/ext/sqlite/sqlite.c 2005-06-07 17:38:37.000000000 +0200
803+++ hardening-patch-5.0.5-0.4.3/ext/sqlite/sqlite.c 2005-09-11 23:30:52.000000000 +0200
804@@ -1481,6 +1481,19 @@
805 db->last_err_code = ret;
806
807 if (ret != SQLITE_OK) {
808+#if HARDENING_PATCH
809+ char *query_copy;
810+ int i;
811+
812+ query_copy = estrdup(sql);
813+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
814+ php_security_log(S_SQL, "SQLite error: %s - query: %s", errtext, query_copy);
815+ efree(query_copy);
816+ if (HG(hphp_sql_bailout_on_error)) {
817+ sqlite_freemem(errtext);
818+ zend_bailout();
819+ }
820+#endif
821 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
822 sqlite_freemem(errtext);
823 goto terminate;
824diff -Nura php-5.0.5/ext/standard/array.c hardening-patch-5.0.5-0.4.3/ext/standard/array.c
825--- php-5.0.5/ext/standard/array.c 2005-09-01 14:01:01.000000000 +0200
826+++ hardening-patch-5.0.5-0.4.3/ext/standard/array.c 2005-09-11 23:30:52.000000000 +0200
827@@ -1283,6 +1283,32 @@
828 }
829 }
830 }
831+
832+ if (var_name[0] == 'H') {
833+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
834+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
835+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
836+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
837+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
838+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
839+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
840+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
841+ return 0;
842+ }
843+ } else if (var_name[0] == '_') {
844+ if ((strcmp(var_name, "_COOKIE")==0)||
845+ (strcmp(var_name, "_ENV")==0)||
846+ (strcmp(var_name, "_FILES")==0)||
847+ (strcmp(var_name, "_GET")==0)||
848+ (strcmp(var_name, "_POST")==0)||
849+ (strcmp(var_name, "_REQUEST")==0)||
850+ (strcmp(var_name, "_SESSION")==0)||
851+ (strcmp(var_name, "_SERVER")==0)) {
852+ return 0;
853+ }
854+ } else if (strcmp(var_name, "GLOBALS")==0) {
855+ return 0;
856+ }
857
858 return 1;
859 }
860diff -Nura php-5.0.5/ext/standard/basic_functions.c hardening-patch-5.0.5-0.4.3/ext/standard/basic_functions.c
861--- php-5.0.5/ext/standard/basic_functions.c 2005-08-21 20:36:33.000000000 +0200
862+++ hardening-patch-5.0.5-0.4.3/ext/standard/basic_functions.c 2005-09-11 23:30:52.000000000 +0200
863@@ -142,12 +142,14 @@
864 typedef struct _php_shutdown_function_entry {
865 zval **arguments;
866 int arg_count;
867+ zend_bool created_by_eval;
868 } php_shutdown_function_entry;
869
870 typedef struct _user_tick_function_entry {
871 zval **arguments;
872 int arg_count;
873 int calling;
874+ zend_bool created_by_eval;
875 } user_tick_function_entry;
876
877 /* some prototypes for local functions */
878@@ -189,6 +191,8 @@
879 PHP_FE(get_html_translation_table, NULL)
880 PHP_FE(sha1, NULL)
881 PHP_FE(sha1_file, NULL)
882+ PHP_FE(sha256, NULL)
883+ PHP_FE(sha256_file, NULL)
884 PHP_NAMED_FE(md5,php_if_md5, NULL)
885 PHP_NAMED_FE(md5_file,php_if_md5_file, NULL)
886 PHP_NAMED_FE(crc32,php_if_crc32, NULL)
887@@ -616,7 +620,7 @@
888 PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
889
890 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
891- PHP_FE(realpath, NULL)
892+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
893 #endif
894
895 #ifdef HAVE_FNMATCH
896@@ -2095,6 +2099,13 @@
897 {
898 zval retval;
899 char *function_name = NULL;
900+#if HARDENING_PATCH
901+ zend_uint orig_code_type = EG(in_code_type);
902+
903+ if (shutdown_function_entry->created_by_eval) {
904+ EG(in_code_type) = ZEND_EVAL_CODE;
905+ }
906+#endif
907
908 if (!zend_is_callable(shutdown_function_entry->arguments[0], 0, &function_name)) {
909 php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", function_name);
910@@ -2110,6 +2121,9 @@
911 if (function_name) {
912 efree(function_name);
913 }
914+#if HARDENING_PATCH
915+ EG(in_code_type) = orig_code_type;
916+#endif
917 return 0;
918 }
919
920@@ -2117,6 +2131,13 @@
921 {
922 zval retval;
923 zval *function = tick_fe->arguments[0];
924+#if HARDENING_PATCH
925+ zend_uint orig_code_type = EG(in_code_type);
926+
927+ if (tick_fe->created_by_eval) {
928+ EG(in_code_type) = ZEND_EVAL_CODE;
929+ }
930+#endif
931
932 /* Prevent reentrant calls to the same user ticks function */
933 if (! tick_fe->calling) {
934@@ -2148,6 +2169,9 @@
935
936 tick_fe->calling = 0;
937 }
938+#if HARDENING_PATCH
939+ EG(in_code_type) = orig_code_type;
940+#endif
941 }
942
943 static void run_user_tick_functions(int tick_count)
944@@ -2211,6 +2235,13 @@
945 }
946
947 shutdown_function_entry.arguments = (zval **) safe_emalloc(sizeof(zval *), shutdown_function_entry.arg_count, 0);
948+#if HARDENING_PATCH
949+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
950+ shutdown_function_entry.created_by_eval = 1;
951+ } else {
952+ shutdown_function_entry.created_by_eval = 0;
953+ }
954+#endif
955
956 if (zend_get_parameters_array(ht, shutdown_function_entry.arg_count, shutdown_function_entry.arguments) == FAILURE) {
957 RETURN_FALSE;
958@@ -2794,6 +2825,13 @@
959 }
960
961 tick_fe.arguments = (zval **) safe_emalloc(sizeof(zval *), tick_fe.arg_count, 0);
962+#if HARDENING_PATCH
963+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
964+ tick_fe.created_by_eval = 1;
965+ } else {
966+ tick_fe.created_by_eval = 0;
967+ }
968+#endif
969
970 if (zend_get_parameters_array(ht, tick_fe.arg_count, tick_fe.arguments) == FAILURE) {
971 RETURN_FALSE;
972@@ -3082,6 +3120,35 @@
973 memcpy(new_key, prefix, prefix_len);
974 memcpy(new_key+prefix_len, hash_key->arKey, hash_key->nKeyLength);
975
976+ if (new_key[0] == 'H') {
977+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
978+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
979+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
980+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
981+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
982+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
983+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
984+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
985+ efree(new_key);
986+ return 0;
987+ }
988+ } else if (new_key[0] == '_') {
989+ if ((strcmp(new_key, "_COOKIE")==0)||
990+ (strcmp(new_key, "_ENV")==0)||
991+ (strcmp(new_key, "_FILES")==0)||
992+ (strcmp(new_key, "_GET")==0)||
993+ (strcmp(new_key, "_POST")==0)||
994+ (strcmp(new_key, "_REQUEST")==0)||
995+ (strcmp(new_key, "_SESSION")==0)||
996+ (strcmp(new_key, "_SERVER")==0)) {
997+ efree(new_key);
998+ return 0;
999+ }
1000+ } else if (strcmp(new_key, "GLOBALS")==0) {
1001+ efree(new_key);
1002+ return 0;
1003+ }
1004+
1005 zend_hash_del(&EG(symbol_table), new_key, new_key_len);
1006 ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
1007
1008diff -Nura php-5.0.5/ext/standard/config.m4 hardening-patch-5.0.5-0.4.3/ext/standard/config.m4
1009--- php-5.0.5/ext/standard/config.m4 2004-12-30 08:04:11.000000000 +0100
1010+++ hardening-patch-5.0.5-0.4.3/ext/standard/config.m4 2005-09-11 23:30:52.000000000 +0200
1011@@ -187,7 +187,7 @@
1012 if test "$ac_cv_crypt_blowfish" = "yes"; then
1013 ac_result=1
1014 else
1015- ac_result=0
1016+ ac_result=1
1017 fi
1018 AC_DEFINE_UNQUOTED(PHP_BLOWFISH_CRYPT, $ac_result, [Whether the system supports BlowFish salt])
1019 ])
1020@@ -469,6 +469,6 @@
1021 incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
1022 http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
1023 var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
1024- filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c)
1025+ filters.c proc_open.c sunfuncs.c streamsfuncs.c http.c sha256.c crypt_blowfish.c )
1026
1027 PHP_ADD_MAKEFILE_FRAGMENT
1028diff -Nura php-5.0.5/ext/standard/config.w32 hardening-patch-5.0.5-0.4.3/ext/standard/config.w32
1029--- php-5.0.5/ext/standard/config.w32 2003-12-06 17:04:33.000000000 +0100
1030+++ hardening-patch-5.0.5-0.4.3/ext/standard/config.w32 2005-09-11 23:30:52.000000000 +0200
1031@@ -14,5 +14,5 @@
1032 url_scanner_ex.c ftp_fopen_wrapper.c http_fopen_wrapper.c \
1033 php_fopen_wrapper.c credits.c css.c var_unserializer.c ftok.c sha1.c \
1034 user_filters.c uuencode.c filters.c proc_open.c sunfuncs.c \
1035- streamsfuncs.c http.c", false /* never shared */);
1036+ streamsfuncs.c http.c sha256.c crypt_blowfish.c", false /* never shared */);
1037
1038diff -Nura php-5.0.5/ext/standard/crypt_blowfish.c hardening-patch-5.0.5-0.4.3/ext/standard/crypt_blowfish.c
1039--- php-5.0.5/ext/standard/crypt_blowfish.c 1970-01-01 01:00:00.000000000 +0100
1040+++ hardening-patch-5.0.5-0.4.3/ext/standard/crypt_blowfish.c 2005-09-11 23:30:52.000000000 +0200
1041@@ -0,0 +1,748 @@
1042+/*
1043+ * This code comes from John the Ripper password cracker, with reentrant
1044+ * and crypt(3) interfaces added, but optimizations specific to password
1045+ * cracking removed.
1046+ *
1047+ * Written by Solar Designer <solar at openwall.com> in 1998-2002 and
1048+ * placed in the public domain.
1049+ *
1050+ * There's absolutely no warranty.
1051+ *
1052+ * It is my intent that you should be able to use this on your system,
1053+ * as a part of a software package, or anywhere else to improve security,
1054+ * ensure compatibility, or for any other purpose. I would appreciate
1055+ * it if you give credit where it is due and keep your modifications in
1056+ * the public domain as well, but I don't require that in order to let
1057+ * you place this code and any modifications you make under a license
1058+ * of your choice.
1059+ *
1060+ * This implementation is compatible with OpenBSD bcrypt.c (version 2a)
1061+ * by Niels Provos <provos at citi.umich.edu>, and uses some of his
1062+ * ideas. The password hashing algorithm was designed by David Mazieres
1063+ * <dm at lcs.mit.edu>.
1064+ *
1065+ * There's a paper on the algorithm that explains its design decisions:
1066+ *
1067+ * http://www.usenix.org/events/usenix99/provos.html
1068+ *
1069+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
1070+ * Blowfish library (I can't be sure if I would think of something if I
1071+ * hadn't seen his code).
1072+ */
1073+
1074+#include <string.h>
1075+
1076+#include <errno.h>
1077+#ifndef __set_errno
1078+#define __set_errno(val) errno = (val)
1079+#endif
1080+
1081+#undef __CONST
1082+#ifdef __GNUC__
1083+#define __CONST __const
1084+#else
1085+#define __CONST
1086+#endif
1087+
1088+#ifdef __i386__
1089+#define BF_ASM 0
1090+#define BF_SCALE 1
1091+#elif defined(__alpha__) || defined(__hppa__)
1092+#define BF_ASM 0
1093+#define BF_SCALE 1
1094+#else
1095+#define BF_ASM 0
1096+#define BF_SCALE 0
1097+#endif
1098+
1099+typedef unsigned int BF_word;
1100+
1101+/* Number of Blowfish rounds, this is also hardcoded into a few places */
1102+#define BF_N 16
1103+
1104+typedef BF_word BF_key[BF_N + 2];
1105+
1106+typedef struct {
1107+ BF_word S[4][0x100];
1108+ BF_key P;
1109+} BF_ctx;
1110+
1111+/*
1112+ * Magic IV for 64 Blowfish encryptions that we do at the end.
1113+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
1114+ */
1115+static BF_word BF_magic_w[6] = {
1116+ 0x4F727068, 0x65616E42, 0x65686F6C,
1117+ 0x64657253, 0x63727944, 0x6F756274
1118+};
1119+
1120+/*
1121+ * P-box and S-box tables initialized with digits of Pi.
1122+ */
1123+static BF_ctx BF_init_state = {
1124+ {
1125+ {
1126+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
1127+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
1128+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
1129+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
1130+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
1131+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
1132+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
1133+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
1134+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
1135+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
1136+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
1137+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
1138+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
1139+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
1140+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
1141+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
1142+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
1143+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
1144+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
1145+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
1146+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
1147+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
1148+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
1149+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
1150+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
1151+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
1152+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
1153+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
1154+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
1155+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
1156+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
1157+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
1158+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
1159+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
1160+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
1161+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
1162+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
1163+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
1164+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
1165+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
1166+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
1167+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
1168+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
1169+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
1170+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
1171+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
1172+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
1173+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
1174+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
1175+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
1176+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
1177+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
1178+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
1179+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
1180+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
1181+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
1182+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
1183+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
1184+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
1185+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
1186+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
1187+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
1188+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
1189+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
1190+ }, {
1191+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
1192+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
1193+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
1194+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
1195+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
1196+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
1197+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
1198+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
1199+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
1200+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
1201+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
1202+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
1203+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
1204+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
1205+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
1206+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
1207+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
1208+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
1209+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
1210+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
1211+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
1212+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
1213+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
1214+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
1215+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
1216+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
1217+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
1218+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
1219+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
1220+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
1221+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
1222+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
1223+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
1224+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
1225+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
1226+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
1227+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
1228+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
1229+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
1230+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
1231+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
1232+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
1233+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
1234+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
1235+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
1236+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
1237+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
1238+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
1239+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
1240+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
1241+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
1242+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
1243+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
1244+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
1245+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
1246+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
1247+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
1248+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
1249+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
1250+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
1251+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
1252+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
1253+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
1254+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
1255+ }, {
1256+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
1257+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
1258+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
1259+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
1260+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
1261+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
1262+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
1263+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
1264+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
1265+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
1266+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
1267+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
1268+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
1269+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
1270+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
1271+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
1272+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
1273+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
1274+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
1275+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
1276+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
1277+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
1278+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
1279+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
1280+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
1281+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
1282+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
1283+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
1284+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
1285+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
1286+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
1287+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
1288+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
1289+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
1290+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
1291+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
1292+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
1293+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
1294+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
1295+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
1296+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
1297+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
1298+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
1299+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
1300+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
1301+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
1302+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
1303+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
1304+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
1305+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
1306+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
1307+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
1308+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
1309+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
1310+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
1311+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
1312+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
1313+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
1314+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
1315+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
1316+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
1317+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
1318+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
1319+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
1320+ }, {
1321+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
1322+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
1323+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
1324+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
1325+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
1326+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
1327+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
1328+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
1329+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
1330+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
1331+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
1332+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
1333+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
1334+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
1335+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
1336+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
1337+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
1338+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
1339+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
1340+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
1341+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
1342+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
1343+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
1344+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
1345+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
1346+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
1347+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
1348+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
1349+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
1350+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
1351+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
1352+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
1353+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
1354+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
1355+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
1356+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
1357+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
1358+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
1359+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
1360+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
1361+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
1362+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
1363+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
1364+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
1365+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
1366+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
1367+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
1368+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
1369+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
1370+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
1371+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
1372+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
1373+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
1374+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
1375+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
1376+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
1377+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
1378+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
1379+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
1380+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
1381+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
1382+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
1383+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
1384+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
1385+ }
1386+ }, {
1387+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
1388+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
1389+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
1390+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
1391+ 0x9216d5d9, 0x8979fb1b
1392+ }
1393+};
1394+
1395+static unsigned char BF_itoa64[64 + 1] =
1396+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1397+
1398+static unsigned char BF_atoi64[0x60] = {
1399+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
1400+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
1401+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
1402+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
1403+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
1404+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
1405+};
1406+
1407+/*
1408+ * This may be optimized out if built with function inlining and no BF_ASM.
1409+ */
1410+static void clean(void *data, int size)
1411+{
1412+#if BF_ASM
1413+ extern void _BF_clean(void *data);
1414+#endif
1415+ memset(data, 0, size);
1416+#if BF_ASM
1417+ _BF_clean(data);
1418+#endif
1419+}
1420+
1421+#define BF_safe_atoi64(dst, src) \
1422+{ \
1423+ tmp = (unsigned char)(src); \
1424+ if (tmp == '$') break; \
1425+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
1426+ tmp = BF_atoi64[tmp]; \
1427+ if (tmp > 63) return -1; \
1428+ (dst) = tmp; \
1429+}
1430+
1431+static int BF_decode(BF_word *dst, __CONST char *src, int size)
1432+{
1433+ unsigned char *dptr = (unsigned char *)dst;
1434+ unsigned char *end = dptr + size;
1435+ unsigned char *sptr = (unsigned char *)src;
1436+ unsigned int tmp, c1, c2, c3, c4;
1437+
1438+ do {
1439+ BF_safe_atoi64(c1, *sptr++);
1440+ BF_safe_atoi64(c2, *sptr++);
1441+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
1442+ if (dptr >= end) break;
1443+
1444+ BF_safe_atoi64(c3, *sptr++);
1445+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
1446+ if (dptr >= end) break;
1447+
1448+ BF_safe_atoi64(c4, *sptr++);
1449+ *dptr++ = ((c3 & 0x03) << 6) | c4;
1450+ } while (dptr < end);
1451+
1452+ while (dptr < end)
1453+ *dptr++ = 0;
1454+
1455+ return 0;
1456+}
1457+
1458+static void BF_encode(char *dst, __CONST BF_word *src, int size)
1459+{
1460+ unsigned char *sptr = (unsigned char *)src;
1461+ unsigned char *end = sptr + size;
1462+ unsigned char *dptr = (unsigned char *)dst;
1463+ unsigned int c1, c2;
1464+
1465+ do {
1466+ c1 = *sptr++;
1467+ *dptr++ = BF_itoa64[c1 >> 2];
1468+ c1 = (c1 & 0x03) << 4;
1469+ if (sptr >= end) {
1470+ *dptr++ = BF_itoa64[c1];
1471+ break;
1472+ }
1473+
1474+ c2 = *sptr++;
1475+ c1 |= c2 >> 4;
1476+ *dptr++ = BF_itoa64[c1];
1477+ c1 = (c2 & 0x0f) << 2;
1478+ if (sptr >= end) {
1479+ *dptr++ = BF_itoa64[c1];
1480+ break;
1481+ }
1482+
1483+ c2 = *sptr++;
1484+ c1 |= c2 >> 6;
1485+ *dptr++ = BF_itoa64[c1];
1486+ *dptr++ = BF_itoa64[c2 & 0x3f];
1487+ } while (sptr < end);
1488+}
1489+
1490+static void BF_swap(BF_word *x, int count)
1491+{
1492+ static int endianness_check = 1;
1493+ char *is_little_endian = (char *)&endianness_check;
1494+ BF_word tmp;
1495+
1496+ if (*is_little_endian)
1497+ do {
1498+ tmp = *x;
1499+ tmp = (tmp << 16) | (tmp >> 16);
1500+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
1501+ } while (--count);
1502+}
1503+
1504+#if BF_SCALE
1505+/* Architectures which can shift addresses left by 2 bits with no extra cost */
1506+#define BF_ROUND(L, R, N) \
1507+ tmp1 = L & 0xFF; \
1508+ tmp2 = L >> 8; \
1509+ tmp2 &= 0xFF; \
1510+ tmp3 = L >> 16; \
1511+ tmp3 &= 0xFF; \
1512+ tmp4 = L >> 24; \
1513+ tmp1 = data.ctx.S[3][tmp1]; \
1514+ tmp2 = data.ctx.S[2][tmp2]; \
1515+ tmp3 = data.ctx.S[1][tmp3]; \
1516+ tmp3 += data.ctx.S[0][tmp4]; \
1517+ tmp3 ^= tmp2; \
1518+ R ^= data.ctx.P[N + 1]; \
1519+ tmp3 += tmp1; \
1520+ R ^= tmp3;
1521+#else
1522+/* Architectures with no complicated addressing modes supported */
1523+#define BF_INDEX(S, i) \
1524+ (*((BF_word *)(((unsigned char *)S) + (i))))
1525+#define BF_ROUND(L, R, N) \
1526+ tmp1 = L & 0xFF; \
1527+ tmp1 <<= 2; \
1528+ tmp2 = L >> 6; \
1529+ tmp2 &= 0x3FC; \
1530+ tmp3 = L >> 14; \
1531+ tmp3 &= 0x3FC; \
1532+ tmp4 = L >> 22; \
1533+ tmp4 &= 0x3FC; \
1534+ tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
1535+ tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
1536+ tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
1537+ tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
1538+ tmp3 ^= tmp2; \
1539+ R ^= data.ctx.P[N + 1]; \
1540+ tmp3 += tmp1; \
1541+ R ^= tmp3;
1542+#endif
1543+
1544+/*
1545+ * Encrypt one block, BF_N is hardcoded here.
1546+ */
1547+#define BF_ENCRYPT \
1548+ L ^= data.ctx.P[0]; \
1549+ BF_ROUND(L, R, 0); \
1550+ BF_ROUND(R, L, 1); \
1551+ BF_ROUND(L, R, 2); \
1552+ BF_ROUND(R, L, 3); \
1553+ BF_ROUND(L, R, 4); \
1554+ BF_ROUND(R, L, 5); \
1555+ BF_ROUND(L, R, 6); \
1556+ BF_ROUND(R, L, 7); \
1557+ BF_ROUND(L, R, 8); \
1558+ BF_ROUND(R, L, 9); \
1559+ BF_ROUND(L, R, 10); \
1560+ BF_ROUND(R, L, 11); \
1561+ BF_ROUND(L, R, 12); \
1562+ BF_ROUND(R, L, 13); \
1563+ BF_ROUND(L, R, 14); \
1564+ BF_ROUND(R, L, 15); \
1565+ tmp4 = R; \
1566+ R = L; \
1567+ L = tmp4 ^ data.ctx.P[BF_N + 1];
1568+
1569+#if BF_ASM
1570+#define BF_body() \
1571+ _BF_body_r(&data.ctx);
1572+#else
1573+#define BF_body() \
1574+ L = R = 0; \
1575+ ptr = data.ctx.P; \
1576+ do { \
1577+ ptr += 2; \
1578+ BF_ENCRYPT; \
1579+ *(ptr - 2) = L; \
1580+ *(ptr - 1) = R; \
1581+ } while (ptr < &data.ctx.P[BF_N + 2]); \
1582+\
1583+ ptr = data.ctx.S[0]; \
1584+ do { \
1585+ ptr += 2; \
1586+ BF_ENCRYPT; \
1587+ *(ptr - 2) = L; \
1588+ *(ptr - 1) = R; \
1589+ } while (ptr < &data.ctx.S[3][0xFF]);
1590+#endif
1591+
1592+static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial)
1593+{
1594+ __CONST char *ptr = key;
1595+ int i, j;
1596+ BF_word tmp;
1597+
1598+ for (i = 0; i < BF_N + 2; i++) {
1599+ tmp = 0;
1600+ for (j = 0; j < 4; j++) {
1601+ tmp <<= 8;
1602+ tmp |= *ptr;
1603+
1604+ if (!*ptr) ptr = key; else ptr++;
1605+ }
1606+
1607+ expanded[i] = tmp;
1608+ initial[i] = BF_init_state.P[i] ^ tmp;
1609+ }
1610+}
1611+
1612+char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
1613+ char *output, int size)
1614+{
1615+#if BF_ASM
1616+ extern void _BF_body_r(BF_ctx *ctx);
1617+#endif
1618+ struct {
1619+ BF_ctx ctx;
1620+ BF_key expanded_key;
1621+ union {
1622+ BF_word salt[4];
1623+ BF_word output[6];
1624+ } binary;
1625+ } data;
1626+ BF_word L, R;
1627+ BF_word tmp1, tmp2, tmp3, tmp4;
1628+ BF_word *ptr;
1629+ BF_word count;
1630+ int i;
1631+
1632+ if (size < 7 + 22 + 31 + 1) {
1633+ __set_errno(ERANGE);
1634+ return NULL;
1635+ }
1636+
1637+ if (setting[0] != '$' ||
1638+ setting[1] != '2' ||
1639+ setting[2] != 'a' ||
1640+ setting[3] != '$' ||
1641+ setting[4] < '0' || setting[4] > '3' ||
1642+ setting[5] < '0' || setting[5] > '9' ||
1643+ setting[6] != '$') {
1644+ __set_errno(EINVAL);
1645+ return NULL;
1646+ }
1647+
1648+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
1649+ if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) {
1650+ clean(data.binary.salt, sizeof(data.binary.salt));
1651+ __set_errno(EINVAL);
1652+ return NULL;
1653+ }
1654+
1655+ BF_swap(data.binary.salt, 4);
1656+
1657+ BF_set_key(key, data.expanded_key, data.ctx.P);
1658+
1659+ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
1660+
1661+ L = R = 0;
1662+ for (i = 0; i < BF_N + 2; i += 2) {
1663+ L ^= data.binary.salt[i & 2];
1664+ R ^= data.binary.salt[(i & 2) + 1];
1665+ BF_ENCRYPT;
1666+ data.ctx.P[i] = L;
1667+ data.ctx.P[i + 1] = R;
1668+ }
1669+
1670+ ptr = data.ctx.S[0];
1671+ do {
1672+ ptr += 4;
1673+ L ^= data.binary.salt[(BF_N + 2) & 3];
1674+ R ^= data.binary.salt[(BF_N + 3) & 3];
1675+ BF_ENCRYPT;
1676+ *(ptr - 4) = L;
1677+ *(ptr - 3) = R;
1678+
1679+ L ^= data.binary.salt[(BF_N + 4) & 3];
1680+ R ^= data.binary.salt[(BF_N + 5) & 3];
1681+ BF_ENCRYPT;
1682+ *(ptr - 2) = L;
1683+ *(ptr - 1) = R;
1684+ } while (ptr < &data.ctx.S[3][0xFF]);
1685+
1686+ do {
1687+ data.ctx.P[0] ^= data.expanded_key[0];
1688+ data.ctx.P[1] ^= data.expanded_key[1];
1689+ data.ctx.P[2] ^= data.expanded_key[2];
1690+ data.ctx.P[3] ^= data.expanded_key[3];
1691+ data.ctx.P[4] ^= data.expanded_key[4];
1692+ data.ctx.P[5] ^= data.expanded_key[5];
1693+ data.ctx.P[6] ^= data.expanded_key[6];
1694+ data.ctx.P[7] ^= data.expanded_key[7];
1695+ data.ctx.P[8] ^= data.expanded_key[8];
1696+ data.ctx.P[9] ^= data.expanded_key[9];
1697+ data.ctx.P[10] ^= data.expanded_key[10];
1698+ data.ctx.P[11] ^= data.expanded_key[11];
1699+ data.ctx.P[12] ^= data.expanded_key[12];
1700+ data.ctx.P[13] ^= data.expanded_key[13];
1701+ data.ctx.P[14] ^= data.expanded_key[14];
1702+ data.ctx.P[15] ^= data.expanded_key[15];
1703+ data.ctx.P[16] ^= data.expanded_key[16];
1704+ data.ctx.P[17] ^= data.expanded_key[17];
1705+
1706+ BF_body();
1707+
1708+ tmp1 = data.binary.salt[0];
1709+ tmp2 = data.binary.salt[1];
1710+ tmp3 = data.binary.salt[2];
1711+ tmp4 = data.binary.salt[3];
1712+ data.ctx.P[0] ^= tmp1;
1713+ data.ctx.P[1] ^= tmp2;
1714+ data.ctx.P[2] ^= tmp3;
1715+ data.ctx.P[3] ^= tmp4;
1716+ data.ctx.P[4] ^= tmp1;
1717+ data.ctx.P[5] ^= tmp2;
1718+ data.ctx.P[6] ^= tmp3;
1719+ data.ctx.P[7] ^= tmp4;
1720+ data.ctx.P[8] ^= tmp1;
1721+ data.ctx.P[9] ^= tmp2;
1722+ data.ctx.P[10] ^= tmp3;
1723+ data.ctx.P[11] ^= tmp4;
1724+ data.ctx.P[12] ^= tmp1;
1725+ data.ctx.P[13] ^= tmp2;
1726+ data.ctx.P[14] ^= tmp3;
1727+ data.ctx.P[15] ^= tmp4;
1728+ data.ctx.P[16] ^= tmp1;
1729+ data.ctx.P[17] ^= tmp2;
1730+
1731+ BF_body();
1732+ } while (--count);
1733+
1734+ for (i = 0; i < 6; i += 2) {
1735+ L = BF_magic_w[i];
1736+ R = BF_magic_w[i + 1];
1737+
1738+ count = 64;
1739+ do {
1740+ BF_ENCRYPT;
1741+ } while (--count);
1742+
1743+ data.binary.output[i] = L;
1744+ data.binary.output[i + 1] = R;
1745+ }
1746+
1747+ memcpy(output, setting, 7 + 22 - 1);
1748+ output[7 + 22 - 1] = BF_itoa64[(int)
1749+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
1750+
1751+/* This has to be bug-compatible with the original implementation, so
1752+ * only encode 23 of the 24 bytes. :-) */
1753+ BF_swap(data.binary.output, 6);
1754+ BF_encode(&output[7 + 22], data.binary.output, 23);
1755+ output[7 + 22 + 31] = '\0';
1756+
1757+/* Overwrite the most obvious sensitive data we have on the stack. Note
1758+ * that this does not guarantee there's no sensitive data left on the
1759+ * stack and/or in registers; I'm not aware of portable code that does. */
1760+ clean(&data, sizeof(data));
1761+
1762+ return output;
1763+}
1764+
1765+char *_crypt_gensalt_blowfish_rn(unsigned long count,
1766+ __CONST char *input, int size, char *output, int output_size)
1767+{
1768+ if (size < 16 || output_size < 7 + 22 + 1 ||
1769+ (count && (count < 4 || count > 31))) {
1770+ if (output_size > 0) output[0] = '\0';
1771+ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
1772+ return NULL;
1773+ }
1774+
1775+ if (!count) count = 5;
1776+
1777+ output[0] = '$';
1778+ output[1] = '2';
1779+ output[2] = 'a';
1780+ output[3] = '$';
1781+ output[4] = '0' + count / 10;
1782+ output[5] = '0' + count % 10;
1783+ output[6] = '$';
1784+
1785+ BF_encode(&output[7], (BF_word *)input, 16);
1786+ output[7 + 22] = '\0';
1787+
1788+ return output;
1789+}
1790diff -Nura php-5.0.5/ext/standard/crypt.c hardening-patch-5.0.5-0.4.3/ext/standard/crypt.c
1791--- php-5.0.5/ext/standard/crypt.c 2004-02-12 20:05:41.000000000 +0100
1792+++ hardening-patch-5.0.5-0.4.3/ext/standard/crypt.c 2005-09-12 18:13:10.000000000 +0200
1793@@ -100,6 +100,8 @@
1794 return SUCCESS;
1795 }
1796
1797+char *_crypt_blowfish_rn(char *key, char *setting, char *output, int size);
1798+char *_crypt_gensalt_blowfish_rn(unsigned long count, char *input, int size, char *output, int output_size);
1799
1800 static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1801
1802@@ -135,7 +137,14 @@
1803
1804 /* The automatic salt generation only covers standard DES and md5-crypt */
1805 if(!*salt) {
1806-#if PHP_MD5_CRYPT
1807+#if PHP_BLOWFISH_CRYPT
1808+ char randat[16];
1809+ int i;
1810+
1811+ for (i=0; i<16; i++) randat[i] = PHP_CRYPT_RAND;
1812+
1813+ _crypt_gensalt_blowfish_rn(5, randat, sizeof(randat), salt, sizeof(salt));
1814+#elif PHP_MD5_CRYPT
1815 strcpy(salt, "$1$");
1816 php_to64(&salt[3], PHP_CRYPT_RAND, 4);
1817 php_to64(&salt[7], PHP_CRYPT_RAND, 4);
1818@@ -145,8 +154,24 @@
1819 salt[2] = '\0';
1820 #endif
1821 }
1822-
1823- RETVAL_STRING(crypt(str, salt), 1);
1824+
1825+ if (salt[0] == '$' &&
1826+ salt[1] == '2' &&
1827+ salt[2] == 'a' &&
1828+ salt[3] == '$' &&
1829+ salt[4] >= '0' && salt[4] <= '3' &&
1830+ salt[5] >= '0' && salt[5] <= '9' &&
1831+ salt[6] == '$') {
1832+
1833+ char output[PHP_MAX_SALT_LEN+1];
1834+
1835+ output[0] = 0;
1836+ _crypt_blowfish_rn(str, salt, output, sizeof(output));
1837+ RETVAL_STRING(output, 1);
1838+
1839+ } else {
1840+ RETVAL_STRING(crypt(str, salt), 1);
1841+ }
1842 }
1843 /* }}} */
1844 #endif
1845diff -Nura php-5.0.5/ext/standard/dl.c hardening-patch-5.0.5-0.4.3/ext/standard/dl.c
1846--- php-5.0.5/ext/standard/dl.c 2005-05-04 15:48:01.000000000 +0200
1847+++ hardening-patch-5.0.5-0.4.3/ext/standard/dl.c 2005-09-11 23:30:52.000000000 +0200
1848@@ -159,8 +159,35 @@
1849 RETURN_FALSE;
1850 }
1851 module_entry = get_module();
1852+
1853+ /* check if Hardening-Patch is installed */
1854+ if (module_entry->zend_api < 1000000000) {
1855+ php_error_docref(NULL TSRMLS_CC, error_type,
1856+ "%s: Unable to initialize module\n"
1857+ "Module compiled without Hardening-Patch, module API=%d, debug=%d, thread-safety=%d\n"
1858+ "PHP compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
1859+ "These options need to match\n",
1860+ module_entry->name, module_entry->zend_api, module_entry->zend_debug, module_entry->zts,
1861+ HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS);
1862+ DL_UNLOAD(handle);
1863+ RETURN_FALSE;
1864+ }
1865+
1866+ /* check if correct Hardening-Patch is installed */
1867+ if (module_entry->zend_api != HARDENING_PATCH_ZEND_MODULE_API_NO) {
1868+ php_error_docref(NULL TSRMLS_CC, error_type,
1869+ "%s: Unable to initialize module\n"
1870+ "Module compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
1871+ "PHP compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
1872+ "These options need to match\n",
1873+ module_entry->name, module_entry->zend_api, module_entry->real_zend_api, module_entry->zend_debug, module_entry->zts,
1874+ HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS);
1875+ DL_UNLOAD(handle);
1876+ RETURN_FALSE;
1877+ }
1878+
1879 if ((module_entry->zend_debug != ZEND_DEBUG) || (module_entry->zts != USING_ZTS)
1880- || (module_entry->zend_api != ZEND_MODULE_API_NO)) {
1881+ || (module_entry->real_zend_api != ZEND_MODULE_API_NO)) {
1882 /* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */
1883 struct pre_4_1_0_module_entry {
1884 char *name;
1885@@ -194,7 +221,7 @@
1886 zts = ((struct pre_4_1_0_module_entry *)module_entry)->zts;
1887 } else {
1888 name = module_entry->name;
1889- zend_api = module_entry->zend_api;
1890+ zend_api = module_entry->real_zend_api;
1891 zend_debug = module_entry->zend_debug;
1892 zts = module_entry->zts;
1893 }
1894diff -Nura php-5.0.5/ext/standard/file.c hardening-patch-5.0.5-0.4.3/ext/standard/file.c
1895--- php-5.0.5/ext/standard/file.c 2005-04-06 15:59:48.000000000 +0200
1896+++ hardening-patch-5.0.5-0.4.3/ext/standard/file.c 2005-09-11 23:30:52.000000000 +0200
1897@@ -2044,7 +2044,7 @@
1898 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
1899 /* {{{ proto string realpath(string path)
1900 Return the resolved path */
1901-PHP_FUNCTION(realpath)
1902+PHP_FUNCTION(real_path)
1903 {
1904 zval **path;
1905 char resolved_path_buff[MAXPATHLEN];
1906diff -Nura php-5.0.5/ext/standard/file.h hardening-patch-5.0.5-0.4.3/ext/standard/file.h
1907--- php-5.0.5/ext/standard/file.h 2005-07-15 11:29:18.000000000 +0200
1908+++ hardening-patch-5.0.5-0.4.3/ext/standard/file.h 2005-09-11 23:30:52.000000000 +0200
1909@@ -60,7 +60,7 @@
1910 PHP_FUNCTION(fd_set);
1911 PHP_FUNCTION(fd_isset);
1912 #if (!defined(__BEOS__) && HAVE_REALPATH) || defined(ZTS)
1913-PHP_FUNCTION(realpath);
1914+PHP_FUNCTION(real_path);
1915 PHP_FUNCTION(fnmatch);
1916 #endif
1917 PHP_NAMED_FUNCTION(php_if_ftruncate);
1918diff -Nura php-5.0.5/ext/standard/head.c hardening-patch-5.0.5-0.4.3/ext/standard/head.c
1919--- php-5.0.5/ext/standard/head.c 2005-06-28 16:49:14.000000000 +0200
1920+++ hardening-patch-5.0.5-0.4.3/ext/standard/head.c 2005-09-11 23:30:52.000000000 +0200
1921@@ -40,10 +40,31 @@
1922 {
1923 zend_bool rep = 1;
1924 sapi_header_line ctr = {0};
1925+#if HARDENING_PATCH
1926+ int i;
1927+#endif
1928
1929 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
1930 &ctr.line_len, &rep, &ctr.response_code) == FAILURE)
1931 return;
1932+
1933+#if HARDENING_PATCH
1934+ if (!HG(hphp_multiheader)) {
1935+ for (i=0; i<ctr.line_len; i++) {
1936+ if (ctr.line[i]==0) {
1937+ php_security_log(S_MISC, "header(): headerline truncated by an ASCII-NUL char");
1938+ ctr.line_len=i;
1939+ break;
1940+ } else if (ctr.line[i]=='\n') {
1941+ if (i>0 && (i<ctr.line_len-1) && (ctr.line[i+1]==' ' || ctr.line[i+1]=='\t')) {
1942+ continue;
1943+ }
1944+ php_security_log(S_MISC, "header(): headerline contains more than one header");
1945+ ctr.line_len=i;
1946+ }
1947+ }
1948+ }
1949+#endif
1950
1951 sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
1952 }
1953diff -Nura php-5.0.5/ext/standard/info.c hardening-patch-5.0.5-0.4.3/ext/standard/info.c
1954--- php-5.0.5/ext/standard/info.c 2005-08-16 02:25:46.000000000 +0200
1955+++ hardening-patch-5.0.5-0.4.3/ext/standard/info.c 2005-09-11 23:30:52.000000000 +0200
1956@@ -409,7 +409,7 @@
1957
1958 if (flag & PHP_INFO_GENERAL) {
1959 char *zend_version = get_zend_version();
1960- char temp_api[10];
1961+ char temp_api[11];
1962 char *logo_guid;
1963
1964 php_uname = php_get_uname('a');
1965@@ -432,11 +432,22 @@
1966 PUTS("\" alt=\"PHP Logo\" /></a>");
1967 }
1968
1969+#if HARDENING_PATCH
1970+ if (!sapi_module.phpinfo_as_text) {
1971+ php_printf("<h1 class=\"p\">PHP Version %s with Hardening-Patch %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
1972+ } else {
1973+ char temp_ver[40];
1974+
1975+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
1976+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
1977+ }
1978+#else
1979 if (!sapi_module.phpinfo_as_text) {
1980 php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
1981 } else {
1982 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1983- }
1984+ }
1985+#endif
1986 php_info_print_box_end();
1987 php_info_print_table_start();
1988 php_info_print_table_row(2, "System", php_uname );
1989diff -Nura php-5.0.5/ext/standard/php_standard.h hardening-patch-5.0.5-0.4.3/ext/standard/php_standard.h
1990--- php-5.0.5/ext/standard/php_standard.h 2004-01-08 18:32:51.000000000 +0100
1991+++ hardening-patch-5.0.5-0.4.3/ext/standard/php_standard.h 2005-09-11 23:30:52.000000000 +0200
1992@@ -28,6 +28,7 @@
1993 #include "php_mail.h"
1994 #include "md5.h"
1995 #include "sha1.h"
1996+#include "sha256.h"
1997 #include "html.h"
1998 #include "exec.h"
1999 #include "file.h"
2000diff -Nura php-5.0.5/ext/standard/sha256.c hardening-patch-5.0.5-0.4.3/ext/standard/sha256.c
2001--- php-5.0.5/ext/standard/sha256.c 1970-01-01 01:00:00.000000000 +0100
2002+++ hardening-patch-5.0.5-0.4.3/ext/standard/sha256.c 2005-09-11 23:30:52.000000000 +0200
2003@@ -0,0 +1,398 @@
2004+/*
2005+ +----------------------------------------------------------------------+
2006+ | PHP Version 5 |
2007+ +----------------------------------------------------------------------+
2008+ | Copyright (c) 1997-2004 The PHP Group |
2009+ +----------------------------------------------------------------------+
2010+ | This source file is subject to version 3.0 of the PHP license, |
2011+ | that is bundled with this package in the file LICENSE, and is |
2012+ | available through the world-wide-web at the following url: |
2013+ | http://www.php.net/license/3_0.txt. |
2014+ | If you did not receive a copy of the PHP license and are unable to |
2015+ | obtain it through the world-wide-web, please send a note to |
2016+ | license@php.net so we can mail you a copy immediately. |
2017+ +----------------------------------------------------------------------+
2018+ | Author: Stefan Esser <sesser@php.net> |
2019+ +----------------------------------------------------------------------+
2020+*/
2021+
2022+/* $Id: sha256.c,v 1.9 2004/01/08 08:17:34 andi Exp $ */
2023+
2024+#include <stdio.h>
2025+#include "php.h"
2026+
2027+/* This code is heavily based on the PHP md5/sha1 implementations */
2028+
2029+#include "sha256.h"
2030+
2031+PHPAPI void make_sha256_digest(char *sha256str, unsigned char *digest)
2032+{
2033+ int i;
2034+
2035+ for (i = 0; i < 32; i++) {
2036+ sprintf(sha256str, "%02x", digest[i]);
2037+ sha256str += 2;
2038+ }
2039+
2040+ *sha256str = '\0';
2041+}
2042+
2043+/* {{{ proto string sha256(string str [, bool raw_output])
2044+ Calculate the sha256 hash of a string */
2045+PHP_FUNCTION(sha256)
2046+{
2047+ char *arg;
2048+ int arg_len;
2049+ zend_bool raw_output = 0;
2050+ char sha256str[65];
2051+ PHP_SHA256_CTX context;
2052+ unsigned char digest[32];
2053+
2054+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
2055+ return;
2056+ }
2057+
2058+ sha256str[0] = '\0';
2059+ PHP_SHA256Init(&context);
2060+ PHP_SHA256Update(&context, arg, arg_len);
2061+ PHP_SHA256Final(digest, &context);
2062+ if (raw_output) {
2063+ RETURN_STRINGL(digest, 32, 1);
2064+ } else {
2065+ make_sha256_digest(sha256str, digest);
2066+ RETVAL_STRING(sha256str, 1);
2067+ }
2068+
2069+}
2070+
2071+/* }}} */
2072+
2073+/* {{{ proto string sha256_file(string filename [, bool raw_output])
2074+ Calculate the sha256 hash of given filename */
2075+PHP_FUNCTION(sha256_file)
2076+{
2077+ char *arg;
2078+ int arg_len;
2079+ zend_bool raw_output = 0;
2080+ char sha256str[65];
2081+ unsigned char buf[1024];
2082+ unsigned char digest[32];
2083+ PHP_SHA256_CTX context;
2084+ int n;
2085+ FILE *fp;
2086+
2087+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
2088+ return;
2089+ }
2090+
2091+ if (PG(safe_mode) && (!php_checkuid(arg, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
2092+ RETURN_FALSE;
2093+ }
2094+
2095+ if (php_check_open_basedir(arg TSRMLS_CC)) {
2096+ RETURN_FALSE;
2097+ }
2098+
2099+ if ((fp = VCWD_FOPEN(arg, "rb")) == NULL) {
2100+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open file");
2101+ RETURN_FALSE;
2102+ }
2103+
2104+ PHP_SHA256Init(&context);
2105+
2106+ while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
2107+ PHP_SHA256Update(&context, buf, n);
2108+ }
2109+
2110+ PHP_SHA256Final(digest, &context);
2111+
2112+ if (ferror(fp)) {
2113+ fclose(fp);
2114+ RETURN_FALSE;
2115+ }
2116+
2117+ fclose(fp);
2118+
2119+ if (raw_output) {
2120+ RETURN_STRINGL(digest, 32, 1);
2121+ } else {
2122+ make_sha256_digest(sha256str, digest);
2123+ RETVAL_STRING(sha256str, 1);
2124+ }
2125+}
2126+/* }}} */
2127+
2128+
2129+static void SHA256Transform(php_uint32[8], const unsigned char[64]);
2130+static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
2131+static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
2132+
2133+static unsigned char PADDING[64] =
2134+{
2135+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2136+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2137+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2138+};
2139+
2140+/* F, G, H and I are basic SHA256 functions.
2141+ */
2142+#define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22))
2143+#define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x))))
2144+#define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25))
2145+#define I(x, y, z) (((x) & (y)) | ((~x) & z))
2146+
2147+/* ROTATE_RIGHT rotates x right n bits.
2148+ */
2149+#define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
2150+
2151+/* W[i]
2152+ */
2153+#define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \
2154+ tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \
2155+ (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) )
2156+
2157+/* ROUND function of sha256
2158+ */
2159+
2160+#define ROUND(a,b,c,d,e,f,g,h,w,k) { \
2161+ t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \
2162+ (h) = F((a)) + G((a), (b), (c)) + t1; \
2163+ (d) += t1; \
2164+ }
2165+
2166+
2167+/* {{{ PHP_SHA256Init
2168+ * SHA256 initialization. Begins an SHA256 operation, writing a new context.
2169+ */
2170+PHPAPI void PHP_SHA256Init(PHP_SHA256_CTX * context)
2171+{
2172+ context->count[0] = context->count[1] = 0;
2173+ /* Load magic initialization constants.
2174+ */
2175+ context->state[0] = 0x6a09e667;
2176+ context->state[1] = 0xbb67ae85;
2177+ context->state[2] = 0x3c6ef372;
2178+ context->state[3] = 0xa54ff53a;
2179+ context->state[4] = 0x510e527f;
2180+ context->state[5] = 0x9b05688c;
2181+ context->state[6] = 0x1f83d9ab;
2182+ context->state[7] = 0x5be0cd19;
2183+}
2184+/* }}} */
2185+
2186+/* {{{ PHP_SHA256Update
2187+ SHA256 block update operation. Continues an SHA256 message-digest
2188+ operation, processing another message block, and updating the
2189+ context.
2190+ */
2191+PHPAPI void PHP_SHA256Update(PHP_SHA256_CTX * context, const unsigned char *input,
2192+ unsigned int inputLen)
2193+{
2194+ unsigned int i, index, partLen;
2195+
2196+ /* Compute number of bytes mod 64 */
2197+ index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
2198+
2199+ /* Update number of bits */
2200+ if ((context->count[0] += ((php_uint32) inputLen << 3))
2201+ < ((php_uint32) inputLen << 3))
2202+ context->count[1]++;
2203+ context->count[1] += ((php_uint32) inputLen >> 29);
2204+
2205+ partLen = 64 - index;
2206+
2207+ /* Transform as many times as possible.
2208+ */
2209+ if (inputLen >= partLen) {
2210+ memcpy
2211+ ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
2212+ SHA256Transform(context->state, context->buffer);
2213+
2214+ for (i = partLen; i + 63 < inputLen; i += 64)
2215+ SHA256Transform(context->state, &input[i]);
2216+
2217+ index = 0;
2218+ } else
2219+ i = 0;
2220+
2221+ /* Buffer remaining input */
2222+ memcpy
2223+ ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
2224+ inputLen - i);
2225+}
2226+/* }}} */
2227+
2228+/* {{{ PHP_SHA256Final
2229+ SHA256 finalization. Ends an SHA256 message-digest operation, writing the
2230+ the message digest and zeroizing the context.
2231+ */
2232+PHPAPI void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * context)
2233+{
2234+ unsigned char bits[8];
2235+ unsigned int index, padLen;
2236+
2237+ /* Save number of bits */
2238+ bits[7] = context->count[0] & 0xFF;
2239+ bits[6] = (context->count[0] >> 8) & 0xFF;
2240+ bits[5] = (context->count[0] >> 16) & 0xFF;
2241+ bits[4] = (context->count[0] >> 24) & 0xFF;
2242+ bits[3] = context->count[1] & 0xFF;
2243+ bits[2] = (context->count[1] >> 8) & 0xFF;
2244+ bits[1] = (context->count[1] >> 16) & 0xFF;
2245+ bits[0] = (context->count[1] >> 24) & 0xFF;
2246+
2247+ /* Pad out to 56 mod 64.
2248+ */
2249+ index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
2250+ padLen = (index < 56) ? (56 - index) : (120 - index);
2251+ PHP_SHA256Update(context, PADDING, padLen);
2252+
2253+ /* Append length (before padding) */
2254+ PHP_SHA256Update(context, bits, 8);
2255+
2256+ /* Store state in digest */
2257+ SHA256Encode(digest, context->state, 32);
2258+
2259+ /* Zeroize sensitive information.
2260+ */
2261+ memset((unsigned char*) context, 0, sizeof(*context));
2262+}
2263+/* }}} */
2264+
2265+/* {{{ SHA256Transform
2266+ * SHA256 basic transformation. Transforms state based on block.
2267+ */
2268+static void SHA256Transform(state, block)
2269+php_uint32 state[8];
2270+const unsigned char block[64];
2271+{
2272+ php_uint32 a = state[0], b = state[1], c = state[2];
2273+ php_uint32 d = state[3], e = state[4], f = state[5];
2274+ php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1;
2275+
2276+ SHA256Decode(x, block, 64);
2277+
2278+ ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98)
2279+ ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491)
2280+ ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf)
2281+ ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5)
2282+ ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b)
2283+ ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1)
2284+ ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4)
2285+ ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5)
2286+ ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98)
2287+ ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01)
2288+ ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be)
2289+ ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3)
2290+ ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74)
2291+ ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe)
2292+ ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7)
2293+ ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174)
2294+ ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1)
2295+ ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786)
2296+ ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6)
2297+ ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc)
2298+ ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f)
2299+ ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa)
2300+ ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc)
2301+ ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da)
2302+ ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152)
2303+ ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d)
2304+ ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8)
2305+ ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7)
2306+ ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3)
2307+ ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147)
2308+ ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351)
2309+ ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967)
2310+ ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85)
2311+ ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138)
2312+ ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc)
2313+ ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13)
2314+ ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354)
2315+ ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb)
2316+ ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e)
2317+ ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85)
2318+ ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1)
2319+ ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b)
2320+ ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70)
2321+ ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3)
2322+ ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819)
2323+ ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624)
2324+ ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585)
2325+ ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070)
2326+ ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116)
2327+ ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08)
2328+ ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c)
2329+ ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5)
2330+ ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3)
2331+ ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a)
2332+ ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f)
2333+ ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3)
2334+ ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee)
2335+ ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f)
2336+ ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814)
2337+ ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208)
2338+ ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa)
2339+ ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb)
2340+ ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7)
2341+ ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2)
2342+
2343+ state[0] += a;
2344+ state[1] += b;
2345+ state[2] += c;
2346+ state[3] += d;
2347+ state[4] += e;
2348+ state[5] += f;
2349+ state[6] += g;
2350+ state[7] += h;
2351+
2352+ /* Zeroize sensitive information. */
2353+ memset((unsigned char*) x, 0, sizeof(x));
2354+}
2355+/* }}} */
2356+
2357+/* {{{ SHA256Encode
2358+ Encodes input (php_uint32) into output (unsigned char). Assumes len is
2359+ a multiple of 4.
2360+ */
2361+static void SHA256Encode(output, input, len)
2362+unsigned char *output;
2363+php_uint32 *input;
2364+unsigned int len;
2365+{
2366+ unsigned int i, j;
2367+
2368+ for (i = 0, j = 0; j < len; i++, j += 4) {
2369+ output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
2370+ output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
2371+ output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
2372+ output[j + 3] = (unsigned char) (input[i] & 0xff);
2373+ }
2374+}
2375+/* }}} */
2376+
2377+/* {{{ SHA256Decode
2378+ Decodes input (unsigned char) into output (php_uint32). Assumes len is
2379+ a multiple of 4.
2380+ */
2381+static void SHA256Decode(output, input, len)
2382+php_uint32 *output;
2383+const unsigned char *input;
2384+unsigned int len;
2385+{
2386+ unsigned int i, j;
2387+
2388+ for (i = 0, j = 0; j < len; i++, j += 4)
2389+ output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
2390+ (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
2391+}
2392+/* }}} */
2393+
2394+/*
2395+ * Local variables:
2396+ * tab-width: 4
2397+ * c-basic-offset: 4
2398+ * End:
2399+ * vim600: sw=4 ts=4 fdm=marker
2400+ * vim<600: sw=4 ts=4
2401+ */
2402diff -Nura php-5.0.5/ext/standard/sha256.h hardening-patch-5.0.5-0.4.3/ext/standard/sha256.h
2403--- php-5.0.5/ext/standard/sha256.h 1970-01-01 01:00:00.000000000 +0100
2404+++ hardening-patch-5.0.5-0.4.3/ext/standard/sha256.h 2005-09-11 23:30:52.000000000 +0200
2405@@ -0,0 +1,40 @@
2406+/*
2407+ +----------------------------------------------------------------------+
2408+ | PHP Version 5 |
2409+ +----------------------------------------------------------------------+
2410+ | Copyright (c) 1997-2004 The PHP Group |
2411+ +----------------------------------------------------------------------+
2412+ | This source file is subject to version 3.0 of the PHP license, |
2413+ | that is bundled with this package in the file LICENSE, and is |
2414+ | available through the world-wide-web at the following url: |
2415+ | http://www.php.net/license/3_0.txt. |
2416+ | If you did not receive a copy of the PHP license and are unable to |
2417+ | obtain it through the world-wide-web, please send a note to |
2418+ | license@php.net so we can mail you a copy immediately. |
2419+ +----------------------------------------------------------------------+
2420+ | Author: Stefan Esser <sesser@php.net> |
2421+ +----------------------------------------------------------------------+
2422+*/
2423+
2424+/* $Id: sha256.h,v 1.4 2004/01/08 17:32:52 sniper Exp $ */
2425+
2426+#ifndef SHA256_H
2427+#define SHA256_H
2428+
2429+#include "ext/standard/basic_functions.h"
2430+
2431+/* SHA1 context. */
2432+typedef struct {
2433+ php_uint32 state[8]; /* state (ABCD) */
2434+ php_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */
2435+ unsigned char buffer[64]; /* input buffer */
2436+} PHP_SHA256_CTX;
2437+
2438+PHPAPI void PHP_SHA256Init(PHP_SHA256_CTX *);
2439+PHPAPI void PHP_SHA256Update(PHP_SHA256_CTX *, const unsigned char *, unsigned int);
2440+PHPAPI void PHP_SHA256Final(unsigned char[32], PHP_SHA256_CTX *);
2441+
2442+PHP_FUNCTION(sha256);
2443+PHP_FUNCTION(sha256_file);
2444+
2445+#endif
2446diff -Nura php-5.0.5/ext/standard/syslog.c hardening-patch-5.0.5-0.4.3/ext/standard/syslog.c
2447--- php-5.0.5/ext/standard/syslog.c 2005-07-15 11:29:19.000000000 +0200
2448+++ hardening-patch-5.0.5-0.4.3/ext/standard/syslog.c 2005-09-11 23:30:52.000000000 +0200
2449@@ -42,6 +42,7 @@
2450 */
2451 PHP_MINIT_FUNCTION(syslog)
2452 {
2453+#if !HARDENING_PATCH
2454 /* error levels */
2455 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
2456 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
2457@@ -97,7 +98,7 @@
2458 /* AIX doesn't have LOG_PERROR */
2459 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
2460 #endif
2461-
2462+#endif
2463 return SUCCESS;
2464 }
2465 /* }}} */
2466diff -Nura php-5.0.5/ext/varfilter/config.m4 hardening-patch-5.0.5-0.4.3/ext/varfilter/config.m4
2467--- php-5.0.5/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
2468+++ hardening-patch-5.0.5-0.4.3/ext/varfilter/config.m4 2005-09-11 23:30:52.000000000 +0200
2469@@ -0,0 +1,11 @@
2470+dnl
2471+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
2472+dnl
2473+
2474+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
2475+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
2476+
2477+if test "$PHP_VARFILTER" != "no"; then
2478+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
2479+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
2480+fi
2481diff -Nura php-5.0.5/ext/varfilter/CREDITS hardening-patch-5.0.5-0.4.3/ext/varfilter/CREDITS
2482--- php-5.0.5/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
2483+++ hardening-patch-5.0.5-0.4.3/ext/varfilter/CREDITS 2005-09-11 23:30:52.000000000 +0200
2484@@ -0,0 +1,2 @@
2485+varfilter
2486+Stefan Esser
2487\ Kein Zeilenumbruch am Dateiende.
2488diff -Nura php-5.0.5/ext/varfilter/php_varfilter.h hardening-patch-5.0.5-0.4.3/ext/varfilter/php_varfilter.h
2489--- php-5.0.5/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
2490+++ hardening-patch-5.0.5-0.4.3/ext/varfilter/php_varfilter.h 2005-09-12 00:03:50.000000000 +0200
2491@@ -0,0 +1,112 @@
2492+/*
2493+ +----------------------------------------------------------------------+
2494+ | Hardened-PHP Project's varfilter extension |
2495+ +----------------------------------------------------------------------+
2496+ | Copyright (c) 2004-2005 Stefan Esser |
2497+ +----------------------------------------------------------------------+
2498+ | This source file is subject to version 2.02 of the PHP license, |
2499+ | that is bundled with this package in the file LICENSE, and is |
2500+ | available at through the world-wide-web at |
2501+ | http://www.php.net/license/2_02.txt. |
2502+ | If you did not receive a copy of the PHP license and are unable to |
2503+ | obtain it through the world-wide-web, please send a note to |
2504+ | license@php.net so we can mail you a copy immediately. |
2505+ +----------------------------------------------------------------------+
2506+ | Author: Stefan Esser <sesser@hardened-php.net> |
2507+ +----------------------------------------------------------------------+
2508+
2509+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
2510+*/
2511+
2512+#ifndef PHP_VARFILTER_H
2513+#define PHP_VARFILTER_H
2514+
2515+extern zend_module_entry varfilter_module_entry;
2516+#define phpext_varfilter_ptr &varfilter_module_entry
2517+
2518+#ifdef PHP_WIN32
2519+#define PHP_VARFILTER_API __declspec(dllexport)
2520+#else
2521+#define PHP_VARFILTER_API
2522+#endif
2523+
2524+#ifdef ZTS
2525+#include "TSRM.h"
2526+#endif
2527+
2528+#include "SAPI.h"
2529+
2530+#include "php_variables.h"
2531+
2532+
2533+PHP_MINIT_FUNCTION(varfilter);
2534+PHP_MSHUTDOWN_FUNCTION(varfilter);
2535+PHP_RINIT_FUNCTION(varfilter);
2536+PHP_RSHUTDOWN_FUNCTION(varfilter);
2537+PHP_MINFO_FUNCTION(varfilter);
2538+
2539+
2540+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
2541+/* request variables */
2542+ long max_request_variables;
2543+ long cur_request_variables;
2544+ long max_varname_length;
2545+ long max_totalname_length;
2546+ long max_value_length;
2547+ long max_array_depth;
2548+ long max_array_index_length;
2549+/* cookie variables */
2550+ long max_cookie_vars;
2551+ long cur_cookie_vars;
2552+ long max_cookie_name_length;
2553+ long max_cookie_totalname_length;
2554+ long max_cookie_value_length;
2555+ long max_cookie_array_depth;
2556+ long max_cookie_array_index_length;
2557+/* get variables */
2558+ long max_get_vars;
2559+ long cur_get_vars;
2560+ long max_get_name_length;
2561+ long max_get_totalname_length;
2562+ long max_get_value_length;
2563+ long max_get_array_depth;
2564+ long max_get_array_index_length;
2565+/* post variables */
2566+ long max_post_vars;
2567+ long cur_post_vars;
2568+ long max_post_name_length;
2569+ long max_post_totalname_length;
2570+ long max_post_value_length;
2571+ long max_post_array_depth;
2572+ long max_post_array_index_length;
2573+/* fileupload */
2574+ long max_uploads;
2575+ long cur_uploads;
2576+ zend_bool disallow_elf_files;
2577+ char *verification_script;
2578+
2579+ZEND_END_MODULE_GLOBALS(varfilter)
2580+
2581+
2582+#ifdef ZTS
2583+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
2584+#else
2585+#define VARFILTER_G(v) (varfilter_globals.v)
2586+#endif
2587+
2588+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
2589+SAPI_UPLOAD_VARNAME_FILTER_FUNC(varfilter_upload_varname_filter);
2590+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
2591+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
2592+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
2593+
2594+#endif /* PHP_VARFILTER_H */
2595+
2596+
2597+/*
2598+ * Local variables:
2599+ * tab-width: 4
2600+ * c-basic-offset: 4
2601+ * indent-tabs-mode: t
2602+ * End:
2603+ */
2604diff -Nura php-5.0.5/ext/varfilter/varfilter.c hardening-patch-5.0.5-0.4.3/ext/varfilter/varfilter.c
2605--- php-5.0.5/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
2606+++ hardening-patch-5.0.5-0.4.3/ext/varfilter/varfilter.c 2005-09-12 00:02:31.000000000 +0200
2607@@ -0,0 +1,726 @@
2608+/*
2609+ +----------------------------------------------------------------------+
2610+ | Hardened-PHP Project's varfilter extension |
2611+ +----------------------------------------------------------------------+
2612+ | Copyright (c) 2004-2005 Stefan Esser |
2613+ +----------------------------------------------------------------------+
2614+ | This source file is subject to version 2.02 of the PHP license, |
2615+ | that is bundled with this package in the file LICENSE, and is |
2616+ | available at through the world-wide-web at |
2617+ | http://www.php.net/license/2_02.txt. |
2618+ | If you did not receive a copy of the PHP license and are unable to |
2619+ | obtain it through the world-wide-web, please send a note to |
2620+ | license@php.net so we can mail you a copy immediately. |
2621+ +----------------------------------------------------------------------+
2622+ | Author: Stefan Esser <sesser@hardened-php.net> |
2623+ +----------------------------------------------------------------------+
2624+
2625+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
2626+*/
2627+
2628+#ifdef HAVE_CONFIG_H
2629+#include "config.h"
2630+#endif
2631+
2632+#include "php.h"
2633+#include "php_ini.h"
2634+#include "ext/standard/info.h"
2635+#include "php_varfilter.h"
2636+#include "hardening_patch.h"
2637+
2638+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
2639+
2640+/* True global resources - no need for thread safety here */
2641+static int le_varfilter;
2642+
2643+/* {{{ varfilter_module_entry
2644+ */
2645+zend_module_entry varfilter_module_entry = {
2646+#if ZEND_MODULE_API_NO >= 20010901
2647+ STANDARD_MODULE_HEADER,
2648+#endif
2649+ "varfilter",
2650+ NULL,
2651+ PHP_MINIT(varfilter),
2652+ PHP_MSHUTDOWN(varfilter),
2653+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
2654+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
2655+ PHP_MINFO(varfilter),
2656+#if ZEND_MODULE_API_NO >= 20010901
2657+ "0.3.2", /* Replace with version number for your extension */
2658+#endif
2659+ STANDARD_MODULE_PROPERTIES
2660+};
2661+/* }}} */
2662+
2663+#ifdef COMPILE_DL_VARFILTER
2664+ZEND_GET_MODULE(varfilter)
2665+#endif
2666+
2667+/* {{{ PHP_INI
2668+ */
2669+PHP_INI_BEGIN()
2670+ /* for backward compatibility */
2671+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
2672+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
2673+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
2674+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
2675+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
2676+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
2677+
2678+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
2679+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
2680+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
2681+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
2682+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
2683+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
2684+
2685+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
2686+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
2687+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
2688+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
2689+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
2690+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
2691+
2692+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
2693+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
2694+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
2695+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
2696+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
2697+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
2698+
2699+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
2700+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
2701+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
2702+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
2703+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
2704+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
2705+
2706+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
2707+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
2708+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
2709+
2710+
2711+PHP_INI_END()
2712+/* }}} */
2713+
2714+/* {{{ php_varfilter_init_globals
2715+ */
2716+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
2717+{
2718+ varfilter_globals->max_request_variables = 200;
2719+ varfilter_globals->max_varname_length = 64;
2720+ varfilter_globals->max_value_length = 10000;
2721+ varfilter_globals->max_array_depth = 100;
2722+ varfilter_globals->max_totalname_length = 256;
2723+ varfilter_globals->max_array_index_length = 64;
2724+
2725+ varfilter_globals->max_cookie_vars = 100;
2726+ varfilter_globals->max_cookie_name_length = 64;
2727+ varfilter_globals->max_cookie_totalname_length = 256;
2728+ varfilter_globals->max_cookie_value_length = 10000;
2729+ varfilter_globals->max_cookie_array_depth = 100;
2730+ varfilter_globals->max_cookie_array_index_length = 64;
2731+
2732+ varfilter_globals->max_get_vars = 100;
2733+ varfilter_globals->max_get_name_length = 64;
2734+ varfilter_globals->max_get_totalname_length = 256;
2735+ varfilter_globals->max_get_value_length = 512;
2736+ varfilter_globals->max_get_array_depth = 50;
2737+ varfilter_globals->max_get_array_index_length = 64;
2738+
2739+ varfilter_globals->max_post_vars = 200;
2740+ varfilter_globals->max_post_name_length = 64;
2741+ varfilter_globals->max_post_totalname_length = 256;
2742+ varfilter_globals->max_post_value_length = 65000;
2743+ varfilter_globals->max_post_array_depth = 100;
2744+ varfilter_globals->max_post_array_index_length = 64;
2745+
2746+ varfilter_globals->max_uploads = 25;
2747+ varfilter_globals->disallow_elf_files = 1;
2748+ varfilter_globals->verification_script = NULL;
2749+}
2750+/* }}} */
2751+
2752+/* {{{ PHP_MINIT_FUNCTION
2753+ */
2754+PHP_MINIT_FUNCTION(varfilter)
2755+{
2756+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
2757+ REGISTER_INI_ENTRIES();
2758+
2759+ sapi_register_input_filter(varfilter_input_filter);
2760+ sapi_register_upload_varname_filter(varfilter_upload_varname_filter);
2761+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
2762+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
2763+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
2764+
2765+ return SUCCESS;
2766+}
2767+/* }}} */
2768+
2769+/* {{{ PHP_MSHUTDOWN_FUNCTION
2770+ */
2771+PHP_MSHUTDOWN_FUNCTION(varfilter)
2772+{
2773+ UNREGISTER_INI_ENTRIES();
2774+
2775+ return SUCCESS;
2776+}
2777+/* }}} */
2778+
2779+/* Remove if there's nothing to do at request start */
2780+/* {{{ PHP_RINIT_FUNCTION
2781+ */
2782+PHP_RINIT_FUNCTION(varfilter)
2783+{
2784+ VARFILTER_G(cur_request_variables) = 0;
2785+ VARFILTER_G(cur_get_vars) = 0;
2786+ VARFILTER_G(cur_post_vars) = 0;
2787+ VARFILTER_G(cur_cookie_vars) = 0;
2788+
2789+ VARFILTER_G(cur_uploads) = 0;
2790+
2791+ return SUCCESS;
2792+}
2793+/* }}} */
2794+
2795+/* Remove if there's nothing to do at request end */
2796+/* {{{ PHP_RSHUTDOWN_FUNCTION
2797+ */
2798+PHP_RSHUTDOWN_FUNCTION(varfilter)
2799+{
2800+ return SUCCESS;
2801+}
2802+/* }}} */
2803+
2804+/* {{{ PHP_MINFO_FUNCTION
2805+ */
2806+PHP_MINFO_FUNCTION(varfilter)
2807+{
2808+ php_info_print_table_start();
2809+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
2810+ php_info_print_table_end();
2811+
2812+ DISPLAY_INI_ENTRIES();
2813+}
2814+/* }}} */
2815+
2816+/* {{{ normalize_varname
2817+ */
2818+static void normalize_varname(char *varname)
2819+{
2820+ char *s=varname, *index=NULL, *indexend=NULL, *p;
2821+
2822+ /* overjump leading space */
2823+ while (*s == ' ') {
2824+ s++;
2825+ }
2826+
2827+ /* and remove it */
2828+ if (s != varname) {
2829+ memmove(varname, s, strlen(s)+1);
2830+ }
2831+
2832+ for (p=varname; *p && *p != '['; p++) {
2833+ switch(*p) {
2834+ case ' ':
2835+ case '.':
2836+ *p='_';
2837+ break;
2838+ }
2839+ }
2840+
2841+ /* find index */
2842+ index = strchr(varname, '[');
2843+ if (index) {
2844+ index++;
2845+ s=index;
2846+ } else {
2847+ return;
2848+ }
2849+
2850+ /* done? */
2851+ while (index) {
2852+
2853+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
2854+ index++;
2855+ }
2856+ indexend = strchr(index, ']');
2857+ indexend = indexend ? indexend + 1 : index + strlen(index);
2858+
2859+ if (s != index) {
2860+ memmove(s, index, strlen(index)+1);
2861+ s += indexend-index;
2862+ } else {
2863+ s = indexend;
2864+ }
2865+
2866+ if (*s == '[') {
2867+ s++;
2868+ index = s;
2869+ } else {
2870+ index = NULL;
2871+ }
2872+ }
2873+ *s++='\0';
2874+}
2875+/* }}} */
2876+
2877+/* {{{ SAPI_UPLOAD_VARNAME_FILTER_FUNC
2878+ */
2879+SAPI_UPLOAD_VARNAME_FILTER_FUNC(varfilter_upload_varname_filter)
2880+{
2881+ char *index, *prev_index = NULL, *var;
2882+ unsigned int var_len, total_len, depth = 0;
2883+
2884+ var = estrdup(varname);
2885+
2886+ /* Normalize the variable name */
2887+ normalize_varname(var);
2888+
2889+ /* Find length of variable name */
2890+ index = strchr(var, '[');
2891+ total_len = strlen(var);
2892+ var_len = index ? index-var : total_len;
2893+
2894+ /* Drop this variable if it exceeds the varname/total length limit */
2895+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
2896+ php_security_log(S_FILES, "configured request variable name length limit exceeded - dropped %s", var);
2897+ goto return_failure;
2898+ }
2899+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
2900+ php_security_log(S_FILES, "configured request variable total name length limit exceeded - dropped %s", var);
2901+ goto return_failure;
2902+ }
2903+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
2904+ php_security_log(S_FILES, "configured POST variable name length limit exceeded - dropped %s", var);
2905+ goto return_failure;
2906+ }
2907+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
2908+ php_security_log(S_FILES, "configured POST variable total name length limit exceeded - dropped %s", var);
2909+ goto return_failure;
2910+ }
2911+
2912+ /* Find out array depth */
2913+ while (index) {
2914+ unsigned int index_length;
2915+
2916+ depth++;
2917+ index = strchr(index+1, '[');
2918+
2919+ if (prev_index) {
2920+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
2921+
2922+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
2923+ php_security_log(S_FILES, "configured request variable array index length limit exceeded - dropped %s", var);
2924+ goto return_failure;
2925+ }
2926+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
2927+ php_security_log(S_FILES, "configured POST variable array index length limit exceeded - dropped %s", var);
2928+ goto return_failure;
2929+ }
2930+ prev_index = index;
2931+ }
2932+
2933+ }
2934+
2935+ /* Drop this variable if it exceeds the array depth limit */
2936+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
2937+ php_security_log(S_FILES, "configured request variable array depth limit exceeded - dropped %s", var);
2938+ goto return_failure;
2939+ }
2940+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
2941+ php_security_log(S_FILES, "configured POST variable array depth limit exceeded - dropped %s", var);
2942+ goto return_failure;
2943+ }
2944+
2945+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
2946+ /* This is to protect several silly scripts that do globalizing themself */
2947+
2948+ switch (var_len) {
2949+ case 18:
2950+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname2;
2951+ break;
2952+ case 17:
2953+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname2;
2954+ break;
2955+ case 16:
2956+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname2;
2957+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname2;
2958+ break;
2959+ case 15:
2960+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname2;
2961+ break;
2962+ case 14:
2963+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname2;
2964+ break;
2965+ case 13:
2966+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname2;
2967+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname2;
2968+ break;
2969+ case 8:
2970+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname2;
2971+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname2;
2972+ break;
2973+ case 7:
2974+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname2;
2975+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname2;
2976+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname2;
2977+ break;
2978+ case 6:
2979+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname2;
2980+ break;
2981+ case 5:
2982+ if (memcmp(var, "_POST", 5)==0) goto protected_varname2;
2983+ break;
2984+ case 4:
2985+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname2;
2986+ if (memcmp(var, "_GET", 4)==0) goto protected_varname2;
2987+ break;
2988+ }
2989+
2990+ efree(var);
2991+ return SUCCESS;
2992+protected_varname2:
2993+ php_security_log(S_FILES, "tried to register forbidden variable '%s' through FILE variables", var);
2994+return_failure:
2995+ efree(var);
2996+ return FAILURE;
2997+}
2998+/* }}} */
2999+
3000+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
3001+ */
3002+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
3003+{
3004+ /* Drop this fileupload if the limit is reached */
3005+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
3006+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
3007+ return FAILURE;
3008+ }
3009+
3010+ return SUCCESS;
3011+}
3012+/* }}} */
3013+
3014+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
3015+ */
3016+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
3017+{
3018+
3019+ if (VARFILTER_G(disallow_elf_files)) {
3020+
3021+ if (offset == 0 && buffer_len > 10) {
3022+
3023+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
3024+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
3025+ return FAILURE;
3026+ }
3027+ }
3028+
3029+ }
3030+
3031+ return SUCCESS;
3032+}
3033+/* }}} */
3034+
3035+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
3036+ */
3037+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
3038+{
3039+ int retval = SUCCESS;
3040+
3041+ if (VARFILTER_G(verification_script)) {
3042+ char cmd[8192];
3043+ FILE *in;
3044+ int first=1;
3045+
3046+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
3047+
3048+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
3049+ php_security_log(S_FILES, "unable to execute fileupload verification script %s - file dropped", VARFILTER_G(verification_script));
3050+ return FAILURE;
3051+ }
3052+
3053+ retval = FAILURE;
3054+
3055+ /* read and forget the result */
3056+ while (1) {
3057+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
3058+ if (readbytes<=0) {
3059+ break;
3060+ }
3061+ if (first) {
3062+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
3063+ first = 0;
3064+ }
3065+ }
3066+ pclose(in);
3067+ }
3068+
3069+ if (retval != SUCCESS) {
3070+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
3071+ return FAILURE;
3072+ }
3073+
3074+ VARFILTER_G(cur_uploads)++;
3075+ return SUCCESS;
3076+}
3077+/* }}} */
3078+
3079+/* {{{ SAPI_INPUT_FILTER_FUNC
3080+ */
3081+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
3082+{
3083+ char *index, *prev_index = NULL;
3084+ unsigned int var_len, total_len, depth = 0;
3085+
3086+ /* Drop this variable if the limit is reached */
3087+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
3088+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
3089+ return 0;
3090+ }
3091+ switch (arg) {
3092+ case PARSE_GET:
3093+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
3094+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
3095+ return 0;
3096+ }
3097+ break;
3098+ case PARSE_COOKIE:
3099+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
3100+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
3101+ return 0;
3102+ }
3103+ break;
3104+ case PARSE_POST:
3105+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
3106+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
3107+ return 0;
3108+ }
3109+ break;
3110+ }
3111+
3112+
3113+ /* Drop this variable if it exceeds the value length limit */
3114+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
3115+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
3116+ return 0;
3117+ }
3118+ switch (arg) {
3119+ case PARSE_GET:
3120+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
3121+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
3122+ return 0;
3123+ }
3124+ break;
3125+ case PARSE_COOKIE:
3126+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
3127+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
3128+ return 0;
3129+ }
3130+ break;
3131+ case PARSE_POST:
3132+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
3133+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
3134+ return 0;
3135+ }
3136+ break;
3137+ }
3138+
3139+ /* Normalize the variable name */
3140+ normalize_varname(var);
3141+
3142+ /* Find length of variable name */
3143+ index = strchr(var, '[');
3144+ total_len = strlen(var);
3145+ var_len = index ? index-var : total_len;
3146+
3147+ /* Drop this variable if it exceeds the varname/total length limit */
3148+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
3149+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
3150+ return 0;
3151+ }
3152+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
3153+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
3154+ return 0;
3155+ }
3156+ switch (arg) {
3157+ case PARSE_GET:
3158+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
3159+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
3160+ return 0;
3161+ }
3162+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
3163+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
3164+ return 0;
3165+ }
3166+ break;
3167+ case PARSE_COOKIE:
3168+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
3169+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
3170+ return 0;
3171+ }
3172+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
3173+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
3174+ return 0;
3175+ }
3176+ break;
3177+ case PARSE_POST:
3178+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
3179+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
3180+ return 0;
3181+ }
3182+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
3183+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
3184+ return 0;
3185+ }
3186+ break;
3187+ }
3188+
3189+ /* Find out array depth */
3190+ while (index) {
3191+ unsigned int index_length;
3192+
3193+ depth++;
3194+ index = strchr(index+1, '[');
3195+
3196+ if (prev_index) {
3197+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
3198+
3199+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
3200+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
3201+ return 0;
3202+ }
3203+ switch (arg) {
3204+ case PARSE_GET:
3205+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
3206+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
3207+ return 0;
3208+ }
3209+ break;
3210+ case PARSE_COOKIE:
3211+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
3212+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
3213+ return 0;
3214+ }
3215+ break;
3216+ case PARSE_POST:
3217+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
3218+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
3219+ return 0;
3220+ }
3221+ break;
3222+ }
3223+ prev_index = index;
3224+ }
3225+
3226+ }
3227+
3228+ /* Drop this variable if it exceeds the array depth limit */
3229+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
3230+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
3231+ return 0;
3232+ }
3233+ switch (arg) {
3234+ case PARSE_GET:
3235+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
3236+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
3237+ return 0;
3238+ }
3239+ break;
3240+ case PARSE_COOKIE:
3241+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
3242+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
3243+ return 0;
3244+ }
3245+ break;
3246+ case PARSE_POST:
3247+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
3248+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
3249+ return 0;
3250+ }
3251+ break;
3252+ }
3253+
3254+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
3255+ /* This is to protect several silly scripts that do globalizing themself */
3256+
3257+ switch (var_len) {
3258+ case 18:
3259+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
3260+ break;
3261+ case 17:
3262+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
3263+ break;
3264+ case 16:
3265+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
3266+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
3267+ break;
3268+ case 15:
3269+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
3270+ break;
3271+ case 14:
3272+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
3273+ break;
3274+ case 13:
3275+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
3276+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
3277+ break;
3278+ case 8:
3279+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
3280+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
3281+ break;
3282+ case 7:
3283+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
3284+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
3285+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
3286+ break;
3287+ case 6:
3288+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
3289+ break;
3290+ case 5:
3291+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
3292+ break;
3293+ case 4:
3294+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
3295+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
3296+ break;
3297+ }
3298+
3299+ /* Okay let PHP register this variable */
3300+ VARFILTER_G(cur_request_variables)++;
3301+ switch (arg) {
3302+ case PARSE_GET:
3303+ VARFILTER_G(cur_get_vars)++;
3304+ break;
3305+ case PARSE_COOKIE:
3306+ VARFILTER_G(cur_cookie_vars)++;
3307+ break;
3308+ case PARSE_POST:
3309+ VARFILTER_G(cur_post_vars)++;
3310+ break;
3311+ }
3312+
3313+ if (new_val_len) {
3314+ *new_val_len = val_len;
3315+ }
3316+
3317+ return 1;
3318+protected_varname:
3319+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
3320+ return 0;
3321+}
3322+/* }}} */
3323+
3324+/*
3325+ * Local variables:
3326+ * tab-width: 4
3327+ * c-basic-offset: 4
3328+ * End:
3329+ * vim600: noet sw=4 ts=4 fdm=marker
3330+ * vim<600: noet sw=4 ts=4
3331+ */
3332+
3333+
3334diff -Nura php-5.0.5/main/fopen_wrappers.c hardening-patch-5.0.5-0.4.3/main/fopen_wrappers.c
3335--- php-5.0.5/main/fopen_wrappers.c 2005-07-16 14:14:44.000000000 +0200
3336+++ hardening-patch-5.0.5-0.4.3/main/fopen_wrappers.c 2005-09-11 23:30:52.000000000 +0200
3337@@ -155,6 +155,21 @@
3338 char *pathbuf;
3339 char *ptr;
3340 char *end;
3341+ char path_copy[MAXPATHLEN];
3342+ int path_len;
3343+
3344+ /* Special case path ends with a trailing slash */
3345+ path_len = strlen(path);
3346+ if (path_len >= MAXPATHLEN) {
3347+ errno = EPERM; /* we deny permission to open it */
3348+ return -1;
3349+ }
3350+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
3351+ memcpy(path_copy, path, path_len+1);
3352+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
3353+ path_copy[path_len] = '\0';
3354+ path = (const char *)&path_copy;
3355+ }
3356
3357 pathbuf = estrdup(PG(open_basedir));
3358
3359diff -Nura php-5.0.5/main/hardened_globals.h hardening-patch-5.0.5-0.4.3/main/hardened_globals.h
3360--- php-5.0.5/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
3361+++ hardening-patch-5.0.5-0.4.3/main/hardened_globals.h 2005-09-12 17:03:36.000000000 +0200
3362@@ -0,0 +1,62 @@
3363+/*
3364+ +----------------------------------------------------------------------+
3365+ | Hardening-Patch for PHP |
3366+ +----------------------------------------------------------------------+
3367+ | Copyright (c) 2004-2005 Stefan Esser |
3368+ +----------------------------------------------------------------------+
3369+ | This source file is subject to version 2.02 of the PHP license, |
3370+ | that is bundled with this package in the file LICENSE, and is |
3371+ | available at through the world-wide-web at |
3372+ | http://www.php.net/license/2_02.txt. |
3373+ | If you did not receive a copy of the PHP license and are unable to |
3374+ | obtain it through the world-wide-web, please send a note to |
3375+ | license@php.net so we can mail you a copy immediately. |
3376+ +----------------------------------------------------------------------+
3377+ | Author: Stefan Esser <sesser@hardened-php.net> |
3378+ +----------------------------------------------------------------------+
3379+ */
3380+
3381+#ifndef HARDENED_GLOBALS_H
3382+#define HARDENED_GLOBALS_H
3383+
3384+typedef struct _hardened_globals hardened_globals_struct;
3385+
3386+#ifdef ZTS
3387+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
3388+extern int hardened_globals_id;
3389+#else
3390+# define HG(v) (hardened_globals.v)
3391+extern struct _hardened_globals hardened_globals;
3392+#endif
3393+
3394+
3395+struct _hardened_globals {
3396+#if HARDENING_PATCH_MM_PROTECT
3397+ unsigned int canary_1;
3398+ unsigned int canary_2;
3399+#endif
3400+#if HARDENING_PATCH_LL_PROTECT
3401+ unsigned int canary_3;
3402+ unsigned int canary_4;
3403+ unsigned int ll_canary_inited;
3404+#endif
3405+ zend_bool hphp_sql_bailout_on_error;
3406+ zend_bool hphp_multiheader;
3407+ HashTable *eval_whitelist;
3408+ HashTable *eval_blacklist;
3409+ HashTable *func_whitelist;
3410+ HashTable *func_blacklist;
3411+ HashTable *include_whitelist;
3412+ HashTable *include_blacklist;
3413+ unsigned int dummy;
3414+};
3415+
3416+
3417+#endif /* HARDENED_GLOBALS_H */
3418+
3419+/*
3420+ * Local variables:
3421+ * tab-width: 4
3422+ * c-basic-offset: 4
3423+ * End:
3424+ */
3425diff -Nura php-5.0.5/main/hardening_patch.c hardening-patch-5.0.5-0.4.3/main/hardening_patch.c
3426--- php-5.0.5/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
3427+++ hardening-patch-5.0.5-0.4.3/main/hardening_patch.c 2005-09-12 18:09:56.000000000 +0200
3428@@ -0,0 +1,424 @@
3429+/*
3430+ +----------------------------------------------------------------------+
3431+ | Hardening Patch for PHP |
3432+ +----------------------------------------------------------------------+
3433+ | Copyright (c) 2004-2005 Stefan Esser |
3434+ +----------------------------------------------------------------------+
3435+ | This source file is subject to version 2.02 of the PHP license, |
3436+ | that is bundled with this package in the file LICENSE, and is |
3437+ | available at through the world-wide-web at |
3438+ | http://www.php.net/license/2_02.txt. |
3439+ | If you did not receive a copy of the PHP license and are unable to |
3440+ | obtain it through the world-wide-web, please send a note to |
3441+ | license@php.net so we can mail you a copy immediately. |
3442+ +----------------------------------------------------------------------+
3443+ | Author: Stefan Esser <sesser@hardened-php.net> |
3444+ +----------------------------------------------------------------------+
3445+ */
3446+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
3447+
3448+#include "php.h"
3449+
3450+#include <stdio.h>
3451+#include <stdlib.h>
3452+
3453+#if HAVE_UNISTD_H
3454+#include <unistd.h>
3455+#endif
3456+#include "SAPI.h"
3457+#include "php_globals.h"
3458+
3459+#if HARDENING_PATCH
3460+
3461+#ifdef HAVE_SYS_SOCKET_H
3462+#include <sys/socket.h>
3463+#endif
3464+
3465+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
3466+#undef AF_UNIX
3467+#endif
3468+
3469+#if defined(AF_UNIX)
3470+#include <sys/un.h>
3471+#endif
3472+
3473+#define SYSLOG_PATH "/dev/log"
3474+
3475+#include "snprintf.h"
3476+
3477+#include "hardening_patch.h"
3478+
3479+#ifdef ZTS
3480+#include "hardened_globals.h"
3481+int hardened_globals_id;
3482+#else
3483+struct _hardened_globals hardened_globals;
3484+#endif
3485+
3486+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
3487+{
3488+ memset(hardened_globals, 0, sizeof(*hardened_globals));
3489+}
3490+
3491+
3492+PHPAPI void hardened_startup()
3493+{
3494+#ifdef ZTS
3495+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
3496+#else
3497+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
3498+#endif
3499+}
3500+
3501+char *loglevel2string(int loglevel)
3502+{
3503+ switch (loglevel) {
3504+ case S_FILES:
3505+ return "FILES";
3506+ case S_INCLUDE:
3507+ return "INCLUDE";
3508+ case S_MEMORY:
3509+ return "MEMORY";
3510+ case S_MISC:
3511+ return "MISC";
3512+ case S_SQL:
3513+ return "SQL";
3514+ case S_EXECUTOR:
3515+ return "EXECUTOR";
3516+ case S_VARS:
3517+ return "VARS";
3518+ default:
3519+ return "UNKNOWN";
3520+ }
3521+}
3522+
3523+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
3524+{
3525+#if defined(AF_UNIX)
3526+ int s, r, i=0;
3527+ struct sockaddr_un saun;
3528+ char buf[4096+64];
3529+ char error[4096+100];
3530+ char *ip_address;
3531+ char *fname;
3532+ int lineno;
3533+ va_list ap;
3534+ TSRMLS_FETCH();
3535+
3536+ if (EG(hphp_log_use_x_forwarded_for)) {
3537+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
3538+ if (ip_address == NULL) {
3539+ ip_address = "X-FORWARDED-FOR not set";
3540+ }
3541+ } else {
3542+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
3543+ if (ip_address == NULL) {
3544+ ip_address = "REMOTE_ADDR not set";
3545+ }
3546+ }
3547+
3548+
3549+ va_start(ap, fmt);
3550+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
3551+ va_end(ap);
3552+ while (error[i]) {
3553+ if (error[i] < 32) error[i] = '.';
3554+ i++;
3555+ }
3556+
3557+ if (zend_is_executing(TSRMLS_C)) {
3558+ lineno = zend_get_executed_lineno(TSRMLS_C);
3559+ fname = zend_get_executed_filename(TSRMLS_C);
3560+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
3561+ } else {
3562+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
3563+ if (fname==NULL) {
3564+ fname = "unknown";
3565+ }
3566+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
3567+ }
3568+
3569+ /* Syslog-Logging disabled? */
3570+ if ((EG(hphp_log_syslog) & loglevel)==0) {
3571+ goto log_sapi;
3572+ }
3573+
3574+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
3575+
3576+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
3577+ if (s == -1) {
3578+ goto log_sapi;
3579+ }
3580+
3581+ memset(&saun, 0, sizeof(saun));
3582+ saun.sun_family = AF_UNIX;
3583+ strcpy(saun.sun_path, SYSLOG_PATH);
3584+ /*saun.sun_len = sizeof(saun);*/
3585+
3586+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
3587+ if (r) {
3588+ close(s);
3589+ s = socket(AF_UNIX, SOCK_STREAM, 0);
3590+ if (s == -1) {
3591+ goto log_sapi;
3592+ }
3593+
3594+ memset(&saun, 0, sizeof(saun));
3595+ saun.sun_family = AF_UNIX;
3596+ strcpy(saun.sun_path, SYSLOG_PATH);
3597+ /*saun.sun_len = sizeof(saun);*/
3598+
3599+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
3600+ if (r) {
3601+ close(s);
3602+ goto log_sapi;
3603+ }
3604+ }
3605+ send(s, error, strlen(error), 0);
3606+
3607+ close(s);
3608+
3609+log_sapi:
3610+ /* SAPI Logging activated? */
3611+ if ((EG(hphp_log_syslog) & loglevel)!=0) {
3612+ sapi_module.log_message(buf);
3613+ }
3614+
3615+log_script:
3616+ /* script logging activaed? */
3617+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
3618+ char cmd[8192], *cmdpos, *bufpos;
3619+ FILE *in;
3620+ int space;
3621+
3622+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
3623+ space = sizeof(cmd) - strlen(cmd);
3624+ cmdpos = cmd + strlen(cmd);
3625+ bufpos = buf;
3626+ if (space <= 1) return;
3627+ while (space > 2 && *bufpos) {
3628+ if (*bufpos == '\'') {
3629+ if (space<=5) break;
3630+ *cmdpos++ = '\'';
3631+ *cmdpos++ = '\\';
3632+ *cmdpos++ = '\'';
3633+ *cmdpos++ = '\'';
3634+ bufpos++;
3635+ space-=4;
3636+ } else {
3637+ *cmdpos++ = *bufpos++;
3638+ space--;
3639+ }
3640+ }
3641+ *cmdpos++ = '\'';
3642+ *cmdpos = 0;
3643+
3644+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
3645+ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", EG(hphp_log_scriptname));
3646+ return;
3647+ }
3648+ /* read and forget the result */
3649+ while (1) {
3650+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
3651+ if (readbytes<=0) {
3652+ break;
3653+ }
3654+ }
3655+ pclose(in);
3656+ }
3657+
3658+#endif
3659+}
3660+#endif
3661+
3662+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
3663+
3664+/* will be replaced later with more compatible method */
3665+PHPAPI unsigned int php_canary()
3666+{
3667+ time_t t;
3668+ unsigned int canary;
3669+ int fd;
3670+
3671+ fd = open("/dev/urandom", 0);
3672+ if (fd != -1) {
3673+ int r = read(fd, &canary, sizeof(canary));
3674+ close(fd);
3675+ if (r == sizeof(canary)) {
3676+ return (canary);
3677+ }
3678+ }
3679+ /* not good but we never want to do this */
3680+ time(&t);
3681+ canary = *(unsigned int *)&t + getpid() << 16;
3682+ return (canary);
3683+}
3684+#endif
3685+
3686+#if HARDENING_PATCH_INC_PROTECT
3687+
3688+PHPAPI int php_is_valid_include(zval *z)
3689+{
3690+ char *filename;
3691+ int len, i;
3692+ TSRMLS_FETCH();
3693+
3694+ /* must be of type string */
3695+ if (z->type != IS_STRING || z->value.str.val == NULL) {
3696+ return (0);
3697+ }
3698+
3699+ /* short cut */
3700+ filename = z->value.str.val;
3701+ len = z->value.str.len;
3702+
3703+ /* 1. must be shorter than MAXPATHLEN */
3704+ if (len > MAXPATHLEN) {
3705+ char *fname = estrndup(filename, len);
3706+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
3707+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
3708+ efree(fname);
3709+ return (0);
3710+ }
3711+
3712+ /* 2. must not be cutted */
3713+ if (len != strlen(filename)) {
3714+ char *fname = estrndup(filename, len);
3715+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
3716+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
3717+ efree(fname);
3718+ return (0);
3719+ }
3720+
3721+ /* 3. when it is an URL first check black/whitelist if both are empty disallow all URLs */
3722+ if (strstr(filename, "://")) {
3723+ char *fname = estrndup(filename, len);
3724+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
3725+
3726+ /* no black or whitelist then disallow all */
3727+ if (HG(include_whitelist)==NULL && HG(include_blacklist)==NULL) {
3728+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
3729+ efree(fname);
3730+ return (0);
3731+ }
3732+
3733+ /* whitelist is stronger than blacklist */
3734+ if (HG(include_whitelist)) {
3735+ char *s, *t, *h, *index;
3736+ uint indexlen;
3737+ ulong numindex;
3738+
3739+ s = filename;
3740+
3741+ do {
3742+ zend_bool isOk = 0;
3743+ int tlen;
3744+
3745+ t = h = strstr(s, "://");
3746+ if (h == NULL) break;
3747+
3748+
3749+ while (t > s && (isalpha(t[-1]) || t[-1]=='_')) {
3750+ t--;
3751+ }
3752+
3753+ tlen = strlen(t);
3754+
3755+ zend_hash_internal_pointer_reset(HG(include_whitelist));
3756+ do {
3757+ int r = zend_hash_get_current_key_ex(HG(include_whitelist), &index, &indexlen, &numindex, 0, NULL);
3758+
3759+ if (r==HASH_KEY_NON_EXISTANT) {
3760+ break;
3761+ }
3762+ if (r==HASH_KEY_IS_STRING) {
3763+ if (h-t <= indexlen-1 && tlen>=indexlen-1) {
3764+ if (strncmp(t, index, indexlen-1)==0) {
3765+ isOk = 1;
3766+ break;
3767+ }
3768+ }
3769+ }
3770+
3771+ zend_hash_move_forward(HG(include_whitelist));
3772+ } while (1);
3773+
3774+ /* not found in whitelist */
3775+ if (!isOk) {
3776+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL that is not allowed in whitelist", fname);
3777+ efree(fname);
3778+ return 0;
3779+ }
3780+
3781+ s = h + 3;
3782+ } while (1);
3783+ } else {
3784+ /* okay then handle the blacklist */
3785+ char *s, *t, *h, *index;
3786+ uint indexlen;
3787+ ulong numindex;
3788+
3789+ s = filename;
3790+
3791+ do {
3792+ int tlen;
3793+
3794+ t = h = strstr(s, "://");
3795+ if (h == NULL) break;
3796+
3797+
3798+ while (t > s) {
3799+ if (isalpha(t[-1]) || t[-1]=='_') t--;
3800+ }
3801+
3802+ tlen = strlen(t);
3803+
3804+ zend_hash_internal_pointer_reset(HG(include_blacklist));
3805+ do {
3806+ int r = zend_hash_get_current_key_ex(HG(include_blacklist), &index, &indexlen, &numindex, 0, NULL);
3807+
3808+ if (r==HASH_KEY_NON_EXISTANT) {
3809+ break;
3810+ }
3811+ if (r==HASH_KEY_IS_STRING) {
3812+ if (h-t <= indexlen-1 && tlen>=indexlen-1) {
3813+ if (strncmp(t, index, indexlen-1)==0) {
3814+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL that is forbidden by the blacklist", fname);
3815+ efree(fname);
3816+ return 0;
3817+ }
3818+ }
3819+ }
3820+
3821+ zend_hash_move_forward(HG(include_blacklist));
3822+ } while (1);
3823+
3824+ s = h + 3;
3825+ } while (1);
3826+ }
3827+
3828+ efree(fname);
3829+ }
3830+
3831+ /* 4. must not be an uploaded file */
3832+ if (SG(rfc1867_uploaded_files)) {
3833+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
3834+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
3835+ return (0);
3836+ }
3837+ }
3838+
3839+ /* passed all tests */
3840+ return (1);
3841+}
3842+
3843+#endif
3844+
3845+/*
3846+ * Local variables:
3847+ * tab-width: 4
3848+ * c-basic-offset: 4
3849+ * End:
3850+ * vim600: sw=4 ts=4 fdm=marker
3851+ * vim<600: sw=4 ts=4
3852+ */
3853diff -Nura php-5.0.5/main/hardening_patch.h hardening-patch-5.0.5-0.4.3/main/hardening_patch.h
3854--- php-5.0.5/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
3855+++ hardening-patch-5.0.5-0.4.3/main/hardening_patch.h 2005-09-11 23:43:23.000000000 +0200
3856@@ -0,0 +1,46 @@
3857+/*
3858+ +----------------------------------------------------------------------+
3859+ | Hardening Patch for PHP |
3860+ +----------------------------------------------------------------------+
3861+ | Copyright (c) 2004-2005 Stefan Esser |
3862+ +----------------------------------------------------------------------+
3863+ | This source file is subject to version 2.02 of the PHP license, |
3864+ | that is bundled with this package in the file LICENSE, and is |
3865+ | available at through the world-wide-web at |
3866+ | http://www.php.net/license/2_02.txt. |
3867+ | If you did not receive a copy of the PHP license and are unable to |
3868+ | obtain it through the world-wide-web, please send a note to |
3869+ | license@php.net so we can mail you a copy immediately. |
3870+ +----------------------------------------------------------------------+
3871+ | Author: Stefan Esser <sesser@hardened-php.net> |
3872+ +----------------------------------------------------------------------+
3873+ */
3874+
3875+#ifndef HARDENING_PATCH_H
3876+#define HARDENING_PATCH_H
3877+
3878+#include "zend.h"
3879+
3880+#if HARDENING_PATCH
3881+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
3882+PHPAPI void hardened_startup();
3883+#define HARDENING_PATCH_VERSION "0.4.3"
3884+
3885+#endif
3886+
3887+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
3888+PHPAPI unsigned int php_canary();
3889+#endif
3890+
3891+#if HARDENING_PATCH_INC_PROTECT
3892+PHPAPI int php_is_valid_include(zval *z);
3893+#endif
3894+
3895+#endif /* HARDENING_PATCH_H */
3896+
3897+/*
3898+ * Local variables:
3899+ * tab-width: 4
3900+ * c-basic-offset: 4
3901+ * End:
3902+ */
3903diff -Nura php-5.0.5/main/hardening_patch.m4 hardening-patch-5.0.5-0.4.3/main/hardening_patch.m4
3904--- php-5.0.5/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
3905+++ hardening-patch-5.0.5-0.4.3/main/hardening_patch.m4 2005-09-11 23:30:52.000000000 +0200
3906@@ -0,0 +1,95 @@
3907+dnl
3908+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
3909+dnl
3910+dnl This file contains Hardening Patch for PHP specific autoconf functions.
3911+dnl
3912+
3913+AC_ARG_ENABLE(hardening-patch-mm-protect,
3914+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
3915+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
3916+],[
3917+ DO_HARDENING_PATCH_MM_PROTECT=yes
3918+])
3919+
3920+AC_ARG_ENABLE(hardening-patch-ll-protect,
3921+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
3922+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
3923+],[
3924+ DO_HARDENING_PATCH_LL_PROTECT=yes
3925+])
3926+
3927+AC_ARG_ENABLE(hardening-patch-inc-protect,
3928+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
3929+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
3930+],[
3931+ DO_HARDENING_PATCH_INC_PROTECT=yes
3932+])
3933+
3934+AC_ARG_ENABLE(hardening-patch-fmt-protect,
3935+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
3936+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
3937+],[
3938+ DO_HARDENING_PATCH_FMT_PROTECT=yes
3939+])
3940+
3941+AC_ARG_ENABLE(hardening-patch-hash-protect,
3942+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
3943+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
3944+],[
3945+ DO_HARDENING_PATCH_HASH_PROTECT=yes
3946+])
3947+
3948+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
3949+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
3950+
3951+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
3952+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
3953+
3954+AC_MSG_CHECKING(whether to protect include/require statements)
3955+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
3956+
3957+AC_MSG_CHECKING(whether to protect PHP Format String functions)
3958+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
3959+
3960+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
3961+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
3962+
3963+
3964+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3965+
3966+
3967+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
3968+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3969+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
3970+else
3971+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
3972+fi
3973+
3974+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
3975+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3976+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
3977+else
3978+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
3979+fi
3980+
3981+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
3982+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3983+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
3984+else
3985+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
3986+fi
3987+
3988+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
3989+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3990+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
3991+else
3992+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
3993+fi
3994+
3995+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
3996+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
3997+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
3998+else
3999+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
4000+fi
4001+
4002diff -Nura php-5.0.5/main/main.c hardening-patch-5.0.5-0.4.3/main/main.c
4003--- php-5.0.5/main/main.c 2005-08-16 20:11:34.000000000 +0200
4004+++ hardening-patch-5.0.5-0.4.3/main/main.c 2005-09-11 23:30:52.000000000 +0200
4005@@ -85,6 +85,10 @@
4006
4007 #include "SAPI.h"
4008 #include "rfc1867.h"
4009+#if HARDENING_PATCH
4010+#include "hardened_globals.h"
4011+#endif
4012+
4013 /* }}} */
4014
4015 #ifndef ZTS
4016@@ -109,10 +113,33 @@
4017 */
4018 static PHP_INI_MH(OnChangeMemoryLimit)
4019 {
4020+#if HARDENING_PATCH
4021+ long orig_memory_limit;
4022+
4023+ if (entry->modified) {
4024+ orig_memory_limit = zend_atoi(entry->orig_value, entry->orig_value_length);
4025+ } else {
4026+ orig_memory_limit = 1<<30;
4027+ }
4028+ if (orig_memory_limit < 0 || orig_memory_limit > (1<<30)) {
4029+ orig_memory_limit = 1<<30;
4030+ }
4031+#endif
4032 if (new_value) {
4033 PG(memory_limit) = zend_atoi(new_value, new_value_length);
4034+#if HARDENING_PATCH
4035+ if (PG(memory_limit) > orig_memory_limit) {
4036+ PG(memory_limit) = orig_memory_limit;
4037+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
4038+ return FAILURE;
4039+ }
4040+#endif
4041 } else {
4042+#if HARDENING_PATCH
4043+ PG(memory_limit) = orig_memory_limit;
4044+#else
4045 PG(memory_limit) = 1<<30; /* effectively, no limit */
4046+#endif
4047 }
4048 return zend_set_memory_limit(PG(memory_limit));
4049 }
4050@@ -1322,6 +1349,10 @@
4051 tsrm_ls = ts_resource(0);
4052 #endif
4053
4054+#if HARDENING_PATCH
4055+ hardened_startup();
4056+#endif
4057+
4058 module_shutdown = 0;
4059 module_startup = 1;
4060 sapi_initialize_empty_request(TSRMLS_C);
4061@@ -1335,6 +1366,12 @@
4062
4063 php_output_startup();
4064
4065+#if HARDENING_PATCH_INC_PROTECT
4066+ zuf.is_valid_include = php_is_valid_include;
4067+#endif
4068+#if HARDENING_PATCH
4069+ zuf.security_log_function = php_security_log;
4070+#endif
4071 zuf.error_function = php_error_cb;
4072 zuf.printf_function = php_printf;
4073 zuf.write_function = php_body_write_wrapper;
4074@@ -1438,6 +1475,10 @@
4075 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, sizeof(PHP_CONFIG_FILE_PATH)-1, CONST_PERSISTENT | CONST_CS);
4076 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
4077 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
4078+#if HARDENING_PATCH
4079+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
4080+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
4081+#endif
4082 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
4083 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
4084 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
4085diff -Nura php-5.0.5/main/php_config.h.in hardening-patch-5.0.5-0.4.3/main/php_config.h.in
4086--- php-5.0.5/main/php_config.h.in 2005-09-05 13:16:27.000000000 +0200
4087+++ hardening-patch-5.0.5-0.4.3/main/php_config.h.in 2005-09-11 23:30:52.000000000 +0200
4088@@ -752,6 +752,39 @@
4089 /* Enabling BIND8 compatibility for Panther */
4090 #undef BIND_8_COMPAT
4091
4092+/* Hardening-Patch for PHP */
4093+#undef HARDENING_PATCH
4094+
4095+/* Memory Manager Protection */
4096+#undef HARDENING_PATCH_MM_PROTECT
4097+
4098+/* Memory Manager Protection */
4099+#undef HARDENING_PATCH_MM_PROTECT
4100+
4101+/* Linked List Protection */
4102+#undef HARDENING_PATCH_LL_PROTECT
4103+
4104+/* Linked List Protection */
4105+#undef HARDENING_PATCH_LL_PROTECT
4106+
4107+/* Include/Require Protection */
4108+#undef HARDENING_PATCH_INC_PROTECT
4109+
4110+/* Include/Require Protection */
4111+#undef HARDENING_PATCH_INC_PROTECT
4112+
4113+/* Fmt String Protection */
4114+#undef HARDENING_PATCH_FMT_PROTECT
4115+
4116+/* Fmt String Protection */
4117+#undef HARDENING_PATCH_FMT_PROTECT
4118+
4119+/* HashTable DTOR Protection */
4120+#undef HARDENING_PATCH_HASH_PROTECT
4121+
4122+/* HashTable DTOR Protection */
4123+#undef HARDENING_PATCH_HASH_PROTECT
4124+
4125 /* Whether you have AOLserver */
4126 #undef HAVE_AOLSERVER
4127
4128@@ -1083,6 +1116,12 @@
4129 /* Define if you have the getaddrinfo function */
4130 #undef HAVE_GETADDRINFO
4131
4132+/* Whether realpath is broken */
4133+#undef PHP_BROKEN_REALPATH
4134+
4135+/* Whether realpath is broken */
4136+#undef PHP_BROKEN_REALPATH
4137+
4138 /* Whether system headers declare timezone */
4139 #undef HAVE_DECLARED_TIMEZONE
4140
4141diff -Nura php-5.0.5/main/php.h hardening-patch-5.0.5-0.4.3/main/php.h
4142--- php-5.0.5/main/php.h 2005-06-29 08:41:15.000000000 +0200
4143+++ hardening-patch-5.0.5-0.4.3/main/php.h 2005-09-11 23:30:52.000000000 +0200
4144@@ -35,11 +35,19 @@
4145 #include "zend_qsort.h"
4146 #include "php_compat.h"
4147
4148+
4149 #include "zend_API.h"
4150
4151 #undef sprintf
4152 #define sprintf php_sprintf
4153
4154+#if HARDENING_PATCH
4155+#if HAVE_REALPATH
4156+#undef realpath
4157+#define realpath php_realpath
4158+#endif
4159+#endif
4160+
4161 /* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
4162 #undef PHP_DEBUG
4163 #define PHP_DEBUG ZEND_DEBUG
4164@@ -330,6 +338,7 @@
4165 #define PHP_FUNCTION ZEND_FUNCTION
4166 #define PHP_METHOD ZEND_METHOD
4167
4168+#define PHP_STATIC_FE ZEND_STATIC_FE
4169 #define PHP_NAMED_FE ZEND_NAMED_FE
4170 #define PHP_FE ZEND_FE
4171 #define PHP_FALIAS ZEND_FALIAS
4172@@ -435,6 +444,10 @@
4173 #endif
4174 #endif /* !XtOffsetOf */
4175
4176+#if HARDENING_PATCH
4177+#include "hardening_patch.h"
4178+#endif
4179+
4180 #endif
4181
4182 /*
4183diff -Nura php-5.0.5/main/php_variables.c hardening-patch-5.0.5-0.4.3/main/php_variables.c
4184--- php-5.0.5/main/php_variables.c 2005-09-01 21:15:51.000000000 +0200
4185+++ hardening-patch-5.0.5-0.4.3/main/php_variables.c 2005-09-11 23:30:52.000000000 +0200
4186@@ -514,7 +514,7 @@
4187 */
4188 static inline void php_register_server_variables(TSRMLS_D)
4189 {
4190- zval *array_ptr=NULL;
4191+ zval *array_ptr=NULL, *vptr;
4192 /* turn off magic_quotes while importing server variables */
4193 int magic_quotes_gpc = PG(magic_quotes_gpc);
4194
4195@@ -530,6 +530,16 @@
4196 /* Server variables */
4197 if (sapi_module.register_server_variables) {
4198 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
4199+ if (zend_hash_find(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), (void **)&vptr)==SUCCESS) {
4200+ char *str;
4201+ if (vptr->type != IS_STRING) {
4202+ str = "Array";
4203+ } else {
4204+ str = vptr->value.str.val;
4205+ }
4206+ php_security_log(S_VARS, "Attacker tried to overwrite HTTP_RAW_POST_DATA with '%s' through a HTTP header", str);
4207+ zend_hash_del(array_ptr->value.ht, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
4208+ }
4209 }
4210
4211 /* PHP Authentication support */
4212diff -Nura php-5.0.5/main/rfc1867.c hardening-patch-5.0.5-0.4.3/main/rfc1867.c
4213--- php-5.0.5/main/rfc1867.c 2005-07-13 22:51:12.000000000 +0200
4214+++ hardening-patch-5.0.5-0.4.3/main/rfc1867.c 2005-09-11 23:58:14.000000000 +0200
4215@@ -132,6 +132,7 @@
4216 #define UPLOAD_ERROR_D 4 /* No file uploaded */
4217 #define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
4218 #define UPLOAD_ERROR_F 7 /* Failed to write file to disk */
4219+#define UPLOAD_ERROR_X 32 /* Filter forbids fileupload */
4220
4221 void php_rfc1867_register_constants(TSRMLS_D)
4222 {
4223@@ -142,6 +143,7 @@
4224 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
4225 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
4226 REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_CANT_WRITE", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
4227+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_X, CONST_CS | CONST_PERSISTENT);
4228 }
4229
4230 static void normalize_protected_variable(char *varname TSRMLS_DC)
4231@@ -854,6 +856,7 @@
4232 char buff[FILLUNIT];
4233 char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
4234 int blen=0, wlen=0;
4235+ unsigned long offset;
4236
4237 zend_llist_clean(&header);
4238
4239@@ -970,7 +973,11 @@
4240 tmp++;
4241 }
4242 }
4243-
4244+
4245+ if (sapi_module.upload_varname_filter && sapi_module.upload_varname_filter(param TSRMLS_CC)==FAILURE) {
4246+ skip_upload = 1;
4247+ }
4248+
4249 total_bytes = cancel_upload = 0;
4250
4251 if (!skip_upload) {
4252@@ -994,6 +1001,11 @@
4253 cancel_upload = UPLOAD_ERROR_D;
4254 }
4255
4256+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
4257+ cancel_upload = UPLOAD_ERROR_X;
4258+ }
4259+
4260+ offset = 0;
4261 end = 0;
4262 while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC)))
4263 {
4264@@ -1008,6 +1020,10 @@
4265 #endif
4266 cancel_upload = UPLOAD_ERROR_B;
4267 } else if (blen > 0) {
4268+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
4269+ cancel_upload = UPLOAD_ERROR_X;
4270+ }
4271+
4272 wlen = write(fd, buff, blen);
4273
4274 if (wlen < blen) {
4275@@ -1036,6 +1052,10 @@
4276 }
4277 #endif
4278
4279+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
4280+ cancel_upload = UPLOAD_ERROR_X;
4281+ }
4282+
4283 if (cancel_upload) {
4284 if (temp_filename) {
4285 if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
4286diff -Nura php-5.0.5/main/SAPI.c hardening-patch-5.0.5-0.4.3/main/SAPI.c
4287--- php-5.0.5/main/SAPI.c 2005-02-22 15:46:15.000000000 +0100
4288+++ hardening-patch-5.0.5-0.4.3/main/SAPI.c 2005-09-12 00:00:07.000000000 +0200
4289@@ -821,6 +821,36 @@
4290 zend_hash_del(&known_post_content_types, post_entry->content_type, post_entry->content_type_len+1);
4291 }
4292
4293+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
4294+{
4295+ sapi_module.input_filter = input_filter;
4296+ return SUCCESS;
4297+}
4298+
4299+SAPI_API int sapi_register_upload_varname_filter(unsigned int (*upload_varname_filter)(char *varname TSRMLS_DC))
4300+{
4301+ sapi_module.upload_varname_filter = upload_varname_filter;
4302+ return SUCCESS;
4303+}
4304+
4305+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
4306+{
4307+ sapi_module.pre_upload_filter = pre_upload_filter;
4308+ return SUCCESS;
4309+}
4310+
4311+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
4312+{
4313+ sapi_module.upload_content_filter = upload_content_filter;
4314+ return SUCCESS;
4315+}
4316+
4317+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
4318+{
4319+ sapi_module.post_upload_filter = post_upload_filter;
4320+ return SUCCESS;
4321+}
4322+
4323
4324 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
4325 {
4326@@ -835,11 +865,6 @@
4327 return SUCCESS;
4328 }
4329
4330-SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
4331-{
4332- sapi_module.input_filter = input_filter;
4333- return SUCCESS;
4334-}
4335
4336 SAPI_API int sapi_flush(TSRMLS_D)
4337 {
4338diff -Nura php-5.0.5/main/SAPI.h hardening-patch-5.0.5-0.4.3/main/SAPI.h
4339--- php-5.0.5/main/SAPI.h 2004-01-08 18:33:04.000000000 +0100
4340+++ hardening-patch-5.0.5-0.4.3/main/SAPI.h 2005-09-12 00:29:07.000000000 +0200
4341@@ -103,9 +103,10 @@
4342 char *current_user;
4343 int current_user_length;
4344
4345- /* this is necessary for CLI module */
4346- int argc;
4347- char **argv;
4348+ /* this is necessary for CLI module */
4349+ int argc;
4350+ char **argv;
4351+
4352 } sapi_request_info;
4353
4354
4355@@ -183,6 +184,10 @@
4356 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
4357 SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
4358
4359+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
4360+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
4361+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
4362+
4363 SAPI_API int sapi_flush(TSRMLS_D);
4364 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
4365 SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC);
4366@@ -245,6 +250,11 @@
4367 int (*get_target_gid)(gid_t * TSRMLS_DC);
4368
4369 unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
4370+
4371+ unsigned int (*upload_varname_filter)(char *varname TSRMLS_DC);
4372+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
4373+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
4374+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
4375
4376 void (*ini_defaults)(HashTable *configuration_hash);
4377 int phpinfo_as_text;
4378@@ -270,7 +280,11 @@
4379
4380 #define SAPI_DEFAULT_MIMETYPE "text/html"
4381 #define SAPI_DEFAULT_CHARSET ""
4382+#if HARDENING_PATCH
4383+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
4384+#else
4385 #define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
4386+#endif
4387
4388 #define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
4389 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
4390@@ -278,6 +292,11 @@
4391 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
4392 #define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
4393
4394+#define SAPI_UPLOAD_VARNAME_FILTER_FUNC(upload_varname_filter) unsigned int upload_varname_filter(char *varname TSRMLS_DC)
4395+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
4396+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
4397+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
4398+
4399 BEGIN_EXTERN_C()
4400 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
4401 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
4402diff -Nura php-5.0.5/main/snprintf.c hardening-patch-5.0.5-0.4.3/main/snprintf.c
4403--- php-5.0.5/main/snprintf.c 2004-11-16 00:14:40.000000000 +0100
4404+++ hardening-patch-5.0.5-0.4.3/main/snprintf.c 2005-09-11 23:30:52.000000000 +0200
4405@@ -1013,7 +1013,11 @@
4406
4407
4408 case 'n':
4409+#if HARDENING_PATCH_FMT_PROTECT
4410+ php_security_log(S_MISC, "'n' specifier within format string");
4411+#else
4412 *(va_arg(ap, int *)) = cc;
4413+#endif
4414 break;
4415
4416 /*
4417diff -Nura php-5.0.5/main/spprintf.c hardening-patch-5.0.5-0.4.3/main/spprintf.c
4418--- php-5.0.5/main/spprintf.c 2004-04-16 01:04:49.000000000 +0200
4419+++ hardening-patch-5.0.5-0.4.3/main/spprintf.c 2005-09-11 23:30:52.000000000 +0200
4420@@ -630,7 +630,11 @@
4421
4422
4423 case 'n':
4424+#if HARDENING_PATCH_FMT_PROTECT
4425+ php_security_log(S_MISC, "'n' specifier within format string");
4426+#else
4427 *(va_arg(ap, int *)) = xbuf->len;
4428+#endif
4429 break;
4430
4431 /*
4432diff -Nura php-5.0.5/php.ini-dist hardening-patch-5.0.5-0.4.3/php.ini-dist
4433--- php-5.0.5/php.ini-dist 2005-05-05 14:33:56.000000000 +0200
4434+++ hardening-patch-5.0.5-0.4.3/php.ini-dist 2005-09-12 23:47:08.000000000 +0200
4435@@ -1197,6 +1197,197 @@
4436 ; instead of original one.
4437 soap.wsdl_cache_ttl=86400
4438
4439+[hardening-patch]
4440+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4441+; Hardening-Patch's logging ;
4442+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4443+
4444+;
4445+; hphp.log.syslog - Configures level for alerts reported through syslog
4446+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
4447+; hphp.log.script - Configures level for alerts reported through external script
4448+;
4449+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
4450+; Or each number up to get desired Hardening-Patch's reporting level
4451+;
4452+; S_ALL - All alerts
4453+; S_MEMORY - All canary violations and the safe unlink protection use this class
4454+; S_VARS - All variable filters trigger this class
4455+; S_FILES - All violation of uploaded files filter use this class
4456+; S_INCLUDE - The protection against malicious include filenames use this class
4457+; S_SQL - Failed SQL queries in MySQL are logged with this class
4458+; S_EXECUTOR - The execution depth protection uses this logging class
4459+; S_MISC - All other log messages (f.e. format string protection) use this class
4460+;
4461+; Example:
4462+;
4463+; - Report all alerts (except memory alerts) to the SAPI errorlog,
4464+; memory alerts through syslog and SQL+Include alerts fo the script
4465+;
4466+;hphp.log.syslog = S_MEMORY
4467+;hphp.log.sapi = S_ALL & ~S_MEMORY
4468+;hphp.log.script = S_INCLUDE | S_SQL
4469+;
4470+; Syslog logging:
4471+;
4472+; - Facility configuration: one of the following facilities
4473+;
4474+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
4475+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
4476+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
4477+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
4478+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
4479+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
4480+; LOG_PERROR
4481+;
4482+; - Priority configuration: one of the followinf priorities
4483+;
4484+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
4485+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
4486+;
4487+hphp.log.syslog.priority = LOG_ALERT
4488+hphp.log.syslog.facility = LOG_USER
4489+;
4490+; Script logging:
4491+;
4492+;hphp.log.script.name = /home/hphp/log_script
4493+;
4494+; Alert configuration:
4495+;
4496+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
4497+;
4498+;hphp.log.use-x-forwarded-for = On
4499+;
4500+
4501+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4502+; Hardening-Patch's Executor options ;
4503+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4504+
4505+; Execution depth limit
4506+;hphp.executor.max_depth = 8000
4507+
4508+; White-/blacklist for function calls during normal execution
4509+;hphp.executor.func.whitelist = ord,chr
4510+;hphp.executor.func.blacklist = system,shell_exec,popen,proc_open,exec,passthru
4511+
4512+; White-/blacklist for function calls during eval() execution
4513+;hphp.executor.eval.whitelist = ord,chr
4514+;hphp.executor.eval.blacklist = system,shell_exec,popen,proc_open,exec,passthru
4515+
4516+; White-/blacklist for URLs allowes in include filenames
4517+;
4518+; - When both options are not set all URLs are forbidden
4519+;
4520+; - When both options are set whitelist is taken and blacklist ignored
4521+;
4522+; - An entry in the lists is either a URL sheme like: http, https
4523+; or the beginning of an URL like: php://input
4524+;
4525+;hphp.executor.include.whitelist = cookietest
4526+;hphp.executor.include.blacklist = http, https, ftp, ftps, php://input, file
4527+
4528+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4529+; Hardening-Patch's REQUEST variable filters ;
4530+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4531+
4532+; Limits the number of REQUEST variables
4533+hphp.request.max_vars = 200
4534+
4535+; Limits the length of variable names (without indices)
4536+hphp.request.max_varname_length = 64
4537+
4538+; Limits the length of complete variable names (with indices)
4539+hphp.request.max_totalname_length = 256
4540+
4541+; Limits the length of array indices
4542+hphp.request.max_array_index_length = 64
4543+
4544+; Limits the depth of arrays
4545+hphp.request.max_array_depth = 100
4546+
4547+; Limits the length of variable values
4548+hphp.request.max_value_length = 65000
4549+
4550+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4551+; Hardening-Patch's COOKIE variable filters ;
4552+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4553+
4554+; Limits the number of COOKIE variables
4555+hphp.cookie.max_vars = 100
4556+
4557+; Limits the length of variable names (without indices)
4558+hphp.cookie.max_name_length = 64
4559+
4560+; Limits the length of complete variable names (with indices)
4561+hphp.cookie.max_totalname_length = 256
4562+
4563+; Limits the length of array indices
4564+hphp.cookie.max_array_index_length = 64
4565+
4566+; Limits the depth of arrays
4567+hphp.cookie.max_array_depth = 100
4568+
4569+; Limits the length of variable values
4570+hphp.cookie.max_value_length = 10000
4571+
4572+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4573+; Hardening-Patch's GET variable filters ;
4574+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4575+
4576+; Limits the number of COOKIE variables
4577+hphp.get.max_vars = 100
4578+
4579+; Limits the length of variable names (without indices)
4580+hphp.get.max_name_length = 64
4581+
4582+; Limits the length of complete variable names (with indices)
4583+hphp.get.max_totalname_length = 256
4584+
4585+; Limits the length of array indices
4586+hphp.get.max_array_index_length = 64
4587+
4588+; Limits the depth of arrays
4589+hphp.get.max_array_depth = 50
4590+
4591+; Limits the length of variable values
4592+hphp.get.max_value_length = 512
4593+
4594+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4595+; Hardening-Patch's POST variable filters ;
4596+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4597+
4598+; Limits the number of POST variables
4599+hphp.post.max_vars = 200
4600+
4601+; Limits the length of variable names (without indices)
4602+hphp.post.max_name_length = 64
4603+
4604+; Limits the length of complete variable names (with indices)
4605+hphp.post.max_totalname_length = 256
4606+
4607+; Limits the length of array indices
4608+hphp.post.max_array_index_length = 64
4609+
4610+; Limits the depth of arrays
4611+hphp.post.max_array_depth = 100
4612+
4613+; Limits the length of variable values
4614+hphp.post.max_value_length = 65000
4615+
4616+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4617+; Hardening-Patch's fileupload variable filters ;
4618+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4619+
4620+; Limits the number of uploadable files
4621+hphp.upload.max_uploads = 25
4622+
4623+; Filter out the upload of ELF executables
4624+hphp.upload.disallow_elf_files = On
4625+
4626+; External filterscript for upload verification
4627+;hphp.upload.verification_script = /home/hphp/verify_script
4628+
4629+
4630 ; Local Variables:
4631 ; tab-width: 4
4632 ; End:
4633diff -Nura php-5.0.5/php.ini-recommended hardening-patch-5.0.5-0.4.3/php.ini-recommended
4634--- php-5.0.5/php.ini-recommended 2005-05-05 14:33:56.000000000 +0200
4635+++ hardening-patch-5.0.5-0.4.3/php.ini-recommended 2005-09-12 23:53:06.000000000 +0200
4636@@ -1255,6 +1255,196 @@
4637 ; instead of original one.
4638 soap.wsdl_cache_ttl=86400
4639
4640+[hardening-patch]
4641+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4642+; Hardening-Patch's logging ;
4643+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4644+
4645+;
4646+; hphp.log.syslog - Configures level for alerts reported through syslog
4647+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
4648+; hphp.log.script - Configures level for alerts reported through external script
4649+;
4650+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
4651+; Or each number up to get desired Hardening-Patch's reporting level
4652+;
4653+; S_ALL - All alerts
4654+; S_MEMORY - All canary violations and the safe unlink protection use this class
4655+; S_VARS - All variable filters trigger this class
4656+; S_FILES - All violation of uploaded files filter use this class
4657+; S_INCLUDE - The protection against malicious include filenames use this class
4658+; S_SQL - Failed SQL queries in MySQL are logged with this class
4659+; S_EXECUTOR - The execution depth protection uses this logging class
4660+; S_MISC - All other log messages (f.e. format string protection) use this class
4661+;
4662+; Example:
4663+;
4664+; - Report all alerts (except memory alerts) to the SAPI errorlog,
4665+; memory alerts through syslog and SQL+Include alerts fo the script
4666+;
4667+;hphp.log.syslog = S_MEMORY
4668+;hphp.log.sapi = S_ALL & ~S_MEMORY
4669+;hphp.log.script = S_INCLUDE | S_SQL
4670+;
4671+; Syslog logging:
4672+;
4673+; - Facility configuration: one of the following facilities
4674+;
4675+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
4676+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
4677+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
4678+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
4679+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
4680+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
4681+; LOG_PERROR
4682+;
4683+; - Priority configuration: one of the followinf priorities
4684+;
4685+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
4686+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
4687+;
4688+hphp.log.syslog.priority = LOG_ALERT
4689+hphp.log.syslog.facility = LOG_USER
4690+;
4691+; Script logging:
4692+;
4693+;hphp.log.script.name = /home/hphp/log_script
4694+;
4695+; Alert configuration:
4696+;
4697+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
4698+;
4699+;hphp.log.use-x-forwarded-for = On
4700+;
4701+
4702+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4703+; Hardening-Patch's Executor options ;
4704+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4705+
4706+; Execution depth limit
4707+;hphp.executor.max_depth = 8000
4708+
4709+; White-/blacklist for function calls during normal execution
4710+;hphp.executor.func.whitelist = ord,chr
4711+;hphp.executor.func.blacklist = system,shell_exec,popen,proc_open,exec,passthru
4712+
4713+; White-/blacklist for function calls during eval() execution
4714+;hphp.executor.eval.whitelist = ord,chr
4715+;hphp.executor.eval.blacklist = system,shell_exec,popen,proc_open,exec,passthru
4716+
4717+; White-/blacklist for URLs allowes in include filenames
4718+;
4719+; - When both options are not set all URLs are forbidden
4720+;
4721+; - When both options are set whitelist is taken and blacklist ignored
4722+;
4723+; - An entry in the lists is either a URL sheme like: http, https
4724+; or the beginning of an URL like: php://input
4725+;
4726+;hphp.executor.include.whitelist = cookietest
4727+;hphp.executor.include.blacklist = http, https, ftp, ftps, php://input, file
4728+
4729+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4730+; Hardening-Patch's REQUEST variable filters ;
4731+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4732+
4733+; Limits the number of REQUEST variables
4734+hphp.request.max_vars = 200
4735+
4736+; Limits the length of variable names (without indices)
4737+hphp.request.max_varname_length = 64
4738+
4739+; Limits the length of complete variable names (with indices)
4740+hphp.request.max_totalname_length = 256
4741+
4742+; Limits the length of array indices
4743+hphp.request.max_array_index_length = 64
4744+
4745+; Limits the depth of arrays
4746+hphp.request.max_array_depth = 100
4747+
4748+; Limits the length of variable values
4749+hphp.request.max_value_length = 65000
4750+
4751+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4752+; Hardening-Patch's COOKIE variable filters ;
4753+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4754+
4755+; Limits the number of COOKIE variables
4756+hphp.cookie.max_vars = 100
4757+
4758+; Limits the length of variable names (without indices)
4759+hphp.cookie.max_name_length = 64
4760+
4761+; Limits the length of complete variable names (with indices)
4762+hphp.cookie.max_totalname_length = 256
4763+
4764+; Limits the length of array indices
4765+hphp.cookie.max_array_index_length = 64
4766+
4767+; Limits the depth of arrays
4768+hphp.cookie.max_array_depth = 100
4769+
4770+; Limits the length of variable values
4771+hphp.cookie.max_value_length = 10000
4772+
4773+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4774+; Hardening-Patch's GET variable filters ;
4775+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4776+
4777+; Limits the number of COOKIE variables
4778+hphp.get.max_vars = 100
4779+
4780+; Limits the length of variable names (without indices)
4781+hphp.get.max_name_length = 64
4782+
4783+; Limits the length of complete variable names (with indices)
4784+hphp.get.max_totalname_length = 256
4785+
4786+; Limits the length of array indices
4787+hphp.get.max_array_index_length = 64
4788+
4789+; Limits the depth of arrays
4790+hphp.get.max_array_depth = 50
4791+
4792+; Limits the length of variable values
4793+hphp.get.max_value_length = 512
4794+
4795+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4796+; Hardening-Patch's POST variable filters ;
4797+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4798+
4799+; Limits the number of POST variables
4800+hphp.post.max_vars = 200
4801+
4802+; Limits the length of variable names (without indices)
4803+hphp.post.max_name_length = 64
4804+
4805+; Limits the length of complete variable names (with indices)
4806+hphp.post.max_totalname_length = 256
4807+
4808+; Limits the length of array indices
4809+hphp.post.max_array_index_length = 64
4810+
4811+; Limits the depth of arrays
4812+hphp.post.max_array_depth = 100
4813+
4814+; Limits the length of variable values
4815+hphp.post.max_value_length = 65000
4816+
4817+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4818+; Hardening-Patch's fileupload variable filters ;
4819+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4820+
4821+; Limits the number of uploadable files
4822+hphp.upload.max_uploads = 25
4823+
4824+; Filter out the upload of ELF executables
4825+hphp.upload.disallow_elf_files = On
4826+
4827+; External filterscript for upload verification
4828+;hphp.upload.verification_script = /home/hphp/verify_script
4829+
4830 ; Local Variables:
4831 ; tab-width: 4
4832 ; End:
4833diff -Nura php-5.0.5/sapi/apache/mod_php5.c hardening-patch-5.0.5-0.4.3/sapi/apache/mod_php5.c
4834--- php-5.0.5/sapi/apache/mod_php5.c 2005-08-01 10:12:42.000000000 +0200
4835+++ hardening-patch-5.0.5-0.4.3/sapi/apache/mod_php5.c 2005-09-11 23:30:52.000000000 +0200
4836@@ -455,7 +455,7 @@
4837 sapi_apache_get_fd,
4838 sapi_apache_force_http_10,
4839 sapi_apache_get_target_uid,
4840- sapi_apache_get_target_gid
4841+ sapi_apache_get_target_gid,
4842 };
4843 /* }}} */
4844
4845@@ -907,7 +907,11 @@
4846 {
4847 TSRMLS_FETCH();
4848 if (PG(expose_php)) {
4849+#if HARDENING_PATCH
4850+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
4851+#else
4852 ap_add_version_component("PHP/" PHP_VERSION);
4853+#endif
4854 }
4855 }
4856 #endif
4857diff -Nura php-5.0.5/sapi/apache2filter/sapi_apache2.c hardening-patch-5.0.5-0.4.3/sapi/apache2filter/sapi_apache2.c
4858--- php-5.0.5/sapi/apache2filter/sapi_apache2.c 2005-07-16 14:30:10.000000000 +0200
4859+++ hardening-patch-5.0.5-0.4.3/sapi/apache2filter/sapi_apache2.c 2005-09-11 23:30:52.000000000 +0200
4860@@ -562,7 +562,11 @@
4861 {
4862 TSRMLS_FETCH();
4863 if (PG(expose_php)) {
4864+#if HARDENING_PATCH
4865+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
4866+#else
4867 ap_add_version_component(p, "PHP/" PHP_VERSION);
4868+#endif
4869 }
4870 }
4871
4872diff -Nura php-5.0.5/sapi/apache2handler/sapi_apache2.c hardening-patch-5.0.5-0.4.3/sapi/apache2handler/sapi_apache2.c
4873--- php-5.0.5/sapi/apache2handler/sapi_apache2.c 2005-09-02 15:51:26.000000000 +0200
4874+++ hardening-patch-5.0.5-0.4.3/sapi/apache2handler/sapi_apache2.c 2005-09-11 23:30:52.000000000 +0200
4875@@ -333,7 +333,11 @@
4876 {
4877 TSRMLS_FETCH();
4878 if (PG(expose_php)) {
4879+#if HARDENING_PATCH
4880+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
4881+#else
4882 ap_add_version_component(p, "PHP/" PHP_VERSION);
4883+#endif
4884 }
4885 }
4886
4887diff -Nura php-5.0.5/sapi/cgi/cgi_main.c hardening-patch-5.0.5-0.4.3/sapi/cgi/cgi_main.c
4888--- php-5.0.5/sapi/cgi/cgi_main.c 2005-04-28 16:24:21.000000000 +0200
4889+++ hardening-patch-5.0.5-0.4.3/sapi/cgi/cgi_main.c 2005-09-11 23:30:52.000000000 +0200
4890@@ -1419,11 +1419,19 @@
4891 SG(headers_sent) = 1;
4892 SG(request_info).no_headers = 1;
4893 }
4894+#if HARDENING_PATCH
4895+#if ZEND_DEBUG
4896+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4897+#else
4898+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4899+#endif
4900+#else
4901 #if ZEND_DEBUG
4902 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4903 #else
4904 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4905 #endif
4906+#endif
4907 php_end_ob_buffers(1 TSRMLS_CC);
4908 exit(1);
4909 break;
4910diff -Nura php-5.0.5/sapi/cli/php_cli.c hardening-patch-5.0.5-0.4.3/sapi/cli/php_cli.c
4911--- php-5.0.5/sapi/cli/php_cli.c 2005-03-22 16:09:20.000000000 +0100
4912+++ hardening-patch-5.0.5-0.4.3/sapi/cli/php_cli.c 2005-09-11 23:30:52.000000000 +0200
4913@@ -694,11 +694,19 @@
4914 if (php_request_startup(TSRMLS_C)==FAILURE) {
4915 goto err;
4916 }
4917+#if HARDENING_PATCH
4918+#if ZEND_DEBUG
4919+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4920+#else
4921+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4922+#endif
4923+#else
4924 #if ZEND_DEBUG
4925 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4926 #else
4927 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
4928 #endif
4929+#endif
4930 php_end_ob_buffers(1 TSRMLS_CC);
4931 exit_status=1;
4932 goto out;
4933diff -Nura php-5.0.5/TSRM/TSRM.h hardening-patch-5.0.5-0.4.3/TSRM/TSRM.h
4934--- php-5.0.5/TSRM/TSRM.h 2005-03-11 12:12:07.000000000 +0100
4935+++ hardening-patch-5.0.5-0.4.3/TSRM/TSRM.h 2005-09-11 23:30:52.000000000 +0200
4936@@ -33,6 +33,13 @@
4937 # define TSRM_API
4938 #endif
4939
4940+#if HARDENING_PATCH
4941+# if HAVE_REALPATH
4942+# undef realpath
4943+# define realpath php_realpath
4944+# endif
4945+#endif
4946+
4947 /* Only compile multi-threading functions if we're in ZTS mode */
4948 #ifdef ZTS
4949
4950@@ -88,6 +95,7 @@
4951
4952 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
4953
4954+
4955 #ifdef __cplusplus
4956 extern "C" {
4957 #endif
4958diff -Nura php-5.0.5/TSRM/tsrm_virtual_cwd.c hardening-patch-5.0.5-0.4.3/TSRM/tsrm_virtual_cwd.c
4959--- php-5.0.5/TSRM/tsrm_virtual_cwd.c 2005-07-16 13:50:59.000000000 +0200
4960+++ hardening-patch-5.0.5-0.4.3/TSRM/tsrm_virtual_cwd.c 2005-09-11 23:30:52.000000000 +0200
4961@@ -184,6 +184,165 @@
4962 return p;
4963 }
4964
4965+#if HARDENING_PATCH
4966+CWD_API char *php_realpath(const char *path, char *resolved)
4967+{
4968+ struct stat sb;
4969+ char *p, *q, *s;
4970+ size_t left_len, resolved_len;
4971+ unsigned symlinks;
4972+ int serrno, slen;
4973+ int is_dir = 1;
4974+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
4975+
4976+ serrno = errno;
4977+ symlinks = 0;
4978+ if (path[0] == '/') {
4979+ resolved[0] = '/';
4980+ resolved[1] = '\0';
4981+ if (path[1] == '\0')
4982+ return (resolved);
4983+ resolved_len = 1;
4984+ left_len = strlcpy(left, path + 1, sizeof(left));
4985+ } else {
4986+ if (getcwd(resolved, PATH_MAX) == NULL) {
4987+ strlcpy(resolved, ".", PATH_MAX);
4988+ return (NULL);
4989+ }
4990+ resolved_len = strlen(resolved);
4991+ left_len = strlcpy(left, path, sizeof(left));
4992+ }
4993+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
4994+ errno = ENAMETOOLONG;
4995+ return (NULL);
4996+ }
4997+
4998+ /*
4999+ * Iterate over path components in `left'.
5000+ */
5001+ while (left_len != 0) {
5002+ /*
5003+ * Extract the next path component and adjust `left'
5004+ * and its length.
5005+ */
5006+ p = strchr(left, '/');
5007+ s = p ? p : left + left_len;
5008+ if (s - left >= sizeof(next_token)) {
5009+ errno = ENAMETOOLONG;
5010+ return (NULL);
5011+ }
5012+ memcpy(next_token, left, s - left);
5013+ next_token[s - left] = '\0';
5014+ left_len -= s - left;
5015+ if (p != NULL)
5016+ memmove(left, s + 1, left_len + 1);
5017+ if (resolved[resolved_len - 1] != '/') {
5018+ if (resolved_len + 1 >= PATH_MAX) {
5019+ errno = ENAMETOOLONG;
5020+ return (NULL);
5021+ }
5022+ resolved[resolved_len++] = '/';
5023+ resolved[resolved_len] = '\0';
5024+ }
5025+ if (next_token[0] == '\0')
5026+ continue;
5027+ else if (strcmp(next_token, ".") == 0)
5028+ continue;
5029+ else if (strcmp(next_token, "..") == 0) {
5030+ /*
5031+ * Strip the last path component except when we have
5032+ * single "/"
5033+ */
5034+ if (!is_dir) {
5035+ errno = ENOENT;
5036+ return (NULL);
5037+ }
5038+ if (resolved_len > 1) {
5039+ resolved[resolved_len - 1] = '\0';
5040+ q = strrchr(resolved, '/');
5041+ *q = '\0';
5042+ resolved_len = q - resolved;
5043+ }
5044+ continue;
5045+ }
5046+
5047+ /*
5048+ * Append the next path component and lstat() it. If
5049+ * lstat() fails we still can return successfully if
5050+ * there are no more path components left.
5051+ */
5052+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
5053+ if (resolved_len >= PATH_MAX) {
5054+ errno = ENAMETOOLONG;
5055+ return (NULL);
5056+ }
5057+ if (lstat(resolved, &sb) != 0) {
5058+ if (errno == ENOENT && p == NULL) {
5059+ errno = serrno;
5060+ return (resolved);
5061+ }
5062+ return (NULL);
5063+ }
5064+ if (S_ISLNK(sb.st_mode)) {
5065+ if (symlinks++ > MAXSYMLINKS) {
5066+ errno = ELOOP;
5067+ return (NULL);
5068+ }
5069+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
5070+ if (slen < 0)
5071+ return (NULL);
5072+ symlink[slen] = '\0';
5073+ if (symlink[0] == '/') {
5074+ resolved[1] = 0;
5075+ resolved_len = 1;
5076+ } else if (resolved_len > 1) {
5077+ /* Strip the last path component. */
5078+ resolved[resolved_len - 1] = '\0';
5079+ q = strrchr(resolved, '/');
5080+ *q = '\0';
5081+ resolved_len = q - resolved;
5082+ }
5083+
5084+ /*
5085+ * If there are any path components left, then
5086+ * append them to symlink. The result is placed
5087+ * in `left'.
5088+ */
5089+ if (p != NULL) {
5090+ if (symlink[slen - 1] != '/') {
5091+ if (slen + 1 >= sizeof(symlink)) {
5092+ errno = ENAMETOOLONG;
5093+ return (NULL);
5094+ }
5095+ symlink[slen] = '/';
5096+ symlink[slen + 1] = 0;
5097+ }
5098+ left_len = strlcat(symlink, left, sizeof(left));
5099+ if (left_len >= sizeof(left)) {
5100+ errno = ENAMETOOLONG;
5101+ return (NULL);
5102+ }
5103+ }
5104+ left_len = strlcpy(left, symlink, sizeof(left));
5105+ } else {
5106+ if (S_ISDIR(sb.st_mode)) {
5107+ is_dir = 1;
5108+ } else {
5109+ is_dir = 0;
5110+ }
5111+ }
5112+ }
5113+
5114+ /*
5115+ * Remove trailing slash except when the resolved pathname
5116+ * is a single "/".
5117+ */
5118+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
5119+ resolved[resolved_len - 1] = '\0';
5120+ return (resolved);
5121+}
5122+#endif
5123+
5124 CWD_API void virtual_cwd_startup(void)
5125 {
5126 char cwd[MAXPATHLEN];
5127@@ -321,8 +480,7 @@
5128 path = resolved_path;
5129 path_length = strlen(path);
5130 } else {
5131- /* disable for now
5132- return 1; */
5133+ return 1;
5134 }
5135 }
5136 } else { /* Concat current directory with relative path and then run realpath() on it */
5137@@ -348,9 +506,8 @@
5138 path = resolved_path;
5139 path_length = strlen(path);
5140 } else {
5141- /* disable for now
5142 free(tmp);
5143- return 1; */
5144+ return 1;
5145 }
5146 }
5147 free(tmp);
5148diff -Nura php-5.0.5/TSRM/tsrm_virtual_cwd.h hardening-patch-5.0.5-0.4.3/TSRM/tsrm_virtual_cwd.h
5149--- php-5.0.5/TSRM/tsrm_virtual_cwd.h 2005-07-16 13:50:59.000000000 +0200
5150+++ hardening-patch-5.0.5-0.4.3/TSRM/tsrm_virtual_cwd.h 2005-09-11 23:30:52.000000000 +0200
5151@@ -126,6 +126,22 @@
5152
5153 typedef int (*verify_path_func)(const cwd_state *);
5154
5155+#ifndef HAVE_STRLCPY
5156+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
5157+#undef strlcpy
5158+#define strlcpy php_strlcpy
5159+#endif
5160+
5161+#ifndef HAVE_STRLCAT
5162+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
5163+#undef strlcat
5164+#define strlcat php_strlcat
5165+#endif
5166+
5167+
5168+#if HARDENING_PATCH
5169+CWD_API char *php_realpath(const char *path, char *resolved);
5170+#endif
5171 CWD_API void virtual_cwd_startup(void);
5172 CWD_API void virtual_cwd_shutdown(void);
5173 CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
5174diff -Nura php-5.0.5/Zend/zend_alloc.c hardening-patch-5.0.5-0.4.3/Zend/zend_alloc.c
5175--- php-5.0.5/Zend/zend_alloc.c 2005-08-18 17:14:23.000000000 +0200
5176+++ hardening-patch-5.0.5-0.4.3/Zend/zend_alloc.c 2005-09-11 23:30:52.000000000 +0200
5177@@ -64,6 +64,11 @@
5178 # define END_MAGIC_SIZE 0
5179 #endif
5180
5181+#if HARDENING_PATCH_MM_PROTECT
5182+# define CANARY_SIZE sizeof(unsigned int)
5183+#else
5184+# define CANARY_SIZE 0
5185+#endif
5186
5187 # if MEMORY_LIMIT
5188 # if ZEND_DEBUG
5189@@ -105,9 +110,17 @@
5190 if (p==AG(head)) { \
5191 AG(head) = p->pNext; \
5192 } else { \
5193+ if (p != p->pLast->pNext) { \
5194+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
5195+ exit(1); \
5196+ } \
5197 p->pLast->pNext = p->pNext; \
5198 } \
5199 if (p->pNext) { \
5200+ if (p != p->pNext->pLast) { \
5201+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
5202+ exit(1); \
5203+ } \
5204 p->pNext->pLast = p->pLast; \
5205 }
5206 #else
5207@@ -146,6 +159,12 @@
5208 DECLARE_CACHE_VARS();
5209 TSRMLS_FETCH();
5210
5211+#if HARDENING_PATCH_MM_PROTECT
5212+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
5213+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
5214+ exit(1);
5215+ }
5216+#endif
5217 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
5218
5219 #if !ZEND_DISABLE_MEMORY_CACHE
5220@@ -164,6 +183,10 @@
5221 AG(cache_stats)[CACHE_INDEX][1]++;
5222 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
5223 #endif
5224+#if HARDENING_PATCH_MM_PROTECT
5225+ p->canary = HG(canary_1);
5226+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
5227+#endif
5228 p->cached = 0;
5229 p->size = size;
5230 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
5231@@ -180,7 +203,7 @@
5232 AG(allocated_memory_peak) = AG(allocated_memory);
5233 }
5234 #endif
5235- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
5236+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
5237 #if !ZEND_DISABLE_MEMORY_CACHE
5238 }
5239 #endif
5240@@ -212,7 +235,10 @@
5241 # endif
5242 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
5243 #endif
5244-
5245+#if HARDENING_PATCH_MM_PROTECT
5246+ p->canary = HG(canary_1);
5247+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
5248+#endif
5249 HANDLE_UNBLOCK_INTERRUPTIONS();
5250 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
5251 }
5252@@ -240,6 +266,10 @@
5253 }
5254 }
5255
5256+
5257+#if HARDENING_PATCH
5258+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
5259+#endif
5260 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset);
5261 return 0;
5262 }
5263@@ -248,9 +278,25 @@
5264
5265 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
5266 {
5267+#if HARDENING_PATCH_MM_PROTECT
5268+ unsigned int canary_2;
5269+#endif
5270 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
5271 DECLARE_CACHE_VARS();
5272 TSRMLS_FETCH();
5273+
5274+#if HARDENING_PATCH_MM_PROTECT
5275+ if (p->canary != HG(canary_1)) goto efree_canary_mismatch;
5276+ memcpy(&canary_2, (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), CANARY_SIZE);
5277+ if (canary_2 != HG(canary_2)) {
5278+efree_canary_mismatch:
5279+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
5280+ exit(1);
5281+ }
5282+ /* to catch double efree()s */
5283+ memset((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), 0, CANARY_SIZE);
5284+ p->canary = 0;
5285+#endif
5286
5287 #if defined(ZTS) && TSRM_DEBUG
5288 if (p->thread_id != tsrm_thread_id()) {
5289@@ -292,23 +338,35 @@
5290
5291 ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
5292 {
5293- void *p;
5294- int final_size = size*nmemb;
5295+ char *p;
5296+ size_t _size = nmemb * size;
5297+
5298+ if (nmemb && (_size/nmemb!=size)) {
5299+#if HARDENING_PATCH
5300+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
5301+#endif
5302+ fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
5303+#if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
5304+ kill(getpid(), SIGSEGV);
5305+#else
5306+ exit(1);
5307+#endif
5308+ }
5309
5310- HANDLE_BLOCK_INTERRUPTIONS();
5311- p = _emalloc(final_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
5312- if (!p) {
5313- HANDLE_UNBLOCK_INTERRUPTIONS();
5314- return (void *) p;
5315+ p = (char *) _emalloc(_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
5316+ if (p) {
5317+ memset(p, 0, _size);
5318 }
5319- memset(p, 0, final_size);
5320- HANDLE_UNBLOCK_INTERRUPTIONS();
5321- return p;
5322+
5323+ return ((void *)p);
5324 }
5325
5326
5327 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
5328 {
5329+#if HARDENING_PATCH_MM_PROTECT
5330+ unsigned int canary_2;
5331+#endif
5332 zend_mem_header *p;
5333 zend_mem_header *orig;
5334 DECLARE_CACHE_VARS();
5335@@ -320,6 +378,16 @@
5336
5337 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
5338
5339+#if HARDENING_PATCH_MM_PROTECT
5340+ if (p->canary != HG(canary_1)) goto erealloc_canary_mismatch;
5341+ memcpy(&canary_2, (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), CANARY_SIZE);
5342+ if (canary_2 != HG(canary_2)) {
5343+erealloc_canary_mismatch:
5344+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
5345+ exit(1);
5346+ }
5347+#endif
5348+
5349 #if defined(ZTS) && TSRM_DEBUG
5350 if (p->thread_id != tsrm_thread_id()) {
5351 void *new_p;
5352@@ -343,7 +411,7 @@
5353 }
5354 #endif
5355 REMOVE_POINTER_FROM_LIST(p);
5356- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
5357+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
5358 if (!p) {
5359 if (!allow_failure) {
5360 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
5361@@ -365,6 +433,9 @@
5362 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
5363 #endif
5364
5365+#if HARDENING_PATCH_MM_PROTECT
5366+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
5367+#endif
5368 p->size = size;
5369
5370 HANDLE_UNBLOCK_INTERRUPTIONS();
5371@@ -439,6 +510,10 @@
5372 {
5373 AG(head) = NULL;
5374
5375+#if HARDENING_PATCH_MM_PROTECT
5376+ HG(canary_1) = zend_canary();
5377+ HG(canary_2) = zend_canary();
5378+#endif
5379 #if MEMORY_LIMIT
5380 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
5381 AG(allocated_memory) = 0;
5382diff -Nura php-5.0.5/Zend/zend_alloc.h hardening-patch-5.0.5-0.4.3/Zend/zend_alloc.h
5383--- php-5.0.5/Zend/zend_alloc.h 2005-06-07 15:37:13.000000000 +0200
5384+++ hardening-patch-5.0.5-0.4.3/Zend/zend_alloc.h 2005-09-11 23:30:52.000000000 +0200
5385@@ -35,6 +35,9 @@
5386 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
5387
5388 typedef struct _zend_mem_header {
5389+#if HARDENING_PATCH_MM_PROTECT
5390+ unsigned int canary;
5391+#endif
5392 #if ZEND_DEBUG
5393 long magic;
5394 char *filename;
5395diff -Nura php-5.0.5/Zend/zend_API.h hardening-patch-5.0.5-0.4.3/Zend/zend_API.h
5396--- php-5.0.5/Zend/zend_API.h 2005-06-27 19:42:06.000000000 +0200
5397+++ hardening-patch-5.0.5-0.4.3/Zend/zend_API.h 2005-09-11 23:30:52.000000000 +0200
5398@@ -47,6 +47,7 @@
5399 #define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name))
5400
5401 #define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
5402+#define ZEND_STATIC_FE(zend_name, name, arg_info) { zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), 0 },
5403
5404 #define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0)
5405 #define ZEND_FE(name, arg_info) ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0)
5406diff -Nura php-5.0.5/Zend/zend_builtin_functions.c hardening-patch-5.0.5-0.4.3/Zend/zend_builtin_functions.c
5407--- php-5.0.5/Zend/zend_builtin_functions.c 2005-06-27 19:42:06.000000000 +0200
5408+++ hardening-patch-5.0.5-0.4.3/Zend/zend_builtin_functions.c 2005-09-11 23:30:52.000000000 +0200
5409@@ -52,6 +52,9 @@
5410 static ZEND_FUNCTION(crash);
5411 #endif
5412 #endif
5413+#if HARDENING_PATCH_MM_PROTECT_DEBUG
5414+static ZEND_FUNCTION(heap_overflow);
5415+#endif
5416 static ZEND_FUNCTION(get_included_files);
5417 static ZEND_FUNCTION(is_subclass_of);
5418 static ZEND_FUNCTION(is_a);
5419@@ -111,6 +114,9 @@
5420 ZEND_FE(crash, NULL)
5421 #endif
5422 #endif
5423+#if HARDENING_PATCH_MM_PROTECT_DEBUG
5424+ ZEND_FE(heap_overflow, NULL)
5425+#endif
5426 ZEND_FE(get_included_files, NULL)
5427 ZEND_FALIAS(get_required_files, get_included_files, NULL)
5428 ZEND_FE(is_subclass_of, NULL)
5429@@ -991,6 +997,19 @@
5430
5431 #endif /* ZEND_DEBUG */
5432
5433+
5434+#if HARDENING_PATCH_MM_PROTECT_DEBUG
5435+ZEND_FUNCTION(heap_overflow)
5436+{
5437+ char *nowhere = emalloc(10);
5438+
5439+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
5440+
5441+ efree(nowhere);
5442+}
5443+#endif
5444+
5445+
5446 /* {{{ proto array get_included_files(void)
5447 Returns an array with the file names that were include_once()'d */
5448 ZEND_FUNCTION(get_included_files)
5449diff -Nura php-5.0.5/Zend/zend.c hardening-patch-5.0.5-0.4.3/Zend/zend.c
5450--- php-5.0.5/Zend/zend.c 2005-07-22 09:33:27.000000000 +0200
5451+++ hardening-patch-5.0.5-0.4.3/Zend/zend.c 2005-09-12 17:02:36.000000000 +0200
5452@@ -54,6 +54,12 @@
5453 ZEND_API void (*zend_unblock_interruptions)(void);
5454 ZEND_API void (*zend_ticks_function)(int ticks);
5455 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
5456+#if HARDENING_PATCH
5457+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
5458+#endif
5459+#if HARDENING_PATCH_INC_PROTECT
5460+ZEND_API int (*zend_is_valid_include)(zval *z);
5461+#endif
5462 int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
5463
5464 void (*zend_on_timeout)(int seconds TSRMLS_DC);
5465@@ -72,9 +78,391 @@
5466 return SUCCESS;
5467 }
5468
5469+#if HARDENING_PATCH
5470+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
5471+{
5472+ if (!new_value) {
5473+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY | S_INTERNAL;
5474+ } else {
5475+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY | S_INTERNAL;
5476+ }
5477+ return SUCCESS;
5478+}
5479+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
5480+{
5481+ if (!new_value) {
5482+ EG(hphp_log_syslog_facility) = LOG_USER;
5483+ } else {
5484+ EG(hphp_log_syslog_facility) = atoi(new_value);
5485+ }
5486+ return SUCCESS;
5487+}
5488+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
5489+{
5490+ if (!new_value) {
5491+ EG(hphp_log_syslog_priority) = LOG_ALERT;
5492+ } else {
5493+ EG(hphp_log_syslog_priority) = atoi(new_value);
5494+ }
5495+ return SUCCESS;
5496+}
5497+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
5498+{
5499+ if (!new_value) {
5500+ EG(hphp_log_sapi) = S_ALL & ~S_SQL | S_INTERNAL;
5501+ } else {
5502+ EG(hphp_log_sapi) = atoi(new_value) | S_INTERNAL;
5503+ }
5504+ return SUCCESS;
5505+}
5506+static ZEND_INI_MH(OnUpdateHPHP_log_script)
5507+{
5508+ if (!new_value) {
5509+ EG(hphp_log_script) = S_ALL & ~S_MEMORY;
5510+ } else {
5511+ EG(hphp_log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
5512+ }
5513+ return SUCCESS;
5514+}
5515+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
5516+{
5517+ if (!new_value) {
5518+ EG(hphp_log_scriptname) = NULL;
5519+ } else {
5520+ if (EG(hphp_log_scriptname)) {
5521+ pefree(EG(hphp_log_scriptname),1);
5522+ }
5523+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
5524+ }
5525+ return SUCCESS;
5526+}
5527+
5528+static ZEND_INI_MH(OnUpdateHPHP_include_whitelist)
5529+{
5530+ char *s = NULL, *e, *val;
5531+ unsigned long dummy = 1;
5532+
5533+ if (!new_value) {
5534+include_whitelist_destroy:
5535+ if (HG(include_whitelist)) {
5536+ zend_hash_destroy(HG(include_whitelist));
5537+ efree(HG(include_whitelist));
5538+ }
5539+ HG(include_whitelist) = NULL;
5540+ return SUCCESS;
5541+ }
5542+ if (!(*new_value)) {
5543+ goto include_whitelist_destroy;
5544+ }
5545+
5546+ ALLOC_HASHTABLE(HG(include_whitelist));
5547+ zend_hash_init(HG(include_whitelist), 5, NULL, NULL, 0);
5548+
5549+ val = zend_str_tolower_dup(new_value, strlen(new_value));
5550+ e = val;
5551+
5552+ while (*e) {
5553+ switch (*e) {
5554+ case ' ':
5555+ case ',':
5556+ if (s) {
5557+ *e = '\0';
5558+ zend_hash_add(HG(include_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5559+ s = NULL;
5560+ }
5561+ break;
5562+ default:
5563+ if (!s) {
5564+ s = e;
5565+ }
5566+ break;
5567+ }
5568+ e++;
5569+ }
5570+ if (s) {
5571+ zend_hash_add(HG(include_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5572+ }
5573+ efree(val);
5574+
5575+ return SUCCESS;
5576+}
5577+
5578+static ZEND_INI_MH(OnUpdateHPHP_include_blacklist)
5579+{
5580+ char *s = NULL, *e, *val;
5581+ unsigned long dummy = 1;
5582+
5583+ if (!new_value) {
5584+include_blacklist_destroy:
5585+ if (HG(include_blacklist)) {
5586+ zend_hash_destroy(HG(include_blacklist));
5587+ efree(HG(include_blacklist));
5588+ }
5589+ HG(include_blacklist) = NULL;
5590+ return SUCCESS;
5591+ }
5592+ if (!(*new_value)) {
5593+ goto include_blacklist_destroy;
5594+ }
5595+
5596+ ALLOC_HASHTABLE(HG(include_blacklist));
5597+ zend_hash_init(HG(include_blacklist), 5, NULL, NULL, 0);
5598+
5599+ val = zend_str_tolower_dup(new_value, strlen(new_value));
5600+ e = val;
5601+
5602+ while (*e) {
5603+ switch (*e) {
5604+ case ' ':
5605+ case ',':
5606+ if (s) {
5607+ *e = '\0';
5608+ zend_hash_add(HG(include_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5609+ s = NULL;
5610+ }
5611+ break;
5612+ default:
5613+ if (!s) {
5614+ s = e;
5615+ }
5616+ break;
5617+ }
5618+ e++;
5619+ }
5620+ if (s) {
5621+ zend_hash_add(HG(include_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5622+ }
5623+ efree(val);
5624+
5625+ return SUCCESS;
5626+}
5627+
5628+static ZEND_INI_MH(OnUpdateHPHP_eval_whitelist)
5629+{
5630+ char *s = NULL, *e, *val;
5631+ unsigned long dummy = 1;
5632+
5633+ if (!new_value) {
5634+eval_whitelist_destroy:
5635+ if (HG(eval_whitelist)) {
5636+ zend_hash_destroy(HG(eval_whitelist));
5637+ efree(HG(eval_whitelist));
5638+ }
5639+ HG(eval_whitelist) = NULL;
5640+ return SUCCESS;
5641+ }
5642+ if (!(*new_value)) {
5643+ goto eval_whitelist_destroy;
5644+ }
5645+
5646+ ALLOC_HASHTABLE(HG(eval_whitelist));
5647+ zend_hash_init(HG(eval_whitelist), 5, NULL, NULL, 0);
5648+
5649+ val = zend_str_tolower_dup(new_value, strlen(new_value));
5650+ e = val;
5651+
5652+ while (*e) {
5653+ switch (*e) {
5654+ case ' ':
5655+ case ',':
5656+ if (s) {
5657+ *e = '\0';
5658+ zend_hash_add(HG(eval_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5659+ s = NULL;
5660+ }
5661+ break;
5662+ default:
5663+ if (!s) {
5664+ s = e;
5665+ }
5666+ break;
5667+ }
5668+ e++;
5669+ }
5670+ if (s) {
5671+ zend_hash_add(HG(eval_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5672+ }
5673+ efree(val);
5674+
5675+ return SUCCESS;
5676+}
5677+
5678+static ZEND_INI_MH(OnUpdateHPHP_eval_blacklist)
5679+{
5680+ char *s = NULL, *e, *val;
5681+ unsigned long dummy = 1;
5682+
5683+ if (!new_value) {
5684+eval_blacklist_destroy:
5685+ if (HG(eval_blacklist)) {
5686+ zend_hash_destroy(HG(eval_blacklist));
5687+ efree(HG(eval_blacklist));
5688+ }
5689+ HG(eval_blacklist) = NULL;
5690+ return SUCCESS;
5691+ }
5692+ if (!(*new_value)) {
5693+ goto eval_blacklist_destroy;
5694+ }
5695+
5696+ ALLOC_HASHTABLE(HG(eval_blacklist));
5697+ zend_hash_init(HG(eval_blacklist), 5, NULL, NULL, 0);
5698+
5699+ val = zend_str_tolower_dup(new_value, strlen(new_value));
5700+ e = val;
5701+
5702+ while (*e) {
5703+ switch (*e) {
5704+ case ' ':
5705+ case ',':
5706+ if (s) {
5707+ *e = '\0';
5708+ zend_hash_add(HG(eval_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5709+ s = NULL;
5710+ }
5711+ break;
5712+ default:
5713+ if (!s) {
5714+ s = e;
5715+ }
5716+ break;
5717+ }
5718+ e++;
5719+ }
5720+ if (s) {
5721+ zend_hash_add(HG(eval_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5722+ }
5723+ efree(val);
5724+
5725+
5726+ return SUCCESS;
5727+}
5728+
5729+static ZEND_INI_MH(OnUpdateHPHP_func_whitelist)
5730+{
5731+ char *s = NULL, *e, *val;
5732+ unsigned long dummy = 1;
5733+
5734+ if (!new_value) {
5735+func_whitelist_destroy:
5736+ if (HG(func_whitelist)) {
5737+ zend_hash_destroy(HG(func_whitelist));
5738+ efree(HG(func_whitelist));
5739+ }
5740+ HG(func_whitelist) = NULL;
5741+ return SUCCESS;
5742+ }
5743+ if (!(*new_value)) {
5744+ goto func_whitelist_destroy;
5745+ }
5746+
5747+ ALLOC_HASHTABLE(HG(func_whitelist));
5748+ zend_hash_init(HG(func_whitelist), 5, NULL, NULL, 0);
5749+
5750+ val = zend_str_tolower_dup(new_value, strlen(new_value));
5751+ e = val;
5752+
5753+ while (*e) {
5754+ switch (*e) {
5755+ case ' ':
5756+ case ',':
5757+ if (s) {
5758+ *e = '\0';
5759+ zend_hash_add(HG(func_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5760+ s = NULL;
5761+ }
5762+ break;
5763+ default:
5764+ if (!s) {
5765+ s = e;
5766+ }
5767+ break;
5768+ }
5769+ e++;
5770+ }
5771+ if (s) {
5772+ zend_hash_add(HG(func_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5773+ }
5774+ efree(val);
5775+
5776+ return SUCCESS;
5777+}
5778+
5779+static ZEND_INI_MH(OnUpdateHPHP_func_blacklist)
5780+{
5781+ char *s = NULL, *e, *val;
5782+ unsigned long dummy = 1;
5783+
5784+ if (!new_value) {
5785+func_blacklist_destroy:
5786+ if (HG(func_blacklist)) {
5787+ zend_hash_destroy(HG(func_blacklist));
5788+ efree(HG(func_blacklist));
5789+ }
5790+ HG(func_blacklist) = NULL;
5791+ return SUCCESS;
5792+ }
5793+ if (!(*new_value)) {
5794+ goto func_blacklist_destroy;
5795+ }
5796+
5797+ ALLOC_HASHTABLE(HG(func_blacklist));
5798+ zend_hash_init(HG(func_blacklist), 5, NULL, NULL, 0);
5799+
5800+ val = zend_str_tolower_dup(new_value, strlen(new_value));
5801+ e = val;
5802+
5803+ while (*e) {
5804+ switch (*e) {
5805+ case ' ':
5806+ case ',':
5807+ if (s) {
5808+ *e = '\0';
5809+ zend_hash_add(HG(func_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5810+ s = NULL;
5811+ }
5812+ break;
5813+ default:
5814+ if (!s) {
5815+ s = e;
5816+ }
5817+ break;
5818+ }
5819+ e++;
5820+ }
5821+ if (s) {
5822+ zend_hash_add(HG(func_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
5823+ }
5824+ efree(val);
5825+
5826+
5827+ return SUCCESS;
5828+}
5829+
5830+#endif
5831
5832 ZEND_INI_BEGIN()
5833 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
5834+#if HARDENING_PATCH
5835+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
5836+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
5837+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
5838+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
5839+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
5840+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
5841+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
5842+
5843+ ZEND_INI_ENTRY("hphp.executor.include.whitelist", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_include_whitelist)
5844+ ZEND_INI_ENTRY("hphp.executor.include.blacklist", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_include_blacklist)
5845+ ZEND_INI_ENTRY("hphp.executor.eval.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_eval_whitelist)
5846+ ZEND_INI_ENTRY("hphp.executor.eval.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_eval_blacklist)
5847+ ZEND_INI_ENTRY("hphp.executor.func.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_func_whitelist)
5848+ ZEND_INI_ENTRY("hphp.executor.func.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_func_blacklist)
5849+
5850+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
5851+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
5852+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
5853+#endif
5854 STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
5855 ZEND_INI_END()
5856
5857@@ -476,6 +864,7 @@
5858 EG(user_error_handler) = NULL;
5859 EG(user_exception_handler) = NULL;
5860 EG(in_execution) = 0;
5861+ EG(in_code_type) = 0;
5862 EG(in_autoload) = NULL;
5863 EG(current_execute_data) = NULL;
5864 EG(current_module) = NULL;
5865@@ -545,6 +934,14 @@
5866 extern zend_scanner_globals language_scanner_globals;
5867 #endif
5868
5869+ /* Set up Hardening-Patch utility functions first */
5870+#if HARDENING_PATCH
5871+ zend_security_log = utility_functions->security_log_function;
5872+#endif
5873+#if HARDENING_PATCH_INC_PROTECT
5874+ zend_is_valid_include = utility_functions->is_valid_include;
5875+#endif
5876+
5877 #ifdef ZTS
5878 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
5879 #else
5880@@ -747,6 +1144,7 @@
5881 }
5882 CG(unclean_shutdown) = 1;
5883 CG(in_compilation) = EG(in_execution) = 0;
5884+ EG(in_code_type) = 0;
5885 EG(current_execute_data) = NULL;
5886 longjmp(EG(bailout), FAILURE);
5887 }
5888diff -Nura php-5.0.5/Zend/zend_canary.c hardening-patch-5.0.5-0.4.3/Zend/zend_canary.c
5889--- php-5.0.5/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
5890+++ hardening-patch-5.0.5-0.4.3/Zend/zend_canary.c 2005-09-11 23:30:52.000000000 +0200
5891@@ -0,0 +1,58 @@
5892+/*
5893+ +----------------------------------------------------------------------+
5894+ | Hardening-Patch for PHP |
5895+ +----------------------------------------------------------------------+
5896+ | Copyright (c) 2004-2005 Stefan Esser |
5897+ +----------------------------------------------------------------------+
5898+ | This source file is subject to version 2.02 of the PHP license, |
5899+ | that is bundled with this package in the file LICENSE, and is |
5900+ | available at through the world-wide-web at |
5901+ | http://www.php.net/license/2_02.txt. |
5902+ | If you did not receive a copy of the PHP license and are unable to |
5903+ | obtain it through the world-wide-web, please send a note to |
5904+ | license@php.net so we can mail you a copy immediately. |
5905+ +----------------------------------------------------------------------+
5906+ | Author: Stefan Esser <sesser@hardened-php.net> |
5907+ +----------------------------------------------------------------------+
5908+ */
5909+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
5910+
5911+#include "zend.h"
5912+
5913+#include <stdio.h>
5914+#include <stdlib.h>
5915+
5916+
5917+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
5918+
5919+/* will be replaced later with more compatible method */
5920+ZEND_API unsigned int zend_canary()
5921+{
5922+ time_t t;
5923+ unsigned int canary;
5924+ int fd;
5925+
5926+ fd = open("/dev/urandom", 0);
5927+ if (fd != -1) {
5928+ int r = read(fd, &canary, sizeof(canary));
5929+ close(fd);
5930+ if (r == sizeof(canary)) {
5931+ return (canary);
5932+ }
5933+ }
5934+ /* not good but we never want to do this */
5935+ time(&t);
5936+ canary = *(unsigned int *)&t + getpid() << 16;
5937+ return (canary);
5938+}
5939+#endif
5940+
5941+
5942+/*
5943+ * Local variables:
5944+ * tab-width: 4
5945+ * c-basic-offset: 4
5946+ * End:
5947+ * vim600: sw=4 ts=4 fdm=marker
5948+ * vim<600: sw=4 ts=4
5949+ */
5950diff -Nura php-5.0.5/Zend/zend_compile.c hardening-patch-5.0.5-0.4.3/Zend/zend_compile.c
5951--- php-5.0.5/Zend/zend_compile.c 2005-07-19 09:33:24.000000000 +0200
5952+++ hardening-patch-5.0.5-0.4.3/Zend/zend_compile.c 2005-09-11 23:30:52.000000000 +0200
5953@@ -979,6 +979,13 @@
5954 op_array.prototype = NULL;
5955
5956 op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
5957+#if HARDENING_PATCH
5958+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
5959+ op_array.created_by_eval = 1;
5960+ } else {
5961+ op_array.created_by_eval = 0;
5962+ }
5963+#endif
5964
5965 if (is_method) {
5966 char *short_class_name = CG(active_class_entry)->name;
5967diff -Nura php-5.0.5/Zend/zend_compile.h hardening-patch-5.0.5-0.4.3/Zend/zend_compile.h
5968--- php-5.0.5/Zend/zend_compile.h 2005-06-24 10:45:43.000000000 +0200
5969+++ hardening-patch-5.0.5-0.4.3/Zend/zend_compile.h 2005-09-11 23:30:52.000000000 +0200
5970@@ -203,6 +203,9 @@
5971 zend_uint doc_comment_len;
5972
5973 void *reserved[ZEND_MAX_RESERVED_RESOURCES];
5974+#if HARDENING_PATCH
5975+ zend_bool created_by_eval;
5976+#endif
5977 };
5978
5979
5980@@ -281,6 +284,8 @@
5981 zval *object;
5982 union _temp_variable *Ts;
5983 zend_bool original_in_execution;
5984+ zend_uint original_in_code_type;
5985+ zend_uint execute_depth;
5986 zend_class_entry *calling_scope;
5987 struct _zend_execute_data *prev_execute_data;
5988 };
5989@@ -774,6 +779,7 @@
5990 #define ZEND_OVERLOADED_FUNCTION 3
5991 #define ZEND_EVAL_CODE 4
5992 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
5993+#define ZEND_SANDBOX_CODE 6
5994
5995 #define ZEND_INTERNAL_CLASS 1
5996 #define ZEND_USER_CLASS 2
5997diff -Nura php-5.0.5/Zend/zend_constants.c hardening-patch-5.0.5-0.4.3/Zend/zend_constants.c
5998--- php-5.0.5/Zend/zend_constants.c 2004-07-13 21:22:11.000000000 +0200
5999+++ hardening-patch-5.0.5-0.4.3/Zend/zend_constants.c 2005-09-11 23:30:52.000000000 +0200
6000@@ -107,6 +107,73 @@
6001 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
6002
6003 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
6004+#if HARDENING_PATCH
6005+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
6006+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
6007+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS);
6008+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
6009+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
6010+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
6011+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
6012+ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS);
6013+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
6014+
6015+ /* error levels */
6016+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
6017+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
6018+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
6019+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
6020+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
6021+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
6022+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
6023+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
6024+ /* facility: type of program logging the message */
6025+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
6026+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
6027+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
6028+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
6029+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
6030+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
6031+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
6032+#ifdef LOG_NEWS
6033+ /* No LOG_NEWS on HP-UX */
6034+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
6035+#endif
6036+#ifdef LOG_UUCP
6037+ /* No LOG_UUCP on HP-UX */
6038+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
6039+#endif
6040+#ifdef LOG_CRON
6041+ /* apparently some systems don't have this one */
6042+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
6043+#endif
6044+#ifdef LOG_AUTHPRIV
6045+ /* AIX doesn't have LOG_AUTHPRIV */
6046+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
6047+#endif
6048+#if !defined(PHP_WIN32) && !defined(NETWARE)
6049+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
6050+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
6051+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
6052+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
6053+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
6054+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
6055+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
6056+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
6057+#endif
6058+ /* options */
6059+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
6060+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
6061+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
6062+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
6063+#ifdef LOG_NOWAIT
6064+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
6065+#endif
6066+#ifdef LOG_PERROR
6067+ /* AIX doesn't have LOG_PERROR */
6068+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
6069+#endif
6070+#endif
6071
6072 /* true/false constants */
6073 {
6074diff -Nura php-5.0.5/Zend/zend_errors.h hardening-patch-5.0.5-0.4.3/Zend/zend_errors.h
6075--- php-5.0.5/Zend/zend_errors.h 2004-01-08 18:31:47.000000000 +0100
6076+++ hardening-patch-5.0.5-0.4.3/Zend/zend_errors.h 2005-09-12 18:12:35.000000000 +0200
6077@@ -38,6 +38,18 @@
6078 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
6079 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
6080
6081+#if HARDENING_PATCH
6082+#define S_MEMORY (1<<0L)
6083+#define S_VARS (1<<1L)
6084+#define S_FILES (1<<2L)
6085+#define S_INCLUDE (1<<3L)
6086+#define S_SQL (1<<4L)
6087+#define S_EXECUTOR (1<<5L)
6088+#define S_MISC (1<<30L)
6089+#define S_INTERNAL (1<<29L)
6090+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MISC | S_SQL | S_EXECUTOR)
6091+#endif
6092+
6093 #endif /* ZEND_ERRORS_H */
6094
6095 /*
6096diff -Nura php-5.0.5/Zend/zend_execute_API.c hardening-patch-5.0.5-0.4.3/Zend/zend_execute_API.c
6097--- php-5.0.5/Zend/zend_execute_API.c 2005-09-02 09:46:39.000000000 +0200
6098+++ hardening-patch-5.0.5-0.4.3/Zend/zend_execute_API.c 2005-09-11 23:30:52.000000000 +0200
6099@@ -137,6 +137,7 @@
6100 EG(class_table) = CG(class_table);
6101
6102 EG(in_execution) = 0;
6103+ EG(in_code_type) = 0;
6104 EG(in_autoload) = NULL;
6105
6106 zend_ptr_stack_init(&EG(argument_stack));
6107@@ -725,6 +726,39 @@
6108 if (zend_hash_find(fci->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
6109 EX(function_state).function = NULL;
6110 }
6111+#if HARDENING_PATCH
6112+ else {
6113+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
6114+ if (HG(eval_whitelist) != NULL) {
6115+ if (!zend_hash_exists(HG(eval_whitelist), function_name_lc, fci->function_name->value.str.len+1)) {
6116+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", function_name_lc);
6117+ efree(function_name_lc);
6118+ zend_bailout();
6119+ }
6120+ } else if (HG(eval_blacklist) != NULL) {
6121+ if (zend_hash_exists(HG(eval_blacklist), function_name_lc, fci->function_name->value.str.len+1)) {
6122+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", function_name_lc);
6123+ efree(function_name_lc);
6124+ zend_bailout();
6125+ }
6126+ }
6127+ }
6128+
6129+ if (HG(func_whitelist) != NULL) {
6130+ if (!zend_hash_exists(HG(func_whitelist), function_name_lc, fci->function_name->value.str.len+1)) {
6131+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", function_name_lc);
6132+ efree(function_name_lc);
6133+ zend_bailout();
6134+ }
6135+ } else if (HG(func_blacklist) != NULL) {
6136+ if (zend_hash_exists(HG(func_blacklist), function_name_lc, fci->function_name->value.str.len+1)) {
6137+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", function_name_lc);
6138+ efree(function_name_lc);
6139+ zend_bailout();
6140+ }
6141+ }
6142+ }
6143+#endif
6144 efree(function_name_lc);
6145 }
6146
6147@@ -999,7 +1033,7 @@
6148 return retval;
6149 }
6150
6151-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
6152+ZEND_API int zend_eval_string_ex_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
6153 {
6154 zval pv;
6155 zend_op_array *new_op_array;
6156@@ -1032,6 +1066,7 @@
6157 zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
6158 zend_op **original_opline_ptr = EG(opline_ptr);
6159
6160+ new_op_array->type = type;
6161 EG(return_value_ptr_ptr) = &local_retval_ptr;
6162 EG(active_op_array) = new_op_array;
6163 EG(no_extensions)=1;
6164@@ -1066,6 +1101,12 @@
6165 }
6166
6167
6168+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
6169+{
6170+ return (zend_eval_string_ex_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
6171+}
6172+
6173+
6174 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
6175 {
6176 int result;
6177diff -Nura php-5.0.5/Zend/zend_execute.c hardening-patch-5.0.5-0.4.3/Zend/zend_execute.c
6178--- php-5.0.5/Zend/zend_execute.c 2005-09-01 15:21:56.000000000 +0200
6179+++ hardening-patch-5.0.5-0.4.3/Zend/zend_execute.c 2005-09-11 23:30:52.000000000 +0200
6180@@ -1374,6 +1374,7 @@
6181 efree(EX(Ts)); \
6182 } \
6183 EG(in_execution) = EX(original_in_execution); \
6184+ EG(in_code_type) = EX(original_in_code_type); \
6185 EG(current_execute_data) = EX(prev_execute_data); \
6186 return 1; /* CHECK_ME */
6187
6188@@ -1400,6 +1401,16 @@
6189 EX(original_in_execution) = EG(in_execution);
6190 EX(prev_execute_data) = EG(current_execute_data);
6191 EG(current_execute_data) = &execute_data;
6192+#if HARDENING_PATCH
6193+ EX(execute_depth) = 0;
6194+
6195+ if ((op_array->type == ZEND_EVAL_CODE || op_array->created_by_eval)&& EG(in_code_type) != ZEND_SANDBOX_CODE) {
6196+ EG(in_code_type) = ZEND_EVAL_CODE;
6197+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
6198+ EG(in_code_type) = ZEND_SANDBOX_CODE;
6199+ op_array->type = ZEND_EVAL_CODE;
6200+ }
6201+#endif
6202
6203 EG(in_execution) = 1;
6204 if (op_array->start_op) {
6205@@ -1426,6 +1437,19 @@
6206 EX(function_state).function_symbol_table = NULL;
6207 #endif
6208
6209+#if HARDENING_PATCH
6210+ if (EX(prev_execute_data) == NULL) {
6211+ EX(execute_depth) = 0;
6212+ } else {
6213+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
6214+ }
6215+
6216+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
6217+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
6218+ zend_bailout();
6219+ }
6220+#endif
6221+
6222 while (1) {
6223 #ifdef ZEND_WIN32
6224 if (EG(timed_out)) {
6225@@ -2680,6 +2704,37 @@
6226 efree(lcname);
6227 zend_error(E_ERROR, "Call to undefined function %s()", function_name_strval);
6228 }
6229+#if HARDENING_PATCH
6230+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
6231+ if (HG(eval_whitelist) != NULL) {
6232+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
6233+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
6234+ efree(lcname);
6235+ zend_bailout();
6236+ }
6237+ } else if (HG(eval_blacklist) != NULL) {
6238+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
6239+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
6240+ efree(lcname);
6241+ zend_bailout();
6242+ }
6243+ }
6244+ }
6245+
6246+ if (HG(func_whitelist) != NULL) {
6247+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
6248+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
6249+ efree(lcname);
6250+ zend_bailout();
6251+ }
6252+ } else if (HG(func_blacklist) != NULL) {
6253+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
6254+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
6255+ efree(lcname);
6256+ zend_bailout();
6257+ }
6258+ }
6259+#endif
6260
6261 efree(lcname);
6262 if (!is_const) {
6263@@ -2886,6 +2941,34 @@
6264 if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
6265 zend_error(E_ERROR, "Unknown function: %s()\n", fname->value.str.val);
6266 }
6267+#if HARDENING_PATCH
6268+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
6269+ if (HG(eval_whitelist) != NULL) {
6270+ if (!zend_hash_exists(HG(eval_whitelist), fname->value.str.val, fname->value.str.len+1)) {
6271+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", fname->value.str.val);
6272+ zend_bailout();
6273+ }
6274+ } else if (HG(eval_blacklist) != NULL) {
6275+ if (zend_hash_exists(HG(eval_blacklist), fname->value.str.val, fname->value.str.len+1)) {
6276+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", fname->value.str.val);
6277+ zend_bailout();
6278+ }
6279+ }
6280+ }
6281+
6282+ if (HG(func_whitelist) != NULL) {
6283+ if (!zend_hash_exists(HG(func_whitelist), fname->value.str.val, fname->value.str.len+1)) {
6284+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", fname->value.str.val);
6285+ zend_bailout();
6286+ }
6287+ } else if (HG(func_blacklist) != NULL) {
6288+ if (zend_hash_exists(HG(func_blacklist), fname->value.str.val, fname->value.str.len+1)) {
6289+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", fname->value.str.val);
6290+ zend_bailout();
6291+ }
6292+ }
6293+#endif
6294+
6295 EX(object) = NULL;
6296 EX(calling_scope) = EX(function_state).function->common.scope;
6297
6298@@ -3573,7 +3656,12 @@
6299 int dummy = 1;
6300 zend_file_handle file_handle;
6301
6302+#if HARDENING_PATCH_INC_PROTECT
6303+ if (zend_is_valid_include(inc_filename)
6304+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
6305+#else
6306 if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
6307+#endif
6308
6309 if (!file_handle.opened_path) {
6310 file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
6311@@ -3598,6 +3686,11 @@
6312 break;
6313 case ZEND_INCLUDE:
6314 case ZEND_REQUIRE:
6315+#if HARDENING_PATCH_INC_PROTECT
6316+ if (!zend_is_valid_include(inc_filename)) {
6317+ break;
6318+ }
6319+#endif
6320 new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
6321 break;
6322 case ZEND_EVAL: {
6323diff -Nura php-5.0.5/Zend/zend_extensions.c hardening-patch-5.0.5-0.4.3/Zend/zend_extensions.c
6324--- php-5.0.5/Zend/zend_extensions.c 2004-01-08 18:31:47.000000000 +0100
6325+++ hardening-patch-5.0.5-0.4.3/Zend/zend_extensions.c 2005-09-11 23:30:52.000000000 +0200
6326@@ -55,23 +55,44 @@
6327 return FAILURE;
6328 }
6329
6330+ /* check if module is compiled against Hardening-Patch */
6331+ if (extension_version_info->zend_extension_api_no < 1000000000) {
6332+ fprintf(stderr, "%s is not compiled with Hardening-Patch.\n"
6333+ "The Hardening-Patch version %d is installed.\n\n",
6334+ new_extension->name,
6335+ HARDENING_PATCH_ZEND_EXTENSION_API_NO);
6336+ DL_UNLOAD(handle);
6337+ return FAILURE;
6338+ }
6339+
6340+
6341+ /* check if module is compiled against correct Hardening-Patch version */
6342+ if (extension_version_info->zend_extension_api_no != HARDENING_PATCH_ZEND_EXTENSION_API_NO) {
6343+ fprintf(stderr, "%s requires Hardening-Patch version %d.\n"
6344+ "The Hardening-Patch version %d is installed.\n\n",
6345+ new_extension->name,
6346+ extension_version_info->zend_extension_api_no,
6347+ HARDENING_PATCH_ZEND_EXTENSION_API_NO);
6348+ DL_UNLOAD(handle);
6349+ return FAILURE;
6350+ }
6351
6352 /* allow extension to proclaim compatibility with any Zend version */
6353- if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
6354- if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
6355+ if (extension_version_info->real_zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
6356+ if (extension_version_info->real_zend_extension_api_no > ZEND_EXTENSION_API_NO) {
6357 fprintf(stderr, "%s requires Zend Engine API version %d.\n"
6358 "The Zend Engine API version %d which is installed, is outdated.\n\n",
6359 new_extension->name,
6360- extension_version_info->zend_extension_api_no,
6361+ extension_version_info->real_zend_extension_api_no,
6362 ZEND_EXTENSION_API_NO);
6363 DL_UNLOAD(handle);
6364 return FAILURE;
6365- } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
6366+ } else if (extension_version_info->real_zend_extension_api_no < ZEND_EXTENSION_API_NO) {
6367 fprintf(stderr, "%s requires Zend Engine API version %d.\n"
6368 "The Zend Engine API version %d which is installed, is newer.\n"
6369 "Contact %s at %s for a later version of %s.\n\n",
6370 new_extension->name,
6371- extension_version_info->zend_extension_api_no,
6372+ extension_version_info->real_zend_extension_api_no,
6373 ZEND_EXTENSION_API_NO,
6374 new_extension->author,
6375 new_extension->URL,
6376diff -Nura php-5.0.5/Zend/zend_extensions.h hardening-patch-5.0.5-0.4.3/Zend/zend_extensions.h
6377--- php-5.0.5/Zend/zend_extensions.h 2004-11-25 21:26:48.000000000 +0100
6378+++ hardening-patch-5.0.5-0.4.3/Zend/zend_extensions.h 2005-09-11 23:30:52.000000000 +0200
6379@@ -24,9 +24,11 @@
6380
6381 #include "zend_compile.h"
6382
6383-/* The first number is the engine version and the rest is the date.
6384+/* The first API number is a flag saying that Hardening-Patch is used.
6385+ * The second number is the engine version and the date.
6386 * This way engine 2 API no. is always greater than engine 1 API no..
6387 */
6388+#define HARDENING_PATCH_ZEND_EXTENSION_API_NO 1002050805
6389 #define ZEND_EXTENSION_API_NO 220040412
6390
6391 typedef struct _zend_extension_version_info {
6392@@ -34,6 +36,7 @@
6393 char *required_zend_version;
6394 unsigned char thread_safe;
6395 unsigned char debug;
6396+ int real_zend_extension_api_no;
6397 } zend_extension_version_info;
6398
6399
6400@@ -101,7 +104,7 @@
6401
6402
6403 #define ZEND_EXTENSION() \
6404- ZEND_EXT_API zend_extension_version_info extension_version_info = { ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG }
6405+ ZEND_EXT_API zend_extension_version_info extension_version_info = { HARDENING_PATCH_ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG, ZEND_EXTENSION_API_NO }
6406
6407 #define STANDARD_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1
6408 #define COMPAT_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1
6409diff -Nura php-5.0.5/Zend/zend_globals.h hardening-patch-5.0.5-0.4.3/Zend/zend_globals.h
6410--- php-5.0.5/Zend/zend_globals.h 2004-11-04 00:14:31.000000000 +0100
6411+++ hardening-patch-5.0.5-0.4.3/Zend/zend_globals.h 2005-09-11 23:30:52.000000000 +0200
6412@@ -174,6 +174,16 @@
6413
6414 int error_reporting;
6415 int orig_error_reporting;
6416+#if HARDENING_PATCH
6417+ int hphp_log_syslog;
6418+ int hphp_log_syslog_facility;
6419+ int hphp_log_syslog_priority;
6420+ int hphp_log_sapi;
6421+ int hphp_log_script;
6422+ char *hphp_log_scriptname;
6423+ zend_bool hphp_log_use_x_forwarded_for;
6424+ long hphp_executor_max_depth;
6425+#endif
6426 int exit_status;
6427
6428 zend_op_array *active_op_array;
6429@@ -191,6 +201,7 @@
6430 int ticks_count;
6431
6432 zend_bool in_execution;
6433+ zend_uint in_code_type;
6434 HashTable *in_autoload;
6435 zend_bool bailout_set;
6436 zend_bool full_tables_cleanup;
6437diff -Nura php-5.0.5/Zend/zend.h hardening-patch-5.0.5-0.4.3/Zend/zend.h
6438--- php-5.0.5/Zend/zend.h 2005-08-25 19:41:08.000000000 +0200
6439+++ hardening-patch-5.0.5-0.4.3/Zend/zend.h 2005-09-11 23:30:52.000000000 +0200
6440@@ -290,6 +290,7 @@
6441 /* Variable information */
6442 zvalue_value value; /* value */
6443 zend_uint refcount;
6444+ zend_ushort flags;
6445 zend_uchar type; /* active type */
6446 zend_uchar is_ref;
6447 };
6448@@ -359,6 +360,12 @@
6449 void (*on_timeout)(int seconds TSRMLS_DC);
6450 int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
6451 int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
6452+#if HARDENING_PATCH
6453+ void (*security_log_function)(int loglevel, char *fmt, ...);
6454+#endif
6455+#if HARDENING_PATCH_INC_PROTECT
6456+ int (*is_valid_include)(zval *z);
6457+#endif
6458 } zend_utility_functions;
6459
6460
6461@@ -497,6 +504,16 @@
6462 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
6463 extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
6464 extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
6465+#if HARDENING_PATCH
6466+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
6467+#endif
6468+#if HARDENING_PATCH_INC_PROTECT
6469+extern ZEND_API int (*zend_is_valid_include)(zval *z);
6470+#endif
6471+
6472+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
6473+ZEND_API unsigned int zend_canary(void);
6474+#endif
6475
6476
6477 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
6478@@ -621,6 +638,11 @@
6479 #define ZEND_MAX_RESERVED_RESOURCES 4
6480
6481
6482+#if HARDENING_PATCH
6483+#include "hardened_globals.h"
6484+#include "php_syslog.h"
6485+#endif
6486+
6487 #endif /* ZEND_H */
6488
6489 /*
6490diff -Nura php-5.0.5/Zend/zend_hash.c hardening-patch-5.0.5-0.4.3/Zend/zend_hash.c
6491--- php-5.0.5/Zend/zend_hash.c 2005-04-25 08:11:00.000000000 +0200
6492+++ hardening-patch-5.0.5-0.4.3/Zend/zend_hash.c 2005-09-11 23:30:52.000000000 +0200
6493@@ -21,6 +21,18 @@
6494
6495 #include "zend.h"
6496
6497+#if HARDENING_PATCH_HASH_PROTECT
6498+ unsigned int zend_hash_canary = 0x1234567;
6499+ zend_bool zend_hash_canary_inited = 0;
6500+#endif
6501+
6502+#define CHECK_HASH_CANARY(hash) \
6503+ if (zend_hash_canary != (hash)->canary) { \
6504+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
6505+ exit(1); \
6506+ }
6507+
6508+
6509 #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
6510 (element)->pNext = (list_head); \
6511 (element)->pLast = NULL; \
6512@@ -138,6 +150,9 @@
6513 {
6514 uint i = 3;
6515 Bucket **tmp;
6516+#if HARDENING_PATCH_HASH_PROTECT
6517+ TSRMLS_FETCH();
6518+#endif
6519
6520 SET_INCONSISTENT(HT_OK);
6521
6522@@ -147,6 +162,13 @@
6523
6524 ht->nTableSize = 1 << i;
6525 ht->nTableMask = ht->nTableSize - 1;
6526+#if HARDENING_PATCH_HASH_PROTECT
6527+ if (zend_hash_canary_inited==0) {
6528+ zend_hash_canary = zend_canary();
6529+ zend_hash_canary_inited = 1;
6530+ }
6531+ ht->canary = zend_hash_canary;
6532+#endif
6533 ht->pDestructor = pDestructor;
6534 ht->arBuckets = NULL;
6535 ht->pListHead = NULL;
6536@@ -226,6 +248,9 @@
6537 }
6538 #endif
6539 if (ht->pDestructor) {
6540+#if HARDENING_PATCH_HASH_PROTECT
6541+ CHECK_HASH_CANARY(ht);
6542+#endif
6543 ht->pDestructor(p->pData);
6544 }
6545 UPDATE_DATA(ht, p, pData, nDataSize);
6546@@ -291,6 +316,9 @@
6547 }
6548 #endif
6549 if (ht->pDestructor) {
6550+#if HARDENING_PATCH_HASH_PROTECT
6551+ CHECK_HASH_CANARY(ht);
6552+#endif
6553 ht->pDestructor(p->pData);
6554 }
6555 UPDATE_DATA(ht, p, pData, nDataSize);
6556@@ -366,6 +394,9 @@
6557 }
6558 #endif
6559 if (ht->pDestructor) {
6560+#if HARDENING_PATCH_HASH_PROTECT
6561+ CHECK_HASH_CANARY(ht);
6562+#endif
6563 ht->pDestructor(p->pData);
6564 }
6565 UPDATE_DATA(ht, p, pData, nDataSize);
6566@@ -414,7 +445,7 @@
6567 IS_CONSISTENT(ht);
6568
6569 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
6570- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
6571+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
6572 if (t) {
6573 HANDLE_BLOCK_INTERRUPTIONS();
6574 ht->arBuckets = t;
6575@@ -424,6 +455,7 @@
6576 HANDLE_UNBLOCK_INTERRUPTIONS();
6577 return SUCCESS;
6578 }
6579+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
6580 return FAILURE;
6581 }
6582 return SUCCESS;
6583@@ -487,6 +519,9 @@
6584 ht->pInternalPointer = p->pListNext;
6585 }
6586 if (ht->pDestructor) {
6587+#if HARDENING_PATCH_HASH_PROTECT
6588+ CHECK_HASH_CANARY(ht);
6589+#endif
6590 ht->pDestructor(p->pData);
6591 }
6592 if (!p->pDataPtr) {
6593@@ -516,6 +551,9 @@
6594 q = p;
6595 p = p->pListNext;
6596 if (ht->pDestructor) {
6597+#if HARDENING_PATCH_HASH_PROTECT
6598+ CHECK_HASH_CANARY(ht);
6599+#endif
6600 ht->pDestructor(q->pData);
6601 }
6602 if (!q->pDataPtr && q->pData) {
6603@@ -542,6 +580,9 @@
6604 q = p;
6605 p = p->pListNext;
6606 if (ht->pDestructor) {
6607+#if HARDENING_PATCH_HASH_PROTECT
6608+ CHECK_HASH_CANARY(ht);
6609+#endif
6610 ht->pDestructor(q->pData);
6611 }
6612 if (!q->pDataPtr && q->pData) {
6613@@ -571,6 +612,9 @@
6614 HANDLE_BLOCK_INTERRUPTIONS();
6615
6616 if (ht->pDestructor) {
6617+#if HARDENING_PATCH_HASH_PROTECT
6618+ CHECK_HASH_CANARY(ht);
6619+#endif
6620 ht->pDestructor(p->pData);
6621 }
6622 if (!p->pDataPtr) {
6623diff -Nura php-5.0.5/Zend/zend_hash.h hardening-patch-5.0.5-0.4.3/Zend/zend_hash.h
6624--- php-5.0.5/Zend/zend_hash.h 2004-01-08 18:31:47.000000000 +0100
6625+++ hardening-patch-5.0.5-0.4.3/Zend/zend_hash.h 2005-09-11 23:30:52.000000000 +0200
6626@@ -58,6 +58,9 @@
6627 } Bucket;
6628
6629 typedef struct _hashtable {
6630+#if HARDENING_PATCH_HASH_PROTECT
6631+ unsigned int canary;
6632+#endif
6633 uint nTableSize;
6634 uint nTableMask;
6635 uint nNumOfElements;
6636diff -Nura php-5.0.5/Zend/zend_language_scanner.l hardening-patch-5.0.5-0.4.3/Zend/zend_language_scanner.l
6637--- php-5.0.5/Zend/zend_language_scanner.l 2005-06-09 10:54:24.000000000 +0200
6638+++ hardening-patch-5.0.5-0.4.3/Zend/zend_language_scanner.l 2005-09-11 23:30:52.000000000 +0200
6639@@ -386,6 +386,13 @@
6640 compilation_successful=0;
6641 } else {
6642 init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
6643+#if HARDENING_PATCH
6644+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
6645+ op_array->created_by_eval = 1;
6646+ } else {
6647+ op_array->created_by_eval = 0;
6648+ }
6649+#endif
6650 CG(in_compilation) = 1;
6651 CG(active_op_array) = op_array;
6652 compiler_result = zendparse(TSRMLS_C);
6653diff -Nura php-5.0.5/Zend/zend_language_scanner.c hardening-patch-5.0.5-0.4.3/Zend/zend_language_scanner.c
6654--- php-5.0.5/Zend/zend_language_scanner.c 2005-09-05 13:16:27.000000000 +0200
6655+++ hardening-patch-5.0.5-0.4.3/Zend/zend_language_scanner.c 2005-09-11 23:30:52.000000000 +0200
6656@@ -3153,6 +3153,13 @@
6657 compilation_successful=0;
6658 } else {
6659 init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
6660+#if HARDENING_PATCH
6661+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
6662+ op_array->created_by_eval = 1;
6663+ } else {
6664+ op_array->created_by_eval = 0;
6665+ }
6666+#endif
6667 CG(in_compilation) = 1;
6668 CG(active_op_array) = op_array;
6669 compiler_result = zendparse(TSRMLS_C);
6670diff -Nura php-5.0.5/Zend/zend_llist.c hardening-patch-5.0.5-0.4.3/Zend/zend_llist.c
6671--- php-5.0.5/Zend/zend_llist.c 2004-01-08 18:31:47.000000000 +0100
6672+++ hardening-patch-5.0.5-0.4.3/Zend/zend_llist.c 2005-09-11 23:30:52.000000000 +0200
6673@@ -22,9 +22,34 @@
6674 #include "zend.h"
6675 #include "zend_llist.h"
6676 #include "zend_qsort.h"
6677+#include "zend_globals.h"
6678+
6679+#define CHECK_LIST_CANARY(list) \
6680+ if (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t) { \
6681+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
6682+ exit(1); \
6683+ }
6684+
6685+#define CHECK_LISTELEMENT_CANARY(elem) \
6686+ if (HG(canary_3) != (elem)->canary) { \
6687+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
6688+ exit(1); \
6689+ }
6690+
6691
6692 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
6693 {
6694+#if HARDENING_PATCH_LL_PROTECT
6695+ TSRMLS_FETCH();
6696+
6697+ if (!HG(ll_canary_inited)) {
6698+ HG(canary_3) = zend_canary();
6699+ HG(canary_4) = zend_canary();
6700+ HG(ll_canary_inited) = 1;
6701+ }
6702+ l->canary_h = HG(canary_3);
6703+ l->canary_t = HG(canary_4);
6704+#endif
6705 l->head = NULL;
6706 l->tail = NULL;
6707 l->count = 0;
6708@@ -38,6 +63,11 @@
6709 {
6710 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
6711
6712+#if HARDENING_PATCH_LL_PROTECT
6713+ TSRMLS_FETCH();
6714+ CHECK_LIST_CANARY(l)
6715+ tmp->canary = HG(canary_3);
6716+#endif
6717 tmp->prev = l->tail;
6718 tmp->next = NULL;
6719 if (l->tail) {
6720@@ -56,6 +86,11 @@
6721 {
6722 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
6723
6724+#if HARDENING_PATCH_LL_PROTECT
6725+ TSRMLS_FETCH();
6726+ CHECK_LIST_CANARY(l)
6727+ tmp->canary = HG(canary_3);
6728+#endif
6729 tmp->next = l->head;
6730 tmp->prev = NULL;
6731 if (l->head) {
6732@@ -93,10 +128,20 @@
6733 zend_llist_element *current=l->head;
6734 zend_llist_element *next;
6735
6736+#if HARDENING_PATCH_LL_PROTECT
6737+ TSRMLS_FETCH();
6738+ CHECK_LIST_CANARY(l)
6739+#endif
6740 while (current) {
6741+#if HARDENING_PATCH_LL_PROTECT
6742+ CHECK_LISTELEMENT_CANARY(current)
6743+#endif
6744 next = current->next;
6745 if (compare(current->data, element)) {
6746 DEL_LLIST_ELEMENT(current, l);
6747+#if HARDENING_PATCH_LL_PROTECT
6748+ current->canary = 0;
6749+#endif
6750 break;
6751 }
6752 current = next;
6753@@ -108,7 +153,14 @@
6754 {
6755 zend_llist_element *current=l->head, *next;
6756
6757+#if HARDENING_PATCH_LL_PROTECT
6758+ TSRMLS_FETCH();
6759+ CHECK_LIST_CANARY(l)
6760+#endif
6761 while (current) {
6762+#if HARDENING_PATCH_LL_PROTECT
6763+ CHECK_LISTELEMENT_CANARY(current)
6764+#endif
6765 next = current->next;
6766 if (l->dtor) {
6767 l->dtor(current->data);
6768@@ -133,7 +185,14 @@
6769 zend_llist_element *old_tail;
6770 void *data;
6771
6772+#if HARDENING_PATCH_LL_PROTECT
6773+ TSRMLS_FETCH();
6774+ CHECK_LIST_CANARY(l)
6775+#endif
6776 if ((old_tail = l->tail)) {
6777+#if HARDENING_PATCH_LL_PROTECT
6778+ CHECK_LISTELEMENT_CANARY(old_tail)
6779+#endif
6780 if (l->tail->prev) {
6781 l->tail->prev->next = NULL;
6782 }
6783@@ -159,9 +218,16 @@
6784 {
6785 zend_llist_element *ptr;
6786
6787+#if HARDENING_PATCH_LL_PROTECT
6788+ TSRMLS_FETCH();
6789+ CHECK_LIST_CANARY(src)
6790+#endif
6791 zend_llist_init(dst, src->size, src->dtor, src->persistent);
6792 ptr = src->head;
6793 while (ptr) {
6794+#if HARDENING_PATCH_LL_PROTECT
6795+ CHECK_LISTELEMENT_CANARY(ptr)
6796+#endif
6797 zend_llist_add_element(dst, ptr->data);
6798 ptr = ptr->next;
6799 }
6800@@ -172,11 +238,21 @@
6801 {
6802 zend_llist_element *element, *next;
6803
6804+#if HARDENING_PATCH_LL_PROTECT
6805+ TSRMLS_FETCH();
6806+ CHECK_LIST_CANARY(l)
6807+#endif
6808 element=l->head;
6809 while (element) {
6810+#if HARDENING_PATCH_LL_PROTECT
6811+ CHECK_LISTELEMENT_CANARY(element)
6812+#endif
6813 next = element->next;
6814 if (func(element->data)) {
6815 DEL_LLIST_ELEMENT(element, l);
6816+#if HARDENING_PATCH_LL_PROTECT
6817+ element->canary = 0;
6818+#endif
6819 }
6820 element = next;
6821 }
6822@@ -187,7 +263,13 @@
6823 {
6824 zend_llist_element *element;
6825
6826+#if HARDENING_PATCH_LL_PROTECT
6827+ CHECK_LIST_CANARY(l)
6828+#endif
6829 for (element=l->head; element; element=element->next) {
6830+#if HARDENING_PATCH_LL_PROTECT
6831+ CHECK_LISTELEMENT_CANARY(element)
6832+#endif
6833 func(element->data TSRMLS_CC);
6834 }
6835 }
6836@@ -199,6 +281,9 @@
6837 zend_llist_element **elements;
6838 zend_llist_element *element, **ptr;
6839
6840+#if HARDENING_PATCH_LL_PROTECT
6841+ CHECK_LIST_CANARY(l)
6842+#endif
6843 if (l->count <= 0) {
6844 return;
6845 }
6846@@ -208,6 +293,9 @@
6847 ptr = &elements[0];
6848
6849 for (element=l->head; element; element=element->next) {
6850+#if HARDENING_PATCH_LL_PROTECT
6851+ CHECK_LISTELEMENT_CANARY(element)
6852+#endif
6853 *ptr++ = element;
6854 }
6855
6856@@ -230,7 +318,13 @@
6857 {
6858 zend_llist_element *element;
6859
6860+#if HARDENING_PATCH_LL_PROTECT
6861+ CHECK_LIST_CANARY(l)
6862+#endif
6863 for (element=l->head; element; element=element->next) {
6864+#if HARDENING_PATCH_LL_PROTECT
6865+ CHECK_LISTELEMENT_CANARY(element)
6866+#endif
6867 func(element->data, arg TSRMLS_CC);
6868 }
6869 }
6870@@ -241,8 +335,14 @@
6871 zend_llist_element *element;
6872 va_list args;
6873
6874+#if HARDENING_PATCH_LL_PROTECT
6875+ CHECK_LIST_CANARY(l)
6876+#endif
6877 va_start(args, num_args);
6878 for (element=l->head; element; element=element->next) {
6879+#if HARDENING_PATCH_LL_PROTECT
6880+ CHECK_LISTELEMENT_CANARY(element)
6881+#endif
6882 func(element->data, num_args, args TSRMLS_CC);
6883 }
6884 va_end(args);
6885@@ -251,6 +351,10 @@
6886
6887 ZEND_API int zend_llist_count(zend_llist *l)
6888 {
6889+#if HARDENING_PATCH_LL_PROTECT
6890+ TSRMLS_FETCH();
6891+ CHECK_LIST_CANARY(l)
6892+#endif
6893 return l->count;
6894 }
6895
6896@@ -259,8 +363,15 @@
6897 {
6898 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
6899
6900+#if HARDENING_PATCH_LL_PROTECT
6901+ TSRMLS_FETCH();
6902+ CHECK_LIST_CANARY(l)
6903+#endif
6904 *current = l->head;
6905 if (*current) {
6906+#if HARDENING_PATCH_LL_PROTECT
6907+ CHECK_LISTELEMENT_CANARY(*current)
6908+#endif
6909 return (*current)->data;
6910 } else {
6911 return NULL;
6912@@ -272,8 +383,15 @@
6913 {
6914 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
6915
6916+#if HARDENING_PATCH_LL_PROTECT
6917+ TSRMLS_FETCH();
6918+ CHECK_LIST_CANARY(l)
6919+#endif
6920 *current = l->tail;
6921 if (*current) {
6922+#if HARDENING_PATCH_LL_PROTECT
6923+ CHECK_LISTELEMENT_CANARY(*current)
6924+#endif
6925 return (*current)->data;
6926 } else {
6927 return NULL;
6928@@ -285,9 +403,19 @@
6929 {
6930 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
6931
6932+#if HARDENING_PATCH_LL_PROTECT
6933+ TSRMLS_FETCH();
6934+ CHECK_LIST_CANARY(l)
6935+#endif
6936 if (*current) {
6937+#if HARDENING_PATCH_LL_PROTECT
6938+ CHECK_LISTELEMENT_CANARY(*current)
6939+#endif
6940 *current = (*current)->next;
6941 if (*current) {
6942+#if HARDENING_PATCH_LL_PROTECT
6943+ CHECK_LISTELEMENT_CANARY(*current)
6944+#endif
6945 return (*current)->data;
6946 }
6947 }
6948@@ -299,9 +427,19 @@
6949 {
6950 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
6951
6952+#if HARDENING_PATCH_LL_PROTECT
6953+ TSRMLS_FETCH();
6954+ CHECK_LIST_CANARY(l)
6955+#endif
6956 if (*current) {
6957+#if HARDENING_PATCH_LL_PROTECT
6958+ CHECK_LISTELEMENT_CANARY(*current)
6959+#endif
6960 *current = (*current)->prev;
6961 if (*current) {
6962+#if HARDENING_PATCH_LL_PROTECT
6963+ CHECK_LISTELEMENT_CANARY(*current)
6964+#endif
6965 return (*current)->data;
6966 }
6967 }
6968diff -Nura php-5.0.5/Zend/zend_llist.h hardening-patch-5.0.5-0.4.3/Zend/zend_llist.h
6969--- php-5.0.5/Zend/zend_llist.h 2004-01-08 18:31:47.000000000 +0100
6970+++ hardening-patch-5.0.5-0.4.3/Zend/zend_llist.h 2005-09-11 23:30:52.000000000 +0200
6971@@ -23,6 +23,9 @@
6972 #define ZEND_LLIST_H
6973
6974 typedef struct _zend_llist_element {
6975+#if HARDENING_PATCH_LL_PROTECT
6976+ unsigned int canary;
6977+#endif
6978 struct _zend_llist_element *next;
6979 struct _zend_llist_element *prev;
6980 char data[1]; /* Needs to always be last in the struct */
6981@@ -35,6 +38,9 @@
6982 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
6983
6984 typedef struct _zend_llist {
6985+#if HARDENING_PATCH_LL_PROTECT
6986+ unsigned int canary_h; /* head */
6987+#endif
6988 zend_llist_element *head;
6989 zend_llist_element *tail;
6990 size_t count;
6991@@ -42,6 +48,9 @@
6992 llist_dtor_func_t dtor;
6993 unsigned char persistent;
6994 zend_llist_element *traverse_ptr;
6995+#if HARDENING_PATCH_LL_PROTECT
6996+ unsigned int canary_t; /* tail */
6997+#endif
6998 } zend_llist;
6999
7000 typedef zend_llist_element* zend_llist_position;
7001diff -Nura php-5.0.5/Zend/zend_modules.h hardening-patch-5.0.5-0.4.3/Zend/zend_modules.h
7002--- php-5.0.5/Zend/zend_modules.h 2005-03-16 00:47:12.000000000 +0100
7003+++ hardening-patch-5.0.5-0.4.3/Zend/zend_modules.h 2005-09-12 22:59:59.000000000 +0200
7004@@ -38,6 +38,7 @@
7005 extern struct _zend_arg_info fourth_arg_force_ref[5];
7006 extern struct _zend_arg_info all_args_by_ref[1];
7007
7008+#define HARDENING_PATCH_ZEND_MODULE_API_NO 1002050912
7009 #define ZEND_MODULE_API_NO 20041030
7010 #ifdef ZTS
7011 #define USING_ZTS 1
7012@@ -45,10 +46,10 @@
7013 #define USING_ZTS 0
7014 #endif
7015
7016-#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, NULL
7017-#define ZE2_STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, ini_entries
7018+#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, NULL
7019+#define ZE2_STANDARD_MODULE_HEADER sizeof(zend_module_entry), HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, ini_entries
7020
7021-#define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0
7022+#define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0, ZEND_MODULE_API_NO
7023
7024 #define STANDARD_MODULE_PROPERTIES \
7025 NULL, STANDARD_MODULE_PROPERTIES_EX
7026@@ -81,6 +82,7 @@
7027 unsigned char type;
7028 void *handle;
7029 int module_number;
7030+ unsigned int real_zend_api;
7031 };
7032
7033
7034diff -Nura php-5.0.5/Zend/zend_opcode.c hardening-patch-5.0.5-0.4.3/Zend/zend_opcode.c
7035--- php-5.0.5/Zend/zend_opcode.c 2004-06-06 10:37:12.000000000 +0200
7036+++ hardening-patch-5.0.5-0.4.3/Zend/zend_opcode.c 2005-09-11 23:30:52.000000000 +0200
7037@@ -92,6 +92,9 @@
7038 op_array->uses_this = 0;
7039
7040 op_array->start_op = NULL;
7041+#if HARDENING_PATCH
7042+ op_array->created_by_eval = 0;
7043+#endif
7044
7045 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
7046 }