pyVoIP icon indicating copy to clipboard operation
pyVoIP copied to clipboard

Setup code will not run for me. Issue with a key when hashing Auth request.

Open Cabarnacus opened this issue 2 years ago • 24 comments

Not sure where to go from here. Tried to set up as a client of 3CX PBX (Self Hosted). pyVoIP installed from pip. Traceback is from the example quick start setup code. (KeyError: 'realm')?

The instance of VoIPPhone is set up as follows:

phone=VoIPPhone("10.0.50.100", 5060, "4004", "plOP1QNVuV", callCallback=answer, myIP="192.168.200.5")

All other code is copy and paste from readme file.

TODO: Add 500 Error on Receiving SIP Response
Traceback (most recent call last):
  File "/home/grant/python/voip/main.py", line 12, in <module>
    phone.start()
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/VoIP.py", line 423, in start
    self.sip.start()
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/SIP.py", line 579, in start
    register = self.register()
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/SIP.py", line 906, in register
    regRequest = self.genRegister(response)
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/SIP.py", line 631, in genRegister
    response = self.genAuthorization(request)
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/SIP.py", line 623, in genAuthorization
    HA1 = hashlib.md5(self.username.encode('utf8')+b':'+request.authentication['realm'].encode('utf8')+b':'+self.password.encode('utf8')).hexdigest().encode('utf8')
KeyError: 'realm'

Cabarnacus avatar May 23 '22 02:05 Cabarnacus

@Cabarnacus Were you able to get resolve the issue? I am currently stuck in the same spot @tayler6000 Any chance we could get your input?

astrotrupti avatar Jul 27 '22 18:07 astrotrupti

@astrotrupti I'm afraid not. I shelved my VoIP project for just now. I will probably look for an alternative package to this.

Cabarnacus avatar Jul 27 '22 18:07 Cabarnacus

@Cabarnacus Thanks! Could you please post here if you figure out how to solve it or if you find another package

astrotrupti avatar Jul 27 '22 18:07 astrotrupti

@astrotrupti 👍 will do!

Cabarnacus avatar Jul 27 '22 18:07 Cabarnacus

Hard to know for sure without a packet capture, but it looks like the PBX may not be following the authentication RFC properly. If I can get a packet capture I can make a patch for this case.

tayler6000 avatar Jul 27 '22 22:07 tayler6000

I somehow remember there was an issue with this in current master mostly caused by the fake request to non Asterisk. (I assume you are using Master) Think this was fixed with #10 in v1.6.0-dev branch. You could give it a try

Input-BDF avatar Jul 28 '22 09:07 Input-BDF

I somehow remember there was an issue with this in current master mostly caused by the fake request to non Asterisk. (I assume you are using Master) Think this was fixed with #10 in v1.6.0-dev branch. You could give it a try

I will try another release this weekend if I get a moment. Thanks. 👍

Cabarnacus avatar Jul 28 '22 09:07 Cabarnacus

@tayler6000 Here's a screenshot of the patch. It says it binds but I get the same exact error as @Cabarnacus. new

astrotrupti avatar Jul 28 '22 14:07 astrotrupti

@Input-BDF I tried using v1.6.0-dev. My line doesn't have a password so I enter '' in the password section. I get invalid username and password and it throws "400 Malformed Form, fix your code"

astrotrupti avatar Jul 28 '22 14:07 astrotrupti

@astrotrupti This may actually be due to the fact that you don't have a password. I'll look into it.

tayler6000 avatar Jul 28 '22 15:07 tayler6000

@astrotrupti This may actually be due to the fact that you don't have a password. I'll look into it.

Could also be something with 3CX PBX, with which I personaly have no experience. @astrotrupti if you have a working line without password you could sniff up these packages and compare with pyVoips register requests.

Got my local vanilla Kamailio back working and tested latest 1.6.0-dev with the basic example and passwd='' Worked but (at least in my case) I had to specify myIP. Without I get 403: Not relaying.

@tayler6000 The original problem with the key error came somehow from the fake request in register() before sending user auth which was replaced with genFirstRequest/gen_first_response in 1.6.0 . From there the SIP-server replied without a realm in the response under some conditions.

Input-BDF avatar Jul 28 '22 16:07 Input-BDF

