dequis / purple-facebook

Facebook protocol plugin for libpurple (moved from jgeboski/purple-facebook)
GNU General Public License v2.0
954 stars 88 forks source link

Certificate issues #284

Open jaymzh opened 7 years ago

jaymzh commented 7 years ago

Pidgin prompts for tons of akamai certs upon connecting. Accept/reject will pop them up again, but if you don't choose anything eventually they go away.

dequis commented 7 years ago

What pidgin version? What operating system / distro?

jaymzh commented 7 years ago

Linux (Debian Unstable) Pidgin 2.11.0-2

dequis commented 7 years ago

Buddy list -> help menu -> debug window, make it connect, post the output of that window.

dequis commented 7 years ago

Poke?

jaymzh commented 7 years ago

It doesn't happen consistently, so I haven't been able to capture debug when it happens. I haven't forgotten :)

jaymzh commented 7 years ago

Got some!!

(10:52:31) proxy: Connecting to fbcdn-profile-a.akamaihd.net:443.
(10:52:31) proxy: Connected to fbcdn-profile-a.akamaihd.net:443.
(10:52:31) nss: SSL version 3.3 using 128-bit AES-GCM with 128-bit AEAD MAC
Server Auth: 2048-bit RSA, Key Exchange: 256-bit ECDHE, Compression: NULL
Cipher Suite Name: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
(10:52:31) nss: subject=CN=a248.e.akamai.net,O=Akamai Technologies Inc.,L=Cambridge,ST=MA,C=US issuer=CN=Verizon Akamai SureServer CA G14-SHA2,OU=Cybertrust,O=Verizon Enterprise Solutions,L=Amsterdam,C=NL
(10:52:31) nss: partial certificate chain
(10:52:31) certificate/x509/tls_cached: Starting verify for fbcdn-profile-a.akamaihd.net
(10:52:31) certificate/x509/tls_cached: Checking for cached cert...
(10:52:31) certificate/x509/tls_cached: ...Found cached cert
(10:52:31) nss/x509: Loading certificate from /home/phild/.purple/certificates/x509/tls_peers/fbcdn-profile-a.akamaihd.net
(10:52:31) certificate/x509/tls_cached: Peer cert did NOT match cached
(10:52:31) nss: CERT 0. CN=a248.e.akamai.net,O=Akamai Technologies Inc.,L=Cambridge,ST=MA,C=US :
(10:52:31) nss:   ERROR -8179: SEC_ERROR_UNKNOWN_ISSUER

...

(10:52:34) proxy: Connected to fbcdn-profile-a.akamaihd.net:443.
(10:52:34) nss: SSL version 3.3 using 128-bit AES-GCM with 128-bit AEAD MAC
Server Auth: 2048-bit RSA, Key Exchange: 256-bit ECDHE, Compression: NULL
Cipher Suite Name: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
(10:52:34) nss: subject=CN=a248.e.akamai.net,O=Akamai Technologies Inc.,L=Cambridge,ST=MA,C=US issuer=CN=Verizon Akamai SureServer CA G14-SHA2,OU=Cybertrust,O=Verizon Enterprise Solutions,L=Amsterdam,C=NL
(10:52:34) nss: partial certificate chain
(10:52:34) certificate/x509/tls_cached: Starting verify for fbcdn-profile-a.akamaihd.net
(10:52:34) certificate/x509/tls_cached: Checking for cached cert...
(10:52:34) certificate/x509/tls_cached: ...Found cached cert
(10:52:34) nss/x509: Loading certificate from /home/phild/.purple/certificates/x509/tls_peers/fbcdn-profile-a.akamaihd.net
(10:52:34) certificate/x509/tls_cached: Peer cert did NOT match cached
(10:52:34) nss: CERT 0. CN=a248.e.akamai.net,O=Akamai Technologies Inc.,L=Cambridge,ST=MA,C=US :
(10:52:34) nss:   ERROR -8179: SEC_ERROR_UNKNOWN_ISSUER

Note that the "partial certificate chain" happens on all the connections, but most don't cause a problem - just these ones that actually throw errors from nss.

jaymzh commented 7 years ago

Got some more:

