rasmus          Wed Feb 19 14:41:10 2003 EDT

  Added files:                 
    /php4       README.input_filter 

  Modified files:              
    /php4/ext/mbstring  mb_gpc.c mbstring.c 
    /php4/main  SAPI.c SAPI.h php_content_types.c php_variables.c 
                rfc1867.c 
  Log:
  Input Filter support.  See README.input_filter for details.
  @- Input Filter support added. See  README.input_filter. (Rasmus)
  
  
Index: php4/ext/mbstring/mb_gpc.c
diff -u php4/ext/mbstring/mb_gpc.c:1.3 php4/ext/mbstring/mb_gpc.c:1.4
--- php4/ext/mbstring/mb_gpc.c:1.3      Tue Dec 31 11:06:52 2002
+++ php4/ext/mbstring/mb_gpc.c  Wed Feb 19 14:41:07 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: mb_gpc.c,v 1.3 2002/12/31 16:06:52 sebastian Exp $ */
+/* $Id: mb_gpc.c,v 1.4 2003/02/19 19:41:07 rasmus Exp $ */
 
 /* {{{ includes */
 #ifdef HAVE_CONFIG_H
@@ -169,7 +169,7 @@
                break;
        }
 
-       _php_mb_encoding_handler_ex(array_ptr, res, separator, 0, 0 TSRMLS_CC);
+       _php_mb_encoding_handler_ex(arg, array_ptr, res, separator, 0, 0 TSRMLS_CC);
 
        if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid) {
                switch(arg){
@@ -199,7 +199,7 @@
 /* }}} */
 
 /* {{{ int _php_mb_encoding_handler_ex() */
-int _php_mb_encoding_handler_ex(zval *arg, char *res, char *separator, int 
force_register_globals, int report_errors TSRMLS_DC)
+int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separator, 
+int force_register_globals, int report_errors TSRMLS_DC)
 {
        char *var, *val, *s1, *s2;
        char *strtok_buf = NULL, **val_list = NULL;
@@ -342,6 +342,7 @@
                        val_len = len_list[n];
                }
                n++;
+               val_len = sapi_module.input_filter(data_type, var, val, val_len 
+TSRMLS_CC);
                /* add variable to symbol table */
                php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
                if (convd != NULL){
Index: php4/ext/mbstring/mbstring.c
diff -u php4/ext/mbstring/mbstring.c:1.163 php4/ext/mbstring/mbstring.c:1.164
--- php4/ext/mbstring/mbstring.c:1.163  Tue Feb 18 15:31:04 2003
+++ php4/ext/mbstring/mbstring.c        Wed Feb 19 14:41:07 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: mbstring.c,v 1.163 2003/02/18 20:31:04 moriyoshi Exp $ */
+/* $Id: mbstring.c,v 1.164 2003/02/19 19:41:07 rasmus Exp $ */
 
 /*
  * PHP4 Multibyte String module "mbstring"
@@ -1281,7 +1281,7 @@
 
        encstr = estrndup(encstr, encstr_len);
 
-       RETVAL_BOOL(_php_mb_encoding_handler_ex(track_vars_array, encstr, separator, 
(track_vars_array == NULL), 1 TSRMLS_CC));
+       RETVAL_BOOL(_php_mb_encoding_handler_ex(PARSE_STRING, track_vars_array, 
+encstr, separator, (track_vars_array == NULL), 1 TSRMLS_CC));
 
        if (encstr != NULL) efree(encstr);
        if (separator != NULL) efree(separator);
Index: php4/main/SAPI.c
diff -u php4/main/SAPI.c:1.171 php4/main/SAPI.c:1.172
--- php4/main/SAPI.c:1.171      Tue Feb 11 16:44:02 2003
+++ php4/main/SAPI.c    Wed Feb 19 14:41:07 2003
@@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: SAPI.c,v 1.171 2003/02/11 21:44:02 sesser Exp $ */
+/* $Id: SAPI.c,v 1.172 2003/02/19 19:41:07 rasmus Exp $ */
 
 #include <ctype.h>
 #include <sys/stat.h>
@@ -823,6 +823,11 @@
        return SUCCESS;
 }
 
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char 
+*var, char *val, unsigned int val_len TSRMLS_DC))
+{
+       sapi_module.input_filter = input_filter;
+       return SUCCESS;
+}
 
 SAPI_API int sapi_flush(TSRMLS_D)
 {
Index: php4/main/SAPI.h
diff -u php4/main/SAPI.h:1.98 php4/main/SAPI.h:1.99
--- php4/main/SAPI.h:1.98       Wed Feb 19 03:40:17 2003
+++ php4/main/SAPI.h    Wed Feb 19 14:41:07 2003
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: SAPI.h,v 1.98 2003/02/19 08:40:17 sniper Exp $ */
+/* $Id: SAPI.h,v 1.99 2003/02/19 19:41:07 rasmus Exp $ */
 
 #ifndef SAPI_H
 #define SAPI_H
@@ -178,6 +178,7 @@
 SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry);
 SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
 SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval 
