Fixed possible php script errors caused by $SQSPELL_APP configuration
variable changes. Removed $SQSPELL_EREG configuration option. Plugin's
version increased to 0.5.
+ - $skip_SM_header option was replaced with $encode_header_key and
+ $hide_auth_header options. First option allows to encode user's information
+ with provided encryption key (set in 2. Server settings -> B. Update SMTP /
+ Sendmail settings). Second option allows to disable authenticated user part
+ in Received: header, when user can't force used email address. It is set in
+ 4. General Options -> 9. Allow editing of identity.
Version 1.5.0 - 2 February 2004
-------------------------------
* @return string $header
*/
function prepareRFC822_Header($rfc822_header, $reply_rfc822_header, &$raw_length) {
- global $domain, $version, $username, $skip_SM_header;
+ global $domain, $version, $username, $encode_header_key, $edit_identity, $hide_auth_header;
/* if server var SERVER_NAME not available, use $domain */
if(!sqGetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER)) {
/* This creates an RFC 822 date */
$date = date('D, j M Y H:i:s ', mktime()) . $this->timezone();
/* Create a message-id */
- $message_id = '<' . $REMOTE_PORT . '.' . $REMOTE_ADDR . '.';
- $message_id .= time() . '.squirrel@' . $SERVER_NAME .'>';
+ $message_id = '<' . $REMOTE_PORT . '.';
+ if (isset($encode_header_key) && trim($encode_header_key)!='') {
+ // use encrypted form of remote address
+ $message_id.= OneTimePadEncrypt($this->ip2hex($REMOTE_ADDR),base64_encode($encode_header_key));
+ } else {
+ $message_id.= $REMOTE_ADDR;
+ }
+ $message_id .= '.' . time() . '.squirrel@' . $SERVER_NAME .'>';
/* Make an RFC822 Received: line */
if (isset($REMOTE_HOST)) {
$received_from = "$REMOTE_HOST ([$REMOTE_ADDR])";
$received_from .= " (proxying for $HTTP_X_FORWARDED_FOR)";
}
$header = array();
- if ( !isset($skip_SM_header) || !$skip_SM_header )
- {
- $header[] = "Received: from $received_from" . $rn;
- $header[] = " (SquirrelMail authenticated user $username)" . $rn;
- $header[] = " by $SERVER_NAME with HTTP;" . $rn;
- $header[] = " $date" . $rn;
+
+ /**
+ * SquirrelMail header
+ *
+ * This Received: header provides information that allows to track
+ * user and machine that was used to send email. Don't remove it
+ * unless you understand all possible forging issues or your
+ * webmail installation does not prevent changes in user's email address.
+ * See SquirrelMail bug tracker #847107 for more details about it.
+ */
+ if (isset($encode_header_key) &&
+ trim($encode_header_key)!='') {
+ // use encoded headers, if encryption key is set and not empty
+ $header[].= 'X-Squirrel-UserHash: '.OneTimePadEncrypt($username,base64_encode($encode_header_key)).$rn;
+ $header[].= 'X-Squirrel-FromHash: '.OneTimePadEncrypt($this->ip2hex($REMOTE_ADDR),base64_encode($encode_header_key)).$rn;
+ if (isset($HTTP_X_FORWARDED_FOR))
+ $header[].= 'X-Squirrel-ProxyHash:'.OneTimePadEncrypt($this->ip2hex($HTTP_X_FORWARDED_FOR),base64_encode($encode_header_key)).$rn;
+ } else {
+ // use default received headers
+ $header[] = "Received: from $received_from" . $rn;
+ if ($edit_identity || ! isset($hide_auth_header) || ! $hide_auth_header)
+ $header[] = " (SquirrelMail authenticated user $username)" . $rn;
+ $header[] = " by $SERVER_NAME with HTTP;" . $rn;
+ $header[] = " $date" . $rn;
}
+
/* Insert the rest of the header fields */
$header[] = 'Message-ID: '. $message_id . $rn;
if ($reply_rfc822_header->message_id) {
trim($refer);
return $refer;
}
+
+ /**
+ * Converts ip address to hexadecimal string
+ *
+ * Function is used to convert ipv4 and ipv6 addresses to hex strings.
+ * It removes all delimiter symbols from ip addresses, converts decimal
+ * ipv4 numbers to hex and pads strings in order to present full length
+ * address. ipv4 addresses are represented as 8 byte strings, ipv6 addresses
+ * are represented as 32 byte string.
+ *
+ * If function fails to detect address format, it returns unprocessed string.
+ * @param string $string ip address string
+ * @return string processed ip address string
+ * @since 1.5.1
+ */
+ function ip2hex($string) {
+ if (preg_match("/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/",$string,$match)) {
+ // ipv4 address
+ $ret = str_pad(dechex($match[1]),2,'0',STR_PAD_LEFT)
+ . str_pad(dechex($match[2]),2,'0',STR_PAD_LEFT)
+ . str_pad(dechex($match[3]),2,'0',STR_PAD_LEFT)
+ . str_pad(dechex($match[4]),2,'0',STR_PAD_LEFT);
+ } elseif (preg_match("/^([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)\:([0-9a-h]+)$/i",$string,$match)) {
+ // full ipv6 address
+ $ret = str_pad($match[1],4,'0',STR_PAD_LEFT)
+ . str_pad($match[2],4,'0',STR_PAD_LEFT)
+ . str_pad($match[3],4,'0',STR_PAD_LEFT)
+ . str_pad($match[4],4,'0',STR_PAD_LEFT)
+ . str_pad($match[5],4,'0',STR_PAD_LEFT)
+ . str_pad($match[6],4,'0',STR_PAD_LEFT)
+ . str_pad($match[7],4,'0',STR_PAD_LEFT)
+ . str_pad($match[8],4,'0',STR_PAD_LEFT);
+ } elseif (preg_match("/^\:\:([0-9a-h\:]+)$/i",$string,$match)) {
+ // short ipv6 with all starting symbols nulled
+ $aAddr=explode(':',$match[1]);
+ $ret='';
+ foreach ($aAddr as $addr) {
+ $ret.=str_pad($addr,4,'0',STR_PAD_LEFT);
+ }
+ $ret=str_pad($ret,32,'0',STR_PAD_LEFT);
+ } elseif (preg_match("/^([0-9a-h\:]+)::([0-9a-h\:]+)$/i",$string,$match)) {
+ // short ipv6 with middle part nulled
+ $aStart=explode(':',$match[1]);
+ $sStart='';
+ foreach($aStart as $addr) {
+ $sStart.=str_pad($addr,4,'0',STR_PAD_LEFT);
+ }
+ $aEnd = explode(':',$match[2]);
+ $sEnd='';
+ foreach($aEnd as $addr) {
+ $sEnd.=str_pad($addr,4,'0',STR_PAD_LEFT);
+ }
+ $ret = $sStart
+ . str_pad('',(32 - strlen($sStart . $sEnd)),'0',STR_PAD_LEFT)
+ . $sEnd;
+ } else {
+ // unknown addressing
+ $ret = $string;
+ }
+ return $ret;
+ }
}
?>
\ No newline at end of file
$abook_global_file = '' if ( !$abook_global_file);
$abook_global_file_writeable = 'false' if ( !$abook_global_file_writeable);
$abook_global_file_listing = 'true' if ( !$abook_global_file_listing );
+$encode_header_key = '' if ( !$encode_header_key );
+$hide_auth_header = 'false' if ( !$hide_auth_header );
if ( $ARGV[0] eq '--install-plugin' ) {
print "Activating plugin " . $ARGV[1] . "\n";
if ( lc($useSendmail) eq 'true' ) {
print $WHT . "Sendmail" . $NRM . "\n--------\n";
print "4. Sendmail Path : $WHT$sendmail_path$NRM\n";
- print "5. Suppress SM header : $WHT$skip_SM_header$NRM\n";
+ print "5. Header encryption key : $WHT$encode_header_key$NRM\n";
print "\n";
} else {
print $WHT . "SMTP Settings" . $NRM . "\n-------------\n";
print "6. POP before SMTP : $WHT$pop_before_smtp$NRM\n";
print "7. SMTP Authentication : $WHT$smtp_auth_mech$NRM\n";
print "8. Secure SMTP (TLS) : $WHT$use_smtp_tls$NRM\n";
- print "9. Suppress SM header : $WHT$skip_SM_header$NRM\n";
+ print "9. Header encryption key : $WHT$encode_header_key$NRM\n";
print "\n";
}
}
print "6. Allow use of priority : $WHT$default_use_priority$NRM\n";
print "7. Hide SM attributions : $WHT$hide_sm_attributions$NRM\n";
print "8. Allow use of receipts : $WHT$default_use_mdn$NRM\n";
- print "9. Allow editing of identity : $WHT$edit_identity$NRM/$WHT$edit_name$NRM\n";
+ print "9. Allow editing of identity : $WHT$edit_identity$NRM\n";
+ print " Allow editing of name : $WHT$edit_name$NRM\n";
+ print " Remove username from header : $WHT$hide_auth_header$NRM\n";
print "10. Allow server thread sort : $WHT$allow_thread_sort$NRM\n";
print "11. Allow server-side sorting : $WHT$allow_server_sort$NRM\n";
print "12. Allow server charset search : $WHT$allow_charset_search$NRM\n";
elsif ( $command == 8 ) { $imap_server_type = command19(); }
elsif ( $command == 9 ) { $optional_delimiter = command111(); }
} elsif ( $show_smtp_settings && lc($useSendmail) eq 'true' ) {
- if ( $command == 4 ) { $sendmail_path = command15(); }
+ if ( $command == 4 ) { $sendmail_path = command15(); }
+ elsif ( $command == 5 ) { $encode_header_key = command114(); }
} elsif ( $show_smtp_settings ) {
if ( $command == 4 ) { $smtpServerAddress = command16(); }
elsif ( $command == 5 ) { $smtpPort = command17(); }
elsif ( $command == 6 ) { $pop_before_smtp = command18a(); }
elsif ( $command == 7 ) { $smtp_auth_mech = command112b(); }
elsif ( $command == 8 ) { $use_smtp_tls = command113("SMTP",$use_smtp_tls); }
- elsif ( $command == 9 ) { $skip_SM_header = command114(); }
+ elsif ( $command == 9 ) { $encode_header_key = command114(); }
}
} elsif ( $menu == 3 ) {
if ( $command == 1 ) { $default_folder_prefix = command21(); }
return $default_val;
}
+# $encode_header_key
sub command114{
- print "\nUse this to suppress insertion of SquirrelMail Received: headers\n";
- print "in outbound messages.\n\n";
-
- $YesNo = 'n';
- $YesNo = 'y' if ( lc($skip_SM_header) eq 'true' );
-
- print "Suppress SM header (y/n) [$WHT$YesNo$NRM]: $WHT";
- $new_skip_SM_header = <STDIN>;
- chomp($new_skip_SM_header);
-
- return 'true' if ( lc($new_skip_SM_header) eq 'y' );
- return 'false' if ( lc($new_skip_SM_header) eq 'n' );
- return $skip_SM_header;
+ print "Encryption key allows to hide SquirrelMail Received: headers\n";
+ print "in outbound messages. Interface uses encryption key to encode\n";
+ print "username, remote address and proxied address, then stores encoded\n";
+ print "information in X-Squirrel-* headers.\n";
+ print "\n";
+ print "Warning: used encryption function is not bulletproof. When used\n";
+ print "with static encryption keys, it provides only minimal security\n";
+ print "measures and information can be decoded quickly.\n";
+ print "\n";
+ print "Encoded information can be decoded with decrypt_headers.php script\n";
+ print "from SquirrelMail contrib/ directory.\n";
+ print "\n";
+ print "Enter encryption key: ";
+ $new_encode_header_key = <STDIN>;
+ if ( $new_encode_header_key eq "\n" ) {
+ $new_encode_header_key = $encode_header_key;
+ } else {
+ $new_encode_header_key =~ s/[\r\n]//g;
+ }
+ return $new_encode_header_key;
}
# MOTD
return 'false';
}
+
sub command310 {
print "This allows you to prevent the editing of the user's name and ";
print "email address. This is mainly useful when used with the ";
if ( ( $new_edit =~ /^y\n/i ) || ( ( $new_edit =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
$edit_identity = 'true';
$edit_name = 'true';
+ $hide_auth_header = 'false';
} else {
$edit_identity = 'false';
$edit_name = command311();
+ $hide_auth_header = command311b();
}
return $edit_identity;
}
return $edit_name;
}
+sub command311b {
+ print "SquirrelMail adds username information to every sent email.";
+ print "It is done in order to prevent possible sender forging when ";
+ print "end users are allowed to change their email and name ";
+ print "information.\n";
+ print "\n";
+ print "You can disable this header, if you think that it violates ";
+ print "user's privacy or security. Please note, that setting will ";
+ print "work only when users are not allowed to change their identity.\n";
+ print "\n";
+
+ if ( lc($hide_auth_header) eq "true" ) {
+ $default_value = "y";
+ } else {
+ $default_value = "n";
+ }
+ print "Remove username from email headers? (y/n) [$WHT$default_value$NRM]: $WHT";
+ $new_header = <STDIN>;
+ if ( ( $new_header =~ /^y\n/i ) || ( ( $new_header =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
+ $hide_auth_header = "true";
+ } else {
+ $hide_auth_header = "false";
+ }
+ return $edit_name;
+}
+
sub command312 {
print "This option allows you to choose if users can use thread sorting\n";
print "Your IMAP server must support the THREAD command for this to work\n";
print CF "\$invert_time = $invert_time;\n";
# string
print CF "\$optional_delimiter = '$optional_delimiter';\n";
- #boolean
- print CF "\$skip_SM_header = $skip_SM_header;\n";
+ # string
+ print CF "\$encode_header_key = '$encode_header_key';\n";
print CF "\n";
# string
print CF "\$edit_identity = $edit_identity;\n";
# boolean
print CF "\$edit_name = $edit_name;\n";
+ # boolean
+ print CF "\$hide_auth_header = $hide_auth_header;\n";
# boolean
print CF "\$allow_thread_sort = $allow_thread_sort;\n";
# boolean
$smtpPort = 25;
/**
- * SquirrelMail header control
+ * SquirrelMail header encryption
*
- * Option can be used to disable Received: headers added by SquirrelMail.
- * This can increase user's privacy and solve problems with spam filters
- * that increase spam marks for dynamic dialup addresses.
+ * Encryption key allows to hide SquirrelMail Received: headers
+ * in outbound messages. Interface uses encryption key to encode
+ * username, remote address and proxied address, then stores encoded
+ * information in X-Squirrel-* headers.
*
- * If admin enables this setting, system should have some logging facility
- * or other tools to control users. SquirrelMail's Received: header provides
- * information, that can't be forged by webmail user.
- * @global bool $skip_SM_header
+ * Warning: used encryption function is not bulletproof. When used
+ * with static encryption keys, it provides only minimal security
+ * measures and information can be decoded quickly.
+ *
+ * Encoded information can be decoded with decrypt_headers.php script
+ * from SquirrelMail contrib/ directory.
+ * @global string $encode_header_key
+ * @since 1.5.1
*/
-$skip_SM_header = false;
+$encode_header_key = '';
/**
* Path to Sendmail
* macosx
* hmailserver
* mercury32
+ * dovecot
* other
*
* Please note that this changes only some of server settings.
$edit_identity = true;
$edit_name = true;
+/**
+ * SquirrelMail adds username information to every sent email.
+ * It is done in order to prevent possible sender forging when
+ * end users are allowed to change their email and name
+ * information.
+ *
+ * You can disable this header, if you think that it violates
+ * user's privacy or security. Please note, that setting will
+ * work only when users are not allowed to change their identity.
+ *
+ * See SquirrelMail bug tracker #847107 for more details about it.
+ * @global bool $hide_auth_header
+ */
+$hide_auth_header = false;
+
/**
* Server Side Threading Control
*
--- /dev/null
+<?php
+/**
+ * Script provides form to decode encrypted header information.
+ *
+ * Copyright (c) 2005 The SquirrelMail Project Team
+ * This file is part of SquirrelMail webmail interface.
+ *
+ * SquirrelMail is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * SquirrelMail is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SquirrelMail; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * @version $Id$
+ * @package squirrelmail
+ */
+
+/**
+ * Set constant to path of your SquirrelMail install.
+ * @ignore
+ */
+define('SM_PATH','../');
+
+/**
+ * include SquirrelMail string functions
+ * script needs OneTimePadDecrypt() (functions/strings.php)
+ * and sqgetGlobalVar() (functions/global.php, loaded by strings.php)
+ */
+include_once(SM_PATH.'functions/strings.php');
+
+/**
+ * converts hex string to ip address
+ * @param string $hex hexadecimal string created with squirrelmail ip2hex
+ * function in delivery class.
+ * @return string ip address
+ * @since 1.5.1
+ */
+function hex2ip($hex) {
+ if (strlen($hex)==8) {
+ $ret=hexdec(substr($hex,0,2)).'.'
+ .hexdec(substr($hex,2,2)).'.'
+ .hexdec(substr($hex,4,2)).'.'
+ .hexdec(substr($hex,6,2));
+ } elseif (strlen($hex)==32) {
+ $ret=hexdec(substr($hex,0,4)).':'
+ .hexdec(substr($hex,4,4)).':'
+ .hexdec(substr($hex,8,4)).':'
+ .hexdec(substr($hex,12,4)).':'
+ .hexdec(substr($hex,16,4)).':'
+ .hexdec(substr($hex,20,4)).':'
+ .hexdec(substr($hex,24,4)).':'
+ .hexdec(substr($hex,28,4));
+ } else {
+ $ret=$hex;
+ }
+ return $ret;
+}
+
+/** create page headers */
+header('Content-Type: text/html');
+
+echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
+ ."\n<head>\n<meta name=\"robots\" content=\"noindex,nofollow\">\n"
+ ."</head><body>";
+
+if (sqgetGlobalVar('submit',$submit,SQ_POST)) {
+ if (! sqgetGlobalVar('secret',$secret,SQ_POST) ||
+ empty($secret))
+ echo "<p>You must enter encryption key.</p>\n";
+ if (! sqgetGlobalVar('enc_string',$enc_string,SQ_POST) ||
+ empty($enc_string))
+ echo "<p>You must enter encrypted string.</p>\n";
+
+ if (isset($enc_string) && ! base64_decode($enc_string)) {
+ echo "<p>Encrypted string should be BASE64 encoded.<br />\n"
+ ."Please enter all characters that are listed after header name.</p>\n";
+ } elseif (isset($secret)) {
+ $string=OneTimePadDecrypt($enc_string,base64_encode($secret));
+
+ if (sqgetGlobalVar('ip_addr',$is_addr,SQ_POST)) {
+ $string=hex2ip($string);
+ }
+ echo "<p>Decoded string: ".$string."</p>\n";
+ }
+ echo "<hr />";
+}
+?>
+<form action="<?php echo $PHP_SELF ?>" method="post" >
+<p>
+Secret key: <input type="password" name="secret"><br />
+Encrypted string: <input type="text" name="enc_string"><br />
+Check, if it is an address string: <input type="checkbox" name="ip_addr" /><br />
+<button type="submit" name="submit" value="submit">Submit</button>
+</p>
+</form>
+</body></html>
\ No newline at end of file
*/
function OneTimePadEncrypt ($string, $epad) {
$pad = base64_decode($epad);
+
+ if (strlen($pad)>0) {
+ // make sure that pad is longer than string
+ while (strlen($string)>strlen($pad)) {
+ $pad.=$pad;
+ }
+ } else {
+ // FIXME: what should we do when $epad is not base64 encoded or empty.
+ }
+
$encrypted = '';
for ($i = 0; $i < strlen ($string); $i++) {
$encrypted .= chr (ord($string[$i]) ^ ord($pad[$i]));
*/
function OneTimePadDecrypt ($string, $epad) {
$pad = base64_decode($epad);
+
+ if (strlen($pad)>0) {
+ // make sure that pad is longer than string
+ while (strlen($string)>strlen($pad)) {
+ $pad.=$pad;
+ }
+ } else {
+ // FIXME: what should we do when $epad is not base64 encoded or empty.
+ }
+
$encrypted = base64_decode ($string);
$decrypted = '';
for ($i = 0; $i < strlen ($encrypted); $i++) {