mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Add openauth example to demonstrate a custom auth callback
This commit is contained in:
parent
73b9dfeb31
commit
9af989fabc
@ -6,7 +6,7 @@ GENHTML = genhtml
|
|||||||
SUBDIRS = gnulib/lib include src daemon tools proxy docs gnulib/tests \
|
SUBDIRS = gnulib/lib include src daemon tools proxy docs gnulib/tests \
|
||||||
python tests po examples/domain-events/events-c examples/hellolibvirt \
|
python tests po examples/domain-events/events-c examples/hellolibvirt \
|
||||||
examples/dominfo examples/domsuspend examples/python examples/apparmor \
|
examples/dominfo examples/domsuspend examples/python examples/apparmor \
|
||||||
examples/xml/nwfilter
|
examples/xml/nwfilter examples/openauth
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4
|
ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4
|
||||||
|
|
||||||
|
@ -2129,6 +2129,7 @@ AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile \
|
|||||||
examples/domain-events/events-c/Makefile \
|
examples/domain-events/events-c/Makefile \
|
||||||
examples/domsuspend/Makefile \
|
examples/domsuspend/Makefile \
|
||||||
examples/dominfo/Makefile \
|
examples/dominfo/Makefile \
|
||||||
|
examples/openauth/Makefile \
|
||||||
examples/python/Makefile \
|
examples/python/Makefile \
|
||||||
examples/hellolibvirt/Makefile \
|
examples/hellolibvirt/Makefile \
|
||||||
examples/xml/nwfilter/Makefile)
|
examples/xml/nwfilter/Makefile)
|
||||||
|
5
examples/openauth/.gitignore
vendored
Normal file
5
examples/openauth/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
openauth
|
||||||
|
.deps
|
||||||
|
.libs
|
5
examples/openauth/Makefile.am
Normal file
5
examples/openauth/Makefile.am
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||||
|
noinst_PROGRAMS = openauth
|
||||||
|
openauth_CFLAGS = $(WARN_CFLAGS)
|
||||||
|
openauth_SOURCES = openauth.c
|
||||||
|
openauth_LDADD = @top_builddir@/src/libvirt.la
|
287
examples/openauth/openauth.c
Normal file
287
examples/openauth/openauth.c
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/* This is a copy of the hellolibvirt example demonstaring how to use
|
||||||
|
* virConnectOpenAuth with a custom auth callback */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libvirt/libvirt.h>
|
||||||
|
#include <libvirt/virterror.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
showError(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
virErrorPtr err;
|
||||||
|
|
||||||
|
err = malloc(sizeof(*err));
|
||||||
|
if (err == NULL) {
|
||||||
|
printf("Could not allocate memory for error data\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virConnCopyLastError(conn, err);
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case 0:
|
||||||
|
printf("No error found\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
printf("Parameter error when attempting to get last error\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("libvirt reported: \"%s\"\n", err->message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
virResetError(err);
|
||||||
|
free(err);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
showHypervisorInfo(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned long hvVer, major, minor, release;
|
||||||
|
const char *hvType;
|
||||||
|
|
||||||
|
/* virConnectGetType returns a pointer to a static string, so no
|
||||||
|
* allocation or freeing is necessary; it is possible for the call
|
||||||
|
* to fail if, for example, there is no connection to a
|
||||||
|
* hypervisor, so check what it returns. */
|
||||||
|
hvType = virConnectGetType(conn);
|
||||||
|
if (hvType == NULL) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Failed to get hypervisor type\n");
|
||||||
|
showError(conn);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virConnectGetVersion(conn, &hvVer) != 0) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Failed to get hypervisor version\n");
|
||||||
|
showError(conn);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
major = hvVer / 1000000;
|
||||||
|
hvVer %= 1000000;
|
||||||
|
minor = hvVer / 1000;
|
||||||
|
release = hvVer % 1000;
|
||||||
|
|
||||||
|
printf("Hypervisor: \"%s\" version: %lu.%lu.%lu\n",
|
||||||
|
hvType,
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
release);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
showDomains(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
int ret = 0, i, numNames, numInactiveDomains, numActiveDomains;
|
||||||
|
char **nameList = NULL;
|
||||||
|
|
||||||
|
numActiveDomains = virConnectNumOfDomains(conn);
|
||||||
|
if (numActiveDomains == -1) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Failed to get number of active domains\n");
|
||||||
|
showError(conn);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
numInactiveDomains = virConnectNumOfDefinedDomains(conn);
|
||||||
|
if (numInactiveDomains == -1) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Failed to get number of inactive domains\n");
|
||||||
|
showError(conn);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("There are %d active and %d inactive domains\n",
|
||||||
|
numActiveDomains, numInactiveDomains);
|
||||||
|
|
||||||
|
nameList = malloc(sizeof(*nameList) * numInactiveDomains);
|
||||||
|
|
||||||
|
if (nameList == NULL) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Could not allocate memory for list of inactive domains\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
numNames = virConnectListDefinedDomains(conn,
|
||||||
|
nameList,
|
||||||
|
numInactiveDomains);
|
||||||
|
|
||||||
|
if (numNames == -1) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Could not get list of defined domains from hypervisor\n");
|
||||||
|
showError(conn);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numNames > 0) {
|
||||||
|
printf("Inactive domains:\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < numNames ; i++) {
|
||||||
|
printf(" %s\n", *(nameList + i));
|
||||||
|
/* The API documentation doesn't say so, but the names
|
||||||
|
* returned by virConnectListDefinedDomains are strdup'd and
|
||||||
|
* must be freed here. */
|
||||||
|
free(*(nameList + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(nameList);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Struct to pass the credentials to the auth callback via the cbdata pointer */
|
||||||
|
struct _AuthData {
|
||||||
|
char *username;
|
||||||
|
char *password;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _AuthData AuthData;
|
||||||
|
|
||||||
|
/* This function will be called by libvirt to obtain credentials in order to
|
||||||
|
* authenticate to the hypervisor */
|
||||||
|
static int
|
||||||
|
authCallback(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
AuthData *authData = cbdata;
|
||||||
|
|
||||||
|
/* libvirt might request multiple credentials in a single call.
|
||||||
|
* This example supports VIR_CRED_AUTHNAME and VIR_CRED_PASSPHRASE
|
||||||
|
* credentials only, but there are several other types.
|
||||||
|
*
|
||||||
|
* A request may also contain a prompt message that can be displayed
|
||||||
|
* to the user and a challenge. The challenge is specific to the
|
||||||
|
* credential type and hypervisor type.
|
||||||
|
*
|
||||||
|
* For example the ESX driver passes the hostname of the ESX or vCenter
|
||||||
|
* server as challenge. This allows a auth callback to return the
|
||||||
|
* proper credentials. */
|
||||||
|
for (i = 0; i < ncred ; ++i) {
|
||||||
|
switch (cred[i].type) {
|
||||||
|
case VIR_CRED_AUTHNAME:
|
||||||
|
cred[i].result = strdup(authData->username);
|
||||||
|
|
||||||
|
if (cred[i].result == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cred[i].resultlen = strlen(cred[i].result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIR_CRED_PASSPHRASE:
|
||||||
|
cred[i].result = strdup(authData->password);
|
||||||
|
|
||||||
|
if (cred[i].result == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cred[i].resultlen = strlen(cred[i].result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The list of credential types supported by our auth callback */
|
||||||
|
static int credTypes[] = {
|
||||||
|
VIR_CRED_AUTHNAME,
|
||||||
|
VIR_CRED_PASSPHRASE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* The auth struct that will be passed to virConnectOpenAuth */
|
||||||
|
static virConnectAuth auth = {
|
||||||
|
credTypes,
|
||||||
|
sizeof(credTypes) / sizeof(int),
|
||||||
|
authCallback,
|
||||||
|
NULL, // cbdata will be initialized in main
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
virConnectPtr conn;
|
||||||
|
char *uri;
|
||||||
|
AuthData authData;
|
||||||
|
|
||||||
|
if (argc != 4) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Usage: %s <uri> <username> <password>\n", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
uri = argv[1];
|
||||||
|
authData.username = argv[2];
|
||||||
|
authData.password = argv[3];
|
||||||
|
auth.cbdata = &authData;
|
||||||
|
|
||||||
|
printf("Attempting to connect to hypervisor\n");
|
||||||
|
|
||||||
|
conn = virConnectOpenAuth(uri, &auth, 0);
|
||||||
|
|
||||||
|
if (NULL == conn) {
|
||||||
|
ret = 1;
|
||||||
|
printf("No connection to hypervisor\n");
|
||||||
|
showError(conn);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
uri = virConnectGetURI(conn);
|
||||||
|
if (uri == NULL) {
|
||||||
|
ret = 1;
|
||||||
|
printf("Failed to get URI for hypervisor connection\n");
|
||||||
|
showError(conn);
|
||||||
|
goto disconnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connected to hypervisor at \"%s\"\n", uri);
|
||||||
|
free(uri);
|
||||||
|
|
||||||
|
if (showHypervisorInfo(conn) != 0) {
|
||||||
|
ret = 1;
|
||||||
|
goto disconnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showDomains(conn) != 0) {
|
||||||
|
ret = 1;
|
||||||
|
goto disconnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect:
|
||||||
|
if (virConnectClose(conn) != 0) {
|
||||||
|
printf("Failed to disconnect from hypervisor\n");
|
||||||
|
showError(conn);
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
printf("Disconnected from hypervisor\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
@ -585,7 +585,7 @@ gzip -9 ChangeLog
|
|||||||
rm -fr %{buildroot}
|
rm -fr %{buildroot}
|
||||||
|
|
||||||
%makeinstall
|
%makeinstall
|
||||||
for i in domain-events/events-c dominfo domsuspend hellolibvirt python xml/nwfilter
|
for i in domain-events/events-c dominfo domsuspend hellolibvirt openauth python xml/nwfilter
|
||||||
do
|
do
|
||||||
(cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in)
|
(cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in)
|
||||||
done
|
done
|
||||||
@ -887,6 +887,7 @@ fi
|
|||||||
%doc examples/domain-events/events-c
|
%doc examples/domain-events/events-c
|
||||||
%doc examples/dominfo
|
%doc examples/dominfo
|
||||||
%doc examples/domsuspend
|
%doc examples/domsuspend
|
||||||
|
%doc examples/openauth
|
||||||
%doc examples/xml
|
%doc examples/xml
|
||||||
|
|
||||||
%if %{with_python}
|
%if %{with_python}
|
||||||
|
Loading…
Reference in New Issue
Block a user