aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Lib
diff options
context:
space:
mode:
authorMax Kostikov <max@kostikov.co>2021-02-20 13:39:54 +0000
committerMax Kostikov <max@kostikov.co>2021-02-20 13:39:54 +0000
commitcc5571687971ddcc097abb5e5c57689005d5b070 (patch)
tree1b2ed0f46b307f09d109350f777438fd04742905 /Zotlabs/Lib
parente1d622c49f95aec51e5c1bd521dcd6fe2a9a5372 (diff)
parentddad4f604b56656086b32992ef98709be2568a37 (diff)
downloadvolse-hubzilla-cc5571687971ddcc097abb5e5c57689005d5b070.tar.gz
volse-hubzilla-cc5571687971ddcc097abb5e5c57689005d5b070.tar.bz2
volse-hubzilla-cc5571687971ddcc097abb5e5c57689005d5b070.zip
Merge branch 'dev' into 'dev'
Dev sync See merge request kostikov/core!1
Diffstat (limited to 'Zotlabs/Lib')
-rw-r--r--Zotlabs/Lib/Activity.php48
-rw-r--r--Zotlabs/Lib/Crypto.php206
-rw-r--r--Zotlabs/Lib/JSalmon.php4
-rw-r--r--Zotlabs/Lib/Keyutils.php4
-rw-r--r--Zotlabs/Lib/LDSignatures.php12
-rw-r--r--Zotlabs/Lib/Libzot.php15
-rw-r--r--Zotlabs/Lib/Zotfinger.php12
7 files changed, 269 insertions, 32 deletions
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index abb28fc64..d0799bb66 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -102,6 +102,17 @@ class Activity {
}
if ($x['success']) {
+ $m = parse_url($url);
+ if ($m) {
+ $site_url = unparse_url(['scheme' => $m['scheme'], 'host' => $m['host'], 'port' => $m['port'] ]);
+ q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s' AND site_update < %s - INTERVAL %s",
+ dbesc(datetime_convert()),
+ dbesc($site_url),
+ db_utcnow(),
+ db_quoteinterval('1 DAY')
+ );
+ }
+
$y = json_decode($x['body'], true);
logger('returned: ' . json_encode($y, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), LOGGER_DEBUG);
return json_decode($x['body'], true);
@@ -275,17 +286,27 @@ class Activity {
$numpages = $total / App::$pager['itemspage'];
$lastpage = (($numpages > intval($numpages)) ? intval($numpages) + 1 : $numpages);
+ $url_parts = parse_url($id);
- $stripped = preg_replace('/([&|\?]page=[0-9]*)/', '', $id);
- $stripped = rtrim($stripped, '/');
+ $ret['partOf'] = z_root() . '/' . $url_parts['path'];
- $ret['partOf'] = z_root() . '/' . $stripped;
+ $extra_query_args = '';
+ $query_args = null;
+ if(isset($url_parts['query'])) {
+ parse_str($url_parts['query'], $query_args);
+ }
+
+ if(is_array($query_args)) {
+ unset($query_args['page']);
+ foreach($query_args as $k => $v)
+ $extra_query_args .= '&' . urlencode($k) . '=' . urlencode($v);
+ }
if (App::$pager['page'] < $lastpage) {
- $ret['next'] = z_root() . '/' . $stripped . '?page=' . (intval(App::$pager['page']) + 1);
+ $ret['next'] = z_root() . '/' . $url_parts['path'] . '?page=' . (intval(App::$pager['page']) + 1) . $extra_query_args;
}
if (App::$pager['page'] > 1) {
- $ret['prev'] = z_root() . '/' . $stripped . '?page=' . (intval(App::$pager['page']) - 1);
+ $ret['prev'] = z_root() . '/' . $url_parts['path'] . '?page=' . (intval(App::$pager['page']) - 1) . $extra_query_args;
}
}
else {
@@ -1340,7 +1361,7 @@ class Activity {
$abook_instance .= ',';
$abook_instance .= z_root();
- q("update abook set abook_instance = '%s', abook_not_here = 0
+ q("update abook set abook_instance = '%s', abook_not_here = 0
where abook_id = %d and abook_channel = %d",
dbesc($abook_instance),
intval($contact['abook_id']),
@@ -1620,7 +1641,7 @@ class Activity {
$m = parse_url($url);
if ($m) {
$hostname = $m['host'];
- $baseurl = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+ $site_url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
}
if (!$r) {
@@ -1630,7 +1651,7 @@ class Activity {
'hubloc_hash' => $url,
'hubloc_addr' => '',
'hubloc_network' => 'activitypub',
- 'hubloc_url' => $baseurl,
+ 'hubloc_url' => $site_url,
'hubloc_host' => $hostname,
'hubloc_callback' => $inbox,
'hubloc_updated' => datetime_convert(),
@@ -1640,6 +1661,13 @@ class Activity {
);
}
+ q("UPDATE site SET site_update = '%s', site_dead = 0 WHERE site_url = '%s' AND site_update < %s - INTERVAL %s",
+ dbesc(datetime_convert()),
+ dbesc($site_url),
+ db_utcnow(),
+ db_quoteinterval('1 DAY')
+ );
+
if (!$icon)
$icon = z_root() . '/' . get_default_profile_photo(300);
@@ -2094,6 +2122,7 @@ class Activity {
$obj_actor = ((isset($act->obj['actor'])) ? $act->obj['actor'] : $act->get_actor('attributedTo', $act->obj));
// ensure we store the original actor
+
self::actor_store($obj_actor['id'], $obj_actor);
$mention = self::get_actor_bbmention($obj_actor['id']);
@@ -2817,9 +2846,6 @@ class Activity {
logger('not a valid activity');
break;
}
- if (is_array($a->actor) && array_key_exists('id', $a->actor)) {
- Activity::actor_store($a->actor['id'], $a->actor);
- }
$item = Activity::decode_note($a);
diff --git a/Zotlabs/Lib/Crypto.php b/Zotlabs/Lib/Crypto.php
new file mode 100644
index 000000000..f1794ae64
--- /dev/null
+++ b/Zotlabs/Lib/Crypto.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+use Exception;
+
+class Crypto {
+
+ public static $openssl_algorithms = [
+
+ // zot6 nickname, opensslname, keylength, ivlength
+
+ ['aes256ctr', 'aes-256-ctr', 32, 16],
+ ['camellia256cfb', 'camellia-256-cfb', 32, 16],
+ ['cast5cfb', 'cast5-cfb', 16, 8],
+ ['aes256cbc', 'aes-256-cbc', 32, 16] // remove after legacy zot has been sunset
+
+ ];
+
+ public static function methods() {
+ $ret = [];
+
+ foreach (self::$openssl_algorithms as $ossl) {
+ $ret[] = $ossl[0] . '.oaep';
+ }
+
+ call_hooks('crypto_methods', $ret);
+ return $ret;
+ }
+
+ public static function signing_methods() {
+
+ $ret = ['sha256'];
+ call_hooks('signing_methods', $ret);
+ return $ret;
+
+ }
+
+ public static function new_keypair($bits) {
+
+ $openssl_options = [
+ 'digest_alg' => 'sha1',
+ 'private_key_bits' => $bits,
+ 'encrypt_key' => false
+ ];
+
+ $conf = get_config('system', 'openssl_conf_file');
+
+ if ($conf) {
+ $openssl_options['config'] = $conf;
+ }
+
+ $result = openssl_pkey_new($openssl_options);
+
+ if (empty($result)) {
+ return false;
+ }
+
+ // Get private key
+
+ $response = ['prvkey' => '', 'pubkey' => ''];
+
+ openssl_pkey_export($result, $response['prvkey']);
+
+ // Get public key
+ $pkey = openssl_pkey_get_details($result);
+ $response['pubkey'] = $pkey["key"];
+
+ return $response;
+
+ }
+
+ public static function sign($data, $key, $alg = 'sha256') {
+
+ if (!$key) {
+ return false;
+ }
+
+ $sig = '';
+ openssl_sign($data, $sig, $key, $alg);
+ return $sig;
+ }
+
+ public static function verify($data, $sig, $key, $alg = 'sha256') {
+
+ if (!$key) {
+ return false;
+ }
+
+ try {
+ $verify = openssl_verify($data, $sig, $key, $alg);
+ } catch (Exception $e) {
+ $verify = (-1);
+ }
+
+ if ($verify === (-1)) {
+ while ($msg = openssl_error_string()) {
+ logger('openssl_verify: ' . $msg, LOGGER_NORMAL, LOG_ERR);
+ }
+ btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR);
+ }
+
+ return (($verify > 0) ? true : false);
+ }
+
+ public static function encapsulate($data, $pubkey, $alg) {
+
+ if (!($alg && $pubkey)) {
+ return $data;
+ }
+
+ $alg_base = $alg;
+ $padding = OPENSSL_PKCS1_PADDING;
+
+ $exts = explode('.', $alg);
+ if (count($exts) > 1) {
+ switch ($exts[1]) {
+ case 'oaep':
+ $padding = OPENSSL_PKCS1_OAEP_PADDING;
+ break;
+ default:
+ break;
+ }
+ $alg_base = $exts[0];
+ }
+
+ $method = null;
+
+ foreach (self::$openssl_algorithms as $ossl) {
+ if ($ossl[0] === $alg_base) {
+ $method = $ossl;
+ break;
+ }
+ }
+
+ if ($method) {
+ $result = ['encrypted' => true];
+
+ $key = openssl_random_pseudo_bytes(256);
+ $iv = openssl_random_pseudo_bytes(256);
+
+ $key1 = substr($key, 0, $method[2]);
+ $iv1 = substr($iv, 0, $method[3]);
+
+ $result['data'] = base64url_encode(openssl_encrypt($data, $method[1], $key1, OPENSSL_RAW_DATA, $iv1), true);
+
+ openssl_public_encrypt($key, $k, $pubkey, $padding);
+ openssl_public_encrypt($iv, $i, $pubkey, $padding);
+
+ $result['alg'] = $alg;
+ $result['key'] = base64url_encode($k, true);
+ $result['iv'] = base64url_encode($i, true);
+ return $result;
+
+ }
+ else {
+ $x = ['data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data];
+ call_hooks('crypto_encapsulate', $x);
+ return $x['result'];
+ }
+ }
+
+ public static function unencapsulate($data, $prvkey) {
+
+ if (!(is_array($data) && array_key_exists('encrypted', $data) && array_key_exists('alg', $data) && $data['alg'])) {
+ logger('not encrypted');
+
+ return $data;
+ }
+
+ $alg_base = $data['alg'];
+ $padding = OPENSSL_PKCS1_PADDING;
+
+ $exts = explode('.', $data['alg']);
+ if (count($exts) > 1) {
+ switch ($exts[1]) {
+ case 'oaep':
+ $padding = OPENSSL_PKCS1_OAEP_PADDING;
+ break;
+ default:
+ break;
+ }
+ $alg_base = $exts[0];
+ }
+
+ $method = null;
+
+ foreach (self::$openssl_algorithms as $ossl) {
+ if ($ossl[0] === $alg_base) {
+ $method = $ossl;
+ break;
+ }
+ }
+
+ if ($method) {
+ openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey, $padding);
+ openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey, $padding);
+ return openssl_decrypt(base64url_decode($data['data']), $method[1], substr($k, 0, $method[2]), OPENSSL_RAW_DATA, substr($i, 0, $method[3]));
+ }
+ else {
+ $x = ['data' => $data, 'prvkey' => $prvkey, 'alg' => $data['alg'], 'result' => $data];
+ call_hooks('crypto_unencapsulate', $x);
+ return $x['result'];
+ }
+ }
+}
diff --git a/Zotlabs/Lib/JSalmon.php b/Zotlabs/Lib/JSalmon.php
index 7f63cf914..f9fe99706 100644
--- a/Zotlabs/Lib/JSalmon.php
+++ b/Zotlabs/Lib/JSalmon.php
@@ -18,7 +18,7 @@ class JSalmon {
$precomputed = '.' . base64url_encode($data_type,true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
- $signature = base64url_encode(rsa_sign($data . $precomputed, $key), true);
+ $signature = base64url_encode(Crypto::sign($data . $precomputed, $key), true);
return ([
'signed' => true,
@@ -54,7 +54,7 @@ class JSalmon {
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
logger('key: ' . print_r($key,true));
if($key['portable_id'] && $key['public_key']) {
- if(rsa_verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
+ if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
logger('verified');
$ret = [ 'success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc'] ];
}
diff --git a/Zotlabs/Lib/Keyutils.php b/Zotlabs/Lib/Keyutils.php
index d4b660c04..616ecfcf6 100644
--- a/Zotlabs/Lib/Keyutils.php
+++ b/Zotlabs/Lib/Keyutils.php
@@ -64,8 +64,8 @@ class Keyutils {
$rsa->loadKey($key);
$rsa->setPublicKey();
- $e = $rsa->modulus->toBytes();
- $m = $rsa->exponent->toBytes();
+ $m = $rsa->modulus->toBytes();
+ $e = $rsa->exponent->toBytes();
}
diff --git a/Zotlabs/Lib/LDSignatures.php b/Zotlabs/Lib/LDSignatures.php
index 2eba66ccf..1c2095f10 100644
--- a/Zotlabs/Lib/LDSignatures.php
+++ b/Zotlabs/Lib/LDSignatures.php
@@ -12,7 +12,7 @@ class LDSignatures {
$ohash = self::hash(self::signable_options($data['signature']));
$dhash = self::hash(self::signable_data($data));
- $x = rsa_verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
+ $x = Crypto::verify($ohash . $dhash,base64_decode($data['signature']['signatureValue']), $pubkey);
logger('LD-verify: ' . intval($x));
return $x;
@@ -35,11 +35,11 @@ class LDSignatures {
$ohash = self::hash(self::signable_options($options));
$dhash = self::hash(self::signable_data($data));
- $options['signatureValue'] = base64_encode(rsa_sign($ohash . $dhash,$channel['channel_prvkey']));
+ $options['signatureValue'] = base64_encode(Crypto::sign($ohash . $dhash,$channel['channel_prvkey']));
$signed = array_merge([
- '@context' => [
- ACTIVITYSTREAMS_JSONLD_REV,
+ '@context' => [
+ ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1' ],
],$options);
@@ -88,7 +88,7 @@ class LDSignatures {
return '';
jsonld_set_document_loader('jsonld_document_loader');
-
+
try {
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
}
@@ -117,7 +117,7 @@ class LDSignatures {
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
- $signature = base64url_encode(rsa_sign($data . $precomputed,$channel['channel_prvkey']));
+ $signature = base64url_encode(Crypto::sign($data . $precomputed,$channel['channel_prvkey']));
return ([
'id' => $arr['id'],
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index 0ead8402e..45d536638 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -130,7 +130,7 @@ class Libzot {
if ($remote_key) {
$algorithm = self::best_algorithm($methods);
if ($algorithm) {
- $data = crypto_encapsulate(json_encode($data), $remote_key, $algorithm);
+ $data = Crypto::encapsulate(json_encode($data), $remote_key, $algorithm);
}
}
@@ -143,7 +143,7 @@ class Libzot {
*
* @param string $methods
* Comma separated list of encryption methods
- * @return string first match from our site method preferences crypto_methods() array
+ * @return string first match from our site method preferences Crypto::methods() array
* of a method which is common to both sites; or 'aes256cbc' if no matches are found.
*/
static function best_algorithm($methods) {
@@ -167,7 +167,7 @@ class Libzot {
if ($methods) {
$x = explode(',', $methods);
if ($x) {
- $y = crypto_methods();
+ $y = Crypto::methods();
if ($y) {
foreach ($y as $yv) {
$yv = trim($yv);
@@ -983,7 +983,7 @@ class Libzot {
logger('Headers: ' . print_r($arr['header'], true), LOGGER_DATA, LOG_DEBUG);
}
- $x = crypto_unencapsulate($x, get_config('system', 'prvkey'));
+ $x = Crypto::unencapsulate($x, get_config('system', 'prvkey'));
if (!is_array($x)) {
$x = json_decode($x, true);
@@ -3020,7 +3020,7 @@ class Libzot {
$ret['site']['directory_url'] = z_root() . '/dirsearch';
- $ret['site']['encryption'] = crypto_methods();
+ $ret['site']['encryption'] = Crypto::methods();
$ret['site']['zot'] = System::get_zot_revision();
// hide detailed site information if you're off the grid
@@ -3140,6 +3140,11 @@ class Libzot {
);
}
+ // this site obviously isn't dead because they are trying to communicate with us.
+ q("update site set site_dead = 0 where site_dead = 1 and site_url = '%s' ",
+ dbesc($hub['hubloc_url'])
+ );
+
return $hub['hubloc_url'];
}
diff --git a/Zotlabs/Lib/Zotfinger.php b/Zotlabs/Lib/Zotfinger.php
index faaf28f35..840d91403 100644
--- a/Zotlabs/Lib/Zotfinger.php
+++ b/Zotlabs/Lib/Zotfinger.php
@@ -18,8 +18,8 @@ class Zotfinger {
if($channel && $m) {
- $headers = [
- 'Accept' => 'application/x-zot+json',
+ $headers = [
+ 'Accept' => 'application/x-zot+json',
'Content-Type' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
@@ -29,9 +29,9 @@ class Zotfinger {
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
}
else {
- $h = [ 'Accept: application/x-zot+json' ];
+ $h = [ 'Accept: application/x-zot+json' ];
}
-
+
$result = [];
$redirects = 0;
@@ -43,11 +43,11 @@ class Zotfinger {
if ($verify) {
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
}
-
+
$result['data'] = json_decode($x['body'],true);
if($result['data'] && is_array($result['data']) && array_key_exists('encrypted',$result['data']) && $result['data']['encrypted']) {
- $result['data'] = json_decode(crypto_unencapsulate($result['data'],get_config('system','prvkey')),true);
+ $result['data'] = json_decode(Crypto::unencapsulate($result['data'],get_config('system','prvkey')),true);
}
logger('decrypted: ' . print_r($result,true));