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.
 
 
 
 
 
 

314 lines
9.7 KiB

  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. }