(13:22:45) nss: SSL version 3.3 using 128-bit AES-GCM with 128-bit AEAD MAC
Server Auth: 256-bit ECDSA, Key Exchange: 256-bit ECDHE, Compression: NULL
Cipher Suite Name: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
(13:22:45) nss: subject=CN=a248.e.akamai.net,O="Akamai Technologies, Inc.",L=Cambridge,ST=Massachusetts,C=US issuer=CN=Symantec Class 3 ECC 256 bit SSL CA - G2,OU=Symantec Trust Network,O=Symantec Corporation,C=US
(13:22:45) nss: partial certificate chain
(13:22:45) certificate/x509/tls_cached: Starting verify for fb-s-c-a.akamaihd.net
(13:22:45) certificate/x509/tls_cached: Checking for cached cert...
(13:22:45) certificate/x509/tls_cached: ...Found cached cert
(13:22:45) nss/x509: Loading certificate from /home/phild/.purple/certificates/x509/tls_peers/fb-s-c-a.akamaihd.net
(13:22:45) certificate/x509/tls_cached: Peer cert did NOT match cached
(13:22:45) nss: CERT 0. CN=a248.e.akamai.net,O="Akamai Technologies, Inc.",L=Cambridge,ST=Massachusetts,C=US :
(13:22:45) nss:   ERROR -8179: SEC_ERROR_UNKNOWN_ISSUER
dequis commented 7 years ago

For the pidgin 2.12.0 release which happened a last week I dealt with a vaguely related issue with gnutls. Mostly related because it forced me to understand more about certificate validation, so that's neat.

Anyway so here are two working attempts to connect to that server:

First connection:

(00:13:23) nss: SSL version 3.3 using 128-bit AES-GCM with 128-bit AEAD MAC
Server Auth: 256-bit ECDSA, Key Exchange: 256-bit ECDHE, Compression: NULL
Cipher Suite Name: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
(00:13:23) nss: subject=CN=a248.e.akamai.net,O="Akamai Technologies, Inc.",L=Cambridge,ST=Massachusetts,C=US issuer=CN=Symantec Class 3 ECC 256 bit SSL CA - G2,OU=Symantec Trust Network,O=Symantec Corporation,C=US
(00:13:23) nss: subject=CN=Symantec Class 3 ECC 256 bit SSL CA - G2,OU=Symantec Trust Network,O=Symantec Corporation,C=US issuer=CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
(00:13:23) nss: subject=CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US issuer=CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
(00:13:23) certificate/x509/tls_cached: Starting verify for a248.e.akamai.net
(00:13:23) certificate/x509/tls_cached: Checking for cached cert...
(00:13:23) certificate/x509/tls_cached: ...Not in cache
(00:13:23) nss/x509: Exporting certificate to /home/dx/.purple/certificates/x509/tls_peers/a248.e.akamai.net
(00:13:23) util: Writing file /home/dx/.purple/certificates/x509/tls_peers/a248.e.akamai.net
(00:13:23) nss: Trusting CN=a248.e.akamai.net,O="Akamai Technologies, Inc.",L=Cambridge,ST=Massachusetts,C=US
(00:13:23) certificate: Successfully verified certificate for a248.e.akamai.net

Second connection:

(00:15:25) nss: SSL version 3.3 using 128-bit AES-GCM with 128-bit AEAD MAC
Server Auth: 256-bit ECDSA, Key Exchange: 256-bit ECDHE, Compression: NULL
Cipher Suite Name: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
(00:15:25) nss: subject=CN=a248.e.akamai.net,O="Akamai Technologies, Inc.",L=Cambridge,ST=Massachusetts,C=US issuer=CN=Symantec Class 3 ECC 256 bit SSL CA - G2,OU=Symantec Trust Network,O=Symantec Corporation,C=US
(00:15:25) nss: partial certificate chain
(00:15:25) certificate/x509/tls_cached: Starting verify for a248.e.akamai.net
(00:15:25) certificate/x509/tls_cached: Checking for cached cert...
(00:15:25) certificate/x509/tls_cached: ...Found cached cert
(00:15:25) nss/x509: Loading certificate from /home/dx/.purple/certificates/x509/tls_peers/a248.e.akamai.net
(00:15:25) certificate/x509/tls_cached: Peer cert matched cached
(00:15:25) nss/x509: Exporting certificate to /home/dx/.purple/certificates/x509/tls_peers/a248.e.akamai.net
(00:15:25) util: Writing file /home/dx/.purple/certificates/x509/tls_peers/a248.e.akamai.net
(00:15:25) nss: Trusting CN=a248.e.akamai.net,O="Akamai Technologies, Inc.",L=Cambridge,ST=Massachusetts,C=US

