util: add API for reading password from the console

This imports a simpler version of GNULIB's getpass() function
impl for Windows. Note that GNULIB's impl was buggy as it
returned a static string on UNIX, and a heap allocated string
on Windows. This new impl always heap allocates.

Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2020-01-14 10:40:52 +00:00
parent 19ff90a9c5
commit db72866310
5 changed files with 37 additions and 6 deletions

View File

@ -30,7 +30,6 @@
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/xpath.h> #include <libxml/xpath.h>
#include "getpass.h"
#ifdef WITH_CURL #ifdef WITH_CURL
# include <curl/curl.h> # include <curl/curl.h>
@ -157,9 +156,9 @@ virConnectAuthCallbackDefault(virConnectCredentialPtr cred,
if (fflush(stdout) != 0) if (fflush(stdout) != 0)
return -1; return -1;
bufptr = getpass(""); bufptr = virGetPassword();
if (!bufptr) if (STREQ(bufptr, ""))
return -1; VIR_FREE(bufptr);
break; break;
default: default:
@ -167,7 +166,7 @@ virConnectAuthCallbackDefault(virConnectCredentialPtr cred,
} }
if (cred[i].type != VIR_CRED_EXTERNAL) { if (cred[i].type != VIR_CRED_EXTERNAL) {
cred[i].result = g_strdup(STREQ(bufptr, "") && cred[i].defresult ? cred[i].defresult : bufptr); cred[i].result = bufptr ? bufptr : g_strdup(cred[i].defresult ? cred[i].defresult : "");
cred[i].resultlen = strlen(cred[i].result); cred[i].resultlen = strlen(cred[i].result);
} }
} }

View File

@ -3380,6 +3380,7 @@ virGetGroupList;
virGetGroupName; virGetGroupName;
virGetHostname; virGetHostname;
virGetHostnameQuiet; virGetHostnameQuiet;
virGetPassword;
virGetSelfLastChanged; virGetSelfLastChanged;
virGetSystemPageSize; virGetSystemPageSize;
virGetSystemPageSizeKB; virGetSystemPageSizeKB;

View File

@ -28,6 +28,10 @@
#include <poll.h> #include <poll.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef WIN32
# include <conio.h>
#endif /* WIN32 */
#ifdef MAJOR_IN_MKDEV #ifdef MAJOR_IN_MKDEV
# include <sys/mkdev.h> # include <sys/mkdev.h>
#elif MAJOR_IN_SYSMACROS #elif MAJOR_IN_SYSMACROS
@ -1731,3 +1735,28 @@ virHostGetDRMRenderNode(void)
VIR_DIR_CLOSE(driDir); VIR_DIR_CLOSE(driDir);
return ret; return ret;
} }
/*
* Get a password from the console input stream.
* The caller must free the returned password.
*
* Returns: the password, or NULL
*/
char *virGetPassword(void)
{
#ifdef WIN32
GString *pw = g_string_new("");
while (1) {
char c = _getch();
if (c == '\r')
break;
g_string_append_c(pw, c);
}
return g_string_free(pw, FALSE);
#else /* !WIN32 */
return g_strdup(getpass(""));
#endif /* ! WIN32 */
}

View File

@ -159,3 +159,5 @@ char *virHostGetDRMRenderNode(void) G_GNUC_NO_INLINE;
*/ */
#define VIR_ASSIGN_IS_OVERFLOW(lvalue, rvalue) \ #define VIR_ASSIGN_IS_OVERFLOW(lvalue, rvalue) \
(((lvalue) = (rvalue)) != (rvalue)) (((lvalue) = (rvalue)) != (rvalue))
char *virGetPassword(void);

View File

@ -250,7 +250,7 @@ cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd)
vshPrint(ctl, "%s", _("Enter new value for secret:")); vshPrint(ctl, "%s", _("Enter new value for secret:"));
fflush(stdout); fflush(stdout);
if (!(file_buf = getpass(""))) { if (!(file_buf = virGetPassword())) {
vshError(ctl, "%s", _("Failed to read secret")); vshError(ctl, "%s", _("Failed to read secret"));
return false; return false;
} }