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, &currentToken);
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