Skip to content

Commit 2705172

Browse files
pfefferlemattwiebe
andauthored
Fix some signature and application user issues (#410)
* Fix some signature and application user issues * it seems that firefish needs at least an inbox also for application users * prepare domain change * use https * fix PHPDoc * remove image check --------- Co-authored-by: Matt Wiebe <[email protected]>
1 parent 26ad897 commit 2705172

File tree

7 files changed

+62
-45
lines changed

7 files changed

+62
-45
lines changed

includes/activity/class-activity.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class Activity extends Base_Object {
2626
'schema' => 'http://schema.org#',
2727
'pt' => 'https://joinpeertube.org/ns#',
2828
'toot' => 'http://joinmastodon.org/ns#',
29+
'webfinger' => 'https://webfinger.net/#',
2930
'litepub' => 'http://litepub.social/ns#',
3031
'value' => 'schema:value',
3132
'Hashtag' => 'as:Hashtag',
@@ -37,8 +38,13 @@ class Activity extends Base_Object {
3738
'@id' => 'toot:featuredTags',
3839
'@type' => '@id',
3940
),
41+
'alsoKnownAs' => array(
42+
'@id' => 'as:alsoKnownAs',
43+
'@type' => '@id',
44+
),
4045
'discoverable' => 'toot:discoverable',
4146
'sensitive' => 'as:sensitive',
47+
'resource' => 'webfinger:resource',
4248
),
4349
);
4450

includes/class-signature.php

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,10 @@ public static function verify_http_signature( $request ) {
162162
$route = '/' . rest_get_url_prefix() . '/' . ltrim( $request->get_route(), '/' );
163163
}
164164
$headers = $request->get_headers();
165-
$actor = isset( json_decode( $request->get_body() )->actor ) ? json_decode( $request->get_body() )->actor : '';
166165
$headers['(request-target)'][0] = strtolower( $request->get_method() ) . ' ' . $route;
167166
} else {
168167
$request = self::format_server_request( $request );
169168
$headers = $request['headers']; // $_SERVER array
170-
$actor = null;
171169
$headers['(request-target)'][0] = strtolower( $headers['request_method'][0] ) . ' ' . $headers['request_uri'][0];
172170
}
173171

@@ -176,9 +174,9 @@ public static function verify_http_signature( $request ) {
176174
}
177175

178176
if ( array_key_exists( 'signature', $headers ) ) {
179-
$signature_block = self::parse_signature_header( $headers['signature'] );
177+
$signature_block = self::parse_signature_header( $headers['signature'][0] );
180178
} elseif ( array_key_exists( 'authorization', $headers ) ) {
181-
$signature_block = self::parse_signature_header( $headers['authorization'] );
179+
$signature_block = self::parse_signature_header( $headers['authorization'][0] );
182180
}
183181

184182
if ( ! isset( $signature_block ) || ! $signature_block ) {
@@ -217,11 +215,8 @@ public static function verify_http_signature( $request ) {
217215
}
218216
}
219217