*destArray TSRMLS_DC));
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char 
+*var, char *val, unsigned int val_len TSRMLS_DC));
 
 SAPI_API int sapi_flush(TSRMLS_D);
 SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
@@ -238,6 +239,8 @@
 
        int (*get_target_uid)(uid_t * TSRMLS_DC);
        int (*get_target_gid)(gid_t * TSRMLS_DC);
+
+       unsigned int (*input_filter)(int arg, char *var, char *val, unsigned int 
+val_len TSRMLS_DC);
 };
 
 
@@ -266,10 +269,12 @@
 #define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char 
*content_type_dup, void *arg TSRMLS_DC)
 
 #define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* 
destArray TSRMLS_DC)
+#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char 
+*var, char *val, unsigned int val_len TSRMLS_DC)
 
 SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
 SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data);
+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter);
 
 #define STANDARD_SAPI_MODULE_PROPERTIES
 
Index: php4/main/php_content_types.c
diff -u php4/main/php_content_types.c:1.26 php4/main/php_content_types.c:1.27
--- php4/main/php_content_types.c:1.26  Tue Dec 31 10:58:53 2002
+++ php4/main/php_content_types.c       Wed Feb 19 14:41:08 2003
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: php_content_types.c,v 1.26 2002/12/31 15:58:53 sebastian Exp $ */
+/* $Id: php_content_types.c,v 1.27 2003/02/19 19:41:08 rasmus Exp $ */
 
 #include "php.h"
 #include "SAPI.h"
@@ -77,6 +77,7 @@
        sapi_register_post_entries(php_post_entries);
        sapi_register_default_post_reader(php_default_post_reader);
        sapi_register_treat_data(php_default_treat_data);
+       sapi_register_input_filter(php_default_input_filter);
        return SUCCESS;
 }
 /* }}} */
Index: php4/main/php_variables.c
diff -u php4/main/php_variables.c:1.49 php4/main/php_variables.c:1.50
--- php4/main/php_variables.c:1.49      Wed Feb 19 03:40:19 2003
+++ php4/main/php_variables.c   Wed Feb 19 14:41:08 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_variables.c,v 1.49 2003/02/19 08:40:19 sniper Exp $ */
+/* $Id: php_variables.c,v 1.50 2003/02/19 19:41:08 rasmus Exp $ */
 
 #include <stdio.h>
 #include "php.h"
@@ -226,12 +226,19 @@
                        *val++ = '\0';
                        php_url_decode(var, strlen(var));
                        val_len = php_url_decode(val, strlen(val));
+                       val_len = sapi_module.input_filter(PARSE_POST, var, val, 
+val_len TSRMLS_CC);
                        php_register_variable_safe(var, val, val_len, array_ptr 
TSRMLS_CC);
                }
                var = php_strtok_r(NULL, "&", &strtok_buf);
        }
 }
 
