Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
9.7 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
  1. <?php
  2. require_once('library/simplepie/simplepie.inc');
  3. require_once('include/items.php');
  4. require_once('include/event.php');
  5. function dfrn_notify_post(&$a) {
  6. $dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : '');
  7. $dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version'] : 2.0);
  8. $challenge = ((x($_POST,'challenge')) ? notags(trim($_POST['challenge'])) : '');
  9. $data = ((x($_POST,'data')) ? $_POST['data'] : '');
  10. $key = ((x($_POST,'key')) ? $_POST['key'] : '');
  11. $dissolve = ((x($_POST,'dissolve')) ? intval($_POST['dissolve']) : 0);
  12. $perm = ((x($_POST,'perm')) ? notags(trim($_POST['perm'])) : 'r');
  13. $ssl_policy = ((x($_POST,'ssl_policy')) ? notags(trim($_POST['ssl_policy'])): 'none');
  14. $writable = (-1);
  15. if($dfrn_version >= 2.21) {
  16. $writable = (($perm === 'rw') ? 1 : 0);
  17. }
  18. $direction = (-1);
  19. if(strpos($dfrn_id,':') == 1) {
  20. $direction = intval(substr($dfrn_id,0,1));
  21. $dfrn_id = substr($dfrn_id,2);
  22. }
  23. $r = q("SELECT * FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1",
  24. dbesc($dfrn_id),
  25. dbesc($challenge)
  26. );
  27. if(! count($r)) {
  28. logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge);
  29. xml_status(3);
  30. }
  31. $r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1",
  32. dbesc($dfrn_id),
  33. dbesc($challenge)
  34. );
  35. // find the local user who owns this relationship.
  36. $sql_extra = '';
  37. switch($direction) {
  38. case (-1):
  39. $sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
  40. break;
  41. case 0:
  42. $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  43. break;
  44. case 1:
  45. $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  46. break;
  47. default:
  48. xml_status(3);
  49. break; // NOTREACHED
  50. }
  51. // be careful - $importer will contain both the contact information for the contact
  52. // sending us the post, and also the user information for the person receiving it.
  53. // since they are mixed together, it is easy to get them confused.
  54. $r = q("SELECT `contact`.*, `contact`.`uid` AS `importer_uid`,
  55. `contact`.`pubkey` AS `cpubkey`,
  56. `contact`.`prvkey` AS `cprvkey`,
  57. `contact`.`thumb` AS `thumb`,
  58. `contact`.`url` as `url`,
  59. `contact`.`name` as `senderName`,
  60. `user`.*
  61. FROM `contact`
  62. LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
  63. WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  64. AND `user`.`nickname` = '%s' AND `user`.`account_expired` = 0 $sql_extra LIMIT 1",
  65. dbesc($a->argv[1])
  66. );
  67. if(! count($r)) {
  68. logger('dfrn_notify: contact not found for dfrn_id ' . $dfrn_id);
  69. xml_status(3);
  70. //NOTREACHED
  71. }
  72. // $importer in this case contains the contact record for the remote contact joined with the user record of our user.
  73. $importer = $r[0];
  74. if(($writable != (-1)) && ($writable != $importer['writable'])) {
  75. q("UPDATE `contact` SET `writable` = %d WHERE `id` = %d LIMIT 1",
  76. intval($writable),
  77. intval($importer['id'])
  78. );
  79. $importer['writable'] = $writable;
  80. }
  81. // if contact's ssl policy changed, update our links
  82. $ssl_changed = false;
  83. if($ssl_policy == 'self' && strstr($importer['url'],'https:')) {
  84. $ssl_changed = true;
  85. $importer['url'] = str_replace('https:','http:',$importer['url']);
  86. $importer['nurl'] = normalise_link($importer['url']);
  87. $importer['photo'] = str_replace('https:','http:',$importer['photo']);
  88. $importer['thumb'] = str_replace('https:','http:',$importer['thumb']);
  89. $importer['micro'] = str_replace('https:','http:',$importer['micro']);
  90. $importer['request'] = str_replace('https:','http:',$importer['request']);
  91. $importer['notify'] = str_replace('https:','http:',$importer['notify']);
  92. $importer['poll'] = str_replace('https:','http:',$importer['poll']);
  93. $importer['confirm'] = str_replace('https:','http:',$importer['confirm']);
  94. $importer['poco'] = str_replace('https:','http:',$importer['poco']);
  95. }
  96. if($ssl_policy == 'full' && strstr($importer['url'],'http:')) {
  97. $ssl_changed = true;
  98. $importer['url'] = str_replace('http:','https:',$importer['url']);
  99. $importer['nurl'] = normalise_link($importer['url']);
  100. $importer['photo'] = str_replace('http:','https:',$importer['photo']);
  101. $importer['thumb'] = str_replace('http:','https:',$importer['thumb']);
  102. $importer['micro'] = str_replace('http:','https:',$importer['micro']);
  103. $importer['request'] = str_replace('http:','https:',$importer['request']);
  104. $importer['notify'] = str_replace('http:','https:',$importer['notify']);
  105. $importer['poll'] = str_replace('http:','https:',$importer['poll']);
  106. $importer['confirm'] = str_replace('http:','https:',$importer['confirm']);
  107. $importer['poco'] = str_replace('http:','https:',$importer['poco']);
  108. }
  109. if($ssl_changed) {
  110. q("update contact set
  111. url = '%s',
  112. nurl = '%s',
  113. photo = '%s',
  114. thumb = '%s',
  115. micro = '%s',
  116. request = '%s',
  117. notify = '%s',
  118. poll = '%s',
  119. confirm = '%s',
  120. poco = '%s'
  121. where id = %d limit 1",
  122. dbesc($importer['url']),
  123. dbesc($importer['nurl']),
  124. dbesc($importer['photo']),
  125. dbesc($importer['thumb']),
  126. dbesc($importer['micro']),
  127. dbesc($importer['request']),
  128. dbesc($importer['notify']),
  129. dbesc($importer['poll']),
  130. dbesc($importer['confirm']),
  131. dbesc($importer['poco']),
  132. intval($importer['id'])
  133. );
  134. }
  135. logger('dfrn_notify: received notify from ' . $importer['name'] . ' for ' . $importer['username']);
  136. logger('dfrn_notify: data: ' . $data, LOGGER_DATA);
  137. if($dissolve == 1) {
  138. /**
  139. * Relationship is dissolved permanently
  140. */
  141. require_once('include/Contact.php');
  142. contact_remove($importer['id']);
  143. logger('relationship dissolved : ' . $importer['name'] . ' dissolved ' . $importer['username']);
  144. xml_status(0);
  145. }
  146. if(strlen($key)) {
  147. $rawkey = hex2bin(trim($key));
  148. logger('rino: md5 raw key: ' . md5($rawkey));
  149. $final_key = '';
  150. if($dfrn_version >= 2.1) {
  151. if((($importer['duplex']) && strlen($importer['cprvkey'])) || (! strlen($importer['cpubkey']))) {
  152. openssl_private_decrypt($rawkey,$final_key,$importer['cprvkey']);
  153. }
  154. else {
  155. openssl_public_decrypt($rawkey,$final_key,$importer['cpubkey']);
  156. }
  157. }
  158. else {
  159. if((($importer['duplex']) && strlen($importer['cpubkey'])) || (! strlen($importer['cprvkey']))) {
  160. openssl_public_decrypt($rawkey,$final_key,$importer['cpubkey']);
  161. }
  162. else {
  163. openssl_private_decrypt($rawkey,$final_key,$importer['cprvkey']);
  164. }
  165. }
  166. logger('rino: received key : ' . $final_key);
  167. $data = aes_decrypt(hex2bin($data),$final_key);
  168. logger('rino: decrypted data: ' . $data, LOGGER_DATA);
  169. }
  170. $ret = local_delivery($importer,$data);
  171. xml_status($ret);
  172. // NOTREACHED
  173. }
  174. function dfrn_notify_content(&$a) {
  175. if(x($_GET,'dfrn_id')) {
  176. // initial communication from external contact, $direction is their direction.
  177. // If this is a duplex communication, ours will be the opposite.
  178. $dfrn_id = notags(trim($_GET['dfrn_id']));
  179. $dfrn_version = (float) $_GET['dfrn_version'];
  180. logger('dfrn_notify: new notification dfrn_id=' . $dfrn_id);
  181. $direction = (-1);
  182. if(strpos($dfrn_id,':') == 1) {
  183. $direction = intval(substr($dfrn_id,0,1));
  184. $dfrn_id = substr($dfrn_id,2);
  185. }
  186. $hash = random_string();
  187. $status = 0;
  188. $r = q("DELETE FROM `challenge` WHERE `expire` < " . intval(time()));
  189. $r = q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` )
  190. VALUES( '%s', '%s', %d ) ",
  191. dbesc($hash),
  192. dbesc($dfrn_id),
  193. intval(time() + 90 )
  194. );
  195. logger('dfrn_notify: challenge=' . $hash, LOGGER_DEBUG );
  196. $sql_extra = '';
  197. switch($direction) {
  198. case (-1):
  199. $sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
  200. $my_id = $dfrn_id;
  201. break;
  202. case 0:
  203. $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  204. $my_id = '1:' . $dfrn_id;
  205. break;
  206. case 1:
  207. $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  208. $my_id = '0:' . $dfrn_id;
  209. break;
  210. default:
  211. $status = 1;
  212. break; // NOTREACHED
  213. }
  214. $r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
  215. WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `user`.`nickname` = '%s'
  216. AND `user`.`account_expired` = 0 $sql_extra LIMIT 1",
  217. dbesc($a->argv[1])
  218. );
  219. if(! count($r))
  220. $status = 1;
  221. $challenge = '';
  222. $encrypted_id = '';
  223. $id_str = $my_id . '.' . mt_rand(1000,9999);
  224. $prv_key = trim($r[0]['prvkey']);
  225. $pub_key = trim($r[0]['pubkey']);
  226. $dplx = intval($r[0]['duplex']);
  227. if((($dplx) && (strlen($prv_key))) || ((strlen($prv_key)) && (!(strlen($pub_key))))) {
  228. openssl_private_encrypt($hash,$challenge,$prv_key);
  229. openssl_private_encrypt($id_str,$encrypted_id,$prv_key);
  230. }
  231. elseif(strlen($pub_key)) {
  232. openssl_public_encrypt($hash,$challenge,$pub_key);
  233. openssl_public_encrypt($id_str,$encrypted_id,$pub_key);
  234. }
  235. else
  236. $status = 1;
  237. $challenge = bin2hex($challenge);
  238. $encrypted_id = bin2hex($encrypted_id);
  239. $rino = ((function_exists('mcrypt_encrypt')) ? 1 : 0);
  240. $rino_enable = get_config('system','rino_encrypt');
  241. if(! $rino_enable)
  242. $rino = 0;
  243. header("Content-type: text/xml");
  244. echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n"
  245. . '<dfrn_notify>' . "\r\n"
  246. . "\t" . '<status>' . $status . '</status>' . "\r\n"
  247. . "\t" . '<dfrn_version>' . DFRN_PROTOCOL_VERSION . '</dfrn_version>' . "\r\n"
  248. . "\t" . '<rino>' . $rino . '</rino>' . "\r\n"
  249. . "\t" . '<dfrn_id>' . $encrypted_id . '</dfrn_id>' . "\r\n"
  250. . "\t" . '<challenge>' . $challenge . '</challenge>' . "\r\n"
  251. . '</dfrn_notify>' . "\r\n" ;
  252. killme();
  253. }
  254. }