onionshare_cli 2.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. onionshare_cli/__init__.py +538 -0
  2. onionshare_cli/censorship.py +311 -0
  3. onionshare_cli/common.py +624 -0
  4. onionshare_cli/meek.py +199 -0
  5. onionshare_cli/mode_settings.py +150 -0
  6. onionshare_cli/onion.py +964 -0
  7. onionshare_cli/onionshare.py +91 -0
  8. onionshare_cli/resources/static/css/style.css +432 -0
  9. onionshare_cli/resources/static/img/ajax.gif +0 -0
  10. onionshare_cli/resources/static/img/favicon.ico +0 -0
  11. onionshare_cli/resources/static/img/logo.png +0 -0
  12. onionshare_cli/resources/static/img/logo_large.png +0 -0
  13. onionshare_cli/resources/static/img/web_file.png +0 -0
  14. onionshare_cli/resources/static/img/web_folder.png +0 -0
  15. onionshare_cli/resources/static/js/chat.js +188 -0
  16. onionshare_cli/resources/static/js/jquery-3.5.1.min.js +2 -0
  17. onionshare_cli/resources/static/js/receive.js +141 -0
  18. onionshare_cli/resources/static/js/send.js +79 -0
  19. onionshare_cli/resources/static/js/socket.io.js +9 -0
  20. onionshare_cli/resources/static/js/socket.io.min.js +7 -0
  21. onionshare_cli/resources/templates/403.html +21 -0
  22. onionshare_cli/resources/templates/404.html +21 -0
  23. onionshare_cli/resources/templates/405.html +21 -0
  24. onionshare_cli/resources/templates/500.html +21 -0
  25. onionshare_cli/resources/templates/chat.html +47 -0
  26. onionshare_cli/resources/templates/denied.html +14 -0
  27. onionshare_cli/resources/templates/listing.html +60 -0
  28. onionshare_cli/resources/templates/receive.html +66 -0
  29. onionshare_cli/resources/templates/send.html +70 -0
  30. onionshare_cli/resources/templates/thankyou.html +27 -0
  31. onionshare_cli/resources/torrc_template +12 -0
  32. onionshare_cli/resources/torrc_template-meek_lite_azure +2 -0
  33. onionshare_cli/resources/torrc_template-obfs4 +12 -0
  34. onionshare_cli/resources/torrc_template-snowflake +3 -0
  35. onionshare_cli/resources/version.txt +1 -0
  36. onionshare_cli/resources/wordlist.txt +7776 -0
  37. onionshare_cli/settings.py +209 -0
  38. onionshare_cli/web/__init__.py +21 -0
  39. onionshare_cli/web/chat_mode.py +190 -0
  40. onionshare_cli/web/receive_mode.py +630 -0
  41. onionshare_cli/web/send_base_mode.py +360 -0
  42. onionshare_cli/web/share_mode.py +599 -0
  43. onionshare_cli/web/web.py +409 -0
  44. onionshare_cli/web/website_mode.py +122 -0
  45. onionshare_cli-2.6.1.dist-info/METADATA +44 -0
  46. onionshare_cli-2.6.1.dist-info/RECORD +48 -0
  47. onionshare_cli-2.6.1.dist-info/WHEEL +4 -0
  48. onionshare_cli-2.6.1.dist-info/entry_points.txt +3 -0
