diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 576ec8f95f..5616c0d44c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1850,6 +1850,8 @@ virAuditSend; # util/virauth.h +virAuthAskCredential; +virAuthConnectCredentialFree; virAuthGetConfigFilePath; virAuthGetConfigFilePathURI; virAuthGetPassword; diff --git a/src/util/virauth.c b/src/util/virauth.c index b9c2ae3ed1..42b77f750a 100644 --- a/src/util/virauth.c +++ b/src/util/virauth.c @@ -31,6 +31,7 @@ #include "virerror.h" #include "configmake.h" #include "virauthconfig.h" +#include "virsecureerase.h" #define VIR_FROM_THIS VIR_FROM_AUTH @@ -283,3 +284,68 @@ virAuthGetPassword(virConnectPtr conn, return virAuthGetPasswordPath(path, auth, servicename, username, hostname); } + + +void +virAuthConnectCredentialFree(virConnectCredential *cred) +{ + if (cred->result) { + virSecureErase(cred->result, cred->resultlen); + g_free(cred->result); + } + g_free(cred); +} + + +/** + * virAuthAskCredential: + * @auth: authentication callback data + * @prompt: question string to ask the user + * @echo: false if user's reply should be considered sensitive and not echoed + * + * Invoke the authentication callback for the connection @auth and ask the user + * the question in @prompt. If @echo is false user's reply should be collected + * as sensitive (user's input not printed on screen). + */ +virConnectCredential * +virAuthAskCredential(virConnectAuthPtr auth, + const char *prompt, + bool echo) +{ + g_autoptr(virConnectCredential) ret = g_new0(virConnectCredential, 1); + size_t i; + + ret->type = -1; + + for (i = 0; i < auth->ncredtype; ++i) { + int type = auth->credtype[i]; + if (echo) { + if (type == VIR_CRED_ECHOPROMPT) { + ret->type = type; + break; + } + } else { + if (type == VIR_CRED_PASSPHRASE || + type == VIR_CRED_NOECHOPROMPT) { + ret->type = type; + break; + } + } + } + + if (ret->type == -1) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("no suitable callback authentication callback was found")); + return NULL; + } + + ret->prompt = prompt; + + if (auth->cb(ret, 1, auth->cbdata) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("failed to retrieve user response for authentication callback")); + return NULL; + } + + return g_steal_pointer(&ret); +} diff --git a/src/util/virauth.h b/src/util/virauth.h index a0fd84962b..3eaf40c626 100644 --- a/src/util/virauth.h +++ b/src/util/virauth.h @@ -52,3 +52,10 @@ char * virAuthGetPasswordPath(const char *path, const char *servicename, const char *username, const char *hostname); + +virConnectCredential *virAuthAskCredential(virConnectAuthPtr auth, + const char *prompt, + bool echo); + +void virAuthConnectCredentialFree(virConnectCredential *cred); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virConnectCredential, virAuthConnectCredentialFree);