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"
#include "datatypes.h"
#include "viralloc.h"
#include "virerror.h"
+#include "viridentity.h"
#include "virlog.h"
#include "virnetdaemon.h"
#include "virnetserver.h"
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;
+}
unsigned long long id,
unsigned int flags);
+int adminClientGetInfo(virNetServerClientPtr client,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
#endif /* __LIBVIRTD_ADMIN_SERVER_H__ */
# define VIR_CLIENT_INFO_SELINUX_CONTEXT "selinux_context"
+int virAdmClientGetInfo(virAdmClientPtr client,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
# ifdef __cplusplus
}
# endif
/* 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>;
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;
/**
* @generate: both
*/
- ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9
+ ADMIN_PROC_SERVER_LOOKUP_CLIENT = 9,
+
+ /**
+ * @generate: none
+ */
+ ADMIN_PROC_CLIENT_GET_INFO = 10
};
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,
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;
+}
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,
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,
};
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;
+}
#
# 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;
virAdmConnectLookupServer;
virAdmServerSetThreadPoolParameters;
virAdmServerListClients;
+ virAdmClientGetInfo;
};