提交 1b1d6474 编写于 作者: D Daniel P. Berrange

Initial integration of SASL authentication, working for Kerberos only

上级 a8977b62
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>
* src/qemu_conf.c: Strip out NIC interfaces named vnetXXX since
......
......@@ -361,6 +361,40 @@ CFLAGS="$old_cflags"
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
AC_ARG_WITH(avahi,
[ --with-avahi use avahi to advertise remote daemon],
......@@ -583,6 +617,11 @@ AC_MSG_NOTICE([Libraries])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([ libxml: $LIBXML_CFLAGS $LIBXML_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
AC_MSG_NOTICE([ avahi: $AVAHI_CFLAGS $AVAHI_LIBS])
else
......
......@@ -131,6 +131,7 @@ typedef enum {
VIR_ERR_NO_DOMAIN, /* domain not found or unexpectedly disappeared */
VIR_ERR_NO_NETWORK, /* network not found */
VIR_ERR_INVALID_MAC, /* invalid MAC adress */
VIR_ERR_AUTH_FAILED, /* authentication failed */
} virErrorNumber;
/**
......
......@@ -16,6 +16,10 @@ Requires: ncurses
Requires: dnsmasq
Requires: bridge-utils
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: libxml2-devel
BuildRequires: readline-devel
......@@ -26,6 +30,7 @@ BuildRequires: avahi-devel
BuildRequires: dnsmasq
BuildRequires: bridge-utils
BuildRequires: qemu
BuildRequires: cyrus-sasl-devel
Obsoletes: libvir
ExclusiveArch: i386 x86_64 ia64
......@@ -132,6 +137,7 @@ fi
%config(noreplace) %{_sysconfdir}/sysconfig/libvirtd
%config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf
%config(noreplace) %{_sysconfdir}/libvirt/qemu.conf
%config(noreplace) %{_sysconfdir}/sasl2/libvirt.conf
%dir %{_datadir}/libvirt/
%dir %{_datadir}/libvirt/networks/
%{_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_proc_switch.h \
mdns.c mdns.h \
libvirtd.sasl \
$(conf_DATA)
libvirtd_SOURCES = \
......@@ -28,14 +29,14 @@ libvirtd_SOURCES = \
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
libvirtd_CFLAGS = \
-I$(top_srcdir)/include -I$(top_builddir)/include \
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) \
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
$(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \
-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_LDADD = ../src/libvirt.la
......@@ -46,7 +47,7 @@ libvirtd_LDADD += $(AVAHI_LIBS)
endif
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
$(INSTALL_DATA) $(srcdir)/default-network.xml \
$(DESTDIR)$(sysconfdir)/$(default_xml_dest)
......@@ -59,7 +60,7 @@ install-data-local: install-init
mkdir -p $(DESTDIR)$(localstatedir)/run/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)/$(default_xml_dest)
rmdir $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart || :
......@@ -67,6 +68,18 @@ uninstall-local: uninstall-init
rmdir $(DESTDIR)$(localstatedir)/run/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
.x.c:
......
......@@ -28,6 +28,9 @@
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "../src/gnutls_1_0_compat.h"
#if HAVE_SASL
#include <sasl/sasl.h>
#endif
#ifdef HAVE_SYS_SYSLIMITS_H
#include <sys/syslimits.h>
......@@ -91,6 +94,10 @@ struct qemud_client {
int tls;
gnutls_session_t session;
enum qemud_tls_direction direction;
int auth;
#if HAVE_SASL
sasl_conn_t *saslconn;
#endif
unsigned int incomingSerial;
unsigned int outgoingSerial;
......@@ -116,6 +123,7 @@ struct qemud_socket {
int readonly;
/* If set, TLS is required on this socket. */
int tls;
int auth;
int port;
struct qemud_socket *next;
};
......
......@@ -37,6 +37,7 @@ PROCESS=libvirtd
LIBVIRTD_CONFIG=
LIBVIRTD_ARGS=
KRB5_KTNAME=/etc/libvirt/krb5.tab
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
......@@ -50,7 +51,7 @@ RETVAL=0
start() {
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=$?
echo
[ $RETVAL -eq 0 ] && touch @localstatedir@/lock/subsys/$SERVICE
......
......@@ -4,3 +4,6 @@
# Listen for TCP/IP connections
# NB. must setup TLS/SSL keys prior to using this
#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
remoteListenTCP (struct qemud_server *server,
const char *port,
int tls)
int tls,
int auth)
{
int fds[2];
int nfds = 0;
......@@ -604,6 +605,7 @@ remoteListenTCP (struct qemud_server *server,
sock->fd = fds[i];
sock->tls = tls;
sock->auth = auth;
if (getsockname(sock->fd, (struct sockaddr *)(&sa), &salen) < 0)
return -1;
......@@ -699,6 +701,9 @@ static struct qemud_server *qemudInitialize(int sigread) {
struct qemud_socket *sock;
char sockname[PATH_MAX];
char roSockname[PATH_MAX];
#if HAVE_SASL
int err;
#endif /* HAVE_SASL */
if (!(server = calloc(1, sizeof(struct qemud_server)))) {
qemudLog(QEMUD_ERR, "Failed to allocate struct qemud_server");
......@@ -728,15 +733,28 @@ static struct qemud_server *qemudInitialize(int sigread) {
virStateInitialize();
#if HAVE_SASL
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;
}
#endif
if (ipsock) {
if (listen_tcp && remoteListenTCP (server, tcp_port, 0) < 0)
#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 (remoteInitializeGnuTLS () < 0)
goto cleanup;
if (remoteListenTCP (server, tls_port, 1) < 0)
if (remoteListenTCP (server, tls_port, 1, REMOTE_AUTH_NONE) < 0)
goto cleanup;
}
}
......@@ -1048,6 +1066,7 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
client->fd = fd;
client->readonly = sock->readonly;
client->tls = sock->tls;
client->auth = sock->auth;
memcpy (&client->addr, &addr, sizeof addr);
client->addrlen = addrlen;
......@@ -1128,6 +1147,9 @@ static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud
if (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);
close(client->fd);
free(client);
......
......@@ -52,6 +52,8 @@
#define DEBUG 0
#define REMOTE_DEBUG(fmt,...) qemudDebug("REMOTE: " fmt, __VA_ARGS__)
static void remoteDispatchError (struct qemud_client *client,
remote_message_header *req,
const char *fmt, ...)
......@@ -118,6 +120,21 @@ remoteDispatchClientRequest (struct qemud_server *server ATTRIBUTE_UNUSED,
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
* this on the version number as well.
*/
......@@ -275,24 +292,15 @@ remoteDispatchClientRequest (struct qemud_server *server ATTRIBUTE_UNUSED,
* reply.
*/
static void
remoteDispatchError (struct qemud_client *client,
remote_message_header *req,
const char *fmt, ...)
remoteDispatchSendError (struct qemud_client *client,
remote_message_header *req,
int code, const char *msg)
{
remote_message_header rep;
remote_error error;
va_list args;
char msgbuf[1024];
char *msg = msgbuf;
XDR xdr;
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
* our hardest to send back a message that such clients could see.
*/
......@@ -313,12 +321,12 @@ remoteDispatchError (struct qemud_client *client,
}
/* Construct the error. */
error.code = VIR_ERR_RPC;
error.code = code;
error.domain = VIR_FROM_REMOTE;
error.message = &msg;
error.message = (char**)&msg;
error.level = VIR_ERR_ERROR;
error.dom = NULL;
error.str1 = &msg;
error.str1 = (char**)&msg;
error.str2 = NULL;
error.str3 = NULL;
error.int1 = 0;
......@@ -364,6 +372,31 @@ remoteDispatchError (struct qemud_client *client,
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. -----*/
static int
......@@ -1946,6 +1979,335 @@ remoteDispatchNumOfNetworks (struct qemud_client *client,
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. -----*/
/* 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_get_capabilities_ret lv_remote_get_capabilities_ret;
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_ret lv_remote_domain_get_os_type_ret;
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_ret lv_remote_domain_create_linux_ret;
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_ret lv_remote_domain_interface_stats_ret;
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_ret lv_remote_network_get_bridge_name_ret;
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_ret lv_remote_domain_migrate_finish_ret;
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_get_autostart_args lv_remote_network_get_autostart_args;
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_get_max_memory_args lv_remote_domain_get_max_memory_args;
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.
*/
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:
fn = (dispatch_fn) remoteDispatchClose;
break;
......
......@@ -2,6 +2,10 @@
* 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 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);
......
......@@ -104,6 +104,15 @@ xdr_remote_error (XDR *xdrs, remote_error *objp)
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
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;
}
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
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_NETWORK_NAME_LIST_MAX 256
#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];
......@@ -63,6 +65,12 @@ struct 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 {
u_int number;
int state;
......@@ -659,6 +667,58 @@ struct remote_network_set_autostart_args {
int autostart;
};
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_PROTOCOL_VERSION 1
......@@ -728,6 +788,10 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63,
REMOTE_PROC_DOMAIN_BLOCK_STATS = 64,
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;
......@@ -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_network (XDR *, remote_network*);
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_sched_param_value (XDR *, remote_sched_param_value*);
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_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_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_message_direction (XDR *, remote_message_direction*);
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_network ();
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_sched_param_value ();
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_ret ();
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_message_direction ();
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. */
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 */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
......@@ -123,6 +129,13 @@ struct remote_error {
remote_network net;
};
/* Authentication types available thus far.... */
enum remote_auth_type {
REMOTE_AUTH_NONE = 0,
REMOTE_AUTH_SASL = 1
};
/* Wire encoding of virVcpuInfo. */
struct remote_vcpu_info {
unsigned int number;
......@@ -612,6 +625,37 @@ struct remote_network_set_autostart_args {
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. -----*/
/* 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_FINISH = 63,
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. */
......
......@@ -5,6 +5,7 @@ INCLUDES = -I$(top_builddir)/include \
-I@top_srcdir@/qemud \
$(LIBXML_CFLAGS) \
$(GNUTLS_CFLAGS) \
$(SASL_CFLAGS) \
-DBINDIR=\""$(libexecdir)"\" \
-DSBINDIR=\""$(sbindir)"\" \
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
......@@ -59,7 +60,7 @@ SERVER_SOURCES = \
../qemud/remote_protocol.c ../qemud/remote_protocol.h
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@
libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \
-version-info @LIBVIRT_VERSION_INFO@ \
......
此差异已折叠。
......@@ -671,6 +671,12 @@ __virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("invalid MAC adress: %s");
break;
case VIR_ERR_AUTH_FAILED:
if (info == NULL)
errmsg = _("authentication failed");
else
errmsg = _("authentication failed: %s");
break;
}
return (errmsg);
}
......
......@@ -17,6 +17,7 @@ INCLUDES = \
-I$(top_srcdir)/src \
$(LIBXML_CFLAGS) \
$(GNUTLS_CFLAGS) \
$(SASL_CFLAGS) \
-D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L \
-DGETTEXT_PACKAGE=\"$(PACKAGE)\" \
$(COVERAGE_CFLAGS) \
......@@ -27,6 +28,7 @@ LDADDS = \
@STATIC_BINARIES@ \
$(LIBXML_LIBS) \
$(GNUTLS_LIBS) \
$(SASL_LIBS) \
$(WARN_CFLAGS) \
$(LIBVIRT) \
$(COVERAGE_LDFLAGS)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册