mirror of
https://github.com/onionshare/onionshare.git
synced 2025-05-05 07:55:23 -04:00
Remove v2 legacy onion support, and its corresponding client auth functionality. Update the v3 Client Auth to take its place in settings
This commit is contained in:
parent
4aa6d6f3ec
commit
286d7703d6
68 changed files with 62 additions and 552 deletions
|
@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
from stem.control import Controller
|
||||
from stem import ProtocolError, SocketClosed
|
||||
from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure
|
||||
from Crypto.PublicKey import RSA
|
||||
import base64
|
||||
import nacl.public
|
||||
import os
|
||||
|
@ -167,7 +166,6 @@ class Onion(object):
|
|||
|
||||
# Assigned later if we are using stealth mode
|
||||
self.auth_string = None
|
||||
self.auth_string_v3 = None
|
||||
|
||||
# Keep track of onions where it's important to gracefully close to prevent truncated downloads
|
||||
self.graceful_close_onions = []
|
||||
|
@ -586,22 +584,6 @@ class Onion(object):
|
|||
callable(list_ephemeral_hidden_services) and self.tor_version >= "0.2.7.1"
|
||||
)
|
||||
|
||||
# Do the versions of stem and tor that I'm using support v2 stealth onion services?
|
||||
try:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
{1: 1},
|
||||
basic_auth={"onionshare": None},
|
||||
await_publication=False,
|
||||
key_type="NEW",
|
||||
key_content="RSA1024",
|
||||
)
|
||||
tmp_service_id = res.service_id
|
||||
self.c.remove_ephemeral_hidden_service(tmp_service_id)
|
||||
self.supports_stealth = True
|
||||
except:
|
||||
# ephemeral stealth onion services are not supported
|
||||
self.supports_stealth = False
|
||||
|
||||
# Do the versions of stem and tor that I'm using support v3 stealth onion services?
|
||||
try:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
|
@ -614,20 +596,16 @@ class Onion(object):
|
|||
)
|
||||
tmp_service_id = res.service_id
|
||||
self.c.remove_ephemeral_hidden_service(tmp_service_id)
|
||||
self.supports_stealth_v3 = True
|
||||
self.supports_stealth = True
|
||||
except:
|
||||
# ephemeral v3 stealth onion services are not supported
|
||||
self.supports_stealth_v3 = False
|
||||
self.supports_stealth = False
|
||||
|
||||
# Does this version of Tor support next-gen ('v3') onions?
|
||||
# Note, this is the version of Tor where this bug was fixed:
|
||||
# https://trac.torproject.org/projects/tor/ticket/28619
|
||||
self.supports_v3_onions = self.tor_version >= Version("0.3.5.7")
|
||||
|
||||
# Does this version of Tor support legacy ('v2') onions?
|
||||
# v2 onions have been phased out as of Tor 0.4.6.1.
|
||||
self.supports_v2_onions = self.tor_version < Version("0.4.6.1")
|
||||
|
||||
|
||||
def is_authenticated(self):
|
||||
"""
|
||||
|
@ -650,85 +628,45 @@ class Onion(object):
|
|||
"Your version of Tor is too old, ephemeral onion services are not supported"
|
||||
)
|
||||
raise TorTooOldEphemeral()
|
||||
if mode_settings.get("general", "client_auth") and not self.supports_stealth:
|
||||
print(
|
||||
"Your version of Tor is too old, stealth onion services are not supported"
|
||||
)
|
||||
raise TorTooOldStealth()
|
||||
|
||||
if mode_settings.get("general", "client_auth_v3") and not self.supports_stealth_v3:
|
||||
print(
|
||||
"Your version of Tor is too old, stealth v3 onion services are not supported"
|
||||
)
|
||||
raise TorTooOldStealth()
|
||||
|
||||
auth_cookie = None
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
if mode_settings.get("onion", "hidservauth_string"):
|
||||
auth_cookie = mode_settings.get("onion", "hidservauth_string").split()[
|
||||
2
|
||||
]
|
||||
if auth_cookie:
|
||||
basic_auth = {"onionshare": auth_cookie}
|
||||
else:
|
||||
# If we had neither a scheduled auth cookie or a persistent hidservauth string,
|
||||
# set the cookie to 'None', which means Tor will create one for us
|
||||
basic_auth = {"onionshare": None}
|
||||
else:
|
||||
# Not using client auth at all
|
||||
basic_auth = None
|
||||
client_auth_v3_pub_key = None
|
||||
|
||||
if mode_settings.get("onion", "private_key"):
|
||||
key_content = mode_settings.get("onion", "private_key")
|
||||
if self.is_v2_key(key_content) and self.supports_v2_onions:
|
||||
key_type = "RSA1024"
|
||||
else:
|
||||
# Assume it was a v3 key. Stem will throw an error if it's something illegible
|
||||
key_type = "ED25519-V3"
|
||||
key_type = "ED25519-V3"
|
||||
else:
|
||||
key_content = "ED25519-V3"
|
||||
key_type = "NEW"
|
||||
# Work out if we can support v3 onion services, which are preferred
|
||||
if self.supports_v3_onions and not mode_settings.get("general", "legacy") and not self.supports_v2_onions:
|
||||
key_content = "ED25519-V3"
|
||||
else:
|
||||
# fall back to v2 onion services
|
||||
key_content = "RSA1024"
|
||||
|
||||
if (
|
||||
(key_type == "ED25519-V3"
|
||||
or key_content == "ED25519-V3")
|
||||
and mode_settings.get("general", "client_auth_v3")
|
||||
):
|
||||
if key_type == "NEW" or not mode_settings.get("onion", "client_auth_v3_priv_key"):
|
||||
# Generate a new key pair for Client Auth on new onions, or if
|
||||
# it's a persistent onion but for some reason we don't them
|
||||
client_auth_v3_priv_key_raw = nacl.public.PrivateKey.generate()
|
||||
client_auth_v3_priv_key = self.key_str(client_auth_v3_priv_key_raw)
|
||||
client_auth_v3_pub_key = self.key_str(client_auth_v3_priv_key_raw.public_key)
|
||||
else:
|
||||
# These should have been saved in settings from the previous run of a persistent onion
|
||||
client_auth_v3_priv_key = mode_settings.get("onion", "client_auth_v3_priv_key")
|
||||
client_auth_v3_pub_key = mode_settings.get("onion", "client_auth_v3_pub_key")
|
||||
|
||||
self.common.log(
|
||||
"Onion", "start_onion-service", f"ClientAuthV3 private key (for Tor Browser: {client_auth_v3_priv_key}"
|
||||
)
|
||||
self.common.log(
|
||||
"Onion", "start_onion-service", f"ClientAuthV3 public key (for Onion service: {client_auth_v3_pub_key}"
|
||||
)
|
||||
# basic_auth is only for v2 onions
|
||||
basic_auth = None
|
||||
|
||||
debug_message = f"key_type={key_type}"
|
||||
if key_type == "NEW":
|
||||
debug_message += f", key_content={key_content}"
|
||||
self.common.log("Onion", "start_onion_service", debug_message)
|
||||
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
if not self.supports_stealth:
|
||||
print(
|
||||
"Your version of Tor is too old, stealth onion services are not supported"
|
||||
)
|
||||
raise TorTooOldStealth()
|
||||
else:
|
||||
if key_type == "NEW" or not mode_settings.get("onion", "client_auth_v3_priv_key"):
|
||||
# Generate a new key pair for Client Auth on new onions, or if
|
||||
# it's a persistent onion but for some reason we don't them
|
||||
client_auth_v3_priv_key_raw = nacl.public.PrivateKey.generate()
|
||||
client_auth_v3_priv_key = self.key_str(client_auth_v3_priv_key_raw)
|
||||
client_auth_v3_pub_key = self.key_str(client_auth_v3_priv_key_raw.public_key)
|
||||
else:
|
||||
# These should have been saved in settings from the previous run of a persistent onion
|
||||
client_auth_v3_priv_key = mode_settings.get("onion", "client_auth_v3_priv_key")
|
||||
client_auth_v3_pub_key = mode_settings.get("onion", "client_auth_v3_pub_key")
|
||||
else:
|
||||
client_auth_v3_priv_key = None
|
||||
client_auth_v3_pub_key = None
|
||||
|
||||
try:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
{80: port},
|
||||
await_publication=await_publication,
|
||||
basic_auth=basic_auth,
|
||||
basic_auth=None,
|
||||
key_type=key_type,
|
||||
key_content=key_content,
|
||||
client_auth_v3=client_auth_v3_pub_key,
|
||||
|
@ -750,25 +688,20 @@ class Onion(object):
|
|||
# Save the private key and hidservauth string
|
||||
if not mode_settings.get("onion", "private_key"):
|
||||
mode_settings.set("onion", "private_key", res.private_key)
|
||||
if mode_settings.get("general", "client_auth") and not mode_settings.get(
|
||||
"onion", "hidservauth_string"
|
||||
):
|
||||
auth_cookie = list(res.client_auth.values())[0]
|
||||
self.auth_string = f"HidServAuth {onion_host} {auth_cookie}"
|
||||
mode_settings.set("onion", "hidservauth_string", self.auth_string)
|
||||
|
||||
# If using V3 onions and Client Auth, save both the private and public key
|
||||
# because we need to send the public key to ADD_ONION, and the private key
|
||||
# to the other user for their Tor Browser.
|
||||
if mode_settings.get("general", "client_auth_v3"):
|
||||
# because we need to send the public key to ADD_ONION (if we restart this
|
||||
# same share at a later date), and the private key to the other user for
|
||||
# their Tor Browser.
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
mode_settings.set("onion", "client_auth_v3_priv_key", client_auth_v3_priv_key)
|
||||
mode_settings.set("onion", "client_auth_v3_pub_key", client_auth_v3_pub_key)
|
||||
# If we were pasting the client auth directly into the filesystem behind a Tor client,
|
||||
# it would need to be in the format below. However, let's just set the private key
|
||||
# by itself, as this can be pasted directly into Tor Browser, which is likely to
|
||||
# be the most common use case.
|
||||
# self.auth_string_v3 = f"{onion_host}:x25519:{client_auth_v3_priv_key}"
|
||||
self.auth_string_v3 = client_auth_v3_priv_key
|
||||
# self.auth_string = f"{onion_host}:x25519:{client_auth_v3_priv_key}"
|
||||
self.auth_string = client_auth_v3_priv_key
|
||||
|
||||
return onion_host
|
||||
|
||||
|
@ -900,15 +833,3 @@ class Onion(object):
|
|||
return ("127.0.0.1", 9150)
|
||||
else:
|
||||
return (self.settings.get("socks_address"), self.settings.get("socks_port"))
|
||||
|
||||
def is_v2_key(self, key):
|
||||
"""
|
||||
Helper function for determining if a key is RSA1024 (v2) or not.
|
||||
"""
|
||||
try:
|
||||
# Import the key
|
||||
key = RSA.importKey(base64.b64decode(key))
|
||||
# Is this a v2 Onion key? (1024 bits) If so, we should keep using it.
|
||||
return key.n.bit_length() == 1024
|
||||
except:
|
||||
return False
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue