sippy 2.3.0__tar.gz → 2.4.1__tar.gz
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.
- {sippy-2.3.0 → sippy-2.4.1}/MANIFEST.in +1 -0
- {sippy-2.3.0/sippy.egg-info → sippy-2.4.1}/PKG-INFO +3 -1
- {sippy-2.3.0 → sippy-2.4.1}/requirements.txt +2 -0
- {sippy-2.3.0 → sippy-2.4.1}/setup.py +1 -1
- {sippy-2.3.0 → sippy-2.4.1}/sippy/B2B/Route.py +75 -22
- {sippy-2.3.0 → sippy-2.4.1}/sippy/B2B/SimpleAPI.py +7 -3
- {sippy-2.3.0 → sippy-2.4.1}/sippy/MyConfigParser.py +7 -3
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/EPoint.py +38 -8
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/udp.py +2 -5
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Session/side.py +2 -3
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/session.py +18 -10
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Security/SipNonce.py +26 -12
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipAuthorization.py +3 -16
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipCallId.py +2 -4
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipCiscoGUID.py +3 -6
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipFrom.py +2 -4
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipVia.py +2 -4
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipWWWAuthenticate.py +2 -9
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UA.py +2 -5
- sippy-2.4.1/sippy/UI/Auth.py +64 -0
- sippy-2.4.1/sippy/UI/Controller.py +380 -0
- sippy-2.4.1/sippy/UI/Lib.py +248 -0
- sippy-2.4.1/sippy/UI/SystemConfiguration.py +5 -0
- sippy-2.4.1/sippy/UI/static/active_calls.js +17 -0
- sippy-2.4.1/sippy/UI/static/config_box.css +29 -0
- sippy-2.4.1/sippy/UI/static/lib.js +146 -0
- sippy-2.4.1/sippy/UI/static/login.css +103 -0
- sippy-2.4.1/sippy/UI/static/ui.css +50 -0
- sippy-2.4.1/sippy/UI/templates/login.html +81 -0
- sippy-2.4.1/sippy/UI/templates/redir2login.html +14 -0
- sippy-2.4.1/sippy/UaStateConnected.py +311 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UaStateGeneric.py +26 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UacStateUpdating.py +32 -25
- sippy-2.4.1/sippy/UasStateGeneric.py +79 -0
- sippy-2.4.1/sippy/UasStateProgressing.py +84 -0
- sippy-2.4.1/sippy/UasStateRinging.py +64 -0
- sippy-2.4.1/sippy/UasStateTrying.py +89 -0
- sippy-2.4.1/sippy/UasStateUpdating.py +103 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/b2bua.py +7 -1
- {sippy-2.3.0 → sippy-2.4.1/sippy.egg-info}/PKG-INFO +3 -1
- {sippy-2.3.0 → sippy-2.4.1}/sippy.egg-info/SOURCES.txt +16 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy.egg-info/requires.txt +2 -0
- sippy-2.4.1/tests/__init__.py +0 -0
- sippy-2.4.1/tests/test_HashOracle.py +30 -0
- sippy-2.4.1/tests/test_RtpEPoint.py +61 -0
- sippy-2.3.0/sippy/UaStateConnected.py +0 -296
- sippy-2.3.0/sippy/UasStateRinging.py +0 -144
- sippy-2.3.0/sippy/UasStateTrying.py +0 -137
- sippy-2.3.0/sippy/UasStateUpdating.py +0 -128
- {sippy-2.3.0 → sippy-2.4.1}/LICENSE +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/README.md +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/pyproject.toml +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/setup.cfg +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/B2B/States.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/B2B/Transforms.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/B2B/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/CCEvents.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/CLIManager.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Core/EventDispatcher.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Core/Exceptions.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Core/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/ESipHeaderCSV.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/ESipHeaderIgnore.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Exceptions/RtpProxyError.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Exceptions/SdpParseError.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Exceptions/SipHandlingError.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Exceptions/SipParseError.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Exceptions/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/External_command.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/FakeAccounting.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Math/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Math/recfilter.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/MsgBody.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/MultipartMixBody.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Network_server.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/RadiusAccounting.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/RadiusAuthorisation.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Radius_client.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Codecs/G711.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Codecs/G722.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Codecs/GenCodec.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Codecs/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Conf.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Core/AudioChunk.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Core/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Handlers.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Ingest.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/OutputWorker.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Params.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/Singletons.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/Worker/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/Worker/external.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/Worker/internal.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/internal.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/local.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/net.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Client/stream.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Cmd/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Cmd/sequencer.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Session/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Session/subcommand.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Session/subcommand_ice.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Session/update.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/Session/webrtc.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/client.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Rtp_proxy/cmd.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SdpBody.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SdpConnecton.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SdpGeneric.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SdpMedia.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SdpMediaDescription.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SdpOrigin.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Security/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Signal.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipAddress.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipAddressHF.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipAllow.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipAlso.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipCCDiversion.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipCSeq.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipConf.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipContact.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipContentLength.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipContentType.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipDiversion.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipExpires.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipGenericHF.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipHeader.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipLogger.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipMaxForwards.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipMsg.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipNumericHF.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipPAssertedIdentity.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipPath.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipProxyAuthenticate.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipProxyAuthorization.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipRAck.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipRSeq.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipReason.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipRecordRoute.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipReferTo.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipReferredBy.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipRegistrationAgent.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipReplaces.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipRequest.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipResponse.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipRoute.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipServer.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipSupported.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipTo.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipTransactionManager.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipURL.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipUserAgent.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/SipWarning.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/StatefulProxy.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Time/MonoTime.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Time/Timeout.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Time/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Time/clock_dtime.py +0 -0
- {sippy-2.3.0/tests → sippy-2.4.1/sippy/UI}/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UaStateDead.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UaStateDisconnected.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UaStateFailed.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UacStateCancelling.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UacStateIdle.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UacStateRinging.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UacStateTrying.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/UasStateIdle.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Udp_server.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/Wss_server.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/XMPP_server.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/__init__.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/b2bua_simple.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/dictionary +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy/misc.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy.egg-info/dependency_links.txt +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy.egg-info/entry_points.txt +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/sippy.egg-info/top_level.txt +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/tests/test_B2BRoute.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/tests/test_B2BTransforms.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/tests/test_Multipart.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/tests/test_RtpParams.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/tests/test_SdbBody.py +0 -0
- {sippy-2.3.0 → sippy-2.4.1}/tests/test_Udp_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sippy
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: RFC3261 SIP Stack and Back-to-Back User Agent (B2BUA)
|
|
5
5
|
Home-page: http://www.b2bua.org/
|
|
6
6
|
Author: Sippy Software, Inc.
|
|
@@ -17,6 +17,8 @@ Requires-Dist: rtpsynth>=1.3.0
|
|
|
17
17
|
Requires-Dist: g722>=1.2.3
|
|
18
18
|
Requires-Dist: pycryptodome
|
|
19
19
|
Requires-Dist: websockets
|
|
20
|
+
Requires-Dist: flask
|
|
21
|
+
Requires-Dist: flask-login
|
|
20
22
|
Dynamic: author
|
|
21
23
|
Dynamic: author-email
|
|
22
24
|
Dynamic: classifier
|
|
@@ -40,32 +40,69 @@ DST_SIP_UA = 'sip-ua'
|
|
|
40
40
|
DST_WSS_UA = 'wss-ua'
|
|
41
41
|
|
|
42
42
|
class B2BRoute(object):
|
|
43
|
+
crt_set = False
|
|
44
|
+
params = None
|
|
45
|
+
extra_headers = None
|
|
43
46
|
rnum = None
|
|
47
|
+
_ui_cats = {'auth': 'Outbound Digest Authentication', 'net': 'Network', 'lim': 'Limits',
|
|
48
|
+
'num': 'Calling / Called Numbers', 'acct': 'Accounting'}
|
|
49
|
+
_ui_hints = {}
|
|
50
|
+
# _ui_hints['rnum'] = {'hidden': True}
|
|
44
51
|
addrinfo = None
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
passw = None
|
|
52
|
+
# _ui_hints['addrinfo'] = {'readonly': True, 'category': _ui_cats['net'], 'hidden': True}
|
|
53
|
+
hostonly:str = None
|
|
54
|
+
# _ui_hints['hostonly'] = {'readonly': True, 'category': _ui_cats['net'], 'hidden': True}
|
|
55
|
+
ainfo = None
|
|
56
|
+
# _ui_hints['ainfo'] = {'readonly': True, 'category': _ui_cats['net'], 'hidden': True}
|
|
57
|
+
hostport:str = None
|
|
58
|
+
_ui_hints['hostport'] = {'name': 'Destination', 'description': 'Destination host:port',
|
|
59
|
+
'category': _ui_cats['net']}
|
|
60
|
+
user:str = None
|
|
61
|
+
_ui_hints['user'] = {'name': 'SIP Username', 'category': _ui_cats['auth'],
|
|
62
|
+
'active': lambda o: not o.pass_auth}
|
|
63
|
+
passw:str = None
|
|
64
|
+
_ui_hints['passw'] = {'name': 'SIP Password', 'category': _ui_cats['auth'], 'password': True,
|
|
65
|
+
'active': lambda o: not o.pass_auth}
|
|
57
66
|
pass_auth = True
|
|
58
|
-
|
|
67
|
+
_ui_hints['pass_auth'] = {'name': 'Mode', 'category': _ui_cats['auth'],
|
|
68
|
+
'values': {False: 'Normal ("UAC")', True: 'Pass-through ("Proxy")'},}
|
|
69
|
+
_cld:str = None
|
|
70
|
+
_ui_hints['cld'] = {'name': 'Called Party (CLD)', 'description': 'Called party number',
|
|
71
|
+
'category': _ui_cats['num'], 'type': str}
|
|
72
|
+
cld_set = False
|
|
73
|
+
_ui_hints['cld_set'] = {'name': 'CLD Mode', 'description': 'Controls outbound CLD',
|
|
74
|
+
'category': _ui_cats['num'], 'active': lambda o: not o.cld,
|
|
75
|
+
'values': lambda o: {True: 'Erase', False: 'Pass-through'}
|
|
76
|
+
if not o.cld else {True: 'Replace'}}
|
|
77
|
+
_cli:str = None
|
|
78
|
+
_ui_hints['cli'] = {'name': 'Calling Party (CLI)', 'description': 'Caller number',
|
|
79
|
+
'category': _ui_cats['num'], 'type': str}
|
|
59
80
|
cli_set = False
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
_ui_hints['cli_set'] = {'name': 'CLI Mode', 'description': 'Controls outbound CLI', 'category':
|
|
82
|
+
_ui_cats['num'], 'active': lambda o: not o.cli,
|
|
83
|
+
'values': lambda o: {True: 'Erase', False: 'Pass-through'}
|
|
84
|
+
if not o.cli else {True: 'Replace'}}
|
|
85
|
+
credit_time:float = None
|
|
86
|
+
_ui_hints['credit_time'] = {'name': 'Credit Time', 'description': 'Allowed call duration, in seconds',
|
|
87
|
+
'category': _ui_cats['lim']}
|
|
88
|
+
expires:float = None
|
|
89
|
+
_ui_hints['expires'] = {'name': 'Route Expiry', 'description': 'Time to expire the route, in seconds',
|
|
90
|
+
'category': _ui_cats['lim']}
|
|
91
|
+
no_progress_expires:float = None
|
|
92
|
+
_ui_hints['no_progress_expires'] = {'name': 'No Progress Timeout', 'category': _ui_cats['lim'],
|
|
93
|
+
'description': 'Time to expire the route if no 180 or 183 provisional response received, in seconds'}
|
|
94
|
+
no_reply_expires:float = None
|
|
95
|
+
_ui_hints['no_reply_expires'] = {'name': 'No Reply Timeout', 'category': _ui_cats['lim'],
|
|
96
|
+
'description': 'Time to expire the route if no provisional response received, in seconds'}
|
|
97
|
+
forward_on_fail = False
|
|
98
|
+
_ui_hints['forward_on_fail'] = {'name': 'Failed Calls', 'category': _ui_cats['acct'],
|
|
99
|
+
'description': 'Emit accounting on SIP failures'}
|
|
63
100
|
|
|
64
101
|
def __init__(self, sroute = None, cself = None):
|
|
65
102
|
if cself != None:
|
|
66
103
|
self.rnum = cself.rnum
|
|
67
104
|
self.addrinfo = cself.addrinfo
|
|
68
|
-
self.
|
|
105
|
+
self._cld = cself.cld
|
|
69
106
|
self.cld_set = cself.cld_set
|
|
70
107
|
self.hostport = cself.hostport
|
|
71
108
|
self.hostonly = cself.hostonly
|
|
@@ -78,7 +115,7 @@ class B2BRoute(object):
|
|
|
78
115
|
self.user = cself.user
|
|
79
116
|
self.passw = cself.passw
|
|
80
117
|
self.pass_auth = cself.pass_auth
|
|
81
|
-
self.
|
|
118
|
+
self._cli = cself.cli
|
|
82
119
|
self.cli_set = cself.cli_set
|
|
83
120
|
self.params = dict(cself.params)
|
|
84
121
|
self.ainfo = cself.ainfo
|
|
@@ -93,7 +130,6 @@ class B2BRoute(object):
|
|
|
93
130
|
# as opposed to the Routing:host, which means that CLD should be obtained
|
|
94
131
|
# from the incoming call leg.
|
|
95
132
|
self.cld = None
|
|
96
|
-
self.cld_set = True
|
|
97
133
|
else:
|
|
98
134
|
self.hostport = route[0]
|
|
99
135
|
if not self.hostport.startswith('['):
|
|
@@ -147,7 +183,6 @@ class B2BRoute(object):
|
|
|
147
183
|
self.cli = v
|
|
148
184
|
if len(self.cli) == 0:
|
|
149
185
|
self.cli = None
|
|
150
|
-
self.cli_set = True
|
|
151
186
|
elif a == 'cnam':
|
|
152
187
|
caller_name = unquote(v)
|
|
153
188
|
if len(caller_name) == 0:
|
|
@@ -175,9 +210,9 @@ class B2BRoute(object):
|
|
|
175
210
|
pass_headers, max_credit_time):
|
|
176
211
|
self.rnum = rnum
|
|
177
212
|
if not self.cld_set:
|
|
178
|
-
self.
|
|
213
|
+
self._cld = default_cld
|
|
179
214
|
if not self.cli_set:
|
|
180
|
-
self.
|
|
215
|
+
self._cli = default_cli
|
|
181
216
|
if not self.crt_set:
|
|
182
217
|
self.crt_set = default_credit_time
|
|
183
218
|
if 'gt' in self.params:
|
|
@@ -210,3 +245,21 @@ class B2BRoute(object):
|
|
|
210
245
|
if af == AF_INET6:
|
|
211
246
|
return ((('[%s]' % amatch[0], amatch[1]), same_af))
|
|
212
247
|
return (((amatch[0], amatch[1]), same_af))
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def cli(self):
|
|
251
|
+
return self._cli
|
|
252
|
+
|
|
253
|
+
@cli.setter
|
|
254
|
+
def cli(self, value):
|
|
255
|
+
self._cli = value
|
|
256
|
+
self.cli_set = True
|
|
257
|
+
|
|
258
|
+
@property
|
|
259
|
+
def cld(self):
|
|
260
|
+
return self._cld
|
|
261
|
+
|
|
262
|
+
@cld.setter
|
|
263
|
+
def cld(self, value):
|
|
264
|
+
self._cld = value
|
|
265
|
+
self.cld_set = True
|
|
@@ -116,10 +116,11 @@ class B2BSimpleAPI(CLIConnectionManager):
|
|
|
116
116
|
clim.send('OK\n')
|
|
117
117
|
return False
|
|
118
118
|
if cmd == 'r':
|
|
119
|
-
if len(args)
|
|
120
|
-
clim.send('ERROR: syntax error: r
|
|
119
|
+
if len(args) not in (1, 2):
|
|
120
|
+
clim.send('ERROR: syntax error: r <id> [<media-index>]\n')
|
|
121
121
|
return False
|
|
122
122
|
idx = int(args[0])
|
|
123
|
+
media_index = int(args[1]) if len(args) == 2 else 0
|
|
123
124
|
dlist = [x for x in ccm.ccmap if x.id == idx]
|
|
124
125
|
if len(dlist) == 0:
|
|
125
126
|
clim.send('ERROR: no call with id of %d has been found\n' % idx)
|
|
@@ -128,9 +129,12 @@ class B2BSimpleAPI(CLIConnectionManager):
|
|
|
128
129
|
if not cc.proxied:
|
|
129
130
|
continue
|
|
130
131
|
if cc.state == CCStateConnected:
|
|
131
|
-
cc.disconnect(MonoTime().getOffsetCopy(-60), origin = 'media_timeout'
|
|
132
|
+
cc.disconnect(MonoTime().getOffsetCopy(-60), origin = 'media_timeout',
|
|
133
|
+
media_index = media_index)
|
|
132
134
|
continue
|
|
133
135
|
if cc.state == CCStateARComplete:
|
|
136
|
+
if cc.rtp_proxy_session is not None:
|
|
137
|
+
cc.rtp_proxy_session.media_timeout_index = media_index
|
|
134
138
|
cc.uaO.disconnect(MonoTime().getOffsetCopy(-60), origin = 'media_timeout')
|
|
135
139
|
continue
|
|
136
140
|
clim.send('OK\n')
|
|
@@ -104,9 +104,13 @@ SUPPORTED_OPTIONS = { \
|
|
|
104
104
|
'"host:port:cert_file:key_file", where "cert_file" ' \
|
|
105
105
|
'/ "key_file" are paths to the TLS certificate ' \
|
|
106
106
|
'and key file respectively in the X.509 PEM format'),
|
|
107
|
-
'pre_auth_proc':
|
|
108
|
-
|
|
109
|
-
'xmpp_b2bua_id': ('I', 'ID passed to the XMPP socket server')
|
|
107
|
+
'pre_auth_proc': ('S', 'internal routine to be executed before authentication '\
|
|
108
|
+
'is being processed. E.g. "HDR2Xattrs[X-foo-hdr]."'), \
|
|
109
|
+
'xmpp_b2bua_id': ('I', 'ID passed to the XMPP socket server'), \
|
|
110
|
+
'ui': ('B', 'enable Web management UI'), \
|
|
111
|
+
'uiparams': ('S', 'Semicolon-separated list of UI parameters corresponding to ' \
|
|
112
|
+
'the flask\'s run() routine'), \
|
|
113
|
+
}
|
|
110
114
|
|
|
111
115
|
class MyConfigParser(RawConfigParser):
|
|
112
116
|
_default_section = None
|
|
@@ -2,6 +2,7 @@ from typing import Optional, Tuple
|
|
|
2
2
|
from uuid import uuid4, UUID
|
|
3
3
|
from threading import Lock
|
|
4
4
|
import errno
|
|
5
|
+
import weakref
|
|
5
6
|
|
|
6
7
|
from rtpsynth.RtpServer import RtpQueueFullError, RtpServer
|
|
7
8
|
from sippy.Time.MonoTime import MonoTime
|
|
@@ -14,9 +15,12 @@ from .Singletons import acquire_rtp_server, release_rtp_server
|
|
|
14
15
|
|
|
15
16
|
class RTPEPoint():
|
|
16
17
|
debug: bool = False
|
|
18
|
+
rtp_received_lock_timeout = 0.01
|
|
17
19
|
id: UUID
|
|
18
20
|
dl_file = None
|
|
19
21
|
firstframe = True
|
|
22
|
+
writer = None
|
|
23
|
+
rserv = None
|
|
20
24
|
rtp_params:RTPParams
|
|
21
25
|
state_lock: Lock
|
|
22
26
|
handlers: RTPHandlers
|
|
@@ -29,7 +33,6 @@ class RTPEPoint():
|
|
|
29
33
|
self._palloc = rc.palloc
|
|
30
34
|
self._rtp_server = None
|
|
31
35
|
self.state_lock = Lock()
|
|
32
|
-
self.writer = None
|
|
33
36
|
self.rsess = self.make_rtp_instream(rtp_params, audio_in)
|
|
34
37
|
rserv_opts = self.make_udp_server_opts(rtp_params)
|
|
35
38
|
self.rserv = self.make_udp_server(rserv_opts)
|
|
@@ -46,6 +49,28 @@ class RTPEPoint():
|
|
|
46
49
|
palloc = self._palloc if rtp_params.rtp_lport == 0 else rtp_params.rtp_lport
|
|
47
50
|
return (rtp_params.rtp_laddr, palloc)
|
|
48
51
|
|
|
52
|
+
def _make_rtp_received_cb(self):
|
|
53
|
+
self_ref = weakref.ref(self)
|
|
54
|
+
|
|
55
|
+
def rtp_received_cb(data, address, rtime_ns=None):
|
|
56
|
+
self = self_ref()
|
|
57
|
+
if self is None:
|
|
58
|
+
return
|
|
59
|
+
return self.rtp_received(data, address, rtime_ns)
|
|
60
|
+
|
|
61
|
+
return rtp_received_cb
|
|
62
|
+
|
|
63
|
+
def _make_send_pkt_cb(self):
|
|
64
|
+
self_ref = weakref.ref(self)
|
|
65
|
+
|
|
66
|
+
def send_pkt_cb(pkt):
|
|
67
|
+
self = self_ref()
|
|
68
|
+
if self is None:
|
|
69
|
+
return
|
|
70
|
+
return self.send_pkt(pkt)
|
|
71
|
+
|
|
72
|
+
return send_pkt_cb
|
|
73
|
+
|
|
49
74
|
def make_udp_server(self, rserv_opts):
|
|
50
75
|
rtp_laddr, palloc = rserv_opts
|
|
51
76
|
server_cls = self.handlers.rtp_server_cls
|
|
@@ -67,7 +92,7 @@ class RTPEPoint():
|
|
|
67
92
|
|
|
68
93
|
def _create_channel(self, rtp_server:RtpServer, bind_host:str, bind_port:int):
|
|
69
94
|
bind_family = self.rtp_params.rtp_family
|
|
70
|
-
ch_kwargs = dict(pkt_in=self.
|
|
95
|
+
ch_kwargs = dict(pkt_in=self._make_rtp_received_cb(), bind_host=bind_host, bind_port=bind_port)
|
|
71
96
|
ch = rtp_server.create_channel(bind_family=bind_family, **ch_kwargs)
|
|
72
97
|
self.rtp_params.rtp_lport = bind_port
|
|
73
98
|
return ch
|
|
@@ -113,7 +138,7 @@ class RTPEPoint():
|
|
|
113
138
|
def writer_setup(self):
|
|
114
139
|
assert self.writer is None
|
|
115
140
|
writer = self.make_writer(self.rtp_params)
|
|
116
|
-
writer.set_pkt_send_f(self.
|
|
141
|
+
writer.set_pkt_send_f(self._make_send_pkt_cb())
|
|
117
142
|
if self.dl_file is not None:
|
|
118
143
|
writer.enable_datalog(self.dl_file)
|
|
119
144
|
writer.start()
|
|
@@ -134,12 +159,18 @@ class RTPEPoint():
|
|
|
134
159
|
rtime = MonoTime().monot
|
|
135
160
|
else:
|
|
136
161
|
rtime = rtime_ns / 1_000_000_000.0
|
|
137
|
-
|
|
162
|
+
if not self.state_lock.acquire(timeout=self.rtp_received_lock_timeout):
|
|
163
|
+
if self.debug:
|
|
164
|
+
print(f'RTP.EPoint.rtp_received[{str(self.id)[:6]}]: state lock timeout')
|
|
165
|
+
return
|
|
166
|
+
try:
|
|
138
167
|
target = self.rtp_params.rtp_target
|
|
139
168
|
if target is not None and address != target:
|
|
140
169
|
if self.debug:
|
|
141
170
|
print(f"InfernRTPIngest.rtp_received: address mismatch {address=} {self.rtp_params.rtp_target=}")
|
|
142
171
|
return
|
|
172
|
+
finally:
|
|
173
|
+
self.state_lock.release()
|
|
143
174
|
self.rsess.rtp_received(data, address, rtime)
|
|
144
175
|
|
|
145
176
|
def update(self, rtp_params:RTPParams):
|
|
@@ -176,7 +207,7 @@ class RTPEPoint():
|
|
|
176
207
|
channel.set_target(target[0], target[1])
|
|
177
208
|
if need_new_writer:
|
|
178
209
|
new_writer = self.make_writer(rtp_params)
|
|
179
|
-
new_writer.set_pkt_send_f(self.
|
|
210
|
+
new_writer.set_pkt_send_f(self._make_send_pkt_cb())
|
|
180
211
|
if self.dl_file is not None:
|
|
181
212
|
new_writer.enable_datalog(self.dl_file)
|
|
182
213
|
new_writer.start()
|
|
@@ -195,12 +226,10 @@ class RTPEPoint():
|
|
|
195
226
|
def shutdown(self):
|
|
196
227
|
with self.state_lock:
|
|
197
228
|
writer, channel, rtp_server = self.writer, self.rserv, self._rtp_server
|
|
198
|
-
self.writer, self._rtp_server = (None, None)
|
|
229
|
+
self.writer, self.rserv, self._rtp_server = (None, None, None)
|
|
199
230
|
if writer is not None:
|
|
200
231
|
writer.end()
|
|
201
232
|
writer.join()
|
|
202
|
-
with self.state_lock:
|
|
203
|
-
self.rserv = None
|
|
204
233
|
if channel is not None:
|
|
205
234
|
channel.close()
|
|
206
235
|
if rtp_server is not None:
|
|
@@ -209,6 +238,7 @@ class RTPEPoint():
|
|
|
209
238
|
def __del__(self):
|
|
210
239
|
if self.debug:
|
|
211
240
|
print('RTP.EPoint.__del__')
|
|
241
|
+
self.shutdown()
|
|
212
242
|
|
|
213
243
|
def soundout(self, chunk:AudioChunk):
|
|
214
244
|
if self.firstframe:
|
|
@@ -34,9 +34,7 @@ from sippy.Rtp_proxy.cmd import Rtp_proxy_cmd
|
|
|
34
34
|
from sippy.Rtp_proxy.Client.net import Rtp_proxy_client_net
|
|
35
35
|
|
|
36
36
|
from socket import SOCK_DGRAM, AF_INET
|
|
37
|
-
from
|
|
38
|
-
from hashlib import md5
|
|
39
|
-
from random import random
|
|
37
|
+
from secrets import token_hex
|
|
40
38
|
|
|
41
39
|
def getnretrans(first_rert, timeout):
|
|
42
40
|
if first_rert <= 0:
|
|
@@ -93,8 +91,7 @@ class Rtp_proxy_client_udp(Rtp_proxy_client_net):
|
|
|
93
91
|
self.delay_flt = recfilter(0.95, 0.25)
|
|
94
92
|
|
|
95
93
|
def send_command(self, command, result_callback = None, *callback_parameters):
|
|
96
|
-
|
|
97
|
-
cookie = md5(entropy.encode()).hexdigest()
|
|
94
|
+
cookie = token_hex(16)
|
|
98
95
|
next_retr = self.delay_flt.lastval * 4.0
|
|
99
96
|
exp_time = 3.0
|
|
100
97
|
if isinstance(command, Rtp_proxy_cmd):
|
|
@@ -90,9 +90,8 @@ class _rtpps_side(object):
|
|
|
90
90
|
command += ' %s %s %d %s %s' % ('%s-%d' % (up.rtpps.call_id, up.index), up.remote_ip, up.remote_port, from_tag, to_tag)
|
|
91
91
|
else:
|
|
92
92
|
command += ' %s %s %d %s' % ('%s-%d' % (up.rtpps.call_id, up.index), up.remote_ip, up.remote_port, from_tag)
|
|
93
|
-
if up.rtpps.notify_socket
|
|
94
|
-
|
|
95
|
-
command += ' %s %s' % (up.rtpps.notify_socket, up.rtpps.notify_tag)
|
|
93
|
+
if up.rtpps.notify_socket is not None and up.rtpps.notify_tag is not None and rtpc.tnot_supported:
|
|
94
|
+
command += ' %s %s' % (up.rtpps.notify_socket, up.rtpps.get_notify_tag(up.index))
|
|
96
95
|
if len(up.subcommands) > 0:
|
|
97
96
|
command = ' && '.join([command,] + [sc for subc in up.subcommands for sc in subc.commands])
|
|
98
97
|
rtpq.send_command(command, self.update_result, up)
|
|
@@ -25,9 +25,12 @@
|
|
|
25
25
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
26
|
|
|
27
27
|
from functools import partial
|
|
28
|
-
from hashlib import md5
|
|
29
28
|
from random import random
|
|
30
|
-
from
|
|
29
|
+
from secrets import token_hex
|
|
30
|
+
try:
|
|
31
|
+
from urllib import quote, unquote
|
|
32
|
+
except ImportError:
|
|
33
|
+
from urllib.parse import quote, unquote
|
|
31
34
|
try:
|
|
32
35
|
from _thread import get_ident
|
|
33
36
|
except ImportError:
|
|
@@ -52,6 +55,7 @@ class Rtp_proxy_session(object):
|
|
|
52
55
|
max_index = -1
|
|
53
56
|
notify_socket = None
|
|
54
57
|
notify_tag = None
|
|
58
|
+
media_timeout_index = None
|
|
55
59
|
global_config = None
|
|
56
60
|
my_ident = None
|
|
57
61
|
insert_nortpp = False
|
|
@@ -74,20 +78,18 @@ class Rtp_proxy_session(object):
|
|
|
74
78
|
if call_id != None:
|
|
75
79
|
self.call_id = call_id
|
|
76
80
|
else:
|
|
77
|
-
|
|
78
|
-
self.call_id = md5(salt.encode()).hexdigest()
|
|
81
|
+
self.call_id = token_hex(16)
|
|
79
82
|
if from_tag != None:
|
|
80
83
|
self.from_tag = from_tag
|
|
81
84
|
else:
|
|
82
|
-
|
|
83
|
-
self.from_tag = md5(salt.encode()).hexdigest()
|
|
85
|
+
self.from_tag = token_hex(16)
|
|
84
86
|
if to_tag != None:
|
|
85
87
|
self.to_tag = to_tag
|
|
86
88
|
else:
|
|
87
|
-
|
|
88
|
-
self.to_tag = md5(salt.encode()).hexdigest()
|
|
89
|
+
self.to_tag = token_hex(16)
|
|
89
90
|
self.notify_socket = self.rtp_proxy_client.notify_socket
|
|
90
91
|
self.notify_tag = notify_tag
|
|
92
|
+
self.media_timeout_index = None
|
|
91
93
|
self.caller = _rtpps_side('caller')
|
|
92
94
|
self.callee = _rtpps_side('callee')
|
|
93
95
|
|
|
@@ -147,12 +149,18 @@ class Rtp_proxy_session(object):
|
|
|
147
149
|
command = make_command('o')
|
|
148
150
|
return self.rtpp_seq.send_command(command, result_callback)
|
|
149
151
|
|
|
152
|
+
def get_notify_tag(self, index):
|
|
153
|
+
if index == 0:
|
|
154
|
+
return self.notify_tag
|
|
155
|
+
return quote('%s %d' % (unquote(self.notify_tag), index))
|
|
156
|
+
|
|
150
157
|
def delete(self):
|
|
151
158
|
if self.rtp_proxy_client == None:
|
|
152
159
|
return
|
|
153
160
|
while self.max_index >= 0:
|
|
154
|
-
|
|
155
|
-
|
|
161
|
+
if self.media_timeout_index is None or self.max_index != self.media_timeout_index:
|
|
162
|
+
command = 'D %s %s %s' % ('%s-%d' % (self.call_id, self.max_index), self.from_tag, self.to_tag)
|
|
163
|
+
self.rtpp_seq.send_command(command)
|
|
156
164
|
self.max_index -= 1
|
|
157
165
|
self.rtp_proxy_client = None
|
|
158
166
|
self.rtpp_seq.delete()
|
|
@@ -27,12 +27,16 @@
|
|
|
27
27
|
|
|
28
28
|
from functools import partial
|
|
29
29
|
from base64 import b64encode, b64decode
|
|
30
|
+
from hmac import compare_digest, new as hmac_new
|
|
31
|
+
from secrets import token_bytes
|
|
30
32
|
|
|
31
|
-
from Crypto import Random
|
|
32
33
|
from Crypto.Cipher import AES
|
|
33
34
|
|
|
34
35
|
from sippy.Time.clock_dtime import clock_getntime, CLOCK_MONOTONIC
|
|
35
36
|
|
|
37
|
+
AES_BLOCK_SIZE = AES.block_size
|
|
38
|
+
MAC_SIZE = 16
|
|
39
|
+
|
|
36
40
|
to_bytes_be = partial(int.to_bytes, byteorder='big')
|
|
37
41
|
from_bytes_be = partial(int.from_bytes, byteorder='big')
|
|
38
42
|
|
|
@@ -43,23 +47,30 @@ def bxor(ba1, ba2):
|
|
|
43
47
|
return to_bytes_be(ba1 ^ ba2, olen)
|
|
44
48
|
|
|
45
49
|
class AESCipher(object):
|
|
46
|
-
bpad = '='.encode()
|
|
47
50
|
cipher = None
|
|
51
|
+
mac_key = None
|
|
48
52
|
|
|
49
53
|
def __init__(self, key):
|
|
50
|
-
self.cipher = AES.new(key, AES.MODE_ECB)
|
|
54
|
+
self.cipher = AES.new(key[:AES_BLOCK_SIZE * 2], AES.MODE_ECB)
|
|
55
|
+
self.mac_key = key[AES_BLOCK_SIZE * 2:]
|
|
51
56
|
|
|
52
57
|
def encrypt(self, raw):
|
|
53
|
-
iv =
|
|
58
|
+
iv = token_bytes(AES_BLOCK_SIZE)
|
|
54
59
|
raw = bxor(raw, iv)
|
|
55
60
|
eraw = self.cipher.encrypt(iv + raw)
|
|
56
|
-
|
|
61
|
+
eraw += hmac_new(self.mac_key, eraw, 'sha256').digest()[:MAC_SIZE]
|
|
62
|
+
return b64encode(eraw).rstrip(b'=')
|
|
57
63
|
|
|
58
64
|
def decrypt(self, enc):
|
|
59
|
-
enc = b64decode(enc +
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
enc = b64decode(enc + (b'=' * (-len(enc) % 4)))
|
|
66
|
+
data = enc[:-MAC_SIZE]
|
|
67
|
+
tag = enc[-MAC_SIZE:]
|
|
68
|
+
ctag = hmac_new(self.mac_key, data, 'sha256').digest()[:MAC_SIZE]
|
|
69
|
+
if not compare_digest(ctag, tag):
|
|
70
|
+
raise ValueError
|
|
71
|
+
raw = self.cipher.decrypt(data)
|
|
72
|
+
iv = raw[:AES_BLOCK_SIZE]
|
|
73
|
+
return bxor(raw[AES_BLOCK_SIZE:], iv)
|
|
63
74
|
|
|
64
75
|
DGST_MD5 = (1 << 0)
|
|
65
76
|
DGST_MD5SESS = (1 << 1)
|
|
@@ -72,7 +83,7 @@ DGST_PRIOS = (DGST_SHA512, DGST_SHA512SESS, DGST_SHA256, DGST_SHA256SESS, DGST_M
|
|
|
72
83
|
|
|
73
84
|
class HashOracle(object):
|
|
74
85
|
try: key # pylint: disable=used-before-assignment
|
|
75
|
-
except: key =
|
|
86
|
+
except: key = token_bytes(AES_BLOCK_SIZE * 4)
|
|
76
87
|
ac = None
|
|
77
88
|
vtime = 32 * 10**9
|
|
78
89
|
|
|
@@ -83,13 +94,16 @@ class HashOracle(object):
|
|
|
83
94
|
ts128 = clock_getntime(CLOCK_MONOTONIC) << len(DGST_PRIOS)
|
|
84
95
|
for ms in cmask:
|
|
85
96
|
ts128 |= ms
|
|
86
|
-
cryptic = self.ac.encrypt(to_bytes_be(ts128,
|
|
97
|
+
cryptic = self.ac.encrypt(to_bytes_be(ts128, AES_BLOCK_SIZE))
|
|
87
98
|
#return cryptic
|
|
88
99
|
return cryptic.decode()
|
|
89
100
|
|
|
90
101
|
def validate_challenge(self, cryptic, cmask):
|
|
91
102
|
new_ts = clock_getntime(CLOCK_MONOTONIC)
|
|
92
|
-
|
|
103
|
+
try:
|
|
104
|
+
decryptic = from_bytes_be(self.ac.decrypt(cryptic.encode()))
|
|
105
|
+
except ValueError:
|
|
106
|
+
return False
|
|
93
107
|
for ms in cmask:
|
|
94
108
|
if (ms & decryptic) == 0:
|
|
95
109
|
return False
|
|
@@ -28,24 +28,11 @@ from sippy.SipGenericHF import SipGenericHF
|
|
|
28
28
|
from sippy.Security.SipNonce import HashOracle, DGST_MD5, DGST_MD5SESS, \
|
|
29
29
|
DGST_SHA256, DGST_SHA256SESS, DGST_SHA512, DGST_SHA512SESS
|
|
30
30
|
|
|
31
|
-
from hashlib import md5, sha256
|
|
31
|
+
from hashlib import md5, new as hash_new, sha256
|
|
32
32
|
|
|
33
|
-
from Crypto.Hash import SHA512
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def __init__(self):
|
|
39
|
-
self.d = SHA512.new(truncate = '256')
|
|
40
|
-
|
|
41
|
-
def update(self, arg):
|
|
42
|
-
self.d.update(arg)
|
|
43
|
-
|
|
44
|
-
def digest(self):
|
|
45
|
-
return self.d.digest()
|
|
46
|
-
|
|
47
|
-
def hexdigest(self):
|
|
48
|
-
return self.d.hexdigest()
|
|
34
|
+
def sha512_256():
|
|
35
|
+
return hash_new('sha512_256')
|
|
49
36
|
|
|
50
37
|
_HASH_FUNC = {None:(md5, DGST_MD5), 'MD5':(md5, DGST_MD5), 'MD5-sess':(md5, DGST_MD5SESS), \
|
|
51
38
|
'SHA-256':(sha256, DGST_SHA256), 'SHA-256-sess':(sha256, DGST_SHA256SESS), \
|
|
@@ -25,9 +25,8 @@
|
|
|
25
25
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
26
|
|
|
27
27
|
from random import random
|
|
28
|
-
from hashlib import md5
|
|
29
|
-
from time import time
|
|
30
28
|
from math import floor
|
|
29
|
+
from secrets import token_hex
|
|
31
30
|
from sippy.SipConf import SipConf
|
|
32
31
|
from sippy.SipGenericHF import SipGenericHF
|
|
33
32
|
|
|
@@ -58,8 +57,7 @@ class SipCallId(SipGenericHF):
|
|
|
58
57
|
return SipCallId(self.body + str(other))
|
|
59
58
|
|
|
60
59
|
def genCallId(self):
|
|
61
|
-
|
|
62
|
-
self.body = md5(salt.encode()).hexdigest()
|
|
60
|
+
self.body = token_hex(16)
|
|
63
61
|
|
|
64
62
|
def getCanName(self, name, compact = False):
|
|
65
63
|
if compact:
|
|
@@ -24,9 +24,7 @@
|
|
|
24
24
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
25
25
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
26
|
|
|
27
|
-
from
|
|
28
|
-
from hashlib import md5
|
|
29
|
-
from time import time
|
|
27
|
+
from secrets import token_bytes
|
|
30
28
|
from sippy.SipGenericHF import SipGenericHF
|
|
31
29
|
|
|
32
30
|
class SipCiscoGUID(SipGenericHF):
|
|
@@ -41,9 +39,8 @@ class SipCiscoGUID(SipGenericHF):
|
|
|
41
39
|
if ciscoGUID != None:
|
|
42
40
|
self.ciscoGUID = ciscoGUID
|
|
43
41
|
else:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
self.ciscoGUID = (int(s[0:8], 16), int(s[8:16], 16), int(s[16:24], 16), int(s[24:32], 16))
|
|
42
|
+
s = token_bytes(16)
|
|
43
|
+
self.ciscoGUID = tuple(int.from_bytes(s[i:i + 4], 'big') for i in range(0, 16, 4))
|
|
47
44
|
|
|
48
45
|
def parse(self):
|
|
49
46
|
self.ciscoGUID = tuple([int(x) for x in self.body.split('-', 3)])
|
|
@@ -25,9 +25,8 @@
|
|
|
25
25
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
26
|
|
|
27
27
|
from random import random
|
|
28
|
-
from hashlib import md5
|
|
29
|
-
from time import time
|
|
30
28
|
from math import floor
|
|
29
|
+
from secrets import token_hex
|
|
31
30
|
from sippy.SipAddressHF import SipAddressHF
|
|
32
31
|
from sippy.SipAddress import SipAddress
|
|
33
32
|
from sippy.SipURL import SipURL
|
|
@@ -57,8 +56,7 @@ class SipFrom(SipAddressHF):
|
|
|
57
56
|
return self.address.getParam('tag')
|
|
58
57
|
|
|
59
58
|
def genTag(self):
|
|
60
|
-
|
|
61
|
-
self.address.setParam('tag', md5(salt.encode()).hexdigest())
|
|
59
|
+
self.address.setParam('tag', token_hex(16))
|
|
62
60
|
|
|
63
61
|
def setTag(self, value):
|
|
64
62
|
self.address.setParam('tag', value)
|
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
26
|
|
|
27
27
|
from random import random
|
|
28
|
-
from
|
|
29
|
-
from time import time
|
|
28
|
+
from secrets import token_hex
|
|
30
29
|
from sippy.SipGenericHF import SipGenericHF
|
|
31
30
|
from sippy.SipConf import SipConf
|
|
32
31
|
from sippy.ESipHeaderCSV import ESipHeaderCSV
|
|
@@ -131,8 +130,7 @@ class SipVia(SipGenericHF):
|
|
|
131
130
|
return SipVia(cself=self)
|
|
132
131
|
|
|
133
132
|
def genBranch(self):
|
|
134
|
-
|
|
135
|
-
self.params['branch'] = 'z9hG4bK' + md5(salt.encode()).hexdigest()
|
|
133
|
+
self.params['branch'] = 'z9hG4bK' + token_hex(16)
|
|
136
134
|
|
|
137
135
|
def getBranch(self):
|
|
138
136
|
return self.params.get('branch', None)
|