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--