+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
+{
+       /* TODO: check .ini setting here and apply user-defined input filter */
+       return val_len;
+}
+
 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
 {
        char *res = NULL, *var, *val, *separator=NULL;
@@ -314,6 +321,7 @@
                        *val++ = '\0';
                        php_url_decode(var, strlen(var));
                        val_len = php_url_decode(val, strlen(val));
+                       val_len = sapi_module.input_filter(arg, var, val, val_len 
+TSRMLS_CC);
                        php_register_variable_safe(var, val, val_len, array_ptr 
TSRMLS_CC);
                } else {
                        php_url_decode(var, strlen(var));
Index: php4/main/rfc1867.c
diff -u php4/main/rfc1867.c:1.132 php4/main/rfc1867.c:1.133
--- php4/main/rfc1867.c:1.132   Wed Feb 19 03:40:19 2003
+++ php4/main/rfc1867.c Wed Feb 19 14:41:09 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: rfc1867.c,v 1.132 2003/02/19 08:40:19 sniper Exp $ */
+/* $Id: rfc1867.c,v 1.133 2003/02/19 19:41:09 rasmus Exp $ */
 
 /*
  *  This product includes software developed by the Apache Group
@@ -805,6 +805,7 @@
                                        value = estrdup("");
                                }
 
+                               sapi_module.input_filter(PARSE_POST, param, value, 
+strlen(value) TSRMLS_CC);
                                safe_php_register_variable(param, value, array_ptr, 0 
TSRMLS_CC);
                                if (!strcmp(param, "MAX_FILE_SIZE")) {
                                        max_file_size = atol(value);

Index: php4/README.input_filter
+++ php4/README.input_filter
Input Filter Support in PHP5
----------------------------

XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
and can be quite difficult to prevent.  Whenever you accept user data
and somehow display this data back to users, you are likely vulnerable
to XSS hacks.

The Input Filter support in PHP5 is aimed at providing the framework
through which a company-wide or site-wide security policy can be
enforced.  It is implemented as a SAPI hook and is called from the
treat_data and post handler functions.  To implement your own security
policy you will need to write a standard PHP extension.  

A simple implementation might look like the following.  This stores the
original raw user data and adds a my_get_raw() function while the normal
$_POST, $_GET and $_COOKIE arrays are only populated with stripped
data.  In this simple example all I am doing is calling strip_tags() on
the data.  If register_globals is turned on, the default globals that
are created will be stripped ($foo) while a $RAW_foo is created with the
original user input.

ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
        zval *post_array;
        zval *get_array;
        zval *cookie_array;
ZEND_END_MODULE_GLOBALS(my_input_filter)

#ifdef ZTS
#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
#else
#define IF_G(v) (my_input_filter_globals.v)
#endif

ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)

function_entry my_input_filter_functions[] = {
    PHP_FE(my_get_raw,   NULL)
    {NULL, NULL, NULL}
};

zend_module_entry my_input_filter_module_entry = {
    STANDARD_MODULE_HEADER,
    "my_input_filter",
    my_input_filter_functions,
    PHP_MINIT(my_input_filter),
    PHP_MSHUTDOWN(my_input_filter),
    NULL,
    PHP_RSHUTDOWN(my_input_filter),
    PHP_MINFO(my_input_filter),
    "0.1",
    STANDARD_MODULE_PROPERTIES
};

PHP_MINIT_FUNCTION(my_input_filter)
{
    ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);

    REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
    REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);

    sapi_register_input_filter(my_sapi_input_filter);
    return SUCCESS;
}

PHP_RSHUTDOWN_FUNCTION(my_input_filter)
{
    if(IF_G(get_array)) {
        zval_ptr_dtor(&IF_G(get_array));
        IF_G(get_array) = NULL;
    }
    if(IF_G(post_array)) {
        zval_ptr_dtor(&IF_G(post_array));
        IF_G(post_array) = NULL;
    }
    if(IF_G(cookie_array)) {
        zval_ptr_dtor(&IF_G(cookie_array));
        IF_G(cookie_array) = NULL;
    }
    return SUCCESS;
}

PHP_MINFO_FUNCTION(my_input_filter)
{
    php_info_print_table_start();
    php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
    php_info_print_table_row( 2, "Revision", "$Revision: 1.1 $");
    php_info_print_table_end();
}

unsigned int  my_sapi_input_filter(int arg, char *var, char *val, unsigned int val_len)
{
    zval new_var;
    zval *array_ptr = NULL;
    char *raw_var;
    int var_len;

    assert(val != NULL);

    switch(arg) {
        case PARSE_GET:
            if(!IF_G(get_array)) {
                ALLOC_ZVAL(array_ptr);
                array_init(array_ptr);
                INIT_PZVAL(array_ptr);
            }
            IF_G(get_array) = array_ptr;
            break;
        case PARSE_POST:
            if(!IF_G(post_array)) {
                ALLOC_ZVAL(array_ptr);
                array_init(array_ptr);
                INIT_PZVAL(array_ptr);
            }
            IF_G(post_array) = array_ptr;
            break;
        case PARSE_COOKIE:
            if(!IF_G(cookie_array)) {
                ALLOC_ZVAL(array_ptr);
                array_init(array_ptr);
                INIT_PZVAL(array_ptr);
            }
            IF_G(cookie_array) = array_ptr;
            break;
    }
    Z_STRLEN(new_var) = val_len;
    Z_STRVAL(new_var) = estrndup(val, val_len);
    Z_TYPE(new_var) = IS_STRING;

    var_len = strlen(var);
    raw_var = emalloc(var_len+5);  /* RAW_ and a \0 */
    strcpy(raw_var, "RAW_");
    strlcat(raw_var,var,var_len+5);

    php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);

    php_strip_tags(val, val_len, NULL, NULL, 0);

    return strlen(val);
}

PHP_FUNCTION(my_get_raw)
{
    long arg;
    char *var;
    int var_len;
    zval **tmp;
    zval *array_ptr = NULL;
    HashTable *hash_ptr;
    char *raw_var;

    if(zend_parse_parameters(2 TSRMLS_CC, "ls|l", &arg, &var, &var_len) == FAILURE) {
        return;
    }

    switch(arg) {
        case PARSE_GET:
            array_ptr = IF_G(get_array);
            break;
        case PARSE_POST:
            array_ptr = IF_G(post_array);
            break;
        case PARSE_COOKIE:
            array_ptr = IF_G(post_array);
            break;
    }

    if(!array_ptr) RETURN_FALSE;

    /*
     * I'm changing the variable name here because when running with register_globals 
on,
     * the variable will end up in the global symbol table
     */
    raw_var = emalloc(var_len+5);  /* RAW_ and a \0 */
    strcpy(raw_var, "RAW_");
    strlcat(raw_var,var,var_len+5);
    hash_ptr = HASH_OF(array_ptr);

    if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
        *return_value = **tmp;
        zval_copy_ctor(return_value);
    } else {
        RETVAL_FALSE;
    }
    efree(raw_var);
}


-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to