Commit e283dcd5 authored by Kasper Skårhøj's avatar Kasper Skårhøj
Browse files

* Added full safety for the internal TYPO3 formmail; email addresses in the fields "recipient" and "recipient_copy" are encrypted in the transfer and the "formmail" interface is safe for spam-misuse (since a proper recipient address cannot be forged automatically).


git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@183 709f56b5-9817-0410-a4d7-c38de5d9e867
parent 0b7f0d91
2004-04-01 Kasper Skårhøj,,, <kasper@typo3.com>
* Added full safety for the internal TYPO3 formmail; email addresses in the fields "recipient" and "recipient_copy" are encrypted in the transfer and the "formmail" interface is safe for spam-misuse (since a proper recipient address cannot be forged automatically).
!!!If someone are using the "formmail" API from other renderers than the FORM cObject in TypoScript you will have to set the recipient address to the encrypted value by default OR alternatively disabled the check by TYPO3_CONF_VARS[FE][strictFormmail] = FALSE
2004-04-01 Kasper Skårhøj,,, <kasper@typo3.com>
* Added Jens Ellerbrocks suggestion for "postUserFuncInt" in stdWrap.
......
......@@ -49,7 +49,7 @@ $TYPO3_CONF_VARS = Array(
),
'SYS' => Array( // System related concerning both frontend and backend.
'sitename' => 'TYPO3', // Name of the base-site. This title shows up in the root of the tree structure if you're an 'admin' backend user.
'encryptionKey' => '', // Insert some unique string here! Used in eg. direct mail module to generate a md5 hash in combination with uid. This string should be kept secret although it's not as critical as a password.
'encryptionKey' => '', // This is a "salt" used for various kinds of encryption, CRC checksums and validations. You can enter any rubbish string here but try to keep it secret. You should notice that a change to this value might invalidate temporary information, URLs etc. At least, clear all cache if you change this so any such information can be rebuild with the new key.
'doNotCheckReferer' => 0, // Boolean. If set, it's NOT checked numerous places that the refering host is the same as the current. This is an option you should set if you have problems with proxies not passing the HTTP_REFERER variable.
'recursiveDomainSearch' => 0, // Boolean. If set, the search for domain records will be done recursively by stripping parts of the host name off until a matching domain record is found.
'devIPmask' => '192.168.*,127.0.0.1', // Defines a list of IP addresses which will allow development-output to display. The debug() function will use this as a filter. See the function t3lib_div::cmpIP() for details on syntax. Setting this to blank value will deny all. Setting to '*' will allow all.
......@@ -154,6 +154,7 @@ $TYPO3_CONF_VARS = Array(
'debug' => 0, // Boolean. If set, some debug HTML-comments may be output somewhere. Can also be set by TypoScript.
'simulateStaticDocuments' => 0, // Boolean. This is the default value for simulateStaticDocuments (configurable with TypoScript which overrides this, if the TypoScript value is present)
'noPHPscriptInclude' => 0, // Boolean. If set, PHP-scripts are not included by TypoScript configurations, unless they reside in 'media/scripts/'-folder. This is a security option to ensure that users with template-access do not terrorize
'strictFormmail' => TRUE, // Boolean. If set, the internal "formmail" feature in TYPO3 will send mail ONLY to recipients which has been encoded by the system itself. This protects against spammers misusing the formmailer.
'compressionLevel' => 0, // Determines output compression. Requires zlib in your php4 install. Range 1-9, where 1 is least compression (approx. 50%) and 9 is greatest compression (approx 33%). 'true' as value will set the compression based on system load (works with Linux, freebsd). Good default value is 3. For more info, see class in t3lib/class.gzip_encode.php written by Sandy McArthur, Jr. <Leknor@Leknor.com>
'compressionDebugInfo' => 0, // Boolean. If set, then in the end of the pages, the sizes of the compressed and non-compressed document is output. This should be used ONLY as a test, because the content is compressed twice in order to output this statistics!
'pageNotFound_handling' => '', // How TYPO3 should handle requests for non-existing/accessible pages. false (default): The 'nearest' page is shown. TRUE or '1': An TYPO3 error box is displayed. Integer > 1: Not used yet. Strings: redirect URL, eg. 'notfound.html' or 'http://www.domain.org/errors/notfound.html'.
......
......@@ -150,7 +150,7 @@
* 5059: function HTMLcaseshift($theValue, $case)
* 5088: function bytes($sizeInBytes,$labels)
* 5099: function calcAge($seconds,$labels)
* 5130: function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName='', $replyTo='')
* 5130: function sendNotifyEmail($msg, $recipients, $cc, $email_from, $email_fromName='', $replyTo='')
* 5157: function URLqMark($url,$params)
* 5173: function checkEmail($email)
* 5185: function clearTSProperties($TSArr,$propList)
......@@ -1677,9 +1677,12 @@ class tslib_cObj {
$fieldCode=$option;
break;
case 'hidden':
$value=trim($parts[2]);
$value = trim($parts[2]);
if (strlen($value) && $confData['fieldname']=='recipient_copy') {
$value = $GLOBALS['TSFE']->codeString($value);
}
$hiddenfields.=sprintf('<input type="hidden" name="%s" value="%s" />',
$confData['fieldname'], $value);
$confData['fieldname'], htmlspecialchars($value));
break;
case 'property':
if (t3lib_div::inList('type,locationData,goodMess,badMess',$confData['fieldname'])) {
......@@ -1775,12 +1778,13 @@ class tslib_cObj {
$action=$LD_A['totalURL'];
}
// copyemail:
// Recipient:
$theEmail = $this->stdWrap($conf['recipient'], $conf['recipient.']);
if ($theEmail) {
$theEmail = $GLOBALS['TSFE']->codeString($theEmail);
$hiddenfields.='<input type="hidden" name="recipient" value="'.htmlspecialchars($theEmail).'" />';
}
// location data:
if ($conf['locationData']) {
if ($conf['locationData']=='HTTP_POST_VARS' && isset($GLOBALS['HTTP_POST_VARS']['locationData'])) {
......@@ -1794,9 +1798,12 @@ class tslib_cObj {
// hidden fields:
if (is_array($conf['hiddenFields.'])) {
reset($conf['hiddenFields.']);
while(list($hF_key,$hF_conf)=each($conf['hiddenFields.'])) {
while(list($hF_key,$hF_conf) = each($conf['hiddenFields.'])) {
if (substr($hF_key,-1)!='.') {
$hF_value = $this->cObjGetSingle($hF_conf,$conf['hiddenFields.'][$hF_key.'.'],'hiddenfields');
if (strlen($value) && $hF_key=='recipient_copy') {
$hF_value = $GLOBALS['TSFE']->codeString($hF_value);
}
$hiddenfields.='<input type="hidden" name="'.$hF_key.'" value="'.htmlspecialchars($hF_value).'" />';
}
}
......
......@@ -1438,7 +1438,7 @@
global $HTTP_POST_VARS;
if ($HTTP_POST_VARS['formtype_db'] || $HTTP_POST_VARS['formtype_mail']) {
$refInfo=parse_url(t3lib_div::getIndpEnv('HTTP_REFERER'));
$refInfo = parse_url(t3lib_div::getIndpEnv('HTTP_REFERER'));
if (t3lib_div::getIndpEnv('TYPO3_HOST_ONLY')==$refInfo['host'] || $this->TYPO3_CONF_VARS['SYS']['doNotCheckReferer']) {
if ($this->locDataCheck($HTTP_POST_VARS['locationData'])) {
$ret = '';
......@@ -1498,6 +1498,23 @@
unset($EMAIL_VARS['locationData']);
unset($EMAIL_VARS['formtype_mail']);
$integrityCheck = $this->TYPO3_CONF_VARS['FE']['strictFormmail'];
// Check recipient field:
$encodedFields = explode(',','recipient,recipient_copy'); // These two fields are the ones which contain recipient addresses that can be misused to send mail from foreign servers.
foreach($encodedFields as $fieldKey) {
if (strlen($EMAIL_VARS[$fieldKey])) {
if ($res = $this->codeString($EMAIL_VARS[$fieldKey], TRUE)) { // Decode...
$EMAIL_VARS[$fieldKey] = $res; // Set value if OK
} elseif ($integrityCheck) { // Otherwise abort:
$GLOBALS['TT']->setTSlogMessage('"Formmail" discovered a field ('.$fieldKey.') which could not be decoded to a valid string. Sending formmail aborted due to security reasons!',3);
return FALSE;
} else {
$GLOBALS['TT']->setTSlogMessage('"Formmail" discovered a field ('.$fieldKey.') which could not be decoded to a valid string. The security level accepts this, but you should consider a correct coding though!',2);
}
}
}
// Hook for preprocessing of the content for formmails:
if (is_array($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sendFormmail-PreProcClass'])) {
foreach($this->TYPO3_CONF_VARS['SC_OPTIONS']['tslib/class.tslib_fe.php']['sendFormmail-PreProcClass'] as $_classRef) {
......@@ -2494,12 +2511,62 @@ if (version == "n3") {
$out = '';
for ($a=0; $a<strlen($string); $a++) {
$charValue = ord(substr($string,$a,1));
$charValue+= intval($GLOBALS['TSFE']->spamProtectEmailAddresses)*($back?-1:1);
$charValue+= intval($this->spamProtectEmailAddresses)*($back?-1:1);
$out.= chr($charValue);
}
return $out;
}
/**
* En/decodes strings with lightweight encryption and a hash containing the server encryptionKey (salt)
* Can be used for authentication of information sent from server generated pages back to the server to establish that the server generated the page. (Like hidden fields with recipient mail addresses)
* Encryption is mainly to avoid spam-bots to pick up information.
*
* @param string Input string to en/decode
* @param boolean If set, string is decoded, not encoded.
* @return string encoded/decoded version of $string
*/
function codeString($string, $decode=FALSE) {
if ($decode) {
list($md5Hash, $str) = explode(':',$string,2);
$newHash = substr(md5($this->TYPO3_CONF_VARS['SYS']['encryptionKey'].':'.$str),0,10);
if (!strcmp($md5Hash, $newHash)) {
$str = base64_decode($str);
$str = $this->roundTripCryptString($str);
return $str;
} else return FALSE; // Decoding check failed! Original string not produced by this server!
} else {
$str = $string;
$str = $this->roundTripCryptString($str);
$str = base64_encode($str);
$newHash = substr(md5($this->TYPO3_CONF_VARS['SYS']['encryptionKey'].':'.$str),0,10);
return $newHash.':'.$str;
}
}
/**
* En/decodes strings with lightweight encryption and a hash containing the server encryptionKey (salt)
* Can be used for authentication of information sent from server generated pages back to the server to establish that the server generated the page. (Like hidden fields with recipient mail addresses)
* Encryption is mainly to avoid spam-bots to pick up information.
*
* @param string Input string to en/decode
* @param boolean If set, string is decoded, not encoded.
* @return string encoded/decoded version of $string
*/
function roundTripCryptString($string) {
$out = '';
$strLen = strlen($string);
$cryptLen = strlen($this->TYPO3_CONF_VARS['SYS']['encryptionKey']);
for ($a=0; $a < $strLen; $a++) {
$xorVal = $cryptLen>0 ? ord($this->TYPO3_CONF_VARS['SYS']['encryptionKey']{($a%$cryptLen)}) : 255;
$out.= chr(ord($string{$a}) ^ $xorVal);
}
return $out;
}
/**
* Checks if a PHPfile may be included.
*
......
......@@ -178,6 +178,7 @@ class SC_wizard_forms {
var $doc; // Document template object
var $content; // Content accumulation for the module.
var $include_once=array(); // List of files to include.
var $attachmentCounter = 0; // Used to numerate attachments automatically.
// Internal, static:
......@@ -410,7 +411,7 @@ class SC_wizard_forms {
// Special parts:
if ($this->special=='formtype_mail' && t3lib_div::inList('formtype_mail,subject,html_enabled',$confData['fieldname'])) {
$specParts[$confData['fieldname']]=$confData['default'];
$specParts[$confData['fieldname']] = $confData['default'];
} else {
// Render title/field preview COLUMN
......@@ -452,6 +453,9 @@ class SC_wizard_forms {
$temp_cells=array();
// Fieldname
if ($this->special=='formtype_mail' && $confData['type']=='file') {
$confData['fieldname'] = 'attachment'.(++$this->attachmentCounter);
}
$temp_cells[$LANG->getLL('forms_fieldName')]='<input type="text"'.$this->doc->formWidth(10).' name="FORMCFG[c]['.(($k+1)*2).'][fieldname]" value="'.htmlspecialchars($confData['fieldname']).'" title="'.$LANG->getLL('forms_fieldName',1).'" />';
// Field configuration depending on the fields type:
......@@ -808,8 +812,16 @@ class SC_wizard_forms {
$confData['fieldname'] = str_replace(' ','_',trim($typeParts[0]));
}
$confData['default'] = implode(chr(10),t3lib_div::trimExplode(',',$parts[2]));
switch((string)$confData['type']) {
case 'select':
case 'radio':
$confData['default'] = implode(chr(10),t3lib_div::trimExplode(',',$parts[2]));
break;
default:
$confData['default'] = trim($parts[2]);
break;
}
// Field configuration depending on the fields type:
switch((string)$confData['type']) {
case 'textarea':
......@@ -842,7 +854,7 @@ class SC_wizard_forms {
// Adding config array:
$cfgArr[]=$confData;
}
// Return cfgArr
return $cfgArr;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment