Upgrader (5.34) - Handle unsavable characters
authorTim Otten <totten@civicrm.org>
Tue, 2 Mar 2021 12:10:15 +0000 (04:10 -0800)
committerTim Otten <totten@civicrm.org>
Tue, 2 Mar 2021 12:41:08 +0000 (04:41 -0800)
commitbb2f693560079182132dda91546277ceff8ff981
treebe2c516806025161d95b2382ebd06ba88ecfb7e9
parenteee40e081c09c17613ac6475d1c24405ab029c4d
Upgrader (5.34) - Handle unsavable characters

Overview
--------

In php-mysqli with utf8mb4, the escaping rules do not handle 8-bit
characters (`chr(128)`+). ([Demo](https://gist.github.com/totten/4083741b920113ffc569d40053ce849d))

Here's a situation reported by @agileware-justin which provokes this:

> 1. SMTP credentials (mailing_backend) were saved and had been encrypted using mcrypt, prior to PHP 7.1
> 2. SMTP outbound email was NOT enabled, but the SMTP credentials are in the database
> 3. Active PHP version was PHP 7.3, without mcrypt module
> 4. CiviCRM 5.34 upgrade triggers the database error

Before
------

The behavior can be viewed in two variables:

* Depending on whether `CIVICRM_CRED_KEYS` is set, the upgrader may be
  writing passwords as plain-text or as `^CTK?` tokens.
* Depending on what value is in `$setting['smtpPassword']`, what value is in
  `CIVICRM_SITE_KEY`, and whether `mcrypt` is active, we may or may not get
  8-bit characters when reading the password
  (`CRM_Utils_Crypt::decrypt($setting['smtpPassword'])`).

The fatal combination arises when using plain-text with 8-bit characters.
But other combinations (encrypted tokens and/or 7-bit plain-text) seem
fine.

After
-----

As before, combinations involving encrypted tokens and/or 7-bit plain-text
are fine.

We don't have a head-on soultion for escaping 8-bit plain-text for use with
php-mysqli-utf8mb4.  (Which is insane, right?) But now we manage the
symptoms better:

* If you aren't even using SMTP (like in Justin's example),
  then this is not legit.  We show a warning and simply discard the
  unneeded/corrupt value of `smtpPassword`.

* If you are using SMTP, then this might theoretically be legit.
  (We haven't confirmed, but it seems plausible in other locales.) We show a
  different warning and encourage the sysadmin to setup `CIVICRM_CRED_KEYS`
  (which will enable the more permissive `^CTK?` format.)
CRM/Upgrade/Incremental/php/FiveThirtyFour.php