1 /*
2 * secret_driver.c: local driver for secret manipulation API
3 *
4 * Copyright (C) 2009-2016 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #include <config.h>
22
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "internal.h"
28 #include "datatypes.h"
29 #include "driver.h"
30 #include "virlog.h"
31 #include "viralloc.h"
32 #include "secret_conf.h"
33 #include "virsecretobj.h"
34 #include "secret_driver.h"
35 #include "virthread.h"
36 #include "viruuid.h"
37 #include "virerror.h"
38 #include "virfile.h"
39 #include "viridentity.h"
40 #include "virpidfile.h"
41 #include "configmake.h"
42 #include "virstring.h"
43 #include "viraccessapicheck.h"
44 #include "secret_event.h"
45 #include "virutil.h"
46
47 #define VIR_FROM_THIS VIR_FROM_SECRET
48
49 VIR_LOG_INIT("secret.secret_driver");
50
51 enum { SECRET_MAX_XML_FILE = 10*1024*1024 };
52
53 /* Internal driver state */
54
55 typedef struct _virSecretDriverState virSecretDriverState;
56 struct _virSecretDriverState {
57 virMutex lock;
58 bool privileged; /* readonly */
59 char *embeddedRoot; /* readonly */
60 int embeddedRefs;
61 virSecretObjList *secrets;
62 char *stateDir;
63 char *configDir;
64
65 /* pid file FD, ensures two copies of the driver can't use the same root */
66 int lockFD;
67
68 /* Immutable pointer, self-locking APIs */
69 virObjectEventState *secretEventState;
70 };
71
72 static virSecretDriverState *driver;
73
74 static void
secretDriverLock(void)75 secretDriverLock(void)
76 {
77 virMutexLock(&driver->lock);
78 }
79
80
81 static void
secretDriverUnlock(void)82 secretDriverUnlock(void)
83 {
84 virMutexUnlock(&driver->lock);
85 }
86
87
88 static virSecretObj *
secretObjFromSecret(virSecretPtr secret)89 secretObjFromSecret(virSecretPtr secret)
90 {
91 virSecretObj *obj;
92 char uuidstr[VIR_UUID_STRING_BUFLEN];
93
94 virUUIDFormat(secret->uuid, uuidstr);
95 if (!(obj = virSecretObjListFindByUUID(driver->secrets, uuidstr))) {
96 virReportError(VIR_ERR_NO_SECRET,
97 _("no secret with matching uuid '%s'"), uuidstr);
98 return NULL;
99 }
100 return obj;
101 }
102
103
104 /* Driver functions */
105
106 static int
secretConnectNumOfSecrets(virConnectPtr conn)107 secretConnectNumOfSecrets(virConnectPtr conn)
108 {
109 if (virConnectNumOfSecretsEnsureACL(conn) < 0)
110 return -1;
111
112 return virSecretObjListNumOfSecrets(driver->secrets,
113 virConnectNumOfSecretsCheckACL,
114 conn);
115 }
116
117
118 static int
secretConnectListSecrets(virConnectPtr conn,char ** uuids,int maxuuids)119 secretConnectListSecrets(virConnectPtr conn,
120 char **uuids,
121 int maxuuids)
122 {
123 memset(uuids, 0, maxuuids * sizeof(*uuids));
124
125 if (virConnectListSecretsEnsureACL(conn) < 0)
126 return -1;
127
128 return virSecretObjListGetUUIDs(driver->secrets, uuids, maxuuids,
129 virConnectListSecretsCheckACL, conn);
130 }
131
132
133 static int
secretConnectListAllSecrets(virConnectPtr conn,virSecretPtr ** secrets,unsigned int flags)134 secretConnectListAllSecrets(virConnectPtr conn,
135 virSecretPtr **secrets,
136 unsigned int flags)
137 {
138 virCheckFlags(VIR_CONNECT_LIST_SECRETS_FILTERS_ALL, -1);
139
140 if (virConnectListAllSecretsEnsureACL(conn) < 0)
141 return -1;
142
143 return virSecretObjListExport(conn, driver->secrets, secrets,
144 virConnectListAllSecretsCheckACL,
145 flags);
146 }
147
148
149 static virSecretPtr
secretLookupByUUID(virConnectPtr conn,const unsigned char * uuid)150 secretLookupByUUID(virConnectPtr conn,
151 const unsigned char *uuid)
152 {
153 virSecretPtr ret = NULL;
154 virSecretObj *obj;
155 virSecretDef *def;
156 char uuidstr[VIR_UUID_STRING_BUFLEN];
157
158 virUUIDFormat(uuid, uuidstr);
159 if (!(obj = virSecretObjListFindByUUID(driver->secrets, uuidstr))) {
160 virReportError(VIR_ERR_NO_SECRET,
161 _("no secret with matching uuid '%s'"), uuidstr);
162 goto cleanup;
163 }
164
165 def = virSecretObjGetDef(obj);
166 if (virSecretLookupByUUIDEnsureACL(conn, def) < 0)
167 goto cleanup;
168
169 ret = virGetSecret(conn,
170 def->uuid,
171 def->usage_type,
172 def->usage_id);
173
174 cleanup:
175 virSecretObjEndAPI(&obj);
176 return ret;
177 }
178
179
180 static virSecretPtr
secretLookupByUsage(virConnectPtr conn,int usageType,const char * usageID)181 secretLookupByUsage(virConnectPtr conn,
182 int usageType,
183 const char *usageID)
184 {
185 virSecretPtr ret = NULL;
186 virSecretObj *obj;
187 virSecretDef *def;
188
189 if (!(obj = virSecretObjListFindByUsage(driver->secrets,
190 usageType, usageID))) {
191 virReportError(VIR_ERR_NO_SECRET,
192 _("no secret with matching usage '%s'"), usageID);
193 goto cleanup;
194 }
195
196 def = virSecretObjGetDef(obj);
197 if (virSecretLookupByUsageEnsureACL(conn, def) < 0)
198 goto cleanup;
199
200 ret = virGetSecret(conn,
201 def->uuid,
202 def->usage_type,
203 def->usage_id);
204
205 cleanup:
206 virSecretObjEndAPI(&obj);
207 return ret;
208 }
209
210
211 static virSecretPtr
secretDefineXML(virConnectPtr conn,const char * xml,unsigned int flags)212 secretDefineXML(virConnectPtr conn,
213 const char *xml,
214 unsigned int flags)
215 {
216 virSecretPtr ret = NULL;
217 virSecretObj *obj = NULL;
218 virSecretDef *objDef;
219 virSecretDef *backup = NULL;
220 virSecretDef *def;
221 virObjectEvent *event = NULL;
222
223 virCheckFlags(VIR_SECRET_DEFINE_VALIDATE, NULL);
224
225 if (!(def = virSecretDefParseString(xml, flags)))
226 return NULL;
227
228 if (virSecretDefineXMLEnsureACL(conn, def) < 0)
229 goto cleanup;
230
231 if (!(obj = virSecretObjListAdd(driver->secrets, &def,
232 driver->configDir, &backup)))
233 goto cleanup;
234 objDef = virSecretObjGetDef(obj);
235
236 if (!objDef->isephemeral) {
237 if (backup && backup->isephemeral) {
238 if (virSecretObjSaveData(obj) < 0)
239 goto restore_backup;
240 }
241
242 if (virSecretObjSaveConfig(obj) < 0) {
243 if (backup && backup->isephemeral) {
244 /* Undo the virSecretObjSaveData() above; ignore errors */
245 virSecretObjDeleteData(obj);
246 }
247 goto restore_backup;
248 }
249 } else if (backup && !backup->isephemeral) {
250 if (virSecretObjDeleteConfig(obj) < 0)
251 goto restore_backup;
252
253 virSecretObjDeleteData(obj);
254 }
255 /* Saved successfully - drop old values */
256 virSecretDefFree(backup);
257
258 event = virSecretEventLifecycleNew(objDef->uuid,
259 objDef->usage_type,
260 objDef->usage_id,
261 VIR_SECRET_EVENT_DEFINED,
262 0);
263
264 ret = virGetSecret(conn,
265 objDef->uuid,
266 objDef->usage_type,
267 objDef->usage_id);
268 goto cleanup;
269
270 restore_backup:
271 /* If we have a backup, then secret was defined before, so just restore
272 * the backup; otherwise, this is a new secret, thus remove it. */
273 if (backup) {
274 virSecretObjSetDef(obj, backup);
275 def = g_steal_pointer(&objDef);
276 } else {
277 virSecretObjListRemove(driver->secrets, obj);
278 virObjectUnref(obj);
279 obj = NULL;
280 }
281
282 cleanup:
283 virSecretDefFree(def);
284 virSecretObjEndAPI(&obj);
285 virObjectEventStateQueue(driver->secretEventState, event);
286
287 return ret;
288 }
289
290
291 static char *
secretGetXMLDesc(virSecretPtr secret,unsigned int flags)292 secretGetXMLDesc(virSecretPtr secret,
293 unsigned int flags)
294 {
295 char *ret = NULL;
296 virSecretObj *obj;
297 virSecretDef *def;
298
299 virCheckFlags(0, NULL);
300
301 if (!(obj = secretObjFromSecret(secret)))
302 goto cleanup;
303
304 def = virSecretObjGetDef(obj);
305 if (virSecretGetXMLDescEnsureACL(secret->conn, def) < 0)
306 goto cleanup;
307
308 ret = virSecretDefFormat(def);
309
310 cleanup:
311 virSecretObjEndAPI(&obj);
312
313 return ret;
314 }
315
316
317 static int
secretSetValue(virSecretPtr secret,const unsigned char * value,size_t value_size,unsigned int flags)318 secretSetValue(virSecretPtr secret,
319 const unsigned char *value,
320 size_t value_size,
321 unsigned int flags)
322 {
323 int ret = -1;
324 virSecretObj *obj;
325 virSecretDef *def;
326 virObjectEvent *event = NULL;
327
328 virCheckFlags(0, -1);
329
330 if (!(obj = secretObjFromSecret(secret)))
331 goto cleanup;
332
333 def = virSecretObjGetDef(obj);
334 if (virSecretSetValueEnsureACL(secret->conn, def) < 0)
335 goto cleanup;
336
337 if (virSecretObjSetValue(obj, value, value_size) < 0)
338 goto cleanup;
339
340 event = virSecretEventValueChangedNew(def->uuid,
341 def->usage_type,
342 def->usage_id);
343 ret = 0;
344
345 cleanup:
346 virSecretObjEndAPI(&obj);
347 virObjectEventStateQueue(driver->secretEventState, event);
348
349 return ret;
350 }
351
352
353 static unsigned char *
secretGetValue(virSecretPtr secret,size_t * value_size,unsigned int flags)354 secretGetValue(virSecretPtr secret,
355 size_t *value_size,
356 unsigned int flags)
357 {
358 unsigned char *ret = NULL;
359 virSecretObj *obj;
360 virSecretDef *def;
361
362 virCheckFlags(0, NULL);
363
364 if (!(obj = secretObjFromSecret(secret)))
365 goto cleanup;
366
367 def = virSecretObjGetDef(obj);
368 if (virSecretGetValueEnsureACL(secret->conn, def) < 0)
369 goto cleanup;
370
371 /*
372 * For historical compat we want to deny access to
373 * private secrets, even if no ACL driver is
374 * present.
375 *
376 * We need to validate the identity requesting
377 * the secret value is running as the same user
378 * credentials as this driver.
379 *
380 * ie a non-root libvirt client should not be
381 * able to request the value from privileged
382 * libvirt driver.
383 *
384 * To apply restrictions to processes running under
385 * the same user account is out of scope.
386 */
387 if (def->isprivate) {
388 int rv = virIdentityIsCurrentElevated();
389 if (rv < 0)
390 goto cleanup;
391 if (rv == 0) {
392 virReportError(VIR_ERR_INVALID_SECRET, "%s",
393 _("secret is private"));
394 goto cleanup;
395 }
396 }
397
398 if (!(ret = virSecretObjGetValue(obj)))
399 goto cleanup;
400
401 *value_size = virSecretObjGetValueSize(obj);
402
403 cleanup:
404 virSecretObjEndAPI(&obj);
405
406 return ret;
407 }
408
409
410 static int
secretUndefine(virSecretPtr secret)411 secretUndefine(virSecretPtr secret)
412 {
413 int ret = -1;
414 virSecretObj *obj;
415 virSecretDef *def;
416 virObjectEvent *event = NULL;
417
418 if (!(obj = secretObjFromSecret(secret)))
419 goto cleanup;
420
421 def = virSecretObjGetDef(obj);
422 if (virSecretUndefineEnsureACL(secret->conn, def) < 0)
423 goto cleanup;
424
425 if (virSecretObjDeleteConfig(obj) < 0)
426 goto cleanup;
427
428 event = virSecretEventLifecycleNew(def->uuid,
429 def->usage_type,
430 def->usage_id,
431 VIR_SECRET_EVENT_UNDEFINED,
432 0);
433
434 virSecretObjDeleteData(obj);
435
436 virSecretObjListRemove(driver->secrets, obj);
437 virObjectUnref(obj);
438 obj = NULL;
439
440 ret = 0;
441
442 cleanup:
443 virSecretObjEndAPI(&obj);
444 virObjectEventStateQueue(driver->secretEventState, event);
445
446 return ret;
447 }
448
449
450 static int
secretStateCleanup(void)451 secretStateCleanup(void)
452 {
453 if (!driver)
454 return -1;
455
456 secretDriverLock();
457
458 virObjectUnref(driver->secrets);
459 VIR_FREE(driver->configDir);
460
461 virObjectUnref(driver->secretEventState);
462
463 if (driver->lockFD != -1)
464 virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
465
466 VIR_FREE(driver->stateDir);
467 secretDriverUnlock();
468 virMutexDestroy(&driver->lock);
469 VIR_FREE(driver);
470
471 return 0;
472 }
473
474
475 static int
secretStateInitialize(bool privileged,const char * root,virStateInhibitCallback callback G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)476 secretStateInitialize(bool privileged,
477 const char *root,
478 virStateInhibitCallback callback G_GNUC_UNUSED,
479 void *opaque G_GNUC_UNUSED)
480 {
481 driver = g_new0(virSecretDriverState, 1);
482
483 driver->lockFD = -1;
484 if (virMutexInit(&driver->lock) < 0) {
485 VIR_FREE(driver);
486 return VIR_DRV_STATE_INIT_ERROR;
487 }
488 secretDriverLock();
489
490 driver->secretEventState = virObjectEventStateNew();
491 driver->privileged = privileged;
492
493 if (root) {
494 driver->embeddedRoot = g_strdup(root);
495 driver->configDir = g_strdup_printf("%s/etc/secrets", root);
496 driver->stateDir = g_strdup_printf("%s/run/secrets", root);
497 } else if (privileged) {
498 driver->configDir = g_strdup_printf("%s/libvirt/secrets", SYSCONFDIR);
499 driver->stateDir = g_strdup_printf("%s/libvirt/secrets", RUNSTATEDIR);
500 } else {
501 g_autofree char *rundir = NULL;
502 g_autofree char *cfgdir = NULL;
503
504 cfgdir = virGetUserConfigDirectory();
505 driver->configDir = g_strdup_printf("%s/secrets/", cfgdir);
506
507 rundir = virGetUserRuntimeDirectory();
508 driver->stateDir = g_strdup_printf("%s/secrets/run", rundir);
509 }
510
511 if (g_mkdir_with_parents(driver->configDir, S_IRWXU) < 0) {
512 virReportSystemError(errno, _("cannot create config directory '%s'"),
513 driver->configDir);
514 goto error;
515 }
516
517 if (g_mkdir_with_parents(driver->stateDir, S_IRWXU) < 0) {
518 virReportSystemError(errno, _("cannot create state directory '%s'"),
519 driver->stateDir);
520 goto error;
521 }
522
523 if ((driver->lockFD =
524 virPidFileAcquire(driver->stateDir, "driver", false, getpid())) < 0)
525 goto error;
526
527 if (!(driver->secrets = virSecretObjListNew()))
528 goto error;
529
530 if (virSecretLoadAllConfigs(driver->secrets, driver->configDir) < 0)
531 goto error;
532
533 secretDriverUnlock();
534 return VIR_DRV_STATE_INIT_COMPLETE;
535
536 error:
537 secretDriverUnlock();
538 secretStateCleanup();
539 return VIR_DRV_STATE_INIT_ERROR;
540 }
541
542
543 static int
secretStateReload(void)544 secretStateReload(void)
545 {
546 if (!driver)
547 return -1;
548
549 secretDriverLock();
550
551 ignore_value(virSecretLoadAllConfigs(driver->secrets, driver->configDir));
552
553 secretDriverUnlock();
554 return 0;
555 }
556
557
558 static virDrvOpenStatus
secretConnectOpen(virConnectPtr conn,virConnectAuthPtr auth G_GNUC_UNUSED,virConf * conf G_GNUC_UNUSED,unsigned int flags)559 secretConnectOpen(virConnectPtr conn,
560 virConnectAuthPtr auth G_GNUC_UNUSED,
561 virConf *conf G_GNUC_UNUSED,
562 unsigned int flags)
563 {
564 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
565
566 if (driver == NULL) {
567 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
568 _("secret state driver is not active"));
569 return VIR_DRV_OPEN_ERROR;
570 }
571
572 if (driver->embeddedRoot) {
573 const char *root = virURIGetParam(conn->uri, "root");
574 if (!root)
575 return VIR_DRV_OPEN_ERROR;
576
577 if (STRNEQ(conn->uri->path, "/embed")) {
578 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
579 _("URI must be secret:///embed"));
580 return VIR_DRV_OPEN_ERROR;
581 }
582
583 if (STRNEQ(root, driver->embeddedRoot)) {
584 virReportError(VIR_ERR_INTERNAL_ERROR,
585 _("Cannot open embedded driver at path '%s', "
586 "already open with path '%s'"),
587 root, driver->embeddedRoot);
588 return VIR_DRV_OPEN_ERROR;
589 }
590 } else {
591 if (!virConnectValidateURIPath(conn->uri->path,
592 "secret",
593 driver->privileged))
594 return VIR_DRV_OPEN_ERROR;
595 }
596
597 if (virConnectOpenEnsureACL(conn) < 0)
598 return VIR_DRV_OPEN_ERROR;
599
600 if (driver->embeddedRoot) {
601 secretDriverLock();
602 if (driver->embeddedRefs == 0)
603 virSetConnectSecret(conn);
604 driver->embeddedRefs++;
605 secretDriverUnlock();
606 }
607
608 return VIR_DRV_OPEN_SUCCESS;
609 }
610
secretConnectClose(virConnectPtr conn G_GNUC_UNUSED)611 static int secretConnectClose(virConnectPtr conn G_GNUC_UNUSED)
612 {
613 if (driver->embeddedRoot) {
614 secretDriverLock();
615 driver->embeddedRefs--;
616 if (driver->embeddedRefs == 0)
617 virSetConnectSecret(NULL);
618 secretDriverUnlock();
619 }
620 return 0;
621 }
622
623
secretConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)624 static int secretConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)
625 {
626 /* Trivially secure, since always inside the daemon */
627 return 1;
628 }
629
630
secretConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)631 static int secretConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)
632 {
633 /* Not encrypted, but remote driver takes care of that */
634 return 0;
635 }
636
637
secretConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)638 static int secretConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
639 {
640 return 1;
641 }
642
643
644 static int
secretConnectSecretEventRegisterAny(virConnectPtr conn,virSecretPtr secret,int eventID,virConnectSecretEventGenericCallback callback,void * opaque,virFreeCallback freecb)645 secretConnectSecretEventRegisterAny(virConnectPtr conn,
646 virSecretPtr secret,
647 int eventID,
648 virConnectSecretEventGenericCallback callback,
649 void *opaque,
650 virFreeCallback freecb)
651 {
652 int callbackID = -1;
653
654 if (virConnectSecretEventRegisterAnyEnsureACL(conn) < 0)
655 return -1;
656
657 if (virSecretEventStateRegisterID(conn, driver->secretEventState,
658 secret, eventID, callback,
659 opaque, freecb, &callbackID) < 0)
660 callbackID = -1;
661
662 return callbackID;
663 }
664
665
666 static int
secretConnectSecretEventDeregisterAny(virConnectPtr conn,int callbackID)667 secretConnectSecretEventDeregisterAny(virConnectPtr conn,
668 int callbackID)
669 {
670 if (virConnectSecretEventDeregisterAnyEnsureACL(conn) < 0)
671 return -1;
672
673 if (virObjectEventStateDeregisterID(conn,
674 driver->secretEventState,
675 callbackID, true) < 0)
676 return -1;
677
678 return 0;
679 }
680
681
682 static virSecretDriver secretDriver = {
683 .name = "secret",
684 .connectNumOfSecrets = secretConnectNumOfSecrets, /* 0.7.1 */
685 .connectListSecrets = secretConnectListSecrets, /* 0.7.1 */
686 .connectListAllSecrets = secretConnectListAllSecrets, /* 0.10.2 */
687 .secretLookupByUUID = secretLookupByUUID, /* 0.7.1 */
688 .secretLookupByUsage = secretLookupByUsage, /* 0.7.1 */
689 .secretDefineXML = secretDefineXML, /* 0.7.1 */
690 .secretGetXMLDesc = secretGetXMLDesc, /* 0.7.1 */
691 .secretSetValue = secretSetValue, /* 0.7.1 */
692 .secretGetValue = secretGetValue, /* 0.7.1 */
693 .secretUndefine = secretUndefine, /* 0.7.1 */
694 .connectSecretEventRegisterAny = secretConnectSecretEventRegisterAny, /* 3.0.0 */
695 .connectSecretEventDeregisterAny = secretConnectSecretEventDeregisterAny, /* 3.0.0 */
696 };
697
698
699 static virHypervisorDriver secretHypervisorDriver = {
700 .name = "secret",
701 .connectOpen = secretConnectOpen, /* 4.1.0 */
702 .connectClose = secretConnectClose, /* 4.1.0 */
703 .connectIsEncrypted = secretConnectIsEncrypted, /* 4.1.0 */
704 .connectIsSecure = secretConnectIsSecure, /* 4.1.0 */
705 .connectIsAlive = secretConnectIsAlive, /* 4.1.0 */
706 };
707
708
709 static virConnectDriver secretConnectDriver = {
710 .localOnly = true,
711 .uriSchemes = (const char *[]){ "secret", NULL },
712 .embeddable = true,
713 .hypervisorDriver = &secretHypervisorDriver,
714 .secretDriver = &secretDriver,
715 };
716
717
718 static virStateDriver stateDriver = {
719 .name = "secret",
720 .stateInitialize = secretStateInitialize,
721 .stateCleanup = secretStateCleanup,
722 .stateReload = secretStateReload,
723 };
724
725
726 int
secretRegister(void)727 secretRegister(void)
728 {
729 if (virRegisterConnectDriver(&secretConnectDriver, false) < 0)
730 return -1;
731 if (virSetSharedSecretDriver(&secretDriver) < 0)
732 return -1;
733 if (virRegisterStateDriver(&stateDriver) < 0)
734 return -1;
735 return 0;
736 }
737