mumble-voip / mumble

Mumble is an open-source, low-latency, high quality voice chat software.
https://www.mumble.info
Other
6.28k stars 1.11k forks source link

Self-compiled Murmur certificate error #4298

Closed TerryGeng closed 4 years ago

TerryGeng commented 4 years ago

I was testing the murmur server built on my macOS. When a client connects to the server, the connection will be dropped and something like

<W>2020-06-17 14:05:37.351 1 => <1:(-1)> New connection: 127.0.0.1:52800
<W>2020-06-17 14:05:37.351 Connection: Failed to set TOS for TCP Socket
<W>2020-06-17 14:05:37.405 1 => <1:(-1)> Connection closed: SecPKCS12Import returned no items [21]

is shown in the log. Looks like Murmur failed to import its self-signed certificate into macOS's keychain. Even running Murmur with sudo cannot solve this problem.

Interestingly, I tried the binary downloaded from mumble.info and it works without this error.

In the end, I have to generate a certificate by myself and manually import that certificate into the keychain to avoid this problem.

I think I'm once again trapped in the security system of macOS but have no idea what is the cause.

Krzmbrzl commented 4 years ago

The error message seems to come from https://github.com/mumble-voip/mumble/blob/73c535b25d1607131245f4969c638c686e506245/src/Connection.cpp#L77-L79 and the function is documented at https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getsockopt.2.html

I think you should probably catch the actual return value of that function and then check whether it's one of the error codes listed in the docs. Once we have the actual error code, we might get further insights as to what's wrong :thinking:

TerryGeng commented 4 years ago

The error code is 22,

22 EINVAL Invalid argument. Some invalid argument was supplied. (For example, specifying an undefined signal to a signal or kill function).

But it looks like this error message always appears, even if I manually fix the certificate issue by the way mentioned above

<W>2020-06-17 17:03:01.747 1 => <3:(-1)> New connection: 127.0.0.1:54180
<W>2020-06-17 17:03:01.747 Connection: Failed to set TOS for TCP Socket
<W>2020-06-17 17:03:03.460 1 => <3:(-1)> Strong certificate for Terry Geng <gengyanda@gmail.com> (signed by Terry Geng)

I'm not sure what it looks like on other platforms.

The real problem comes from

<W>2020-06-17 14:05:37.405 1 => <1:(-1)> Connection closed: SecPKCS12Import returned no items [21]

This line. This is the line that blocks the connection, and it is related to the way macOS handles certificates (the so-called 'Keychain'), that triggers this security-related issue.

Krzmbrzl commented 4 years ago

Interesting... :thinking: (Note though that the cited docs are for error code 22 while you reported a code of 21)

This bug report might be related: https://bugreports.qt.io/browse/QTBUG-53758

Are you using a debug build of the server or a release build? If you're using a release build: Does the problem persist when using the -fg option?

TerryGeng commented 4 years ago

Sorry about my typo. It is 22, the global variable errno is 22.

qWarning("Connection: Failed to set TOS for TCP Socket, %i", errno);

=>

<W>2020-06-17 19:56:37.584 Connection: Failed to set TOS for TCP Socket, 22

I have looked into that issue some hours ago, and that is just the place where I learned the trick of manually adding certificates into the keychain. But besides that, it wasn't very helpful.

I was running a debug build.

Krzmbrzl commented 4 years ago

Does https://forums.developer.apple.com/thread/46463 apply?

I'm afraid I can't really help here though since I don't know macs and I also don't really know the encryption stuff xD

Maybe @davidebeatrici has an idea? :thinking:

stale[bot] commented 4 years ago

This support-issue has been automatically marked as stale because it has not had recent activity. If no further activity occurs, the issue will be automatically closed as we'll assume your problem to be fixed.

TerryGeng commented 4 years ago

Sorry I'm busy with other stuff at hand. I'm gonna test in a few days.

TerryGeng commented 4 years ago

I did some primitive tests. Looks like things work in David's cmake branch.

<W>2020-06-26 10:03:45.594 Murmur 0.0.0 (1.4.0~410~g5d78e8f~snapshot) running on OSX: 10.15.5 19F101: Booting servers
<W>2020-06-26 10:03:45.600 1 => Server listening on 0.0.0.0:64738
<W>2020-06-26 10:03:45.601 1 => Failed to bind UDP Socket to 0.0.0.0:64738
<W>2020-06-26 10:03:45.605 1 => Announcing server via bonjour
<W>2020-06-26 10:03:45.606 1 => Not registering server as public
<W>2020-06-26 10:03:52.592 1 => <1:(-1)> New connection: 127.0.0.1:63563
<W>2020-06-26 10:03:52.592 Connection: Failed to set TOS for TCP Socket
<W>2020-06-26 10:03:54.405 1 => <1:(-1)> Strong certificate for Terry Geng <gengyanda@gmail.com> (signed by Terry Geng)
<W>2020-06-26 10:03:54.409 1 => <1:(-1)> Client version 1.3.0 (OSX 10.15.5 19F101: 1.3.0)
<W>2020-06-26 10:03:54.411 1 => Starting voice thread
<W>2020-06-26 10:03:54.412 1 => CELT codec switch ffffffff80000010 0 (prefer ffffffff80000010) (Opus 1)
<W>2020-06-26 10:03:54.413 1 => <1:Terry(-1)> Authenticated
<W>2020-06-26 10:03:57.588 1 => <1:Terry(-1)> Connection closed: The remote host closed the connection [1]
<W>2020-06-26 10:03:57.589 1 => Ending voice thread

