Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  /*
   3   * Copyright 2011 Google Inc.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   */
  17  
  18  if (!class_exists('Google_Client')) {
  19    require_once dirname(__FILE__) . '/../autoload.php';
  20  }
  21  
  22  /**
  23   * Signs data.
  24   *
  25   * Only used for testing.
  26   *
  27   * @author Brian Eaton <beaton@google.com>
  28   */
  29  class Google_Signer_P12 extends Google_Signer_Abstract
  30  {
  31    // OpenSSL private key resource
  32    private $privateKey;
  33  
  34    // Creates a new signer from a .p12 file.
  35    public function __construct($p12, $password)
  36    {
  37      if (!function_exists('openssl_x509_read')) {
  38        throw new Google_Exception(
  39            'The Google PHP API library needs the openssl PHP extension'
  40        );
  41      }
  42  
  43      // If the private key is provided directly, then this isn't in the p12
  44      // format. Different versions of openssl support different p12 formats
  45      // and the key from google wasn't being accepted by the version available
  46      // at the time.
  47      if (!$password && strpos($p12, "-----BEGIN RSA PRIVATE KEY-----") !== false) {
  48        $this->privateKey = openssl_pkey_get_private($p12);
  49      } elseif ($password === 'notasecret' && strpos($p12, "-----BEGIN PRIVATE KEY-----") !== false) {
  50        $this->privateKey = openssl_pkey_get_private($p12);
  51      } else {
  52        // This throws on error
  53        $certs = array();
  54        if (!openssl_pkcs12_read($p12, $certs, $password)) {
  55          throw new Google_Auth_Exception(
  56              "Unable to parse the p12 file.  " .
  57              "Is this a .p12 file?  Is the password correct?  OpenSSL error: " .
  58              openssl_error_string()
  59          );
  60        }
  61        // TODO(beaton): is this part of the contract for the openssl_pkcs12_read
  62        // method?  What happens if there are multiple private keys?  Do we care?
  63        if (!array_key_exists("pkey", $certs) || !$certs["pkey"]) {
  64          throw new Google_Auth_Exception("No private key found in p12 file.");
  65        }
  66        $this->privateKey = openssl_pkey_get_private($certs['pkey']);
  67      }
  68  
  69      if (!$this->privateKey) {
  70        throw new Google_Auth_Exception("Unable to load private key");
  71      }
  72    }
  73  
  74    public function __destruct()
  75    {
  76      if ($this->privateKey) {
  77        // TODO: Remove this block once PHP 8.0 becomes required.
  78        if (PHP_MAJOR_VERSION < 8) {
  79          openssl_pkey_free($this->privateKey);
  80        }
  81      }
  82    }
  83  
  84    public function sign($data)
  85    {
  86      if (version_compare(PHP_VERSION, '5.3.0') < 0) {
  87        throw new Google_Auth_Exception(
  88            "PHP 5.3.0 or higher is required to use service accounts."
  89        );
  90      }
  91      $hash = defined("OPENSSL_ALGO_SHA256") ? OPENSSL_ALGO_SHA256 : "sha256";
  92      if (!openssl_sign($data, $signature, $this->privateKey, $hash)) {
  93        throw new Google_Auth_Exception("Unable to sign data");
  94      }
  95      return $signature;
  96    }
  97  }