]> xenbits.xensource.com Git - libvirt.git/commitdiff
admin: Introduce virAdmClientGetInfo API
authorErik Skultety <eskultet@redhat.com>
Fri, 22 Apr 2016 11:05:42 +0000 (13:05 +0200)
committerErik Skultety <eskultet@redhat.com>
Tue, 3 May 2016 13:52:50 +0000 (15:52 +0200)
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>
daemon/admin.c
daemon/admin_server.c
daemon/admin_server.h
include/libvirt/libvirt-admin.h
src/admin/admin_protocol.x
src/admin/admin_remote.c
src/admin_protocol-structs
src/libvirt-admin.c
src/libvirt_admin_private.syms
src/libvirt_admin_public.syms

index fcbdee5fa3e6229e1d966ce4b77552741ca70252..3de09ca900ab9381aad2ece10a240943fc91fd5a 100644 (file)
@@ -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, &params, &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"
index 9ea11645711e001981dab57c05edf61ec4219fe1..2fc467539cd8260f59a10f0de7bf308c18aa30bf 100644 (file)
@@ -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;
+}
index a593251d7ac6aaed9e000bb4f53d5964a1413d83..95c76b9e0f39640d76a11c8e6a50f7c29d6495fb 100644 (file)
@@ -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__ */
index 5c30aae1259e0132d6229bba93f803dcf91b9a8a..0a1ea61e33e04ff18be10d0ab286336ec56a689e 100644 (file)
@@ -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
index da21db8d39520b623e3df84149e31e3828ed8fad..67bdbf30eecba30d41bc87561570986f23ca518f 100644 (file)
@@ -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
 };
index b833ea4e159fdfc00f3013ff92138d1407863d42..40fcddb5fb910af2f4e576808d261c58264a1ad5 100644 (file)
@@ -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;
+}
index dc2220e3ef88926992ab31d7336159eaf4520da9..ea9adf6c3c16c8ee22102ef9f7fb071cbcdf62a7 100644 (file)
@@ -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,
 };
index d9cdb811f1ea9a9a5bfeed28e4e31a0106bd5eb9..a94f5dd1d30312a315b8bfaa6ca65828f35c8b22 100644 (file)
@@ -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;
+}
index 3d7ecbcb717eba70edddb3feaf4441792312f70a..affe8c113351e623c58ef07cdfe7ffba03b0bb5f 100644 (file)
@@ -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;
index 066ae0ce98d70ab7405e08198c7cd11f83e52bae..27e4a1deedcb9b4b572120699ed98775bbdeda02 100644 (file)
@@ -33,4 +33,5 @@ LIBVIRT_ADMIN_1.3.0 {
         virAdmConnectLookupServer;
         virAdmServerSetThreadPoolParameters;
         virAdmServerListClients;
+        virAdmClientGetInfo;
 };