Changeset 1167

Show
Ignore:
Timestamp:
11/18/08 18:42:22 (2 months ago)
Author:
laurentj
Message:

ticket #478: support of security check against CSRF in jForms. new xml attribute allowAnyOrigin on the root element to disable it, and new jFormsBase::securityLevel

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/lib/jelix/core-modules/jelix/locales/en_EN/formserr.UTF-8.properties

    r1070 r1167  
    2323unknow.control=(830) The control "%1$s" doesn't exist in the form "%2$s" (template %3$s) 
    2424 
     25invalid.token=(835) The token of the form is not valide, you should fill the form from the original web page 
     26 
    2527js.err.invalid= "%s" field is invalid 
    2628js.err.required= "%s" field is required 
  • trunk/lib/jelix/core-modules/jelix/locales/en_US/formserr.UTF-8.properties

    r1070 r1167  
    2323unknow.control=(830) The control "%1$s" doesn't exist in the form "%2$s" (template %3$s) 
    2424 
     25invalid.token=(835) The token of the form is not valide, you should fill the form from the original web page 
     26 
    2527js.err.invalid= "%s" field is invalid 
    2628js.err.required= "%s" field is required 
  • trunk/lib/jelix/core-modules/jelix/locales/fr_FR/formserr.UTF-8.properties

    r1070 r1167  
    2323unknow.control=(830) Le contrôle "%1$s" n'existe pas dans le formulaire "%2$s" (template "%3$s") 
    2424 
     25invalid.token=(835) Le token du formulaire n'est pas valide, vous devez vous remplir le formulaire correctement à partir du site. 
     26 
    2527js.err.invalid=La saisie de "%s" est invalide 
    2628js.err.required=La saisie de "%s" est obligatoire 
  • trunk/lib/jelix/docs/ns/jforms_1.1.rng

    r1127 r1167  
    88   <start> 
    99      <element name="form"> 
     10         <optional><attribute name="allowAnyOrigin"> 
     11            <choice><value>true</value><value>false</value></choice> 
     12            </attribute></optional> 
    1013         <ref name="form.controls" /> 
    1114      </element> 
  • trunk/lib/jelix/forms/jFormsBase.class.php

    r1165 r1167  
    3535 */ 
    3636abstract class jFormsBase { 
     37     
     38    const SECURITY_LOW = 0; 
     39    const SECURITY_CSRF = 1; 
     40 
     41    public $securityLevel = 1; 
    3742 
    3843    /** 
     
    133138    public function initFromRequest(){ 
    134139        $req = $GLOBALS['gJCoord']->request; 
     140        if ($this->securityLevel == jFormsBase::SECURITY_CSRF) { 
     141            if ($this->container->token !== $req->getParam('__JFORMS_TOKEN__')) 
     142                throw new jException("jelix~formserr.invalid.token"); 
     143        } 
     144 
    135145        foreach($this->rootControls as $name=>$ctrl){ 
    136146            if(!$this->container->isActivated($name) || $this->container->isReadOnly($name)) 
  • trunk/lib/jelix/forms/jFormsCompiler_jf_1_0.class.php

    r1098 r1167  
    4141            $source[] = $this->generatePHPControl($controltype, $control); 
    4242        } 
     43         
     44        $this->_compile($xml, $source); 
     45    } 
     46     
     47    protected function _compile ($xml, &$source) { 
     48        // nothing for the moment, can be overrided 
    4349    } 
    4450 
  • trunk/lib/jelix/forms/jFormsCompiler_jf_1_1.class.php

    r1065 r1167  
    2626                                      'url','email','ipv4','ipv6','html'); 
    2727 
     28    protected function _compile ($xml, &$source) { 
     29        if(isset($xml['allowAnyOrigin']) && $xml['allowAnyOrigin'] == 'true') { 
     30            $source[]='$this->securityLevel=0;'; 
     31        } 
     32    } 
    2833 
    2934    protected function generateMenulist(&$source, $control, &$attributes) { 
  • trunk/lib/jelix/forms/jFormsDataContainer.class.php

    r1156 r1167  
    5858     */ 
    5959    public $updatetime = 0; 
     60 
     61    /** 
     62     * token for security against CSRF 
     63     */ 
     64    public $token = ''; 
    6065 
    6166    /** 
  • trunk/lib/jelix/plugins/jforms/html/html.jformsbuilder.php

    r1104 r1167  
    113113</script>'; 
    114114 
    115  
    116         if(count($url->params) || count($this->_form->getHiddens())){ 
    117             echo '<div class="jforms-hiddens">'; 
    118             foreach ($url->params as $p_name => $p_value) { 
    119                 echo '<input type="hidden" name="', $p_name ,'" value="', htmlspecialchars($p_value), '"',$this->_endt, "\n"; 
    120             } 
    121             foreach ($this->_form->getHiddens() as $ctrl) { 
    122                 if(!$this->_form->isActivated($ctrl->ref)) continue; 
    123                 echo '<input type="hidden" name="', $ctrl->ref,'" id="',$this->_name,'_',$ctrl->ref,'" value="', htmlspecialchars($this->_form->getData($ctrl->ref)), '"',$this->_endt, "\n"; 
    124             } 
    125             echo '</div>'; 
     115        $hiddens = ''; 
     116        foreach ($url->params as $p_name => $p_value) { 
     117            $hiddens .= '<input type="hidden" name="'. $p_name .'" value="'. htmlspecialchars($p_value). '"'.$this->_endt. "\n"; 
     118        } 
     119 
     120        foreach ($this->_form->getHiddens() as $ctrl) { 
     121            if(!$this->_form->isActivated($ctrl->ref)) continue; 
     122            $hiddens .= '<input type="hidden" name="'. $ctrl->ref.'" id="'.$this->_name.'_'.$ctrl->ref.'" value="'. htmlspecialchars($this->_form->getData($ctrl->ref)). '"'.$this->_endt. "\n"; 
     123        } 
     124 
     125        if($this->_form->securityLevel){ 
     126            $c = $this->_form->getContainer(); 
     127            $tok = $c->token = md5($c->formId.time().session_id()); 
     128            $hiddens .= '<input type="hidden" name="__JFORMS_TOKEN__" value="'.$tok.'"'.$this->_endt. "\n"; 
     129        } 
     130 
     131        if($hiddens){ 
     132            echo '<div class="jforms-hiddens">',$hiddens,'</div>'; 
    126133        } 
    127134 
  • trunk/lib/jelix/plugins/jforms/htmllight/htmllight.jformsbuilder.php

    r1104 r1167  
    112112</script>'; 
    113113 
    114  
    115         if(count($url->params) || count($this->_form->getHiddens())){ 
    116             echo '<div class="jforms-hiddens">'; 
    117             foreach ($url->params as $p_name => $p_value) { 
    118                 echo '<input type="hidden" name="', $p_name ,'" value="', htmlspecialchars($p_value), '"',$this->_endt, "\n"; 
    119             } 
    120             foreach ($this->_form->getHiddens() as $ctrl) { 
    121                 if(!$this->_form->isActivated($ctrl->ref)) continue; 
    122                 echo '<input type="hidden" name="', $ctrl->ref,'" id="',$this->_name,'_',$ctrl->ref,'" value="', htmlspecialchars($this->_form->getData($ctrl->ref)), '"',$this->_endt, "\n"; 
    123             } 
    124             echo '</div>'; 
     114        $hiddens = ''; 
     115        foreach ($url->params as $p_name => $p_value) { 
     116            $hiddens .= '<input type="hidden" name="'. $p_name .'" value="'. htmlspecialchars($p_value). '"'.$this->_endt. "\n"; 
     117        } 
     118 
     119        foreach ($this->_form->getHiddens() as $ctrl) { 
     120            if(!$this->_form->isActivated($ctrl->ref)) continue; 
     121            $hiddens .= '<input type="hidden" name="'. $ctrl->ref.'" id="'.$this->_name.'_'.$ctrl->ref.'" value="'. htmlspecialchars($this->_form->getData($ctrl->ref)). '"'.$this->_endt. "\n"; 
     122        } 
     123 
     124        if($this->_form->securityLevel){ 
     125            $c = $this->_form->getContainer(); 
     126            $tok = $c->token = md5($c->formId.time().session_id()); 
     127            $hiddens .= '<input type="hidden" name="__JFORMS_TOKEN__" value="'.$tok.'"'.$this->_endt. "\n"; 
     128        } 
     129 
     130        if($hiddens){ 
     131            echo '<div class="jforms-hiddens">',$hiddens,'</div>'; 
    125132        } 
    126133 
  • trunk/testapp/modules/jelix_tests/forms/label.form.xml

    r1127 r1167  
    11<?xml version="1.0" encoding="utf-8"?> 
    2 <form xmlns="http://jelix.org/ns/forms/1.1"
     2<form xmlns="http://jelix.org/ns/forms/1.1" allowAnyOrigin="true"
    33 
    44   <input ref="label" required="true"> 
  • trunk/testapp/modules/jelix_tests/forms/product.form.xml

    r1062 r1167  
    11<?xml version="1.0" encoding="utf-8"?> 
    2 <form xmlns="http://jelix.org/ns/forms/1.0"> 
     2<form xmlns="http://jelix.org/ns/forms/1.1" allowAnyOrigin="true"> 
    33 
    44   <input ref="name" required="true"> 
  • trunk/testapp/modules/jelix_tests/tests/jforms.htmlbuilder.html_cli.php

    r1104 r1167  
    3434        $this->container = new jFormsDataContainer('formtest',''); 
    3535        $this->form = new testHMLForm('formtest', $this->container, true ); 
     36        $this->form->securityLevel = 0; 
    3637        $this->builder = new testJFormsHtmlBuilder($this->form); 
    3738 
     
    5657        $this->assertEqualOrDiff('', $this->builder->getJsContent()); 
    5758 
     59        $this->form->securityLevel = 1; 
    5860        $this->builder->setAction('jelix_tests~urlsig:url1',array('foo'=>'b>ar')); 
    5961        ob_start(); 
     
    7072<input type="hidden" name="module" value="jelix_tests"/> 
    7173<input type="hidden" name="action" value="urlsig:url1"/> 
     74<input type="hidden" name="__JFORMS_TOKEN__" value="'.$this->container->token.'"/> 
    7275</div>'; 
    7376        $this->assertEqualOrDiff($result, $out); 
    7477        $this->formname = $this->builder->getName(); 
    7578        $this->assertEqualOrDiff('', $this->builder->getJsContent()); 
     79        $this->form->securityLevel = 0; 
    7680 
    7781    } 
  • trunk/testapp/modules/jelix_tests/tests/jforms.htmllightbuilder.html_cli.php

    r1104 r1167  
    3434        $this->container = new jFormsDataContainer('formtestlight',''); 
    3535        $this->form = new testHtmlLightForm('formtestlight', $this->container, true ); 
     36        $this->form->securityLevel = 0; 
    3637        $this->builder = new testJFormsHtmlLightBuilder($this->form); 
    3738 
Download in other formats: Unified Diff Zip Archive