SASL implementation
Willem Dantuma
willem.dantuma@dobs.nl
20 Nov 2003 01:52:17 +0100
--=-CztVctplTNL1o+sia54b
Content-Type: multipart/alternative; boundary="=-w1yXIDF+g/FS3SYYLr3u"
--=-w1yXIDF+g/FS3SYYLr3u
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hi,
Well here it is my first shot at the sasl implementation of DBusAuth, i
only tested it with the sasl PLAIN method so far.
It still needs a major cleanup and some function reshuffeling.
This implementation merges the existing two authentication methods with
all possible sasl methods, the dbus_connection_set_get_password_function
and dbus_connection_set_get_username_function where added to the api to
set the callback funtions used to promt for the username and password (
if needed ).
dbus-monitor and dbus-send still needs to be modified to support this
but these are waiting for the change of dbus_bus_get which i have not
done yet.
Willem Dantuma
--=-w1yXIDF+g/FS3SYYLr3u
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
<META NAME="GENERATOR" CONTENT="GtkHTML/1.1.8">
</HEAD>
<BODY>
Hi,<BR>
<BR>
Well here it is my first shot at the sasl implementation of DBusAuth, i only tested it with the sasl PLAIN method so far.<BR>
<BR>
It still needs a major cleanup and some function reshuffeling.<BR>
<BR>
This implementation merges the existing two authentication methods with all possible sasl methods, the dbus_connection_set_get_password_function and dbus_connection_set_get_username_function where added to the api to set the callback funtions used to promt for the username and password ( if needed ).<BR>
<BR>
dbus-monitor and dbus-send still needs to be modified to support this but these are waiting for the change of dbus_bus_get which i have not done yet.<BR>
<BR>
<BR>
Willem Dantuma
</BODY>
</HTML>
--=-w1yXIDF+g/FS3SYYLr3u--
--=-CztVctplTNL1o+sia54b
Content-Disposition: attachment; filename=dbus-sasl.diff
Content-Type: text/x-patch; name=dbus-sasl.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Index: ChangeLog
===================================================================
RCS file: /cvs/dbus/dbus/ChangeLog,v
retrieving revision 1.438
diff -u -p -r1.438 ChangeLog
--- ChangeLog 19 Nov 2003 21:51:09 -0000 1.438
+++ ChangeLog 19 Nov 2003 23:36:28 -0000
@@ -1,3 +1,43 @@
+2003-11-19 Willem Dantuma <willem@dobs.nl>
+
+ * configure.in: add option and cheks for sasl
+
+ * dbus/Makefile.am: add sasl libraries
+
+ * dbus/dbus-auth.h: prototypes for the new functions
+ _dbus_auth_set_remote_ip, dbus_auth_set_local_ip,
+ _dbus_auth_set_host, _dbus_auth_set_get_username_function
+ and _dbus_auth_set_get_password_function
+
+ * dbus/dbus-auth.c: fairly large change implementing the sasl stuff,
+ the two existing authentication mechanims are merged with the available
+ sasl mecanisms. Several new and modififications to existing functions
+ also added fields to the DBusAuth, DBusAuthClient and DBusAuthServer
+ structures facilitate all this.
+
+ * dbus/dbus-connection.h: new functions
+ dbus_connection_set_get_username_function and
+ dbus_connection_set_get_password_function
+
+ * dbus/dbus-connection.c: implementations
+
+ * dbus/dbus-sysdeps.h: new functions
+ _dbus_transport_is_inet
+ _dbus_transport_get_local_ip and
+ _dbus_transport_get_remote_ip
+
+ * dbus/dbus-sysdeps.c: implementations
+
+ * dbus/dbus-transport-unix.c: modifications to
+ _dbus_transport_new_for_fd to add the remote_ip, local_ip and host
+ information to the DBusAuth class
+
+ * dbus/dbus-transport.h: new functions
+ _dbus_transport_set_get_username_function and
+ _dbus_transport_set_get_password_function
+
+ * dbus/dbus-transport.c: implementations
+
2003-11-19 Havoc Pennington <hp@redhat.com>
* NEWS: update
Index: configure.in
===================================================================
RCS file: /cvs/dbus/dbus/configure.in,v
retrieving revision 1.76
diff -u -p -r1.76 configure.in
--- configure.in 19 Nov 2003 21:51:09 -0000 1.76
+++ configure.in 19 Nov 2003 22:40:56 -0000
@@ -37,7 +37,7 @@ AC_ARG_ENABLE(abstract-sockets, [ --ena
AC_ARG_ENABLE(gcj, [ --enable-gcj build gcj bindings],enable_gcj=$enableval,enable_gcj=no)
AC_ARG_ENABLE(mono, [ --enable-mono build mono bindings],enable_mono=$enableval,enable_mono=no)
AC_ARG_ENABLE(python, [ --enable-python build python bindings],enable_python=$enableval,enable_python=auto)
-
+AC_ARG_ENABLE(sasl, [ --enable-sasl enable sasl authentication],enable_sasl=$enableval,enable_sasl=no)
AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use])
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
@@ -670,6 +670,34 @@ dnl Qt flags
AC_SUBST(DBUS_QT_CXXFLAGS)
AC_SUBST(DBUS_QT_LIBS)
+
+### SASL detection
+have_sasl=no
+
+AC_CHECK_HEADERS(sasl/sasl.h)
+
+if test $ac_cv_header_sasl_sasl_h = yes ; then
+ have_sasl=yes
+ AC_CHECK_LIB(sasl2, sasl_client_init,
+ [DBUS_SASL_LIBS="-lsasl2"],[have_sasl=no])
+fi
+
+if test x$enable_sasl = xyes; then
+ if test x$have_sasl = xno; then
+ AC_MSG_ERROR([SASL explicitly required, and SASL libraries not found])
+ else
+ AC_DEFINE(HAVE_SASL,1,[define if you have sasl])
+ fi
+fi
+
+if test x$enable_sasl = xno; then
+ have_sasl=no;
+fi
+
+AC_SUBST(DBUS_SASL_LIBS)
+
+
+
### X11 detection
AC_PATH_XTRA
@@ -1019,6 +1047,7 @@ echo "
Using XML parser: ${with_xml}
Init scripts style: ${with_init_scripts}
Abstract socket names: ${have_abstract_sockets}
+ SASL Authentication: ${enable_sasl}
System bus socket: ${DBUS_SYSTEM_SOCKET}
System bus address: ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS}
System bus PID file: ${DBUS_SYSTEM_PID_FILE}
Index: dbus/Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/dbus/Makefile.am,v
retrieving revision 1.58
diff -u -p -r1.58 Makefile.am
--- dbus/Makefile.am 15 Oct 2003 21:09:40 -0000 1.58
+++ dbus/Makefile.am 19 Nov 2003 22:41:34 -0000
@@ -124,7 +124,9 @@ EXTRA_DIST=dbus-arch-deps.h.in
## and is only used for static linking within the dbus package.
noinst_LTLIBRARIES=libdbus-convenience.la
-libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS)
+libdbus_convenience_la_LIBADD= $(DBUS_SASL_LIBS)
+
+libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS) ${DBUS_SASL_LIBS}
## don't export symbols that start with "_" (we use this
## convention for internal symbols)
libdbus_1_la_LDFLAGS= -export-symbols-regex "^[^_].*"
Index: dbus/dbus-auth.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-auth.h,v
retrieving revision 1.6
diff -u -p -r1.6 dbus-auth.h
--- dbus/dbus-auth.h 1 Apr 2003 05:33:01 -0000 1.6
+++ dbus/dbus-auth.h 19 Nov 2003 22:41:52 -0000
@@ -2,6 +2,7 @@
/* dbus-auth.h Authentication
*
* Copyright (C) 2002 Red Hat Inc.
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -27,6 +28,7 @@
#include <dbus/dbus-errors.h>
#include <dbus/dbus-string.h>
#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-transport.h>
DBUS_BEGIN_DECLS;
@@ -42,39 +44,53 @@ typedef enum
DBUS_AUTH_STATE_AUTHENTICATED
} DBusAuthState;
-DBusAuth* _dbus_auth_server_new (void);
-DBusAuth* _dbus_auth_client_new (void);
-void _dbus_auth_ref (DBusAuth *auth);
-void _dbus_auth_unref (DBusAuth *auth);
-dbus_bool_t _dbus_auth_set_mechanisms (DBusAuth *auth,
- const char **mechanisms);
-DBusAuthState _dbus_auth_do_work (DBusAuth *auth);
-dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth,
- const DBusString **str);
-void _dbus_auth_bytes_sent (DBusAuth *auth,
- int bytes_sent);
-void _dbus_auth_get_buffer (DBusAuth *auth,
- DBusString **buffer);
-void _dbus_auth_return_buffer (DBusAuth *auth,
- DBusString *buffer,
- int bytes_read);
-void _dbus_auth_get_unused_bytes (DBusAuth *auth,
- const DBusString **str);
-void _dbus_auth_delete_unused_bytes (DBusAuth *auth);
-dbus_bool_t _dbus_auth_needs_encoding (DBusAuth *auth);
-dbus_bool_t _dbus_auth_encode_data (DBusAuth *auth,
- const DBusString *plaintext,
- DBusString *encoded);
-dbus_bool_t _dbus_auth_needs_decoding (DBusAuth *auth);
-dbus_bool_t _dbus_auth_decode_data (DBusAuth *auth,
- const DBusString *encoded,
- DBusString *plaintext);
-void _dbus_auth_set_credentials (DBusAuth *auth,
- const DBusCredentials *credentials);
-void _dbus_auth_get_identity (DBusAuth *auth,
- DBusCredentials *credentials);
-dbus_bool_t _dbus_auth_set_context (DBusAuth *auth,
- const DBusString *context);
+
+DBusAuth* _dbus_auth_server_new (void);
+DBusAuth* _dbus_auth_client_new (void);
+dbus_bool_t _dbus_auth_start (DBusAuth *auth);
+void _dbus_auth_ref (DBusAuth *auth);
+void _dbus_auth_unref (DBusAuth *auth);
+dbus_bool_t _dbus_auth_set_mechanisms (DBusAuth *auth,
+ const char **mechanisms);
+DBusAuthState _dbus_auth_do_work (DBusAuth *auth);
+dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth,
+ const DBusString **str);
+void _dbus_auth_bytes_sent (DBusAuth *auth,
+ int bytes_sent);
+void _dbus_auth_get_buffer (DBusAuth *auth,
+ DBusString **buffer);
+void _dbus_auth_return_buffer (DBusAuth *auth,
+ DBusString *buffer,
+ int bytes_read);
+void _dbus_auth_get_unused_bytes (DBusAuth *auth,
+ const DBusString **str);
+void _dbus_auth_delete_unused_bytes (DBusAuth *auth);
+dbus_bool_t _dbus_auth_needs_encoding (DBusAuth *auth);
+dbus_bool_t _dbus_auth_encode_data (DBusAuth *auth,
+ const DBusString *plaintext,
+ DBusString *encoded);
+dbus_bool_t _dbus_auth_needs_decoding (DBusAuth *auth);
+dbus_bool_t _dbus_auth_decode_data (DBusAuth *auth,
+ const DBusString *encoded,
+ DBusString *plaintext);
+void _dbus_auth_set_credentials (DBusAuth *auth,
+ const DBusCredentials *credentials);
+void _dbus_auth_get_identity (DBusAuth *auth,
+ DBusCredentials *credentials);
+dbus_bool_t _dbus_auth_set_context (DBusAuth *auth,
+ const DBusString *context);
+dbus_bool_t _dbus_auth_set_remote_ip (DBusAuth *auth,
+ DBusString *remote_ip);
+dbus_bool_t _dbus_auth_set_local_ip (DBusAuth *auth,
+ DBusString *local_ip);
+dbus_bool_t _dbus_auth_set_host (DBusAuth *auth,
+ const char *host);
+void _dbus_auth_set_get_username_function (DBusAuth *auth,
+ DBusGetUsernameFunction function);
+void _dbus_auth_set_get_password_function (DBusAuth *auth,
+ DBusGetPasswordFunction function);
+
+
DBUS_END_DECLS;
Index: dbus/dbus-auth.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-auth.c,v
retrieving revision 1.29
diff -u -p -r1.29 dbus-auth.c
--- dbus/dbus-auth.c 30 Sep 2003 02:32:52 -0000 1.29
+++ dbus/dbus-auth.c 19 Nov 2003 22:42:05 -0000
@@ -2,6 +2,7 @@
/* dbus-auth.c Authentication
*
* Copyright (C) 2002, 2003 Red Hat Inc.
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -27,6 +28,9 @@
#include "dbus-keyring.h"
#include "dbus-sha.h"
#include "dbus-userdb.h"
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif /* HAVE_SASL */
/**
* @defgroup DBusAuth Authentication
@@ -82,6 +86,7 @@ typedef struct
DBusProcessAuthCommandFunction func; /**< Function to handle the command */
} DBusAuthCommandHandler;
+
/**
* This function appends an initial client response to the given string
*/
@@ -89,7 +94,7 @@ typedef dbus_bool_t (* DBusInitialRespon
DBusString *response);
/**
- * This function processes a block of data received from the peer.
+ * This function processes a block of data received from the peer
* i.e. handles a DATA command.
*/
typedef dbus_bool_t (* DBusAuthDataFunction) (DBusAuth *auth,
@@ -112,14 +117,30 @@ typedef dbus_bool_t (* DBusAuthDecodeFun
/**
* This function is called when the mechanism is abandoned.
*/
-typedef void (* DBusAuthShutdownFunction) (DBusAuth *auth);
+typedef void (* DBusAuthShutdownFunction) (DBusAuth *auth);
+
+#ifdef HAVE_SASL
+
+int _dbus_sasl_log (void *context,
+ int priority,
+ const char *message);
+int _dbus_sasl_get_username_callback (void *context,
+ int id,
+ const char **result,
+ unsigned *len);
+int _dbus_sasl_get_password_callback (sasl_conn_t *conn,
+ void *context,
+ int id,
+ sasl_secret_t **psecret);
+
+#endif
/**
* Virtual table representing a particular auth mechanism.
*/
typedef struct
{
- const char *mechanism; /**< Name of the mechanism */
+ DBusString mechanism; /**< Name of the mechanism */
DBusAuthDataFunction server_data_func; /**< Function on server side for DATA */
DBusAuthEncodeFunction server_encode_func; /**< Function on server side to encode */
DBusAuthDecodeFunction server_decode_func; /**< Function on server side to decode */
@@ -131,6 +152,7 @@ typedef struct
DBusAuthShutdownFunction client_shutdown_func; /**< Function on client side for shutdown */
} DBusAuthMechanismHandler;
+
/**
* Internal members of DBusAuth.
*/
@@ -176,6 +198,11 @@ struct DBusAuth
unsigned int already_got_mechanisms : 1; /**< Client already got mech list */
unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */
unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */
+ DBusAuthMechanismHandler *all_mechanisms; /**< All possible auth mechanisms */
+ DBusString local_ip; /**< Local IP address in case of a tcp domain socket */
+ DBusString remote_ip; /**< Remote IP address in case of a tcp domain socket */
+ void *sasl_context; /**< SASL context or NULL when SASL isn't enabled */
+ void *sasl_callbacks; /**< pointer to a sasl_callback_t */
};
/**
@@ -186,21 +213,33 @@ typedef struct
DBusAuth base; /**< Parent class */
DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */
-
+ DBusString host; /**< FQDN of host connecting to */
+ DBusString username; /** username */
+ DBusGetUsernameFunction get_username_function; /** function to call when a username is needed */
+ DBusString password; /** password */
+ DBusGetPasswordFunction get_password_function; /** function to call when a password is needed */
+ void *sasl_secret; /** pointer to a sasl_secret_t */
} DBusAuthClient;
-/**
+/** if(!_dbus_string_init(& DBUS_AUTH_CLIENT(auth)->host))
+ goto nomem;
+
* "Subclass" of DBusAuth for server side.
*/
typedef struct
{
- DBusAuth base; /**< Parent class */
+ DBusAuth base; /**< Parent class */
- int failures; /**< Number of times client has been rejected */
- int max_failures; /**< Number of times we reject before disconnect */
+ int failures; /**< Number of times client has been rejected */
+ int max_failures; /**< Number of times we reject before disconnect */
+ dbus_bool_t allready_replyed; /**< TRUE if we allready replyed to a first response */
} DBusAuthServer;
+static dbus_bool_t get_word (const DBusString *str,
+ int *start,
+ DBusString *word);
+static dbus_bool_t init_all_mechanisms (DBusAuth *auth);
static dbus_bool_t process_auth (DBusAuth *auth,
const DBusString *command,
const DBusString *args);
@@ -232,6 +271,8 @@ static dbus_bool_t process_error_client
static dbus_bool_t client_try_next_mechanism (DBusAuth *auth);
static dbus_bool_t send_rejected (DBusAuth *auth);
+static dbus_bool_t dbus_auth_sasl_client_new (DBusAuth *auth);
+static dbus_bool_t dbus_auth_sasl_server_new (DBusAuth *auth);
static DBusAuthCommandHandler
server_handlers[] = {
@@ -280,6 +321,13 @@ client_handlers[] = {
*/
#define DBUS_AUTH_NAME(auth) (DBUS_AUTH_IS_SERVER(auth) ? "server" : "client")
+
+#ifdef HAVE_SASL
+static dbus_bool_t sasl_client_initialized = FALSE;
+static dbus_bool_t sasl_server_initialized = FALSE;
+#endif /* HAVE_SASL */
+
+
static DBusAuth*
_dbus_auth_new (int size)
{
@@ -324,9 +372,16 @@ _dbus_auth_new (int size)
/* default context if none is specified */
if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
goto enomem_5;
-
- return auth;
+ if (!_dbus_string_init (&auth->remote_ip))
+ goto enomem_5;
+
+ if (!_dbus_string_init (&auth->local_ip))
+ goto enomem_6;
+
+ return auth;
+ enomem_6:
+ _dbus_string_free (&auth->remote_ip);
enomem_5:
_dbus_string_free (&auth->challenge);
enomem_4:
@@ -357,7 +412,7 @@ shutdown_mech (DBusAuth *auth)
if (auth->mech != NULL)
{
_dbus_verbose ("%s: Shutting down mechanism %s\n",
- DBUS_AUTH_NAME (auth), auth->mech->mechanism);
+ DBUS_AUTH_NAME (auth), _dbus_string_get_const_data(&auth->mech->mechanism));
if (DBUS_AUTH_IS_CLIENT (auth))
(* auth->mech->client_shutdown_func) (auth);
@@ -388,7 +443,8 @@ sha1_compute_hash (DBusAuth *aut
retval = FALSE;
if (!_dbus_string_init (&cookie))
- return FALSE;
+ return FALSE;
+
if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id,
&cookie))
@@ -612,7 +668,7 @@ sha1_handle_second_client_response (DBus
{
/* We are expecting a response which is the hex-encoded client
* challenge, space, then SHA-1 hash of the concatenation of our
- * challenge, ":", client challenge, ":", secret key, all
+ * challenge, ":", client challenge, "s:", secret key, all
* hex-encoded.
*/
int i;
@@ -869,7 +925,6 @@ handle_client_data_cookie_sha1_mech (DBu
_dbus_assert (!dbus_error_is_set (&error));
}
}
-
_dbus_assert (auth->keyring != NULL);
if (!_dbus_string_init (&tmp))
@@ -1119,54 +1174,534 @@ handle_client_shutdown_external_mech (DB
}
-/* Put mechanisms here in order of preference.
- * What I eventually want to have is:
- *
- * - a mechanism that checks UNIX domain socket credentials
- * - a simple magic cookie mechanism like X11 or ICE
- * - mechanisms that chain to Cyrus SASL, so we can use anything it
- * offers such as Kerberos, X509, whatever.
- *
- */
-static const DBusAuthMechanismHandler
-all_mechanisms[] = {
- { "EXTERNAL",
- handle_server_data_external_mech,
- NULL, NULL,
- handle_server_shutdown_external_mech,
- handle_client_initial_response_external_mech,
- handle_client_data_external_mech,
- NULL, NULL,
- handle_client_shutdown_external_mech },
- { "DBUS_COOKIE_SHA1",
- handle_server_data_cookie_sha1_mech,
- NULL, NULL,
- handle_server_shutdown_cookie_sha1_mech,
- handle_client_initial_response_cookie_sha1_mech,
- handle_client_data_cookie_sha1_mech,
- NULL, NULL,
- handle_client_shutdown_cookie_sha1_mech },
- { NULL, NULL }
-};
+
+#ifdef HAVE_SASL
+
+static dbus_bool_t
+handle_server_data_sasl_mech (DBusAuth *auth,
+ const DBusString *data)
+{
+ int result,outlen;
+ const char *out;
+ DBusString server_response;
+ dbus_bool_t retval = FALSE;
+
+ if(!_dbus_string_init(&server_response))
+ return retval;
+
+ if(! DBUS_AUTH_SERVER(auth)->allready_replyed)
+ {
+ result=sasl_server_start((sasl_conn_t * ) auth->sasl_context,
+ _dbus_string_get_const_data(&auth->mech->mechanism),
+ _dbus_string_get_const_data(data),
+ _dbus_string_get_length(data),
+ &out,
+ &outlen);
+ }
+ else
+ {
+ result=sasl_server_step((sasl_conn_t * ) auth->sasl_context,
+ _dbus_string_get_const_data(data),
+ _dbus_string_get_length(data),
+ &out,
+ &outlen);
+ }
+ if(result != SASL_OK && result != SASL_CONTINUE )
+ {
+ _dbus_string_free(&server_response);
+ return send_rejected(auth);
+ }
+
+ DBUS_AUTH_SERVER(auth)->allready_replyed = TRUE;
+
+ if(result == SASL_CONTINUE)
+ {
+ if(!_dbus_string_append_len(&server_response,out,outlen))
+ goto out_1;
+
+ if(!_dbus_string_append(&auth->outgoing,"DATA "))
+ goto out_1;
+
+ if (!_dbus_string_base64_encode (&server_response, 0,
+ &auth->outgoing,
+ _dbus_string_get_length (&auth->outgoing)))
+ goto out_1;
+ retval=TRUE;
+ }
+ else
+ {
+ DBusString username;
+ const char *sasl_username=NULL;
+
+ if(sasl_getprop((sasl_conn_t *) auth->sasl_context,SASL_USERNAME,(const void **) &sasl_username) == SASL_OK
+ && sasl_username != NULL )
+ {
+ _dbus_string_init_const(&username,sasl_username);
+ if(!_dbus_credentials_from_username (&username, &auth->authorized_identity))
+ goto out_1;
+ }
+
+ if(!_dbus_string_append(&auth->outgoing,"OK\r\n"))
+ goto out_1;
+
+ auth->authenticated_pending_begin = TRUE;
+ retval=TRUE;
+ }
+
+out_1:
+ _dbus_string_free(&server_response);
+
+ return retval;
+
+}
+
+
+static void
+handle_server_shutdown_sasl_mech (DBusAuth *auth)
+{
+}
+
+
+static dbus_bool_t
+handle_client_initial_response_sasl_mech (DBusAuth *auth,
+ DBusString *response)
+{
+ int result,outlen;
+ const char *out,*mech_using=NULL;
+ DBusString client_response;
+ dbus_bool_t retval = FALSE;
+
+
+ if(!_dbus_string_init(&client_response))
+ return retval;
+
+ result=sasl_client_start((sasl_conn_t * ) auth->sasl_context,
+ _dbus_string_get_const_data(&auth->mech->mechanism),
+ NULL,
+ &out,
+ &outlen,
+ &mech_using);
+
+ if(result == SASL_OK || result == SASL_CONTINUE)
+ {
+ if(!_dbus_string_append_len(&client_response,out,outlen))
+ goto out_1;
+ if (!_dbus_string_base64_encode (&client_response, 0,
+ response,
+ _dbus_string_get_length (response)))
+ goto out_1;
+ retval=TRUE;
+ }
+
+out_1:
+ _dbus_string_free(&client_response);
+
+ return retval;
+}
+
+
+static dbus_bool_t
+handle_client_data_sasl_mech (DBusAuth *auth,
+ const DBusString *data)
+{
+ int result,outlen;
+ const char *out;
+ DBusString client_response;
+ dbus_bool_t retval = FALSE;
+
+ if(!_dbus_string_init(&client_response))
+ return retval;
+
+ result=sasl_client_step((sasl_conn_t * ) auth->sasl_context,
+ _dbus_string_get_const_data(data),
+ _dbus_string_get_length(data),
+ NULL,
+ &out,
+ &outlen);
+
+
+ if(result == SASL_CONTINUE)
+ {
+ if(!_dbus_string_append_len(&client_response,out,outlen))
+ goto out_1;
+ if(!_dbus_string_append(&auth->outgoing,"DATA "))
+ goto out_1;
+ if (!_dbus_string_base64_encode (&client_response, 0,
+ &auth->outgoing,
+ _dbus_string_get_length (&auth->outgoing)))
+ goto out_1;
+ retval=TRUE;
+ }
+
+ if(result == SASL_OK)
+ retval =TRUE;
+
+out_1:
+ _dbus_string_free(&client_response);
+
+ return retval;
+
+}
+
+static void
+handle_client_shutdown_sasl_mech (DBusAuth *auth)
+{
+}
+
+
+int
+_dbus_sasl_log(void *context,
+ int priority,
+ const char *message)
+{
+ if(priority == SASL_LOG_ERR || priority == SASL_LOG_WARN )
+ _dbus_verbose("SASL :%s\n",message);
+
+ return SASL_OK;
+}
+
+int
+_dbus_sasl_get_username_callback(void *context,
+ int id,
+ const char **result,
+ unsigned *len)
+{
+ char const *username=NULL;
+
+ if(! DBUS_AUTH_IS_CLIENT((DBusAuth *) context))
+ return SASL_BADPARAM;
+ if(!result)
+ return SASL_BADPARAM;
+
+ DBusAuthClient *auth = DBUS_AUTH_CLIENT(context);
+
+ switch(id)
+ {
+ case SASL_CB_AUTHNAME:
+ case SASL_CB_USER:
+ if(auth->get_username_function)
+ {
+ if((*auth->get_username_function) (&username) && username)
+ {
+ if(! _dbus_string_set_length(&auth->username,0))
+ goto out_1;
+ if(! _dbus_string_append(&auth->username,username))
+ goto out_1;
+ }
+ }
+ *result=_dbus_string_get_const_data(&auth->username);
+ if(len)
+ *len=_dbus_string_get_length(&auth->username);
+ break;
+ default:
+ return SASL_BADPARAM;
+ }
+
+ return SASL_OK;
+out_1:
+ return SASL_FAIL;
+}
+
+
+int
+_dbus_sasl_get_password_callback(sasl_conn_t *conn,
+ void *context,
+ int id,
+ sasl_secret_t **psecret)
+{
+ char const *password;
+
+ if(!conn || !psecret || id != SASL_CB_PASS)
+ return SASL_BADPARAM;
+
+ DBusAuthClient *auth = DBUS_AUTH_CLIENT(context);
+
+ if(auth->sasl_secret)
+ dbus_free(auth->sasl_secret);
+
+ if(auth->get_username_function)
+ {
+ if((*auth->get_password_function) (&password) && password)
+ {
+ if(! _dbus_string_set_length(&auth->password,0))
+ goto out_1;
+ if(! _dbus_string_append(&auth->password,password))
+ goto out_1;
+ }
+ }
+
+ auth->sasl_secret=(void *) dbus_malloc0(sizeof(sasl_secret_t)+ _dbus_string_get_length(&auth->password));
+ if(!auth->sasl_secret)
+ return SASL_NOMEM;
+
+ *psecret=(sasl_secret_t *) auth->sasl_secret;
+
+ strcpy((char *) (*psecret)->data, _dbus_string_get_data(&auth->password));
+ (*psecret)->len=_dbus_string_get_length(&auth->password);
+
+ return SASL_OK;
+ out_1:
+ return SASL_FAIL;
+}
+
+
+static dbus_bool_t
+dbus_auth_sasl_server_new(DBusAuth *auth)
+{
+ int result;
+ sasl_conn_t *context;
+ const char *local_ip=NULL;
+ const char *remote_ip=NULL;
+
+ /* TODO locking */
+ if(!sasl_server_initialized) {
+ static sasl_callback_t server_callbacks[] = {
+ { SASL_CB_LOG, &_dbus_sasl_log, NULL },
+ { SASL_CB_LIST_END, NULL, NULL }
+ };
+
+ result=sasl_server_init(server_callbacks,"dbus");
+ if(result != SASL_OK )
+ return FALSE;
+ sasl_server_initialized = TRUE;
+ }
+
+ if(_dbus_string_get_length(&auth->local_ip))
+ local_ip=_dbus_string_get_const_data(&auth->local_ip);
+ if(_dbus_string_get_length(&auth->remote_ip))
+ remote_ip=_dbus_string_get_const_data(&auth->remote_ip);
+
+ result=sasl_server_new("dbus",NULL,NULL,local_ip,remote_ip,NULL,0,&context);
+ if( result != SASL_OK )
+ return FALSE;
+
+ auth->sasl_context=(void *) context;
+
+ return TRUE;
+}
+
+
+static dbus_bool_t
+dbus_auth_sasl_client_new(DBusAuth *auth)
+{
+ int result;
+ sasl_conn_t *context;
+ sasl_callback_t *callback=(sasl_callback_t *) auth->sasl_callbacks;
+ const char *local_ip=NULL;
+ const char *remote_ip=NULL;
+ const char *host=NULL;
+
+ /* TODO locking ? */
+ if(!sasl_client_initialized) {
+ callback->id = SASL_CB_USER;
+ callback->proc = &_dbus_sasl_get_username_callback;
+ callback->context = (void *) auth;
+ callback++;
+ callback->id = SASL_CB_AUTHNAME;
+ callback->proc = &_dbus_sasl_get_username_callback;
+ callback->context = (void *) auth;
+ callback++;
+ callback->id = SASL_CB_PASS;
+ callback->proc = &_dbus_sasl_get_password_callback;
+ callback->context = (void *) auth;
+ callback++;
+ callback->id = SASL_CB_LIST_END;
+ callback->proc = NULL;
+ callback->context = NULL;
+
+ result=sasl_client_init((sasl_callback_t *) auth->sasl_callbacks);
+ if(result != SASL_OK )
+ return FALSE;
+ sasl_client_initialized = TRUE;
+ }
+
+ if(_dbus_string_get_length(& DBUS_AUTH_CLIENT(auth)->host))
+ host=_dbus_string_get_const_data(& DBUS_AUTH_CLIENT(auth)->host);
+ if(_dbus_string_get_length(&auth->local_ip))
+ local_ip=_dbus_string_get_const_data(&auth->local_ip);
+ if(_dbus_string_get_length(&auth->remote_ip))
+ remote_ip=_dbus_string_get_const_data(&auth->remote_ip);
+
+ result=sasl_client_new("dbus",host,local_ip,remote_ip,NULL,0,&context);
+ if( result != SASL_OK )
+ return FALSE;
+
+ auth->sasl_context=(void *) context;
+
+ return TRUE;
+}
+
+#endif /* HAVE_SASL */
+
+
+
+/* Initialize all mechanisms we can handle */
+
+dbus_bool_t static
+init_all_mechanisms (DBusAuth *auth)
+{
+ DBusAuthMechanismHandler *mechanism;
+ int number_of_sasl_mechanisms = 0;
+
+ if(auth->all_mechanisms)
+ return TRUE;
+
+#ifdef HAVE_SASL
+ int length;
+ const char *sasl_mechanisms;
+ int result;
+ dbus_bool_t sasl_initialized;
+
+ auth->sasl_callbacks=dbus_new0(sasl_callback_t,4);
+ if(auth->sasl_callbacks)
+ {
+ if(DBUS_AUTH_IS_CLIENT(auth))
+ {
+ sasl_initialized=dbus_auth_sasl_client_new(auth);
+ }
+ else
+ {
+ sasl_initialized=dbus_auth_sasl_server_new(auth);
+ }
+
+ if(sasl_initialized)
+ {
+ result=sasl_listmech((sasl_conn_t * ) auth->sasl_context,
+ NULL,
+ "",
+ " ",
+ "",
+ &sasl_mechanisms,
+ &length,
+ &number_of_sasl_mechanisms);
+ if( result != SASL_OK )
+ number_of_sasl_mechanisms=0;
+ }
+ }
+#endif /* HAVE_SASL */
+ mechanism=(DBusAuthMechanismHandler *) dbus_malloc0((3+number_of_sasl_mechanisms) * sizeof(DBusAuthMechanismHandler));
+ if ( mechanism == NULL )
+ return FALSE;
+
+ auth->all_mechanisms=mechanism;
+
+ _dbus_string_init_const (&mechanism->mechanism, "EXTERNAL");
+ mechanism->server_data_func = handle_server_data_external_mech;
+ mechanism->server_encode_func = NULL;
+ mechanism->server_decode_func = NULL;
+ mechanism->server_shutdown_func = handle_server_shutdown_external_mech;
+ mechanism->client_initial_response_func = handle_client_initial_response_external_mech;
+ mechanism->client_data_func = handle_client_data_external_mech;
+ mechanism->client_encode_func = NULL;
+ mechanism->client_decode_func = NULL;
+ mechanism->client_shutdown_func = handle_client_shutdown_external_mech;
+
+ mechanism++;
+ _dbus_string_init_const (&mechanism->mechanism, "DBUS_COOKIE_SHA1");
+ mechanism->server_data_func = handle_server_data_cookie_sha1_mech;
+ mechanism->server_encode_func = NULL;
+ mechanism->server_decode_func = NULL;
+ mechanism->server_shutdown_func = handle_server_shutdown_cookie_sha1_mech;
+ mechanism->client_initial_response_func = handle_client_initial_response_cookie_sha1_mech;
+ mechanism->client_data_func = handle_client_data_cookie_sha1_mech;
+ mechanism->client_encode_func = NULL;
+ mechanism->client_decode_func = NULL;
+ mechanism->client_shutdown_func = handle_client_shutdown_cookie_sha1_mech;
+
+#ifdef HAVE_SASL
+
+ if(number_of_sasl_mechanisms)
+ _dbus_verbose("%s: Merge SASL mechanisms (%s)\n",DBUS_AUTH_NAME (auth),sasl_mechanisms);
+
+ int i;
+ int next = 0;
+ DBusString sasl_mechanisms_copy;
+
+
+ if(!_dbus_string_init(&sasl_mechanisms_copy))
+ goto out_1;
+ if(!_dbus_string_append(&sasl_mechanisms_copy,sasl_mechanisms))
+ goto out_2;
+
+ for(i=0;i<number_of_sasl_mechanisms;i++)
+ {
+ mechanism++;
+ if(!_dbus_string_init (&mechanism->mechanism))
+ goto out_3;
+ if(!get_word (&sasl_mechanisms_copy,&next, &mechanism->mechanism))
+ goto out_4;
+ mechanism->server_data_func = handle_server_data_sasl_mech;
+ mechanism->server_encode_func = NULL;
+ mechanism->server_decode_func = NULL;
+ mechanism->server_shutdown_func = handle_server_shutdown_sasl_mech;
+ mechanism->client_initial_response_func = handle_client_initial_response_sasl_mech;
+ mechanism->client_data_func = handle_client_data_sasl_mech;
+ mechanism->client_encode_func = NULL;
+ mechanism->client_decode_func = NULL;
+ mechanism->client_shutdown_func = handle_client_shutdown_sasl_mech;
+ }
+
+ goto out_2;
+
+ out_4:
+ _dbus_string_free(&mechanism->mechanism);
+ out_3:
+ mechanism--;
+ out_2:
+ _dbus_string_free(&sasl_mechanisms_copy);
+ out_1:
+#endif /* HAVE_SASL */
+
+ mechanism++;
+ _dbus_string_init_const(&mechanism->mechanism,"");
+ mechanism->server_data_func = NULL;
+
+ return TRUE;
+}
+
+
+static void
+free_all_mechanisms (DBusAuth *auth)
+{
+ int i;
+
+ if( auth->all_mechanisms )
+ {
+ i = 0;
+ while (auth->all_mechanisms[i].server_data_func != NULL)
+ {
+ _dbus_string_free( &auth->all_mechanisms[i].mechanism );
+ i++;
+ }
+ /* and the last one */
+ _dbus_string_free( &auth->all_mechanisms[i].mechanism );
+
+ dbus_free(auth->all_mechanisms);
+
+ auth->all_mechanisms = NULL;
+ }
+}
+
static const DBusAuthMechanismHandler*
-find_mech (const DBusString *name,
- char **allowed_mechs)
+find_mech (DBusAuth *auth,
+ const DBusString *name,
+ char **allowed_mechs)
{
int i;
-
+
if (allowed_mechs != NULL &&
!_dbus_string_array_contains ((const char**) allowed_mechs,
_dbus_string_get_const_data (name)))
return NULL;
i = 0;
- while (all_mechanisms[i].mechanism != NULL)
+ while (auth->all_mechanisms[i].server_data_func != NULL)
{
- if (_dbus_string_equal_c_str (name,
- all_mechanisms[i].mechanism))
+ if (_dbus_string_equal (name,
+ &auth->all_mechanisms[i].mechanism))
- return &all_mechanisms[i];
+ return &auth->all_mechanisms[i];
++i;
}
@@ -1174,6 +1709,7 @@ find_mech (const DBusString *name,
return NULL;
}
+
static dbus_bool_t
send_rejected (DBusAuth *auth)
{
@@ -1188,20 +1724,37 @@ send_rejected (DBusAuth *auth)
"REJECTED"))
goto nomem;
- i = 0;
- while (all_mechanisms[i].mechanism != NULL)
- {
- if (!_dbus_string_append (&command,
+ if (auth->allowed_mechs != NULL )
+ {
+ i = 0;
+ while(auth->allowed_mechs[i] != NULL )
+ {
+ if (!_dbus_string_append (&command,
" "))
- goto nomem;
+ goto nomem;
- if (!_dbus_string_append (&command,
- all_mechanisms[i].mechanism))
- goto nomem;
+ if (!_dbus_string_append (&command,auth->allowed_mechs[i]))
+ goto nomem;
+
+ i++;
+ }
+ }
+ else
+ {
+ i = 0;
+ while (auth->all_mechanisms[i].server_data_func != NULL)
+ {
+ if (!_dbus_string_append (&command,
+ " "))
+ goto nomem;
+
+ if (!_dbus_string_append (&command,
+ _dbus_string_get_const_data(&auth->all_mechanisms[i].mechanism)))
+ goto nomem;
- ++i;
- }
-
+ ++i;
+ }
+ }
if (!_dbus_string_append (&command, "\r\n"))
goto nomem;
@@ -1229,6 +1782,9 @@ process_auth (DBusAuth *auth,
const DBusString *command,
const DBusString *args)
{
+
+ if(!init_all_mechanisms(auth))
+ return FALSE;
if (auth->mech)
{
/* We are already using a mechanism, client is on crack */
@@ -1280,13 +1836,13 @@ process_auth (DBusAuth *auth,
if (!_dbus_string_base64_decode (&base64_response, 0,
&decoded_response, 0))
goto failed;
-
- auth->mech = find_mech (&mech, auth->allowed_mechs);
+
+ auth->mech = find_mech (auth, &mech, auth->allowed_mechs);
if (auth->mech != NULL)
{
_dbus_verbose ("%s: Trying mechanism %s with initial response of %d bytes\n",
DBUS_AUTH_NAME (auth),
- auth->mech->mechanism,
+ _dbus_string_get_const_data(&auth->mech->mechanism),
_dbus_string_get_length (&decoded_response));
if (!(* auth->mech->server_data_func) (auth,
@@ -1445,14 +2001,14 @@ record_mechanisms (DBusAuth *aut
if (!_dbus_string_init (&m))
goto nomem;
-
+
if (!get_word (args, &next, &m))
{
_dbus_string_free (&m);
goto nomem;
}
- mech = find_mech (&m, auth->allowed_mechs);
+ mech = find_mech (auth, &m, auth->allowed_mechs);
if (mech != NULL)
{
@@ -1466,7 +2022,7 @@ record_mechanisms (DBusAuth *aut
*/
_dbus_verbose ("%s: Adding mechanism %s to list we will try\n",
- DBUS_AUTH_NAME (auth), mech->mechanism);
+ DBUS_AUTH_NAME (auth), _dbus_string_get_const_data(&mech->mechanism));
if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
(void*) mech))
@@ -1512,11 +2068,11 @@ client_try_next_mechanism (DBusAuth *aut
if (auth->allowed_mechs != NULL &&
!_dbus_string_array_contains ((const char**) auth->allowed_mechs,
- mech->mechanism))
+ _dbus_string_get_const_data(&mech->mechanism)))
{
/* don't try this one after all */
_dbus_verbose ("%s: Mechanism %s isn't in the list of allowed mechanisms\n",
- DBUS_AUTH_NAME (auth), mech->mechanism);
+ DBUS_AUTH_NAME (auth), _dbus_string_get_const_data(&mech->mechanism));
mech = NULL;
_dbus_list_pop_first (& client->mechs_to_try);
}
@@ -1538,12 +2094,14 @@ client_try_next_mechanism (DBusAuth *aut
}
if (!_dbus_string_append (&auth_command,
- mech->mechanism))
+ _dbus_string_get_const_data(&mech->mechanism)))
{
_dbus_string_free (&auth_command);
return FALSE;
}
+ auth->mech = mech;
+
if (mech->client_initial_response_func != NULL)
{
if (!_dbus_string_append (&auth_command, " "))
@@ -1554,6 +2112,8 @@ client_try_next_mechanism (DBusAuth *aut
if (!(* mech->client_initial_response_func) (auth, &auth_command))
{
+ /* pop this one to avoid looping */
+ _dbus_list_pop_first (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
_dbus_string_free (&auth_command);
return FALSE;
}
@@ -1574,12 +2134,11 @@ client_try_next_mechanism (DBusAuth *aut
return FALSE;
}
- auth->mech = mech;
_dbus_list_pop_first (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
_dbus_verbose ("%s: Trying mechanism %s\n",
DBUS_AUTH_NAME (auth),
- auth->mech->mechanism);
+ _dbus_string_get_const_data(&auth->mech->mechanism));
_dbus_string_free (&auth_command);
@@ -1669,7 +2228,7 @@ process_data_client (DBusAuth *a
"ERROR \"Got DATA when not in an auth exchange\"\r\n"))
return FALSE;
}
-
+
return TRUE;
}
@@ -1850,10 +2409,11 @@ _dbus_auth_server_new (void)
*/
server_auth->failures = 0;
server_auth->max_failures = 6;
-
+
return auth;
}
+
/**
* Creates a new auth conversation object for the client side.
* See doc/dbus-sasl-profile.txt for full details on what
@@ -1865,6 +2425,7 @@ DBusAuth*
_dbus_auth_client_new (void)
{
DBusAuth *auth;
+ DBusAuthClient *client_auth;
auth = _dbus_auth_new (sizeof (DBusAuthClient));
if (auth == NULL)
@@ -1872,24 +2433,50 @@ _dbus_auth_client_new (void)
auth->handlers = client_handlers;
- /* Add a default mechanism to try */
- if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
- (void*) &all_mechanisms[0]))
- {
- _dbus_auth_unref (auth);
- return NULL;
- }
+ client_auth = DBUS_AUTH_CLIENT (auth);
- /* Now try the mechanism we just added */
- if (!client_try_next_mechanism (auth))
- {
- _dbus_auth_unref (auth);
- return NULL;
- }
-
+ if(!_dbus_string_init(& client_auth->host))
+ goto nomem;
+
+ if(!_dbus_string_init(& client_auth->username))
+ goto nomem;
+ if(!_dbus_string_init(& client_auth->password))
+ goto nomem;
+
return auth;
+nomem:
+ _dbus_auth_unref(auth);
+
+ return NULL;
}
+
+/**
+ * Starts the client side authentication process
+ *
+ * @param auth the auth conversation
+ * @returns #TRUE if successfull
+ */
+dbus_bool_t
+_dbus_auth_start (DBusAuth *auth)
+ {
+ if(DBUS_AUTH_IS_CLIENT(auth))
+ {
+ if (!init_all_mechanisms(auth))
+ return FALSE;
+ /* Add a default mechanism to try */
+ if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
+ (void*) &auth->all_mechanisms[0]))
+ return FALSE;
+ if (!client_try_next_mechanism (auth))
+ return FALSE;
+
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
/**
* Increments the refcount of an auth object.
*
@@ -1922,6 +2509,11 @@ _dbus_auth_unref (DBusAuth *auth)
if (DBUS_AUTH_IS_CLIENT (auth))
{
_dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
+ _dbus_string_free(& DBUS_AUTH_CLIENT (auth)->host);
+ _dbus_string_free(& DBUS_AUTH_CLIENT (auth)->username);
+ _dbus_string_free(& DBUS_AUTH_CLIENT (auth)->password);
+ if(DBUS_AUTH_CLIENT (auth)->sasl_secret)
+ dbus_free(DBUS_AUTH_CLIENT (auth)->sasl_secret);
}
if (auth->keyring)
@@ -1932,13 +2524,126 @@ _dbus_auth_unref (DBusAuth *auth)
_dbus_string_free (&auth->identity);
_dbus_string_free (&auth->incoming);
_dbus_string_free (&auth->outgoing);
+ _dbus_string_free (&auth->local_ip);
+ _dbus_string_free (&auth->remote_ip);
dbus_free_string_array (auth->allowed_mechs);
+
+ free_all_mechanisms(auth);
+
+#ifdef HAVE_SASL
+ if(auth->sasl_context)
+ sasl_dispose((sasl_conn_t **) &auth->sasl_context);
+ if(auth->sasl_callbacks)
+ dbus_free(auth->sasl_callbacks);
+#endif /* HAVE_SASL */
dbus_free (auth);
}
}
+
+/**
+ * Sets the remote ip
+ *
+ * @param auth the auth conversation
+ * @param remote_ip the remote ip adress
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_auth_set_remote_ip(DBusAuth *auth,
+ DBusString *remote_ip)
+{
+ int p;
+
+ if(!_dbus_string_copy(remote_ip,0,&auth->remote_ip,0))
+ return FALSE;
+ if(!_dbus_string_find(&auth->remote_ip,0,":",&p))
+ return FALSE;
+ _dbus_string_set_byte(&auth->remote_ip,p,';');
+
+ return TRUE;
+}
+
+
+/**
+ * Sets the local ip
+ *
+ * @param auth the auth conversation
+ * @param local_ip the local ip adress
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_auth_set_local_ip(DBusAuth *auth,
+ DBusString *local_ip)
+{
+ int p;
+
+ if(!_dbus_string_copy(local_ip,0,&auth->local_ip,0))
+ return FALSE;
+ if(!_dbus_string_find(&auth->local_ip,0,":",&p))
+ return FALSE;
+ _dbus_string_set_byte(&auth->local_ip,p,';');
+
+ return TRUE;
+}
+
+
+/**
+ * Sets the host name
+ *
+ * @param auth the auth conversation
+ * @param host host connecting to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_auth_set_host(DBusAuth *auth,
+ const char *host)
+{
+ if(DBUS_AUTH_IS_CLIENT(auth))
+ {
+ if(!_dbus_string_set_length(& DBUS_AUTH_CLIENT(auth)->host,0))
+ return FALSE;
+ if(!_dbus_string_append(& DBUS_AUTH_CLIENT(auth)->host,host))
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * see dbus_connection_set_get_username_function()
+ *
+ * @param auth the auth conversation
+ * @param function to call when a username is needed
+ */
+void
+_dbus_auth_set_get_username_function (DBusAuth *auth,
+ DBusGetUsernameFunction function)
+{
+ if(DBUS_AUTH_IS_CLIENT(auth))
+ {
+ DBUS_AUTH_CLIENT (auth)->get_username_function=function;
+ }
+}
+
+/**
+ * see dbus_connection_set_get_password_function()
+ *
+ * @param auth the auth conversation
+ * @param function to call when a password is needed
+ */
+void
+_dbus_auth_set_get_password_function (DBusAuth *auth,
+ DBusGetPasswordFunction function)
+{
+ if(DBUS_AUTH_IS_CLIENT(auth))
+ {
+ DBUS_AUTH_CLIENT (auth)->get_password_function=function;
+ }
+}
+
+
/**
* Sets an array of authentication mechanism names
* that we are willing to use.
@@ -1969,6 +2674,7 @@ _dbus_auth_set_mechanisms (DBusAuth *
return TRUE;
}
+
/**
* @param auth the auth conversation object
* @returns #TRUE if we're in a final state
Index: dbus/dbus-connection.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.h,v
retrieving revision 1.25
diff -u -p -r1.25 dbus-connection.h
--- dbus/dbus-connection.h 30 Sep 2003 02:32:52 -0000 1.25
+++ dbus/dbus-connection.h 19 Nov 2003 22:42:20 -0000
@@ -2,6 +2,7 @@
/* dbus-connection.h DBusConnection object
*
* Copyright (C) 2002, 2003 Red Hat Inc.
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -84,6 +85,8 @@ typedef void (* DBusWakeupMainFun
typedef dbus_bool_t (* DBusAllowUnixUserFunction) (DBusConnection *connection,
unsigned long uid,
void *data);
+typedef dbus_bool_t (* DBusGetPasswordFunction) (const char **password);
+typedef dbus_bool_t (* DBusGetUsernameFunction) (const char **username);
typedef void (* DBusPendingCallNotifyFunction) (DBusPendingCall *pending,
void *user_data);
@@ -148,6 +151,11 @@ void dbus_connection_set_u
DBusAllowUnixUserFunction function,
void *data,
DBusFreeFunction free_data_function);
+void dbus_connection_set_get_username_function (DBusConnection *connection,
+ DBusGetUsernameFunction function);
+void dbus_connection_set_get_password_function (DBusConnection *connection,
+ DBusGetPasswordFunction function);
+
int dbus_watch_get_fd (DBusWatch *watch);
Index: dbus/dbus-connection.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.c,v
retrieving revision 1.73
diff -u -p -r1.73 dbus-connection.c
--- dbus/dbus-connection.c 26 Oct 2003 15:36:15 -0000 1.73
+++ dbus/dbus-connection.c 19 Nov 2003 22:42:35 -0000
@@ -2,6 +2,7 @@
/* dbus-connection.c DBusConnection object
*
* Copyright (C) 2002, 2003 Red Hat Inc.
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -3015,6 +3016,42 @@ dbus_connection_set_unix_user_function (
}
/**
+ * Set the function to call when a username is needed for authentication
+ *
+ * @param connection the connection
+ * @param function to call when username is needed
+ */
+void
+dbus_connection_set_get_username_function (DBusConnection *connection,
+ DBusGetUsernameFunction function)
+{
+
+ _dbus_return_if_fail (connection != NULL);
+ CONNECTION_LOCK (connection);
+ _dbus_transport_set_get_username_function (connection->transport,
+ function);
+ CONNECTION_UNLOCK (connection);
+
+}
+
+/**
+ * Set the function to call when a password is needed for authentication
+ *
+ * @param connection the connection
+ * @param function to call when password is needed
+ */
+void
+dbus_connection_set_get_password_function (DBusConnection *connection,
+ DBusGetPasswordFunction function)
+{
+ _dbus_return_if_fail (connection != NULL);
+ CONNECTION_LOCK (connection);
+ _dbus_transport_set_get_password_function (connection->transport,
+ function);
+ CONNECTION_UNLOCK (connection);
+}
+
+/**
* Adds a message filter. Filters are handlers that are run on all
* incoming messages, prior to the objects registered with
* dbus_connection_register_object_path(). Filters are run in the
Index: dbus/dbus-sysdeps.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.h,v
retrieving revision 1.36
diff -u -p -r1.36 dbus-sysdeps.h
--- dbus/dbus-sysdeps.h 30 Sep 2003 02:32:53 -0000 1.36
+++ dbus/dbus-sysdeps.h 19 Nov 2003 22:42:47 -0000
@@ -3,6 +3,7 @@
*
* Copyright (C) 2002, 2003 Red Hat, Inc.
* Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -120,6 +121,12 @@ int _dbus_listen_tcp_socket (const cha
dbus_uint32_t port,
DBusError *error);
int _dbus_accept (int listen_fd);
+dbus_bool_t _dbus_transport_is_inet (int transport_fd);
+dbus_bool_t _dbus_transport_get_remote_ip (int transport_fd,
+ DBusString *address);
+dbus_bool_t _dbus_transport_get_local_ip (int transport_fd,
+ DBusString *address);
+
dbus_bool_t _dbus_read_credentials_unix_socket (int client_fd,
DBusCredentials *credentials,
Index: dbus/dbus-sysdeps.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.c,v
retrieving revision 1.67
diff -u -p -r1.67 dbus-sysdeps.c
--- dbus/dbus-sysdeps.c 16 Oct 2003 06:34:51 -0000 1.67
+++ dbus/dbus-sysdeps.c 19 Nov 2003 22:42:59 -0000
@@ -3,6 +3,7 @@
*
* Copyright (C) 2002, 2003 Red Hat, Inc.
* Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -44,6 +45,7 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netdb.h>
#include <grp.h>
@@ -583,7 +585,7 @@ _dbus_listen_unix_socket (const char
* nonblocking.
*
* @param host the host name to connect to
- * @param port the prot to connect to
+ * @param port the port to connect to
* @param error return location for error code
* @returns connection file descriptor or -1 on error
*/
@@ -752,6 +754,7 @@ write_credentials_byte (int
if (bytes_written < 0)
{
+ _dbus_verbose("Errno=%d",errno);
dbus_set_error (error, _dbus_error_from_errno (errno),
"Failed to write credentials byte: %s",
_dbus_strerror (errno));
@@ -968,6 +971,104 @@ _dbus_accept (int listen_fd)
return client_fd;
}
+
+static dbus_bool_t
+get_address (DBusString *address,
+ struct sockaddr_storage *sa)
+
+{
+ char buffer[INET6_ADDRSTRLEN + 1];
+
+ if(sa->ss_family == AF_INET )
+ {
+ if(inet_ntop(sa->ss_family,&((struct sockaddr_in *)sa)->sin_addr,(char *) buffer,INET6_ADDRSTRLEN)== NULL )
+ return FALSE;
+ if(!_dbus_string_append(address,buffer))
+ return FALSE;
+ if(!_dbus_string_append(address,":"))
+ return FALSE;
+ if(!_dbus_string_append_printf(address,"%hu",ntohs(((struct sockaddr_in *)sa)->sin_port)))
+ return FALSE;
+ }
+ else if(sa->ss_family == AF_INET6 )
+ {
+ if(inet_ntop(sa->ss_family,&((struct sockaddr_in6 *)sa)->sin6_addr,(char *) buffer,INET6_ADDRSTRLEN)== NULL )
+ return FALSE;
+ if(!_dbus_string_append(address,":"))
+ return FALSE;
+ if(!_dbus_string_append_printf(address,"%hu",ntohs(((struct sockaddr_in6 *)sa)->sin6_port)))
+ return FALSE;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * Returns true if the address type of the transport_fd is INET
+ *
+ * @param transport_fd the transport file descriptor
+ * @returns #TRUE when address type is AF_INET or AF_INET6
+ */
+dbus_bool_t
+_dbus_transport_is_inet(int transport_fd)
+{
+ struct sockaddr_storage sa;
+ int len=sizeof(sa);
+
+ if(getsockname(transport_fd,(struct sockaddr *) &sa, &len) == -1 )
+ return FALSE;
+
+ if(sa.ss_family == AF_INET || sa.ss_family == AF_INET6 )
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
+ * Get the remote IP address from a transport fd.
+ *
+ * @param transport_fd the transport file descriptor
+ * @param ip_address filled with the remote IP address
+ * @returns #TRUE when successfull
+ */
+dbus_bool_t
+_dbus_transport_get_remote_ip (int transport_fd,
+ DBusString *address)
+{
+ struct sockaddr_storage sa;
+ int len=sizeof(sa);
+
+ if(getpeername(transport_fd,(struct sockaddr *) &sa,&len) == -1 )
+ return FALSE;
+
+ return get_address(address,&sa);
+}
+
+
+/**
+ * Get the local IP address from a transport fd.
+ *
+ * @param transport_fd the transport file descriptor
+ * @param ip_address filled with the local IP address
+ * @returns #TRUE when successfull
+ */
+dbus_bool_t
+_dbus_transport_get_local_ip (int transport_fd,
+ DBusString *address)
+{
+ struct sockaddr_storage sa;
+ int len=sizeof(sa);
+
+ if(getsockname(transport_fd,(struct sockaddr *) &sa,&len) == -1 )
+ return FALSE;
+
+ return get_address(address,&sa);
+}
+
+
/** @} */
/**
Index: dbus/dbus-transport-unix.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-transport-unix.c,v
retrieving revision 1.33
diff -u -p -r1.33 dbus-transport-unix.c
--- dbus/dbus-transport-unix.c 21 Jun 2003 07:51:39 -0000 1.33
+++ dbus/dbus-transport-unix.c 19 Nov 2003 22:43:24 -0000
@@ -2,6 +2,7 @@
/* dbus-transport-unix.c UNIX socket subclasses of DBusTransport
*
* Copyright (C) 2002, 2003 Red Hat Inc.
+ * Copyright (C) 2003 Dobs
*
* Licensed under the Academic Free License version 1.2
*
@@ -1024,6 +1025,7 @@ _dbus_transport_new_for_fd (int
const DBusString *address)
{
DBusTransportUnix *unix_transport;
+ DBusString ip;
unix_transport = dbus_new0 (DBusTransportUnix, 1);
if (unix_transport == NULL)
@@ -1056,6 +1058,23 @@ _dbus_transport_new_for_fd (int
unix_transport->fd = fd;
unix_transport->message_bytes_written = 0;
+
+ /* if this is a tcp socket set the local and remote address on the auth object */
+ if(_dbus_transport_is_inet(fd)) {
+ if(!_dbus_string_init(&ip))
+ goto failed_5;
+ if(!_dbus_transport_get_remote_ip(fd,&ip))
+ goto failed_6;
+ if(!_dbus_auth_set_remote_ip( ((DBusTransport *) unix_transport)->auth,&ip))
+ goto failed_6;
+ if(!_dbus_string_set_length(&ip,0))
+ goto failed_6;
+ if(!_dbus_transport_get_local_ip(fd,&ip))
+ goto failed_6;
+ if(!_dbus_auth_set_local_ip(((DBusTransport *) unix_transport)->auth,&ip))
+ goto failed_6;
+ _dbus_string_free(&ip);
+ }
/* These values should probably be tunable or something. */
unix_transport->max_bytes_read_per_iteration = 2048;
@@ -1063,6 +1082,10 @@ _dbus_transport_new_for_fd (int
return (DBusTransport*) unix_transport;
+ failed_6:
+ _dbus_string_free(&ip);
+ failed_5:
+ _dbus_transport_finalize_base ((DBusTransport *) unix_transport);
failed_4:
_dbus_watch_unref (unix_transport->read_watch);
failed_3:
@@ -1205,8 +1228,17 @@ _dbus_transport_new_for_tcp_socket (cons
}
_dbus_string_free (&address);
+
+ if(!_dbus_auth_set_host(transport->auth,host))
+ goto nomem;
return transport;
+
+nomem:
+ _dbus_close(fd,NULL);
+ unix_finalize(transport);
+
+ return NULL;
}
/** @} */
Index: dbus/dbus-transport.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-transport.h,v
retrieving revision 1.11
diff -u -p -r1.11 dbus-transport.h
--- dbus/dbus-transport.h 16 Apr 2003 23:01:33 -0000 1.11
+++ dbus/dbus-transport.h 19 Nov 2003 22:43:39 -0000
@@ -30,43 +30,46 @@ DBUS_BEGIN_DECLS;
typedef struct DBusTransport DBusTransport;
-DBusTransport* _dbus_transport_open (const char *address,
- DBusError *error);
-void _dbus_transport_ref (DBusTransport *transport);
-void _dbus_transport_unref (DBusTransport *transport);
-void _dbus_transport_disconnect (DBusTransport *transport);
-dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport);
-dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport);
-const char* _dbus_transport_get_address (DBusTransport *transport);
-dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport,
- DBusWatch *watch,
- unsigned int condition);
-dbus_bool_t _dbus_transport_set_connection (DBusTransport *transport,
- DBusConnection *connection);
-void _dbus_transport_messages_pending (DBusTransport *transport,
- int queue_length);
-void _dbus_transport_do_iteration (DBusTransport *transport,
- unsigned int flags,
- int timeout_milliseconds);
-DBusDispatchStatus _dbus_transport_get_dispatch_status (DBusTransport *transport);
-dbus_bool_t _dbus_transport_queue_messages (DBusTransport *transport);
-void _dbus_transport_set_max_message_size (DBusTransport *transport,
- long size);
-long _dbus_transport_get_max_message_size (DBusTransport *transport);
-void _dbus_transport_set_max_received_size (DBusTransport *transport,
- long size);
-long _dbus_transport_get_max_received_size (DBusTransport *transport);
-dbus_bool_t _dbus_transport_get_unix_user (DBusTransport *transport,
- unsigned long *uid);
-void _dbus_transport_set_unix_user_function (DBusTransport *transport,
- DBusAllowUnixUserFunction function,
- void *data,
- DBusFreeFunction free_data_function,
- void **old_data,
- DBusFreeFunction *old_free_data_function);
-dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
- const char **mechanisms);
-
+DBusTransport* _dbus_transport_open (const char *address,
+ DBusError *error);
+void _dbus_transport_ref (DBusTransport *transport);
+void _dbus_transport_unref (DBusTransport *transport);
+void _dbus_transport_disconnect (DBusTransport *transport);
+dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport);
+dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport);
+const char* _dbus_transport_get_address (DBusTransport *transport);
+dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport,
+ DBusWatch *watch,
+ unsigned int condition);
+dbus_bool_t _dbus_transport_set_connection (DBusTransport *transport,
+ DBusConnection *connection);
+void _dbus_transport_messages_pending (DBusTransport *transport,
+ int queue_length);
+void _dbus_transport_do_iteration (DBusTransport *transport,
+ unsigned int flags,
+ int timeout_milliseconds);
+DBusDispatchStatus _dbus_transport_get_dispatch_status (DBusTransport *transport);
+dbus_bool_t _dbus_transport_queue_messages (DBusTransport *transport);
+void _dbus_transport_set_max_message_size (DBusTransport *transport,
+ long size);
+long _dbus_transport_get_max_message_size (DBusTransport *transport);
+void _dbus_transport_set_max_received_size (DBusTransport *transport,
+ long size);
+long _dbus_transport_get_max_received_size (DBusTransport *transport);
+dbus_bool_t _dbus_transport_get_unix_user (DBusTransport *transport,
+ unsigned long *uid);
+void _dbus_transport_set_unix_user_function (DBusTransport *transport,
+ DBusAllowUnixUserFunction function,
+ void *data,
+ DBusFreeFunction free_data_function,
+ void **old_data,
+ DBusFreeFunction *old_free_data_function);
+dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
+ const char **mechanisms);
+void _dbus_transport_set_get_username_function (DBusTransport *transport,
+ DBusGetUsernameFunction function);
+void _dbus_transport_set_get_password_function (DBusTransport *transport,
+ DBusGetPasswordFunction function)
Index: dbus/dbus-transport.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-transport.c,v
retrieving revision 1.35
diff -u -p -r1.35 dbus-transport.c
--- dbus/dbus-transport.c 26 Oct 2003 15:36:15 -0000 1.35
+++ dbus/dbus-transport.c 19 Nov 2003 22:43:49 -0000
@@ -116,7 +116,7 @@ _dbus_transport_init_base (DBusTransport
_dbus_message_loader_unref (loader);
return FALSE;
}
-
+
if (server)
{
_dbus_assert (address == NULL);
@@ -340,10 +340,13 @@ _dbus_transport_open (const char *ad
}
else
{
+ _dbus_auth_start(transport->auth);
dbus_error_free (&first_error);
}
dbus_address_entries_free (entries);
+
+
return transport;
bad_address:
@@ -979,5 +982,31 @@ _dbus_transport_set_auth_mechanisms (DBu
return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
}
+/**
+ * see dbus_connection_set_get_username_function()
+ *
+ * @param transport the transport
+ * @param function the function to call when a username is needed
+ */
+void
+_dbus_transport_set_get_username_function (DBusTransport *transport,
+ DBusGetUsernameFunction function)
+{
+ _dbus_auth_set_get_username_function (transport->auth,function);
+}
+
+/**
+ * see dbus_connection_set_get_password_function()
+ *
+ * @param transport the transport
+ * @param function the function to call when a password is needed
+ */
+void
+_dbus_transport_set_get_password_function (DBusTransport *transport,
+ DBusGetPasswordFunction function)
+{
+ _dbus_auth_set_get_password_function (transport->auth,function);
+}
+
/** @} */
Index: doc/TODO
===================================================================
RCS file: /cvs/dbus/dbus/doc/TODO,v
retrieving revision 1.34
diff -u -p -r1.34 TODO
--- doc/TODO 1 Nov 2003 18:24:32 -0000 1.34
+++ doc/TODO 19 Nov 2003 23:35:02 -0000
@@ -128,3 +128,15 @@
- rename HEADER_FIELD_SERVICE -> HEADER_FIELD_DESTINATION
and HEADER_FIELD_SENDER_SERVICE -> HEADER_FIELD_SENDER
for both dbus-protocol.h and in the spec
+
+ - cleanup sasl stuff, maybe move most of it to dbus-sysdeps
+ in one go with implement the state machine :-)
+ ( see above )
+
+ - maybe don't compile sasl as an option so we can use the
+ sasl base64 en/decoding implementations
+
+ - modify the dbus-monitor and dbus-send utilities to support
+ the username and password callbacks.
+
+ - remove the implicit call to dbus_bus_register in dbus_bus_get
--=-CztVctplTNL1o+sia54b--