1 /*
2 * viridentity.c: helper APIs for managing user identities
3 *
4 * Copyright (C) 2012-2013 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
22 #include <config.h>
23
24 #include <unistd.h>
25 #include <fcntl.h>
26 #if WITH_SELINUX
27 # include <selinux/selinux.h>
28 #endif
29
30 #define LIBVIRT_VIRIDENTITYPRIV_H_ALLOW
31
32 #include "internal.h"
33 #include "viralloc.h"
34 #include "virerror.h"
35 #include "viridentitypriv.h"
36 #include "virlog.h"
37 #include "virobject.h"
38 #include "virrandom.h"
39 #include "virthread.h"
40 #include "virutil.h"
41 #include "virstring.h"
42 #include "virprocess.h"
43 #include "virtypedparam.h"
44 #include "virfile.h"
45 #include "configmake.h"
46
47 #define VIR_FROM_THIS VIR_FROM_IDENTITY
48
49 #define VIR_CONNECT_IDENTITY_SYSTEM_TOKEN "system.token"
50
51 VIR_LOG_INIT("util.identity");
52
53 struct _virIdentity {
54 GObject parent;
55
56 int nparams;
57 int maxparams;
58 virTypedParameterPtr params;
59 };
60
G_DEFINE_TYPE(virIdentity,vir_identity,G_TYPE_OBJECT)61 G_DEFINE_TYPE(virIdentity, vir_identity, G_TYPE_OBJECT)
62
63 static virThreadLocal virIdentityCurrent;
64 static char *systemToken;
65
66 static void virIdentityFinalize(GObject *obj);
67
68 static void virIdentityCurrentCleanup(void *ident)
69 {
70 if (ident)
71 g_object_unref(ident);
72 }
73
virIdentityOnceInit(void)74 static int virIdentityOnceInit(void)
75 {
76 if (virThreadLocalInit(&virIdentityCurrent,
77 virIdentityCurrentCleanup) < 0) {
78 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
79 _("Cannot initialize thread local for current identity"));
80 return -1;
81 }
82
83 if (!(systemToken = virIdentityEnsureSystemToken()))
84 return -1;
85
86 return 0;
87 }
88
89 VIR_ONCE_GLOBAL_INIT(virIdentity);
90
vir_identity_init(virIdentity * ident G_GNUC_UNUSED)91 static void vir_identity_init(virIdentity *ident G_GNUC_UNUSED)
92 {
93 }
94
vir_identity_class_init(virIdentityClass * klass)95 static void vir_identity_class_init(virIdentityClass *klass)
96 {
97 GObjectClass *obj = G_OBJECT_CLASS(klass);
98
99 obj->finalize = virIdentityFinalize;
100 }
101
102 /**
103 * virIdentityGetCurrent:
104 *
105 * Get the current identity associated with this thread. The
106 * caller will own a reference to the returned identity, but
107 * must not modify the object in any way, other than to
108 * release the reference when done with g_object_unref
109 *
110 * Returns: a reference to the current identity, or NULL
111 */
virIdentityGetCurrent(void)112 virIdentity *virIdentityGetCurrent(void)
113 {
114 virIdentity *ident;
115
116 if (virIdentityInitialize() < 0)
117 return NULL;
118
119 ident = virThreadLocalGet(&virIdentityCurrent);
120 if (ident)
121 g_object_ref(ident);
122 return ident;
123 }
124
125
126 /**
127 * virIdentitySetCurrent:
128 *
129 * Set the new identity to be associated with this thread.
130 * The caller should not modify the passed identity after
131 * it has been set, other than to release its own reference.
132 *
133 * Returns 0 on success, or -1 on error
134 */
virIdentitySetCurrent(virIdentity * ident)135 int virIdentitySetCurrent(virIdentity *ident)
136 {
137 virIdentity *old = NULL;
138
139 if (virIdentityInitialize() < 0)
140 return -1;
141
142 old = virThreadLocalGet(&virIdentityCurrent);
143
144 if (virThreadLocalSet(&virIdentityCurrent,
145 ident ? g_object_ref(ident) : NULL) < 0) {
146 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
147 _("Unable to set thread local identity"));
148 if (ident)
149 g_object_unref(ident);
150 return -1;
151 }
152
153 if (old)
154 g_object_unref(old);
155 return 0;
156 }
157
158
159 /**
160 * virIdentityElevateCurrent:
161 *
162 * Set the new identity to be associated with this thread,
163 * to an elevated copy of the current identity. The old
164 * current identity is returned and should be released by
165 * the caller when no longer required.
166 *
167 * Returns the previous identity, or NULL on error
168 */
virIdentityElevateCurrent(void)169 virIdentity *virIdentityElevateCurrent(void)
170 {
171 g_autoptr(virIdentity) ident = virIdentityGetCurrent();
172 const char *token;
173 int rc;
174
175 if (!ident) {
176 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
177 _("No current identity to elevate"));
178 return NULL;
179 }
180
181 if ((rc = virIdentityGetSystemToken(ident, &token)) < 0)
182 return NULL;
183
184 if (rc == 0) {
185 g_autoptr(virIdentity) identel = virIdentityNewCopy(ident);
186
187 if (virIdentitySetSystemToken(identel, systemToken) < 0)
188 return NULL;
189
190 if (virIdentitySetCurrent(identel) < 0)
191 return NULL;
192 }
193
194 return g_steal_pointer(&ident);
195 }
196
197
virIdentityRestoreHelper(virIdentity ** identptr)198 void virIdentityRestoreHelper(virIdentity **identptr)
199 {
200 virIdentity *ident = *identptr;
201
202 if (ident != NULL) {
203 virIdentitySetCurrent(ident);
204 /* virIdentitySetCurrent() grabs its own reference.
205 * We don't need ours anymore. */
206 g_object_unref(ident);
207 }
208 }
209
210 #define TOKEN_BYTES 16
211 #define TOKEN_STRLEN (TOKEN_BYTES * 2)
212
213 static char *
virIdentityConstructSystemTokenPath(void)214 virIdentityConstructSystemTokenPath(void)
215 {
216 g_autofree char *commondir = NULL;
217 if (geteuid() == 0) {
218 commondir = g_strdup(RUNSTATEDIR "/libvirt/common");
219 } else {
220 g_autofree char *rundir = virGetUserRuntimeDirectory();
221 commondir = g_strdup_printf("%s/common", rundir);
222 }
223
224 if (g_mkdir_with_parents(commondir, 0700) < 0) {
225 virReportSystemError(errno,
226 _("Cannot create daemon common directory '%s'"),
227 commondir);
228 return NULL;
229 }
230
231 return g_strdup_printf("%s/system.token", commondir);
232 }
233
234
235 char *
virIdentityEnsureSystemToken(void)236 virIdentityEnsureSystemToken(void)
237 {
238 g_autofree char *tokenfile = virIdentityConstructSystemTokenPath();
239 g_autofree char *token = NULL;
240 VIR_AUTOCLOSE fd = -1;
241 struct stat st;
242
243 if (!tokenfile)
244 return NULL;
245
246 fd = open(tokenfile, O_RDWR|O_APPEND|O_CREAT, 0600);
247 if (fd < 0) {
248 virReportSystemError(errno,
249 _("Unable to open system token %s"),
250 tokenfile);
251 return NULL;
252 }
253
254 if (virSetCloseExec(fd) < 0) {
255 virReportSystemError(errno,
256 _("Failed to set close-on-exec flag '%s'"),
257 tokenfile);
258 return NULL;
259 }
260
261 if (virFileLock(fd, false, 0, 1, true) < 0) {
262 virReportSystemError(errno,
263 _("Failed to lock system token '%s'"),
264 tokenfile);
265 return NULL;
266 }
267
268 if (fstat(fd, &st) < 0) {
269 virReportSystemError(errno,
270 _("Failed to check system token '%s'"),
271 tokenfile);
272 return NULL;
273 }
274
275 /* Ok, we're the first one here, so we must populate it */
276 if (st.st_size == 0) {
277 if (!(token = virRandomToken(TOKEN_BYTES))) {
278 return NULL;
279 }
280 if (safewrite(fd, token, TOKEN_STRLEN) != TOKEN_STRLEN) {
281 virReportSystemError(errno,
282 _("Failed to write system token '%s'"),
283 tokenfile);
284 return NULL;
285 }
286 } else {
287 if (virFileReadLimFD(fd, TOKEN_STRLEN, &token) < 0) {
288 virReportSystemError(errno,
289 _("Failed to read system token '%s'"),
290 tokenfile);
291 return NULL;
292 }
293 if (strlen(token) != TOKEN_STRLEN) {
294 virReportSystemError(errno,
295 _("System token in %s was corrupt"),
296 tokenfile);
297 return NULL;
298 }
299 }
300
301 return g_steal_pointer(&token);
302 }
303
304
305 /**
306 * virIdentityGetSystem:
307 *
308 * Returns an identity that represents the system itself.
309 * This is the identity that the process is running as
310 *
311 * Returns a reference to the system identity, or NULL
312 */
virIdentityGetSystem(void)313 virIdentity *virIdentityGetSystem(void)
314 {
315 g_autofree char *username = NULL;
316 g_autofree char *groupname = NULL;
317 unsigned long long startTime;
318 g_autoptr(virIdentity) ret = virIdentityNew();
319 #if WITH_SELINUX
320 char *con;
321 #endif
322 g_autofree char *token = NULL;
323
324 if (virIdentitySetProcessID(ret, getpid()) < 0)
325 return NULL;
326
327 if (virProcessGetStartTime(getpid(), &startTime) < 0)
328 return NULL;
329 if (startTime != 0 &&
330 virIdentitySetProcessTime(ret, startTime) < 0)
331 return NULL;
332
333 if (!(username = virGetUserName(geteuid())))
334 return ret;
335 if (virIdentitySetUserName(ret, username) < 0)
336 return NULL;
337 if (virIdentitySetUNIXUserID(ret, getuid()) < 0)
338 return NULL;
339
340 if (!(groupname = virGetGroupName(getegid())))
341 return ret;
342 if (virIdentitySetGroupName(ret, groupname) < 0)
343 return NULL;
344 if (virIdentitySetUNIXGroupID(ret, getgid()) < 0)
345 return NULL;
346
347 #if WITH_SELINUX
348 if (is_selinux_enabled() > 0) {
349 if (getcon(&con) < 0) {
350 virReportSystemError(errno, "%s",
351 _("Unable to lookup SELinux process context"));
352 return NULL;
353 }
354 if (virIdentitySetSELinuxContext(ret, con) < 0) {
355 freecon(con);
356 return NULL;
357 }
358 freecon(con);
359 }
360 #endif
361
362 if (!(token = virIdentityEnsureSystemToken()))
363 return NULL;
364
365 if (virIdentitySetSystemToken(ret, token) < 0)
366 return NULL;
367
368 return g_steal_pointer(&ret);
369 }
370
371
372 /**
373 * virIdentityIsCurrentElevated:
374 *
375 * Determine if the current identity has elevated privileges.
376 * This indicates that it was invoked on behalf of the
377 * user by a libvirt daemon.
378 *
379 * Returns: true if elevated
380 */
virIdentityIsCurrentElevated(void)381 int virIdentityIsCurrentElevated(void)
382 {
383 g_autoptr(virIdentity) current = virIdentityGetCurrent();
384 const char *currentToken = NULL;
385 int rv;
386
387 if (!current) {
388 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
389 _("No current identity"));
390 return -1;
391 }
392
393 rv = virIdentityGetSystemToken(current, ¤tToken);
394 if (rv <= 0)
395 return rv;
396
397 return STREQ_NULLABLE(currentToken, systemToken);
398 }
399
400 /**
401 * virIdentityNew:
402 *
403 * Creates a new empty identity object. After creating, one or
404 * more identifying attributes should be set on the identity.
405 *
406 * Returns: a new empty identity
407 */
virIdentityNew(void)408 virIdentity *virIdentityNew(void)
409 {
410 return VIR_IDENTITY(g_object_new(VIR_TYPE_IDENTITY, NULL));
411 }
412
413
414 /**
415 * virIdentityNewCopy:
416 *
417 * Creates a new identity object that is a deep copy of an
418 * existing identity.
419 *
420 * Returns: a copy of the source identity
421 */
virIdentityNewCopy(virIdentity * src)422 virIdentity *virIdentityNewCopy(virIdentity *src)
423 {
424 g_autoptr(virIdentity) ident = virIdentityNew();
425
426 if (virTypedParamsCopy(&ident->params, src->params, src->nparams) < 0)
427 return NULL;
428 ident->nparams = src->nparams;
429 ident->maxparams = src->nparams;
430
431 return g_steal_pointer(&ident);
432 }
433
434
virIdentityFinalize(GObject * object)435 static void virIdentityFinalize(GObject *object)
436 {
437 virIdentity *ident = VIR_IDENTITY(object);
438
439 virTypedParamsFree(ident->params, ident->nparams);
440
441 G_OBJECT_CLASS(vir_identity_parent_class)->finalize(object);
442 }
443
444
445 /*
446 * Returns: 0 if not present, 1 if present, -1 on error
447 */
virIdentityGetUserName(virIdentity * ident,const char ** username)448 int virIdentityGetUserName(virIdentity *ident,
449 const char **username)
450 {
451 *username = NULL;
452 return virTypedParamsGetString(ident->params,
453 ident->nparams,
454 VIR_CONNECT_IDENTITY_USER_NAME,
455 username);
456 }
457
458
459 /*
460 * Returns: 0 if not present, 1 if present, -1 on error
461 */
virIdentityGetUNIXUserID(virIdentity * ident,uid_t * uid)462 int virIdentityGetUNIXUserID(virIdentity *ident,
463 uid_t *uid)
464 {
465 unsigned long long val;
466 int rc;
467
468 *uid = -1;
469 rc = virTypedParamsGetULLong(ident->params,
470 ident->nparams,
471 VIR_CONNECT_IDENTITY_UNIX_USER_ID,
472 &val);
473 if (rc <= 0)
474 return rc;
475
476 *uid = (uid_t)val;
477
478 return 1;
479 }
480
481
482 /*
483 * Returns: 0 if not present, 1 if present, -1 on error
484 */
virIdentityGetGroupName(virIdentity * ident,const char ** groupname)485 int virIdentityGetGroupName(virIdentity *ident,
486 const char **groupname)
487 {
488 *groupname = NULL;
489 return virTypedParamsGetString(ident->params,
490 ident->nparams,
491 VIR_CONNECT_IDENTITY_GROUP_NAME,
492 groupname);
493 }
494
495
496 /*
497 * Returns: 0 if not present, 1 if present, -1 on error
498 */
virIdentityGetUNIXGroupID(virIdentity * ident,gid_t * gid)499 int virIdentityGetUNIXGroupID(virIdentity *ident,
500 gid_t *gid)
501 {
502 unsigned long long val;
503 int rc;
504
505 *gid = -1;
506 rc = virTypedParamsGetULLong(ident->params,
507 ident->nparams,
508 VIR_CONNECT_IDENTITY_UNIX_GROUP_ID,
509 &val);
510 if (rc <= 0)
511 return rc;
512
513 *gid = (gid_t)val;
514
515 return 1;
516 }
517
518
519 /*
520 * Returns: 0 if not present, 1 if present, -1 on error
521 */
virIdentityGetProcessID(virIdentity * ident,pid_t * pid)522 int virIdentityGetProcessID(virIdentity *ident,
523 pid_t *pid)
524 {
525 long long val;
526 int rc;
527
528 *pid = 0;
529 rc = virTypedParamsGetLLong(ident->params,
530 ident->nparams,
531 VIR_CONNECT_IDENTITY_PROCESS_ID,
532 &val);
533 if (rc <= 0)
534 return rc;
535
536 *pid = (pid_t)val;
537
538 return 1;
539 }
540
541
542 /*
543 * Returns: 0 if not present, 1 if present, -1 on error
544 */
virIdentityGetProcessTime(virIdentity * ident,unsigned long long * timestamp)545 int virIdentityGetProcessTime(virIdentity *ident,
546 unsigned long long *timestamp)
547 {
548 *timestamp = 0;
549 return virTypedParamsGetULLong(ident->params,
550 ident->nparams,
551 VIR_CONNECT_IDENTITY_PROCESS_TIME,
552 timestamp);
553 }
554
555
556 /*
557 * Returns: 0 if not present, 1 if present, -1 on error
558 */
virIdentityGetSASLUserName(virIdentity * ident,const char ** username)559 int virIdentityGetSASLUserName(virIdentity *ident,
560 const char **username)
561 {
562 *username = NULL;
563 return virTypedParamsGetString(ident->params,
564 ident->nparams,
565 VIR_CONNECT_IDENTITY_SASL_USER_NAME,
566 username);
567 }
568
569
570 /*
571 * Returns: 0 if not present, 1 if present, -1 on error
572 */
virIdentityGetX509DName(virIdentity * ident,const char ** dname)573 int virIdentityGetX509DName(virIdentity *ident,
574 const char **dname)
575 {
576 *dname = NULL;
577 return virTypedParamsGetString(ident->params,
578 ident->nparams,
579 VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME,
580 dname);
581 }
582
583
584 /*
585 * Returns: 0 if not present, 1 if present, -1 on error
586 */
virIdentityGetSELinuxContext(virIdentity * ident,const char ** context)587 int virIdentityGetSELinuxContext(virIdentity *ident,
588 const char **context)
589 {
590 *context = NULL;
591 return virTypedParamsGetString(ident->params,
592 ident->nparams,
593 VIR_CONNECT_IDENTITY_SELINUX_CONTEXT,
594 context);
595 }
596
597
virIdentityGetSystemToken(virIdentity * ident,const char ** token)598 int virIdentityGetSystemToken(virIdentity *ident,
599 const char **token)
600 {
601 *token = NULL;
602 return virTypedParamsGetString(ident->params,
603 ident->nparams,
604 VIR_CONNECT_IDENTITY_SYSTEM_TOKEN,
605 token);
606 }
607
608
virIdentitySetUserName(virIdentity * ident,const char * username)609 int virIdentitySetUserName(virIdentity *ident,
610 const char *username)
611 {
612 if (virTypedParamsGet(ident->params,
613 ident->nparams,
614 VIR_CONNECT_IDENTITY_USER_NAME)) {
615 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
616 _("Identity attribute is already set"));
617 return -1;
618 }
619
620 return virTypedParamsAddString(&ident->params,
621 &ident->nparams,
622 &ident->maxparams,
623 VIR_CONNECT_IDENTITY_USER_NAME,
624 username);
625 }
626
627
virIdentitySetUNIXUserID(virIdentity * ident,uid_t uid)628 int virIdentitySetUNIXUserID(virIdentity *ident,
629 uid_t uid)
630 {
631 if (virTypedParamsGet(ident->params,
632 ident->nparams,
633 VIR_CONNECT_IDENTITY_UNIX_USER_ID)) {
634 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
635 _("Identity attribute is already set"));
636 return -1;
637 }
638
639 return virTypedParamsAddULLong(&ident->params,
640 &ident->nparams,
641 &ident->maxparams,
642 VIR_CONNECT_IDENTITY_UNIX_USER_ID,
643 uid);
644 }
645
646
virIdentitySetGroupName(virIdentity * ident,const char * groupname)647 int virIdentitySetGroupName(virIdentity *ident,
648 const char *groupname)
649 {
650 if (virTypedParamsGet(ident->params,
651 ident->nparams,
652 VIR_CONNECT_IDENTITY_GROUP_NAME)) {
653 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
654 _("Identity attribute is already set"));
655 return -1;
656 }
657
658 return virTypedParamsAddString(&ident->params,
659 &ident->nparams,
660 &ident->maxparams,
661 VIR_CONNECT_IDENTITY_GROUP_NAME,
662 groupname);
663 }
664
665
virIdentitySetUNIXGroupID(virIdentity * ident,gid_t gid)666 int virIdentitySetUNIXGroupID(virIdentity *ident,
667 gid_t gid)
668 {
669 if (virTypedParamsGet(ident->params,
670 ident->nparams,
671 VIR_CONNECT_IDENTITY_UNIX_GROUP_ID)) {
672 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
673 _("Identity attribute is already set"));
674 return -1;
675 }
676
677 return virTypedParamsAddULLong(&ident->params,
678 &ident->nparams,
679 &ident->maxparams,
680 VIR_CONNECT_IDENTITY_UNIX_GROUP_ID,
681 gid);
682 }
683
684
virIdentitySetProcessID(virIdentity * ident,pid_t pid)685 int virIdentitySetProcessID(virIdentity *ident,
686 pid_t pid)
687 {
688 if (virTypedParamsGet(ident->params,
689 ident->nparams,
690 VIR_CONNECT_IDENTITY_PROCESS_ID)) {
691 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
692 _("Identity attribute is already set"));
693 return -1;
694 }
695
696 return virTypedParamsAddLLong(&ident->params,
697 &ident->nparams,
698 &ident->maxparams,
699 VIR_CONNECT_IDENTITY_PROCESS_ID,
700 pid);
701 }
702
703
virIdentitySetProcessTime(virIdentity * ident,unsigned long long timestamp)704 int virIdentitySetProcessTime(virIdentity *ident,
705 unsigned long long timestamp)
706 {
707 if (virTypedParamsGet(ident->params,
708 ident->nparams,
709 VIR_CONNECT_IDENTITY_PROCESS_TIME)) {
710 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
711 _("Identity attribute is already set"));
712 return -1;
713 }
714
715 return virTypedParamsAddULLong(&ident->params,
716 &ident->nparams,
717 &ident->maxparams,
718 VIR_CONNECT_IDENTITY_PROCESS_TIME,
719 timestamp);
720 }
721
722
723
virIdentitySetSASLUserName(virIdentity * ident,const char * username)724 int virIdentitySetSASLUserName(virIdentity *ident,
725 const char *username)
726 {
727 if (virTypedParamsGet(ident->params,
728 ident->nparams,
729 VIR_CONNECT_IDENTITY_SASL_USER_NAME)) {
730 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
731 _("Identity attribute is already set"));
732 return -1;
733 }
734
735 return virTypedParamsAddString(&ident->params,
736 &ident->nparams,
737 &ident->maxparams,
738 VIR_CONNECT_IDENTITY_SASL_USER_NAME,
739 username);
740 }
741
742
virIdentitySetX509DName(virIdentity * ident,const char * dname)743 int virIdentitySetX509DName(virIdentity *ident,
744 const char *dname)
745 {
746 if (virTypedParamsGet(ident->params,
747 ident->nparams,
748 VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME)) {
749 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
750 _("Identity attribute is already set"));
751 return -1;
752 }
753
754 return virTypedParamsAddString(&ident->params,
755 &ident->nparams,
756 &ident->maxparams,
757 VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME,
758 dname);
759 }
760
761
virIdentitySetSELinuxContext(virIdentity * ident,const char * context)762 int virIdentitySetSELinuxContext(virIdentity *ident,
763 const char *context)
764 {
765 if (virTypedParamsGet(ident->params,
766 ident->nparams,
767 VIR_CONNECT_IDENTITY_SELINUX_CONTEXT)) {
768 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
769 _("Identity attribute is already set"));
770 return -1;
771 }
772
773 return virTypedParamsAddString(&ident->params,
774 &ident->nparams,
775 &ident->maxparams,
776 VIR_CONNECT_IDENTITY_SELINUX_CONTEXT,
777 context);
778 }
779
780
virIdentitySetSystemToken(virIdentity * ident,const char * token)781 int virIdentitySetSystemToken(virIdentity *ident,
782 const char *token)
783 {
784 if (virTypedParamsGet(ident->params,
785 ident->nparams,
786 VIR_CONNECT_IDENTITY_SYSTEM_TOKEN)) {
787 virReportError(VIR_ERR_OPERATION_DENIED, "%s",
788 _("Identity attribute is already set"));
789 return -1;
790 }
791
792 return virTypedParamsAddString(&ident->params,
793 &ident->nparams,
794 &ident->maxparams,
795 VIR_CONNECT_IDENTITY_SYSTEM_TOKEN,
796 token);
797 }
798
799
virIdentitySetParameters(virIdentity * ident,virTypedParameterPtr params,int nparams)800 int virIdentitySetParameters(virIdentity *ident,
801 virTypedParameterPtr params,
802 int nparams)
803 {
804 if (virTypedParamsValidate(params, nparams,
805 VIR_CONNECT_IDENTITY_USER_NAME,
806 VIR_TYPED_PARAM_STRING,
807 VIR_CONNECT_IDENTITY_UNIX_USER_ID,
808 VIR_TYPED_PARAM_ULLONG,
809 VIR_CONNECT_IDENTITY_GROUP_NAME,
810 VIR_TYPED_PARAM_STRING,
811 VIR_CONNECT_IDENTITY_UNIX_GROUP_ID,
812 VIR_TYPED_PARAM_ULLONG,
813 VIR_CONNECT_IDENTITY_PROCESS_ID,
814 VIR_TYPED_PARAM_LLONG,
815 VIR_CONNECT_IDENTITY_PROCESS_TIME,
816 VIR_TYPED_PARAM_ULLONG,
817 VIR_CONNECT_IDENTITY_SASL_USER_NAME,
818 VIR_TYPED_PARAM_STRING,
819 VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME,
820 VIR_TYPED_PARAM_STRING,
821 VIR_CONNECT_IDENTITY_SELINUX_CONTEXT,
822 VIR_TYPED_PARAM_STRING,
823 VIR_CONNECT_IDENTITY_SYSTEM_TOKEN,
824 VIR_TYPED_PARAM_STRING,
825 NULL) < 0)
826 return -1;
827
828 virTypedParamsFree(ident->params, ident->nparams);
829 ident->params = NULL;
830 ident->nparams = 0;
831 ident->maxparams = 0;
832 if (virTypedParamsCopy(&ident->params, params, nparams) < 0)
833 return -1;
834 ident->nparams = nparams;
835 ident->maxparams = nparams;
836
837 return 0;
838 }
839
840
virIdentityGetParameters(virIdentity * ident,virTypedParameterPtr * params,int * nparams)841 int virIdentityGetParameters(virIdentity *ident,
842 virTypedParameterPtr *params,
843 int *nparams)
844 {
845 *params = NULL;
846 *nparams = 0;
847
848 if (virTypedParamsCopy(params, ident->params, ident->nparams) < 0)
849 return -1;
850
851 *nparams = ident->nparams;
852
853 return 0;
854 }
855