Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21d1c7ebfe | ||
|
|
996a43be5b | ||
|
|
9e8127e577 | ||
|
|
cfcd324a11 | ||
|
|
6872634bf4 | ||
|
|
091090c6fd | ||
|
|
bd4fff4200 | ||
|
|
52dfd0be05 | ||
|
|
60f1737115 | ||
|
|
7a5d6baf02 | ||
|
|
44a332a77b |
@@ -16,7 +16,7 @@ from hippolyzer.lib.proxy.addons import AddonManager
|
||||
from hippolyzer.lib.proxy.addon_utils import BaseAddon
|
||||
from hippolyzer.lib.proxy.ca_utils import setup_ca
|
||||
from hippolyzer.lib.proxy.commands import handle_command
|
||||
from hippolyzer.lib.proxy.http_proxy import create_http_proxy, create_proxy_master, HTTPFlowContext
|
||||
from hippolyzer.lib.proxy.http_proxy import create_http_proxy, HTTPFlowContext
|
||||
from hippolyzer.lib.proxy.http_event_manager import MITMProxyEventManager
|
||||
from hippolyzer.lib.proxy.lludp_proxy import SLSOCKS5Server
|
||||
from hippolyzer.lib.base.message.message import Message
|
||||
@@ -85,12 +85,12 @@ class REPLAddon(BaseAddon):
|
||||
AddonManager.spawn_repl()
|
||||
|
||||
|
||||
def run_http_proxy_process(proxy_host, http_proxy_port, flow_context: HTTPFlowContext):
|
||||
def run_http_proxy_process(proxy_host, http_proxy_port, flow_context: HTTPFlowContext, ssl_insecure=False):
|
||||
mitm_loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(mitm_loop)
|
||||
|
||||
async def mitmproxy_loop():
|
||||
mitmproxy_master = create_http_proxy(proxy_host, http_proxy_port, flow_context)
|
||||
mitmproxy_master = create_http_proxy(proxy_host, http_proxy_port, flow_context, ssl_insecure=ssl_insecure)
|
||||
gc.freeze()
|
||||
await mitmproxy_master.run()
|
||||
|
||||
@@ -98,7 +98,7 @@ def run_http_proxy_process(proxy_host, http_proxy_port, flow_context: HTTPFlowCo
|
||||
|
||||
|
||||
def start_proxy(session_manager: SessionManager, extra_addons: Optional[list] = None,
|
||||
extra_addon_paths: Optional[list] = None, proxy_host=None):
|
||||
extra_addon_paths: Optional[list] = None, proxy_host=None, ssl_insecure=False):
|
||||
extra_addons = extra_addons or []
|
||||
extra_addon_paths = extra_addon_paths or []
|
||||
extra_addons.append(SelectionManagerAddon())
|
||||
@@ -123,17 +123,13 @@ def start_proxy(session_manager: SessionManager, extra_addons: Optional[list] =
|
||||
# TODO: argparse
|
||||
if len(sys.argv) == 3:
|
||||
if sys.argv[1] == "--setup-ca":
|
||||
try:
|
||||
mitmproxy_master = create_http_proxy(proxy_host, http_proxy_port, flow_context)
|
||||
except mitmproxy.exceptions.MitmproxyException:
|
||||
# Proxy already running, create the master so we don't try to bind to a port
|
||||
mitmproxy_master = create_proxy_master(proxy_host, http_proxy_port, flow_context)
|
||||
mitmproxy_master = create_http_proxy(proxy_host, http_proxy_port, flow_context)
|
||||
setup_ca(sys.argv[2], mitmproxy_master)
|
||||
return sys.exit(0)
|
||||
|
||||
http_proc = multiprocessing.Process(
|
||||
target=run_http_proxy_process,
|
||||
args=(proxy_host, http_proxy_port, flow_context),
|
||||
args=(proxy_host, http_proxy_port, flow_context, ssl_insecure),
|
||||
daemon=True,
|
||||
)
|
||||
http_proc.start()
|
||||
|
||||
@@ -42,7 +42,7 @@ from hippolyzer.lib.base.network.transport import Direction, SocketUDPTransport
|
||||
from hippolyzer.lib.proxy.addons import BaseInteractionManager, AddonManager
|
||||
from hippolyzer.lib.proxy.ca_utils import setup_ca_everywhere
|
||||
from hippolyzer.lib.proxy.caps_client import ProxyCapsClient
|
||||
from hippolyzer.lib.proxy.http_proxy import create_proxy_master, HTTPFlowContext
|
||||
from hippolyzer.lib.proxy.http_proxy import create_http_proxy, HTTPFlowContext
|
||||
from hippolyzer.lib.proxy.message_logger import LLUDPMessageLogEntry, AbstractMessageLogEntry, WrappingMessageLogger, \
|
||||
import_log_entries, export_log_entries
|
||||
from hippolyzer.lib.proxy.region import ProxiedRegion
|
||||
@@ -275,9 +275,11 @@ class MessageLogWindow(QtWidgets.QMainWindow):
|
||||
self.actionOpenMessageBuilder.triggered.connect(self._openMessageBuilder)
|
||||
|
||||
self.actionProxyRemotelyAccessible.setChecked(self.settings.REMOTELY_ACCESSIBLE)
|
||||
self.actionProxySSLInsecure.setChecked(self.settings.SSL_INSECURE)
|
||||
self.actionUseViewerObjectCache.setChecked(self.settings.USE_VIEWER_OBJECT_CACHE)
|
||||
self.actionRequestMissingObjects.setChecked(self.settings.AUTOMATICALLY_REQUEST_MISSING_OBJECTS)
|
||||
self.actionProxyRemotelyAccessible.triggered.connect(self._setProxyRemotelyAccessible)
|
||||
self.actionProxySSLInsecure.triggered.connect(self._setProxySSLInsecure)
|
||||
self.actionUseViewerObjectCache.triggered.connect(self._setUseViewerObjectCache)
|
||||
self.actionRequestMissingObjects.triggered.connect(self._setRequestMissingObjects)
|
||||
self.actionOpenNewMessageLogWindow.triggered.connect(self._openNewMessageLogWindow)
|
||||
@@ -458,7 +460,7 @@ class MessageLogWindow(QtWidgets.QMainWindow):
|
||||
if clicked_btn is not yes_btn:
|
||||
return
|
||||
|
||||
master = create_proxy_master("127.0.0.1", -1, HTTPFlowContext())
|
||||
master = create_http_proxy("127.0.0.1", -1, HTTPFlowContext())
|
||||
dirs = setup_ca_everywhere(master)
|
||||
|
||||
msg = QtWidgets.QMessageBox()
|
||||
@@ -474,6 +476,12 @@ class MessageLogWindow(QtWidgets.QMainWindow):
|
||||
msg.setText("Remote accessibility setting changes will take effect on next run")
|
||||
msg.exec()
|
||||
|
||||
def _setProxySSLInsecure(self, checked: bool):
|
||||
self.sessionManager.settings.SSL_INSECURE = checked
|
||||
msg = QtWidgets.QMessageBox()
|
||||
msg.setText("SSL security setting changes will take effect on next run")
|
||||
msg.exec()
|
||||
|
||||
def _setUseViewerObjectCache(self, checked: bool):
|
||||
self.sessionManager.settings.USE_VIEWER_OBJECT_CACHE = checked
|
||||
|
||||
@@ -937,6 +945,7 @@ def gui_main():
|
||||
session_manager=window.sessionManager,
|
||||
extra_addon_paths=window.getAddonList(),
|
||||
proxy_host=http_host,
|
||||
ssl_insecure=settings.SSL_INSECURE,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>22</height>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@@ -268,6 +268,7 @@
|
||||
<addaction name="actionProxyRemotelyAccessible"/>
|
||||
<addaction name="actionUseViewerObjectCache"/>
|
||||
<addaction name="actionRequestMissingObjects"/>
|
||||
<addaction name="actionProxySSLInsecure"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
@@ -342,6 +343,17 @@
|
||||
<string>Export Log Entries</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionProxySSLInsecure">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow Insecure SSL Connections</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Allow invalid SSL certificates from upstream connections</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -222,7 +222,7 @@ class Message:
|
||||
def add_blocks(self, block_list):
|
||||
# can have a list of blocks if it is multiple or variable
|
||||
for block in block_list:
|
||||
if type(block) == list:
|
||||
if type(block) is list:
|
||||
for bl in block:
|
||||
self.add_block(bl)
|
||||
else:
|
||||
|
||||
@@ -1917,7 +1917,7 @@ class IntEnumSubfieldSerializer(AdapterInstanceSubfieldSerializer):
|
||||
val = super().deserialize(ctx_obj, val, pod=pod)
|
||||
# Don't pretend we were able to deserialize this if we
|
||||
# had to fall through to the `int` case.
|
||||
if pod and type(val) == int:
|
||||
if pod and type(val) is int:
|
||||
return UNSERIALIZABLE
|
||||
return val
|
||||
|
||||
|
||||
@@ -1461,6 +1461,8 @@ class ExtraParamType(IntEnum):
|
||||
RESERVED = 0x50
|
||||
MESH = 0x60
|
||||
EXTENDED_MESH = 0x70
|
||||
RENDER_MATERIAL = 0x80
|
||||
REFLECTION_PROBE = 0x90
|
||||
|
||||
|
||||
class ExtendedMeshFlags(IntFlag):
|
||||
@@ -1483,6 +1485,13 @@ class SculptTypeData:
|
||||
Mirror: bool = se.bitfield_field(bits=1, adapter=se.BoolAdapter())
|
||||
|
||||
|
||||
class ReflectionProbeFlags(IntFlag):
|
||||
# use a box influence volume
|
||||
BOX_VOLUME = 0x1
|
||||
# render dynamic objects (avatars) into this Reflection Probe
|
||||
DYNAMIC = 0x2
|
||||
|
||||
|
||||
EXTRA_PARAM_TEMPLATES = {
|
||||
ExtraParamType.FLEXIBLE: se.Template({
|
||||
"Tension": se.BitField(se.U8, {"Tension": 6, "Softness1": 2}),
|
||||
@@ -1514,6 +1523,15 @@ EXTRA_PARAM_TEMPLATES = {
|
||||
ExtraParamType.EXTENDED_MESH: se.Template({
|
||||
"Flags": se.IntFlag(ExtendedMeshFlags, se.U32),
|
||||
}),
|
||||
ExtraParamType.RENDER_MATERIAL: se.Collection(se.U8, se.Template({
|
||||
"TEIdx": se.U8,
|
||||
"TEID": se.UUID,
|
||||
})),
|
||||
ExtraParamType.REFLECTION_PROBE: se.Template({
|
||||
"Ambiance": se.F32,
|
||||
"ClipDistance": se.F32,
|
||||
"Flags": se.IntFlag(ReflectionProbeFlags, se.U8),
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -762,7 +762,8 @@ class RegionObjectsState:
|
||||
def handle_object_reparented(self, obj: Object, old_parent_id: int):
|
||||
"""Recreate any links to ancestor Objects for obj due to parent changes"""
|
||||
self._unparent_object(obj, old_parent_id)
|
||||
self._parent_object(obj, insert_at_head=True)
|
||||
# Avatars get sent to the _end_ of the child list when reparented
|
||||
self._parent_object(obj, insert_at_head=obj.PCode != PCode.AVATAR)
|
||||
|
||||
def collect_orphans(self, parent_localid: int) -> Sequence[int]:
|
||||
"""Take ownership of any orphan IDs belonging to parent_localid"""
|
||||
|
||||
@@ -174,7 +174,10 @@ class AddonManager:
|
||||
def load_addon_from_path(cls, path, reload=False, raise_exceptions=True):
|
||||
path = pathlib.Path(path).absolute()
|
||||
mod_name = "hippolyzer.user_addon_%s" % path.stem
|
||||
cls.BASE_ADDON_SPECS.append(importlib.util.spec_from_file_location(mod_name, path))
|
||||
spec = importlib.util.spec_from_file_location(mod_name, path)
|
||||
if not spec:
|
||||
raise ValueError(f"Unable to load {path}")
|
||||
cls.BASE_ADDON_SPECS.append(spec)
|
||||
addon_dir = os.path.realpath(pathlib.Path(path).parent.absolute())
|
||||
|
||||
if addon_dir not in sys.path:
|
||||
|
||||
@@ -224,6 +224,11 @@ class MITMProxyEventManager:
|
||||
|
||||
status = flow.response.status_code
|
||||
cap_data: Optional[CapData] = flow.metadata["cap_data"]
|
||||
if not cap_data:
|
||||
# Make sure there's always cap data attached to the flow, even if it's
|
||||
# empty. Some consumers expect it to always be there, when it might not
|
||||
# be if the proxy barfed while handling the request.
|
||||
cap_data = flow.metadata["cap_data"] = CapData()
|
||||
|
||||
if status == 200 and cap_data and cap_data.cap_name == "FirestormBridge":
|
||||
# Fake FirestormBridge cap based on a bridge-like response coming from
|
||||
|
||||
@@ -236,7 +236,7 @@ class SLMITMMaster(mitmproxy.master.Master):
|
||||
)
|
||||
|
||||
|
||||
def create_proxy_master(host, port, flow_context: HTTPFlowContext): # pragma: no cover
|
||||
def create_http_proxy(host, port, flow_context: HTTPFlowContext, ssl_insecure=False): # pragma: no cover
|
||||
opts = mitmproxy.options.Options()
|
||||
master = SLMITMMaster(flow_context, opts)
|
||||
|
||||
@@ -251,10 +251,6 @@ def create_proxy_master(host, port, flow_context: HTTPFlowContext): # pragma: n
|
||||
ssl_verify_upstream_trusted_ca=ca_bundle,
|
||||
listen_host=host,
|
||||
listen_port=port,
|
||||
ssl_insecure=ssl_insecure,
|
||||
)
|
||||
return master
|
||||
|
||||
|
||||
def create_http_proxy(bind_host, port, flow_context: HTTPFlowContext): # pragma: no cover
|
||||
master = create_proxy_master(bind_host, port, flow_context)
|
||||
return master
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import datetime as dt
|
||||
import logging
|
||||
|
||||
from hippolyzer.lib.base.helpers import get_mtime
|
||||
from hippolyzer.lib.client.inventory_manager import InventoryManager
|
||||
@@ -25,4 +26,7 @@ class ProxyInventoryManager(InventoryManager):
|
||||
newest_cache = inv_cache_path
|
||||
|
||||
if newest_cache:
|
||||
self.load_cache(newest_cache)
|
||||
try:
|
||||
self.load_cache(newest_cache)
|
||||
except:
|
||||
logging.exception("Failed to load invcache")
|
||||
|
||||
@@ -35,3 +35,4 @@ class ProxySettings(Settings):
|
||||
AUTOMATICALLY_REQUEST_MISSING_OBJECTS: bool = SettingDescriptor(False)
|
||||
ADDON_SCRIPTS: List[str] = SettingDescriptor(list)
|
||||
FILTERS: Dict[str, str] = SettingDescriptor(dict)
|
||||
SSL_INSECURE: bool = SettingDescriptor(False)
|
||||
|
||||
@@ -83,7 +83,7 @@ class SOCKS5Server:
|
||||
try:
|
||||
# UDP Associate
|
||||
if cmd == 3:
|
||||
loop = asyncio.get_running_loop()
|
||||
loop = asyncio.get_event_loop_policy().get_event_loop()
|
||||
transport, protocol = await loop.create_datagram_endpoint(
|
||||
self._udp_protocol_creator(writer.get_extra_info("peername")),
|
||||
local_addr=('0.0.0.0', 0))
|
||||
|
||||
@@ -65,7 +65,7 @@ class TaskScheduler:
|
||||
task.cancel()
|
||||
|
||||
try:
|
||||
event_loop = asyncio.get_running_loop()
|
||||
event_loop = asyncio.get_event_loop_policy().get_event_loop()
|
||||
await_all = asyncio.gather(*(task for task_data, task in self.tasks))
|
||||
event_loop.run_until_complete(await_all)
|
||||
except RuntimeError:
|
||||
|
||||
3
setup.py
3
setup.py
@@ -25,7 +25,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
here = path.abspath(path.dirname(__file__))
|
||||
|
||||
version = '0.13.2'
|
||||
version = '0.13.4'
|
||||
|
||||
with open(path.join(here, 'README.md')) as readme_fh:
|
||||
readme = readme_fh.read()
|
||||
@@ -94,6 +94,7 @@ setup(
|
||||
'idna<3,>=2.5',
|
||||
# 7.x will be a major change.
|
||||
'mitmproxy>=8.0.0,<8.1',
|
||||
'Werkzeug<3.0',
|
||||
# For REPLs
|
||||
'ptpython<4.0',
|
||||
# JP2 codec
|
||||
|
||||
@@ -89,7 +89,7 @@ class _MutableMultiDictTests:
|
||||
d = create_instance()
|
||||
s = pickle.dumps(d, protocol)
|
||||
ud = pickle.loads(s)
|
||||
assert type(ud) == type(d)
|
||||
assert type(ud) is type(d)
|
||||
assert ud == d
|
||||
alternative = pickle.dumps(create_instance("werkzeug"), protocol)
|
||||
assert pickle.loads(alternative) == d
|
||||
|
||||
Reference in New Issue
Block a user