220-
if ( $actor ) {
221-
$public_key = self::get_remote_key( $actor );
222-
} else {
223-
$public_key = self::get_remote_key( $signature_block['keyId'] );
224-
}
218+
$public_key = self::get_remote_key( $signature_block['keyId'] );
219+
225220
if ( \is_wp_error( $public_key ) ) {
226221
return $public_key;
227222
}
@@ -242,7 +237,7 @@ public static function verify_http_signature( $request ) {
242237
* @return string The public key.
243238
*/
244239
public static function get_remote_key( $key_id ) { // phpcs:ignore
245-
$actor = get_remote_metadata_by_actor( strtok( strip_fragment_from_url( $key_id ), '?' ) ); // phpcs:ignore
240+
$actor = get_remote_metadata_by_actor( strip_fragment_from_url( $key_id ) ); // phpcs:ignore
246241
if ( \is_wp_error( $actor ) ) {
247242
return $actor;
248243
}
@@ -274,32 +269,31 @@ public static function get_signature_algorithm( $signature_block ) {
274269
/**
275270
* Parses the Signature header
276271
*
277-
* @param array $header The signature header.
272+
* @param string $signature The signature header.
278273
*
279274
* @return array signature parts
280275
*/
281-
public static function parse_signature_header( $header ) {
282-
$parsed_header = array();
283-
$matches = array();
284-
$h_string = \implode( ',', (array) $header[0] );
276+
public static function parse_signature_header( $signature ) {
277+
$parsed_header = array();
278+
$matches = array();
285279

286-
if ( \preg_match( '/keyId="(.*?)"/ism', $h_string, $matches ) ) {
287-
$parsed_header['keyId'] = $matches[1];
280+
if ( \preg_match( '/keyId="(.*?)"/ism', $signature, $matches ) ) {
281+
$parsed_header['keyId'] = trim( $matches[1] );
288282
}
289-
if ( \preg_match( '/created=([0-9]*)/ism', $h_string, $matches ) ) {
290-
$parsed_header['(created)'] = $matches[1];
283+
if ( \preg_match( '/created=([0-9]*)/ism', $signature, $matches ) ) {
284+
$parsed_header['(created)'] = trim( $matches[1] );
291285
}
292-
if ( \preg_match( '/expires=([0-9]*)/ism', $h_string, $matches ) ) {
293-
$parsed_header['(expires)'] = $matches[1];
286+
if ( \preg_match( '/expires=([0-9]*)/ism', $signature, $matches ) ) {
287+
$parsed_header['(expires)'] = trim( $matches[1] );
294288
}
295-
if ( \preg_match( '/algorithm="(.*?)"/ism', $h_string, $matches ) ) {
296-
$parsed_header['algorithm'] = $matches[1];
289+
if ( \preg_match( '/algorithm="(.*?)"/ism', $signature, $matches ) ) {
290+
$parsed_header['algorithm'] = trim( $matches[1] );
297291
}
298-
if ( \preg_match( '/headers="(.*?)"/ism', $h_string, $matches ) ) {
299-
$parsed_header['headers'] = \explode( ' ', $matches[1] );
292+
if ( \preg_match( '/headers="(.*?)"/ism', $signature, $matches ) ) {
293+
$parsed_header['headers'] = \explode( ' ', trim( $matches[1] ) );
300294
}
301-
if ( \preg_match( '/signature="(.*?)"/ism', $h_string, $matches ) ) {
302-
$parsed_header['signature'] = \base64_decode( preg_replace( '/\s+/', '', $matches[1] ) ); // phpcs:ignore
295+
if ( \preg_match( '/signature="(.*?)"/ism', $signature, $matches ) ) {
296+
$parsed_header['signature'] = \base64_decode( preg_replace( '/\s+/', '', trim( $matches[1] ) ) ); // phpcs:ignore
303297
}
304298

305299
if ( ( $parsed_header['signature'] ) && ( $parsed_header['algorithm'] ) && ( ! $parsed_header['headers'] ) ) {
@@ -312,7 +306,7 @@ public static function parse_signature_header( $header ) {
312306
/**
313307
* Gets the header data from the included pseudo headers
314308
*
315-
* @param array $signed_headers
309+
* @param array $signed_headers The signed headers.
316310
* @param array $signature_block (pseudo-headers)
317311
* @param array $headers (http headers)
318312
*

includes/model/class-application-user.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ class Application_User extends Blog_User {
2222
*/
2323
protected $type = 'Application';
2424

25+
/**
26+
* If the User is discoverable.
27+
*
28+
* @var boolean
29+
*/
30+
protected $discoverable = false;
31+
2532
/**
2633
* Get the User-Url.
2734
*
@@ -35,7 +42,7 @@ public function get_name() {
3542
return 'application';
3643
}
3744

38-
public function get_username() {
45+
public function get_preferred_username() {
3946
return $this::get_name();
4047
}
4148

@@ -79,14 +86,6 @@ private function generate_key_pair() {
7986
}
8087
}
8188

82-
public function get_inbox() {
83-
return null;
84-
}
85-
86-
public function get_outbox() {
87-
return null;
88-
}
89-
9089
public function get_followers() {
9190
return null;
9291
}

includes/model/class-user.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,25 @@ class User extends Actor {
3737
protected $featured;
3838

3939
/**
40-
* The Webfinger-style identifier.
40+
* The User-Type
4141
*
4242
* @var string
4343
*/
44-
protected $resource;
44+
protected $type = 'Person';
4545

4646
/**
47-
* The User-Type
47+
* If the User is discoverable.
4848
*
49-
* @var string
49+
* @var boolean
5050
*/
51-
protected $type = 'Person';
51+
protected $discoverable = true;
52+
53+
/**
54+
* The WebFinger Resource.
55+
*
56+
* @var string<url>
57+
*/
58+
protected $resource;
5259

5360
public static function from_wp_user( $user_id ) {
5461
if ( is_user_disabled( $user_id ) ) {

includes/rest/class-inbox.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ public static function shared_inbox_post( $request ) {
171171
}
172172

173173
foreach ( $users as $user ) {
174+
$user = User_Collection::get_by_various( $user );
175+
176+
if ( is_wp_error( $user ) ) {
177+
continue;
178+
}
179+
174180
$type = \strtolower( $type );
175181

176182
\do_action( 'activitypub_inbox', $data, $user->ID, $type );

includes/rest/class-server.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public static function register_routes() {
4646
*/
4747
public static function application_actor() {
4848
$user = new Application_User();
49+
50+
$user->set_context(
51+
\Activitypub\Activity\Activity::CONTEXT
52+
);
53+
4954
$json = $user->to_array();
5055

5156
$response = new WP_REST_Response( $json, 200 );
@@ -80,12 +85,12 @@ public static function authorize_activitypub_requests( $response, $handler, $req
8085
}
8186

8287
// POST-Requets are always signed
83-
if ( 'POST' === $request->get_method() ) {
88+
if ( 'post' === \strtolower( $request->get_method() ) ) {
8489
$verified_request = Signature::verify_http_signature( $request );
8590
if ( \is_wp_error( $verified_request ) ) {
8691
return $verified_request;
8792
}
88-
} elseif ( 'GET' === $request->get_method() ) { // GET-Requests are only signed in secure mode
93+
} elseif ( 'get' === \strtolower( $request->get_method() ) ) { // GET-Requests are only signed in secure mode
8994
if ( ACTIVITYPUB_AUTHORIZED_FETCH ) {
9095
$verified_request = Signature::verify_http_signature( $request );
9196
if ( \is_wp_error( $verified_request ) ) {

tests/test-class-activitypub-rest-post-signature-verification.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function test_activity_signature() {
3939

4040
// Start verification
4141
// parse_signature_header, get_signed_data, get_public_key
42-
$signature_block = Activitypub\Signature::parse_signature_header( $headers['signature'] );
42+
$signature_block = Activitypub\Signature::parse_signature_header( $headers['signature'][0] );
4343
$signed_headers = $signature_block['headers'];
4444
$signed_data = Activitypub\Signature::get_signed_data( $signed_headers, $signature_block, $headers );
4545

0 commit comments

Comments
 (0)