However, in https://github.com/mumble-voip/mumble/commit/7c67ea33f47716a188da045ead2035f978fc6253 (where the cmake branch is based), murmur doesn't work.

<W>2020-06-26 10:05:00.833 Murmur 1.4.0 (1.4.0~381~g3770d0e~snapshot) running on OSX: 10.15.5 19F101: Booting servers
<W>2020-06-26 10:05:00.837 1 => Server listening on 0.0.0.0:64738
<W>2020-06-26 10:05:00.838 1 => Failed to bind UDP Socket to 0.0.0.0:64738
<W>2020-06-26 10:05:00.840 1 => Announcing server via bonjour
<W>2020-06-26 10:05:00.841 1 => Not registering server as public
<W>2020-06-26 10:05:07.329 1 => <1:(-1)> New connection: 127.0.0.1:63771
<W>2020-06-26 10:05:07.329 Connection: Failed to set TOS for TCP Socket
<W>2020-06-26 10:05:07.390 1 => <1:(-1)> Connection closed: SecPKCS12Import returned no items [21]

It makes me wonder if this problem is related to the Qt versions between these branches.

BTW: I printed the error message of Failed to bind UDP Socket to 0.0.0.0:64738 and it gave Address already in use. With lsof, I can only see the TCP binding.

terrygeng@Terrys-Macbook-Pro ~$ sudo lsof -nP -i | grep 64738
murmurd   30474      terrygeng   20u  IPv6 0xb216efbaae15d70d      0t0  TCP *:64738 (LISTEN)

AFAIK TCP connections can share the same port with UDP. I'm not sure what prevents the UDP socket from binding.

Krzmbrzl commented 4 years ago

Hm... Very curious :thinking:

Did you use Davide's branch with the Qt version provided by vcpkg? And the "normal" build was done with Qt from homebrew? In that case I think it's failing with the newer Qt version as afaik homebrew currently ships a newer Qt version than vcpkg...

stale[bot] commented 4 years ago

This support-issue has been automatically marked as stale because it has not had recent activity. If no further activity occurs, the issue will be automatically closed as we'll assume your problem to be fixed.

TerryGeng commented 4 years ago

Somehow today I tested again, and both the cmake version and the qmake version don't work with the same "Connection closed: SecPKCS12Import returned no items" error.

From some discussion elsewhere, it seems that when an application is trying to add a key pair into the system's keychain, a popup will show up and ask the user for permission, but this doesn't happen when running murmur, even with -fg option or running under debug mode.

Maybe this is just some security problem and will be luckily solved by properly build the release sign the binary?

Could you guys please let me know when you are making an official ready-to-publish binary so I can test it again then?

FYI: for other Mac users who are seeing this error message, my current workaround is to generate a self-signed certificate and manually add it to my keychain:

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain murmur.cert 

Update: I tried to adopt https://codereview.qt-project.org/c/qt/qtbase/+/184243 (i.e. set the env variable QT_SSL_USE_TEMPORARY_KEYCHAIN) to avoid directly adding a key pair into the permanent keychain and murmur works again.

With QT_SSL_USE_TEMPORARY_KEYCHAIN:

