false ]; if (!$this->validateAuthorizationHeader()) { $this->error('Missing or invalid authorization header.'); } $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']); if ($sigblock) { $keyId = $sigblock['keyId']; $parsed = parse_url($keyId); if (str_starts_with($parsed['scheme'],'http')) { unset($parsed['fragment']); unset($parsed['query']); $keyId = unparse_url($parsed); } else { $keyId = str_replace('acct:', '', $keyId); } if ($keyId) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC", dbesc($keyId), dbesc($keyId), dbesc($keyId) ); if (! $r) { $found = discover_by_webbie($keyId); logger('found = ' . print_r($found, true)); if ($found) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ", dbesc($keyId), dbesc($keyId), dbesc($keyId) ); } } if ($r) { foreach ($r as $hubloc) { $verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']); if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) { logger('OWA header: ' . print_r($verified,true),LOGGER_DATA); logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA); $ret['success'] = true; $token = random_string(32); Verify::create('owt',0,$token,$hubloc['hubloc_id_url']); $result = ''; openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']); $ret['encrypted_token'] = base64url_encode($result); break; } else { logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']); } } if (!$ret['success']) { // Possible a reinstall? // In this case we probably already have an old hubloc // but not the new one yet. $found = discover_by_webbie($keyId); if ($found) { $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1", dbesc(str_replace('acct:', '', $keyId)), dbesc($keyId) ); if ($r) { $verified = HTTPSig::verify(file_get_contents('php://input'), $r[0]['xchan_pubkey']); if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) { logger('OWA header: ' . print_r($verified,true), LOGGER_DATA); logger('OWA success: ' . $r[0]['hubloc_id_url'], LOGGER_DATA); $ret['success'] = true; $token = random_string(32); Verify::create('owt', 0, $token, $r[0]['hubloc_id_url']); $result = ''; openssl_public_encrypt($token, $result, $r[0]['xchan_pubkey']); $ret['encrypted_token'] = base64url_encode($result); } else { logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']); } } } } } } } json_return_and_die($ret,'application/x-zot+json'); } private function validateAuthorizationHeader(): bool { if (!empty($_SERVER['HTTP_AUTHORIZATION'])) { $auth = trim($_SERVER['HTTP_AUTHORIZATION']); } else if (!empty($_SERVER['REDIRECT_REMOTE_USER'])) { $auth = trim($_SERVER['REDIRECT_REMOTE_USER']); } else { return false; } return strncmp($auth, 'Signature', 9) === 0; } /** * Terminates the request, and return a json error response. * * @Note This function does not return! * * @param string $msg The error message for the response. */ private function error(string $msg): void { $ret = [ 'success' => false, 'message' => $msg ]; json_return_and_die($ret,'application/x-zot+json'); } }