mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-31 10:23:09 +00:00
c8238579fb
Historically, we declared pointer type to our types: typedef struct _virXXX virXXX; typedef virXXX *virXXXPtr; But usefulness of such declaration is questionable, at best. Unfortunately, we can't drop every such declaration - we have to carry some over, because they are part of public API (e.g. virDomainPtr). But for internal types - we can do drop them and use what every other C project uses 'virXXX *'. This change was generated by a very ugly shell script that generated sed script which was then called over each file in the repository. For the shell script refer to the cover letter: https://listman.redhat.com/archives/libvir-list/2021-March/msg00537.html Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
610 lines
17 KiB
C
610 lines
17 KiB
C
/*
|
|
* viridentity.c: helper APIs for managing user identities
|
|
*
|
|
* Copyright (C) 2012-2013 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <unistd.h>
|
|
#if WITH_SELINUX
|
|
# include <selinux/selinux.h>
|
|
#endif
|
|
|
|
#include "internal.h"
|
|
#include "viralloc.h"
|
|
#include "virerror.h"
|
|
#include "viridentity.h"
|
|
#include "virlog.h"
|
|
#include "virobject.h"
|
|
#include "virthread.h"
|
|
#include "virutil.h"
|
|
#include "virstring.h"
|
|
#include "virprocess.h"
|
|
#include "virtypedparam.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_IDENTITY
|
|
|
|
VIR_LOG_INIT("util.identity");
|
|
|
|
struct _virIdentity {
|
|
GObject parent;
|
|
|
|
int nparams;
|
|
int maxparams;
|
|
virTypedParameterPtr params;
|
|
};
|
|
|
|
G_DEFINE_TYPE(virIdentity, vir_identity, G_TYPE_OBJECT)
|
|
|
|
static virThreadLocal virIdentityCurrent;
|
|
|
|
static void virIdentityFinalize(GObject *obj);
|
|
|
|
static void virIdentityCurrentCleanup(void *ident)
|
|
{
|
|
if (ident)
|
|
g_object_unref(ident);
|
|
}
|
|
|
|
static int virIdentityOnceInit(void)
|
|
{
|
|
if (virThreadLocalInit(&virIdentityCurrent,
|
|
virIdentityCurrentCleanup) < 0) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
_("Cannot initialize thread local for current identity"));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
VIR_ONCE_GLOBAL_INIT(virIdentity);
|
|
|
|
static void vir_identity_init(virIdentity *ident G_GNUC_UNUSED)
|
|
{
|
|
}
|
|
|
|
static void vir_identity_class_init(virIdentityClass *klass)
|
|
{
|
|
GObjectClass *obj = G_OBJECT_CLASS(klass);
|
|
|
|
obj->finalize = virIdentityFinalize;
|
|
}
|
|
|
|
/**
|
|
* virIdentityGetCurrent:
|
|
*
|
|
* Get the current identity associated with this thread. The
|
|
* caller will own a reference to the returned identity, but
|
|
* must not modify the object in any way, other than to
|
|
* release the reference when done with g_object_unref
|
|
*
|
|
* Returns: a reference to the current identity, or NULL
|
|
*/
|
|
virIdentity *virIdentityGetCurrent(void)
|
|
{
|
|
virIdentity *ident;
|
|
|
|
if (virIdentityInitialize() < 0)
|
|
return NULL;
|
|
|
|
ident = virThreadLocalGet(&virIdentityCurrent);
|
|
if (ident)
|
|
g_object_ref(ident);
|
|
return ident;
|
|
}
|
|
|
|
|
|
/**
|
|
* virIdentitySetCurrent:
|
|
*
|
|
* Set the new identity to be associated with this thread.
|
|
* The caller should not modify the passed identity after
|
|
* it has been set, other than to release its own reference.
|
|
*
|
|
* Returns 0 on success, or -1 on error
|
|
*/
|
|
int virIdentitySetCurrent(virIdentity *ident)
|
|
{
|
|
g_autoptr(virIdentity) old = NULL;
|
|
|
|
if (virIdentityInitialize() < 0)
|
|
return -1;
|
|
|
|
old = virThreadLocalGet(&virIdentityCurrent);
|
|
|
|
if (virThreadLocalSet(&virIdentityCurrent,
|
|
ident ? g_object_ref(ident) : NULL) < 0) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
_("Unable to set thread local identity"));
|
|
if (ident)
|
|
g_object_unref(ident);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* virIdentityGetSystem:
|
|
*
|
|
* Returns an identity that represents the system itself.
|
|
* This is the identity that the process is running as
|
|
*
|
|
* Returns a reference to the system identity, or NULL
|
|
*/
|
|
virIdentity *virIdentityGetSystem(void)
|
|
{
|
|
g_autofree char *username = NULL;
|
|
g_autofree char *groupname = NULL;
|
|
unsigned long long startTime;
|
|
g_autoptr(virIdentity) ret = NULL;
|
|
#if WITH_SELINUX
|
|
char *con;
|
|
#endif
|
|
|
|
if (!(ret = virIdentityNew()))
|
|
return NULL;
|
|
|
|
if (virIdentitySetProcessID(ret, getpid()) < 0)
|
|
return NULL;
|
|
|
|
if (virProcessGetStartTime(getpid(), &startTime) < 0)
|
|
return NULL;
|
|
if (startTime != 0 &&
|
|
virIdentitySetProcessTime(ret, startTime) < 0)
|
|
return NULL;
|
|
|
|
if (!(username = virGetUserName(geteuid())))
|
|
return ret;
|
|
if (virIdentitySetUserName(ret, username) < 0)
|
|
return NULL;
|
|
if (virIdentitySetUNIXUserID(ret, getuid()) < 0)
|
|
return NULL;
|
|
|
|
if (!(groupname = virGetGroupName(getegid())))
|
|
return ret;
|
|
if (virIdentitySetGroupName(ret, groupname) < 0)
|
|
return NULL;
|
|
if (virIdentitySetUNIXGroupID(ret, getgid()) < 0)
|
|
return NULL;
|
|
|
|
#if WITH_SELINUX
|
|
if (is_selinux_enabled() > 0) {
|
|
if (getcon(&con) < 0) {
|
|
virReportSystemError(errno, "%s",
|
|
_("Unable to lookup SELinux process context"));
|
|
return NULL;
|
|
}
|
|
if (virIdentitySetSELinuxContext(ret, con) < 0) {
|
|
freecon(con);
|
|
return NULL;
|
|
}
|
|
freecon(con);
|
|
}
|
|
#endif
|
|
|
|
return g_steal_pointer(&ret);
|
|
}
|
|
|
|
|
|
/**
|
|
* virIdentityNew:
|
|
*
|
|
* Creates a new empty identity object. After creating, one or
|
|
* more identifying attributes should be set on the identity.
|
|
*
|
|
* Returns: a new empty identity
|
|
*/
|
|
virIdentity *virIdentityNew(void)
|
|
{
|
|
return VIR_IDENTITY(g_object_new(VIR_TYPE_IDENTITY, NULL));
|
|
}
|
|
|
|
|
|
static void virIdentityFinalize(GObject *object)
|
|
{
|
|
virIdentity *ident = VIR_IDENTITY(object);
|
|
|
|
virTypedParamsFree(ident->params, ident->nparams);
|
|
|
|
G_OBJECT_CLASS(vir_identity_parent_class)->finalize(object);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetUserName(virIdentity *ident,
|
|
const char **username)
|
|
{
|
|
*username = NULL;
|
|
return virTypedParamsGetString(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_USER_NAME,
|
|
username);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetUNIXUserID(virIdentity *ident,
|
|
uid_t *uid)
|
|
{
|
|
unsigned long long val;
|
|
int rc;
|
|
|
|
*uid = -1;
|
|
rc = virTypedParamsGetULLong(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_UNIX_USER_ID,
|
|
&val);
|
|
if (rc <= 0)
|
|
return rc;
|
|
|
|
*uid = (uid_t)val;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetGroupName(virIdentity *ident,
|
|
const char **groupname)
|
|
{
|
|
*groupname = NULL;
|
|
return virTypedParamsGetString(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_GROUP_NAME,
|
|
groupname);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetUNIXGroupID(virIdentity *ident,
|
|
gid_t *gid)
|
|
{
|
|
unsigned long long val;
|
|
int rc;
|
|
|
|
*gid = -1;
|
|
rc = virTypedParamsGetULLong(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_UNIX_GROUP_ID,
|
|
&val);
|
|
if (rc <= 0)
|
|
return rc;
|
|
|
|
*gid = (gid_t)val;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetProcessID(virIdentity *ident,
|
|
pid_t *pid)
|
|
{
|
|
long long val;
|
|
int rc;
|
|
|
|
*pid = 0;
|
|
rc = virTypedParamsGetLLong(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_PROCESS_ID,
|
|
&val);
|
|
if (rc <= 0)
|
|
return rc;
|
|
|
|
*pid = (pid_t)val;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetProcessTime(virIdentity *ident,
|
|
unsigned long long *timestamp)
|
|
{
|
|
*timestamp = 0;
|
|
return virTypedParamsGetULLong(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_PROCESS_TIME,
|
|
timestamp);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetSASLUserName(virIdentity *ident,
|
|
const char **username)
|
|
{
|
|
*username = NULL;
|
|
return virTypedParamsGetString(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_SASL_USER_NAME,
|
|
username);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetX509DName(virIdentity *ident,
|
|
const char **dname)
|
|
{
|
|
*dname = NULL;
|
|
return virTypedParamsGetString(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME,
|
|
dname);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns: 0 if not present, 1 if present, -1 on error
|
|
*/
|
|
int virIdentityGetSELinuxContext(virIdentity *ident,
|
|
const char **context)
|
|
{
|
|
*context = NULL;
|
|
return virTypedParamsGetString(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_SELINUX_CONTEXT,
|
|
context);
|
|
}
|
|
|
|
|
|
int virIdentitySetUserName(virIdentity *ident,
|
|
const char *username)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_USER_NAME)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddString(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_USER_NAME,
|
|
username);
|
|
}
|
|
|
|
|
|
int virIdentitySetUNIXUserID(virIdentity *ident,
|
|
uid_t uid)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_UNIX_USER_ID)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddULLong(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_UNIX_USER_ID,
|
|
uid);
|
|
}
|
|
|
|
|
|
int virIdentitySetGroupName(virIdentity *ident,
|
|
const char *groupname)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_GROUP_NAME)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddString(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_GROUP_NAME,
|
|
groupname);
|
|
}
|
|
|
|
|
|
int virIdentitySetUNIXGroupID(virIdentity *ident,
|
|
gid_t gid)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_UNIX_GROUP_ID)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddULLong(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_UNIX_GROUP_ID,
|
|
gid);
|
|
}
|
|
|
|
|
|
int virIdentitySetProcessID(virIdentity *ident,
|
|
pid_t pid)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_PROCESS_ID)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddLLong(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_PROCESS_ID,
|
|
pid);
|
|
}
|
|
|
|
|
|
int virIdentitySetProcessTime(virIdentity *ident,
|
|
unsigned long long timestamp)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_PROCESS_TIME)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddULLong(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_PROCESS_TIME,
|
|
timestamp);
|
|
}
|
|
|
|
|
|
|
|
int virIdentitySetSASLUserName(virIdentity *ident,
|
|
const char *username)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_SASL_USER_NAME)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddString(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_SASL_USER_NAME,
|
|
username);
|
|
}
|
|
|
|
|
|
int virIdentitySetX509DName(virIdentity *ident,
|
|
const char *dname)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddString(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME,
|
|
dname);
|
|
}
|
|
|
|
|
|
int virIdentitySetSELinuxContext(virIdentity *ident,
|
|
const char *context)
|
|
{
|
|
if (virTypedParamsGet(ident->params,
|
|
ident->nparams,
|
|
VIR_CONNECT_IDENTITY_SELINUX_CONTEXT)) {
|
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
|
_("Identity attribute is already set"));
|
|
return -1;
|
|
}
|
|
|
|
return virTypedParamsAddString(&ident->params,
|
|
&ident->nparams,
|
|
&ident->maxparams,
|
|
VIR_CONNECT_IDENTITY_SELINUX_CONTEXT,
|
|
context);
|
|
}
|
|
|
|
|
|
int virIdentitySetParameters(virIdentity *ident,
|
|
virTypedParameterPtr params,
|
|
int nparams)
|
|
{
|
|
if (virTypedParamsValidate(params, nparams,
|
|
VIR_CONNECT_IDENTITY_USER_NAME,
|
|
VIR_TYPED_PARAM_STRING,
|
|
VIR_CONNECT_IDENTITY_UNIX_USER_ID,
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
VIR_CONNECT_IDENTITY_GROUP_NAME,
|
|
VIR_TYPED_PARAM_STRING,
|
|
VIR_CONNECT_IDENTITY_UNIX_GROUP_ID,
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
VIR_CONNECT_IDENTITY_PROCESS_ID,
|
|
VIR_TYPED_PARAM_LLONG,
|
|
VIR_CONNECT_IDENTITY_PROCESS_TIME,
|
|
VIR_TYPED_PARAM_ULLONG,
|
|
VIR_CONNECT_IDENTITY_SASL_USER_NAME,
|
|
VIR_TYPED_PARAM_STRING,
|
|
VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME,
|
|
VIR_TYPED_PARAM_STRING,
|
|
VIR_CONNECT_IDENTITY_SELINUX_CONTEXT,
|
|
VIR_TYPED_PARAM_STRING,
|
|
NULL) < 0)
|
|
return -1;
|
|
|
|
virTypedParamsFree(ident->params, ident->nparams);
|
|
ident->params = NULL;
|
|
ident->nparams = 0;
|
|
ident->maxparams = 0;
|
|
if (virTypedParamsCopy(&ident->params, params, nparams) < 0)
|
|
return -1;
|
|
ident->nparams = nparams;
|
|
ident->maxparams = nparams;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int virIdentityGetParameters(virIdentity *ident,
|
|
virTypedParameterPtr *params,
|
|
int *nparams)
|
|
{
|
|
*params = NULL;
|
|
*nparams = 0;
|
|
|
|
if (virTypedParamsCopy(params, ident->params, ident->nparams) < 0)
|
|
return -1;
|
|
|
|
*nparams = ident->nparams;
|
|
|
|
return 0;
|
|
}
|