terrygeng@Terrys-Macbook-Pro release$ QT_SSL_USE_TEMPORARY_KEYCHAIN=1 ./murmurd -fg
<X>2020-07-05 17:14:51.600 SSL: OpenSSL version is 'OpenSSL 1.1.1g  21 Apr 2020'
<W>2020-07-05 17:14:51.600 Initializing settings from /Users/terrygeng/Desktop/mumble-voip/mumble/release/murmur.ini (basepath /Users/terrygeng/Desktop/mumble-voip/mumble/release)
<W>2020-07-05 17:14:51.601 MetaParams: TLS cipher preference is "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA"
<W>2020-07-05 17:14:52.033 ServerDB: Opened SQLite database /Users/terrygeng/Desktop/mumble-voip/mumble/release/murmur.sqlite
<W>2020-07-05 17:14:52.033 ServerDB: Using SQLite's default rollback journal.
<W>2020-07-05 17:14:52.035 MurmurIce: Endpoint "tcp -h 127.0.0.1 -p 6502 -t 60000" running
<W>2020-07-05 17:14:52.036 Murmur 1.4.0 (1.4.0~381~g3770d0e~snapshot) running on OSX: 10.15.5 19F101: Booting servers
<W>2020-07-05 17:14:52.041 1 => Server listening on 0.0.0.0:64738
<W>2020-07-05 17:14:52.042 1 => Failed to bind UDP Socket to 0.0.0.0:64738
<W>2020-07-05 17:14:52.045 1 => Announcing server via bonjour
<W>2020-07-05 17:14:52.046 1 => Not registering server as public
<W>2020-07-05 17:15:10.550 1 => <2:(-1)> New connection: [0::1]:52128
<W>2020-07-05 17:15:10.550 Connection: Failed to set TOS for TCP Socket
<W>2020-07-05 17:15:10.660 1 => <2:(-1)> Strong certificate for Terry Geng <gengyanda@gmail.com> (signed by Terry Geng)
<W>2020-07-05 17:15:10.677 1 => <2:(-1)> Client version 1.4.0 (OSX 10.15.5 19F101: 1.4.0~381~g3770d0e~snapshot)
<W>2020-07-05 17:15:10.678 1 => Starting voice thread
<W>2020-07-05 17:15:10.679 1 => CELT codec switch ffffffff8000000b 0 (prefer ffffffff8000000b) (Opus 1)
<W>2020-07-05 17:15:10.680 1 => <2:Terry(-1)> Authenticated
<W>2020-07-05 17:15:19.999 1 => <2:Terry(-1)> Connection closed: The remote host closed the connection [1]
<W>2020-07-05 17:15:20.000 1 => Ending voice thread
^C

Without:

terrygeng@Terrys-Macbook-Pro release$ ./murmurd -fg
<X>2020-07-05 17:15:32.551 SSL: OpenSSL version is 'OpenSSL 1.1.1g  21 Apr 2020'
<W>2020-07-05 17:15:32.551 Initializing settings from /Users/terrygeng/Desktop/mumble-voip/mumble/release/murmur.ini (basepath /Users/terrygeng/Desktop/mumble-voip/mumble/release)
<W>2020-07-05 17:15:32.553 MetaParams: TLS cipher preference is "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA"
<W>2020-07-05 17:15:32.998 ServerDB: Opened SQLite database /Users/terrygeng/Desktop/mumble-voip/mumble/release/murmur.sqlite
<W>2020-07-05 17:15:32.998 ServerDB: Using SQLite's default rollback journal.
<W>2020-07-05 17:15:33.000 MurmurIce: Endpoint "tcp -h 127.0.0.1 -p 6502 -t 60000" running
<W>2020-07-05 17:15:33.000 Murmur 1.4.0 (1.4.0~381~g3770d0e~snapshot) running on OSX: 10.15.5 19F101: Booting servers
<W>2020-07-05 17:15:33.006 1 => Server listening on 0.0.0.0:64738
<W>2020-07-05 17:15:33.007 1 => Failed to bind UDP Socket to 0.0.0.0:64738
<W>2020-07-05 17:15:33.009 1 => Announcing server via bonjour
<W>2020-07-05 17:15:33.011 1 => Not registering server as public
<W>2020-07-05 17:15:42.232 1 => <1:(-1)> New connection: [0::1]:52219
<W>2020-07-05 17:15:42.232 Connection: Failed to set TOS for TCP Socket
<W>2020-07-05 17:15:42.289 1 => <1:(-1)> Connection closed: SecPKCS12Import returned no items [21]
TerryGeng commented 4 years ago

With the successful attempt mentioned in the previous post, I think I will write a patch with qputenv() to set this environment variable when starting murmur.

I think this is not just a hotfix, but also something that is necessary to avoid the auto-generated self-signed murmur certification messes up system's keychain because after this patch, murmur's key pairs won't be saved in system's keychain.

What's your idea about this? @Krzmbrzl @davidebeatrici

Meanwhile, I will start a new issue regarding Failed to bind UDP Socket to 0.0.0.0:64738 problem.

Krzmbrzl commented 4 years ago

So basically the server would then not add the certificate into the local Keychain but uses a separate, temporary one?

In principle I think that's absolutely fine given that murmur is probably the only one that'll need this certificate on the machine. I guess the only question would be if this would still integrate nicely with permanent certificates in the normal Keychain (e. g. If someone has setup e.g. a Let's Encrypt cert) :thinking:

TerryGeng commented 4 years ago

I have tested and confirmed that this patch works for using an existed certificate specified in the murmur.ini file :)

It works no matter if I have added the certificate file into the keychain. The only difference seems to be: if I have the key pair in the system's keychain beforehand, Qt will load the private key from the keychain so I got a popup asking for my permission. (But actually I have provided the private key file in murmur.ini, so in fact there's no need to access the private key in the keychain. This silly design has been discussed in https://bugreports.qt.io/browse/QTBUG-53758)