pyVoIP
pyVoIP copied to clipboard
Still have FritzBox authentication error on 1.6.2
Hi, I've updated the library to the last 1.6.2 version but I still have problems authenticating to my fritz box.


i have the same error:
- pyVoIP:
REGISTER sip:192.168.11.7 SIP/2.0
Via: SIP/2.0/UDP 192.168.11.88:5060;branch=z9hG4bK088986c7b2844e5797488dd0f;rport
From: "101" <sip:[email protected]>;tag=13639361
To: "101" <sip:[email protected]>
Call-ID: [email protected]:5060
CSeq: 1 REGISTER
Contact: <sip:[email protected]:5060;transport=UDP>;+sip.instance="<urn:uuid:533EA043-3D65-47B8-A23B-D4345D7B3071>"
Allow: INVITE, ACK, BYE, CANCEL
Max-Forwards: 70
Allow-Events: org.3gpp.nwinitdereg
User-Agent: pyVoIP 1.6.2
Expires: 120
Content-Length: 0
- Asterisk:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.11.88:5060;branch=z9hG4bK088986c7b2844e5797488dd0f;received=192.168.11.88;rport=5060
From: "101" <sip:[email protected]>;tag=13639361
To: "101" <sip:[email protected]>;tag=as7f240d2c
Call-ID: [email protected]:5060
CSeq: 1 REGISTER
Server: FPBX-13.0.74(11.21.0)
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=**MD5**, **realm**="asterisk", **nonce**="0c943d28"
Content-Length: 0
- pyVoIP:
REGISTER sip:192.168.11.7 SIP/2.0
Via: SIP/2.0/UDP 192.168.11.88:5060;branch=z9hG4bKd95ce81ab1e54bcaa1150c8b3;rport
From: "101" <sip:[email protected]>;tag=13639361
To: "101" <sip:[email protected]>
Call-ID: [email protected]:5060
CSeq: 2 REGISTER
Contact: <sip:[email protected]:5060;transport=UDP>;+sip.instance="<urn:uuid:533EA043-3D65-47B8-A23B-D4345D7B3071>"
Allow: INVITE, ACK, BYE, CANCEL
Max-Forwards: 70
Allow-Events: org.3gpp.nwinitdereg
User-Agent: pyVoIP 1.6.2
Expires: 120
Authorization: Digest **username**="101",**realm**="asterisk",**nonce**="0c943d28",uri="sip:192.168.11.7;transport=UDP",**response**="8c8fff877ffa698a19bada31ed1fa46d",algorithm=MD5
Content-Length: 0
(password = "123123")
- Asterisk:
SIP/2.0 401 **Unauthorized**
Via: SIP/2.0/UDP 192.168.11.88:5060;branch=z9hG4bKd95ce81ab1e54bcaa1150c8b3;received=192.168.11.88;rport=5060
From: "101" <sip:[email protected]>;tag=13639361
To: "101" <sip:[email protected]>;tag=as55b5d463
Call-ID: [email protected]:5060
CSeq: 2 REGISTER
Server: FPBX-13.0.74(11.21.0)
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="3bb11a60"
Content-Length: 0
- pyVoIP: Invalid Username or Password for SIP server 192.168.11.7:5060
how to check the response?
I did all the hashing myself and it all checks out so I'm not sure what the issue is here @AndreySozonov There seems to have been some semi recent RFCs updating the WWW-Authenticate scheme but they recommend not using algorithm=MD5 and the use of additional parameters, so it does not seem to be using it. Did a previous version of pyVoIP work for you?
Also you can use the following code for easier debugging on registry, but you may need to install from source instead of PyPI.
import pyVoIP
pyVoIP.DEBUG = True
Also, please be sure to use code blocks with posting code with Ctrl+e.
I've gotten to the point where I have downloaded the source code to Asterisk 11 to see where the error is happening. However my C is rusty, if anyone can figure out why some people are getting an error while other's are not, I would be greatly appreciative.
I've also reinstalled it from the source and enabled debugging. This is the message
SENT
REGISTER sip:fritz.box SIP/2.0
Via: SIP/2.0/UDP 0.0.0.0:5060;branch=z9hG4bK138a8aa6cabd4b8c92c2b325d;rport
From: "alarmnegozio" <sip:[email protected]>;tag=2a7547e5
To: "alarmnegozio" <sip:[email protected]>
Call-ID: [email protected]:5060
CSeq: 1 REGISTER
Contact: <sip:[email protected]:5060;transport=UDP>;+sip.instance="<urn:uuid:DA030FE3-24AE-4ADE-86DD-AC5FD0A37397>"
Allow: INVITE, ACK, BYE, CANCEL
Max-Forwards: 70
Allow-Events: org.3gpp.nwinitdereg
User-Agent: pyVoIP 1.6.2
Expires: 120
Content-Length: 0
RECEIVED
Status: 401 Unauthorized
Headers:
Via: [{'type': 'SIP/2.0/UDP', 'address': ('0.0.0.0', '5060'), 'branch': 'z9hG4bK138a8aa6cabd4b8c92c2b325d', 'rport': '5060', 'received': '192.168.1.200'}]
From: {'raw': '"alarmnegozio" <sip:[email protected]>', 'tag': '2a7547e5', 'address': '[email protected]', 'number': 'alarmnegozio', 'caller': 'alarmnegozio" ', 'host': 'fritz.box'}
To: {'raw': '"alarmnegozio" <sip:[email protected]>', 'tag': '6DC5C2CCC210248B', 'address': '[email protected]', 'number': 'alarmnegozio', 'caller': 'alarmnegozio" ', 'host': 'fritz.box'}
Call-ID: [email protected]:5060
CSeq: {'check': '1', 'method': 'REGISTER'}
WWW-Authenticate: {'realm': 'fritz.box', 'nonce': '0648C4E9C7FDC385'}
User-Agent: FRITZ!OS
Content-Length: 0
Body:
Raw:
b'SIP/2.0 401 Unauthorized\r\nVia: SIP/2.0/UDP 0.0.0.0:5060;branch=z9hG4bK138a8aa6cabd4b8c92c2b325d;rport=5060;received=192.168.1.200\r\nFrom: "alarmnegozio" <sip:[email protected]>;tag=2a7547e5\r\nTo: "alarmnegozio" <sip:[email protected]>;tag=6DC5C2CCC210248B\r\nCall-ID: [email protected]:5060\r\nCSeq: 1 REGISTER\r\nWWW-Authenticate: Digest realm="fritz.box", nonce="0648C4E9C7FDC385"\r\nUser-Agent: FRITZ!OS\r\nContent-Length: 0\r\n\r\n'
RECEIVED
Status: 401 Unauthorized
Headers:
Via: [{'type': 'SIP/2.0/UDP', 'address': ('0.0.0.0', '5060'), 'branch': 'z9hG4bK658a06ae91aa4db3a3b094cc7', 'rport': '5060', 'received': '192.168.1.200'}]
From: {'raw': '"alarmnegozio" <sip:[email protected]>', 'tag': '2a7547e5', 'address': '[email protected]', 'number': 'alarmnegozio', 'caller': 'alarmnegozio" ', 'host': 'fritz.box'}
To: {'raw': '"alarmnegozio" <sip:[email protected]>', 'tag': '68CE7BCC0655CAE8', 'address': '[email protected]', 'number': 'alarmnegozio', 'caller': 'alarmnegozio" ', 'host': 'fritz.box'}
Call-ID: [email protected]:5060
CSeq: {'check': '2', 'method': 'REGISTER'}
WWW-Authenticate: {'realm': 'fritz.box', 'nonce': 'AB140D882868700D'}
User-Agent: FRITZ!OS
Content-Length: 0
@mattiarainieri @AndreySozonov What is the username associated with these numbers?
I don't see any instance of this check in Asterisk 11 that I found, however it may be worth noting that this is said in RFC 3261 Section 8.1.1.4
Note that when requests are retried after certain failure responses that solicit an amendment to a request (for example, a challenge for authentication), these retried requests are not considered new requests, and therefore do not need new Call-ID header fields; see Section 8.1.3.5.
This doesn't use any keywords from BCP 14 but that doesn't mean that an engineer hasn't relied on this behavior for routing messages, and we do not currently do this. Will be implementing this in 2.0.
@tayler6000 the voip username is “alarmnegozio”
User "101". The registration error occurred when connecting to different versions of Asterisk (I tested 11 and 13). MicroSip softphone with the same credentials connected without problems. Perhaps the reason is related to the OS used: me and @mattiarainieri used Asterisk on Raspberry Pi. Tomorrow i will test pyVoIP on another server with an asterisk.
Hello again. I'm wondering what's going wrong there. Since I'm not that good at reading foreign code but much better in implementing my own I experimented with a simple protocol class structure for SIP and there, authentication against my fritz.box works fine. What's missing here now is RTP protocol so my experiments are pretty useless so far. I don't really want to build a concurrent library so I don't think that I'll complete that thing.. unless someone tells me how to send and receive audio data via rtp..
Maybe my source helps you to figure out what's wrong with yours: https://github.com/TecDroiD/simple_voip
Edit: didn't clean up my files.. this one should be the interesting part: https://github.com/TecDroiD/simple_voip/blob/master/voip/sipmessage.py
@TecDroiD Thank you, this will help a lot
@TecDroiD Our authentication systems are the same so I'm still unsure what the issue is. Could you maybe upload a packet capture of each system trying to authenticate?
well.. there seems to be some more binary data in your capture pyvoip.txt simple_voip.txt
well.. there seems to be some more binary data in your capture
Can you merge my PR and then get me the simple_voip again? Your code has some significantly malformed headers and I'm genuinely concerned you stumbled across a vulnerability in fritz.box.
simple_voip.txt here it is. I end up unauthorized now
here it is. I end up unauthorized now
Ok, I don't have access to a Fritz box to test, but I have a feeling if you delete the comma before the response it'll work on your box because it'll fail to read it and assume it's right. If deleting that comma makes it work I highly recommend you contact fritz box and tell them they have a vulnerability in their code.
Honestly, they'll probably give you a bounty for it.
We'll see.. still, I cannot make any call yet
Just found something else: in my sipmessage.py, line 160 you changed t3cDr01d to z9hG4bKt3cDr01d. When I roll this back, I can make a call.. Also when I remove only one character from your id text. currently looking for that entry in your code but maybe the entry is too long for fritzbox?
Hmm, weird. It's a RFC requirement to have that prefix for the branch. I'm pretty sure I referenced it in the commit but if you just search for magic cookie in the RFC you'll find it.
def gen_branch(self, length=32) -> str:
"""
Generate unique branch id according to
https://datatracker.ietf.org/doc/html/rfc3261#section-8.1.1.7
"""
branchid = uuid.uuid4().hex[: length - 7]
return f"z9hG4bK{branchid}"
as far as i understood, that magic cookie identifies the newer version of SIP RFC. Maybe it enables some extra checks on fritzos? I already found out that there are some optional entries (think it was Contact) which are required by fritzbox.. What if there's just something stupid missing, just because its optional?
I think you're right about the extra checks. The RFC says the branch should be globally unique if following the new standard. So maybe the second register needs to use a different branch not the same one from the original request?
@xyc0815 Welcome back, please, do you have any thoughts on this?
When I use web SIP services I had problems with username in contact in the first request (def gen_first_response(self, deregister=False))
regRequest += (
"Contact: "
+ f"<sip:{self.username}@{self.bind_ip}:{self.bind_port};"
+ "transport=UDP>;+sip.instance="
+ f'"<urn:uuid:{self.urnUUID}>"\r\n'
)
So I don't use the username in this function. Because I've can also use a SIP proxy in between, I've other functions to get the right IP and port.
regRequest += 'Contact: ' + \
f'<sip:{self.get_my_ip()}:{self.get_my_port()};' + \
'transport=UDP>;+sip.instance=' + \
f'"<urn:uuid:{self.urnUUID}>"\r\n'
With the second register call I've also send the username in the contact element. Maybe we have here the same problem.
I also wasn't able to register or make a call with FritzBox. I debugged this a lot and compared packet captures with those from MicroSIP client.
I modified pyVoip until I could make it work. Eventually, it was all about the Call-ID
field and the branch
.
For REGISTER
with authorization there are two requests. The Call-ID
needs to be the same for first request without and for the second request with authorization.
For INVITE
I figured, the Call-ID
should also remain the same troughout the whole transaction (first and second request) however the branch
needs to be different when doing authentication with the second INVITE
request. The current implementation keeps the same branch for both.
Hi @philipp-fischer , could you please share your changes? I'm trying to authenticate pyvoip to my fritz box just to receive the signalling for detecting calls from a dect doorbell. The fritz internal call monitor does not log or signal internal calls, but I would like to log them and maybe add smart home actions such as "doorbell rings --> turn on light if it's dark"
Hi @philipp-fischer , could you please share your changes? I'm trying to authenticate pyvoip to my fritz box just to receive the signalling for detecting calls from a dect doorbell. The fritz internal call monitor does not log or signal internal calls, but I would like to log them and maybe add smart home actions such as "doorbell rings --> turn on light if it's dark"
In the end I resorted to an entirely new mini-implementation I created. I can share that when I return from vacation.
Hello,
As far as I understand, the connection runs via UDP. In the following project, the connection runs via TCP by default: https://github.com/astoeckel/femtosip For me it works perfectly on the Fritz!Box 7490 with TCP. With UDP it gives me an authentication error. I am called anyway, but with an error message. That might solve the problem. An optional choice for UDP or TCP would be desirable.
Good luck
EDIT: I am called NOT if I use UDP with femtosip. Only TCP
@hartwigt: Here is the code I created for the purpose of making a call: https://gist.github.com/philipp-fischer/d7fa8df8541955863aebcf24291af007 It also contains a stub to register with the server to receive calls, but I never tested this. Maybe this femtosip that @epicbananana posted above is worth a try?
I will test it