examples: Organize C examples into categories
[libvirt/ericb.git] / examples / misc / openauth.c
blobefd21c374f55c47957c12e4859956568c95fcc76
1 /* This is a copy of the hellolibvirt example demonstaring how to use
2 * virConnectOpenAuth with a custom auth callback */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <libvirt/libvirt.h>
8 #include <libvirt/virterror.h>
10 static void
11 showError(virConnectPtr conn)
13 int ret;
14 virErrorPtr err;
16 err = malloc(sizeof(*err));
17 if (err == NULL) {
18 printf("Could not allocate memory for error data\n");
19 goto out;
22 ret = virConnCopyLastError(conn, err);
24 switch (ret) {
25 case 0:
26 printf("No error found\n");
27 break;
29 case -1:
30 printf("Parameter error when attempting to get last error\n");
31 break;
33 default:
34 printf("libvirt reported: \"%s\"\n", err->message);
35 break;
38 virResetError(err);
39 free(err);
41 out:
42 return;
46 static int
47 showHypervisorInfo(virConnectPtr conn)
49 int ret = 0;
50 unsigned long hvVer, major, minor, release;
51 const char *hvType;
53 /* virConnectGetType returns a pointer to a static string, so no
54 * allocation or freeing is necessary; it is possible for the call
55 * to fail if, for example, there is no connection to a
56 * hypervisor, so check what it returns. */
57 hvType = virConnectGetType(conn);
58 if (hvType == NULL) {
59 ret = 1;
60 printf("Failed to get hypervisor type\n");
61 showError(conn);
62 goto out;
65 if (virConnectGetVersion(conn, &hvVer) != 0) {
66 ret = 1;
67 printf("Failed to get hypervisor version\n");
68 showError(conn);
69 goto out;
72 major = hvVer / 1000000;
73 hvVer %= 1000000;
74 minor = hvVer / 1000;
75 release = hvVer % 1000;
77 printf("Hypervisor: \"%s\" version: %lu.%lu.%lu\n",
78 hvType,
79 major,
80 minor,
81 release);
83 out:
84 return ret;
88 static int
89 showDomains(virConnectPtr conn)
91 int ret = 0, numNames, numInactiveDomains, numActiveDomains;
92 ssize_t i;
93 char **nameList = NULL;
95 numActiveDomains = virConnectNumOfDomains(conn);
96 if (numActiveDomains == -1) {
97 ret = 1;
98 printf("Failed to get number of active domains\n");
99 showError(conn);
100 goto out;
103 numInactiveDomains = virConnectNumOfDefinedDomains(conn);
104 if (numInactiveDomains == -1) {
105 ret = 1;
106 printf("Failed to get number of inactive domains\n");
107 showError(conn);
108 goto out;
111 printf("There are %d active and %d inactive domains\n",
112 numActiveDomains, numInactiveDomains);
114 nameList = malloc(sizeof(*nameList) * numInactiveDomains);
116 if (nameList == NULL) {
117 ret = 1;
118 printf("Could not allocate memory for list of inactive domains\n");
119 goto out;
122 numNames = virConnectListDefinedDomains(conn,
123 nameList,
124 numInactiveDomains);
126 if (numNames == -1) {
127 ret = 1;
128 printf("Could not get list of defined domains from hypervisor\n");
129 showError(conn);
130 goto out;
133 if (numNames > 0)
134 printf("Inactive domains:\n");
136 for (i = 0; i < numNames; i++) {
137 printf(" %s\n", *(nameList + i));
138 /* The API documentation doesn't say so, but the names
139 * returned by virConnectListDefinedDomains are strdup'd and
140 * must be freed here. */
141 free(*(nameList + i));
144 out:
145 free(nameList);
146 return ret;
149 /* Struct to pass the credentials to the auth callback via the cbdata pointer */
150 struct _AuthData {
151 char *username;
152 char *password;
155 typedef struct _AuthData AuthData;
157 /* This function will be called by libvirt to obtain credentials in order to
158 * authenticate to the hypervisor */
159 static int
160 authCallback(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata)
162 size_t i;
163 AuthData *authData = cbdata;
165 /* libvirt might request multiple credentials in a single call.
166 * This example supports VIR_CRED_AUTHNAME and VIR_CRED_PASSPHRASE
167 * credentials only, but there are several other types.
169 * A request may also contain a prompt message that can be displayed
170 * to the user and a challenge. The challenge is specific to the
171 * credential type and hypervisor type.
173 * For example the ESX driver passes the hostname of the ESX or vCenter
174 * server as challenge. This allows a auth callback to return the
175 * proper credentials. */
176 for (i = 0; i < ncred; ++i) {
177 switch (cred[i].type) {
178 case VIR_CRED_AUTHNAME:
179 cred[i].result = strdup(authData->username);
181 if (cred[i].result == NULL)
182 return -1;
184 cred[i].resultlen = strlen(cred[i].result);
185 break;
187 case VIR_CRED_PASSPHRASE:
188 cred[i].result = strdup(authData->password);
190 if (cred[i].result == NULL)
191 return -1;
193 cred[i].resultlen = strlen(cred[i].result);
194 break;
196 default:
197 return -1;
201 return 0;
205 /* The list of credential types supported by our auth callback */
206 static int credTypes[] = {
207 VIR_CRED_AUTHNAME,
208 VIR_CRED_PASSPHRASE
212 /* The auth struct that will be passed to virConnectOpenAuth */
213 static virConnectAuth auth = {
214 credTypes,
215 sizeof(credTypes) / sizeof(int),
216 authCallback,
217 NULL, /* cbdata will be initialized in main */
222 main(int argc, char *argv[])
224 int ret = 0;
225 virConnectPtr conn;
226 char *uri;
227 AuthData authData;
229 if (argc != 4) {
230 ret = 1;
231 printf("Usage: %s <uri> <username> <password>\n", argv[0]);
232 goto out;
235 uri = argv[1];
236 authData.username = argv[2];
237 authData.password = argv[3];
238 auth.cbdata = &authData;
240 printf("Attempting to connect to hypervisor\n");
242 conn = virConnectOpenAuth(uri, &auth, 0);
244 if (NULL == conn) {
245 ret = 1;
246 printf("No connection to hypervisor\n");
247 showError(conn);
248 goto out;
251 uri = virConnectGetURI(conn);
252 if (uri == NULL) {
253 ret = 1;
254 printf("Failed to get URI for hypervisor connection\n");
255 showError(conn);
256 goto disconnect;
259 printf("Connected to hypervisor at \"%s\"\n", uri);
260 free(uri);
262 if (showHypervisorInfo(conn) != 0) {
263 ret = 1;
264 goto disconnect;
267 if (showDomains(conn) != 0) {
268 ret = 1;
269 goto disconnect;
272 disconnect:
273 if (virConnectClose(conn) != 0) {
274 printf("Failed to disconnect from hypervisor\n");
275 showError(conn);
276 ret = 1;
277 } else {
278 printf("Disconnected from hypervisor\n");
281 out:
282 return ret;