onionshare_cli/meek.py ADDED
@@ -0,0 +1,199 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ OnionShare | https://onionshare.org/
4
+
5
+ Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ """
20
+ import os
21
+ import subprocess
22
+ import time
23
+
24
+
25
+ class Meek(object):
26
+ """
27
+ The Meek object starts the meek-client as a subprocess.
28
+ This process is used to do domain-fronting to connect to
29
+ the Tor APIs for censorship circumvention and retrieving
30
+ bridges, before connecting to Tor.
31
+ """
32
+
33
+ def __init__(self, common, get_tor_paths=None):
34
+ """
35
+ Set up the Meek object
36
+ """
37
+
38
+ self.common = common
39
+ self.common.log("Meek", "__init__")
40
+
41
+ # Set the path of the meek binary
42
+ if not get_tor_paths:
43
+ get_tor_paths = self.common.get_tor_paths
44
+ (
45
+ self.tor_path,
46
+ self.tor_geo_ip_file_path,
47
+ self.tor_geo_ipv6_file_path,
48
+ self.obfs4proxy_file_path,
49
+ self.snowflake_file_path,
50
+ self.meek_client_file_path,
51
+ ) = get_tor_paths()
52
+
53
+ self.meek_proxies = {}
54
+ self.meek_url = "https://moat.torproject.org.global.prod.fastly.net/"
55
+ self.meek_front = "cdn.sstatic.net"
56
+ self.meek_env = {
57
+ "TOR_PT_MANAGED_TRANSPORT_VER": "1",
58
+ "TOR_PT_CLIENT_TRANSPORTS": "meek",
59
+ }
60
+ self.meek_host = "127.0.0.1"
61
+ self.meek_port = None
62
+
63
+ def start(self):
64
+ """
65
+ Start the Meek Client and populate the SOCKS proxies dict
66
+ for use with requests to the Tor Moat API.
67
+ """
68
+ # Abort early if we can't find the Meek client
69
+ if self.meek_client_file_path is None or not os.path.exists(
70
+ self.meek_client_file_path
71
+ ):
72
+ raise MeekNotFound(self.common)
73
+
74
+ # Start the Meek Client as a subprocess.
75
+ self.common.log("Meek", "start", "Starting meek client")
76
+
77
+ if self.common.platform == "Windows":
78
+ env = os.environ.copy()
79
+ for key in self.meek_env:
80
+ env[key] = self.meek_env[key]
81
+
82
+ # In Windows, hide console window when opening meek-client.exe subprocess
83
+ startupinfo = subprocess.STARTUPINFO()
84
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
85
+ self.meek_proc = subprocess.Popen(
86
+ [
87
+ self.meek_client_file_path,
88
+ "--url",
89
+ self.meek_url,
90
+ "--front",
91
+ self.meek_front,
92
+ ],
93
+ stdout=subprocess.PIPE,
94
+ stderr=subprocess.PIPE,
95
+ startupinfo=startupinfo,
96
+ bufsize=1,
97
+ env=env,
98
+ text=True,
99
+ )
100
+ else:
101
+ self.meek_proc = subprocess.Popen(
102
+ [
103
+ self.meek_client_file_path,
104
+ "--url",
105
+ self.meek_url,
106
+ "--front",
107
+ self.meek_front,
108
+ ],
109
+ stdout=subprocess.PIPE,
110
+ stderr=subprocess.PIPE,
111
+ bufsize=1,
112
+ env=self.meek_env,
113
+ # Using universal_newlines instead of text because the snap package using python < 3.7
114
+ universal_newlines=True,
115
+ )
116
+
117
+ # Obtain the host and port that meek is running on
118
+ for line in iter(self.meek_proc.stdout.readline, b""):
119
+ if "CMETHOD meek socks5" in line:
120
+ self.meek_host = line.split(" ")[3].split(":")[0]
121
+ self.meek_port = line.split(" ")[3].split(":")[1]
122
+ self.common.log(
123
+ "Meek",
124
+ "start",
125
+ f"Meek running on {self.meek_host}:{self.meek_port}",
126
+ )
127
+ break
128
+
129
+ if "CMETHOD-ERROR" in line:
130
+ self.cleanup()
131
+ raise MeekNotRunning(self.common, line)
132
+ break
133
+
134
+ if self.meek_port:
135
+ self.meek_proxies = {
136
+ "http": f"socks5h://{self.meek_host}:{self.meek_port}",
137
+ "https": f"socks5h://{self.meek_host}:{self.meek_port}",
138
+ }
139
+ else:
140
+ self.cleanup()
141
+ raise MeekNotRunning(self.common, "Could not obtain the meek port")
142
+
143
+ def cleanup(self):
144
+ """
145
+ Kill any meek subprocesses.
146
+ """
147
+ self.common.log("Meek", "cleanup")
148
+
149
+ if self.meek_proc:
150
+ self.meek_proc.terminate()
151
+ time.sleep(0.2)
152
+ if self.meek_proc.poll() is None:
153
+ self.common.log(
154
+ "Meek",
155
+ "cleanup",
156
+ "Tried to terminate meek-client process but it's still running",
157
+ )
158
+ try:
159
+ self.meek_proc.kill()
160
+ time.sleep(0.2)
161
+ if self.meek_proc.poll() is None:
162
+ self.common.log(
163
+ "Meek",
164
+ "cleanup",
165
+ "Tried to kill meek-client process but it's still running",
166
+ )
167
+ except Exception:
168
+ self.common.log(
169
+ "Meek", "cleanup", "Exception while killing meek-client process"
170
+ )
171
+ self.meek_proc = None
172
+
173
+ # Reset other Meek settings
174
+ self.meek_proxies = {}
175
+ self.meek_port = None
176
+
177
+
178
+ class MeekNotRunning(Exception):
179
+ """
180
+ We were unable to start Meek or obtain the port
181
+ number it started on, in order to do domain fronting.
182
+ """
183
+
184
+ def __init__(self, common, info=None):
185
+ self.common = common
186
+ msg = "Meek experienced an error starting up"
187
+ if info:
188
+ msg = msg + f": {info}"
189
+ self.common.log("MeekNotRunning", "__init__", msg)
190
+
191
+
192
+ class MeekNotFound(Exception):
193
+ """
194
+ We were unable to find the Meek Client binary.
195
+ """
196
+
197
+ def __init__(self, common):
198
+ self.common = common
199
+ self.common.log("MeekNotFound", "__init__", "Could not find the meek binary")
@@ -0,0 +1,150 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ OnionShare | https://onionshare.org/
4
+
5
+ Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ """
20
+ import os
21
+ import json
22
+ import platform
23
+
24
+ if platform.system() == "Darwin":
25
+ import pwd
26
+
27
+
28
+ class ModeSettings:
29
+ """
30
+ This stores the settings for a single instance of an OnionShare mode. In CLI there
31
+ is only one ModeSettings, and in the GUI there is a separate ModeSettings for each tab
32
+ """
33
+
34
+ def __init__(self, common, filename=None, id=None):
35
+ self.common = common
36
+
37
+ self.default_settings = {
38
+ "onion": {
39
+ "private_key": None,
40
+ "client_auth_priv_key": None,
41
+ "client_auth_pub_key": None,
42
+ },
43
+ "persistent": {"mode": None, "enabled": False},
44
+ "general": {
45
+ "title": None,
46
+ "public": False,
47
+ "autostart_timer": False,
48
+ "autostop_timer": False,
49
+ "service_id": None,
50
+ },
51
+ "share": {"autostop_sharing": True, "filenames": []},
52
+ "receive": {
53
+ "data_dir": self.build_default_receive_data_dir(),
54
+ "webhook_url": None,
55
+ "disable_text": False,
56
+ "disable_files": False,
57
+ },
58
+ "website": {"disable_csp": False, "custom_csp": None, "filenames": []},
59
+ "chat": {},
60
+ }
61
+ self._settings = {}
62
+
63
+ self.just_created = False
64
+ if id:
65
+ self.id = id
66
+ else:
67
+ self.id = self.common.build_password(3)
68
+
69
+ self.load(filename)
70
+
71
+ def fill_in_defaults(self):
72
+ """
73
+ If there are any missing settings from self._settings, replace them with
74
+ their default values.
75
+ """
76
+ for key in self.default_settings:
77
+ if key in self._settings:
78
+ for inner_key in self.default_settings[key]:
79
+ if inner_key not in self._settings[key]:
80
+ self._settings[key][inner_key] = self.default_settings[key][
81
+ inner_key
82
+ ]
83
+ else:
84
+ self._settings[key] = self.default_settings[key]
85
+
86
+ def get(self, group, key):
87
+ return self._settings[group][key]
88
+
89
+ def set(self, group, key, val):
90
+ self._settings[group][key] = val
91
+ self.common.log(
92
+ "ModeSettings", "set", f"updating {self.id}: {group}.{key} = {val}"
93
+ )
94
+ self.save()
95
+
96
+ def build_default_receive_data_dir(self):
97
+ """
98
+ Returns the path of the default Downloads directory for receive mode.
99
+ """
100
+
101
+ if self.common.platform == "Darwin":
102
+ # We can't use os.path.expanduser() in macOS because in the sandbox it
103
+ # returns the path to the sandboxed homedir
104
+ real_homedir = pwd.getpwuid(os.getuid()).pw_dir
105
+ return os.path.join(real_homedir, "OnionShare")
106
+ elif self.common.platform == "Windows":
107
+ # On Windows, os.path.expanduser() needs to use backslash, or else it
108
+ # retains the forward slash, which breaks opening the folder in explorer.
109
+ return os.path.expanduser("~\\OnionShare")
110
+ else:
111
+ # All other OSes
112
+ return os.path.expanduser("~/OnionShare")
113
+
114
+ def load(self, filename=None):
115
+ # Load persistent settings from disk. If the file doesn't exist, create it
116
+ if filename:
117
+ self.filename = filename
118
+ else:
119
+ self.filename = os.path.join(
120
+ self.common.build_persistent_dir(), f"{self.id}.json"
121
+ )
122
+
123
+ if os.path.exists(self.filename):
124
+ try:
125
+ with open(self.filename, "r") as f:
126
+ self._settings = json.load(f)
127
+ self.fill_in_defaults()
128
+ self.common.log("ModeSettings", "load", f"loaded {self.filename}")
129
+ return
130
+ except Exception:
131
+ pass
132
+
133
+ # If loading settings didn't work, create the settings file
134
+ self.common.log("ModeSettings", "load", f"creating {self.filename}")
135
+ self.fill_in_defaults()
136
+ self.just_created = True
137
+
138
+ def save(self):
139
+ # Save persistent setting to disk
140
+ if not self.get("persistent", "enabled"):
141
+ return
142
+
143
+ if self.filename:
144
+ with open(self.filename, "w") as file:
145
+ file.write(json.dumps(self._settings, indent=2))
146
+
147
+ def delete(self):
148
+ # Delete the file from disk
149
+ if os.path.exists(self.filename):
150
+ os.remove(self.filename)