From 94c1eec169db66bb4ad9d633342aead3b0f35b9f Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Tue, 1 May 2012 12:12:37 +0200 Subject: Don’t hardcode passwords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s a bad idea to hardcode these, although playback does not work with non-android login yet. --- src/libpiano/crypt.c | 17 +++++------------ src/libpiano/crypt.h | 7 +++++-- src/libpiano/piano.c | 31 +++++++++++++++++++++++++++++-- src/libpiano/piano.h | 14 +++++++++++--- src/libpiano/request.c | 17 +++++++++-------- src/libpiano/response.c | 9 +++++---- src/main.c | 4 +++- src/settings.c | 28 ++++++++++++++++++++++++++++ src/settings.h | 3 ++- 9 files changed, 97 insertions(+), 33 deletions(-) diff --git a/src/libpiano/crypt.c b/src/libpiano/crypt.c index 6dafcca..29ad3cb 100644 --- a/src/libpiano/crypt.c +++ b/src/libpiano/crypt.c @@ -32,11 +32,13 @@ THE SOFTWARE. /* decrypt hex-encoded, blowfish-crypted string: decode 2 hex-encoded blocks, * decrypt, byteswap + * @param gcrypt handle * @param hex string * @param decrypted string length (without trailing NUL) * @return decrypted string or NULL */ -char *PianoDecryptString (const char * const input, size_t * const retSize) { +char *PianoDecryptString (gcry_cipher_hd_t h, const char * const input, + size_t * const retSize) { size_t inputLen = strlen (input); gcry_error_t gret; unsigned char *output; @@ -53,26 +55,22 @@ char *PianoDecryptString (const char * const input, size_t * const retSize) { output[i] = strtol (hex, NULL, 16); } - gcry_cipher_hd_t h; - gcry_cipher_open (&h, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB, 0); - gcry_cipher_setkey (h, (unsigned char *) "R=U!LH$O2B#", 11); gret = gcry_cipher_decrypt (h, output, outputLen, NULL, 0); if (gret) { - fprintf (stderr, "Failure: %s/%s\n", gcry_strsource (gret), gcry_strerror (gret)); return NULL; } - gcry_cipher_close (h); *retSize = outputLen; return (char *) output; } /* blowfish-encrypt/hex-encode string + * @param gcrypt handle * @param encrypt this * @return encrypted, hex-encoded string */ -char *PianoEncryptString (const char *s) { +char *PianoEncryptString (gcry_cipher_hd_t h, const char *s) { unsigned char *paddedInput, *hexOutput; size_t inputLen = strlen (s); /* blowfish expects two 32 bit blocks */ @@ -82,12 +80,8 @@ char *PianoEncryptString (const char *s) { paddedInput = calloc (paddedInputLen+1, sizeof (*paddedInput)); memcpy (paddedInput, s, inputLen); - gcry_cipher_hd_t h; - gcry_cipher_open (&h, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB, 0); - gcry_cipher_setkey (h, (unsigned char *) "6#26FRL$ZWD", 11); gret = gcry_cipher_encrypt (h, paddedInput, paddedInputLen, NULL, 0); if (gret) { - fprintf (stderr, "Failure: %s/%s\n", gcry_strsource (gret), gcry_strerror (gret)); return NULL; } @@ -96,7 +90,6 @@ char *PianoEncryptString (const char *s) { snprintf ((char * restrict) &hexOutput[i*2], 3, "%02x", paddedInput[i]); } - gcry_cipher_close (h); free (paddedInput); return (char *) hexOutput; diff --git a/src/libpiano/crypt.h b/src/libpiano/crypt.h index 945e9e6..59820e2 100644 --- a/src/libpiano/crypt.h +++ b/src/libpiano/crypt.h @@ -24,7 +24,10 @@ THE SOFTWARE. #ifndef _CRYPH_H #define _CRYPT_H -char *PianoDecryptString (const char * const, size_t * const); -char *PianoEncryptString (const char *strInput); +#include + +char *PianoDecryptString (gcry_cipher_hd_t, const char * const, + size_t * const); +char *PianoEncryptString (gcry_cipher_hd_t, const char *); #endif /* _CRYPT_H */ diff --git a/src/libpiano/piano.c b/src/libpiano/piano.c index f9dfa51..bd8847b 100644 --- a/src/libpiano/piano.c +++ b/src/libpiano/piano.c @@ -40,8 +40,23 @@ THE SOFTWARE. * @param piano handle * @return nothing */ -void PianoInit (PianoHandle_t *ph) { +void PianoInit (PianoHandle_t *ph, const char *partnerUser, + const char *partnerPassword, const char *device, const char *inkey, + const char *outkey) { memset (ph, 0, sizeof (*ph)); + ph->partner.user = strdup (partnerUser); + ph->partner.password = strdup (partnerPassword); + ph->partner.device = strdup (device); + + gcry_cipher_open (&ph->partner.in, GCRY_CIPHER_BLOWFISH, + GCRY_CIPHER_MODE_ECB, 0); + gcry_cipher_setkey (ph->partner.in, (const unsigned char *) inkey, + strlen (inkey)); + + gcry_cipher_open (&ph->partner.out, GCRY_CIPHER_BLOWFISH, + GCRY_CIPHER_MODE_ECB, 0); + gcry_cipher_setkey (ph->partner.out, (const unsigned char *) outkey, + strlen (outkey)); } /* destroy artist linked list @@ -150,6 +165,18 @@ void PianoDestroyUserInfo (PianoUserInfo_t *user) { free (user->listenerId); } +/* destroy partner + */ +static void PianoDestroyPartner (PianoPartner_t *partner) { + free (partner->user); + free (partner->password); + free (partner->device); + free (partner->authToken); + gcry_cipher_close (partner->in); + gcry_cipher_close (partner->out); + memset (partner, 0, sizeof (*partner)); +} + /* frees the whole piano handle structure * @param piano handle * @return nothing @@ -157,6 +184,7 @@ void PianoDestroyUserInfo (PianoUserInfo_t *user) { void PianoDestroy (PianoHandle_t *ph) { PianoDestroyUserInfo (&ph->user); PianoDestroyStations (ph->stations); + PianoDestroyPartner (&ph->partner); /* destroy genre stations */ PianoGenreCategory_t *curGenreCat = ph->genreStations, *lastGenreCat; while (curGenreCat != NULL) { @@ -166,7 +194,6 @@ void PianoDestroy (PianoHandle_t *ph) { curGenreCat = curGenreCat->next; free (lastGenreCat); } - free (ph->partnerAuthToken); memset (ph, 0, sizeof (*ph)); } diff --git a/src/libpiano/piano.h b/src/libpiano/piano.h index 6d20747..86dcce0 100644 --- a/src/libpiano/piano.h +++ b/src/libpiano/piano.h @@ -25,6 +25,7 @@ THE SOFTWARE. #define _PIANO_H #include +#include /* this is our public API; don't expect this api to be stable as long as * pandora does not provide a stable api @@ -106,14 +107,19 @@ typedef struct PianoGenreCategory { struct PianoGenreCategory *next; } PianoGenreCategory_t; +typedef struct PianoPartner { + gcry_cipher_hd_t in, out; + char *authToken, *device, *user, *password; + unsigned int id; +} PianoPartner_t; + typedef struct PianoHandle { PianoUserInfo_t user; /* linked lists */ PianoStation_t *stations; PianoGenreCategory_t *genreStations; + PianoPartner_t partner; int timeOffset; - char *partnerAuthToken; - unsigned int partnerId; } PianoHandle_t; typedef struct PianoSearchResult { @@ -291,7 +297,9 @@ typedef enum { } PianoReturn_t; -void PianoInit (PianoHandle_t *); +void PianoInit (PianoHandle_t *, const char *, + const char *, const char *, const char *, + const char *); void PianoDestroy (PianoHandle_t *); void PianoDestroyPlaylist (PianoSong_t *); void PianoDestroySearchResult (PianoSearchResult_t *); diff --git a/src/libpiano/request.c b/src/libpiano/request.c index a5a33e9..3a1d7fb 100644 --- a/src/libpiano/request.c +++ b/src/libpiano/request.c @@ -70,11 +70,11 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, req->secure = true; json_object_object_add (j, "username", - json_object_new_string ("android")); + json_object_new_string (ph->partner.user)); json_object_object_add (j, "password", - json_object_new_string ("AC7IBG09A3DTSYM4R41UJWL07VLN8JI7")); + json_object_new_string (ph->partner.password)); json_object_object_add (j, "deviceModel", - json_object_new_string ("android-generic")); + json_object_new_string (ph->partner.device)); json_object_object_add (j, "version", json_object_new_string ("5")); json_object_object_add (j, "includeUrls", @@ -95,16 +95,16 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, json_object_object_add (j, "password", json_object_new_string (logindata->password)); json_object_object_add (j, "partnerAuthToken", - json_object_new_string (ph->partnerAuthToken)); + json_object_new_string (ph->partner.authToken)); json_object_object_add (j, "syncTime", json_object_new_int (timestamp)); - urlencAuthToken = WaitressUrlEncode (ph->partnerAuthToken); + urlencAuthToken = WaitressUrlEncode (ph->partner.authToken); assert (urlencAuthToken != NULL); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "method=auth.userLogin&" "auth_token=%s&partner_id=%i", urlencAuthToken, - ph->partnerId); + ph->partner.id); free (urlencAuthToken); break; @@ -483,7 +483,7 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "method=%s&auth_token=%s&partner_id=%i&user_id=%s", method, - urlencAuthToken, ph->partnerId, ph->user.listenerId); + urlencAuthToken, ph->partner.id, ph->user.listenerId); free (urlencAuthToken); @@ -496,7 +496,8 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, /* json to string */ jsonSendBuf = json_object_to_json_string (j); if (encrypted) { - if ((req->postData = PianoEncryptString (jsonSendBuf)) == NULL) { + if ((req->postData = PianoEncryptString (ph->partner.out, + jsonSendBuf)) == NULL) { return PIANO_RET_OUT_OF_MEMORY; } } else { diff --git a/src/libpiano/response.c b/src/libpiano/response.c index 65af76e..4b33248 100644 --- a/src/libpiano/response.c +++ b/src/libpiano/response.c @@ -103,8 +103,9 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { size_t decryptedSize; ret = PIANO_RET_ERR; - if ((decryptedTimestamp = PianoDecryptString (cryptedTimestamp, - &decryptedSize)) != NULL && decryptedSize > 4) { + if ((decryptedTimestamp = PianoDecryptString (ph->partner.in, + cryptedTimestamp, &decryptedSize)) != NULL && + decryptedSize > 4) { /* skip four bytes garbage(?) at beginning */ timestamp = strtoul (decryptedTimestamp+4, NULL, 0); ph->timeOffset = realTimestamp - timestamp; @@ -112,9 +113,9 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { } free (decryptedTimestamp); /* get auth token */ - ph->partnerAuthToken = PianoJsonStrdup (result, + ph->partner.authToken = PianoJsonStrdup (result, "partnerAuthToken"); - ph->partnerId = json_object_get_int ( + ph->partner.id = json_object_get_int ( json_object_object_get (result, "partnerId")); ++reqData->step; break; diff --git a/src/main.c b/src/main.c index 43f3ffc..26099f5 100644 --- a/src/main.c +++ b/src/main.c @@ -341,11 +341,13 @@ int main (int argc, char **argv) { /* init some things */ ao_initialize (); gnutls_global_init (); - PianoInit (&app.ph); BarSettingsInit (&app.settings); BarSettingsRead (&app.settings); + PianoInit (&app.ph, app.settings.partnerUser, app.settings.partnerPassword, + app.settings.device, app.settings.inkey, app.settings.outkey); + BarUiMsg (&app.settings, MSG_NONE, "Welcome to " PACKAGE " (" VERSION ")! "); if (app.settings.keys[BAR_KS_HELP] == BAR_KS_DISABLED) { diff --git a/src/settings.c b/src/settings.c index d1dcc7f..d603387 100644 --- a/src/settings.c +++ b/src/settings.c @@ -93,6 +93,11 @@ void BarSettingsDestroy (BarSettings_t *settings) { free (settings->npStationFormat); free (settings->listSongFormat); free (settings->fifo); + free (settings->partnerUser); + free (settings->partnerPassword); + free (settings->device); + free (settings->inkey); + free (settings->outkey); for (size_t i = 0; i < MSG_COUNT; i++) { free (settings->msgFormat[i].prefix); free (settings->msgFormat[i].postfix); @@ -131,6 +136,11 @@ void BarSettingsRead (BarSettings_t *settings) { settings->npSongFormat = strdup ("\"%t\" by \"%a\" on \"%l\"%r%@%s"); settings->npStationFormat = strdup ("Station \"%n\" (%i)"); settings->listSongFormat = strdup ("%i) %a - %t%r"); + settings->partnerUser = strdup ("android"); + settings->partnerPassword = strdup ("AC7IBG09A3DTSYM4R41UJWL07VLN8JI7"); + settings->device = strdup ("android-generic"); + settings->inkey = strdup ("R=U!LH$O2B#"); + settings->outkey = strdup ("6#26FRL$ZWD"); settings->fifo = malloc (PATH_MAX * sizeof (*settings->fifo)); BarGetXdgConfigDir (PACKAGE "/ctl", settings->fifo, PATH_MAX); memcpy (settings->tlsFingerprint, "\xA2\xA0\xBE\x8A\x37\x92\x39\xAE" @@ -179,6 +189,24 @@ void BarSettingsRead (BarSettings_t *settings) { settings->username = strdup (val); } else if (streq ("password", key)) { settings->password = strdup (val); + } else if (streq ("partner_user", key)) { + free (settings->partnerUser); + settings->partnerUser = strdup (val); + } else if (streq ("partner_password", key)) { + free (settings->partnerPassword); + settings->partnerPassword = strdup (val); + } else if (streq ("device", key)) { + free (settings->device); + settings->device = strdup (val); + } else if (streq ("encrypt_password", key)) { + free (settings->outkey); + settings->outkey = strdup (val); + } else if (streq ("decrypt_password", key)) { + free (settings->inkey); + settings->inkey = strdup (val); + } else if (memcmp ("act_", key, 4) == 0) { + } else if (memcmp ("act_", key, 4) == 0) { + } else if (memcmp ("act_", key, 4) == 0) { } else if (memcmp ("act_", key, 4) == 0) { size_t i; /* keyboard shortcuts */ diff --git a/src/settings.h b/src/settings.h index ce3732b..ff19882 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2011 +Copyright (c) 2008-2012 Lars-Dominik Braun Permission is hereby granted, free of charge, to any person obtaining a copy @@ -99,6 +99,7 @@ typedef struct { char *npStationFormat; char *listSongFormat; char *fifo; + char *partnerUser, *partnerPassword, *device, *inkey, *outkey; char tlsFingerprint[20]; char keys[BAR_KS_COUNT]; BarMsgFormatStr_t msgFormat[MSG_COUNT]; -- cgit v1.2.3