From 962dee5cdd3b468318916d9c8862bc4c3653c402 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Thu, 11 Oct 2012 18:09:46 +0200 Subject: New setting: Read password from external command Closes #314. --- contrib/config-example | 2 ++ contrib/pianobar.1 | 6 ++++ src/main.c | 77 +++++++++++++++++++++++++++++++++++++++++++++----- src/settings.c | 3 ++ src/settings.h | 2 +- 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/contrib/config-example b/contrib/config-example index f52d3a0..dbc8cc5 100644 --- a/contrib/config-example +++ b/contrib/config-example @@ -5,6 +5,8 @@ # User #user = your@user.name #password = password +# or +#password_command = gpg --decrypt ~/password # Proxy (for those who are not living in the USA) #control_proxy = http://127.0.0.1:9090/ diff --git a/contrib/pianobar.1 b/contrib/pianobar.1 index 4cc6d00..53bb301 100644 --- a/contrib/pianobar.1 +++ b/contrib/pianobar.1 @@ -296,6 +296,12 @@ Icon for loved songs. .B password = plaintext_password Your pandora.com password. Plain-text. +.TP +.B password_command = gpg --decrypt ~/password +Use output of command as password. This setting is overridden by specifying a +password with +.B password. + .TP .B proxy = http://user:password@host:port/ Use a http proxy. Note that this setting overrides the http_proxy environment diff --git a/src/main.c b/src/main.c index 1d24167..2465334 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,7 @@ THE SOFTWARE. #include #include #include +/* fork () */ #include #include #include @@ -46,6 +47,10 @@ THE SOFTWARE. #include #include #include +/* waitpid () */ +#include +#include + /* pandora.com library */ #include @@ -92,22 +97,78 @@ static bool BarMainLoginUser (BarApp_t *app) { /* ask for username/password if none were provided in settings */ -static void BarMainGetLoginCredentials (BarSettings_t *settings, +static bool BarMainGetLoginCredentials (BarSettings_t *settings, BarReadlineFds_t *input) { if (settings->username == NULL) { char nameBuf[100]; + BarUiMsg (settings, MSG_QUESTION, "Email: "); BarReadlineStr (nameBuf, sizeof (nameBuf), input, BAR_RL_DEFAULT); settings->username = strdup (nameBuf); } + if (settings->password == NULL) { char passBuf[100]; - BarUiMsg (settings, MSG_QUESTION, "Password: "); - BarReadlineStr (passBuf, sizeof (passBuf), input, BAR_RL_NOECHO); - /* write missing newline */ - puts (""); - settings->password = strdup (passBuf); + + if (settings->passwordCmd == NULL) { + BarUiMsg (settings, MSG_QUESTION, "Password: "); + BarReadlineStr (passBuf, sizeof (passBuf), input, BAR_RL_NOECHO); + /* write missing newline */ + puts (""); + settings->password = strdup (passBuf); + } else { + pid_t chld; + int pipeFd[2]; + + BarUiMsg (settings, MSG_INFO, "Requesting password from external helper... "); + + if (pipe (pipeFd) == -1) { + BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); + return false; + } + + chld = fork (); + if (chld == 0) { + /* child */ + close (pipeFd[0]); + dup2 (pipeFd[1], fileno (stdout)); + execl ("/bin/sh", "/bin/sh", "-c", settings->passwordCmd, (char *) NULL); + BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); + close (pipeFd[1]); + exit (1); + } else if (chld == -1) { + BarUiMsg (settings, MSG_NONE, "Error: %s\n", strerror (errno)); + return false; + } else { + /* parent */ + int status; + + close (pipeFd[1]); + memset (passBuf, 0, sizeof (passBuf)); + read (pipeFd[0], passBuf, sizeof (passBuf)-1); + close (pipeFd[0]); + + /* drop trailing newlines */ + ssize_t len = strlen (passBuf)-1; + while (len >= 0 && passBuf[len] == '\n') { + passBuf[len] = '\0'; + --len; + } + + waitpid (chld, &status, 0); + if (WEXITSTATUS (status) == 0) { + settings->password = strdup (passBuf); + BarUiMsg (settings, MSG_NONE, "Ok.\n"); + } else { + BarUiMsg (settings, MSG_NONE, "Error: Exit status %i.\n", WEXITSTATUS (status)); + return false; + } + } + + } } + + return true; } /* get station list @@ -270,7 +331,9 @@ static void BarMainPrintTime (BarApp_t *app) { static void BarMainLoop (BarApp_t *app) { pthread_t playerThread; - BarMainGetLoginCredentials (&app->settings, &app->input); + if (!BarMainGetLoginCredentials (&app->settings, &app->input)) { + return; + } BarMainLoadProxy (&app->settings, &app->waith); diff --git a/src/settings.c b/src/settings.c index c8bcbfe..014c561 100644 --- a/src/settings.c +++ b/src/settings.c @@ -86,6 +86,7 @@ void BarSettingsDestroy (BarSettings_t *settings) { free (settings->proxy); free (settings->username); free (settings->password); + free (settings->passwordCmd); free (settings->autostartStation); free (settings->eventCmd); free (settings->loveIcon); @@ -189,6 +190,8 @@ void BarSettingsRead (BarSettings_t *settings) { settings->username = strdup (val); } else if (streq ("password", key)) { settings->password = strdup (val); + } else if (streq ("password_command", key)) { + settings->passwordCmd = strdup (val); } else if (streq ("rpc_host", key)) { free (settings->rpcHost); settings->rpcHost = strdup (val); diff --git a/src/settings.h b/src/settings.h index 0f4c6de..30915c2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -87,7 +87,7 @@ typedef struct { BarStationSorting_t sortOrder; PianoAudioQuality_t audioQuality; char *username; - char *password; + char *password, *passwordCmd; char *controlProxy; /* non-american listeners need this */ char *proxy; char *autostartStation; -- cgit v1.2.3