[libvirt] [PATCH 3/7] virnetsocket: Provide socket address format in a more standard form

Erik Skultety eskultet at redhat.com
Fri Apr 29 13:45:55 UTC 2016


Our socket address format is in a rather non-standard format and that is
because sasl library requires the IP address and service to be delimited by a
semicolon. The string form is a completely internal matter, however once the
admin interfaces to retrieve client identity information are merged, we should
return the socket address string in a common format, e.g. format defined by
URI rfc-3986, i.e. the IP address and service are delimited by a colon and
in case of an IPv6 address, square brackets are added:

Examples:
    127.0.0.1:1234
    [::1]:1234

This patch changes our default format to the one described above, while adding
separate methods to request the non-standard SASL format using semicolon as a
delimiter.

Signed-off-by: Erik Skultety <eskultet at redhat.com>
---
 daemon/remote.c              | 13 +++++++++++--
 src/remote/remote_driver.c   |  7 +++++++
 src/rpc/virnetclient.c       | 10 ++++++++++
 src/rpc/virnetclient.h       |  2 ++
 src/rpc/virnetserverclient.c | 13 +++++++++++++
 src/rpc/virnetserverclient.h |  2 ++
 src/rpc/virnetsocket.c       | 17 +++++++++++++++--
 src/rpc/virnetsocket.h       |  2 ++
 src/util/virsocketaddr.c     | 24 ++++++++++++++++++++----
 tests/virnetsockettest.c     | 10 +++++-----
 10 files changed, 87 insertions(+), 13 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index fde029d..b2a420b 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -2937,6 +2937,8 @@ remoteDispatchAuthSaslInit(virNetServerPtr server ATTRIBUTE_UNUSED,
     virNetSASLSessionPtr sasl = NULL;
     struct daemonClientPrivate *priv =
         virNetServerClientGetPrivateData(client);
+    char *localAddr = NULL;
+    char *remoteAddr = NULL;
 
     virMutexLock(&priv->lock);
 
@@ -2947,10 +2949,17 @@ remoteDispatchAuthSaslInit(virNetServerPtr server ATTRIBUTE_UNUSED,
         goto authfail;
     }
 
+    localAddr = virNetServerClientLocalAddrFormatSASL(client);
+    remoteAddr = virNetServerClientRemoteAddrFormatSASL(client);
+
     sasl = virNetSASLSessionNewServer(saslCtxt,
                                       "libvirt",
-                                      virNetServerClientLocalAddrString(client),
-                                      virNetServerClientRemoteAddrString(client));
+                                      localAddr,
+                                      remoteAddr);
+
+    VIR_FREE(localAddr);
+    VIR_FREE(remoteAddr);
+
     if (!sasl)
         goto authfail;
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 6bed2c5..e3cf5fb 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -3684,6 +3684,8 @@ remoteAuthSASL(virConnectPtr conn, struct private_data *priv,
     sasl_callback_t *saslcb = NULL;
     int ret = -1;
     const char *mechlist;
+    char *localAddr = NULL;
+    char *remoteAddr = NULL;
     virNetSASLContextPtr saslCtxt;
     virNetSASLSessionPtr sasl = NULL;
     struct remoteAuthInteractState state;
@@ -3702,6 +3704,9 @@ remoteAuthSASL(virConnectPtr conn, struct private_data *priv,
         saslcb = NULL;
     }
 
+    localAddr = virNetClientLocalAddrFormatSASL(priv->client);
+    remoteAddr = virNetClientRemoteAddrFormatSASL(priv->client);
+
     /* Setup a handle for being a client */
     if (!(sasl = virNetSASLSessionNewClient(saslCtxt,
                                             "libvirt",
@@ -3889,6 +3894,8 @@ remoteAuthSASL(virConnectPtr conn, struct private_data *priv,
 
  cleanup:
     VIR_FREE(serverin);
+    VIR_FREE(localAddr);
+    VIR_FREE(remoteAddr);
 
     remoteAuthInteractStateClear(&state, true);
     VIR_FREE(saslcb);
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index d8ed15b..26b02fa 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -954,6 +954,16 @@ const char *virNetClientRemoteAddrString(virNetClientPtr client)
     return virNetSocketRemoteAddrString(client->sock);
 }
 
+char *virNetClientLocalAddrFormatSASL(virNetClientPtr client)
+{
+    return virNetSocketLocalAddrFormatSASL(client->sock);
+}
+
+char *virNetClientRemoteAddrFormatSASL(virNetClientPtr client)
+{
+    return virNetSocketRemoteAddrFormatSASL(client->sock);
+}
+
 #if WITH_GNUTLS
 int virNetClientGetTLSKeySize(virNetClientPtr client)
 {
diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h
index 38f929c..4b78677 100644
--- a/src/rpc/virnetclient.h
+++ b/src/rpc/virnetclient.h
@@ -123,6 +123,8 @@ bool virNetClientIsOpen(virNetClientPtr client);
 
 const char *virNetClientLocalAddrString(virNetClientPtr client);
 const char *virNetClientRemoteAddrString(virNetClientPtr client);
+char *virNetClientLocalAddrFormatSASL(virNetClientPtr client);
+char *virNetClientRemoteAddrFormatSASL(virNetClientPtr client);
 
 # ifdef WITH_GNUTLS
 int virNetClientGetTLSKeySize(virNetClientPtr client);
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index a9d70e1..a7b3b15 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -911,6 +911,19 @@ const char *virNetServerClientRemoteAddrString(virNetServerClientPtr client)
     return virNetSocketRemoteAddrString(client->sock);
 }
 
+char *virNetServerClientLocalAddrFormatSASL(virNetServerClientPtr client)
+{
+    if (!client->sock)
+        return NULL;
+    return virNetSocketLocalAddrFormatSASL(client->sock);
+}
+
+char *virNetServerClientRemoteAddrFormatSASL(virNetServerClientPtr client)
+{
+    if (!client->sock)
+        return NULL;
+    return virNetSocketRemoteAddrFormatSASL(client->sock);
+}
 
 void virNetServerClientDispose(void *obj)
 {
diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h
index 55a8af1..267e4ec 100644
--- a/src/rpc/virnetserverclient.h
+++ b/src/rpc/virnetserverclient.h
@@ -139,6 +139,8 @@ int virNetServerClientStartKeepAlive(virNetServerClientPtr client);
 
 const char *virNetServerClientLocalAddrString(virNetServerClientPtr client);
 const char *virNetServerClientRemoteAddrString(virNetServerClientPtr client);
+char *virNetServerClientLocalAddrFormatSASL(virNetServerClientPtr client);
+char *virNetServerClientRemoteAddrFormatSASL(virNetServerClientPtr client);
 
 int virNetServerClientSendMessage(virNetServerClientPtr client,
                                   virNetMessagePtr msg);
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index d909b94..a90cc55 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -262,11 +262,11 @@ static virNetSocketPtr virNetSocketNew(virSocketAddrPtr localAddr,
 
 
     if (localAddr &&
-        !(sock->localAddrStr = virSocketAddrFormatFull(localAddr, true, ";")))
+        !(sock->localAddrStr = virSocketAddrFormatFull(localAddr, true, NULL)))
         goto error;
 
     if (remoteAddr &&
-        !(sock->remoteAddrStr = virSocketAddrFormatFull(remoteAddr, true, ";")))
+        !(sock->remoteAddrStr = virSocketAddrFormatFull(remoteAddr, true, NULL)))
         goto error;
 
     sock->client = isClient;
@@ -1465,6 +1465,19 @@ const char *virNetSocketRemoteAddrString(virNetSocketPtr sock)
     return sock->remoteAddrStr;
 }
 
+/* These helper functions return a SASL-formatted socket addr string,
+ * caller is responsible for freeing the string.
+ */
+char *virNetSocketLocalAddrFormatSASL(virNetSocketPtr sock)
+{
+    return virSocketAddrFormatFull(&sock->localAddr, true, ";");
+}
+
+char *virNetSocketRemoteAddrFormatSASL(virNetSocketPtr sock)
+{
+    return virSocketAddrFormatFull(&sock->remoteAddr, true, ";");
+}
+
 
 #if WITH_GNUTLS
 static ssize_t virNetSocketTLSSessionWrite(const char *buf,
diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h
index 5de3d92..4eb7187 100644
--- a/src/rpc/virnetsocket.h
+++ b/src/rpc/virnetsocket.h
@@ -150,6 +150,8 @@ bool virNetSocketHasPendingData(virNetSocketPtr sock);
 
 const char *virNetSocketLocalAddrString(virNetSocketPtr sock);
 const char *virNetSocketRemoteAddrString(virNetSocketPtr sock);
+char *virNetSocketLocalAddrFormatSASL(virNetSocketPtr sock);
+char *virNetSocketRemoteAddrFormatSASL(virNetSocketPtr sock);
 
 int virNetSocketListen(virNetSocketPtr sock, int backlog);
 int virNetSocketAccept(virNetSocketPtr sock,
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 4b45681..a0c92ea 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -339,9 +339,11 @@ virSocketAddrFormat(const virSocketAddr *addr)
  * @withService: if true, then service info is appended
  * @separator: separator between hostname & service.
  *
- * Returns a string representation of the given address
- * Returns NULL on any error
- * Caller must free the returned string
+ * Returns a string representation of the given address. If a format conforming
+ * to URI specification is required, NULL should be passed to separator.
+ * Set @separator only if non-URI format is required, e.g. passing ';' for
+ * @separator if the address should be used with SASL.
+ * Caller must free the returned string.
  */
 char *
 virSocketAddrFormatFull(const virSocketAddr *addr,
@@ -383,8 +385,22 @@ virSocketAddrFormatFull(const virSocketAddr *addr,
     }
 
     if (withService) {
-        if (virAsprintf(&addrstr, "%s%s%s", host, separator, port) == -1)
+        char *ipv6_host = NULL;
+        /* sasl_new_client demands the socket address to be in an odd format:
+         * a.b.c.d;port or e:f:g:h:i:j:k:l;port, so use square brackets for
+         * IPv6 only if no separator is passed to the function
+         */
+        if (!separator && VIR_SOCKET_ADDR_FAMILY(addr) == AF_INET6) {
+            if (virAsprintf(&ipv6_host, "[%s]", host) < 0)
+                goto error;
+        }
+
+        if (virAsprintf(&addrstr, "%s%s%s",
+                        ipv6_host ? ipv6_host : host,
+                        separator ? separator : ":", port) == -1)
             goto error;
+
+        VIR_FREE(ipv6_host);
     } else {
         if (VIR_STRDUP(addrstr, host) < 0)
             goto error;
diff --git a/tests/virnetsockettest.c b/tests/virnetsockettest.c
index 5786870..c2bc4e7 100644
--- a/tests/virnetsockettest.c
+++ b/tests/virnetsockettest.c
@@ -249,7 +249,7 @@ static int testSocketUNIXAddrs(const void *data ATTRIBUTE_UNUSED)
     if (virNetSocketNewListenUNIX(path, 0700, -1, getegid(), &lsock) < 0)
         goto cleanup;
 
-    if (STRNEQ(virNetSocketLocalAddrString(lsock), "127.0.0.1;0")) {
+    if (STRNEQ(virNetSocketLocalAddrString(lsock), "127.0.0.1:0")) {
         VIR_DEBUG("Unexpected local address");
         goto cleanup;
     }
@@ -265,12 +265,12 @@ static int testSocketUNIXAddrs(const void *data ATTRIBUTE_UNUSED)
     if (virNetSocketNewConnectUNIX(path, false, NULL, &csock) < 0)
         goto cleanup;
 
-    if (STRNEQ(virNetSocketLocalAddrString(csock), "127.0.0.1;0")) {
+    if (STRNEQ(virNetSocketLocalAddrString(csock), "127.0.0.1:0")) {
         VIR_DEBUG("Unexpected local address");
         goto cleanup;
     }
 
-    if (STRNEQ(virNetSocketRemoteAddrString(csock), "127.0.0.1;0")) {
+    if (STRNEQ(virNetSocketRemoteAddrString(csock), "127.0.0.1:0")) {
         VIR_DEBUG("Unexpected local address");
         goto cleanup;
     }
@@ -282,12 +282,12 @@ static int testSocketUNIXAddrs(const void *data ATTRIBUTE_UNUSED)
     }
 
 
-    if (STRNEQ(virNetSocketLocalAddrString(ssock), "127.0.0.1;0")) {
+    if (STRNEQ(virNetSocketLocalAddrString(ssock), "127.0.0.1:0")) {
         VIR_DEBUG("Unexpected local address");
         goto cleanup;
     }
 
-    if (STRNEQ(virNetSocketRemoteAddrString(ssock), "127.0.0.1;0")) {
+    if (STRNEQ(virNetSocketRemoteAddrString(ssock), "127.0.0.1:0")) {
         VIR_DEBUG("Unexpected local address");
         goto cleanup;
     }
-- 
2.4.11




More information about the libvir-list mailing list