mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-05 05:45:46 +00:00
Initial integration of SASL authentication, working for Kerberos only
This commit is contained in:
parent
a8977b62ba
commit
1b1d647439
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
|||||||
|
Wed Dec 5 10:20:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* configure.in: Add checks for SASL library
|
||||||
|
* include/libvirt/virterror.h: Add VIR_ERR_AUTH_FAILED
|
||||||
|
* libvirt.spec.in: Add deps on cyrus-sasl & md5 plugin
|
||||||
|
and add SASL config file
|
||||||
|
* qemud/Makefile.am: Add SASL config file & build flags
|
||||||
|
* qemud/remote_protocol.x: new RPC calls for SASL
|
||||||
|
* qemud/internal.h, qemud/qemud.c, qemud/remote.c: Server
|
||||||
|
side of SASL authentication support
|
||||||
|
* qemud/libvirtd.init.in, qemud/libvirtd.sysconf: Set
|
||||||
|
KRB5_KTNAME to tell daemon where kerberos keytab lives
|
||||||
|
* qemud/libvirtd.sasl: example SASL config file
|
||||||
|
* src/Makefile.am, tests/Makefile.am: add SASL build flags
|
||||||
|
* src/remote_internal.c: Add support for SASL auth client
|
||||||
|
* src/virterror.c: Add VOIR_ERR_AUTH_FAILED string
|
||||||
|
|
||||||
Wed Dec 5 10:07:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
Wed Dec 5 10:07:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
* src/qemu_conf.c: Strip out NIC interfaces named vnetXXX since
|
* src/qemu_conf.c: Strip out NIC interfaces named vnetXXX since
|
||||||
|
39
configure.in
39
configure.in
@ -361,6 +361,40 @@ CFLAGS="$old_cflags"
|
|||||||
LDFLAGS="$old_ldflags"
|
LDFLAGS="$old_ldflags"
|
||||||
|
|
||||||
|
|
||||||
|
dnl Cyrus SASL
|
||||||
|
AC_ARG_WITH(sasl,
|
||||||
|
[ --with-sasl use cyrus SASL for authentication],
|
||||||
|
[],
|
||||||
|
[with_sasl=yes])
|
||||||
|
|
||||||
|
SASL_CFLAGS=
|
||||||
|
SASL_LIBS=
|
||||||
|
if test "$with_sasl" != "no"; then
|
||||||
|
if test "$with_sasl" != "yes"; then
|
||||||
|
SASL_CFLAGS="-I$with_sasl"
|
||||||
|
SASL_LIBS="-L$with_sasl"
|
||||||
|
fi
|
||||||
|
old_cflags="$CFLAGS"
|
||||||
|
old_libs="$LIBS"
|
||||||
|
CFLAGS="$CFLAGS $SASL_CFLAGS"
|
||||||
|
LIBS="$LIBS $SASL_LIBS"
|
||||||
|
AC_CHECK_HEADER([sasl/sasl.h],
|
||||||
|
[],
|
||||||
|
AC_MSG_ERROR([You must install the Cyrus SASL development package in order to compile libvirt]))
|
||||||
|
AC_CHECK_LIB(sasl2, sasl_client_init,
|
||||||
|
[],
|
||||||
|
[AC_MSG_ERROR([You must install the Cyrus SASL library in order to compile and run libvirt])])
|
||||||
|
CFLAGS="$old_cflags"
|
||||||
|
LIBS="$old_libs"
|
||||||
|
SASL_LIBS="$SASL_LIBS -lsasl2"
|
||||||
|
AC_DEFINE_UNQUOTED(HAVE_SASL, 1, [whether Cyrus SASL is available for authentication])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_SASL, [test "$with_sasl" != "no"])
|
||||||
|
AC_SUBST(SASL_CFLAGS)
|
||||||
|
AC_SUBST(SASL_LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl Avahi library
|
dnl Avahi library
|
||||||
AC_ARG_WITH(avahi,
|
AC_ARG_WITH(avahi,
|
||||||
[ --with-avahi use avahi to advertise remote daemon],
|
[ --with-avahi use avahi to advertise remote daemon],
|
||||||
@ -583,6 +617,11 @@ AC_MSG_NOTICE([Libraries])
|
|||||||
AC_MSG_NOTICE([])
|
AC_MSG_NOTICE([])
|
||||||
AC_MSG_NOTICE([ libxml: $LIBXML_CFLAGS $LIBXML_LIBS])
|
AC_MSG_NOTICE([ libxml: $LIBXML_CFLAGS $LIBXML_LIBS])
|
||||||
AC_MSG_NOTICE([ gnutls: $GNUTLS_CFLAGS $GNUTLS_LIBS])
|
AC_MSG_NOTICE([ gnutls: $GNUTLS_CFLAGS $GNUTLS_LIBS])
|
||||||
|
if test "$with_sasl" != "no" ; then
|
||||||
|
AC_MSG_NOTICE([ sasl: $SASL_CFLAGS $SASL_LIBS])
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([ sasl: no])
|
||||||
|
fi
|
||||||
if test "$with_avahi" = "yes" ; then
|
if test "$with_avahi" = "yes" ; then
|
||||||
AC_MSG_NOTICE([ avahi: $AVAHI_CFLAGS $AVAHI_LIBS])
|
AC_MSG_NOTICE([ avahi: $AVAHI_CFLAGS $AVAHI_LIBS])
|
||||||
else
|
else
|
||||||
|
@ -131,6 +131,7 @@ typedef enum {
|
|||||||
VIR_ERR_NO_DOMAIN, /* domain not found or unexpectedly disappeared */
|
VIR_ERR_NO_DOMAIN, /* domain not found or unexpectedly disappeared */
|
||||||
VIR_ERR_NO_NETWORK, /* network not found */
|
VIR_ERR_NO_NETWORK, /* network not found */
|
||||||
VIR_ERR_INVALID_MAC, /* invalid MAC adress */
|
VIR_ERR_INVALID_MAC, /* invalid MAC adress */
|
||||||
|
VIR_ERR_AUTH_FAILED, /* authentication failed */
|
||||||
} virErrorNumber;
|
} virErrorNumber;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,6 +16,10 @@ Requires: ncurses
|
|||||||
Requires: dnsmasq
|
Requires: dnsmasq
|
||||||
Requires: bridge-utils
|
Requires: bridge-utils
|
||||||
Requires: iptables
|
Requires: iptables
|
||||||
|
Requires: cyrus-sasl
|
||||||
|
# Not technically required, but makes 'out-of-box' config
|
||||||
|
# work correctly & doesn't have onerous dependancies
|
||||||
|
Requires: cyrus-sasl-md5
|
||||||
BuildRequires: xen-devel
|
BuildRequires: xen-devel
|
||||||
BuildRequires: libxml2-devel
|
BuildRequires: libxml2-devel
|
||||||
BuildRequires: readline-devel
|
BuildRequires: readline-devel
|
||||||
@ -26,6 +30,7 @@ BuildRequires: avahi-devel
|
|||||||
BuildRequires: dnsmasq
|
BuildRequires: dnsmasq
|
||||||
BuildRequires: bridge-utils
|
BuildRequires: bridge-utils
|
||||||
BuildRequires: qemu
|
BuildRequires: qemu
|
||||||
|
BuildRequires: cyrus-sasl-devel
|
||||||
Obsoletes: libvir
|
Obsoletes: libvir
|
||||||
ExclusiveArch: i386 x86_64 ia64
|
ExclusiveArch: i386 x86_64 ia64
|
||||||
|
|
||||||
@ -132,6 +137,7 @@ fi
|
|||||||
%config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
|
%config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
|
||||||
%config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
|
%config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
|
||||||
%config(noreplace) %{_sysconfdir}/libvirt/qemu.conf
|
%config(noreplace) %{_sysconfdir}/libvirt/qemu.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
|
||||||
%dir %{_datadir}/libvirt/
|
%dir %{_datadir}/libvirt/
|
||||||
%dir %{_datadir}/libvirt/networks/
|
%dir %{_datadir}/libvirt/networks/
|
||||||
%{_datadir}/libvirt/networks/default.xml
|
%{_datadir}/libvirt/networks/default.xml
|
||||||
|
@ -17,6 +17,7 @@ EXTRA_DIST = libvirtd.init.in libvirtd.sysconf default-network.xml \
|
|||||||
remote_dispatch_localvars.h \
|
remote_dispatch_localvars.h \
|
||||||
remote_dispatch_proc_switch.h \
|
remote_dispatch_proc_switch.h \
|
||||||
mdns.c mdns.h \
|
mdns.c mdns.h \
|
||||||
|
libvirtd.sasl \
|
||||||
$(conf_DATA)
|
$(conf_DATA)
|
||||||
|
|
||||||
libvirtd_SOURCES = \
|
libvirtd_SOURCES = \
|
||||||
@ -28,14 +29,14 @@ libvirtd_SOURCES = \
|
|||||||
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
|
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
|
||||||
libvirtd_CFLAGS = \
|
libvirtd_CFLAGS = \
|
||||||
-I$(top_srcdir)/include -I$(top_builddir)/include \
|
-I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||||
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) \
|
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
|
||||||
$(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
|
$(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
|
||||||
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
|
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
|
||||||
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
|
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
|
||||||
-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \
|
-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \
|
||||||
-DGETTEXT_PACKAGE=\"$(PACKAGE)\"
|
-DGETTEXT_PACKAGE=\"$(PACKAGE)\"
|
||||||
|
|
||||||
libvirtd_LDFLAGS = $(WARN_CFLAGS) $(LIBXML_LIBS) $(GNUTLS_LIBS)
|
libvirtd_LDFLAGS = $(WARN_CFLAGS) $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS)
|
||||||
libvirtd_DEPENDENCIES = ../src/libvirt.la
|
libvirtd_DEPENDENCIES = ../src/libvirt.la
|
||||||
libvirtd_LDADD = ../src/libvirt.la
|
libvirtd_LDADD = ../src/libvirt.la
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ libvirtd_LDADD += $(AVAHI_LIBS)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
default_xml_dest = libvirt/qemu/networks/default.xml
|
default_xml_dest = libvirt/qemu/networks/default.xml
|
||||||
install-data-local: install-init
|
install-data-local: install-init install-data-sasl
|
||||||
mkdir -p $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart
|
mkdir -p $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart
|
||||||
$(INSTALL_DATA) $(srcdir)/default-network.xml \
|
$(INSTALL_DATA) $(srcdir)/default-network.xml \
|
||||||
$(DESTDIR)$(sysconfdir)/$(default_xml_dest)
|
$(DESTDIR)$(sysconfdir)/$(default_xml_dest)
|
||||||
@ -59,7 +60,7 @@ install-data-local: install-init
|
|||||||
mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt
|
mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt
|
||||||
mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt
|
mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt
|
||||||
|
|
||||||
uninstall-local: uninstall-init
|
uninstall-local:: uninstall-init uninstall-data-sasl
|
||||||
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
|
rm -f $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml
|
||||||
rm -f $(DESTDIR)$(sysconfdir)/$(default_xml_dest)
|
rm -f $(DESTDIR)$(sysconfdir)/$(default_xml_dest)
|
||||||
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
|
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
|
||||||
@ -67,6 +68,18 @@ uninstall-local: uninstall-init
|
|||||||
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
|
rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
|
||||||
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
|
rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
|
||||||
|
|
||||||
|
if HAVE_SASL
|
||||||
|
install-data-sasl:: install-init
|
||||||
|
mkdir -p $(DESTDIR)$(sysconfdir)/sasl2/
|
||||||
|
$(INSTALL_DATA) $(srcdir)/libvirtd.sasl $(DESTDIR)$(sysconfdir)/sasl2/libvirt.conf
|
||||||
|
|
||||||
|
uninstall-data-sasl:: install-init
|
||||||
|
rm -f $(DESTDIR)$(sysconfdir)/sasl2/libvirt.conf
|
||||||
|
rmdir $(DESTDIR)$(sysconfdir)/sasl2/
|
||||||
|
else
|
||||||
|
install-data-sasl:
|
||||||
|
uninstall-data-sasl:
|
||||||
|
endif
|
||||||
|
|
||||||
if RPCGEN
|
if RPCGEN
|
||||||
.x.c:
|
.x.c:
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
#include <gnutls/x509.h>
|
#include <gnutls/x509.h>
|
||||||
#include "../src/gnutls_1_0_compat.h"
|
#include "../src/gnutls_1_0_compat.h"
|
||||||
|
#if HAVE_SASL
|
||||||
|
#include <sasl/sasl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SYSLIMITS_H
|
#ifdef HAVE_SYS_SYSLIMITS_H
|
||||||
#include <sys/syslimits.h>
|
#include <sys/syslimits.h>
|
||||||
@ -91,6 +94,10 @@ struct qemud_client {
|
|||||||
int tls;
|
int tls;
|
||||||
gnutls_session_t session;
|
gnutls_session_t session;
|
||||||
enum qemud_tls_direction direction;
|
enum qemud_tls_direction direction;
|
||||||
|
int auth;
|
||||||
|
#if HAVE_SASL
|
||||||
|
sasl_conn_t *saslconn;
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned int incomingSerial;
|
unsigned int incomingSerial;
|
||||||
unsigned int outgoingSerial;
|
unsigned int outgoingSerial;
|
||||||
@ -116,6 +123,7 @@ struct qemud_socket {
|
|||||||
int readonly;
|
int readonly;
|
||||||
/* If set, TLS is required on this socket. */
|
/* If set, TLS is required on this socket. */
|
||||||
int tls;
|
int tls;
|
||||||
|
int auth;
|
||||||
int port;
|
int port;
|
||||||
struct qemud_socket *next;
|
struct qemud_socket *next;
|
||||||
};
|
};
|
||||||
|
@ -37,6 +37,7 @@ PROCESS=libvirtd
|
|||||||
|
|
||||||
LIBVIRTD_CONFIG=
|
LIBVIRTD_CONFIG=
|
||||||
LIBVIRTD_ARGS=
|
LIBVIRTD_ARGS=
|
||||||
|
KRB5_KTNAME=/etc/libvirt/krb5.tab
|
||||||
|
|
||||||
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
|
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ RETVAL=0
|
|||||||
|
|
||||||
start() {
|
start() {
|
||||||
echo -n $"Starting $SERVICE daemon: "
|
echo -n $"Starting $SERVICE daemon: "
|
||||||
daemon --check $SERVICE $PROCESS --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS
|
KRB5_KTNAME=$KRB5_KTNAME daemon --check $SERVICE $PROCESS --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo
|
echo
|
||||||
[ $RETVAL -eq 0 ] && touch @localstatedir@/lock/subsys/$SERVICE
|
[ $RETVAL -eq 0 ] && touch @localstatedir@/lock/subsys/$SERVICE
|
||||||
|
@ -4,3 +4,6 @@
|
|||||||
# Listen for TCP/IP connections
|
# Listen for TCP/IP connections
|
||||||
# NB. must setup TLS/SSL keys prior to using this
|
# NB. must setup TLS/SSL keys prior to using this
|
||||||
#LIBVIRTD_ARGS="--listen"
|
#LIBVIRTD_ARGS="--listen"
|
||||||
|
|
||||||
|
# Override Kerberos service keytab for SASL/GSSAPI
|
||||||
|
#KRB5_KTNAME=/etc/libvirt/krb5.tab
|
||||||
|
@ -575,7 +575,8 @@ remoteMakeSockets (int *fds, int max_fds, int *nfds_r, const char *service)
|
|||||||
static int
|
static int
|
||||||
remoteListenTCP (struct qemud_server *server,
|
remoteListenTCP (struct qemud_server *server,
|
||||||
const char *port,
|
const char *port,
|
||||||
int tls)
|
int tls,
|
||||||
|
int auth)
|
||||||
{
|
{
|
||||||
int fds[2];
|
int fds[2];
|
||||||
int nfds = 0;
|
int nfds = 0;
|
||||||
@ -604,6 +605,7 @@ remoteListenTCP (struct qemud_server *server,
|
|||||||
|
|
||||||
sock->fd = fds[i];
|
sock->fd = fds[i];
|
||||||
sock->tls = tls;
|
sock->tls = tls;
|
||||||
|
sock->auth = auth;
|
||||||
|
|
||||||
if (getsockname(sock->fd, (struct sockaddr *)(&sa), &salen) < 0)
|
if (getsockname(sock->fd, (struct sockaddr *)(&sa), &salen) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -699,6 +701,9 @@ static struct qemud_server *qemudInitialize(int sigread) {
|
|||||||
struct qemud_socket *sock;
|
struct qemud_socket *sock;
|
||||||
char sockname[PATH_MAX];
|
char sockname[PATH_MAX];
|
||||||
char roSockname[PATH_MAX];
|
char roSockname[PATH_MAX];
|
||||||
|
#if HAVE_SASL
|
||||||
|
int err;
|
||||||
|
#endif /* HAVE_SASL */
|
||||||
|
|
||||||
if (!(server = calloc(1, sizeof(struct qemud_server)))) {
|
if (!(server = calloc(1, sizeof(struct qemud_server)))) {
|
||||||
qemudLog(QEMUD_ERR, "Failed to allocate struct qemud_server");
|
qemudLog(QEMUD_ERR, "Failed to allocate struct qemud_server");
|
||||||
@ -728,15 +733,28 @@ static struct qemud_server *qemudInitialize(int sigread) {
|
|||||||
|
|
||||||
virStateInitialize();
|
virStateInitialize();
|
||||||
|
|
||||||
if (ipsock) {
|
#if HAVE_SASL
|
||||||
if (listen_tcp && remoteListenTCP (server, tcp_port, 0) < 0)
|
if ((err = sasl_server_init(NULL, "libvirt")) != SASL_OK) {
|
||||||
|
qemudLog(QEMUD_ERR, "Failed to initialize SASL authentication %s",
|
||||||
|
sasl_errstring(err, NULL, NULL));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ipsock) {
|
||||||
|
#if HAVE_SASL
|
||||||
|
if (listen_tcp && remoteListenTCP (server, tcp_port, 0, REMOTE_AUTH_SASL) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
#else
|
||||||
|
if (listen_tcp && remoteListenTCP (server, tcp_port, 0, REMOTE_AUTH_NONE) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (listen_tls) {
|
if (listen_tls) {
|
||||||
if (remoteInitializeGnuTLS () < 0)
|
if (remoteInitializeGnuTLS () < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (remoteListenTCP (server, tls_port, 1) < 0)
|
if (remoteListenTCP (server, tls_port, 1, REMOTE_AUTH_NONE) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1048,6 +1066,7 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
|
|||||||
client->fd = fd;
|
client->fd = fd;
|
||||||
client->readonly = sock->readonly;
|
client->readonly = sock->readonly;
|
||||||
client->tls = sock->tls;
|
client->tls = sock->tls;
|
||||||
|
client->auth = sock->auth;
|
||||||
memcpy (&client->addr, &addr, sizeof addr);
|
memcpy (&client->addr, &addr, sizeof addr);
|
||||||
client->addrlen = addrlen;
|
client->addrlen = addrlen;
|
||||||
|
|
||||||
@ -1128,6 +1147,9 @@ static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud
|
|||||||
if (client->conn)
|
if (client->conn)
|
||||||
virConnectClose(client->conn);
|
virConnectClose(client->conn);
|
||||||
|
|
||||||
|
#if HAVE_SASL
|
||||||
|
if (client->saslconn) sasl_dispose(&client->saslconn);
|
||||||
|
#endif
|
||||||
if (client->tls && client->session) gnutls_deinit (client->session);
|
if (client->tls && client->session) gnutls_deinit (client->session);
|
||||||
close(client->fd);
|
close(client->fd);
|
||||||
free(client);
|
free(client);
|
||||||
|
390
qemud/remote.c
390
qemud/remote.c
@ -52,6 +52,8 @@
|
|||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
|
||||||
|
#define REMOTE_DEBUG(fmt,...) qemudDebug("REMOTE: " fmt, __VA_ARGS__)
|
||||||
|
|
||||||
static void remoteDispatchError (struct qemud_client *client,
|
static void remoteDispatchError (struct qemud_client *client,
|
||||||
remote_message_header *req,
|
remote_message_header *req,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
@ -118,6 +120,21 @@ remoteDispatchClientRequest (struct qemud_server *server ATTRIBUTE_UNUSED,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If client is marked as needing auth, don't allow any RPC ops,
|
||||||
|
* except for authentication ones
|
||||||
|
*/
|
||||||
|
if (client->auth) {
|
||||||
|
if (req.proc != REMOTE_PROC_AUTH_LIST &&
|
||||||
|
req.proc != REMOTE_PROC_AUTH_SASL_INIT &&
|
||||||
|
req.proc != REMOTE_PROC_AUTH_SASL_START &&
|
||||||
|
req.proc != REMOTE_PROC_AUTH_SASL_STEP
|
||||||
|
) {
|
||||||
|
remoteDispatchError (client, &req, "authentication required");
|
||||||
|
xdr_destroy (&xdr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Based on the procedure number, dispatch. In future we may base
|
/* Based on the procedure number, dispatch. In future we may base
|
||||||
* this on the version number as well.
|
* this on the version number as well.
|
||||||
*/
|
*/
|
||||||
@ -275,24 +292,15 @@ remoteDispatchClientRequest (struct qemud_server *server ATTRIBUTE_UNUSED,
|
|||||||
* reply.
|
* reply.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
remoteDispatchError (struct qemud_client *client,
|
remoteDispatchSendError (struct qemud_client *client,
|
||||||
remote_message_header *req,
|
remote_message_header *req,
|
||||||
const char *fmt, ...)
|
int code, const char *msg)
|
||||||
{
|
{
|
||||||
remote_message_header rep;
|
remote_message_header rep;
|
||||||
remote_error error;
|
remote_error error;
|
||||||
va_list args;
|
|
||||||
char msgbuf[1024];
|
|
||||||
char *msg = msgbuf;
|
|
||||||
XDR xdr;
|
XDR xdr;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
va_start (args, fmt);
|
|
||||||
vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
|
|
||||||
va_end (args);
|
|
||||||
|
|
||||||
qemudDebug ("%s", msgbuf);
|
|
||||||
|
|
||||||
/* Future versions of the protocol may use different vers or prog. Try
|
/* Future versions of the protocol may use different vers or prog. Try
|
||||||
* our hardest to send back a message that such clients could see.
|
* our hardest to send back a message that such clients could see.
|
||||||
*/
|
*/
|
||||||
@ -313,12 +321,12 @@ remoteDispatchError (struct qemud_client *client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the error. */
|
/* Construct the error. */
|
||||||
error.code = VIR_ERR_RPC;
|
error.code = code;
|
||||||
error.domain = VIR_FROM_REMOTE;
|
error.domain = VIR_FROM_REMOTE;
|
||||||
error.message = &msg;
|
error.message = (char**)&msg;
|
||||||
error.level = VIR_ERR_ERROR;
|
error.level = VIR_ERR_ERROR;
|
||||||
error.dom = NULL;
|
error.dom = NULL;
|
||||||
error.str1 = &msg;
|
error.str1 = (char**)&msg;
|
||||||
error.str2 = NULL;
|
error.str2 = NULL;
|
||||||
error.str3 = NULL;
|
error.str3 = NULL;
|
||||||
error.int1 = 0;
|
error.int1 = 0;
|
||||||
@ -364,6 +372,31 @@ remoteDispatchError (struct qemud_client *client,
|
|||||||
if (client->tls) client->direction = QEMUD_TLS_DIRECTION_WRITE;
|
if (client->tls) client->direction = QEMUD_TLS_DIRECTION_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remoteDispatchFailAuth (struct qemud_client *client,
|
||||||
|
remote_message_header *req)
|
||||||
|
{
|
||||||
|
remoteDispatchSendError (client, req, VIR_ERR_AUTH_FAILED, "authentication failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remoteDispatchError (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char msgbuf[1024];
|
||||||
|
char *msg = msgbuf;
|
||||||
|
|
||||||
|
va_start (args, fmt);
|
||||||
|
vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
remoteDispatchSendError (client, req, VIR_ERR_RPC, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----- Functions. -----*/
|
/*----- Functions. -----*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1946,6 +1979,335 @@ remoteDispatchNumOfNetworks (struct qemud_client *client,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthList (struct qemud_client *client,
|
||||||
|
remote_message_header *req ATTRIBUTE_UNUSED,
|
||||||
|
void *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_list_ret *ret)
|
||||||
|
{
|
||||||
|
ret->types.types_len = 1;
|
||||||
|
if ((ret->types.types_val = calloc (ret->types.types_len, sizeof (remote_auth_type))) == NULL) {
|
||||||
|
remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, "auth types");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
ret->types.types_val[0] = client->auth;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_SASL
|
||||||
|
/*
|
||||||
|
* NB, keep in sync with similar method in src/remote_internal.c
|
||||||
|
*/
|
||||||
|
static char *addrToString(struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
struct sockaddr_storage *sa, socklen_t salen) {
|
||||||
|
char host[1024], port[20];
|
||||||
|
char *addr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((err = getnameinfo((struct sockaddr *)sa, salen,
|
||||||
|
host, sizeof(host),
|
||||||
|
port, sizeof(port),
|
||||||
|
NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
|
||||||
|
remoteDispatchError(client, req,
|
||||||
|
"Cannot resolve address %d: %s", err, gai_strerror(err));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = malloc(strlen(host) + 1 + strlen(port) + 1);
|
||||||
|
if (!addr) {
|
||||||
|
remoteDispatchError(client, req, "cannot allocate address");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(addr, host);
|
||||||
|
strcat(addr, ";");
|
||||||
|
strcat(addr, port);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes the SASL session in prepare for authentication
|
||||||
|
* and gives the client a list of allowed mechansims to choose
|
||||||
|
*
|
||||||
|
* XXX callbacks for stuff like password verification ?
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthSaslInit (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
void *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_sasl_init_ret *ret)
|
||||||
|
{
|
||||||
|
const char *mechlist = NULL;
|
||||||
|
int err;
|
||||||
|
struct sockaddr_storage sa;
|
||||||
|
socklen_t salen;
|
||||||
|
char *localAddr, *remoteAddr;
|
||||||
|
|
||||||
|
REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
|
||||||
|
if (client->auth != REMOTE_AUTH_SASL ||
|
||||||
|
client->saslconn != NULL) {
|
||||||
|
qemudLog(QEMUD_ERR, "client tried invalid SASL init request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get local address in form IPADDR:PORT */
|
||||||
|
salen = sizeof(sa);
|
||||||
|
if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
|
||||||
|
remoteDispatchError(client, req, "failed to get sock address %d (%s)",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if ((localAddr = addrToString(client, req, &sa, salen)) == NULL) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get remote address in form IPADDR:PORT */
|
||||||
|
salen = sizeof(sa);
|
||||||
|
if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
|
||||||
|
remoteDispatchError(client, req, "failed to get peer address %d (%s)",
|
||||||
|
errno, strerror(errno));
|
||||||
|
free(localAddr);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if ((remoteAddr = addrToString(client, req, &sa, salen)) == NULL) {
|
||||||
|
free(localAddr);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sasl_server_new("libvirt",
|
||||||
|
NULL, /* FQDN - just delegates to gethostname */
|
||||||
|
NULL, /* User realm */
|
||||||
|
localAddr,
|
||||||
|
remoteAddr,
|
||||||
|
NULL, /* XXX Callbacks */
|
||||||
|
SASL_SUCCESS_DATA,
|
||||||
|
&client->saslconn);
|
||||||
|
free(localAddr);
|
||||||
|
free(remoteAddr);
|
||||||
|
if (err != SASL_OK) {
|
||||||
|
qemudLog(QEMUD_ERR, "sasl context setup failed %d (%s)",
|
||||||
|
err, sasl_errstring(err, NULL, NULL));
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sasl_listmech(client->saslconn,
|
||||||
|
NULL, /* Don't need to set user */
|
||||||
|
"", /* Prefix */
|
||||||
|
",", /* Separator */
|
||||||
|
"", /* Suffix */
|
||||||
|
&mechlist,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (err != SASL_OK) {
|
||||||
|
qemudLog(QEMUD_ERR, "cannot list SASL mechanisms %d (%s)",
|
||||||
|
err, sasl_errdetail(client->saslconn));
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
sasl_dispose(&client->saslconn);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
|
||||||
|
ret->mechlist = strdup(mechlist);
|
||||||
|
if (!ret->mechlist) {
|
||||||
|
qemudLog(QEMUD_ERR, "cannot allocate mechlist");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
sasl_dispose(&client->saslconn);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This starts the SASL authentication negotiation.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthSaslStart (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
remote_auth_sasl_start_args *args,
|
||||||
|
remote_auth_sasl_start_ret *ret)
|
||||||
|
{
|
||||||
|
const char *serverout;
|
||||||
|
unsigned int serveroutlen;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
REMOTE_DEBUG("Start SASL auth %d", client->fd);
|
||||||
|
if (client->auth != REMOTE_AUTH_SASL ||
|
||||||
|
client->saslconn == NULL) {
|
||||||
|
qemudLog(QEMUD_ERR, "client tried invalid SASL start request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
REMOTE_DEBUG("Using SASL mechanism %s. Data %d bytes, nil: %d",
|
||||||
|
args->mech, args->data.data_len, args->nil);
|
||||||
|
err = sasl_server_start(client->saslconn,
|
||||||
|
args->mech,
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
args->nil ? NULL : args->data.data_val,
|
||||||
|
args->data.data_len,
|
||||||
|
&serverout,
|
||||||
|
&serveroutlen);
|
||||||
|
if (err != SASL_OK &&
|
||||||
|
err != SASL_CONTINUE) {
|
||||||
|
qemudLog(QEMUD_ERR, "sasl start failed %d (%s)",
|
||||||
|
err, sasl_errdetail(client->saslconn));
|
||||||
|
sasl_dispose(&client->saslconn);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
|
||||||
|
qemudLog(QEMUD_ERR, "sasl start reply data too long %d", serveroutlen);
|
||||||
|
sasl_dispose(&client->saslconn);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
if (serverout) {
|
||||||
|
ret->data.data_val = malloc(serveroutlen);
|
||||||
|
if (!ret->data.data_val) {
|
||||||
|
remoteDispatchError (client, req, "out of memory allocating array");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
memcpy(ret->data.data_val, serverout, serveroutlen);
|
||||||
|
} else {
|
||||||
|
ret->data.data_val = NULL;
|
||||||
|
}
|
||||||
|
ret->nil = serverout ? 0 : 1;
|
||||||
|
ret->data.data_len = serveroutlen;
|
||||||
|
|
||||||
|
REMOTE_DEBUG("SASL return data %d bytes, nil; %d", ret->data.data_len, ret->nil);
|
||||||
|
if (err == SASL_CONTINUE) {
|
||||||
|
ret->complete = 0;
|
||||||
|
} else {
|
||||||
|
REMOTE_DEBUG("Authentication successful %d", client->fd);
|
||||||
|
ret->complete = 1;
|
||||||
|
client->auth = REMOTE_AUTH_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthSaslStep (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
remote_auth_sasl_step_args *args,
|
||||||
|
remote_auth_sasl_step_ret *ret)
|
||||||
|
{
|
||||||
|
const char *serverout;
|
||||||
|
unsigned int serveroutlen;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
REMOTE_DEBUG("Step SASL auth %d", client->fd);
|
||||||
|
if (client->auth != REMOTE_AUTH_SASL ||
|
||||||
|
client->saslconn == NULL) {
|
||||||
|
qemudLog(QEMUD_ERR, "client tried invalid SASL start request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
REMOTE_DEBUG("Using SASL Data %d bytes, nil: %d",
|
||||||
|
args->data.data_len, args->nil);
|
||||||
|
err = sasl_server_step(client->saslconn,
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
args->nil ? NULL : args->data.data_val,
|
||||||
|
args->data.data_len,
|
||||||
|
&serverout,
|
||||||
|
&serveroutlen);
|
||||||
|
if (err != SASL_OK &&
|
||||||
|
err != SASL_CONTINUE) {
|
||||||
|
qemudLog(QEMUD_ERR, "sasl step failed %d (%s)",
|
||||||
|
err, sasl_errdetail(client->saslconn));
|
||||||
|
sasl_dispose(&client->saslconn);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
|
||||||
|
qemudLog(QEMUD_ERR, "sasl step reply data too long %d", serveroutlen);
|
||||||
|
sasl_dispose(&client->saslconn);
|
||||||
|
client->saslconn = NULL;
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
if (serverout) {
|
||||||
|
ret->data.data_val = malloc(serveroutlen);
|
||||||
|
if (!ret->data.data_val) {
|
||||||
|
remoteDispatchError (client, req, "out of memory allocating array");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
memcpy(ret->data.data_val, serverout, serveroutlen);
|
||||||
|
} else {
|
||||||
|
ret->data.data_val = NULL;
|
||||||
|
}
|
||||||
|
ret->nil = serverout ? 0 : 1;
|
||||||
|
ret->data.data_len = serveroutlen;
|
||||||
|
|
||||||
|
REMOTE_DEBUG("SASL return data %d bytes, nil; %d", ret->data.data_len, ret->nil);
|
||||||
|
if (err == SASL_CONTINUE) {
|
||||||
|
ret->complete = 0;
|
||||||
|
} else {
|
||||||
|
REMOTE_DEBUG("Authentication successful %d", client->fd);
|
||||||
|
ret->complete = 1;
|
||||||
|
client->auth = REMOTE_AUTH_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else /* HAVE_SASL */
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthSaslInit (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
void *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
qemudLog(QEMUD_ERR, "client tried unsupported SASL init request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthSaslStart (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
qemudLog(QEMUD_ERR, "client tried unsupported SASL start request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthSaslStep (struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
qemudLog(QEMUD_ERR, "client tried unsupported SASL step request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SASL */
|
||||||
|
|
||||||
|
|
||||||
/*----- Helpers. -----*/
|
/*----- Helpers. -----*/
|
||||||
|
|
||||||
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
||||||
|
@ -9,6 +9,7 @@ remote_list_defined_domains_args lv_remote_list_defined_domains_args;
|
|||||||
remote_list_defined_domains_ret lv_remote_list_defined_domains_ret;
|
remote_list_defined_domains_ret lv_remote_list_defined_domains_ret;
|
||||||
remote_get_capabilities_ret lv_remote_get_capabilities_ret;
|
remote_get_capabilities_ret lv_remote_get_capabilities_ret;
|
||||||
remote_domain_set_max_memory_args lv_remote_domain_set_max_memory_args;
|
remote_domain_set_max_memory_args lv_remote_domain_set_max_memory_args;
|
||||||
|
remote_auth_sasl_init_ret lv_remote_auth_sasl_init_ret;
|
||||||
remote_domain_get_os_type_args lv_remote_domain_get_os_type_args;
|
remote_domain_get_os_type_args lv_remote_domain_get_os_type_args;
|
||||||
remote_domain_get_os_type_ret lv_remote_domain_get_os_type_ret;
|
remote_domain_get_os_type_ret lv_remote_domain_get_os_type_ret;
|
||||||
remote_domain_get_autostart_args lv_remote_domain_get_autostart_args;
|
remote_domain_get_autostart_args lv_remote_domain_get_autostart_args;
|
||||||
@ -36,6 +37,8 @@ remote_domain_set_memory_args lv_remote_domain_set_memory_args;
|
|||||||
remote_domain_create_linux_args lv_remote_domain_create_linux_args;
|
remote_domain_create_linux_args lv_remote_domain_create_linux_args;
|
||||||
remote_domain_create_linux_ret lv_remote_domain_create_linux_ret;
|
remote_domain_create_linux_ret lv_remote_domain_create_linux_ret;
|
||||||
remote_domain_set_scheduler_parameters_args lv_remote_domain_set_scheduler_parameters_args;
|
remote_domain_set_scheduler_parameters_args lv_remote_domain_set_scheduler_parameters_args;
|
||||||
|
remote_auth_sasl_start_args lv_remote_auth_sasl_start_args;
|
||||||
|
remote_auth_sasl_start_ret lv_remote_auth_sasl_start_ret;
|
||||||
remote_domain_interface_stats_args lv_remote_domain_interface_stats_args;
|
remote_domain_interface_stats_args lv_remote_domain_interface_stats_args;
|
||||||
remote_domain_interface_stats_ret lv_remote_domain_interface_stats_ret;
|
remote_domain_interface_stats_ret lv_remote_domain_interface_stats_ret;
|
||||||
remote_domain_get_max_vcpus_args lv_remote_domain_get_max_vcpus_args;
|
remote_domain_get_max_vcpus_args lv_remote_domain_get_max_vcpus_args;
|
||||||
@ -50,6 +53,8 @@ remote_domain_resume_args lv_remote_domain_resume_args;
|
|||||||
remote_network_get_bridge_name_args lv_remote_network_get_bridge_name_args;
|
remote_network_get_bridge_name_args lv_remote_network_get_bridge_name_args;
|
||||||
remote_network_get_bridge_name_ret lv_remote_network_get_bridge_name_ret;
|
remote_network_get_bridge_name_ret lv_remote_network_get_bridge_name_ret;
|
||||||
remote_domain_destroy_args lv_remote_domain_destroy_args;
|
remote_domain_destroy_args lv_remote_domain_destroy_args;
|
||||||
|
remote_auth_sasl_step_args lv_remote_auth_sasl_step_args;
|
||||||
|
remote_auth_sasl_step_ret lv_remote_auth_sasl_step_ret;
|
||||||
remote_domain_migrate_finish_args lv_remote_domain_migrate_finish_args;
|
remote_domain_migrate_finish_args lv_remote_domain_migrate_finish_args;
|
||||||
remote_domain_migrate_finish_ret lv_remote_domain_migrate_finish_ret;
|
remote_domain_migrate_finish_ret lv_remote_domain_migrate_finish_ret;
|
||||||
remote_domain_get_vcpus_args lv_remote_domain_get_vcpus_args;
|
remote_domain_get_vcpus_args lv_remote_domain_get_vcpus_args;
|
||||||
@ -74,6 +79,7 @@ remote_domain_suspend_args lv_remote_domain_suspend_args;
|
|||||||
remote_network_set_autostart_args lv_remote_network_set_autostart_args;
|
remote_network_set_autostart_args lv_remote_network_set_autostart_args;
|
||||||
remote_network_get_autostart_args lv_remote_network_get_autostart_args;
|
remote_network_get_autostart_args lv_remote_network_get_autostart_args;
|
||||||
remote_network_get_autostart_ret lv_remote_network_get_autostart_ret;
|
remote_network_get_autostart_ret lv_remote_network_get_autostart_ret;
|
||||||
|
remote_auth_list_ret lv_remote_auth_list_ret;
|
||||||
remote_domain_core_dump_args lv_remote_domain_core_dump_args;
|
remote_domain_core_dump_args lv_remote_domain_core_dump_args;
|
||||||
remote_domain_get_max_memory_args lv_remote_domain_get_max_memory_args;
|
remote_domain_get_max_memory_args lv_remote_domain_get_max_memory_args;
|
||||||
remote_domain_get_max_memory_ret lv_remote_domain_get_max_memory_ret;
|
remote_domain_get_max_memory_ret lv_remote_domain_get_max_memory_ret;
|
||||||
|
@ -2,6 +2,36 @@
|
|||||||
* Do not edit this file. Any changes you make will be lost.
|
* Do not edit this file. Any changes you make will be lost.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
case REMOTE_PROC_AUTH_LIST:
|
||||||
|
fn = (dispatch_fn) remoteDispatchAuthList;
|
||||||
|
ret_filter = (xdrproc_t) xdr_remote_auth_list_ret;
|
||||||
|
ret = (char *) &lv_remote_auth_list_ret;
|
||||||
|
memset (&lv_remote_auth_list_ret, 0, sizeof lv_remote_auth_list_ret);
|
||||||
|
break;
|
||||||
|
case REMOTE_PROC_AUTH_SASL_INIT:
|
||||||
|
fn = (dispatch_fn) remoteDispatchAuthSaslInit;
|
||||||
|
ret_filter = (xdrproc_t) xdr_remote_auth_sasl_init_ret;
|
||||||
|
ret = (char *) &lv_remote_auth_sasl_init_ret;
|
||||||
|
memset (&lv_remote_auth_sasl_init_ret, 0, sizeof lv_remote_auth_sasl_init_ret);
|
||||||
|
break;
|
||||||
|
case REMOTE_PROC_AUTH_SASL_START:
|
||||||
|
fn = (dispatch_fn) remoteDispatchAuthSaslStart;
|
||||||
|
args_filter = (xdrproc_t) xdr_remote_auth_sasl_start_args;
|
||||||
|
args = (char *) &lv_remote_auth_sasl_start_args;
|
||||||
|
memset (&lv_remote_auth_sasl_start_args, 0, sizeof lv_remote_auth_sasl_start_args);
|
||||||
|
ret_filter = (xdrproc_t) xdr_remote_auth_sasl_start_ret;
|
||||||
|
ret = (char *) &lv_remote_auth_sasl_start_ret;
|
||||||
|
memset (&lv_remote_auth_sasl_start_ret, 0, sizeof lv_remote_auth_sasl_start_ret);
|
||||||
|
break;
|
||||||
|
case REMOTE_PROC_AUTH_SASL_STEP:
|
||||||
|
fn = (dispatch_fn) remoteDispatchAuthSaslStep;
|
||||||
|
args_filter = (xdrproc_t) xdr_remote_auth_sasl_step_args;
|
||||||
|
args = (char *) &lv_remote_auth_sasl_step_args;
|
||||||
|
memset (&lv_remote_auth_sasl_step_args, 0, sizeof lv_remote_auth_sasl_step_args);
|
||||||
|
ret_filter = (xdrproc_t) xdr_remote_auth_sasl_step_ret;
|
||||||
|
ret = (char *) &lv_remote_auth_sasl_step_ret;
|
||||||
|
memset (&lv_remote_auth_sasl_step_ret, 0, sizeof lv_remote_auth_sasl_step_ret);
|
||||||
|
break;
|
||||||
case REMOTE_PROC_CLOSE:
|
case REMOTE_PROC_CLOSE:
|
||||||
fn = (dispatch_fn) remoteDispatchClose;
|
fn = (dispatch_fn) remoteDispatchClose;
|
||||||
break;
|
break;
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
* Do not edit this file. Any changes you make will be lost.
|
* Do not edit this file. Any changes you make will be lost.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static int remoteDispatchAuthList (struct qemud_client *client, remote_message_header *req, void *args, remote_auth_list_ret *ret);
|
||||||
|
static int remoteDispatchAuthSaslInit (struct qemud_client *client, remote_message_header *req, void *args, remote_auth_sasl_init_ret *ret);
|
||||||
|
static int remoteDispatchAuthSaslStart (struct qemud_client *client, remote_message_header *req, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret);
|
||||||
|
static int remoteDispatchAuthSaslStep (struct qemud_client *client, remote_message_header *req, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret);
|
||||||
static int remoteDispatchClose (struct qemud_client *client, remote_message_header *req, void *args, void *ret);
|
static int remoteDispatchClose (struct qemud_client *client, remote_message_header *req, void *args, void *ret);
|
||||||
static int remoteDispatchDomainAttachDevice (struct qemud_client *client, remote_message_header *req, remote_domain_attach_device_args *args, void *ret);
|
static int remoteDispatchDomainAttachDevice (struct qemud_client *client, remote_message_header *req, remote_domain_attach_device_args *args, void *ret);
|
||||||
static int remoteDispatchDomainBlockStats (struct qemud_client *client, remote_message_header *req, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret);
|
static int remoteDispatchDomainBlockStats (struct qemud_client *client, remote_message_header *req, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret);
|
||||||
|
@ -104,6 +104,15 @@ xdr_remote_error (XDR *xdrs, remote_error *objp)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_type (XDR *xdrs, remote_auth_type *objp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!xdr_enum (xdrs, (enum_t *) objp))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
bool_t
|
bool_t
|
||||||
xdr_remote_vcpu_info (XDR *xdrs, remote_vcpu_info *objp)
|
xdr_remote_vcpu_info (XDR *xdrs, remote_vcpu_info *objp)
|
||||||
{
|
{
|
||||||
@ -1221,6 +1230,84 @@ xdr_remote_network_set_autostart_args (XDR *xdrs, remote_network_set_autostart_a
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_list_ret (XDR *xdrs, remote_auth_list_ret *objp)
|
||||||
|
{
|
||||||
|
char **objp_cpp0 = (char **) (void *) &objp->types.types_val;
|
||||||
|
|
||||||
|
if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->types.types_len, REMOTE_AUTH_TYPE_LIST_MAX,
|
||||||
|
sizeof (remote_auth_type), (xdrproc_t) xdr_remote_auth_type))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_sasl_init_ret (XDR *xdrs, remote_auth_sasl_init_ret *objp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!xdr_remote_nonnull_string (xdrs, &objp->mechlist))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_sasl_start_args (XDR *xdrs, remote_auth_sasl_start_args *objp)
|
||||||
|
{
|
||||||
|
char **objp_cpp0 = (char **) (void *) &objp->data.data_val;
|
||||||
|
|
||||||
|
if (!xdr_remote_nonnull_string (xdrs, &objp->mech))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_int (xdrs, &objp->nil))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->data.data_len, REMOTE_AUTH_SASL_DATA_MAX,
|
||||||
|
sizeof (char), (xdrproc_t) xdr_char))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_sasl_start_ret (XDR *xdrs, remote_auth_sasl_start_ret *objp)
|
||||||
|
{
|
||||||
|
char **objp_cpp0 = (char **) (void *) &objp->data.data_val;
|
||||||
|
|
||||||
|
if (!xdr_int (xdrs, &objp->complete))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_int (xdrs, &objp->nil))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->data.data_len, REMOTE_AUTH_SASL_DATA_MAX,
|
||||||
|
sizeof (char), (xdrproc_t) xdr_char))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_sasl_step_args (XDR *xdrs, remote_auth_sasl_step_args *objp)
|
||||||
|
{
|
||||||
|
char **objp_cpp0 = (char **) (void *) &objp->data.data_val;
|
||||||
|
|
||||||
|
if (!xdr_int (xdrs, &objp->nil))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->data.data_len, REMOTE_AUTH_SASL_DATA_MAX,
|
||||||
|
sizeof (char), (xdrproc_t) xdr_char))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_sasl_step_ret (XDR *xdrs, remote_auth_sasl_step_ret *objp)
|
||||||
|
{
|
||||||
|
char **objp_cpp0 = (char **) (void *) &objp->data.data_val;
|
||||||
|
|
||||||
|
if (!xdr_int (xdrs, &objp->complete))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_int (xdrs, &objp->nil))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->data.data_len, REMOTE_AUTH_SASL_DATA_MAX,
|
||||||
|
sizeof (char), (xdrproc_t) xdr_char))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
bool_t
|
bool_t
|
||||||
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
|
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,8 @@ typedef remote_nonnull_string *remote_string;
|
|||||||
#define REMOTE_MIGRATE_COOKIE_MAX 256
|
#define REMOTE_MIGRATE_COOKIE_MAX 256
|
||||||
#define REMOTE_NETWORK_NAME_LIST_MAX 256
|
#define REMOTE_NETWORK_NAME_LIST_MAX 256
|
||||||
#define REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX 16
|
#define REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX 16
|
||||||
|
#define REMOTE_AUTH_SASL_DATA_MAX 65536
|
||||||
|
#define REMOTE_AUTH_TYPE_LIST_MAX 20
|
||||||
|
|
||||||
typedef char remote_uuid[VIR_UUID_BUFLEN];
|
typedef char remote_uuid[VIR_UUID_BUFLEN];
|
||||||
|
|
||||||
@ -63,6 +65,12 @@ struct remote_error {
|
|||||||
};
|
};
|
||||||
typedef struct remote_error remote_error;
|
typedef struct remote_error remote_error;
|
||||||
|
|
||||||
|
enum remote_auth_type {
|
||||||
|
REMOTE_AUTH_NONE = 0,
|
||||||
|
REMOTE_AUTH_SASL = 1,
|
||||||
|
};
|
||||||
|
typedef enum remote_auth_type remote_auth_type;
|
||||||
|
|
||||||
struct remote_vcpu_info {
|
struct remote_vcpu_info {
|
||||||
u_int number;
|
u_int number;
|
||||||
int state;
|
int state;
|
||||||
@ -659,6 +667,58 @@ struct remote_network_set_autostart_args {
|
|||||||
int autostart;
|
int autostart;
|
||||||
};
|
};
|
||||||
typedef struct remote_network_set_autostart_args remote_network_set_autostart_args;
|
typedef struct remote_network_set_autostart_args remote_network_set_autostart_args;
|
||||||
|
|
||||||
|
struct remote_auth_list_ret {
|
||||||
|
struct {
|
||||||
|
u_int types_len;
|
||||||
|
remote_auth_type *types_val;
|
||||||
|
} types;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_list_ret remote_auth_list_ret;
|
||||||
|
|
||||||
|
struct remote_auth_sasl_init_ret {
|
||||||
|
remote_nonnull_string mechlist;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_sasl_init_ret remote_auth_sasl_init_ret;
|
||||||
|
|
||||||
|
struct remote_auth_sasl_start_args {
|
||||||
|
remote_nonnull_string mech;
|
||||||
|
int nil;
|
||||||
|
struct {
|
||||||
|
u_int data_len;
|
||||||
|
char *data_val;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_sasl_start_args remote_auth_sasl_start_args;
|
||||||
|
|
||||||
|
struct remote_auth_sasl_start_ret {
|
||||||
|
int complete;
|
||||||
|
int nil;
|
||||||
|
struct {
|
||||||
|
u_int data_len;
|
||||||
|
char *data_val;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_sasl_start_ret remote_auth_sasl_start_ret;
|
||||||
|
|
||||||
|
struct remote_auth_sasl_step_args {
|
||||||
|
int nil;
|
||||||
|
struct {
|
||||||
|
u_int data_len;
|
||||||
|
char *data_val;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_sasl_step_args remote_auth_sasl_step_args;
|
||||||
|
|
||||||
|
struct remote_auth_sasl_step_ret {
|
||||||
|
int complete;
|
||||||
|
int nil;
|
||||||
|
struct {
|
||||||
|
u_int data_len;
|
||||||
|
char *data_val;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_sasl_step_ret remote_auth_sasl_step_ret;
|
||||||
#define REMOTE_PROGRAM 0x20008086
|
#define REMOTE_PROGRAM 0x20008086
|
||||||
#define REMOTE_PROTOCOL_VERSION 1
|
#define REMOTE_PROTOCOL_VERSION 1
|
||||||
|
|
||||||
@ -728,6 +788,10 @@ enum remote_procedure {
|
|||||||
REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
|
REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
|
||||||
REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
|
REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
|
||||||
REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65,
|
REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65,
|
||||||
|
REMOTE_PROC_AUTH_LIST = 66,
|
||||||
|
REMOTE_PROC_AUTH_SASL_INIT = 67,
|
||||||
|
REMOTE_PROC_AUTH_SASL_START = 68,
|
||||||
|
REMOTE_PROC_AUTH_SASL_STEP = 69,
|
||||||
};
|
};
|
||||||
typedef enum remote_procedure remote_procedure;
|
typedef enum remote_procedure remote_procedure;
|
||||||
|
|
||||||
@ -766,6 +830,7 @@ extern bool_t xdr_remote_nonnull_network (XDR *, remote_nonnull_network*);
|
|||||||
extern bool_t xdr_remote_domain (XDR *, remote_domain*);
|
extern bool_t xdr_remote_domain (XDR *, remote_domain*);
|
||||||
extern bool_t xdr_remote_network (XDR *, remote_network*);
|
extern bool_t xdr_remote_network (XDR *, remote_network*);
|
||||||
extern bool_t xdr_remote_error (XDR *, remote_error*);
|
extern bool_t xdr_remote_error (XDR *, remote_error*);
|
||||||
|
extern bool_t xdr_remote_auth_type (XDR *, remote_auth_type*);
|
||||||
extern bool_t xdr_remote_vcpu_info (XDR *, remote_vcpu_info*);
|
extern bool_t xdr_remote_vcpu_info (XDR *, remote_vcpu_info*);
|
||||||
extern bool_t xdr_remote_sched_param_value (XDR *, remote_sched_param_value*);
|
extern bool_t xdr_remote_sched_param_value (XDR *, remote_sched_param_value*);
|
||||||
extern bool_t xdr_remote_sched_param (XDR *, remote_sched_param*);
|
extern bool_t xdr_remote_sched_param (XDR *, remote_sched_param*);
|
||||||
@ -864,6 +929,12 @@ extern bool_t xdr_remote_network_get_bridge_name_ret (XDR *, remote_network_get
|
|||||||
extern bool_t xdr_remote_network_get_autostart_args (XDR *, remote_network_get_autostart_args*);
|
extern bool_t xdr_remote_network_get_autostart_args (XDR *, remote_network_get_autostart_args*);
|
||||||
extern bool_t xdr_remote_network_get_autostart_ret (XDR *, remote_network_get_autostart_ret*);
|
extern bool_t xdr_remote_network_get_autostart_ret (XDR *, remote_network_get_autostart_ret*);
|
||||||
extern bool_t xdr_remote_network_set_autostart_args (XDR *, remote_network_set_autostart_args*);
|
extern bool_t xdr_remote_network_set_autostart_args (XDR *, remote_network_set_autostart_args*);
|
||||||
|
extern bool_t xdr_remote_auth_list_ret (XDR *, remote_auth_list_ret*);
|
||||||
|
extern bool_t xdr_remote_auth_sasl_init_ret (XDR *, remote_auth_sasl_init_ret*);
|
||||||
|
extern bool_t xdr_remote_auth_sasl_start_args (XDR *, remote_auth_sasl_start_args*);
|
||||||
|
extern bool_t xdr_remote_auth_sasl_start_ret (XDR *, remote_auth_sasl_start_ret*);
|
||||||
|
extern bool_t xdr_remote_auth_sasl_step_args (XDR *, remote_auth_sasl_step_args*);
|
||||||
|
extern bool_t xdr_remote_auth_sasl_step_ret (XDR *, remote_auth_sasl_step_ret*);
|
||||||
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
|
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
|
||||||
extern bool_t xdr_remote_message_direction (XDR *, remote_message_direction*);
|
extern bool_t xdr_remote_message_direction (XDR *, remote_message_direction*);
|
||||||
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
|
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
|
||||||
@ -878,6 +949,7 @@ extern bool_t xdr_remote_nonnull_network ();
|
|||||||
extern bool_t xdr_remote_domain ();
|
extern bool_t xdr_remote_domain ();
|
||||||
extern bool_t xdr_remote_network ();
|
extern bool_t xdr_remote_network ();
|
||||||
extern bool_t xdr_remote_error ();
|
extern bool_t xdr_remote_error ();
|
||||||
|
extern bool_t xdr_remote_auth_type ();
|
||||||
extern bool_t xdr_remote_vcpu_info ();
|
extern bool_t xdr_remote_vcpu_info ();
|
||||||
extern bool_t xdr_remote_sched_param_value ();
|
extern bool_t xdr_remote_sched_param_value ();
|
||||||
extern bool_t xdr_remote_sched_param ();
|
extern bool_t xdr_remote_sched_param ();
|
||||||
@ -976,6 +1048,12 @@ extern bool_t xdr_remote_network_get_bridge_name_ret ();
|
|||||||
extern bool_t xdr_remote_network_get_autostart_args ();
|
extern bool_t xdr_remote_network_get_autostart_args ();
|
||||||
extern bool_t xdr_remote_network_get_autostart_ret ();
|
extern bool_t xdr_remote_network_get_autostart_ret ();
|
||||||
extern bool_t xdr_remote_network_set_autostart_args ();
|
extern bool_t xdr_remote_network_set_autostart_args ();
|
||||||
|
extern bool_t xdr_remote_auth_list_ret ();
|
||||||
|
extern bool_t xdr_remote_auth_sasl_init_ret ();
|
||||||
|
extern bool_t xdr_remote_auth_sasl_start_args ();
|
||||||
|
extern bool_t xdr_remote_auth_sasl_start_ret ();
|
||||||
|
extern bool_t xdr_remote_auth_sasl_step_args ();
|
||||||
|
extern bool_t xdr_remote_auth_sasl_step_ret ();
|
||||||
extern bool_t xdr_remote_procedure ();
|
extern bool_t xdr_remote_procedure ();
|
||||||
extern bool_t xdr_remote_message_direction ();
|
extern bool_t xdr_remote_message_direction ();
|
||||||
extern bool_t xdr_remote_message_status ();
|
extern bool_t xdr_remote_message_status ();
|
||||||
|
@ -81,6 +81,12 @@ const REMOTE_NETWORK_NAME_LIST_MAX = 256;
|
|||||||
/* Upper limit on list of scheduler parameters. */
|
/* Upper limit on list of scheduler parameters. */
|
||||||
const REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX = 16;
|
const REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX = 16;
|
||||||
|
|
||||||
|
/* Upper limit on SASL auth negotiation packet */
|
||||||
|
const REMOTE_AUTH_SASL_DATA_MAX = 65536;
|
||||||
|
|
||||||
|
/* Maximum number of auth types */
|
||||||
|
const REMOTE_AUTH_TYPE_LIST_MAX = 20;
|
||||||
|
|
||||||
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
|
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
|
||||||
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
|
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
|
||||||
|
|
||||||
@ -123,6 +129,13 @@ struct remote_error {
|
|||||||
remote_network net;
|
remote_network net;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Authentication types available thus far.... */
|
||||||
|
enum remote_auth_type {
|
||||||
|
REMOTE_AUTH_NONE = 0,
|
||||||
|
REMOTE_AUTH_SASL = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Wire encoding of virVcpuInfo. */
|
/* Wire encoding of virVcpuInfo. */
|
||||||
struct remote_vcpu_info {
|
struct remote_vcpu_info {
|
||||||
unsigned int number;
|
unsigned int number;
|
||||||
@ -612,6 +625,37 @@ struct remote_network_set_autostart_args {
|
|||||||
int autostart;
|
int autostart;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct remote_auth_list_ret {
|
||||||
|
remote_auth_type types<REMOTE_AUTH_TYPE_LIST_MAX>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct remote_auth_sasl_init_ret {
|
||||||
|
remote_nonnull_string mechlist;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct remote_auth_sasl_start_args {
|
||||||
|
remote_nonnull_string mech;
|
||||||
|
int nil;
|
||||||
|
char data<REMOTE_AUTH_SASL_DATA_MAX>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct remote_auth_sasl_start_ret {
|
||||||
|
int complete;
|
||||||
|
int nil;
|
||||||
|
char data<REMOTE_AUTH_SASL_DATA_MAX>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct remote_auth_sasl_step_args {
|
||||||
|
int nil;
|
||||||
|
char data<REMOTE_AUTH_SASL_DATA_MAX>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct remote_auth_sasl_step_ret {
|
||||||
|
int complete;
|
||||||
|
int nil;
|
||||||
|
char data<REMOTE_AUTH_SASL_DATA_MAX>;
|
||||||
|
};
|
||||||
|
|
||||||
/*----- Protocol. -----*/
|
/*----- Protocol. -----*/
|
||||||
|
|
||||||
/* Define the program number, protocol version and procedure numbers here. */
|
/* Define the program number, protocol version and procedure numbers here. */
|
||||||
@ -683,7 +727,11 @@ enum remote_procedure {
|
|||||||
REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62,
|
REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62,
|
||||||
REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
|
REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
|
||||||
REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
|
REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
|
||||||
REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65
|
REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65,
|
||||||
|
REMOTE_PROC_AUTH_LIST = 66,
|
||||||
|
REMOTE_PROC_AUTH_SASL_INIT = 67,
|
||||||
|
REMOTE_PROC_AUTH_SASL_START = 68,
|
||||||
|
REMOTE_PROC_AUTH_SASL_STEP = 69
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Custom RPC structure. */
|
/* Custom RPC structure. */
|
||||||
|
@ -5,6 +5,7 @@ INCLUDES = -I$(top_builddir)/include \
|
|||||||
-I@top_srcdir@/qemud \
|
-I@top_srcdir@/qemud \
|
||||||
$(LIBXML_CFLAGS) \
|
$(LIBXML_CFLAGS) \
|
||||||
$(GNUTLS_CFLAGS) \
|
$(GNUTLS_CFLAGS) \
|
||||||
|
$(SASL_CFLAGS) \
|
||||||
-DBINDIR=\""$(libexecdir)"\" \
|
-DBINDIR=\""$(libexecdir)"\" \
|
||||||
-DSBINDIR=\""$(sbindir)"\" \
|
-DSBINDIR=\""$(sbindir)"\" \
|
||||||
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
|
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
|
||||||
@ -59,7 +60,7 @@ SERVER_SOURCES = \
|
|||||||
../qemud/remote_protocol.c ../qemud/remote_protocol.h
|
../qemud/remote_protocol.c ../qemud/remote_protocol.h
|
||||||
|
|
||||||
libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
|
libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
|
||||||
libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(LTLIBOBJS) \
|
libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) $(LTLIBOBJS) \
|
||||||
@CYGWIN_EXTRA_LIBADD@
|
@CYGWIN_EXTRA_LIBADD@
|
||||||
libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \
|
libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \
|
||||||
-version-info @LIBVIRT_VERSION_INFO@ \
|
-version-info @LIBVIRT_VERSION_INFO@ \
|
||||||
|
@ -48,6 +48,9 @@
|
|||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
#include <gnutls/x509.h>
|
#include <gnutls/x509.h>
|
||||||
#include "gnutls_1_0_compat.h"
|
#include "gnutls_1_0_compat.h"
|
||||||
|
#if HAVE_SASL
|
||||||
|
#include <sasl/sasl.h>
|
||||||
|
#endif
|
||||||
#include <libxml/uri.h>
|
#include <libxml/uri.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@ -72,6 +75,11 @@ struct private_data {
|
|||||||
char *type; /* Cached return from remoteType. */
|
char *type; /* Cached return from remoteType. */
|
||||||
int counter; /* Generates serial numbers for RPC. */
|
int counter; /* Generates serial numbers for RPC. */
|
||||||
int networkOnly; /* Only used for network API */
|
int networkOnly; /* Only used for network API */
|
||||||
|
char *hostname; /* Original hostname */
|
||||||
|
FILE *debugLog; /* Debug remote protocol */
|
||||||
|
#if HAVE_SASL
|
||||||
|
sasl_conn_t *saslconn; /* SASL context */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_PRIVATE(conn,retcode) \
|
#define GET_PRIVATE(conn,retcode) \
|
||||||
@ -90,7 +98,20 @@ struct private_data {
|
|||||||
return (retcode); \
|
return (retcode); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static int call (virConnectPtr conn, struct private_data *priv, int in_open, int proc_nr, xdrproc_t args_filter, char *args, xdrproc_t ret_filter, char *ret);
|
enum {
|
||||||
|
REMOTE_CALL_IN_OPEN = 1,
|
||||||
|
REMOTE_CALL_QUIET_MISSING_RPC = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int call (virConnectPtr conn, struct private_data *priv,
|
||||||
|
int flags, int proc_nr,
|
||||||
|
xdrproc_t args_filter, char *args,
|
||||||
|
xdrproc_t ret_filter, char *ret);
|
||||||
|
static int remoteAuthenticate (virConnectPtr conn, struct private_data *priv, int in_open);
|
||||||
|
#if HAVE_SASL
|
||||||
|
static int remoteAuthSASL (virConnectPtr conn, struct private_data *priv, int in_open);
|
||||||
|
#endif
|
||||||
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
||||||
static void server_error (virConnectPtr conn, remote_error *err);
|
static void server_error (virConnectPtr conn, remote_error *err);
|
||||||
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
|
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
|
||||||
@ -121,7 +142,7 @@ static void query_free (struct query_fields *fields);
|
|||||||
|
|
||||||
/* GnuTLS functions used by remoteOpen. */
|
/* GnuTLS functions used by remoteOpen. */
|
||||||
static int initialise_gnutls (virConnectPtr conn);
|
static int initialise_gnutls (virConnectPtr conn);
|
||||||
static gnutls_session_t negotiate_gnutls_on_connection (virConnectPtr conn, int sock, int no_verify, const char *hostname);
|
static gnutls_session_t negotiate_gnutls_on_connection (virConnectPtr conn, struct private_data *priv, int no_verify);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remoteStartup(void)
|
remoteStartup(void)
|
||||||
@ -133,6 +154,22 @@ remoteStartup(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_SASL
|
||||||
|
static void
|
||||||
|
remoteDebug(struct private_data *priv, const char *msg,...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
if (priv->debugLog == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(args, msg);
|
||||||
|
vfprintf(priv->debugLog, msg, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(priv->debugLog, "\n");
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SASL */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remoteFindServerPath:
|
* remoteFindServerPath:
|
||||||
*
|
*
|
||||||
@ -297,7 +334,7 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
* get freed in the failed: path.
|
* get freed in the failed: path.
|
||||||
*/
|
*/
|
||||||
char *name = 0, *command = 0, *sockname = 0, *netcat = 0, *username = 0;
|
char *name = 0, *command = 0, *sockname = 0, *netcat = 0, *username = 0;
|
||||||
char *server = 0, *port = 0;
|
char *port = 0;
|
||||||
int no_verify = 0, no_tty = 0;
|
int no_verify = 0, no_tty = 0;
|
||||||
char **cmd_argv = 0;
|
char **cmd_argv = 0;
|
||||||
|
|
||||||
@ -305,12 +342,6 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
int retcode = VIR_DRV_OPEN_ERROR;
|
int retcode = VIR_DRV_OPEN_ERROR;
|
||||||
|
|
||||||
/* Remote server defaults to "localhost" if not specified. */
|
/* Remote server defaults to "localhost" if not specified. */
|
||||||
server = strdup (uri->server ? uri->server : "localhost");
|
|
||||||
if (!server) {
|
|
||||||
out_of_memory:
|
|
||||||
error (conn, VIR_ERR_NO_MEMORY, "duplicating server name");
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
if (uri->port != 0) {
|
if (uri->port != 0) {
|
||||||
if (asprintf (&port, "%d", uri->port) == -1) goto out_of_memory;
|
if (asprintf (&port, "%d", uri->port) == -1) goto out_of_memory;
|
||||||
} else if (transport == trans_tls) {
|
} else if (transport == trans_tls) {
|
||||||
@ -325,6 +356,12 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
} else
|
} else
|
||||||
port = NULL; /* Port not used for unix, ext. */
|
port = NULL; /* Port not used for unix, ext. */
|
||||||
|
|
||||||
|
|
||||||
|
priv->hostname = strdup (uri->server ? uri->server : "localhost");
|
||||||
|
if (!priv->hostname) {
|
||||||
|
error (NULL, VIR_ERR_NO_MEMORY, "allocating priv->hostname");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
if (uri->user) {
|
if (uri->user) {
|
||||||
username = strdup (uri->user);
|
username = strdup (uri->user);
|
||||||
if (!username) goto out_of_memory;
|
if (!username) goto out_of_memory;
|
||||||
@ -367,6 +404,12 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
} else if (strcasecmp (var->name, "no_tty") == 0) {
|
} else if (strcasecmp (var->name, "no_tty") == 0) {
|
||||||
no_tty = atoi (var->value);
|
no_tty = atoi (var->value);
|
||||||
var->ignore = 1;
|
var->ignore = 1;
|
||||||
|
} else if (strcasecmp (var->name, "debug") == 0) {
|
||||||
|
if (var->value &&
|
||||||
|
strcasecmp(var->value, "stdout") == 0)
|
||||||
|
priv->debugLog = stdout;
|
||||||
|
else
|
||||||
|
priv->debugLog = stderr;
|
||||||
}
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
else
|
else
|
||||||
@ -436,7 +479,7 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
memset (&hints, 0, sizeof hints);
|
memset (&hints, 0, sizeof hints);
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_flags = AI_ADDRCONFIG;
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
int e = getaddrinfo (server, port, &hints, &res);
|
int e = getaddrinfo (priv->hostname, port, &hints, &res);
|
||||||
if (e != 0) {
|
if (e != 0) {
|
||||||
error (conn, VIR_ERR_INVALID_ARG, gai_strerror (e));
|
error (conn, VIR_ERR_INVALID_ARG, gai_strerror (e));
|
||||||
goto failed;
|
goto failed;
|
||||||
@ -476,7 +519,7 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
if (priv->uses_tls) {
|
if (priv->uses_tls) {
|
||||||
priv->session =
|
priv->session =
|
||||||
negotiate_gnutls_on_connection
|
negotiate_gnutls_on_connection
|
||||||
(conn, priv->sock, no_verify, server);
|
(conn, priv, no_verify);
|
||||||
if (!priv->session) {
|
if (!priv->session) {
|
||||||
close (priv->sock);
|
close (priv->sock);
|
||||||
priv->sock = -1;
|
priv->sock = -1;
|
||||||
@ -603,7 +646,7 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
cmd_argv[j++] = strdup ("-e");
|
cmd_argv[j++] = strdup ("-e");
|
||||||
cmd_argv[j++] = strdup ("none");
|
cmd_argv[j++] = strdup ("none");
|
||||||
}
|
}
|
||||||
cmd_argv[j++] = strdup (server);
|
cmd_argv[j++] = strdup (priv->hostname);
|
||||||
cmd_argv[j++] = strdup (netcat ? netcat : "nc");
|
cmd_argv[j++] = strdup (netcat ? netcat : "nc");
|
||||||
cmd_argv[j++] = strdup ("-U");
|
cmd_argv[j++] = strdup ("-U");
|
||||||
cmd_argv[j++] = strdup (sockname ? sockname : LIBVIRTD_PRIV_UNIX_SOCKET);
|
cmd_argv[j++] = strdup (sockname ? sockname : LIBVIRTD_PRIV_UNIX_SOCKET);
|
||||||
@ -665,10 +708,15 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
}
|
}
|
||||||
} /* switch (transport) */
|
} /* switch (transport) */
|
||||||
|
|
||||||
|
|
||||||
|
/* Try and authenticate with server */
|
||||||
|
if (remoteAuthenticate(conn, priv, 1) == -1)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
/* Finally we can call the remote side's open function. */
|
/* Finally we can call the remote side's open function. */
|
||||||
remote_open_args args = { &name, flags };
|
remote_open_args args = { &name, flags };
|
||||||
|
|
||||||
if (call (conn, priv, 1, REMOTE_PROC_OPEN,
|
if (call (conn, priv, REMOTE_CALL_IN_OPEN, REMOTE_PROC_OPEN,
|
||||||
(xdrproc_t) xdr_remote_open_args, (char *) &args,
|
(xdrproc_t) xdr_remote_open_args, (char *) &args,
|
||||||
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||||
goto failed;
|
goto failed;
|
||||||
@ -676,30 +724,13 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
/* Successful. */
|
/* Successful. */
|
||||||
retcode = VIR_DRV_OPEN_SUCCESS;
|
retcode = VIR_DRV_OPEN_SUCCESS;
|
||||||
|
|
||||||
/*FALLTHROUGH*/
|
cleanup:
|
||||||
failed:
|
|
||||||
/* Close the socket if we failed. */
|
|
||||||
if (retcode != VIR_DRV_OPEN_SUCCESS && priv->sock >= 0) {
|
|
||||||
if (priv->uses_tls && priv->session)
|
|
||||||
gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
|
|
||||||
close (priv->sock);
|
|
||||||
if (priv->pid > 0) {
|
|
||||||
pid_t reap;
|
|
||||||
do {
|
|
||||||
reap = waitpid(priv->pid, NULL, 0);
|
|
||||||
if (reap == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
} while (reap != -1 && reap != priv->pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free up the URL and strings. */
|
/* Free up the URL and strings. */
|
||||||
if (name) free (name);
|
if (name) free (name);
|
||||||
if (command) free (command);
|
if (command) free (command);
|
||||||
if (sockname) free (sockname);
|
if (sockname) free (sockname);
|
||||||
if (netcat) free (netcat);
|
if (netcat) free (netcat);
|
||||||
if (username) free (username);
|
if (username) free (username);
|
||||||
if (server) free (server);
|
|
||||||
if (port) free (port);
|
if (port) free (port);
|
||||||
if (cmd_argv) {
|
if (cmd_argv) {
|
||||||
char **cmd_argv_ptr = cmd_argv;
|
char **cmd_argv_ptr = cmd_argv;
|
||||||
@ -711,6 +742,34 @@ doRemoteOpen (virConnectPtr conn, struct private_data *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return retcode;
|
return retcode;
|
||||||
|
|
||||||
|
out_of_memory:
|
||||||
|
error (NULL, VIR_ERR_NO_MEMORY, "uri params");
|
||||||
|
|
||||||
|
failed:
|
||||||
|
/* Close the socket if we failed. */
|
||||||
|
if (priv->sock >= 0) {
|
||||||
|
if (priv->uses_tls && priv->session) {
|
||||||
|
gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
|
||||||
|
gnutls_deinit (priv->session);
|
||||||
|
}
|
||||||
|
close (priv->sock);
|
||||||
|
if (priv->pid > 0) {
|
||||||
|
pid_t reap;
|
||||||
|
do {
|
||||||
|
reap = waitpid(priv->pid, NULL, 0);
|
||||||
|
if (reap == -1 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
} while (reap != -1 && reap != priv->pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->hostname) {
|
||||||
|
free (priv->hostname);
|
||||||
|
priv->hostname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1017,11 +1076,12 @@ initialise_gnutls (virConnectPtr conn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verify_certificate (virConnectPtr conn, gnutls_session_t session, const char *hostname);
|
static int verify_certificate (virConnectPtr conn, struct private_data *priv, gnutls_session_t session);
|
||||||
|
|
||||||
static gnutls_session_t
|
static gnutls_session_t
|
||||||
negotiate_gnutls_on_connection (virConnectPtr conn,
|
negotiate_gnutls_on_connection (virConnectPtr conn,
|
||||||
int sock, int no_verify, const char *hostname)
|
struct private_data *priv,
|
||||||
|
int no_verify)
|
||||||
{
|
{
|
||||||
const int cert_type_priority[3] = {
|
const int cert_type_priority[3] = {
|
||||||
GNUTLS_CRT_X509,
|
GNUTLS_CRT_X509,
|
||||||
@ -1062,7 +1122,7 @@ negotiate_gnutls_on_connection (virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gnutls_transport_set_ptr (session,
|
gnutls_transport_set_ptr (session,
|
||||||
(gnutls_transport_ptr_t) (long) sock);
|
(gnutls_transport_ptr_t) (long) priv->sock);
|
||||||
|
|
||||||
/* Perform the TLS handshake. */
|
/* Perform the TLS handshake. */
|
||||||
again:
|
again:
|
||||||
@ -1075,7 +1135,7 @@ negotiate_gnutls_on_connection (virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Verify certificate. */
|
/* Verify certificate. */
|
||||||
if (verify_certificate (conn, session, hostname) == -1) {
|
if (verify_certificate (conn, priv, session) == -1) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"remote_internal: failed to verify peer's certificate\n");
|
"remote_internal: failed to verify peer's certificate\n");
|
||||||
if (!no_verify) return NULL;
|
if (!no_verify) return NULL;
|
||||||
@ -1110,8 +1170,8 @@ negotiate_gnutls_on_connection (virConnectPtr conn,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
|
verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
gnutls_session_t session,
|
struct private_data *priv,
|
||||||
const char *hostname)
|
gnutls_session_t session)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
@ -1189,14 +1249,14 @@ verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
if (!gnutls_x509_crt_check_hostname (cert, hostname)) {
|
if (!gnutls_x509_crt_check_hostname (cert, priv->hostname)) {
|
||||||
__virRaiseError
|
__virRaiseError
|
||||||
(conn, NULL, NULL,
|
(conn, NULL, NULL,
|
||||||
VIR_FROM_REMOTE, VIR_ERR_RPC,
|
VIR_FROM_REMOTE, VIR_ERR_RPC,
|
||||||
VIR_ERR_ERROR, hostname, NULL, NULL,
|
VIR_ERR_ERROR, priv->hostname, NULL, NULL,
|
||||||
0, 0,
|
0, 0,
|
||||||
"Certificate's owner does not match the hostname (%s)",
|
"Certificate's owner does not match the hostname (%s)",
|
||||||
hostname);
|
priv->hostname);
|
||||||
gnutls_x509_crt_deinit (cert);
|
gnutls_x509_crt_deinit (cert);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1218,8 +1278,14 @@ doRemoteClose (virConnectPtr conn, struct private_data *priv)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Close socket. */
|
/* Close socket. */
|
||||||
if (priv->uses_tls && priv->session)
|
if (priv->uses_tls && priv->session) {
|
||||||
gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
|
gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
|
||||||
|
gnutls_deinit (priv->session);
|
||||||
|
}
|
||||||
|
#if HAVE_SASL
|
||||||
|
if (priv->saslconn)
|
||||||
|
sasl_dispose (&priv->saslconn);
|
||||||
|
#endif
|
||||||
close (priv->sock);
|
close (priv->sock);
|
||||||
|
|
||||||
if (priv->pid > 0) {
|
if (priv->pid > 0) {
|
||||||
@ -1231,6 +1297,9 @@ doRemoteClose (virConnectPtr conn, struct private_data *priv)
|
|||||||
} while (reap != -1 && reap != priv->pid);
|
} while (reap != -1 && reap != priv->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free hostname copy */
|
||||||
|
if (priv->hostname) free (priv->hostname);
|
||||||
|
|
||||||
/* See comment for remoteType. */
|
/* See comment for remoteType. */
|
||||||
if (priv->type) free (priv->type);
|
if (priv->type) free (priv->type);
|
||||||
|
|
||||||
@ -2751,6 +2820,298 @@ remoteNetworkSetAutostart (virNetworkPtr network, int autostart)
|
|||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteAuthenticate (virConnectPtr conn, struct private_data *priv, int in_open)
|
||||||
|
{
|
||||||
|
struct remote_auth_list_ret ret;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(&ret, 0, sizeof ret);
|
||||||
|
err = call (conn, priv,
|
||||||
|
REMOTE_CALL_IN_OPEN | REMOTE_CALL_QUIET_MISSING_RPC,
|
||||||
|
REMOTE_PROC_AUTH_LIST,
|
||||||
|
(xdrproc_t) xdr_void, (char *) NULL,
|
||||||
|
(xdrproc_t) xdr_remote_auth_list_ret, (char *) &ret);
|
||||||
|
if (err == -2) /* Missing RPC - old server - ignore */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ret.types.types_len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (ret.types.types_val[0]) {
|
||||||
|
#if HAVE_SASL
|
||||||
|
case REMOTE_AUTH_SASL:
|
||||||
|
if (remoteAuthSASL(conn, priv, in_open) < 0) {
|
||||||
|
free(ret.types.types_val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case REMOTE_AUTH_NONE:
|
||||||
|
/* Nothing todo, hurrah ! */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"unsupported authentication type %d", ret.types.types_val[0]);
|
||||||
|
free(ret.types.types_val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ret.types.types_val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_SASL
|
||||||
|
/*
|
||||||
|
* NB, keep in sync with similar method in qemud/remote.c
|
||||||
|
*/
|
||||||
|
static char *addrToString(struct sockaddr_storage *sa, socklen_t salen)
|
||||||
|
{
|
||||||
|
char host[NI_MAXHOST], port[NI_MAXSERV];
|
||||||
|
char *addr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((err = getnameinfo((struct sockaddr *)sa, salen,
|
||||||
|
host, sizeof(host),
|
||||||
|
port, sizeof(port),
|
||||||
|
NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
|
||||||
|
__virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_NO_MEMORY, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"Cannot resolve address %d: %s", err, gai_strerror(err));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = malloc(strlen(host) + 1 + strlen(port) + 1);
|
||||||
|
if (!addr) {
|
||||||
|
__virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_NO_MEMORY, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"address");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(addr, host);
|
||||||
|
strcat(addr, ";");
|
||||||
|
strcat(addr, port);
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Perform the SASL authentication process
|
||||||
|
*
|
||||||
|
* XXX negotiate a session encryption layer for non-TLS sockets
|
||||||
|
* XXX fetch credentials from a libvirt client app callback
|
||||||
|
* XXX max packet size spec
|
||||||
|
* XXX better mechanism negotiation ? Ask client app ?
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
remoteAuthSASL (virConnectPtr conn, struct private_data *priv, int in_open)
|
||||||
|
{
|
||||||
|
sasl_conn_t *saslconn = NULL;
|
||||||
|
remote_auth_sasl_init_ret iret;
|
||||||
|
remote_auth_sasl_start_args sargs;
|
||||||
|
remote_auth_sasl_start_ret sret;
|
||||||
|
remote_auth_sasl_step_args pargs;
|
||||||
|
remote_auth_sasl_step_ret pret;
|
||||||
|
const char *clientout;
|
||||||
|
char *serverin;
|
||||||
|
unsigned int clientoutlen, serverinlen;
|
||||||
|
const char *mech;
|
||||||
|
int err, complete;
|
||||||
|
struct sockaddr_storage sa;
|
||||||
|
socklen_t salen;
|
||||||
|
char *localAddr, *remoteAddr;
|
||||||
|
|
||||||
|
remoteDebug(priv, "Client initialize SASL authentication");
|
||||||
|
/* Sets up the SASL library as a whole */
|
||||||
|
err = sasl_client_init(NULL);
|
||||||
|
if (err != SASL_OK) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"failed to initialize SASL library: %d (%s)",
|
||||||
|
err, sasl_errstring(err, NULL, NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get local address in form IPADDR:PORT */
|
||||||
|
salen = sizeof(sa);
|
||||||
|
if (getsockname(priv->sock, (struct sockaddr*)&sa, &salen) < 0) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"failed to get sock address %d (%s)",
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((localAddr = addrToString(&sa, salen)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get remote address in form IPADDR:PORT */
|
||||||
|
salen = sizeof(sa);
|
||||||
|
if (getpeername(priv->sock, (struct sockaddr*)&sa, &salen) < 0) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"failed to get peer address %d (%s)",
|
||||||
|
errno, strerror(errno));
|
||||||
|
free(localAddr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((remoteAddr = addrToString(&sa, salen)) == NULL) {
|
||||||
|
free(localAddr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup a handle for being a client */
|
||||||
|
err = sasl_client_new("libvirt",
|
||||||
|
priv->hostname,
|
||||||
|
localAddr,
|
||||||
|
remoteAddr,
|
||||||
|
NULL, /* XXX callbacks */
|
||||||
|
SASL_SUCCESS_DATA,
|
||||||
|
&saslconn);
|
||||||
|
free(localAddr);
|
||||||
|
free(remoteAddr);
|
||||||
|
if (err != SASL_OK) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"Failed to create SASL client context: %d (%s)",
|
||||||
|
err, sasl_errstring(err, NULL, NULL));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First call is to inquire about supported mechanisms in the server */
|
||||||
|
memset (&iret, 0, sizeof iret);
|
||||||
|
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_SASL_INIT,
|
||||||
|
(xdrproc_t) xdr_void, (char *)NULL,
|
||||||
|
(xdrproc_t) xdr_remote_auth_sasl_init_ret, (char *) &iret) != 0) {
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return -1; /* virError already set by call */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Start the auth negotiation on the client end first */
|
||||||
|
remoteDebug(priv, "Client start negotiation mechlist '%s'", iret.mechlist);
|
||||||
|
err = sasl_client_start(saslconn,
|
||||||
|
iret.mechlist,
|
||||||
|
NULL, /* XXX interactions */
|
||||||
|
&clientout,
|
||||||
|
&clientoutlen,
|
||||||
|
&mech);
|
||||||
|
if (err != SASL_OK && err != SASL_CONTINUE) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"Failed to start SASL negotiation: %d (%s)",
|
||||||
|
err, sasl_errdetail(saslconn));
|
||||||
|
free(iret.mechlist);
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(iret.mechlist);
|
||||||
|
|
||||||
|
if (clientoutlen > REMOTE_AUTH_SASL_DATA_MAX) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"SASL negotiation data too long: %d bytes", clientoutlen);
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
memset(&sargs, 0, sizeof sargs);
|
||||||
|
sargs.nil = clientout ? 0 : 1;
|
||||||
|
sargs.data.data_val = (char*)clientout;
|
||||||
|
sargs.data.data_len = clientoutlen;
|
||||||
|
sargs.mech = (char*)mech;
|
||||||
|
remoteDebug(priv, "Server start negotiation with mech %s. Data %d bytes %p", mech, clientoutlen, clientout);
|
||||||
|
|
||||||
|
/* Now send the initial auth data to the server */
|
||||||
|
memset (&sret, 0, sizeof sret);
|
||||||
|
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_SASL_START,
|
||||||
|
(xdrproc_t) xdr_remote_auth_sasl_start_args, (char *) &sargs,
|
||||||
|
(xdrproc_t) xdr_remote_auth_sasl_start_ret, (char *) &sret) != 0) {
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return -1; /* virError already set by call */
|
||||||
|
}
|
||||||
|
|
||||||
|
complete = sret.complete;
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
serverin = sret.nil ? NULL : sret.data.data_val;
|
||||||
|
serverinlen = sret.data.data_len;
|
||||||
|
remoteDebug(priv, "Client step result complete: %d. Data %d bytes %p",
|
||||||
|
complete, serverinlen, serverin);
|
||||||
|
|
||||||
|
/* Loop-the-loop...
|
||||||
|
* Even if the server has completed, the client must *always* do at least one step
|
||||||
|
* in this loop to verify the server isn't lieing about something. Mutual auth */
|
||||||
|
for (;;) {
|
||||||
|
err = sasl_client_step(saslconn,
|
||||||
|
serverin,
|
||||||
|
serverinlen,
|
||||||
|
NULL, /* XXX interactions */
|
||||||
|
&clientout,
|
||||||
|
&clientoutlen);
|
||||||
|
if (serverin) free(serverin);
|
||||||
|
if (err != SASL_OK && err != SASL_CONTINUE) {
|
||||||
|
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
|
VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
|
"Failed SASL step: %d (%s)",
|
||||||
|
err, sasl_errdetail(saslconn));
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
remoteDebug(priv, "Client step result %d. Data %d bytes %p", err, clientoutlen, clientout);
|
||||||
|
|
||||||
|
/* Previous server call showed completion & we're now locally complete too */
|
||||||
|
if (complete && err == SASL_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Not done, prepare to talk with the server for another iteration */
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
memset(&pargs, 0, sizeof pargs);
|
||||||
|
pargs.nil = clientout ? 0 : 1;
|
||||||
|
pargs.data.data_val = (char*)clientout;
|
||||||
|
pargs.data.data_len = clientoutlen;
|
||||||
|
remoteDebug(priv, "Server step with %d bytes %p", clientoutlen, clientout);
|
||||||
|
|
||||||
|
memset (&pret, 0, sizeof pret);
|
||||||
|
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_SASL_STEP,
|
||||||
|
(xdrproc_t) xdr_remote_auth_sasl_step_args, (char *) &pargs,
|
||||||
|
(xdrproc_t) xdr_remote_auth_sasl_step_ret, (char *) &pret) != 0) {
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return -1; /* virError already set by call */
|
||||||
|
}
|
||||||
|
|
||||||
|
complete = pret.complete;
|
||||||
|
/* NB, distinction of NULL vs "" is *critical* in SASL */
|
||||||
|
serverin = pret.nil ? NULL : pret.data.data_val;
|
||||||
|
serverinlen = pret.data.data_len;
|
||||||
|
|
||||||
|
remoteDebug(priv, "Client step result complete: %d. Data %d bytes %p",
|
||||||
|
complete, serverinlen, serverin);
|
||||||
|
|
||||||
|
/* This server call shows complete, and earlier client step was OK */
|
||||||
|
if (complete && err == SASL_OK) {
|
||||||
|
if (serverin) free(serverin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteDebug(priv, "SASL authentication complete");
|
||||||
|
/* XXX keep this around for wire encoding */
|
||||||
|
sasl_dispose(&saslconn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SASL */
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int really_write (virConnectPtr conn, struct private_data *priv,
|
static int really_write (virConnectPtr conn, struct private_data *priv,
|
||||||
int in_open, char *bytes, int len);
|
int in_open, char *bytes, int len);
|
||||||
static int really_read (virConnectPtr conn, struct private_data *priv,
|
static int really_read (virConnectPtr conn, struct private_data *priv,
|
||||||
@ -2768,7 +3129,7 @@ static int really_read (virConnectPtr conn, struct private_data *priv,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
call (virConnectPtr conn, struct private_data *priv,
|
call (virConnectPtr conn, struct private_data *priv,
|
||||||
int in_open /* if we are in virConnectOpen */,
|
int flags /* if we are in virConnectOpen */,
|
||||||
int proc_nr,
|
int proc_nr,
|
||||||
xdrproc_t args_filter, char *args,
|
xdrproc_t args_filter, char *args,
|
||||||
xdrproc_t ret_filter, char *ret)
|
xdrproc_t ret_filter, char *ret)
|
||||||
@ -2793,13 +3154,13 @@ call (virConnectPtr conn, struct private_data *priv,
|
|||||||
/* Serialise header followed by args. */
|
/* Serialise header followed by args. */
|
||||||
xdrmem_create (&xdr, buffer, sizeof buffer, XDR_ENCODE);
|
xdrmem_create (&xdr, buffer, sizeof buffer, XDR_ENCODE);
|
||||||
if (!xdr_remote_message_header (&xdr, &hdr)) {
|
if (!xdr_remote_message_header (&xdr, &hdr)) {
|
||||||
error (in_open ? NULL : conn,
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
|
||||||
VIR_ERR_RPC, "xdr_remote_message_header");
|
VIR_ERR_RPC, "xdr_remote_message_header");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(*args_filter) (&xdr, args)) {
|
if (!(*args_filter) (&xdr, args)) {
|
||||||
error (in_open ? NULL : conn, VIR_ERR_RPC, "marshalling args");
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, "marshalling args");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2815,23 +3176,23 @@ call (virConnectPtr conn, struct private_data *priv,
|
|||||||
/* Encode the length word. */
|
/* Encode the length word. */
|
||||||
xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_ENCODE);
|
xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_ENCODE);
|
||||||
if (!xdr_int (&xdr, &len)) {
|
if (!xdr_int (&xdr, &len)) {
|
||||||
error (in_open ? NULL : conn, VIR_ERR_RPC, "xdr_int (length word)");
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, "xdr_int (length word)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xdr_destroy (&xdr);
|
xdr_destroy (&xdr);
|
||||||
|
|
||||||
/* Send length word followed by header+args. */
|
/* Send length word followed by header+args. */
|
||||||
if (really_write (conn, priv, in_open, buffer2, sizeof buffer2) == -1 ||
|
if (really_write (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer2, sizeof buffer2) == -1 ||
|
||||||
really_write (conn, priv, in_open, buffer, len-4) == -1)
|
really_write (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer, len-4) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Read and deserialise length word. */
|
/* Read and deserialise length word. */
|
||||||
if (really_read (conn, priv, in_open, buffer2, sizeof buffer2) == -1)
|
if (really_read (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer2, sizeof buffer2) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE);
|
xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE);
|
||||||
if (!xdr_int (&xdr, &len)) {
|
if (!xdr_int (&xdr, &len)) {
|
||||||
error (in_open ? NULL : conn,
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
|
||||||
VIR_ERR_RPC, "xdr_int (length word, reply)");
|
VIR_ERR_RPC, "xdr_int (length word, reply)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2841,33 +3202,33 @@ call (virConnectPtr conn, struct private_data *priv,
|
|||||||
len -= 4;
|
len -= 4;
|
||||||
|
|
||||||
if (len < 0 || len > REMOTE_MESSAGE_MAX) {
|
if (len < 0 || len > REMOTE_MESSAGE_MAX) {
|
||||||
error (in_open ? NULL : conn,
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
|
||||||
VIR_ERR_RPC, "packet received from server too large");
|
VIR_ERR_RPC, "packet received from server too large");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read reply header and what follows (either a ret or an error). */
|
/* Read reply header and what follows (either a ret or an error). */
|
||||||
if (really_read (conn, priv, in_open, buffer, len) == -1)
|
if (really_read (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer, len) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Deserialise reply header. */
|
/* Deserialise reply header. */
|
||||||
xdrmem_create (&xdr, buffer, len, XDR_DECODE);
|
xdrmem_create (&xdr, buffer, len, XDR_DECODE);
|
||||||
if (!xdr_remote_message_header (&xdr, &hdr)) {
|
if (!xdr_remote_message_header (&xdr, &hdr)) {
|
||||||
error (in_open ? NULL : conn,
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
|
||||||
VIR_ERR_RPC, "xdr_remote_message_header (reply)");
|
VIR_ERR_RPC, "xdr_remote_message_header (reply)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check program, version, etc. are what we expect. */
|
/* Check program, version, etc. are what we expect. */
|
||||||
if (hdr.prog != REMOTE_PROGRAM) {
|
if (hdr.prog != REMOTE_PROGRAM) {
|
||||||
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
__virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
"unknown program (received %x, expected %x)",
|
"unknown program (received %x, expected %x)",
|
||||||
hdr.prog, REMOTE_PROGRAM);
|
hdr.prog, REMOTE_PROGRAM);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (hdr.vers != REMOTE_PROTOCOL_VERSION) {
|
if (hdr.vers != REMOTE_PROTOCOL_VERSION) {
|
||||||
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
__virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
"unknown protocol version (received %x, expected %x)",
|
"unknown protocol version (received %x, expected %x)",
|
||||||
hdr.vers, REMOTE_PROTOCOL_VERSION);
|
hdr.vers, REMOTE_PROTOCOL_VERSION);
|
||||||
@ -2879,21 +3240,21 @@ call (virConnectPtr conn, struct private_data *priv,
|
|||||||
* message being received at this point.
|
* message being received at this point.
|
||||||
*/
|
*/
|
||||||
if (hdr.proc != proc_nr) {
|
if (hdr.proc != proc_nr) {
|
||||||
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
__virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
"unknown procedure (received %x, expected %x)",
|
"unknown procedure (received %x, expected %x)",
|
||||||
hdr.proc, proc_nr);
|
hdr.proc, proc_nr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (hdr.direction != REMOTE_REPLY) {
|
if (hdr.direction != REMOTE_REPLY) {
|
||||||
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
__virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
"unknown direction (received %x, expected %x)",
|
"unknown direction (received %x, expected %x)",
|
||||||
hdr.direction, REMOTE_REPLY);
|
hdr.direction, REMOTE_REPLY);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (hdr.serial != serial) {
|
if (hdr.serial != serial) {
|
||||||
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
__virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
"unknown serial (received %x, expected %x)",
|
"unknown serial (received %x, expected %x)",
|
||||||
hdr.serial, serial);
|
hdr.serial, serial);
|
||||||
@ -2907,7 +3268,7 @@ call (virConnectPtr conn, struct private_data *priv,
|
|||||||
switch (hdr.status) {
|
switch (hdr.status) {
|
||||||
case REMOTE_OK:
|
case REMOTE_OK:
|
||||||
if (!(*ret_filter) (&xdr, ret)) {
|
if (!(*ret_filter) (&xdr, ret)) {
|
||||||
error (in_open ? NULL : conn, VIR_ERR_RPC, "unmarshalling ret");
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, "unmarshalling ret");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xdr_destroy (&xdr);
|
xdr_destroy (&xdr);
|
||||||
@ -2916,17 +3277,26 @@ call (virConnectPtr conn, struct private_data *priv,
|
|||||||
case REMOTE_ERROR:
|
case REMOTE_ERROR:
|
||||||
memset (&rerror, 0, sizeof rerror);
|
memset (&rerror, 0, sizeof rerror);
|
||||||
if (!xdr_remote_error (&xdr, &rerror)) {
|
if (!xdr_remote_error (&xdr, &rerror)) {
|
||||||
error (in_open ? NULL : conn,
|
error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
|
||||||
VIR_ERR_RPC, "unmarshalling remote_error");
|
VIR_ERR_RPC, "unmarshalling remote_error");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xdr_destroy (&xdr);
|
xdr_destroy (&xdr);
|
||||||
server_error (in_open ? NULL : conn, &rerror);
|
/* See if caller asked us to keep quiet about missing RPCs
|
||||||
|
* eg for interop with older servers */
|
||||||
|
if (flags & REMOTE_CALL_QUIET_MISSING_RPC &&
|
||||||
|
rerror.domain == VIR_FROM_REMOTE &&
|
||||||
|
rerror.code == VIR_ERR_RPC &&
|
||||||
|
rerror.level == VIR_ERR_ERROR &&
|
||||||
|
STREQLEN(*rerror.message, "unknown procedure", 17)) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
server_error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, &rerror);
|
||||||
xdr_free ((xdrproc_t) xdr_remote_error, (char *) &rerror);
|
xdr_free ((xdrproc_t) xdr_remote_error, (char *) &rerror);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
__virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
__virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||||
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
|
||||||
"unknown status (received %x)",
|
"unknown status (received %x)",
|
||||||
hdr.status);
|
hdr.status);
|
||||||
|
@ -671,6 +671,12 @@ __virErrorMsg(virErrorNumber error, const char *info)
|
|||||||
else
|
else
|
||||||
errmsg = _("invalid MAC adress: %s");
|
errmsg = _("invalid MAC adress: %s");
|
||||||
break;
|
break;
|
||||||
|
case VIR_ERR_AUTH_FAILED:
|
||||||
|
if (info == NULL)
|
||||||
|
errmsg = _("authentication failed");
|
||||||
|
else
|
||||||
|
errmsg = _("authentication failed: %s");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (errmsg);
|
return (errmsg);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ INCLUDES = \
|
|||||||
-I$(top_srcdir)/src \
|
-I$(top_srcdir)/src \
|
||||||
$(LIBXML_CFLAGS) \
|
$(LIBXML_CFLAGS) \
|
||||||
$(GNUTLS_CFLAGS) \
|
$(GNUTLS_CFLAGS) \
|
||||||
|
$(SASL_CFLAGS) \
|
||||||
-D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L \
|
-D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L \
|
||||||
-DGETTEXT_PACKAGE=\"$(PACKAGE)\" \
|
-DGETTEXT_PACKAGE=\"$(PACKAGE)\" \
|
||||||
$(COVERAGE_CFLAGS) \
|
$(COVERAGE_CFLAGS) \
|
||||||
@ -27,6 +28,7 @@ LDADDS = \
|
|||||||
@STATIC_BINARIES@ \
|
@STATIC_BINARIES@ \
|
||||||
$(LIBXML_LIBS) \
|
$(LIBXML_LIBS) \
|
||||||
$(GNUTLS_LIBS) \
|
$(GNUTLS_LIBS) \
|
||||||
|
$(SASL_LIBS) \
|
||||||
$(WARN_CFLAGS) \
|
$(WARN_CFLAGS) \
|
||||||
$(LIBVIRT) \
|
$(LIBVIRT) \
|
||||||
$(COVERAGE_LDFLAGS)
|
$(COVERAGE_LDFLAGS)
|
||||||
|
Loading…
Reference in New Issue
Block a user