WordPress.org

Make WordPress Core

Ticket #39309: 39309-upgrader-sign.patch

File 39309-upgrader-sign.patch, 3.6 KB (added by paragoninitiativeenterprises, 20 months ago)
  • wp-admin/includes/class-wp-upgrader.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    140140                $this->generic_strings();
    141141        }
    142142
     143    /**
     144     * Return an array of trusted Ed25519 public keys
     145     *
     146     * @return array<int, string>
     147     */
     148        public function getPublicKeys()
     149    {
     150        return array(
     151            ParagonIE_Sodium_Compat::hex2bin( '4d6236cc44829b2f96a26d905aec92162077ef5aa7e0a4e2a6d251258dc83bd1' )
     152        );
     153    }
     154
    143155        /**
    144156         * Add the generic strings to WP_Upgrader::$strings.
    145157         *
     
    275287
    276288                $this->skin->feedback( 'downloading_package', $package );
    277289
    278                 $download_file = download_url( $package );
     290                $download_file = download_url( $package, 300, self::getPublicKeys() );
    279291
    280292                if ( is_wp_error( $download_file ) ) {
    281293                        return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() );
  • wp-admin/includes/file.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    965965 *
    966966 * @param string $url the URL of the file to download
    967967 * @param int $timeout The timeout for the request to download the file default 300 seconds
     968 * @param array<int, string> $publicKeys An array of strings containing Ed25519 public keys
    968969 * @return mixed WP_Error on failure, string Filename on success.
    969970 */
    970 function download_url( $url, $timeout = 300 ) {
     971function download_url( $url, $timeout = 300, $publicKeys = array() ) {
    971972        //WARNING: The file is not automatically deleted, The script must unlink() the file.
    972973        if ( ! $url ) {
    973974                return new WP_Error( 'http_no_url', __( 'Invalid URL Provided.' ) );
     
    10071008                }
    10081009        }
    10091010
     1011    $content_ed25519_hex = wp_remote_retrieve_header( $response, 'content-ed25519' );
     1012    $ed25519_check = verify_file_ed25519( $tmpfname, $publicKeys, $content_ed25519_hex );
     1013    if ( is_wp_error( $ed25519_check ) ) {
     1014        unlink( $tmpfname );
     1015        return $ed25519_check;
     1016    }
     1017
    10101018        return $tmpfname;
    10111019}
    10121020
     
    18961904        </div>
    18971905        <?php
    18981906}
     1907
     1908/**
     1909 * Verifies the Ed25519 signature of a file for a given set of public keys.
     1910 *
     1911 * @since 5.0 (presumably)
     1912 *
     1913 * @param string $filename
     1914 * @param array<int, string> $publicKeys
     1915 * @param string $signature
     1916 * @return bool|object WP_Error on failure, true on success
     1917 */
     1918function verify_file_ed25519( $filename, $publicKeys, $signature ) {
     1919    if ( ParagonIE_Sodium_Core_Util::strlen( $signature ) === ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES * 2) {
     1920        $signature = ParagonIE_Sodium_Compat::hex2bin($signature);
     1921    }
     1922    $verified = false;
     1923    foreach ($publicKeys as $public_key) {
     1924        if (ParagonIE_Sodium_Core_Util::strlen( $public_key ) === ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES * 2) {
     1925            $public_key = ParagonIE_Sodium_Compat::hex2bin( $public_key );
     1926        }
     1927        $verified = $verified || ParagonIE_Sodium_File::verify( $signature, $filename, $public_key );
     1928    }
     1929    if ( $verified ) {
     1930        return true;
     1931    }
     1932    return new WP_Error( 'ed25519_mismatch', sprintf( __( 'The signature of the file (%1$s) is not valid for any of the trusted public keys.' ), bin2hex( $signature ) ) );
     1933}