TestBootstrapper.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import hashlib
  2. import os
  3. import pytest
  4. from Bootstrapper import BootstrapperPlugin
  5. from Bootstrapper.BootstrapperDb import BootstrapperDb
  6. from Peer import Peer
  7. from Crypt import CryptRsa
  8. from util import helper
  9. @pytest.fixture()
  10. def bootstrapper_db(request):
  11. BootstrapperPlugin.db.close()
  12. BootstrapperPlugin.db = BootstrapperDb()
  13. BootstrapperPlugin.db.createTables() # Reset db
  14. BootstrapperPlugin.db.cur.logging = True
  15. def cleanup():
  16. BootstrapperPlugin.db.close()
  17. os.unlink(BootstrapperPlugin.db.db_path)
  18. request.addfinalizer(cleanup)
  19. return BootstrapperPlugin.db
  20. @pytest.mark.usefixtures("resetSettings")
  21. class TestBootstrapper:
  22. def testBootstrapperDb(self, file_server, bootstrapper_db):
  23. ip_type = helper.getIpType(file_server.ip)
  24. peer = Peer(file_server.ip, 1544, connection_server=file_server)
  25. hash1 = hashlib.sha256("site1").digest()
  26. hash2 = hashlib.sha256("site2").digest()
  27. hash3 = hashlib.sha256("site3").digest()
  28. # Verify empty result
  29. res = peer.request("announce", {
  30. "hashes": [hash1, hash2],
  31. "port": 15441, "need_types": [ip_type], "need_num": 10, "add": [ip_type]
  32. })
  33. assert len(res["peers"][0][ip_type]) == 0 # Empty result
  34. # Verify added peer on previous request
  35. bootstrapper_db.peerAnnounce(ip_type, file_server.ip_external, port=15441, hashes=[hash1, hash2], delete_missing_hashes=True)
  36. res = peer.request("announce", {
  37. "hashes": [hash1, hash2],
  38. "port": 15441, "need_types": [ip_type], "need_num": 10, "add": [ip_type]
  39. })
  40. assert len(res["peers"][0][ip_type]) == 1
  41. assert len(res["peers"][1][ip_type]) == 1
  42. # hash2 deleted from 1.2.3.4
  43. bootstrapper_db.peerAnnounce(ip_type, file_server.ip_external, port=15441, hashes=[hash1], delete_missing_hashes=True)
  44. res = peer.request("announce", {
  45. "hashes": [hash1, hash2],
  46. "port": 15441, "need_types": [ip_type], "need_num": 10, "add": [ip_type]
  47. })
  48. assert len(res["peers"][0][ip_type]) == 1
  49. assert len(res["peers"][1][ip_type]) == 0
  50. # Announce 3 hash again
  51. bootstrapper_db.peerAnnounce(ip_type, file_server.ip_external, port=15441, hashes=[hash1, hash2, hash3], delete_missing_hashes=True)
  52. res = peer.request("announce", {
  53. "hashes": [hash1, hash2, hash3],
  54. "port": 15441, "need_types": [ip_type], "need_num": 10, "add": [ip_type]
  55. })
  56. assert len(res["peers"][0][ip_type]) == 1
  57. assert len(res["peers"][1][ip_type]) == 1
  58. assert len(res["peers"][2][ip_type]) == 1
  59. # Single hash announce
  60. res = peer.request("announce", {
  61. "hashes": [hash1], "port": 15441, "need_types": [ip_type], "need_num": 10, "add": [ip_type]
  62. })
  63. assert len(res["peers"][0][ip_type]) == 1
  64. # Test DB cleanup
  65. assert map(lambda row: row[0], bootstrapper_db.execute("SELECT address FROM peer").fetchall()) == [file_server.ip_external] # 127.0.0.1 never get added to db
  66. # Delete peers
  67. bootstrapper_db.execute("DELETE FROM peer WHERE address = ?", [file_server.ip_external])
  68. assert bootstrapper_db.execute("SELECT COUNT(*) AS num FROM peer_to_hash").fetchone()["num"] == 0
  69. assert bootstrapper_db.execute("SELECT COUNT(*) AS num FROM hash").fetchone()["num"] == 3 # 3 sites
  70. assert bootstrapper_db.execute("SELECT COUNT(*) AS num FROM peer").fetchone()["num"] == 0 # 0 peer
  71. def testPassive(self, file_server, bootstrapper_db):
  72. peer = Peer(file_server.ip, 1544, connection_server=file_server)
  73. ip_type = helper.getIpType(file_server.ip)
  74. hash1 = hashlib.sha256("hash1").digest()
  75. bootstrapper_db.peerAnnounce(ip_type, address=None, port=15441, hashes=[hash1])
  76. res = peer.request("announce", {
  77. "hashes": [hash1], "port": 15441, "need_types": [ip_type], "need_num": 10, "add": []
  78. })
  79. assert len(res["peers"][0]["ipv4"]) == 0 # Empty result
  80. def testAddOnion(self, file_server, site, bootstrapper_db, tor_manager):
  81. onion1 = tor_manager.addOnion()
  82. onion2 = tor_manager.addOnion()
  83. peer = Peer(file_server.ip, 1544, connection_server=file_server)
  84. hash1 = hashlib.sha256("site1").digest()
  85. hash2 = hashlib.sha256("site2").digest()
  86. hash3 = hashlib.sha256("site3").digest()
  87. bootstrapper_db.peerAnnounce(ip_type="ipv4", address="1.2.3.4", port=1234, hashes=[hash1, hash2, hash3])
  88. res = peer.request("announce", {
  89. "onions": [onion1, onion1, onion2],
  90. "hashes": [hash1, hash2, hash3], "port": 15441, "need_types": ["ipv4", "onion"], "need_num": 10, "add": ["onion"]
  91. })
  92. assert len(res["peers"][0]["ipv4"]) == 1
  93. # Onion address not added yet
  94. site_peers = bootstrapper_db.peerList(address="1.2.3.4", port=1234, hash=hash1)
  95. assert len(site_peers["onion"]) == 0
  96. assert "onion_sign_this" in res
  97. # Sign the nonces
  98. sign1 = CryptRsa.sign(res["onion_sign_this"], tor_manager.getPrivatekey(onion1))
  99. sign2 = CryptRsa.sign(res["onion_sign_this"], tor_manager.getPrivatekey(onion2))
  100. # Bad sign (different address)
  101. res = peer.request("announce", {
  102. "onions": [onion1], "onion_sign_this": res["onion_sign_this"],
  103. "onion_signs": {tor_manager.getPublickey(onion2): sign2},
  104. "hashes": [hash1], "port": 15441, "need_types": ["ipv4", "onion"], "need_num": 10, "add": ["onion"]
  105. })
  106. assert "onion_sign_this" in res
  107. site_peers1 = bootstrapper_db.peerList(address="1.2.3.4", port=1234, hash=hash1)
  108. assert len(site_peers1["onion"]) == 0 # Not added
  109. # Bad sign (missing one)
  110. res = peer.request("announce", {
  111. "onions": [onion1, onion1, onion2], "onion_sign_this": res["onion_sign_this"],
  112. "onion_signs": {tor_manager.getPublickey(onion1): sign1},
  113. "hashes": [hash1, hash2, hash3], "port": 15441, "need_types": ["ipv4", "onion"], "need_num": 10, "add": ["onion"]
  114. })
  115. assert "onion_sign_this" in res
  116. site_peers1 = bootstrapper_db.peerList(address="1.2.3.4", port=1234, hash=hash1)
  117. assert len(site_peers1["onion"]) == 0 # Not added
  118. # Good sign
  119. res = peer.request("announce", {
  120. "onions": [onion1, onion1, onion2], "onion_sign_this": res["onion_sign_this"],
  121. "onion_signs": {tor_manager.getPublickey(onion1): sign1, tor_manager.getPublickey(onion2): sign2},
  122. "hashes": [hash1, hash2, hash3], "port": 15441, "need_types": ["ipv4", "onion"], "need_num": 10, "add": ["onion"]
  123. })
  124. assert "onion_sign_this" not in res
  125. # Onion addresses added
  126. site_peers1 = bootstrapper_db.peerList(address="1.2.3.4", port=1234, hash=hash1)
  127. assert len(site_peers1["onion"]) == 1
  128. site_peers2 = bootstrapper_db.peerList(address="1.2.3.4", port=1234, hash=hash2)
  129. assert len(site_peers2["onion"]) == 1
  130. site_peers3 = bootstrapper_db.peerList(address="1.2.3.4", port=1234, hash=hash3)
  131. assert len(site_peers3["onion"]) == 1
  132. assert site_peers1["onion"][0] == site_peers2["onion"][0]
  133. assert site_peers2["onion"][0] != site_peers3["onion"][0]
  134. assert helper.unpackOnionAddress(site_peers1["onion"][0])[0] == onion1 + ".onion"
  135. assert helper.unpackOnionAddress(site_peers2["onion"][0])[0] == onion1 + ".onion"
  136. assert helper.unpackOnionAddress(site_peers3["onion"][0])[0] == onion2 + ".onion"
  137. tor_manager.delOnion(onion1)
  138. tor_manager.delOnion(onion2)
  139. def testRequestPeers(self, file_server, site, bootstrapper_db, tor_manager):
  140. site.connection_server = file_server
  141. file_server.tor_manager = tor_manager
  142. hash = hashlib.sha256(site.address).digest()
  143. # Request peers from tracker
  144. assert len(site.peers) == 0
  145. bootstrapper_db.peerAnnounce(ip_type="ipv4", address="1.2.3.4", port=1234, hashes=[hash])
  146. site.announcer.announceTracker("zero://%s:%s" % (file_server.ip, file_server.port))
  147. assert len(site.peers) == 1
  148. # Test onion address store
  149. bootstrapper_db.peerAnnounce(ip_type="onion", address="bka4ht2bzxchy44r", port=1234, hashes=[hash], onion_signed=True)
  150. site.announcer.announceTracker("zero://%s:%s" % (file_server.ip, file_server.port))
  151. assert len(site.peers) == 2
  152. assert "bka4ht2bzxchy44r.onion:1234" in site.peers
  153. @pytest.mark.slow
  154. def testAnnounce(self, file_server, tor_manager):
  155. file_server.tor_manager = tor_manager
  156. hash1 = hashlib.sha256("1Nekos4fiBqfcazyG1bAxdBT5oBvA76Z").digest()
  157. hash2 = hashlib.sha256("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr").digest()
  158. peer = Peer("zero.booth.moe", 443, connection_server=file_server)
  159. assert peer.request("ping")
  160. peer = Peer("boot3rdez4rzn36x.onion", 15441, connection_server=file_server)
  161. assert peer.request("ping")
  162. res = peer.request("announce", {
  163. "hashes": [hash1, hash2],
  164. "port": 15441, "need_types": ["ip4", "onion"], "need_num": 100, "add": [""]
  165. })
  166. assert res
  167. def testBackwardCompatibility(self, file_server, bootstrapper_db):
  168. peer = Peer(file_server.ip, 1544, connection_server=file_server)
  169. hash1 = hashlib.sha256("site1").digest()
  170. bootstrapper_db.peerAnnounce("ipv4", file_server.ip_external, port=15441, hashes=[hash1], delete_missing_hashes=True)
  171. # Test with ipv4 need type
  172. res = peer.request("announce", {
  173. "hashes": [hash1],
  174. "port": 15441, "need_types": ["ipv4"], "need_num": 10, "add": []
  175. })
  176. assert len(res["peers"][0]["ipv4"]) == 1
  177. # Test with ip4 need type
  178. res = peer.request("announce", {
  179. "hashes": [hash1],
  180. "port": 15441, "need_types": ["ip4"], "need_num": 10, "add": []
  181. })
  182. assert len(res["peers"][0]["ip4"]) == 1