@Input-BDF Unfortunately I get the same error - Invalid username or Password for SIP server when I do what you did with 1.6.0-dev. Thanks for checking though

astrotrupti avatar Jul 28 '22 18:07 astrotrupti

@tayler6000 @Input-BDF @Cabarnacus I got it to register successfully and it also says Busy when the callback is set to None. To do that I commented out both "realm" and "nonce" wherever they appeared. However, now, probably but I am not sure due to lack of knowledge, because I got rid of "realm" and "nonce" the algorithm doesn't enter def answer() function from the example or the call goes to unknown and never gets answered. Do you all have any suggestions here?

astrotrupti avatar Aug 01 '22 16:08 astrotrupti

@astrotrupti do have a password for your phone setup?

tayler6000 avatar Sep 22 '22 05:09 tayler6000

@Cabarnacus Can you confirm if this is still an issue in v1.6.2?

tayler6000 avatar Sep 26 '22 16:09 tayler6000

I'm starting with this package (v1.6.2), trying to make a call with Yeaster tg100. But I can't register, I always have - Invalid username or Password for SIP server. I tested the device's config with zoiper client and everything works well.

cfpena avatar Sep 27 '22 03:09 cfpena

@cfpena Can you please install pyVoIP from master and then add

import pyVoIP
pyVoIP.DEBUG = True

to the beginning of your code? Then reply with the debug output minus the packet that says "(DO NOT SHARE THIS PACKET)"? This will help us to debug the regex to fix the issue for your server.

tayler6000 avatar Sep 27 '22 05:09 tayler6000

@tayler6000

==================================================
Unauthorized, SIP Message Log:

