*/
class PhpMail implements MailInterface {
+ /**
+ * The configuration factory.
+ *
+ * @var \Drupal\Core\Config\ConfigFactoryInterface
+ */
+ protected $configFactory;
+
+ /**
+ * PhpMail constructor.
+ */
+ public function __construct() {
+ $this->configFactory = \Drupal::configFactory();
+ }
+
/**
* Concatenates and wraps the email body for plain-text mails.
*
// On most non-Windows systems, the "-f" option to the sendmail command
// is used to set the Return-Path. There is no space between -f and
// the value of the return path.
- $additional_headers = isset($message['Return-Path']) ? '-f' . $message['Return-Path'] : '';
+ // We validate the return path, unless it is equal to the site mail, which
+ // we assume to be safe.
+ $site_mail = $this->configFactory->get('system.site')->get('mail');
+ $additional_headers = isset($message['Return-Path']) && ($site_mail === $message['Return-Path'] || static::_isShellSafe($message['Return-Path'])) ? '-f' . $message['Return-Path'] : '';
$mail_result = @mail(
$message['to'],
$mail_subject,
return $mail_result;
}
+ /**
+ * Disallows potentially unsafe shell characters.
+ *
+ * Functionally similar to PHPMailer::isShellSafe() which resulted from
+ * CVE-2016-10045. Note that escapeshellarg and escapeshellcmd are inadequate
+ * for this purpose.
+ *
+ * @param string $string
+ * The string to be validated.
+ *
+ * @return bool
+ * True if the string is shell-safe.
+ *
+ * @see https://github.com/PHPMailer/PHPMailer/issues/924
+ * @see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.phpmailer.php#L1430
+ *
+ * @todo Rename to ::isShellSafe() and/or discuss whether this is the correct
+ * location for this helper.
+ */
+ protected static function _isShellSafe($string) {
+ if (escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), ["'$string'", "\"$string\""])) {
+ return FALSE;
+ }
+ if (preg_match('/[^a-zA-Z0-9@_\-.]/', $string) !== 0) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
}