mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 00:52:33 -04:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
deb4c54ebf | ||
|
|
281f518705 | ||
|
|
a8d9747b12 | ||
|
|
4b15b07b8b | ||
|
|
607a5488d6 | ||
|
|
519b52ccdc | ||
|
|
99fd2e1cb9 | ||
|
|
a69c460ee6 | ||
|
|
71ba6406e3 | ||
|
|
4922acb18a | ||
|
|
a0ea19e51c | ||
|
|
8c4457db8b |
13
CHANGELOG
13
CHANGELOG
@@ -1,3 +1,16 @@
|
||||
Hubzilla 11.2.1 (2026-05-20)
|
||||
- Fix channel creation failing in some situations
|
||||
- Drop payloads with unsafe json-ld keys in LDSignatures::verify() and add tests
|
||||
- Fix App::$profile set for removed channels
|
||||
- Fix MessageFilter breaking when expecting string but array is given
|
||||
- Superblock: fix blocking failed in some setups (sponsored by NLnet NGI0 Commons Fund/Superblock)
|
||||
- Superblock: fix missing import of attribute (sponsored by NLnet NGI0 Commons Fund/Superblock)
|
||||
- Superblock: improved detection of reshares (sponsored by NLnet NGI0 Commons Fund/Superblock)
|
||||
- Cards: fix PHP warning
|
||||
- Gallery: fix PHP warnings and only implement observer related javascript if there actually is an observer
|
||||
- Diaspora: fix missing local namespace for thr_parent
|
||||
|
||||
|
||||
Hubzilla 11.2 (2026-03-26)
|
||||
Features
|
||||
- Introduce parse_webbie() for preparing webbies and URLs for webfinger usage
|
||||
|
||||
@@ -8,9 +8,10 @@ class LDSignatures {
|
||||
|
||||
|
||||
static function verify($data,$pubkey) {
|
||||
$expand_and_check_unsafe = true;
|
||||
|
||||
$ohash = self::hash(self::signable_options($data['signature']));
|
||||
$dhash = self::hash(self::signable_data($data));
|
||||
$ohash = self::hash(self::signable_options($data['signature']), $expand_and_check_unsafe);
|
||||
$dhash = self::hash(self::signable_data($data), $expand_and_check_unsafe);
|
||||
|
||||
$x = Crypto::verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
|
||||
logger('LD-verify: ' . intval($x));
|
||||
@@ -74,11 +75,11 @@ class LDSignatures {
|
||||
return json_encode($newopts,JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
static function hash($obj) {
|
||||
return hash('sha256', self::normalise($obj));
|
||||
static function hash($obj, $expand_and_check_unsafe = false) {
|
||||
return hash('sha256', self::normalise($obj, $expand_and_check_unsafe));
|
||||
}
|
||||
|
||||
static function normalise($data) {
|
||||
static function normalise($data, $expand_and_check_unsafe) {
|
||||
$ret = '';
|
||||
|
||||
if(is_string($data)) {
|
||||
@@ -90,6 +91,15 @@ class LDSignatures {
|
||||
|
||||
jsonld_set_document_loader('jsonld_document_loader');
|
||||
|
||||
if ($expand_and_check_unsafe) {
|
||||
$expanded = jsonld_expand($data);
|
||||
|
||||
if (self::contains_unsafe_keys($expanded)) {
|
||||
logger('contains_unsafe_keys: ' . print_r($data,true));
|
||||
throw new \Exception('json-ld graph modification operation detected');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$ret = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
@@ -132,6 +142,41 @@ class LDSignatures {
|
||||
|
||||
}
|
||||
|
||||
static function contains_unsafe_keys(array|object $data, int $depth = 0): bool
|
||||
{
|
||||
if ($depth > 64) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$unsafe_keys = ['@graph', '@included', '@reverse'];
|
||||
|
||||
if (is_object($data)) {
|
||||
$data = (array) $data;
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $key => $value) {
|
||||
//
|
||||
// We can't use `in_array` since the keys may contain more than
|
||||
// just the keyword after expansion, typically "_:@included"
|
||||
// for an unnamed node with the "@included" key.
|
||||
//
|
||||
// So we use `array_filter` with a callback instead:
|
||||
$matches = array_filter($unsafe_keys, fn ($k) => strpos($key, $k) !== false);
|
||||
|
||||
if (!empty($matches)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_array($value) || is_object($value)) {
|
||||
if (self::contains_unsafe_keys($value, $depth + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ class MessageFilter
|
||||
|
||||
if (preg_match('/(.*?)\s~=\s(.*?)$/', $s, $matches)) {
|
||||
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
|
||||
if (stripos($x, trim($matches[2])) !== false) {
|
||||
if (is_string($x) && stripos($x, trim($matches[2])) !== false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -33,7 +33,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
// first name
|
||||
if(strpos($x,' '))
|
||||
$test[] = legal_webbie(substr($x,0,strpos($x,' ')));
|
||||
if($test[0]) {
|
||||
if (!empty($test[0])) {
|
||||
// first name plus first initial of last
|
||||
$test[] = ((strpos($x,' ')) ? $test[0] . legal_webbie(trim(substr($x,strpos($x,' '),2))) : '');
|
||||
// first name plus random number
|
||||
@@ -69,7 +69,7 @@ class New_channel extends \Zotlabs\Web\Controller {
|
||||
// first name
|
||||
if(strpos($x,' '))
|
||||
$test[] = legal_webbie(substr($x,0,strpos($x,' ')));
|
||||
if($test[0]) {
|
||||
if (!empty($test[0])) {
|
||||
// first name plus first initial of last
|
||||
$test[] = ((strpos($x,' ')) ? $test[0] . legal_webbie(trim(substr($x,strpos($x,' '),2))) : '');
|
||||
// first name plus random number
|
||||
|
||||
@@ -60,26 +60,16 @@ class Profile extends Controller {
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/atom+xml',
|
||||
'title' => t('Posts and comments'),
|
||||
'href' => z_root() . '/feed/' . $which
|
||||
'href' => z_root() . '/feed/' . $which . '?top=0'
|
||||
]);
|
||||
|
||||
head_add_link([
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/atom+xml',
|
||||
'title' => t('Only posts'),
|
||||
'href' => z_root() . '/feed/' . $which . '?f=&top=1'
|
||||
'href' => z_root() . '/feed/' . $which . '?top=1'
|
||||
]);
|
||||
|
||||
|
||||
if (!$profile) {
|
||||
$x = q("select channel_id as profile_uid from channel where channel_address = '%s' limit 1",
|
||||
dbesc(argv(1))
|
||||
);
|
||||
if ($x) {
|
||||
App::$profile = $x[0];
|
||||
}
|
||||
}
|
||||
|
||||
profile_load($which, $profile);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,15 +8,18 @@
|
||||
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use App;
|
||||
|
||||
class Fullprofile {
|
||||
|
||||
function widget($arr) {
|
||||
|
||||
if(!(isset(\App::$profile['profile_uid']) && \App::$profile['profile_uid']))
|
||||
if (empty(App::$profile['profile_uid'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$block = observer_prohibited();
|
||||
|
||||
return profile_sidebar(\App::$profile, $block, true, true);
|
||||
return profile_sidebar(App::$profile, $block, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use App;
|
||||
|
||||
class Profile {
|
||||
function widget($args) {
|
||||
if(!isset(App::$profile['profile_uid'])) {
|
||||
if (empty(App::$profile['profile_uid'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
2
boot.php
2
boot.php
@@ -70,7 +70,7 @@ require_once('include/security.php');
|
||||
|
||||
|
||||
define('PLATFORM_NAME', 'hubzilla');
|
||||
define('STD_VERSION', '11.2');
|
||||
define('STD_VERSION', '11.2.1');
|
||||
define('ZOT_REVISION', '6.0');
|
||||
|
||||
define('DB_UPDATE_VERSION', 1265);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "@type",
|
||||
"proof": {
|
||||
"@id": "https://w3id.org/security#proof",
|
||||
"@type": "@id",
|
||||
"@type": "@id"
|
||||
},
|
||||
"DataIntegrityProof": {
|
||||
"@id": "https://w3id.org/security#DataIntegrityProof"
|
||||
@@ -35,19 +35,19 @@
|
||||
},
|
||||
"assertionMethod": {
|
||||
"@id": "https://w3id.org/security#assertionMethod",
|
||||
"@type": "@id",
|
||||
"@type": "@id"
|
||||
},
|
||||
"authentication": {
|
||||
"@id": "https://w3id.org/security#authenticationMethod",
|
||||
"@type": "@id",
|
||||
"@type": "@id"
|
||||
},
|
||||
"capabilityInvocation": {
|
||||
"@id": "https://w3id.org/security#capabilityInvocationMethod",
|
||||
"@type": "@id",
|
||||
"@type": "@id"
|
||||
},
|
||||
"capabilityDelegation": {
|
||||
"@id": "https://w3id.org/security#capabilityDelegationMethod",
|
||||
"@type": "@id",
|
||||
"@type": "@id"
|
||||
},
|
||||
"keyAgreement": {
|
||||
"@id": "https://w3id.org/security#keyAgreementMethod",
|
||||
|
||||
106
tests/unit/Lib/LDSignaturesTest.php
Normal file
106
tests/unit/Lib/LDSignaturesTest.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit\Lib;
|
||||
|
||||
use Zotlabs\Lib\Crypto;
|
||||
use Zotlabs\Lib\LDSignatures;
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
|
||||
class LDSignaturesTest extends UnitTestCase {
|
||||
|
||||
public function testVerifyLDSignature(): void {
|
||||
$channel = [
|
||||
'channel_address' => 'test',
|
||||
'channel_prvkey' => <<<'EOD'
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvUNHsxNNL8egKxBl
|
||||
rQdhdKz7N1DfJ8yMAYGPizta9uZ9uoe2qbgYpFPP41gbWvCJqDptmRCWXVZnmH6E
|
||||
Pe6pLwIDAQABAkBtvgJoKsv55YXREqvyPbJbxiXQuFr9J9US1n5WXG9tc8+S1SB3
|
||||
Azh7GtORAVnFkba5Ruj/Qij+CLe1ggCkwu0pAiEA41HXbZzQbb4hOxB9mkVvlMYj
|
||||
r8UqOEtbvKEpnCUAeLUCIQDVJD8BnuCLKRxdtJRbWjwSe++/czwCTVTFv+XIyXX8
|
||||
0wIgMx6qhZnoPWWub2vr8w9+YkSUreh28CXyQV80zkp76qkCIQCA1X34Ps6/j0QE
|
||||
KCkc5vg0vBF5CfCV+6RoO8xrh8r33QIhANFLEX+THSmi6s+/d3rUHRqj7cTzJdHh
|
||||
31v2ixfbFhB6
|
||||
-----END PRIVATE KEY-----
|
||||
EOD,
|
||||
'channel_pubkey' => <<<'EOD'
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL1DR7MTTS/HoCsQZa0HYXSs+zdQ3yfM
|
||||
jAGBj4s7WvbmfbqHtqm4GKRTz+NYG1rwiag6bZkQll1WZ5h+hD3uqS8CAwEAAQ==
|
||||
-----END PUBLIC KEY-----
|
||||
EOD,
|
||||
];
|
||||
|
||||
$activity = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'type' => 'Like',
|
||||
'actor' => 'https://hubzilla.test/channel/test',
|
||||
'to' => [
|
||||
'https://hatchat.example/sarah/',
|
||||
'https://example.com/peeps/john/',
|
||||
],
|
||||
'object' => [
|
||||
'@context' => ['@language' => 'en'],
|
||||
'id' => 'https://example.org/~alice/note/23',
|
||||
'type' => 'Note',
|
||||
'attributedTo' => 'https://example.org/~alice',
|
||||
'content' => "I'm a goat",
|
||||
],
|
||||
'signature' => [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'type' => 'RsaSignature2017',
|
||||
'nonce' => 'e3158dce627da99138d238805d2f129db05bd65efce0f712de494565c852f7fc',
|
||||
'created' => '2026-05-01T09:22:05Z',
|
||||
'creator' => 'https://hubzilla.test/channel/test',
|
||||
'signatureValue' =>
|
||||
'iFo/j+sG4h7zDiVis8FMOaJvw7ZanbsPdUrS5WTUkcMzL/dg3xPPpt9pKREhVx73ne6y6tIjzq6TWzWEpYvUFg=='
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertTrue(LDSignatures::verify($activity, $channel['channel_pubkey']));
|
||||
|
||||
|
||||
// Verify that the signature is independent of the order
|
||||
// of the fields
|
||||
$activity_2 = [
|
||||
'type' => 'Like',
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'actor' => 'https://hubzilla.test/channel/test',
|
||||
'to' => [
|
||||
'https://example.com/peeps/john/',
|
||||
'https://hatchat.example/sarah/',
|
||||
],
|
||||
'signature' => [
|
||||
'nonce' => 'e3158dce627da99138d238805d2f129db05bd65efce0f712de494565c852f7fc',
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'created' => '2026-05-01T09:22:05Z',
|
||||
'type' => 'RsaSignature2017',
|
||||
'creator' => 'https://hubzilla.test/channel/test',
|
||||
'signatureValue' =>
|
||||
'iFo/j+sG4h7zDiVis8FMOaJvw7ZanbsPdUrS5WTUkcMzL/dg3xPPpt9pKREhVx73ne6y6tIjzq6TWzWEpYvUFg=='
|
||||
],
|
||||
'object' => [
|
||||
'@context' => ['@language' => 'en'],
|
||||
'type' => 'Note',
|
||||
'attributedTo' => 'https://example.org/~alice',
|
||||
'id' => 'https://example.org/~alice/note/23',
|
||||
'content' => "I'm a goat",
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertFalse($activity == $activity_2);
|
||||
$this->assertTrue(LDSignatures::verify($activity_2, $channel['channel_pubkey']));
|
||||
}
|
||||
}
|
||||
@@ -118,37 +118,20 @@ channel:
|
||||
channel_startpage: ""
|
||||
channel_pubkey: |
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAn2ads2RKygqTbN0kxuGI
|
||||
3Vuh/1SSvHls2cYMXZJpwqix5+y2/zqqzAVUayMCPt1ZHLfc+uG0Z97+XmWNuuIo
|
||||
RCBB5Os29NKo4+K66prYlfBFeuvji9tV1zGwBMYMC2RabITIjH9yazE+Tox54iV+
|
||||
kw/IYPsnv4vPIcuC8dnvZ0v7/Kkhm6Hp0ZrGRNKccHuinJeiuhvfXXG3xrrBrMY7
|
||||
iw7I3i2hvw/BSFdJ1RnuMGlr2W3qcZQvlqCWIGAzEpmXom9bwBKo/ZZ2MSJCgEVY
|
||||
KKPqjLs/7IKRzlzUFIuk8Uibrhoxmc0NaqIeQOUtyelFdc/P3p2fEjwJd7sr8dzo
|
||||
NFVgUMHGiqu0C5fZ90KnfLNrXJcMb4VjsvGFyIDt0AZY5w4rjoKmjlB/p4/CRfyz
|
||||
qFnp2ZK4eRPqurmGwnSArsjPLMhWjlc7NRXtQ1nyMNAEi4RRhlJyjmvJIRrdeVu2
|
||||
Nq6ZknBq0SeDlH/3uRfNPwHxqgDFNTCgsg4/Lgj2au1XbaEBlgRq3PDAh4a3H+fO
|
||||
iGKinJy2/p9TGvrKTcO3mremHbuVg41G6FjxvzuZKx3P7ssN4KBlCJ9L/tJX5RDn
|
||||
4m5u4ZdaPZBXxjgXj24SDLETaz+K0DxwtjGQ7kTpC0zv6hLcEGxS2220cX7Msgih
|
||||
pWX+ItWfet/uLkmfyCpaxt0CAwEAAQ==
|
||||
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL1DR7MTTS/HoCsQZa0HYXSs+zdQ3yfM
|
||||
jAGBj4s7WvbmfbqHtqm4GKRTz+NYG1rwiag6bZkQll1WZ5h+hD3uqS8CAwEAAQ==
|
||||
-----END PUBLIC KEY-----
|
||||
channel_prvkey: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCfZp2zZErKCpNs
|
||||
3STG4YjdW6H/VJK8eWzZxgxdkmnCqLHn7Lb/OqrMBVRrIwI+3Vkct9z64bRn3v5e
|
||||
ZY264ihEIEHk6zb00qjj4rrqmtiV8EV66+OL21XXMbAExgwLZFpshMiMf3JrMT5O
|
||||
jHniJX6TD8hg+ye/i88hy4Lx2e9nS/v8qSGboenRmsZE0pxwe6Kcl6K6G99dcbfG
|
||||
usGsxjuLDsjeLaG/D8FIV0nVGe4waWvZbepxlC+WoJYgYDMSmZeib1vAEqj9lnYx
|
||||
IkKARVgoo+qMuz/sgpHOXNQUi6TxSJuuGjGZzQ1qoh5A5S3J6UV1z8/enZ8SPAl3
|
||||
uyvx3Og0VWBQwcaKq7QLl9n3Qqd8s2tclwxvhWOy8YXIgO3QBljnDiuOgqaOUH+n
|
||||
j8JF/LOoWenZkrh5E+q6uYbCdICuyM8syFaOVzs1Fe1DWfIw0ASLhFGGUnKOa8kh
|
||||
Gt15W7Y2rpmScGrRJ4OUf/e5F80/AfGqAMU1MKCyDj8uCPZq7VdtoQGWBGrc8MCH
|
||||
hrcf586IYqKcnLb+n1Ma+spNw7eat6Ydu5WDjUboWPG/O5krHc/uyw3goGUIn0v+
|
||||
0lflEOfibm7hl1o9kFfGOBePbhIMsRNrP4rQPHC2MZDuROkLTO/qEtwQbFLbbbRx
|
||||
fsyyCKGlZf4i1Z963+4uSZ/IKlrG3QIDAQABAoICAAGXQ9gpllXVYgV1CzwBPhKI
|
||||
KqynyAN3CnHS+EZ1IraVZJnTYuaBtqOCIxv4Sw+xua+1GxDARhgU9utzboUbYuT+
|
||||
gGyGjMjH6HUbyxtHz9pmkz7ykesQVZc9UPZ/O9lfl0fG0dHrJ2BwAEvxkCQvFR1m
|
||||
doIXR50xtJpvqPR9JRaeFhtTsc5B667n8Ut4YaTSwGZOh3UoODllxucwxSQ9DJTq
|
||||
9nDB5P/JP7fXMoQHYKPy4
|
||||
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvUNHsxNNL8egKxBl
|
||||
rQdhdKz7N1DfJ8yMAYGPizta9uZ9uoe2qbgYpFPP41gbWvCJqDptmRCWXVZnmH6E
|
||||
Pe6pLwIDAQABAkBtvgJoKsv55YXREqvyPbJbxiXQuFr9J9US1n5WXG9tc8+S1SB3
|
||||
Azh7GtORAVnFkba5Ruj/Qij+CLe1ggCkwu0pAiEA41HXbZzQbb4hOxB9mkVvlMYj
|
||||
r8UqOEtbvKEpnCUAeLUCIQDVJD8BnuCLKRxdtJRbWjwSe++/czwCTVTFv+XIyXX8
|
||||
0wIgMx6qhZnoPWWub2vr8w9+YkSUreh28CXyQV80zkp76qkCIQCA1X34Ps6/j0QE
|
||||
KCkc5vg0vBF5CfCV+6RoO8xrh8r33QIhANFLEX+THSmi6s+/d3rUHRqj7cTzJdHh
|
||||
31v2ixfbFhB6
|
||||
-----END PRIVATE KEY-----
|
||||
channel_epubkey: "cBYhT+C+ZzzXDLlZh1hEsWzz5HI06TwW6o8HgfyLlFo"
|
||||
channel_eprvkey: "/ClTxXKn7Lts+O6CgqJ2cCe0FlKpNSZfrBLPaB1Bq2twFiFP4L5nPNcMuVmHWESxbPPkcjTpPBbqjweB/IuUWg"
|
||||
channel_notifyflags: 65535
|
||||
|
||||
Reference in New Issue
Block a user