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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.3.1"/>
<title>The Red Matrix: mod/post.php File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
$(window).load(resizeHeight);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
$(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="rm-64.png"/></td>
<td style="padding-left: 0.5em;">
<div id="projectname">The Red Matrix
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.3.1 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main Page</span></a></li>
<li><a href="pages.html"><span>Related Pages</span></a></li>
<li><a href="namespaces.html"><span>Namespaces</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
<li class="current"><a href="files.html"><span>Files</span></a></li>
<li>
<div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</li>
</ul>
</div>
<div id="navrow2" class="tabs2">
<ul class="tablist">
<li><a href="files.html"><span>File List</span></a></li>
<li><a href="globals.html"><span>File Members</span></a></li>
</ul>
</div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('post_8php.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark"> </span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark"> </span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark"> </span>Namespaces</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark"> </span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark"> </span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark"> </span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark"> </span>Pages</a></div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="summary">
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
<div class="title">post.php File Reference</div> </div>
</div><!--header-->
<div class="contents">
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:af4b48181ce773ef0cdfc972441445c34"><td class="memItemLeft" align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="post_8php.html#af4b48181ce773ef0cdfc972441445c34">post_init</a> (&$a)</td></tr>
<tr class="separator:af4b48181ce773ef0cdfc972441445c34"><td class="memSeparator" colspan="2"> </td></tr>
<tr class="memitem:af59e6a1dc22d19d9257b01cd7ccedb75"><td class="memItemLeft" align="right" valign="top"> </td><td class="memItemRight" valign="bottom"><a class="el" href="post_8php.html#af59e6a1dc22d19d9257b01cd7ccedb75">post_post</a> (&$a)</td></tr>
<tr class="separator:af59e6a1dc22d19d9257b01cd7ccedb75"><td class="memSeparator" colspan="2"> </td></tr>
</table>
<h2 class="groupheader">Function Documentation</h2>
<a class="anchor" id="af4b48181ce773ef0cdfc972441445c34"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">post_init </td>
<td>(</td>
<td class="paramtype">& </td>
<td class="paramname"><em>$a</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Zot endpoint </p>
<h1>Magic Auth</h1>
<p>So-called "magic auth" takes place by a special exchange. On the site where the "channel to be authenticated" lives (e.g. $mysite), a redirection is made via $mysite/magic to the zot endpoint of the remote site ($remotesite) with special GET parameters.</p>
<p>The endpoint is typically <a href="https://$remotesite/post">https://$remotesite/post</a> - or whatever was specified as the callback url in prior communications (we will bootstrap an address and fetch a zot info packet if possible where no prior communications exist)</p>
<p>Four GET parameters are supplied:</p>
<p>auth => the urlencoded webbie (<a href="#" onclick="location.href='mai'+'lto:'+'cha'+'nn'+'el@'+'ho'+'st.'+'do'+'mai'+'n'; return false;">chann<span style="display: none;">.nosp@m.</span>el@h<span style="display: none;">.nosp@m.</span>ost.d<span style="display: none;">.nosp@m.</span>omai<span style="display: none;">.nosp@m.</span>n</a>) of the channel requesting access dest => the desired destination URL (urlencoded) sec => a random string which is also stored on $mysite for use during the verification phase. version => the zot revision</p>
<p>When this packet is received, an "auth-check" zot message is sent to $mysite. (e.g. if $_GET['auth'] is <a href="#" onclick="location.href='mai'+'lto:'+'foo'+'ba'+'r@p'+'od'+'unk'+'.e'+'du'; return false;">fooba<span style="display: none;">.nosp@m.</span>r@po<span style="display: none;">.nosp@m.</span>dunk.<span style="display: none;">.nosp@m.</span>edu</a>, a zot packet is sent to the podunk.edu zot endpoint, which is typically /post) If no information has been recorded about the requesting identity a zot information packet will be retrieved before continuing.</p>
<p>The sender of this packet is an arbitrary/random site channel. The recipients will be a single recipient corresponding to the guid and guid_sig we have associated with the requesting auth identity</p>
<p>{ "type":"auth_check", "sender":{ "guid":"kgVFf_...", "guid_sig":"PT9-TApz...", "url":"http:\/\/podunk.edu", "url_sig":"T8Bp7j..." }, "recipients":{ { "guid":"ZHSqb...", "guid_sig":"JsAAXi..." } } "callback":"\/post", "version":1, "secret":"1eaa661", "secret_sig":"eKV968b1..." }</p>
<p>auth_check messages MUST use encapsulated encryption. This message is sent to the origination site, which checks the 'secret' to see if it is the same as the 'sec' which it passed originally. It also checks the secret_sig which is the secret signed by the destination channel's private key and base64url encoded. If everything checks out, a json packet is returned:</p>
<p>{ "success":1, "confirm":"q0Ysovd1u..." "service_class":(optional) "level":(optional) }</p>
<p>'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the base64url encoded whirlpool hash of the requestor's guid and guid_sig; signed with the source channel private key. This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login. Service_class can be used by cooperating sites to provide different access rights based on account rights and subscription plans. It is a string whose contents are not defined by protocol. Example: "basic" or "gold".</p>
</div>
</div>
<a class="anchor" id="af59e6a1dc22d19d9257b01cd7ccedb75"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">post_post </td>
<td>(</td>
<td class="paramtype">& </td>
<td class="paramname"><em>$a</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>post_post(&$a) zot communications and messaging</p>
<p>Sender HTTP posts to this endpoint ($site/post typically) with 'data' parameter set to json zot message packet. This packet is optionally encrypted, which we will discover if the json has an 'iv' element. $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data); $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded. Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate.</p>
<p>Once decrypted, one will find the normal json_encoded zot message packet.</p>
<p>Defined packet types are: notify, purge, refresh, force_refresh, auth_check, ping, and pickup</p>
<p>Standard packet: (used by notify, purge, refresh, force_refresh, and auth_check)</p>
<p>{ "type": "notify", "sender":{ "guid":"kgVFf_1...", "guid_sig":"PT9-TApzp...", "url":"http:\/\/podunk.edu", "url_sig":"T8Bp7j5...", }, "recipients": { optional recipient array }, "callback":"\/post", "version":1, "secret":"1eaa...", "secret_sig": "df89025470fac8..." }</p>
<p>Signature fields are all signed with the sender channel private key and base64url encoded. Recipients are arrays of guid and guid_sig, which were previously signed with the recipients private key and base64url encoded and later obtained via channel discovery. Absence of recipients indicates a public message or visible to all potential listeners on this site.</p>
<p>"pickup" packet: The pickup packet is sent in response to a notify packet from another site</p>
<p>{ "type":"pickup", "url":"http:\/\/example.com", "callback":"http:\/\/example.com\/post", "callback_sig":"teE1_fLI...", "secret":"1eaa...", "secret_sig":"O7nB4_..." }</p>
<p>In the pickup packet, the sig fields correspond to the respective data element signed with this site's system private key and then base64url encoded. The "secret" is the same as the original secret from the notify packet.</p>
<p>If verification is successful, a json structure is returned containing a success indicator and an array of type 'pickup'. Each pickup element contains the original notify request and a message field whose contents are dependent on the message type</p>
<p>This JSON array is AES encapsulated using the site public key of the site that sent the initial zot pickup packet. Using the above example, this would be example.com.</p>
<p>{ "success":1, "pickup":{ "notify":{ "type":"notify", "sender":{ "guid":"kgVFf_...", "guid_sig":"PT9-TApz...", "url":"http:\/\/z.podunk.edu", "url_sig":"T8Bp7j5D..." }, "callback":"\/post", "version":1, "secret":"1eaa661..." }, "message":{ "type":"activity", "message_id":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", "message_top":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", "message_parent":"10b049ce384cbb2da9467319bc98169ab36290b8bbb403aa0c0accd9cb072e76@podunk.edu", "created":"2012-11-20 04:04:16", "edited":"2012-11-20 04:04:16", "title":"", "body":"Hi Nickordo", "app":"", "verb":"post", "object_type":"", "target_type":"", "permalink":"", "location":"", "longlat":"", "owner":{ "name":"Indigo", "address":"indigo@podunk.edu", "url":"http:\/\/podunk.edu", "photo":{ "mimetype":"image\/jpeg", "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" }, "guid":"kgVFf_...", "guid_sig":"PT9-TAp...", }, "author":{ "name":"Indigo", "address":"indigo@podunk.edu", "url":"http:\/\/podunk.edu", "photo":{ "mimetype":"image\/jpeg", "src":"http:\/\/podunk.edu\/photo\/profile\/m\/5" }, "guid":"kgVFf_...", "guid_sig":"PT9-TAp..." } } } }</p>
<p>Currently defined message types are 'activity', 'mail', 'profile' and 'channel_sync', which each have different content schemas.</p>
<p>Ping packet: A ping packet does not require any parameters except the type. It may or may not be encrypted.</p>
<p>{ "type": "ping" }</p>
<p>On receipt of a ping packet a ping response will be returned:</p>
<p>{ "success" : 1, "site" { "url":"http:\/\/podunk.edu", "url_sig":"T8Bp7j5...", "sitekey": "&ndash;&mdash;BEGIN PUBLIC KEY&ndash;&mdash;
MIICIjANBgkqhkiG9w0BAQE..." } }</p>
<p>The ping packet can be used to verify that a site has not been re-installed, and to initiate corrective action if it has. The url_sig is signed with the site private key and base64url encoded - and this should verify with the enclosed sitekey. Failure to verify indicates the site is corrupt or otherwise unable to communicate using zot. This return packet is not otherwise verified, so should be compared with other results obtained from this site which were verified prior to taking action. For instance if you have one verified result with this signature and key, and other records for this url which have different signatures and keys, it indicates that the site was re-installed and corrective action may commence (remove or mark invalid any entries with different signatures). If you have no records which match this url_sig and key - no corrective action should be taken as this packet may have been returned by an imposter. </p>
<p>Many message packets will arrive encrypted. The existence of an 'iv' element tells us we need to unencapsulate the AES-256-CBC content using the site private key</p>
<p>The 'pickup' message arrives with a tracking ID which is associated with a particular outq_hash First verify that that the returned signatures verify, then check that we have an outbound queue item with the correct hash. If everything verifies, find any/all outbound messages in the queue for this hubloc and send them back</p>
<p>If we made it to here, the signatures verify, but we still don't know if the tracking ID is valid. It wouldn't be an error if the tracking ID isn't found, because we may have sent this particular queue item with another pickup (after the tracking ID for the other pickup was verified).</p>
<p>Everything is good if we made it here, so find all messages that are going to this location and send them all.</p>
<p>pickup: end</p>
<p>All other message types require us to verify the sender. This is a generic check, so we will do it once here and bail if anything goes wrong.</p>
<p>Check if the sender is already verified here</p>
<p>Have never seen this guid or this guid coming from this location. Check it and register it.</p>
<p>This hub has now been proven to be valid. Any hub with the same URL and a different sitekey cannot be valid. Get rid of them (mark them deleted). There's a good chance they were re-installs.</p>
<p>Requestor visits /magic/?dest=somewhere on their own site with a browser magic redirects them to $destsite/post [with auth args....] $destsite sends an auth_check packet to originator site The auth_check packet is handled here by the originator's site</p>
<ul>
<li>the browser session is still waiting inside $destsite/post for everything to verify If everything checks out we'll return a token to $destsite and then $destsite will verify the token, authenticate the browser session and then redirect to the original destination. If authentication fails, the redirection to the original destination will still take place but without authentication.</li>
</ul>
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
|