Problem/Motivation

Authorization fails because of Notice: unserialize(): Error at offset 12341 of 973195 bytes in Drupal\drd\Crypt\Method\OpenSSL->decrypt() (line 187 of /modules/contrib/drd/src/Crypt/Method/OpenSSL.php)

Steps to reproduce

This happens with php 5.6 on the cores. I tried adding a D6 and D7 core. Both failed with the same error.
DRD 4 was installed with D9, php 7.3.26.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Comments

tcorneli created an issue. See original summary.

jurgenhaas’s picture

Version: 4.0.0 » 4.0.x-dev

That's a difficult one. Unfortunately I can't reproduce so we need to speculate and probably we need you to do some debugging here.

As a first possibility, are there probably incompatible OpenSSL versions on the DRD and the remote hosts? Never heard of anything like that, but we should make sure it's not that. Please go to /admin/reports/status/php#module_openssl on all involved Drupal sites and see what version and other detail information you can find.

If it's not that, we need to analyse what response we're getting from the remote host after authorization. For that, please go to line 180 of /modules/contrib/drd/src/Crypt/Method/OpenSSL.php with an editor and insert the following block right after line 180:

    file_put_contents('/tmp/test.log', openssl_decrypt(
      $body,
      $this->cipher,
      $this->getPassword(),
      OPENSSL_RAW_DATA,
      $this->iv
    ));

Adjust the filename /tmp/test.log to something that can be written to on you DRD host and then try to reproduce this step and see what's in that file. It looks like that content cannot be unserialized for some reason.

jurgenhaas’s picture

To append to the log file, rather use this code:

$fp = fopen('/tmp/test.log', 'a');
fwrite($fp, openssl_decrypt(
      $body,
      $this->cipher,
      $this->getPassword(),
      OPENSSL_RAW_DATA,
      $this->iv
    ));  
fclose($fp);  

  • jurgenhaas committed 7995212 on 4.0.x
    Issue #3195442 by jurgenhaas: Notice: unserialize(): Error at offset in...
steveoriol’s picture

In fact, after having exchanged with jurgenhaas on another channel, we found that some D6 and D7 site returned to the DRD site a serialized string with unauthorized characters like r:xxx.
It is characters can disappear if the configuration of the target site is modified, for example the configuration of the language of the site, and others ...

jurgenhaas rewrote the "decrypt" function of OpenSSL.php, and now it allows modifying the "r: xxx" if it causes the deserialization of the chain to fail.

  public function decrypt($body, $iv) {
    $this->iv = $iv;
    $data = openssl_decrypt(
      $body,
      $this->cipher,
      $this->getPassword(),
      OPENSSL_RAW_DATA,
      $this->iv
    );
    /** @noinspection UnserializeExploitsInspection */
    $result = unserialize($data);
    if ($result === FALSE) {
      $data = str_replace([';r:', ';R:'], ';i:', $data);
      /** @noinspection UnserializeExploitsInspection */
      $result = unserialize($data);
    }
    return $result;
  }

Since then, I no longer have any problem connecting sites :-)
Well done jurgenhaas!

jurgenhaas’s picture

Status: Active » Fixed

Thank you so much @steveoriol for working through this strange bug and helping me to identify the real issue with the invalid parts in PHP serialization. We still don't know why this is happening on older Drupal versions, but our workaround does work and should harm anything.

Pushed the code to the project and will push version 4.0.3 this afternoon.

@tcorneli please give that new version a try too and let us know if your issue is resolved by it as well.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

tcorneli’s picture

Hi, I revisited this issue and I can confirm it was resolved with the latest update.
Thanks guys!