mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
admin: Introduce virAdmClientGetInfo API
Expose a public API to retrieve some identity and connection information about a client connected to the specified server on daemon. The identity info retrieved is mostly connection transport dependent, i.e. there won't be any socket address returned for a local (UNIX socket) connection, while on the other hand, when connected through TLS or unencrypted TCP, obviously no UNIX process identification will be present in the returned data. All supported values that can be returned in typed params are exposed and documented in include/libvirt/libvirt-admin.h Signed-off-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
parent
8420a53edf
commit
4a0e910825
@ -236,4 +236,63 @@ adminDispatchServerSetThreadpoolParameters(virNetServerPtr server ATTRIBUTE_UNUS
|
||||
virObjectUnref(srv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
adminDispatchClientGetInfo(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||
virNetServerClientPtr client,
|
||||
virNetMessagePtr msg ATTRIBUTE_UNUSED,
|
||||
virNetMessageErrorPtr rerr,
|
||||
struct admin_client_get_info_args *args,
|
||||
struct admin_client_get_info_ret *ret)
|
||||
{
|
||||
int rv = -1;
|
||||
virNetServerPtr srv = NULL;
|
||||
virNetServerClientPtr clnt = NULL;
|
||||
virTypedParameterPtr params = NULL;
|
||||
int nparams = 0;
|
||||
struct daemonAdmClientPrivate *priv =
|
||||
virNetServerClientGetPrivateData(client);
|
||||
|
||||
if (!(srv = virNetDaemonGetServer(priv->dmn, args->clnt.srv.name))) {
|
||||
virReportError(VIR_ERR_NO_SERVER,
|
||||
_("no server with matching name '%s' found"),
|
||||
args->clnt.srv.name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(clnt = virNetServerGetClient(srv, args->clnt.id))) {
|
||||
virReportError(VIR_ERR_NO_CLIENT,
|
||||
_("no client with matching id '%lu' found"),
|
||||
args->clnt.id);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (adminClientGetInfo(clnt, ¶ms, &nparams, args->flags) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (nparams > ADMIN_CLIENT_INFO_PARAMETERS_MAX) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Number of client info parameters %d exceeds max "
|
||||
"allowed limit: %d"), nparams,
|
||||
ADMIN_CLIENT_INFO_PARAMETERS_MAX);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virTypedParamsSerialize(params, nparams,
|
||||
(virTypedParameterRemotePtr *) &ret->params.params_val,
|
||||
&ret->params.params_len,
|
||||
VIR_TYPED_PARAM_STRING_OKAY) < 0)
|
||||
goto cleanup;
|
||||
|
||||
rv = 0;
|
||||
|
||||
cleanup:
|
||||
if (rv < 0)
|
||||
virNetMessageSaveError(rerr);
|
||||
|
||||
virTypedParamsFree(params, nparams);
|
||||
virObjectUnref(clnt);
|
||||
virObjectUnref(srv);
|
||||
return rv;
|
||||
}
|
||||
#include "admin_dispatch.h"
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "datatypes.h"
|
||||
#include "viralloc.h"
|
||||
#include "virerror.h"
|
||||
#include "viridentity.h"
|
||||
#include "virlog.h"
|
||||
#include "virnetdaemon.h"
|
||||
#include "virnetserver.h"
|
||||
@ -211,3 +212,94 @@ adminServerLookupClient(virNetServerPtr srv,
|
||||
|
||||
return virNetServerGetClient(srv, id);
|
||||
}
|
||||
|
||||
int
|
||||
adminClientGetInfo(virNetServerClientPtr client,
|
||||
virTypedParameterPtr *params,
|
||||
int *nparams,
|
||||
unsigned int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
int maxparams = 0;
|
||||
bool readonly;
|
||||
const char *sock_addr = NULL;
|
||||
const char *attr = NULL;
|
||||
virTypedParameterPtr tmpparams = NULL;
|
||||
virIdentityPtr identity = NULL;
|
||||
|
||||
virCheckFlags(0, -1);
|
||||
|
||||
if (virNetServerClientGetInfo(client, &readonly,
|
||||
&sock_addr, &identity) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virTypedParamsAddBoolean(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_READONLY,
|
||||
readonly) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!virNetServerClientIsLocal(client)) {
|
||||
if (virTypedParamsAddString(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_SOCKET_ADDR,
|
||||
sock_addr) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virIdentityGetSASLUserName(identity, &attr) < 0 ||
|
||||
(attr &&
|
||||
virTypedParamsAddString(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_SASL_USER_NAME,
|
||||
attr) < 0))
|
||||
goto cleanup;
|
||||
|
||||
if (virIdentityGetX509DName(identity, &attr) < 0 ||
|
||||
(attr &&
|
||||
virTypedParamsAddString(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_X509_DISTINGUISHED_NAME,
|
||||
attr) < 0))
|
||||
goto cleanup;
|
||||
} else {
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
if (virIdentityGetUNIXUserID(identity, &uid) < 0 ||
|
||||
virTypedParamsAddInt(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_UNIX_USER_ID, uid) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virIdentityGetUNIXUserName(identity, &attr) < 0 ||
|
||||
virTypedParamsAddString(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_UNIX_USER_NAME,
|
||||
attr) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virIdentityGetUNIXGroupID(identity, &gid) < 0 ||
|
||||
virTypedParamsAddInt(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_UNIX_GROUP_ID, gid) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virIdentityGetUNIXGroupName(identity, &attr) < 0 ||
|
||||
virTypedParamsAddString(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_UNIX_GROUP_NAME,
|
||||
attr) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virIdentityGetUNIXProcessID(identity, &pid) < 0 ||
|
||||
virTypedParamsAddInt(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_UNIX_PROCESS_ID, pid) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virIdentityGetSELinuxContext(identity, &attr) < 0 ||
|
||||
(attr &&
|
||||
virTypedParamsAddString(&tmpparams, nparams, &maxparams,
|
||||
VIR_CLIENT_INFO_SELINUX_CONTEXT, attr) < 0))
|
||||
goto cleanup;
|
||||
|
||||
*params = tmpparams;
|
||||
tmpparams = NULL;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virObjectUnref(identity);
|
||||
return ret;
|
||||
}
|
||||
|
@ -54,4 +54,9 @@ virNetServerClientPtr adminServerLookupClient(virNetServerPtr srv,
|
||||
unsigned long long id,
|
||||
unsigned int flags);
|
||||
|
||||
int adminClientGetInfo(virNetServerClientPtr client,
|
||||
virTypedParameterPtr *params,
|
||||
int *nparams,
|
||||
unsigned int flags);
|
||||
|
||||
#endif /* __LIBVIRTD_ADMIN_SERVER_H__ */
|
||||
|
@ -344,6 +344,11 @@ virAdmServerLookupClient(virAdmServerPtr srv,
|
||||
|
||||
# define VIR_CLIENT_INFO_SELINUX_CONTEXT "selinux_context"
|
||||
|
||||
int virAdmClientGetInfo(virAdmClientPtr client,
|
||||
virTypedParameterPtr *params,
|
||||
int *nparams,
|
||||
unsigned int flags);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
@ -42,6 +42,9 @@ const ADMIN_SERVER_THREADPOOL_PARAMETERS_MAX = 32;
|
||||
/* Upper limit on list of clients */
|
||||
const ADMIN_CLIENT_LIST_MAX = 16384;
|
||||
|
||||
/* Upper limit on number of client info parameters */
|
||||
const ADMIN_CLIENT_INFO_PARAMETERS_MAX = 64;
|
||||
|
||||
/* A long string, which may NOT be NULL. */
|
||||
typedef string admin_nonnull_string<ADMIN_STRING_MAX>;
|
||||
|
||||
@ -148,6 +151,15 @@ struct admin_server_lookup_client_ret {
|
||||
admin_nonnull_client clnt;
|
||||
};
|
||||
|
||||
struct admin_client_get_info_args {
|
||||
admin_nonnull_client clnt;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct admin_client_get_info_ret { /* insert@1 */
|
||||
admin_typed_param params<ADMIN_CLIENT_INFO_PARAMETERS_MAX>;
|
||||
};
|
||||
|
||||
/* Define the program number, protocol version and procedure numbers here. */
|
||||
const ADMIN_PROGRAM = 0x06900690;
|
||||
const ADMIN_PROTOCOL_VERSION = 1;
|
||||
@ -213,5 +225,10 @@ enum admin_procedure {
|
||||
/**
|
||||
* @generate: both
|
||||
*/
|
||||
ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9
|
||||
ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9,
|
||||
|
||||
/**
|
||||
* @generate: none
|
||||
*/
|
||||
ADMIN_PROC_CLIENT_GET_INFO = 10
|
||||
};
|
||||
|
@ -67,6 +67,16 @@ make_nonnull_server(admin_nonnull_server *srv_dst, virAdmServerPtr srv_src)
|
||||
srv_dst->name = srv_src->name;
|
||||
}
|
||||
|
||||
static void
|
||||
make_nonnull_client(admin_nonnull_client *client_dst,
|
||||
virAdmClientPtr client_src)
|
||||
{
|
||||
client_dst->id = client_src->id;
|
||||
client_dst->transport = client_src->transport;
|
||||
client_dst->timestamp = client_src->timestamp;
|
||||
make_nonnull_server(&client_dst->srv, client_src->srv);
|
||||
}
|
||||
|
||||
static int
|
||||
callFull(virAdmConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
remoteAdminPrivPtr priv,
|
||||
@ -308,3 +318,40 @@ remoteAdminServerSetThreadPoolParameters(virAdmServerPtr srv,
|
||||
virObjectUnlock(priv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
remoteAdminClientGetInfo(virAdmClientPtr client,
|
||||
virTypedParameterPtr *params,
|
||||
int *nparams,
|
||||
unsigned int flags)
|
||||
{
|
||||
int rv = -1;
|
||||
remoteAdminPrivPtr priv = client->srv->conn->privateData;
|
||||
admin_client_get_info_args args;
|
||||
admin_client_get_info_ret ret;
|
||||
|
||||
args.flags = flags;
|
||||
make_nonnull_client(&args.clnt, client);
|
||||
|
||||
memset(&ret, 0, sizeof(ret));
|
||||
virObjectLock(priv);
|
||||
|
||||
if (call(client->srv->conn, 0, ADMIN_PROC_CLIENT_GET_INFO,
|
||||
(xdrproc_t)xdr_admin_client_get_info_args, (char *) &args,
|
||||
(xdrproc_t)xdr_admin_client_get_info_ret, (char *) &ret) == -1)
|
||||
goto cleanup;
|
||||
|
||||
if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
|
||||
ret.params.params_len,
|
||||
ADMIN_CLIENT_INFO_PARAMETERS_MAX,
|
||||
params,
|
||||
nparams) < 0)
|
||||
goto cleanup;
|
||||
|
||||
rv = 0;
|
||||
xdr_free((xdrproc_t)xdr_admin_client_get_info_ret, (char *) &ret);
|
||||
|
||||
cleanup:
|
||||
virObjectUnlock(priv);
|
||||
return rv;
|
||||
}
|
||||
|
@ -95,6 +95,16 @@ struct admin_server_lookup_client_args {
|
||||
struct admin_server_lookup_client_ret {
|
||||
admin_nonnull_client clnt;
|
||||
};
|
||||
struct admin_client_get_info_args {
|
||||
admin_nonnull_client clnt;
|
||||
u_int flags;
|
||||
};
|
||||
struct admin_client_get_info_ret {
|
||||
struct {
|
||||
u_int params_len;
|
||||
admin_typed_param * params_val;
|
||||
} params;
|
||||
};
|
||||
enum admin_procedure {
|
||||
ADMIN_PROC_CONNECT_OPEN = 1,
|
||||
ADMIN_PROC_CONNECT_CLOSE = 2,
|
||||
@ -105,4 +115,5 @@ enum admin_procedure {
|
||||
ADMIN_PROC_SERVER_SET_THREADPOOL_PARAMETERS = 7,
|
||||
ADMIN_PROC_SERVER_LIST_CLIENTS = 8,
|
||||
ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9,
|
||||
ADMIN_PROC_CLIENT_GET_INFO = 10,
|
||||
};
|
||||
|
@ -925,3 +925,53 @@ virAdmServerLookupClient(virAdmServerPtr srv,
|
||||
virDispatchError(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* virAdmClientGetInfo:
|
||||
* @client: a client object reference
|
||||
* @params: pointer to a list of typed parameters which will be allocated
|
||||
* to store all returned parameters
|
||||
* @nparams: pointer which will hold the number of params returned in @params
|
||||
* @flags: extra flags; not used yet, so callers should always pass 0
|
||||
*
|
||||
* Extract identity information about a client. Attributes returned in @params
|
||||
* are mostly transport-dependent, i.e. some attributes including client
|
||||
* process's pid, gid, uid, or remote side's socket address are only available
|
||||
* for a specific connection type - local vs remote.
|
||||
* Other identity attributes like authentication method used
|
||||
* (if authentication is enabled on the remote host), SELinux context, or
|
||||
* an indicator whether client is connected via a read-only connection are
|
||||
* independent of the connection transport.
|
||||
*
|
||||
* Note that the read-only connection indicator returns false for TCP/TLS
|
||||
* clients because libvirt treats such connections as read-write by default,
|
||||
* even though a TCP client is able to restrict access to certain APIs for
|
||||
* itself.
|
||||
*
|
||||
* Returns 0 if the information has been successfully retrieved or -1 in case
|
||||
* of an error.
|
||||
*/
|
||||
int
|
||||
virAdmClientGetInfo(virAdmClientPtr client,
|
||||
virTypedParameterPtr *params,
|
||||
int *nparams,
|
||||
unsigned int flags)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
VIR_DEBUG("client=%p, params=%p, nparams=%p, flags=%x",
|
||||
client, params, nparams, flags);
|
||||
|
||||
virResetLastError();
|
||||
virCheckAdmClientReturn(client, -1);
|
||||
virCheckNonNullArgGoto(params, error);
|
||||
virCheckFlagsGoto(0, error);
|
||||
|
||||
if ((ret = remoteAdminClientGetInfo(client, params, nparams, flags)) < 0)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
virDispatchError(NULL);
|
||||
return -1;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#
|
||||
|
||||
# admin/admin_protocol.x
|
||||
xdr_admin_client_get_info_args;
|
||||
xdr_admin_client_get_info_ret;
|
||||
xdr_admin_connect_get_lib_version_ret;
|
||||
xdr_admin_connect_list_servers_args;
|
||||
xdr_admin_connect_list_servers_ret;
|
||||
|
@ -33,4 +33,5 @@ LIBVIRT_ADMIN_1.3.0 {
|
||||
virAdmConnectLookupServer;
|
||||
virAdmServerSetThreadPoolParameters;
|
||||
virAdmServerListClients;
|
||||
virAdmClientGetInfo;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user