aboutsummaryrefslogtreecommitdiffstats
path: root/include/salmon.php
blob: bd2d620a815132b4087c3d1e52d73a323180cc3f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?php

require_once('library/asn1.php');

function salmon_key($pubkey) {
	$lines = explode("\n",$pubkey);
	unset($lines[0]);
	unset($lines[count($lines)]);
	$x = base64_decode(implode('',$lines));

	$r = ASN_BASE::parseASNString($x);

	$m = $r[0]->asnData[1]->asnData[0]->asnData[0]->asnData;
	$e = $r[0]->asnData[1]->asnData[0]->asnData[1]->asnData;


	return 'RSA' . '.' . $m . '.' . $e ;
}


function base64url_encode($s) {
	return strtr(base64_encode($s),'+/','-_');
}

function base64url_decode($s) {
	return base64_decode(strtr($s,'-_','+/'));
}

function get_salmon_key($uri,$keyhash) {
	$ret = array();

	$debugging = get_config('system','debugging');
	if($debugging)		
		file_put_contents('salmon.out', "\n" . 'Fetch key' . "\n", FILE_APPEND);

	if(strstr($uri,'@')) {	
		$arr = webfinger($uri);
		if($debugging)
			file_put_contents('salmon.out', "\n" . 'Fetch key from webfinger' . "\n", FILE_APPEND);
	}
	else {
		$html = fetch_url($uri);
		$a = get_app();
		$h = $a->get_curl_headers();
		if($debugging)
			file_put_contents('salmon.out', "\n" . 'Fetch key via HTML header: ' . $h . "\n", FILE_APPEND);

		$l = explode("\n",$h);
		if(count($l)) {
			foreach($l as $line) {
				
				if($debugging)
					file_put_contents('salmon.out', "\n" . $line . "\n", FILE_APPEND);
				if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
					$link = $matches[1];
					if($debugging)
						file_put_contents('salmon.out', "\n" . 'Fetch key via Link from header: ' . $link . "\n", FILE_APPEND);
					break;
				}
			}
		}
	}

	if(! isset($link)) {
		require_once('library/HTML5/Parser.php');
		$dom = HTML5_Parser::parse($html);

		if(! $dom)
			return '';

		$items = $dom->getElementsByTagName('link');

		foreach($items as $item) {
			$x = $item->getAttribute('rel');
			if($x == "lrdd") {
				$link = $item->getAttribute('href');
				if($debugging)
					file_put_contents('salmon.out', "\n" . 'Fetch key via HTML body' . $link . "\n", FILE_APPEND);
				break;
			}
		}
	}

	if(! isset($link))
		return '';

	$arr = fetch_xrd_links($link);

	if($arr) {
		foreach($arr as $a) {
			if($a['@attributes']['rel'] === 'magic-public-key') {
				$ret[] = $a['@attributes']['href'];
			}
		}
	}
	if(count($ret)) {
		for($x = 0; $x < count($ret); $x ++) {
			if(substr($ret[$x],0,5) === 'data:') {
				if(strstr($ret[$x],','))
					$ret[$x] = substr($ret[$x],strpos($ret[$x],',')+1);
				else
					$ret[$x] = substr($ret[$x],5);
			}
			else
				$ret[$x] = fetch_url($ret[$x]);
		}
	}
	if($debugging)
		file_put_contents('salmon.out', "\n" . 'Key located: ' . print_r($ret,true) . "\n", FILE_APPEND);

	if(count($ret) == 1) {
		return $ret[0];
	}
	else {
		foreach($ret as $a) {
			$hash = base64url_encode(hash('sha256',$a));
			if($hash == $keyhash)
				return $a;
		}
	}

	return '';
}