feelfreelinux / cspot

A Spotify Connect player targeting, but not limited to embedded devices (ESP32).
Other
495 stars 46 forks source link

Authorization declined when using cspotcli with zeroconf #127

Closed markuspi closed 2 years ago

markuspi commented 2 years ago

I am getting an authorization declined error when trying to run cspotcli on Ubuntu 22.04:

$ ./cspotcli                                              
*** WARNING *** The program 'cspotcli' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/blog/projects/avahi-compat.html>
I ZeroconfAuthenticator.cpp:55: Zeroconf registering handlers
I HTTPServer.cpp:68: Starting server at port 2137
I ZeroconfAuthenticator.cpp:26: Got request for info
I ZeroconfAuthenticator.cpp:26: Got request for info
I ZeroconfAuthenticator.cpp:37: Got request for adding user
I main.cpp:80: Creating player
D Session.cpp:39: Connecting with AP <ap-gew4.spotify.com:4070>
D PlainConnection.cpp:70: Connected to spotify server
D Session.cpp:42: Sending APHello packet...
D Session.cpp:102: Processing AP hello response...
D Session.cpp:104: Received AP hello response
D Session.cpp:150: Received shannon keys
E Session.cpp:90: Authorization declined
I PlainConnection.cpp:175: Closing socket...

Using password authentication seems to work initially, however the player is not showing up in any of my other spotify apps:

 ./cspotcli -u '***' -p '***'
I main.cpp:80: Creating player
D Session.cpp:39: Connecting with AP <ap-gew4.spotify.com:4070>
D PlainConnection.cpp:70: Connected to spotify server
D Session.cpp:42: Sending APHello packet...
D Session.cpp:102: Processing AP hello response...
D Session.cpp:104: Received AP hello response
D Session.cpp:150: Received shannon keys
D Session.cpp:81: Authorization successful
Start
stop
D MercuryManager.cpp:299: executing MercuryType SUB
D MercuryManager.cpp:216: Received packet with code 2 of length 336
D MercuryManager.cpp:216: Received packet with code 118 of length 2
D MercuryManager.cpp:216: Received packet with code 27 of length 2
D MercuryManager.cpp:223: Received country code: DE
D MercuryManager.cpp:216: Received packet with code 80 of length 6164
D MercuryManager.cpp:216: Received packet with code 31 of length 17
D MercuryManager.cpp:216: Received packet with code 105 of length 0
D MercuryManager.cpp:216: Received packet with code 181 of length 513
D MercuryManager.cpp:216: Received packet with code 74 of length 4
D MercuryManager.cpp:216: Received packet with code 179 of length 59
D MercuryManager.cpp:299: executing MercuryType SEND
D SpircController.cpp:32: Sent kMessageTypeHello!
D MercuryManager.cpp:216: Received packet with code 178 of length 188
D MercuryManager.cpp:254:  MercuryType::UNSUB response->parts[0].size() = 127
HeikoGr commented 2 years ago

spotify assigned you to their server "ap-gew4.spotify.com:4070", which seems to have troubles in the last days. (https://www.google.com/search?q=spotify+ap-gew4.spotify.com)

Maybe this is the problem in this case.

You can try to alter the file https://github.com/feelfreelinux/cspot/tree/master/cspot/src/ApResolve.cpp

from

    if (configMan->apOverride != "")
    {
        return configMan->apOverride;
    }

(line 88-91)

    // if (configMan->apOverride != "")
    // {
        return "ap-guc3.spotify.com:80";
    // }
markuspi commented 2 years ago

Thanks for the quick response! Unfortunately the problem persists even with your suggested change. Btw librespot-java used ap-gew4.spotify.com:443 when I tested it. Could this problem be related to TLS?

HeikoGr commented 2 years ago

i have no idea.

but i doubt, that the ports spotify is using are in any case related to their original protocol. They surely use the ports to go through proxies and NATs.

markuspi commented 2 years ago

I think I found the cause of the problem: in LoginBlob::decodeBlobSecondary, the length of blobData for me is 192 bytes. For some reason, crypto->aesECBdecrypt does not decrypt the last block (16 bytes):

CSPOT_LOG(debug, "blobData len: %d", blobData.size());
CSPOT_LOG(debug, "before: %s", bytesToHexString(blobData).c_str());
crypto->aesECBdecrypt(key, blobData);
CSPOT_LOG(debug, "after: %s", bytesToHexString(blobData).c_str());
blobData len: 192
D LoginBlob.cpp:76: before: a32b475be55cc[...redacted...]3c2423cc8a92d14838ae4a0458db0faf418a5b171cc7d6eaeb697b1bc36a958498367018af4b4e254abbdd581e355f166bde33efe19abccf2
D LoginBlob.cpp:78: after:  4919686365393[...redacted...]a30106c507027b9455f065f535e244b0e62731a360475df132c4f69023148667a2c3b4a633544ef50abbdd581e355f166bde33efe19abccf2
HeikoGr commented 2 years ago

i don't think the shorter blobData must be a fault.

the function crypto->aesECBdecrypt is able to change the value for blobData. And as i understand aesECB decryption it is possible, that the decrypted string is shorter then the encrypted.

HeikoGr commented 2 years ago

Using password authentication seems to work initially, however the player is not showing up in any of my other spotify apps

yes, a i understand targets/cli/main.cpp zeroconf is only starting up when u use no username/password.

markuspi commented 2 years ago

Disabling padding in bell/src/CryptoOpenSSL.cpp fixed the issue for me:

@@ -127,6 +128,7 @@ void CryptoOpenSSL::aesECBdecrypt(const std::vector<uint8_t>& key, std::vector<u
     int len = 0;

     EVP_DecryptInit_ex(ctx, EVP_aes_192_ecb(), NULL, key.data(), NULL);
+    EVP_CIPHER_CTX_set_padding(ctx, 0);
     EVP_DecryptUpdate(ctx, data.data(), &len, data.data(), data.size());
     EVP_DecryptFinal_ex(ctx, data.data() + len, &len);

My theory why this happens is this:

See also: librespot-java using AES/ECB/NoPadding and OpenSSL docs about default padding

HeikoGr commented 2 years ago

great work! glad i was not all wrong (at least with the ap server) :-D

i can confirm, that it works for me too now! Can you write a pull request?

@feelfreelinux i wonder, why there is no problem when using euphonium?!?

feelfreelinux commented 2 years ago

This checks out, as it does not break on my account. Thanks a lot for your contribution, i merged the changes into bell :)

feelfreelinux commented 2 years ago

great work! glad i was not all wrong (at least with the ap server) :-D

i can confirm, that it works for me too now! Can you write a pull request?

@feelfreelinux i wonder, why there is no problem when using euphonium?!?

Have you ran euphonium on desktop? I think its just because, on esp32 we simply just use mbedtls which is not affected by this issue.

HeikoGr commented 2 years ago

I think its just because, on esp32 we simply just use mbedtls which is not affected by this issue.

this is it. Of course

feelfreelinux commented 2 years ago

I think this should finally take care of the issue. Thanks a lot for pointing this out!