Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

   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  #[AllowDynamicProperties]
  30  class Google_Signer_P12 extends Google_Signer_Abstract
  31  {
  32    // OpenSSL private key resource
  33    private $privateKey;
  34  
  35    // Creates a new signer from a .p12 file.
  36    public function __construct($p12, $password)
  37    {
  38      if (!function_exists('openssl_x509_read')) {
  39        throw new Google_Exception(
  40            'The Google PHP API library needs the openssl PHP extension'
  41        );
  42      }
  43  
  44      // If the private key is provided directly, then this isn't in the p12
  45      // format. Different versions of openssl support different p12 formats
  46      // and the key from google wasn't being accepted by the version available
  47      // at the time.
  48      if (!$password && strpos($p12, "-----BEGIN RSA PRIVATE KEY-----") !== false) {
  49        $this->privateKey = openssl_pkey_get_private($p12);
  50      } elseif ($password === 'notasecret' && strpos($p12, "-----BEGIN PRIVATE KEY-----") !== false) {
  51        $this->privateKey = openssl_pkey_get_private($p12);
  52      } else {
  53        // This throws on error
  54        $certs = array();
  55        if (!openssl_pkcs12_read($p12, $certs, $password)) {
  56          throw new Google_Auth_Exception(
  57              "Unable to parse the p12 file.  " .
  58              "Is this a .p12 file?  Is the password correct?  OpenSSL error: " .
  59              openssl_error_string()
  60          );
  61        }
  62        // TODO(beaton): is this part of the contract for the openssl_pkcs12_read
  63        // method?  What happens if there are multiple private keys?  Do we care?
  64        if (!array_key_exists("pkey", $certs) || !$certs["pkey"]) {
  65          throw new Google_Auth_Exception("No private key found in p12 file.");
  66        }
  67        $this->privateKey = openssl_pkey_get_private($certs['pkey']);
  68      }
  69  
  70      if (!$this->privateKey) {
  71        throw new Google_Auth_Exception("Unable to load private key");
  72      }
  73    }
  74  
  75    public function __destruct()
  76    {
  77      if ($this->privateKey) {
  78        // TODO: Remove this block once PHP 8.0 becomes required.
  79        if (PHP_MAJOR_VERSION < 8) {
  80          openssl_pkey_free($this->privateKey);
  81        }
  82      }
  83    }
  84  
  85    public function sign($data)
  86    {
  87      if (version_compare(PHP_VERSION, '5.3.0') < 0) {
  88        throw new Google_Auth_Exception(
  89            "PHP 5.3.0 or higher is required to use service accounts."
  90        );
  91      }
  92      $hash = defined("OPENSSL_ALGO_SHA256") ? OPENSSL_ALGO_SHA256 : "sha256";
  93      if (!openssl_sign($data, $signature, $this->privateKey, $hash)) {
  94        throw new Google_Auth_Exception("Unable to sign data");
  95      }
  96      return $signature;
  97    }
  98  }