[libvirt] [PATCH 05/10] Generic module for handling SASL authentication & encryption

Daniel P. Berrange berrange at redhat.com
Wed Jun 22 15:33:54 UTC 2011


This provides two modules for handling SASL

 * virNetSASLContext provides the process-wide state, currently
   just a whitelist of usernames on the server and a one time
   library init call

 * virNetTLSSession provides the per-connection state, ie the
   SASL session itself. This also include APIs for providing
   data encryption/decryption once the session is established

* src/Makefile.am: Add to libvirt-net-rpc.la
* src/rpc/virnetsaslcontext.c, src/rpc/virnetsaslcontext.h: Generic
  SASL handling code
---
 cfg.mk                      |    2 +
 po/POTFILES.in              |    1 +
 src/Makefile.am             |    9 +
 src/rpc/virnetsaslcontext.c |  598 +++++++++++++++++++++++++++++++++++++++++++
 src/rpc/virnetsaslcontext.h |  120 +++++++++
 5 files changed, 730 insertions(+), 0 deletions(-)
 create mode 100644 src/rpc/virnetsaslcontext.c
 create mode 100644 src/rpc/virnetsaslcontext.h

diff --git a/cfg.mk b/cfg.mk
index c0062af..e12f98a 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -127,6 +127,8 @@ useless_free_options =				\
   --name=virLastErrFreeData			\
   --name=virNetMessageFree                      \
   --name=virNetSocketFree                       \
+  --name=virNetSASLContextFree                  \
+  --name=virNetSASLSessionFree                  \
   --name=virNetTLSSessionFree                   \
   --name=virNWFilterDefFree			\
   --name=virNWFilterEntryFree			\
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0aa52b2..61ba1f7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -70,6 +70,7 @@ src/qemu/qemu_process.c
 src/remote/remote_client_bodies.h
 src/remote/remote_driver.c
 src/rpc/virnetmessage.c
+src/rpc/virnetsaslcontext.c
 src/rpc/virnetsocket.c
 src/rpc/virnettlscontext.c
 src/secret/secret_driver.c
diff --git a/src/Makefile.am b/src/Makefile.am
index a5f8ddc..ed0ca56 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1194,11 +1194,20 @@ libvirt_net_rpc_la_SOURCES = \
 	rpc/virnetprotocol.h rpc/virnetprotocol.c \
 	rpc/virnetsocket.h rpc/virnetsocket.c \
 	rpc/virnettlscontext.h rpc/virnettlscontext.c
+if HAVE_SASL
+libvirt_net_rpc_la_SOURCES += \
+	rpc/virnetsaslcontext.h rpc/virnetsaslcontext.c
+else
+EXTRA_DIST += \
+	rpc/virnetsaslcontext.h rpc/virnetsaslcontext.c
+endif
 libvirt_net_rpc_la_CFLAGS = \
 			$(GNUTLS_CFLAGS) \
+			$(SASL_CFLAGS) \
 			$(AM_CFLAGS)
 libvirt_net_rpc_la_LDFLAGS = \
 			$(GNUTLS_LIBS) \
+			$(SASL_LIBS) \
 			$(AM_LDFLAGS) \
 			$(CYGWIN_EXTRA_LDFLAGS) \
 			$(MINGW_EXTRA_LDFLAGS)
