summaryrefslogtreecommitdiff
diff options
authorDavid Prévot <taffit@debian.org>2026-06-16 00:13:58 +0200
committergit-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com>2026-06-16 04:37:31 +0000
commit643c65f662c4d56ae92f886cdd35f7cd9f1886c6 (patch)
tree992fe394b0cd159704182cd82c4a42b22cef3caa
parent04b06a5c587fb085b7ac7ebabf86a717cfb2dd70 (diff)
Imported using git-ubuntu import.
Notes
Notes: [ terrafrost ] * CHANGELOG: add CVE * ASN1: speed up OID calculation * X509: add setURLFetchCallback() method * CHANGELOG: add new release [ David Prévot ] * Update CVE ID in previous changelog entry
-rw-r--r--CHANGELOG.md13
-rw-r--r--README.md11
-rw-r--r--debian/changelog15
-rw-r--r--phpseclib/File/ASN1.php22
-rw-r--r--phpseclib/File/X509.php71
5 files changed, 117 insertions, 15 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7074aea..82a8ec8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,13 @@
# Changelog
+## 2.0.55 - 2026-06-14
+
+- X509: add setURLFetchCallback() method
+- ASN1: speed up OID calculations
+
## 2.0.54 - 2026-04-27
-- ASN1: more stringent OID length limits
+- ASN1: more stringent OID length limits (CVE-2026-44167)
## 2.0.53 - 2026-04-09
@@ -416,9 +421,13 @@
- Classes were renamed and namespaced ([#243](https://github.com/phpseclib/phpseclib/issues/243))
- The use of an autoloader is now required (e.g. Composer)
+## 1.0.30 - 2026-06-14
+
+- X509: add setURLFetchCallback() method
+
## 1.0.29 - 2026-04-27
-- ASN1: more stringent OID length limits
+- ASN1: more stringent OID length limits (CVE-2026-44167)
## 1.0.28 - 2026-04-09
diff --git a/README.md b/README.md
index 967546c..c047ea5 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,17 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
* Unstable API
* Do not use in production
+### 4.0
+
+* Expected Release Date: September 2026
+* Long term support (LTS) release
+* X509 split into separate X509, CRL, CSR and SPKAC classes
+* PFX and CMS classes added
+* All ASN1 classes are lazy loaded by default
+* Minimum PHP version: 8.1.0
+* PSR-4 autoloading with namespace rooted at `\phpseclib4`
+* Install via Composer: `composer require phpseclib/phpseclib:4.0.x-dev`
+
### 3.0
* Long term support (LTS) release
diff --git a/debian/changelog b/debian/changelog
index b3053a3..6eeaea0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,21 @@
+php-phpseclib (2.0.55-1) unstable; urgency=medium
+
+ [ terrafrost ]
+ * CHANGELOG: add CVE
+ * ASN1: speed up OID calculation
+ * X509: add setURLFetchCallback() method
+ * CHANGELOG: add new release
+
+ [ David Prévot ]
+ * Update CVE ID in previous changelog entry
+
+ -- David Prévot <taffit@debian.org> Tue, 16 Jun 2026 00:13:58 +0200
+
php-phpseclib (2.0.54-1) unstable; urgency=medium
[ terrafrost ]
* ASN1: reduce length of supported OIDs from 4096 bytes to 128 bytes
- [CVE-2024-27355] (GHSA-3qpq-r242-jqj7)
+ [CVE-2026-44167] (GHSA-3qpq-r242-jqj7)
* CHANGELOG: add new entry
[ David Prévot ]
diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php
index 704826c..afe714d 100644
--- a/phpseclib/File/ASN1.php
+++ b/phpseclib/File/ASN1.php
@@ -1172,6 +1172,10 @@ class ASN1
*/
function _decodeOID($content)
{
+ if (!defined('PHP_INT_SIZE')) {
+ define('PHP_INT_SIZE', 4);
+ }
+
static $eighty;
if (!$eighty) {
$eighty = new BigInteger(80);
@@ -1191,13 +1195,21 @@ class ASN1
}
$n = new BigInteger();
+ $subn = $numBytes = 0;
while ($pos < $len) {
$temp = ord($content[$pos++]);
- $n = $n->bitwise_leftShift(7);
- $n = $n->bitwise_or(new BigInteger($temp & 0x7F));
- if (~$temp & 0x80) {
- $oid[] = $n;
- $n = new BigInteger();
+ $subn <<= 7;
+ $subn |= ($temp & 0x7F);
+ $numBytes++;
+ $endByte = ~$temp & 0x80;
+ if ($numBytes === PHP_INT_SIZE || $endByte) {
+ $n = $n->bitwise_leftShift($numBytes * 7);
+ $n = $n->bitwise_or(new BigInteger($subn));
+ $subn = $numBytes = 0;
+ if ($endByte) {
+ $oid[] = $n;
+ $n = new BigInteger();
+ }
}
}
$part1 = array_shift($oid);
diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php
index 4991f85..cdc112f 100644
--- a/phpseclib/File/X509.php
+++ b/phpseclib/File/X509.php
@@ -323,6 +323,14 @@ class X509
static $disable_url_fetch = false;
/**
+ * URL fetch callback
+ *
+ * @var string|array|null
+ * @access private
+ */
+ static $urlFetchCallback = null;
+
+ /**
* Default Constructor.
*
* @return \phpseclib\File\X509
@@ -2152,6 +2160,10 @@ class X509
/**
* Fetches a URL
*
+ * If a fetch callback is set via setURLFetchCallback(), the host is resolved
+ * once and the connection is pinned to that IP (the callback judges the
+ * resolved IP, preventing DNS-rebinding bypass).
+ *
* @param string $url
* @access private
* @return bool|string
@@ -2163,25 +2175,58 @@ class X509
}
$parts = parse_url($url);
+ if ($parts === false || !isset($parts['scheme']) || !isset($parts['host'])) {
+ return false;
+ }
+ $host = $parts['host'];
+ $port = isset($parts['port']) ? $parts['port'] : 80;
+
+ if (isset(self::$urlFetchCallback)) {
+ if (filter_var($host, FILTER_VALIDATE_IP)) {
+ $ip = $host;
+ // unwrap IPv4-mapped IPv6 so the callback judges the real v4 address
+ if (preg_match('/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $ip, $m)) {
+ $ip = $m[1];
+ }
+ } else {
+ $records = dns_get_record($host, DNS_A | DNS_AAAA);
+ if (!$records) {
+ return false;
+ }
+ if (isset($records[0]['ip'])) {
+ $ip = $records[0]['ip'];
+ } elseif (isset($records[0]['ipv6'])) {
+ $ip = $records[0]['ipv6'];
+ } else {
+ return false;
+ }
+ }
+ if (!call_user_func(self::$urlFetchCallback, $host, $ip, $port, $parts['scheme'])) {
+ return false;
+ }
+ $target = strpos($ip, ':') !== false ? "[$ip]" : $ip;
+ } else {
+ $target = $host;
+ }
+
$data = '';
switch ($parts['scheme']) {
case 'http':
- $fsock = @fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80);
+ $fsock = @fsockopen($target, $port);
if (!$fsock) {
return false;
}
- $path = $parts['path'];
+ $path = isset($parts['path']) ? $parts['path'] : '/';
if (isset($parts['query'])) {
$path.= '?' . $parts['query'];
}
fputs($fsock, "GET $path HTTP/1.0\r\n");
- fputs($fsock, "Host: $parts[host]\r\n\r\n");
+ fputs($fsock, "Host: $host\r\n\r\n");
$line = fgets($fsock, 1024);
- if (strlen($line) < 3) {
+ if ($line === false || strlen($line) < 3) {
return false;
}
- preg_match('#HTTP/1.\d (\d{3})#', $line, $temp);
- if ($temp[1] != '200') {
+ if (!preg_match('#HTTP/1.\d (\d{3})#', $line, $temp) || $temp[1] != '200') {
return false;
}
@@ -2200,7 +2245,8 @@ class X509
break;
//case 'ftp':
//case 'ldap':
- //default:
+ default:
+ return false;
}
return $data;
@@ -5123,4 +5169,15 @@ class X509
}
return isset($reverseMap[$name]) ? $reverseMap[$name] : $name;
}
+
+ /**
+ * Returns the OID corresponding to a name
+ *
+ * @access public
+ * @param array|string|null $callback
+ */
+ static function setURLFetchCallback($callback)
+ {
+ self::$urlFetchCallback = $callback;
+ }
}