SENT
REGISTER sip:192.168.10.210 SIP/2.0
Via: SIP/2.0/UDP 192.168.10.185:5060;branch=z9hG4bK4ccbf433c29e45b4b26853666;rport
From: "20001" <sip:[email protected]>;tag=9d84de77
To: "20001" <sip:[email protected]>
Call-ID: [email protected]:5060
CSeq: 1 REGISTER
Contact: <sip:[email protected]:5060;transport=UDP>;+sip.instance="<urn:uuid:7AB37954-1EC7-4C0D-AB4C-B0DD6C0876F4>"
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': ('192.168.10.185', '5060'), 'branch': 'z9hG4bK4ccbf433c29e45b4b26853666', 'received': '192.168.10.185', 'rport': '5060'}]
From: {'raw': '"20001" <sip:[email protected]>', 'tag': '9d84de77', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
To: {'raw': '"20001" <sip:[email protected]>', 'tag': 'as226f9890', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
Call-ID: [email protected]:5060
CSeq: {'check': '1', 'method': 'REGISTER'}
Server: TG100
Allow: ['INVITE', 'ACK', 'CANCEL', 'OPTIONS', 'BYE', 'REFER', 'SUBSCRIBE', 'NOTIFY', 'INFO']
Supported: ['replaces', 'timer']
WWW-Authenticate: {'algorithm': 'MD5', 'realm': 'asterisk', 'nonce': '03bbeb46'}
Content-Length: 0

Body:

Raw:
b'SIP/2.0 401 Unauthorized\r\nVia: SIP/2.0/UDP 192.168.10.185:5060;branch=z9hG4bK4ccbf433c29e45b4b26853666;received=192.168.10.185;rport=5060\r\nFrom: "20001" <sip:[email protected]>;tag=9d84de77\r\nTo: "20001" <sip:[email protected]>;tag=as226f9890\r\nCall-ID: [email protected]:5060\r\nCSeq: 1 REGISTER\r\nServer: TG100\r\nAllow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO\r\nSupported: replaces, timer\r\nWWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="03bbeb46"\r\nContent-Length: 0\r\n\r\n'

SENT (DO NOT SHARE THIS PACKET)
*********************


RECEIVED
Status: 401 Unauthorized

Headers:
Via: [{'type': 'SIP/2.0/UDP', 'address': ('192.168.10.185', '5060'), 'branch': 'z9hG4bKeddd669af1c44200aded2be25', 'received': '192.168.10.185', 'rport': '5060'}]
From: {'raw': '"20001" <sip:[email protected]>', 'tag': '9d84de77', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
To: {'raw': '"20001" <sip:[email protected]>', 'tag': 'as00b6278f', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
Call-ID: [email protected]:5060
CSeq: {'check': '2', 'method': 'REGISTER'}
Server: TG100
Allow: ['INVITE', 'ACK', 'CANCEL', 'OPTIONS', 'BYE', 'REFER', 'SUBSCRIBE', 'NOTIFY', 'INFO']
Supported: ['replaces', 'timer']
WWW-Authenticate: {'algorithm': 'MD5', 'realm': 'asterisk', 'nonce': '4256fa21'}
Content-Length: 0

Body:

Raw:
b'SIP/2.0 401 Unauthorized\r\nVia: SIP/2.0/UDP 192.168.10.185:5060;branch=z9hG4bKeddd669af1c44200aded2be25;received=192.168.10.185;rport=5060\r\nFrom: "20001" <sip:[email protected]>;tag=9d84de77\r\nTo: "20001" <sip:[email protected]>;tag=as00b6278f\r\nCall-ID: [email protected]:5060\r\nCSeq: 2 REGISTER\r\nServer: TG100\r\nAllow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO\r\nSupported: replaces, timer\r\nWWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="4256fa21"\r\nContent-Length: 0\r\n\r\n'
==================================================
Traceback (most recent call last):
  File "/Users/cfpena/projects/test/pyVoIP/main.py", line 84, in <module>
    phone.start()
  File "/Users/cfpena/projects/test/pyVoIP/pyVoIP/VoIP.py", line 656, in start
    self.sip.start()
  File "/Users/cfpena/projects/test/pyVoIP/pyVoIP/SIP.py", line 949, in start
    self.register()
  File "/Users/cfpena/projects/test/pyVoIP/pyVoIP/SIP.py", line 1743, in register
    raise InvalidAccountInfoError(
pyVoIP.SIP.InvalidAccountInfoError: Invalid Username or Password for SIP server 192.168.10.210:5060

I really appreciate your help. Thanks in advance

cfpena avatar Sep 27 '22 22:09 cfpena

@tayler6000

==================================================
Unauthorized, SIP Message Log:

SENT
REGISTER sip:192.168.10.210 SIP/2.0
Via: SIP/2.0/UDP 192.168.10.185:5060;branch=z9hG4bK4ccbf433c29e45b4b26853666;rport
From: "20001" <sip:[email protected]>;tag=9d84de77
To: "20001" <sip:[email protected]>
Call-ID: [email protected]:5060
CSeq: 1 REGISTER
Contact: <sip:[email protected]:5060;transport=UDP>;+sip.instance="<urn:uuid:7AB37954-1EC7-4C0D-AB4C-B0DD6C0876F4>"
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': ('192.168.10.185', '5060'), 'branch': 'z9hG4bK4ccbf433c29e45b4b26853666', 'received': '192.168.10.185', 'rport': '5060'}]
From: {'raw': '"20001" <sip:[email protected]>', 'tag': '9d84de77', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
To: {'raw': '"20001" <sip:[email protected]>', 'tag': 'as226f9890', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
Call-ID: [email protected]:5060
CSeq: {'check': '1', 'method': 'REGISTER'}
Server: TG100
Allow: ['INVITE', 'ACK', 'CANCEL', 'OPTIONS', 'BYE', 'REFER', 'SUBSCRIBE', 'NOTIFY', 'INFO']
Supported: ['replaces', 'timer']
WWW-Authenticate: {'algorithm': 'MD5', 'realm': 'asterisk', 'nonce': '03bbeb46'}
Content-Length: 0

Body:

Raw:
b'SIP/2.0 401 Unauthorized\r\nVia: SIP/2.0/UDP 192.168.10.185:5060;branch=z9hG4bK4ccbf433c29e45b4b26853666;received=192.168.10.185;rport=5060\r\nFrom: "20001" <sip:[email protected]>;tag=9d84de77\r\nTo: "20001" <sip:[email protected]>;tag=as226f9890\r\nCall-ID: [email protected]:5060\r\nCSeq: 1 REGISTER\r\nServer: TG100\r\nAllow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO\r\nSupported: replaces, timer\r\nWWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="03bbeb46"\r\nContent-Length: 0\r\n\r\n'

SENT (DO NOT SHARE THIS PACKET)
*********************


RECEIVED
Status: 401 Unauthorized

Headers:
Via: [{'type': 'SIP/2.0/UDP', 'address': ('192.168.10.185', '5060'), 'branch': 'z9hG4bKeddd669af1c44200aded2be25', 'received': '192.168.10.185', 'rport': '5060'}]
From: {'raw': '"20001" <sip:[email protected]>', 'tag': '9d84de77', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
To: {'raw': '"20001" <sip:[email protected]>', 'tag': 'as00b6278f', 'address': '[email protected]', 'number': '20001', 'caller': '20001" ', 'host': '192.168.10.210'}
Call-ID: [email protected]:5060
CSeq: {'check': '2', 'method': 'REGISTER'}
Server: TG100
Allow: ['INVITE', 'ACK', 'CANCEL', 'OPTIONS', 'BYE', 'REFER', 'SUBSCRIBE', 'NOTIFY', 'INFO']
Supported: ['replaces', 'timer']
WWW-Authenticate: {'algorithm': 'MD5', 'realm': 'asterisk', 'nonce': '4256fa21'}
Content-Length: 0

Body:

Raw:
b'SIP/2.0 401 Unauthorized\r\nVia: SIP/2.0/UDP 192.168.10.185:5060;branch=z9hG4bKeddd669af1c44200aded2be25;received=192.168.10.185;rport=5060\r\nFrom: "20001" <sip:[email protected]>;tag=9d84de77\r\nTo: "20001" <sip:[email protected]>;tag=as00b6278f\r\nCall-ID: [email protected]:5060\r\nCSeq: 2 REGISTER\r\nServer: TG100\r\nAllow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO\r\nSupported: replaces, timer\r\nWWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="4256fa21"\r\nContent-Length: 0\r\n\r\n'
==================================================
Traceback (most recent call last):
  File "/Users/cfpena/projects/test/pyVoIP/main.py", line 84, in <module>
    phone.start()
  File "/Users/cfpena/projects/test/pyVoIP/pyVoIP/VoIP.py", line 656, in start
    self.sip.start()
  File "/Users/cfpena/projects/test/pyVoIP/pyVoIP/SIP.py", line 949, in start
    self.register()
  File "/Users/cfpena/projects/test/pyVoIP/pyVoIP/SIP.py", line 1743, in register
    raise InvalidAccountInfoError(
pyVoIP.SIP.InvalidAccountInfoError: Invalid Username or Password for SIP server 192.168.10.210:5060

I really appreciate your help. Thanks in advance

To be honest, I see nothing wrong with this... Does anyone else see an issue here?

tayler6000 avatar Sep 27 '22 22:09 tayler6000

@tayler6000

I was trying to check the problem with debugging and wireshark but couldn't find anything. But when I changed to pip version 1.5.6, everything worked fine.

For version 1.5.6 to work I had to disable the 'qualify' option. The reason is that the "option" method is not allowed. But in the current master branch and pip version 1.6 I couldn't find the problem.

cfpena avatar Sep 30 '22 00:09 cfpena

@tayler6000

I was trying to check the problem with debugging and wireshark but couldn't find anything. But when I changed to pip version 1.5.6, everything worked fine.

For version 1.5.6 to work I had to disable the 'qualify' option. The reason is that the "option" method is not allowed. But in the current master branch and pip version 1.6 I couldn't find the problem.

This is very strange. If you're comfortable, could you send another debug log like you did before and the password you use for the sip account? My email is [email protected] this is really the only thing I can think of to debug this further.

tayler6000 avatar Sep 30 '22 01:09 tayler6000

@tayler6000 I was trying to check the problem with debugging and wireshark but couldn't find anything. But when I changed to pip version 1.5.6, everything worked fine. For version 1.5.6 to work I had to disable the 'qualify' option. The reason is that the "option" method is not allowed. But in the current master branch and pip version 1.6 I couldn't find the problem.

This is very strange. If you're comfortable, could you send another debug log like you did before and the password you use for the sip account? My email is [email protected] this is really the only thing I can think of to debug this further.

I've already made a separate script to compare the MD5 hash response and it's exactly the same. I will send you an email tomorrow with the requested information and some more data.

cfpena avatar Sep 30 '22 03:09 cfpena

@cfpena Can you please install pyVoIP from master and then add

import pyVoIP
pyVoIP.DEBUG = True

to the beginning of your code? Then reply with the debug output minus the packet that says "(DO NOT SHARE THIS PACKET)"? This will help us to debug the regex to fix the issue for your server.

As requested see below. There was no section titled "(DO NOT SHARE THIS PACKET)"?

I have tested this configuration out with a softphone (Grandstream wave) and it works fine. One thing to note is that GS Wave gives the options of the "SIP User ID" which is typically the extension number, and a "SIP Authentication ID" which is a randomly generated username (3CX endorse this for security reasons). Both have to be provided for registration to work.

For the purposes of this test I have configured the Authentication ID to the same as the User ID (server side). I have done this as the class VoIPPhone takes the argument "username". I am unsure if this is meant to be the extension (user id) or the authentication ID.

I have not used Asterisk based SIP servers before but i'm sure I read somewhere that there no distinction between a User ID and and Authentication ID. Maybe since the intended use of pyVoIP is to be paired with Asterisk then it is not compatible with 3CX at this time.

Proxy auth required
Status: 407 Proxy Authentication Required

Headers:
Via: [{'type': 'SIP/2.0/UDP', 'address': ('192.168.1.115', '5060'), 'branch': 'z9hG4bKa204b49c872e4536ad20ab0fe', 'rport': '5060'}]
Proxy-Authenticate: Digest nonce="414d53596337438754:e4245f22523b9adb224fe90d7c52e239",algorithm=MD5,realm="3CXPhoneSystem"
To: {'raw': '"4004"<sip:[email protected]>', 'tag': 'c61b1d0b', 'address': '[email protected]', 'number': '4004', 'caller': '4004', 'host': '10.0.50.100'}
From: {'raw': '"4004" <sip:[email protected]>', 'tag': 'a07c805b', 'address': '[email protected]', 'number': '4004', 'caller': '4004" ', 'host': '10.0.50.100'}
Call-ID: [email protected]:5060
CSeq: {'check': '1', 'method': 'REGISTER'}
Content-Length: 0

Body:

Raw:
b'SIP/2.0 407 Proxy Authentication Required\r\nVia: SIP/2.0/UDP 192.168.1.115:5060;branch=z9hG4bKa204b49c872e4536ad20ab0fe;rport=5060\r\nProxy-Authenticate: Digest nonce="414d53596337438754:e4245f22523b9adb224fe90d7c52e239",algorithm=MD5,realm="3CXPhoneSystem"\r\nTo: "4004"<sip:[email protected]>;tag=c61b1d0b\r\nFrom: "4004" <sip:[email protected]>;tag=a07c805b\r\nCall-ID: [email protected]:5060\r\nCSeq: 1 REGISTER\r\nContent-Length: 0\r\n\r\n'
b'SIP/2.0 407 Proxy Authentication Required\r\nVia: SIP/2.0/UDP 192.168.1.115:5060;branch=z9hG4bKa204b49c872e4536ad20ab0fe;rport=5060\r\nProxy-Authenticate: Digest nonce="414d53596337438754:e4245f22523b9adb224fe90d7c52e239",algorithm=MD5,realm="3CXPhoneSystem"\r\nTo: "4004"<sip:[email protected]>;tag=c61b1d0b\r\nFrom: "4004" <sip:[email protected]>;tag=a07c805b\r\nCall-ID: [email protected]:5060\r\nCSeq: 1 REGISTER\r\nContent-Length: 0\r\n\r\n'
Traceback (most recent call last):
  File "/home/grant/python/voip/main.py", line 17, in <module>
    phone.start()
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/VoIP.py", line 656, in start
    self.sip.start()
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/SIP.py", line 949, in start
    self.register()
  File "/home/grant/python/voip/venv/lib/python3.10/site-packages/pyVoIP/SIP.py", line 1794, in register
    raise InvalidAccountInfoError(
pyVoIP.SIP.InvalidAccountInfoError: Invalid Username or Password for SIP server 10.0.50.100:5060

Cabarnacus avatar Sep 30 '22 20:09 Cabarnacus

@Cabarnacus You would have needed to install from source to get that extra level of debug, however this explains the issue. PyVoIP does not currently support proxies. Reference #69

tayler6000 avatar Sep 30 '22 20:09 tayler6000