diff --git a/src/rpc/virnetsaslcontext.c b/src/rpc/virnetsaslcontext.c
new file mode 100644
index 0000000..6b2a883
--- /dev/null
+++ b/src/rpc/virnetsaslcontext.c
@@ -0,0 +1,598 @@
+/*
+ * virnetsaslcontext.c: SASL encryption/auth handling
+ *
+ * Copyright (C) 2010-2011 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#include <config.h>
+
+#include <fnmatch.h>
+
+#include "virnetsaslcontext.h"
+#include "virnetmessage.h"
+
+#include "virterror_internal.h"
+#include "memory.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_RPC
+#define virNetError(code, ...)                                    \
+    virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
+
+
+struct _virNetSASLContext {
+    const char *const*usernameWhitelist;
+    int refs;
+};
+
+struct _virNetSASLSession {
+    sasl_conn_t *conn;
+    int refs;
+    size_t maxbufsize;
+};
+
+
+virNetSASLContextPtr virNetSASLContextNewClient(void)
+{
+    virNetSASLContextPtr ctxt;
+    int err;
+
+    err = sasl_client_init(NULL);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("failed to initialize SASL library: %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return NULL;
+    }
+
+    if (VIR_ALLOC(ctxt) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    ctxt->refs = 1;
+
+    return ctxt;
+}
+
+virNetSASLContextPtr virNetSASLContextNewServer(const char *const*usernameWhitelist)
+{
+    virNetSASLContextPtr ctxt;
+    int err;
+
+    err = sasl_server_init(NULL, "libvirt");
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("failed to initialize SASL library: %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return NULL;
+    }
+
+    if (VIR_ALLOC(ctxt) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    ctxt->usernameWhitelist = usernameWhitelist;
+    ctxt->refs = 1;
+
+    return ctxt;
+}
+
+int virNetSASLContextCheckIdentity(virNetSASLContextPtr ctxt,
+                                   const char *identity)
+{
+    const char *const*wildcards;
+
+    /* If the list is not set, allow any DN. */
+    wildcards = ctxt->usernameWhitelist;
+    if (!wildcards)
+        return 1; /* No ACL, allow all */
+
+    while (*wildcards) {
+        int ret = fnmatch (*wildcards, identity, 0);
+        if (ret == 0) /* Succesful match */
+            return 1;
+        if (ret != FNM_NOMATCH) {
+            virNetError(VIR_ERR_INTERNAL_ERROR,
+                        _("Malformed TLS whitelist regular expression '%s'"),
+                        *wildcards);
+            return -1;
+        }
+
+        wildcards++;
+    }
+
+    /* Denied */
+    VIR_ERROR(_("SASL client %s not allowed in whitelist"), identity);
+
+    /* This is the most common error: make it informative. */
+    virNetError(VIR_ERR_SYSTEM_ERROR, "%s",
+                _("Client's username is not on the list of allowed clients"));
+    return 0;
+}
+
+
+void virNetSASLContextRef(virNetSASLContextPtr ctxt)
+{
+    ctxt->refs++;
+}
+
+void virNetSASLContextFree(virNetSASLContextPtr ctxt)
+{
+    if (!ctxt)
+        return;
+
+    ctxt->refs--;
+    if (ctxt->refs > 0)
+        return;
+
+    VIR_FREE(ctxt);
+}
+
+virNetSASLSessionPtr virNetSASLSessionNewClient(virNetSASLContextPtr ctxt ATTRIBUTE_UNUSED,
+                                                const char *service,
+                                                const char *hostname,
+                                                const char *localAddr,
+                                                const char *remoteAddr,
+                                                const sasl_callback_t *cbs)
+{
+    virNetSASLSessionPtr sasl = NULL;
+    int err;
+
+    if (VIR_ALLOC(sasl) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    sasl->refs = 1;
+    /* Arbitrary size for amount of data we can encode in a single block */
+    sasl->maxbufsize = 1 << 16;
+
+    err = sasl_client_new(service,
+                          hostname,
+                          localAddr,
+                          remoteAddr,
+                          cbs,
+                          SASL_SUCCESS_DATA,
+                          &sasl->conn);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("Failed to create SASL client context: %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        goto cleanup;
+    }
+
+    return sasl;
+
+cleanup:
+    virNetSASLSessionFree(sasl);
+    return NULL;
+}
+
+virNetSASLSessionPtr virNetSASLSessionNewServer(virNetSASLContextPtr ctxt ATTRIBUTE_UNUSED,
+                                                const char *service,
+                                                const char *localAddr,
+                                                const char *remoteAddr)
+{
+    virNetSASLSessionPtr sasl = NULL;
+    int err;
+
+    if (VIR_ALLOC(sasl) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    sasl->refs = 1;
+    /* Arbitrary size for amount of data we can encode in a single block */
+    sasl->maxbufsize = 1 << 16;
+
+    err = sasl_server_new(service,
+                          NULL,
+                          NULL,
+                          localAddr,
+                          remoteAddr,
+                          NULL,
+                          SASL_SUCCESS_DATA,
+                          &sasl->conn);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("Failed to create SASL client context: %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        goto cleanup;
+    }
+
+    return sasl;
+
+cleanup:
+    virNetSASLSessionFree(sasl);
+    return NULL;
+}
+
+void virNetSASLSessionRef(virNetSASLSessionPtr sasl)
+{
+    sasl->refs++;
+}
+
+int virNetSASLSessionExtKeySize(virNetSASLSessionPtr sasl,
+                                int ssf)
+{
+    int err;
+
+    err = sasl_setprop(sasl->conn, SASL_SSF_EXTERNAL, &ssf);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_INTERNAL_ERROR,
+                    _("cannot set external SSF %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return -1;
+    }
+    return 0;
+}
+
+const char *virNetSASLSessionGetIdentity(virNetSASLSessionPtr sasl)
+{
+    const void *val;
+    int err;
+
+    err = sasl_getprop(sasl->conn, SASL_USERNAME, &val);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("cannot query SASL username on connection %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return NULL;
+    }
+    if (val == NULL) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("no client username was found"));
+        return NULL;
+    }
+    VIR_DEBUG("SASL client username %s", (const char *)val);
+
+    return (const char*)val;
+}
+
+
+int virNetSASLSessionGetKeySize(virNetSASLSessionPtr sasl)
+{
+    int err;
+    int ssf;
+    const void *val;
+    err = sasl_getprop(sasl->conn, SASL_SSF, &val);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("cannot query SASL ssf on connection %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return -1;
+    }
+    ssf = *(const int *)val;
+    return ssf;
+}
+
+int virNetSASLSessionSecProps(virNetSASLSessionPtr sasl,
+                              int minSSF,
+                              int maxSSF,
+                              bool allowAnonymous)
+{
+    sasl_security_properties_t secprops;
+    int err;
+
+    VIR_DEBUG("minSSF=%d maxSSF=%d allowAnonymous=%d maxbufsize=%zu",
+              minSSF, maxSSF, allowAnonymous, sasl->maxbufsize);
+
+    memset(&secprops, 0, sizeof secprops);
+
+    secprops.min_ssf = minSSF;
+    secprops.max_ssf = maxSSF;
+    secprops.maxbufsize = sasl->maxbufsize;
+    secprops.security_flags = allowAnonymous ? 0 :
+        SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT;
+
+    err = sasl_setprop(sasl->conn, SASL_SEC_PROPS, &secprops);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_INTERNAL_ERROR,
+                    _("cannot set security props %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int virNetSASLSessionUpdateBufSize(virNetSASLSessionPtr sasl)
+{
+    unsigned *maxbufsize;
+    int err;
+
+    err = sasl_getprop(sasl->conn, SASL_MAXOUTBUF, (const void **)&maxbufsize);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_INTERNAL_ERROR,
+                    _("cannot get security props %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return -1;
+    }
+
+    VIR_DEBUG("Negotiated bufsize is %u vs requested size %zu",
+              *maxbufsize, sasl->maxbufsize);
+    sasl->maxbufsize = *maxbufsize;
+    return 0;
+}
+
+char *virNetSASLSessionListMechanisms(virNetSASLSessionPtr sasl)
+{
+    const char *mechlist;
+    char *ret;
+    int err;
+
+    err = sasl_listmech(sasl->conn,
+                        NULL, /* Don't need to set user */
+                        "", /* Prefix */
+                        ",", /* Separator */
+                        "", /* Suffix */
+                        &mechlist,
+                        NULL,
+                        NULL);
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_INTERNAL_ERROR,
+                    _("cannot list SASL mechanisms %d (%s)"),
+                    err, sasl_errdetail(sasl->conn));
+        return NULL;
+    }
+    if (!(ret = strdup(mechlist))) {
+        virReportOOMError();
+        return NULL;
+    }
+    return ret;
+}
+
+
+int virNetSASLSessionClientStart(virNetSASLSessionPtr sasl,
+                                 const char *mechlist,
+                                 sasl_interact_t **prompt_need,
+                                 const char **clientout,
+                                 size_t *clientoutlen,
+                                 const char **mech)
+{
+    unsigned outlen = 0;
+
+    VIR_DEBUG("sasl=%p mechlist=%s prompt_need=%p clientout=%p clientoutlen=%p mech=%p",
+              sasl, mechlist, prompt_need, clientout, clientoutlen, mech);
+
+    int err = sasl_client_start(sasl->conn,
+                                mechlist,
+                                prompt_need,
+                                clientout,
+                                &outlen,
+                                mech);
+
+    *clientoutlen = outlen;
+
+    switch (err) {
+    case SASL_OK:
+        if (virNetSASLSessionUpdateBufSize(sasl) < 0)
+            return -1;
+        return VIR_NET_SASL_COMPLETE;
+    case SASL_CONTINUE:
+        return VIR_NET_SASL_CONTINUE;
+    case SASL_INTERACT:
+        return VIR_NET_SASL_INTERACT;
+
+    default:
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("Failed to start SASL negotiation: %d (%s)"),
+                    err, sasl_errdetail(sasl->conn));
+        return -1;
+    }
+}
+
+
+int virNetSASLSessionClientStep(virNetSASLSessionPtr sasl,
+                                const char *serverin,
+                                size_t serverinlen,
+                                sasl_interact_t **prompt_need,
+                                const char **clientout,
+                                size_t *clientoutlen)
+{
+    unsigned inlen = serverinlen;
+    unsigned outlen = 0;
+
+    VIR_DEBUG("sasl=%p serverin=%s serverinlen=%zu prompt_need=%p clientout=%p clientoutlen=%p",
+              sasl, serverin, serverinlen, prompt_need, clientout, clientoutlen);
+
+    int err = sasl_client_step(sasl->conn,
+                               serverin,
+                               inlen,
+                               prompt_need,
+                               clientout,
+                               &outlen);
+    *clientoutlen = outlen;
+
+    switch (err) {
+    case SASL_OK:
+        if (virNetSASLSessionUpdateBufSize(sasl) < 0)
+            return -1;
+        return VIR_NET_SASL_COMPLETE;
+    case SASL_CONTINUE:
+        return VIR_NET_SASL_CONTINUE;
+    case SASL_INTERACT:
+        return VIR_NET_SASL_INTERACT;
+
+    default:
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("Failed to step SASL negotiation: %d (%s)"),
+                    err, sasl_errdetail(sasl->conn));
+        return -1;
+    }
+}
+
+int virNetSASLSessionServerStart(virNetSASLSessionPtr sasl,
+                                 const char *mechname,
+                                 const char *clientin,
+                                 size_t clientinlen,
+                                 const char **serverout,
+                                 size_t *serveroutlen)
+{
+    unsigned inlen = clientinlen;
+    unsigned outlen = 0;
+    int err = sasl_server_start(sasl->conn,
+                                mechname,
+                                clientin,
+                                inlen,
+                                serverout,
+                                &outlen);
+
+    *serveroutlen = outlen;
+
+    switch (err) {
+    case SASL_OK:
+        if (virNetSASLSessionUpdateBufSize(sasl) < 0)
+            return -1;
+        return VIR_NET_SASL_COMPLETE;
+    case SASL_CONTINUE:
+        return VIR_NET_SASL_CONTINUE;
+    case SASL_INTERACT:
+        return VIR_NET_SASL_INTERACT;
+
+    default:
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("Failed to start SASL negotiation: %d (%s)"),
+                    err, sasl_errdetail(sasl->conn));
+        return -1;
+    }
+}
+
+
+int virNetSASLSessionServerStep(virNetSASLSessionPtr sasl,
+                                const char *clientin,
+                                size_t clientinlen,
+                                const char **serverout,
+                                size_t *serveroutlen)
+{
+    unsigned inlen = clientinlen;
+    unsigned outlen = 0;
+
+    int err = sasl_server_step(sasl->conn,
+                               clientin,
+                               inlen,
+                               serverout,
+                               &outlen);
+
+    *serveroutlen = outlen;
+
+    switch (err) {
+    case SASL_OK:
+        if (virNetSASLSessionUpdateBufSize(sasl) < 0)
+            return -1;
+        return VIR_NET_SASL_COMPLETE;
+    case SASL_CONTINUE:
+        return VIR_NET_SASL_CONTINUE;
+    case SASL_INTERACT:
+        return VIR_NET_SASL_INTERACT;
+
+    default:
+        virNetError(VIR_ERR_AUTH_FAILED,
+                    _("Failed to start SASL negotiation: %d (%s)"),
+                    err, sasl_errdetail(sasl->conn));
+        return -1;
+    }
+}
+
+size_t virNetSASLSessionGetMaxBufSize(virNetSASLSessionPtr sasl)
+{
+    return sasl->maxbufsize;
+}
+
+ssize_t virNetSASLSessionEncode(virNetSASLSessionPtr sasl,
+                                const char *input,
+                                size_t inputLen,
+                                const char **output,
+                                size_t *outputlen)
+{
+    unsigned inlen = inputLen;
+    unsigned outlen = 0;
+    int err;
+
+    if (inputLen > sasl->maxbufsize) {
+        virReportSystemError(EINVAL,
+                             _("SASL data length %zu too long, max %zu"),
+                             inputLen, sasl->maxbufsize);
+        return -1;
+    }
+
+    err = sasl_encode(sasl->conn,
+                      input,
+                      inlen,
+                      output,
+                      &outlen);
+    *outputlen = outlen;
+
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_INTERNAL_ERROR,
+                    _("failed to encode SASL data: %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return -1;
+    }
+    return 0;
+}
+
+ssize_t virNetSASLSessionDecode(virNetSASLSessionPtr sasl,
+                                const char *input,
+                                size_t inputLen,
+                                const char **output,
+                                size_t *outputlen)
+{
+    unsigned inlen = inputLen;
+    unsigned outlen = 0;
+    int err;
+
+    if (inputLen > sasl->maxbufsize) {
+        virReportSystemError(EINVAL,
+                             _("SASL data length %zu too long, max %zu"),
+                             inputLen, sasl->maxbufsize);
+        return -1;
+    }
+
+    err = sasl_decode(sasl->conn,
+                      input,
+                      inlen,
+                      output,
+                      &outlen);
+    *outputlen = outlen;
+    if (err != SASL_OK) {
+        virNetError(VIR_ERR_INTERNAL_ERROR,
+                    _("failed to decode SASL data: %d (%s)"),
+                    err, sasl_errstring(err, NULL, NULL));
+        return -1;
+    }
+    return 0;
+}
+
+void virNetSASLSessionFree(virNetSASLSessionPtr sasl)
+{
+    if (!sasl)
+        return;
+
+    sasl->refs--;
+    if (sasl->refs > 0)
+        return;
+
+    if (sasl->conn)
+        sasl_dispose(&sasl->conn);
+
+    VIR_FREE(sasl);
+}
diff --git a/src/rpc/virnetsaslcontext.h b/src/rpc/virnetsaslcontext.h
new file mode 100644
index 0000000..61a739d
--- /dev/null
+++ b/src/rpc/virnetsaslcontext.h
@@ -0,0 +1,120 @@
+/*
+ * virnetsaslcontext.h: SASL encryption/auth handling
+ *
+ * Copyright (C) 2010-2011 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+
+#ifndef __VIR_NET_CLIENT_SASL_CONTEXT_H__
+# define __VIR_NET_CLIENT_SASL_CONTEXT_H__
+
+# include <sasl/sasl.h>
+
+# include <stdbool.h>
+# include <sys/types.h>
+
+typedef struct _virNetSASLContext virNetSASLContext;
+typedef virNetSASLContext *virNetSASLContextPtr;
+
+typedef struct _virNetSASLSession virNetSASLSession;
+typedef virNetSASLSession *virNetSASLSessionPtr;
+
+enum {
+    VIR_NET_SASL_COMPLETE,
+    VIR_NET_SASL_CONTINUE,
+    VIR_NET_SASL_INTERACT,
+};
+
+virNetSASLContextPtr virNetSASLContextNewClient(void);
+virNetSASLContextPtr virNetSASLContextNewServer(const char *const*usernameWhitelist);
+
+int virNetSASLContextCheckIdentity(virNetSASLContextPtr ctxt,
+                                   const char *identity);
+
+void virNetSASLContextRef(virNetSASLContextPtr sasl);
+void virNetSASLContextFree(virNetSASLContextPtr sasl);
+
+virNetSASLSessionPtr virNetSASLSessionNewClient(virNetSASLContextPtr ctxt,
+                                                const char *service,
+                                                const char *hostname,
+                                                const char *localAddr,
+                                                const char *remoteAddr,
+                                                const sasl_callback_t *cbs);
+virNetSASLSessionPtr virNetSASLSessionNewServer(virNetSASLContextPtr ctxt,
+                                                const char *service,
+                                                const char *localAddr,
+                                                const char *remoteAddr);
+
+char *virNetSASLSessionListMechanisms(virNetSASLSessionPtr sasl);
+
+void virNetSASLSessionRef(virNetSASLSessionPtr sasl);
+
+int virNetSASLSessionExtKeySize(virNetSASLSessionPtr sasl,
+                                int ssf);
+
+int virNetSASLSessionGetKeySize(virNetSASLSessionPtr sasl);
+
+const char *virNetSASLSessionGetIdentity(virNetSASLSessionPtr sasl);
+
+int virNetSASLSessionSecProps(virNetSASLSessionPtr sasl,
+                              int minSSF,
+                              int maxSSF,
+                              bool allowAnonymous);
+
+int virNetSASLSessionClientStart(virNetSASLSessionPtr sasl,
+                                 const char *mechlist,
+                                 sasl_interact_t **prompt_need,
+                                 const char **clientout,
+                                 size_t *clientoutlen,
+                                 const char **mech);
+
+int virNetSASLSessionClientStep(virNetSASLSessionPtr sasl,
+                                const char *serverin,
+                                size_t serverinlen,
+                                sasl_interact_t **prompt_need,
+                                const char **clientout,
+                                size_t *clientoutlen);
+
+int virNetSASLSessionServerStart(virNetSASLSessionPtr sasl,
+                                 const char *mechname,
+                                 const char *clientin,
+                                 size_t clientinlen,
+                                 const char **serverout,
+                                 size_t *serveroutlen);
+
+int virNetSASLSessionServerStep(virNetSASLSessionPtr sasl,
+                                const char *clientin,
+                                size_t clientinlen,
+                                const char **serverout,
+                                size_t *serveroutlen);
+
+size_t virNetSASLSessionGetMaxBufSize(virNetSASLSessionPtr sasl);
+
+ssize_t virNetSASLSessionEncode(virNetSASLSessionPtr sasl,
+                                const char *input,
+                                size_t inputLen,
+                                const char **output,
+                                size_t *outputlen);
+
+ssize_t virNetSASLSessionDecode(virNetSASLSessionPtr sasl,
+                                const char *input,
+                                size_t inputLen,
+                                const char **output,
+                                size_t *outputlen);
+
+void virNetSASLSessionFree(virNetSASLSessionPtr sasl);
+
+#endif /* __VIR_NET_CLIENT_SASL_CONTEXT_H__ */
-- 
1.7.4.4




More information about the libvir-list mailing list