The first time the certificate wasn't cached, and it got a full chain.

The second time the certificate was cached, and it got a partial chain, but since the fingerprint of that certificate matches the cached one, it doesn't go through NSS validation again.

The partial chain thing is their server being clever and avoiding sending the whole chain again because there was another connection recently. Google does that thing sometimes too. I'm not sure if that's specific to their implementations or if it's a normal way to do SSL. I'd love to know.

A more readable version of the chain, with CN only:

  1. a248.e.akamai.net (issued by...)
  2. Symantec Class 3 ECC 256 bit SSL CA - G2 (issued by...)
  3. VeriSign Class 3 Public Primary Certification Authority - G5 (self-signed root)

3 is in root stores, 2 isn't (and 1 isn't a CA)

When the server decides to send a partial chain which only includes 1, you either need to trust 1 (when it's cached) or 2 (when it's in the root store). When 1 is not cached because the server decides to send a slightly different version of the same certificate, you end up relying on its issuer, which isn't trusted, and this error happens.

Now the part I don't understand:

AFAIK, libpurple with NSS doesn't do anything weird to validate certificates. So, if anything, the "cached certificate" feature that libpurple adds on top of NSS helps turn this into a rare issue, as opposed to failing every time the server decides to send a partial chain.

That doesn't sound right. Maybe libpurple isn't using NSS as properly as it should, maybe SSL libraries already do in-memory caching of validations in some sort of session state, maybe the concept of "on-disk cached certificates compared by their sha256 fingerprint" is the wrong approach, maybe other SSL clients do actually need similar things but they implement it differently (SPKI fp, like i did with gnutls?)

brianjmurrell commented 2 years ago

I'm seeing this with 0.9.6:

(05:42:28) account: Connecting to account [redacted].
(05:42:28) connection: Connecting. gc = 0x55c4e58f5290
(05:42:28) http: Performing new request 0x55c4eedb58b0 to graph.facebook.com.
(05:42:28) dnsquery: Performing DNS lookup for graph.facebook.com
(05:42:28) dns: Wait for DNS child 1387567 failed: No child processes
(05:42:28) dns: Created new DNS child 1388424, there are now 1 children.
(05:42:28) dns: Successfully sent DNS request to child 1388424
(05:42:28) dns: Got response for 'graph.facebook.com'
(05:42:28) dnsquery: IP resolved for graph.facebook.com
(05:42:28) proxy: Attempting connection to 2a03:2880:f00d:1:face:b00c:0:1
(05:42:28) proxy: Connecting to graph.facebook.com:443 with no proxy
(05:42:28) proxy: Connection in progress
(05:42:28) proxy: Connecting to graph.facebook.com:443.
(05:42:28) proxy: Connected to graph.facebook.com:443.
(05:42:29) nss: SSL version 3.3 using 128-bit AES-GCM with 128-bit AEAD MAC
Server Auth: 256-bit ECDSA, Key Exchange: 256-bit ECDHE, Compression: NULL
Cipher Suite Name: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
(05:42:29) nss: subject=CN=*.facebook.com,O="Facebook, Inc.",L=Menlo Park,ST=California,C=US issuer=CN=DigiCert SHA2 High Assurance Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US
(05:42:29) nss: partial certificate chain
(05:42:29) certificate/x509/tls_cached: Starting verify for graph.facebook.com
(05:42:29) certificate/x509/tls_cached: Checking for cached cert...
(05:42:29) certificate/x509/tls_cached: ...Found cached cert
(05:42:29) nss/x509: Loading certificate from /home/brian/.purple/certificates/x509/tls_peers/graph.facebook.com
(05:42:29) certificate/x509/tls_cached: Peer cert did NOT match cached
(05:42:29) nss: CERT 0. CN=*.facebook.com,O="Facebook, Inc.",L=Menlo Park,ST=California,C=US :
(05:42:29) nss:   ERROR -8179: SEC_ERROR_UNKNOWN_ISSUER