diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./client/mysql.cc ../../mysql-5.0.34/client/mysql.cc
--- ./client/mysql.cc	2007-01-17 12:52:06.000000000 +0300
+++ ../../mysql-5.0.34/client/mysql.cc	2007-02-22 07:37:13.000000000 +0300
@@ -140,6 +140,9 @@
                default_pager_set= 0, opt_sigint_ignore= 0,
                show_warnings= 0;
 static volatile int executing_query= 0, interrupted_query= 0;
+#ifdef HAVE_SASL
+static my_bool opt_client_sasl=1;
+#endif
 static ulong opt_max_allowed_packet, opt_net_buffer_length;
 static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
 static my_string opt_mysql_unix_port=0;
@@ -757,6 +760,9 @@
   {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
     (gptr*) &show_warnings, (gptr*) &show_warnings, 0, GET_BOOL, NO_ARG, 
     0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SASL
+  {"sasl", '9', "Enable SASL authentication in client if possible.", (gptr*) &opt_client_sasl,    (gptr*) &opt_client_sasl, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+#endif
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -3256,6 +3262,9 @@
   if (shared_memory_base_name)
     mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
 #endif
+#ifdef HAVE_SASL
+  mysql.options.sasl=opt_client_sasl;
+#endif 
   if (safe_updates)
   {
     char init_command[100];
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./client/mysqldump.c ../../mysql-5.0.34/client/mysqldump.c
--- ./client/mysqldump.c	2007-01-17 12:52:07.000000000 +0300
+++ ../../mysql-5.0.34/client/mysqldump.c	2007-02-21 23:37:16.000000000 +0300
@@ -96,6 +96,9 @@
                 opt_hex_blob=0, opt_order_by_primary=0, opt_ignore=0,
                 opt_complete_insert= 0, opt_drop_database= 0,
                 opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1;
+#ifdef HAVE_SASL
+static my_bool opt_client_sasl=1;
+#endif
 static ulong opt_max_allowed_packet, opt_net_buffer_length;
 static MYSQL mysql_connection,*mysql=0;
 static my_bool insert_pat_inited= 0, info_flag;
@@ -414,6 +417,11 @@
    (gptr*) &where, (gptr*) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
    NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SASL
+  {"sasl", '9', "Enable SASL authentication in client if possible.", (gptr*) &opt_client_sasl,    (gptr*) &opt_client_sasl,
+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+#endif
+
   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -981,6 +990,9 @@
     mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
 #endif
   mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
+#ifdef HAVE_SASL
+  mysql_connection.options.sasl=opt_client_sasl;
+#endif
   if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
                                   NULL,opt_mysql_port,opt_mysql_unix_port,
                                   0)))
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./include/mysql.h ../../mysql-5.0.34/include/mysql.h
--- ./include/mysql.h	2007-01-17 12:52:36.000000000 +0300
+++ ../../mysql-5.0.34/include/mysql.h	2007-02-22 07:37:13.000000000 +0300
@@ -203,7 +203,7 @@
   my_bool secure_auth;
   /* 0 - never report, 1 - always report (default) */
   my_bool report_data_truncation;
-
+  my_bool sasl;
   /* function pointers for local infile support */
   int (*local_infile_init)(void **, const char *, void *);
   int (*local_infile_read)(void *, char *, unsigned int);
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./libmysqld/client.c ../../mysql-5.0.34/libmysqld/client.c
--- ./libmysqld/client.c	2007-01-17 12:51:53.000000000 +0300
+++ ../../mysql-5.0.34/libmysqld/client.c	2007-02-22 07:37:13.000000000 +0300
@@ -113,6 +113,10 @@
 #include "client_settings.h"
 #include <sql_common.h>
 
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 uint		mysql_port=0;
 char		*mysql_unix_port= 0;
 const char	*unknown_sqlstate= "HY000";
@@ -935,6 +939,9 @@
   "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
   "multi-results", "multi-statements", "multi-queries", "secure-auth",
   "report-data-truncation",
+#ifdef HAVE_SASL
+"sasl",
+#endif
   NullS
 };
 
@@ -1149,6 +1156,11 @@
         case 34: /* report-data-truncation */
           options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
           break;
+#ifdef HAVE_SASL
+	case 35: /*allow sasl authentication in clients*/
+	  options->sasl=opt_arg ? atoi(opt_arg) : 1;
+	  break;
+#endif
 	default:
 	  DBUG_PRINT("warning",("unknown option: %s",option[0]));
 	}
@@ -1493,6 +1505,9 @@
 #ifdef HAVE_SMEM
   mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;
 #endif
+#ifdef HAVE_SASL
+  int           use_sasl = 0;
+#endif
 
   mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
   mysql->options.report_data_truncation= TRUE;  /* default */
@@ -1778,13 +1793,81 @@
 }
 C_MODE_END
 
+#ifdef HAVE_SASL
+static int simple(void *context __attribute__((unused)),
+                  int id,
+                  const char **result,
+                  unsigned *len)
+{
+    char * name=strdup((char*)context); 
+    int z;
+    *result = name;
+    DBUG_PRINT("info",("CB simple: name = %s", name));
+    if(len) *len=strlen(name);
+    return SASL_OK;
+}
+
+static int getrealm(void *context __attribute__((unused)), 
+                    int id,
+                    const char **availrealms,
+                    const char **result)
+{
+
+    DBUG_PRINT("info",("CB getrealm: name = %s", availrealms[0]));    
+    return SASL_OK;
+}
+
+static int
+getsecret(sasl_conn_t *conn,
+          void *context __attribute__((unused)),
+          int id,
+          sasl_secret_t **psecret)
+{
+    char *password = context;
+    size_t len;
+    static sasl_secret_t *x;
+    DBUG_PRINT("info",("CB secret: pass = %s", password));
+    len = strlen(password);
+
+    x = (sasl_secret_t *) realloc(x, sizeof(sasl_secret_t) + len);
+  
+    if (!x) {
+        memset(password, 0, len);
+        return SASL_NOMEM;
+    }
+
+    x->len = len;
+    strcpy(x->data, password);
+    memset(password, 0, len);
+    
+    *psecret = x;
+    return SASL_OK;
+}
+
+static int canon(sasl_conn_t *conn,
+                              void *context,
+                              const char *in, unsigned inlen,
+                              unsigned flags,
+                              const char *user_realm,
+                              char *out,
+			     unsigned out_max, unsigned *out_len){
+  DBUG_PRINT("info",("CB canon: in = %s , %i", in, inlen));
+  out=strncpy(out,in,out_max);
+  *out_len=inlen;
+  return SASL_OK;
+}
+#endif
 
 MYSQL * STDCALL 
 CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
 		       const char *passwd, const char *db,
 		       uint port, const char *unix_socket,ulong client_flag)
 {
+#ifdef HAVE_SASL
+  char		buff[NAME_LEN+USERNAME_LENGTH+1000];
+#else
   char		buff[NAME_LEN+USERNAME_LENGTH+100];
+#endif
   char		*end,*host_info;
   my_socket	sock;
   in_addr_t	ip_addr;
@@ -1801,6 +1884,10 @@
 #ifdef HAVE_SYS_UN_H
   struct	sockaddr_un UNIXaddr;
 #endif
+#ifdef HAVE_SASL
+  int           use_sasl = 1;
+#endif
+ 
   init_sigpipe_variables
   DBUG_ENTER("mysql_real_connect");
   LINT_INIT(host_info);
@@ -2109,7 +2196,14 @@
     /* New protocol with 16 bytes to describe server characteristics */
     mysql->server_language=end[2];
     mysql->server_status=uint2korr(end+3);
+#ifdef HAVE_SASL
+      /*SASL negotiation is supported by the server and will be used by client if password is empty*/
+    DBUG_PRINT("info",("SASL available %i", mysql->options.sasl));
+    use_sasl = (end[5] & 0x01) && mysql->options.sasl;
+	//&(passwd=="");
+#endif 
   }
+ 
   end+= 18;
   if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 
                            (char *) net->read_pos))
@@ -2187,6 +2281,13 @@
     int4store(buff+4, net->max_packet_size);
     buff[8]= (char) mysql->charset->number;
     bzero(buff+9, 32-9);
+#if HAVE_SASL
+      if (use_sasl) {
+	/* Sasl should be used by the server*/
+	buff[9] |= 0x01;
+      } 
+      DBUG_PRINT("info: ",("SASL caps %i", (uint) buff[9]));
+#endif
     end= buff+32;
   }
   else
@@ -2263,6 +2364,11 @@
 #endif
   DBUG_PRINT("info",("user: %s",end));
   end= strend(end) + 1;
+#ifdef HAVE_SASL
+  if (use_sasl){
+    *end++= '\0';
+  } else
+#endif
   if (passwd[0])
   {
     if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
@@ -2298,6 +2403,130 @@
                              errno);
     goto error;
   }
+#ifdef HAVE_SASL
+  if (use_sasl)
+    {
+      sasl_conn_t *conn = NULL;
+      unsigned int pkt_len;
+      int result;
+      sasl_interact_t *client_interact = NULL;
+      const char *out, *mechusing;
+      unsigned int outlen;
+      char * user1, * passwd1;
+      static sasl_callback_t callbacks[] = {
+	{ SASL_CB_GETREALM, &getrealm, NULL },
+	{ SASL_CB_USER, &simple, NULL }, 
+	{ SASL_CB_AUTHNAME, &simple, NULL }, 
+	{ SASL_CB_PASS, &getsecret, NULL },
+	{ SASL_CB_CANON_USER, &canon, NULL },
+	{ SASL_CB_LIST_END, NULL, NULL }
+      };
+      DBUG_PRINT("info",("SASL: user: %s", user));
+      callbacks[1].context=user;
+      callbacks[2].context=callbacks[1].context;
+      callbacks[3].context=passwd;
+      if ((result = sasl_client_init(callbacks)) != SASL_OK)
+	goto sasl_error;
+      DBUG_PRINT("info",("SASL: host=%s", host ? host : "(null)"));
+      /* Initialise SASL */
+      if ((result = sasl_client_new("mysql", host ? host : "localhost",
+				    NULL, NULL, NULL, 0, &conn)) != SASL_OK)
+	{
+	sasl_error:
+	  out = conn ? sasl_errdetail(conn) : NULL;
+	  sprintf(net->last_error, "SASL error: %s",
+		  out ? out : sasl_errstring(result, NULL, NULL));
+	  DBUG_PRINT("info",("SASL: %s (%s)", 
+			     sasl_errstring(result, NULL, NULL),
+			     out ? out : "null" ));
+	  set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+	  goto error;
+	}
+
+      /* Receive 'C' {mechlist} '.' */
+      /*2*/
+      if ((pkt_len = cli_safe_read(mysql)) == packet_error)
+	goto error;
+      if (pkt_len == 0 || net->read_pos[0] != 'C' 
+	  || net->read_pos[pkt_len - 1] != '.') {
+	set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+	goto error;
+      }
+      net->read_pos[pkt_len - 1] = '\0';
+
+      DBUG_PRINT("info",("SASL: server mechs: %s", net->read_pos + 1));
+      /* Ask SASL to select a mechanism */
+      result = sasl_client_start(conn, net->read_pos + 1, NULL,
+				   &out, &outlen, &mechusing);
+      if (result != SASL_CONTINUE && result != SASL_OK) {
+	 result = sasl_client_start(conn, "PLAIN", NULL,
+				   &out, &outlen, &mechusing);	  
+      }
+      if (result != SASL_CONTINUE && result != SASL_OK)
+	    goto sasl_error;
+      DBUG_PRINT("info",("SASL: using mech %s", mechusing));
+      /* Send: {mechlen} {haveout} {mechanism} '.' [{out}]} */
+      buff[0] = (char) strlen(mechusing);
+      buff[1] = (out != NULL);
+      pkt_len = 2;
+      memcpy(buff + pkt_len, mechusing, buff[0]); pkt_len += buff[0];
+      buff[pkt_len] = '.'; pkt_len++;
+      if (out) {
+	DBUG_PRINT("info",("SASL: Out %s, %i", (char *) (buff+pkt_len), outlen));
+	memcpy(buff + pkt_len, out, outlen); pkt_len += outlen;
+      }
+      /*3*/
+      if (my_net_write(net, buff, pkt_len) || net_flush(net)) {
+	set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+	goto error;
+      }
+
+      /* Enter SASL negotiation loop while command byte is '+' */
+      /*4*/
+      DBUG_PRINT("info",("SASL:Negotiation Start: %s, %i", (const char *) net->read_pos, pkt_len));
+      
+     if ((pkt_len = cli_safe_read(mysql)) == packet_error){
+	DBUG_PRINT("info",("SASL:Negotiation Fail: %i", packet_error));
+	goto error;
+	}
+     DBUG_PRINT("info",("SASL:Server reply 4: %s, %i", (const char *) net->read_pos, pkt_len));
+     while (net->read_pos[0] == '+') {
+       DBUG_PRINT("info",("SASL:Client step: a"));
+	result = sasl_client_step(conn, (const char *) (net->read_pos + 1),
+				  pkt_len - 1, &client_interact, &out, &outlen);
+	DBUG_PRINT("info",("SASL:Client step: %i", outlen));
+	if (result != SASL_OK && result != SASL_CONTINUE) {
+	  DBUG_PRINT("info",("SASL:Negotiation Fail: %i", packet_error));
+	  goto error;
+	}
+	/*5+2n*/
+	if (my_net_write(net, out, outlen) || net_flush(net)) {
+	  set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+	  goto error;
+	}
+	/*6+2n*/
+	if ((pkt_len = cli_safe_read(mysql)) == packet_error)
+		goto error;	 
+      }
+     DBUG_PRINT("info",("Exit loop!"));
+      if (net->read_pos[0] == 'F') { /* Failed */
+        DBUG_PRINT("info",("SASL: fail (%s)", (char *) (net->read_pos+1)));
+	use_sasl = 0;
+	goto error;
+      }
+      if (net->read_pos[0] != 'A') {
+	set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+	goto error;
+      }
+      DBUG_PRINT("info",("SASL: authenticated"));
+
+      /* At this point, SASL authentication is complete */
+      /* XXX add a vio layer for sasl */
+
+    sasl_done: ;
+      
+    }
+#endif /* HAVE_SASL */
   
   /*
     Part 3: Authorization data's been sent. Now server can reply with
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./libmysqld/examples/mysql.cc ../../mysql-5.0.34/libmysqld/examples/mysql.cc
--- ./libmysqld/examples/mysql.cc	2007-01-17 12:52:06.000000000 +0300
+++ ../../mysql-5.0.34/libmysqld/examples/mysql.cc	2007-02-22 07:37:13.000000000 +0300
@@ -140,6 +140,9 @@
                default_pager_set= 0, opt_sigint_ignore= 0,
                show_warnings= 0;
 static volatile int executing_query= 0, interrupted_query= 0;
+#ifdef HAVE_SASL
+static my_bool opt_client_sasl=1;
+#endif
 static ulong opt_max_allowed_packet, opt_net_buffer_length;
 static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
 static my_string opt_mysql_unix_port=0;
@@ -757,6 +760,9 @@
   {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
     (gptr*) &show_warnings, (gptr*) &show_warnings, 0, GET_BOOL, NO_ARG, 
     0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SASL
+  {"sasl", '9', "Enable SASL authentication in client if possible.", (gptr*) &opt_client_sasl,    (gptr*) &opt_client_sasl, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+#endif
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -3256,6 +3262,9 @@
   if (shared_memory_base_name)
     mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
 #endif
+#ifdef HAVE_SASL
+  mysql.options.sasl=opt_client_sasl;
+#endif 
   if (safe_updates)
   {
     char init_command[100];
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./libmysqld/sql_acl.cc ../../mysql-5.0.34/libmysqld/sql_acl.cc
--- ./libmysqld/sql_acl.cc	2007-01-17 12:52:09.000000000 +0300
+++ ../../mysql-5.0.34/libmysqld/sql_acl.cc	2007-02-22 07:37:13.000000000 +0300
@@ -760,6 +760,12 @@
       if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
       {
         /* check password: it should be empty or valid */
+#ifdef HAVE_SASL        
+	if (sctx->sasl_mech) {
+	  acl_user= acl_user_tmp;
+          res= 0;
+	} else 
+#endif
         if (passwd_len == acl_user_tmp->salt_len)
         {
           if (acl_user_tmp->salt_len == 0 ||
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./libmysqld/sql_parse.cc ../../mysql-5.0.34/libmysqld/sql_parse.cc
--- ./libmysqld/sql_parse.cc	2007-01-17 12:52:35.000000000 +0300
+++ ../../mysql-5.0.34/libmysqld/sql_parse.cc	2007-02-22 07:37:13.000000000 +0300
@@ -33,6 +33,10 @@
 #include "sp.h"
 #include "sp_cache.h"
 
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 #ifdef HAVE_OPENSSL
 /*
   Without SSL the handshake consists of one packet. This packet
@@ -826,6 +830,11 @@
   NET *net= &thd->net;
   ulong pkt_len= 0;
   char *end;
+#ifdef HAVE_SASL
+  int use_sasl = 0;
+  thd->security_ctx->sasl_mech = 0;
+#endif
+  
 
   DBUG_PRINT("info",
              ("New connection received on %s", vio_description(net->vio)));
@@ -913,6 +922,9 @@
     end[2]=(char) default_charset_info->number;
     int2store(end+3, thd->server_status);
     bzero(end+5, 13);
+#ifdef HAVE_SASL
+    end[5] |= 0x01;  /* Non-standard: indicates that SASL is available */
+#endif
     end+= 18;
     /* write scramble tail */
     end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
@@ -944,6 +956,13 @@
     DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
     thd_init_client_charset(thd, (uint) net->read_pos[8]);
     thd->update_charset();
+#ifdef HAVE_SASL
+    use_sasl = net->read_pos[9] & 0x01;
+    DBUG_PRINT("info", ("SASL required= %i, sasl_used =%i",global_system_variables.require_sasl, use_sasl));
+    if (global_system_variables.require_sasl && (!use_sasl)){
+	return(ER_HANDSHAKE_ERROR);
+     }
+#endif
     end= (char*) net->read_pos+32;
   }
   else
@@ -1044,6 +1063,116 @@
     user_len-= 2;
   }
 
+#ifdef HAVE_SASL
+  if (use_sasl) {
+    sasl_conn_t *conn;
+    const char *mechs;
+    unsigned int mechlen;
+    int result;
+    const char *out;
+    unsigned int outlen;
+    DBUG_PRINT("info", ("SASL: localhost: %s", my_localhost));
+    result = sasl_server_new("mysql",
+			     NULL, /* localhost */
+			     NULL, /* realm */
+			     NULL, NULL, /* IP Address information strings */
+			     NULL, /* Callbacks supported only for this connection */
+			     0,   /* Flags */
+			     &conn);
+    if (result != SASL_OK) {
+    sasl_error:
+      out = conn ? sasl_errdetail(conn) : NULL;
+      DBUG_PRINT("info",("SASL: %s (%s)", sasl_errstring(result, NULL, NULL),
+			 out ? out : "null" ));
+      return(ER_HANDSHAKE_ERROR);
+    }
+    result = sasl_listmech(conn, NULL, "", " ", ".", 
+			   &mechs, &mechlen, NULL);
+    if (result != SASL_OK)
+      goto sasl_error;
+    DBUG_PRINT("info", ("SASL: mechs: %.*s", mechlen, mechs));
+
+    /* Send 'C' {mechlist} '.' */
+    /*2*/
+    if (net_write_command(net, 'C', "", 0, mechs, mechlen))
+      return(ER_HANDSHAKE_ERROR);
+
+    /* Receive {mechlen} {haveout} {mechanism} '.' [{datalen}] */
+    /*3*/
+    if ((pkt_len = my_net_read(net)) == packet_error || pkt_len < 3)
+      return(ER_HANDSHAKE_ERROR);
+    mechlen = net->read_pos[0];
+    DBUG_PRINT("info", ("SASL: mechlen: %i, %s", mechlen,net->read_pos));
+    if (mechlen + 3 > pkt_len || net->read_pos[2 + mechlen] != '.')
+      return(ER_HANDSHAKE_ERROR);
+    net->read_pos[2 + mechlen] = '\0';
+    DBUG_PRINT("info", ("SASL: client mech: %s", net->read_pos + 2));
+    DBUG_PRINT("info",("Start server 1, %i, %s", net->read_pos[1], (const char *)(net->read_pos + mechlen + 3)));
+    result = sasl_server_start(conn, (const char *)net->read_pos + 2,
+			       net->read_pos[1] ? (const char *)(net->read_pos + mechlen + 3) : NULL,
+			       net->read_pos[1] ? pkt_len - (mechlen + 3) : 0,
+			       &out, &outlen);
+    DBUG_PRINT("info",("Start server 2\n"));
+    if (result != SASL_OK && result != SASL_CONTINUE) {
+      const char *errtxt = sasl_errdetail(conn);
+      DBUG_PRINT("info", ("SASL: fail: %s", errtxt));
+      if (net_write_command(net, 'F', "", 0, errtxt, 
+			    errtxt == NULL ?  0 : strlen(errtxt)))
+	return(ER_HANDSHAKE_ERROR);
+      use_sasl = 0;
+      goto sasl_done;
+    }
+
+    while (result == SASL_CONTINUE) {
+      /*4+2n*/
+       if (net_write_command(net, '+', "", 0, out, outlen))
+	return(ER_HANDSHAKE_ERROR);
+      DBUG_PRINT("info",("Write client: %s,%i",out,outlen));
+      /*5+2n*/
+      if ((pkt_len = my_net_read(net)) == packet_error)
+	return(ER_HANDSHAKE_ERROR);
+      DBUG_PRINT("info",("Read Client: %s,%i",(const char *)net->read_pos,pkt_len));
+      result = sasl_server_step(conn, (const char *)net->read_pos, pkt_len,
+				&out, &outlen);
+      if (result != SASL_OK && result != SASL_CONTINUE) {
+	const char *errtxt = sasl_errdetail(conn);
+	DBUG_PRINT("info", ("SASL: fail: %s", errtxt));
+	if (net_write_command(net, 'F', "", 0, errtxt, 
+			      errtxt == NULL ?  0 : strlen(errtxt)))
+	  return(ER_HANDSHAKE_ERROR);
+	use_sasl = 0;
+	goto sasl_done;
+      }
+    }
+    
+    DBUG_PRINT("info", ("SASL: client authenticated"));
+    if (net_write_command(net, 'A', "", 0, out, outlen))
+      return(ER_HANDSHAKE_ERROR);
+
+    /* At this point, SASL authentication is complete */
+    /* XXX add a vio layer for sasl */
+    /* XXX use sasl_getprop to get user@realm */
+    {
+      const char *auth_user = NULL;
+      const char *auth_realm = NULL;
+      const char *auth_mech = NULL;
+      sasl_getprop(conn, SASL_USERNAME, (const void **)&auth_user);
+      sasl_getprop(conn, SASL_DEFUSERREALM, (const void **)&auth_realm);
+      sasl_getprop(conn, SASL_MECHNAME, (const void **)&auth_mech);
+      DBUG_PRINT("info", ("SASL: authenticated user=%s realm=%s mech=%s",
+			  auth_user ? auth_user : "<null>",
+			  auth_realm ? auth_realm : "<null>",
+			  auth_mech ? auth_mech : "<null>"));
+    end = (char *) auth_user;
+    }
+
+  sasl_done: ;
+        thd->security_ctx->sasl_mech=use_sasl;
+	/*security layer is not yet supported so we done with sasl right now*/
+	sasl_dispose(&conn);
+  }
+#endif /* HAVE_SASL */
+
   if (thd->main_security_ctx.user)
     x_free(thd->main_security_ctx.user);
   if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql/client.c ../../mysql-5.0.34/sql/client.c
--- ./sql/client.c	2007-01-17 12:51:53.000000000 +0300
+++ ../../mysql-5.0.34/sql/client.c	2007-02-22 07:37:13.000000000 +0300
@@ -113,6 +113,10 @@
 #include "client_settings.h"
 #include <sql_common.h>
 
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 uint		mysql_port=0;
 char		*mysql_unix_port= 0;
 const char	*unknown_sqlstate= "HY000";
@@ -935,6 +938,9 @@
   "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
   "multi-results", "multi-statements", "multi-queries", "secure-auth",
   "report-data-truncation",
+#ifdef HAVE_SASL
+"sasl",
+#endif
   NullS
 };
 
@@ -1149,6 +1155,11 @@
         case 34: /* report-data-truncation */
           options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
           break;
+#ifdef HAVE_SASL
+	case 35: /*allow sasl authentication in clients*/
+	  options->sasl=opt_arg ? atoi(opt_arg) : 1;
+	  break;
+#endif
 	default:
 	  DBUG_PRINT("warning",("unknown option: %s",option[0]));
 	}
@@ -1493,6 +1504,9 @@
 #ifdef HAVE_SMEM
   mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;
 #endif
+#ifdef HAVE_SASL
+  int           use_sasl = 0;
+#endif
 
   mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
   mysql->options.report_data_truncation= TRUE;  /* default */
@@ -1777,14 +1791,81 @@
   return 0;
 }
 C_MODE_END
+#ifdef HAVE_SASL
+static int simple(void *context __attribute__((unused)),
+                  int id,
+                  const char **result,
+                  unsigned *len)
+{
+    char * name=strdup((char*)context); 
+    int z;
+    *result = name;
+    DBUG_PRINT("info",("CB simple: name = %s", name));
+    if(len) *len=strlen(name);
+    return SASL_OK;
+}
+
+static int getrealm(void *context __attribute__((unused)), 
+                    int id,
+                    const char **availrealms,
+                    const char **result)
+{
+
+    DBUG_PRINT("info",("CB getrealm: name = %s", availrealms[0]));    
+    return SASL_OK;
+}
 
+static int
+getsecret(sasl_conn_t *conn,
+          void *context __attribute__((unused)),
+          int id,
+          sasl_secret_t **psecret)
+{
+    char *password = context;
+    size_t len;
+    static sasl_secret_t *x;
+    DBUG_PRINT("info",("CB secret: pass = %s", password));
+    len = strlen(password);
+
+    x = (sasl_secret_t *) realloc(x, sizeof(sasl_secret_t) + len);
+  
+    if (!x) {
+        memset(password, 0, len);
+        return SASL_NOMEM;
+    }
+
+    x->len = len;
+    strcpy(x->data, password);
+    memset(password, 0, len);
+    
+    *psecret = x;
+    return SASL_OK;
+}
+
+static int canon(sasl_conn_t *conn,
+                              void *context,
+                              const char *in, unsigned inlen,
+                              unsigned flags,
+                              const char *user_realm,
+                              char *out,
+			     unsigned out_max, unsigned *out_len){
+  DBUG_PRINT("info",("CB canon: in = %s , %i", in, inlen));
+  out=strncpy(out,in,out_max);
+  *out_len=inlen;
+  return SASL_OK;
+}
+#endif
 
 MYSQL * STDCALL 
 CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
 		       const char *passwd, const char *db,
 		       uint port, const char *unix_socket,ulong client_flag)
 {
+#ifdef HAVE_SASL
+  char		buff[NAME_LEN+USERNAME_LENGTH+1000];
+#else
   char		buff[NAME_LEN+USERNAME_LENGTH+100];
+#endif
   char		*end,*host_info;
   my_socket	sock;
   in_addr_t	ip_addr;
@@ -1801,6 +1882,10 @@
 #ifdef HAVE_SYS_UN_H
   struct	sockaddr_un UNIXaddr;
 #endif
+#ifdef HAVE_SASL
+  int           use_sasl = 1;
+#endif
+ 
   init_sigpipe_variables
   DBUG_ENTER("mysql_real_connect");
   LINT_INIT(host_info);
@@ -2109,7 +2194,14 @@
     /* New protocol with 16 bytes to describe server characteristics */
     mysql->server_language=end[2];
     mysql->server_status=uint2korr(end+3);
+#ifdef HAVE_SASL
+      /*SASL negotiation is supported by the server and will be used by client if password is empty*/
+    DBUG_PRINT("info",("SASL available %i", mysql->options.sasl));
+    use_sasl = (end[5] & 0x01) && mysql->options.sasl;
+	//&(passwd=="");
+#endif 
   }
+ 
   end+= 18;
   if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 
                            (char *) net->read_pos))
@@ -2187,6 +2279,13 @@
     int4store(buff+4, net->max_packet_size);
     buff[8]= (char) mysql->charset->number;
     bzero(buff+9, 32-9);
+#if HAVE_SASL
+      if (use_sasl) {
+	/* Sasl should be used by the server*/
+	buff[9] |= 0x01;
+      } 
+      DBUG_PRINT("info: ",("SASL caps %i", (uint) buff[9]));
+#endif
     end= buff+32;
   }
   else
@@ -2263,6 +2362,11 @@
 #endif
   DBUG_PRINT("info",("user: %s",end));
   end= strend(end) + 1;
+#ifdef HAVE_SASL
+  if (use_sasl){
+    *end++= '\0';
+  } else
+#endif
   if (passwd[0])
   {
     if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
@@ -2298,6 +2401,130 @@
                              errno);
     goto error;
   }
+#ifdef HAVE_SASL
+  if (use_sasl)
+    {
+      sasl_conn_t *conn = NULL;
+      unsigned int pkt_len;
+      int result;
+      sasl_interact_t *client_interact = NULL;
+      const char *out, *mechusing;
+      unsigned int outlen;
+      char * user1, * passwd1;
+      static sasl_callback_t callbacks[] = {
+	{ SASL_CB_GETREALM, &getrealm, NULL },
+	{ SASL_CB_USER, &simple, NULL }, 
+	{ SASL_CB_AUTHNAME, &simple, NULL }, 
+	{ SASL_CB_PASS, &getsecret, NULL },
+	{ SASL_CB_CANON_USER, &canon, NULL },
+	{ SASL_CB_LIST_END, NULL, NULL }
+      };
+      DBUG_PRINT("info",("SASL: user: %s", user));
+      callbacks[1].context=user;
+      callbacks[2].context=callbacks[1].context;
+      callbacks[3].context=passwd;
+      if ((result = sasl_client_init(callbacks)) != SASL_OK)
+	goto sasl_error;
+      DBUG_PRINT("info",("SASL: host=%s", host ? host : "(null)"));
+      /* Initialise SASL */
+      if ((result = sasl_client_new("mysql", host ? host : "localhost",
+				    NULL, NULL, NULL, 0, &conn)) != SASL_OK)
+	{
+	sasl_error:
+	  out = conn ? sasl_errdetail(conn) : NULL;
+	  sprintf(net->last_error, "SASL error: %s",
+		  out ? out : sasl_errstring(result, NULL, NULL));
+	  DBUG_PRINT("info",("SASL: %s (%s)", 
+			     sasl_errstring(result, NULL, NULL),
+			     out ? out : "null" ));
+	  set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+	  goto error;
+	}
+
+      /* Receive 'C' {mechlist} '.' */
+      /*2*/
+      if ((pkt_len = cli_safe_read(mysql)) == packet_error)
+	goto error;
+      if (pkt_len == 0 || net->read_pos[0] != 'C' 
+	  || net->read_pos[pkt_len - 1] != '.') {
+	set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+	goto error;
+      }
+      net->read_pos[pkt_len - 1] = '\0';
+
+      DBUG_PRINT("info",("SASL: server mechs: %s", net->read_pos + 1));
+      /* Ask SASL to select a mechanism */
+      result = sasl_client_start(conn, net->read_pos + 1, NULL,
+				   &out, &outlen, &mechusing);
+      if (result != SASL_CONTINUE && result != SASL_OK) {
+	 result = sasl_client_start(conn, "PLAIN", NULL,
+				   &out, &outlen, &mechusing);	  
+      }
+      if (result != SASL_CONTINUE && result != SASL_OK)
+	    goto sasl_error;
+      DBUG_PRINT("info",("SASL: using mech %s", mechusing));
+      /* Send: {mechlen} {haveout} {mechanism} '.' [{out}]} */
+      buff[0] = (char) strlen(mechusing);
+      buff[1] = (out != NULL);
+      pkt_len = 2;
+      memcpy(buff + pkt_len, mechusing, buff[0]); pkt_len += buff[0];
+      buff[pkt_len] = '.'; pkt_len++;
+      if (out) {
+	DBUG_PRINT("info",("SASL: Out %s, %i", (char *) (buff+pkt_len), outlen));
+	memcpy(buff + pkt_len, out, outlen); pkt_len += outlen;
+      }
+      /*3*/
+      if (my_net_write(net, buff, pkt_len) || net_flush(net)) {
+	set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+	goto error;
+      }
+
+      /* Enter SASL negotiation loop while command byte is '+' */
+      /*4*/
+      DBUG_PRINT("info",("SASL:Negotiation Start: %s, %i", (const char *) net->read_pos, pkt_len));
+      
+     if ((pkt_len = cli_safe_read(mysql)) == packet_error){
+	DBUG_PRINT("info",("SASL:Negotiation Fail: %i", packet_error));
+	goto error;
+	}
+     DBUG_PRINT("info",("SASL:Server reply 4: %s, %i", (const char *) net->read_pos, pkt_len));
+     while (net->read_pos[0] == '+') {
+       DBUG_PRINT("info",("SASL:Client step: a"));
+	result = sasl_client_step(conn, (const char *) (net->read_pos + 1),
+				  pkt_len - 1, &client_interact, &out, &outlen);
+	DBUG_PRINT("info",("SASL:Client step: %i", outlen));
+	if (result != SASL_OK && result != SASL_CONTINUE) {
+	  DBUG_PRINT("info",("SASL:Negotiation Fail: %i", packet_error));
+	  goto error;
+	}
+	/*5+2n*/
+	if (my_net_write(net, out, outlen) || net_flush(net)) {
+	  set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+	  goto error;
+	}
+	/*6+2n*/
+	if ((pkt_len = cli_safe_read(mysql)) == packet_error)
+		goto error;	 
+      }
+     DBUG_PRINT("info",("Exit loop!"));
+      if (net->read_pos[0] == 'F') { /* Failed */
+        DBUG_PRINT("info",("SASL: fail (%s)", (char *) (net->read_pos+1)));
+	use_sasl = 0;
+	goto error;
+      }
+      if (net->read_pos[0] != 'A') {
+	set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+	goto error;
+      }
+      DBUG_PRINT("info",("SASL: authenticated"));
+
+      /* At this point, SASL authentication is complete */
+      /* XXX add a vio layer for sasl */
+
+    sasl_done: ;
+      
+    }
+#endif /* HAVE_SASL */
   
   /*
     Part 3: Authorization data's been sent. Now server can reply with
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql/mysqld.cc ../../mysql-5.0.34/sql/mysqld.cc
--- ./sql/mysqld.cc	2007-01-17 12:51:54.000000000 +0300
+++ ../../mysql-5.0.34/sql/mysqld.cc	2007-02-22 07:37:13.000000000 +0300
@@ -60,6 +60,9 @@
 #include <errmsg.h>
 #include "sp_rcontext.h"
 #include "sp_cache.h"
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif
 
 #define mysqld_charset &my_charset_latin1
 
@@ -3224,6 +3227,16 @@
 
   init_max_user_conn();
   init_update_queries();
+#ifdef HAVE_SASL
+  {
+      int result;
+      if ((result = sasl_server_init(NULL, "mysqld")) != SASL_OK) {
+	  sql_print_error(sasl_errstring(result, NULL, NULL));
+	  sql_print_error("Can't init SASL");
+	  unireg_abort(1);
+      }
+  }
+#endif
   DBUG_RETURN(0);
 }
 
@@ -4694,6 +4707,9 @@
   OPT_OLD_STYLE_USER_LIMITS,
   OPT_LOG_SLOW_ADMIN_STATEMENTS,
   OPT_TABLE_LOCK_WAIT_TIMEOUT,
+#ifdef HAVE_SASL
+  OPT_REQUIRE_SASL,
+#endif
   OPT_PORT_OPEN_TIMEOUT,
   OPT_MERGE,
   OPT_INNODB_ROLLBACK_ON_TIMEOUT
@@ -6049,6 +6065,11 @@
    (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
    REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT),
    0, 1, 0},
+#ifdef HAVE_SASL
+  {"require_sasl", OPT_REQUIRE_SASL, "Server requires authentication through SASL. Enabled by default.",
+   (gptr*) &global_system_variables.require_sasl, (gptr*) &global_system_variables.require_sasl, 0, GET_BOOL,
+   NO_ARG, 1, 0, 0, 0, 0, 0},
+#endif
   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql/sql_acl.cc ../../mysql-5.0.34/sql/sql_acl.cc
--- ./sql/sql_acl.cc	2007-01-17 12:52:09.000000000 +0300
+++ ../../mysql-5.0.34/sql/sql_acl.cc	2007-02-22 07:37:13.000000000 +0300
@@ -760,6 +760,12 @@
       if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
       {
         /* check password: it should be empty or valid */
+#ifdef HAVE_SASL        
+	if (sctx->sasl_mech) {
+	  acl_user= acl_user_tmp;
+          res= 0;
+	} else 
+#endif
         if (passwd_len == acl_user_tmp->salt_len)
         {
           if (acl_user_tmp->salt_len == 0 ||
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql/sql_acl.h ../../mysql-5.0.34/sql/sql_acl.h
--- ./sql/sql_acl.h	2007-01-17 12:51:54.000000000 +0300
+++ ../../mysql-5.0.34/sql/sql_acl.h	2007-02-22 07:37:13.000000000 +0300
@@ -160,6 +160,7 @@
   uint8 salt_len;        // 0 - no password, 4 - 3.20, 8 - 3.23, 20 - 4.1.1 
   enum SSL_type ssl_type;
   const char *ssl_cipher, *x509_issuer, *x509_subject;
+  uint8 sasl_mech;	// 0 if SASL not used
 };
 
 
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql/sql_class.h ../../mysql-5.0.34/sql/sql_class.h
--- ./sql/sql_class.h	2007-01-17 12:52:35.000000000 +0300
+++ ../../mysql-5.0.34/sql/sql_class.h	2007-02-22 07:37:13.000000000 +0300
@@ -585,6 +585,9 @@
   DATE_TIME_FORMAT *date_format;
   DATE_TIME_FORMAT *datetime_format;
   DATE_TIME_FORMAT *time_format;
+#ifdef HAVE_SASL
+  my_bool require_sasl;
+#endif
   my_bool sysdate_is_now;
 };
 
@@ -930,6 +933,7 @@
   char   priv_host[MAX_HOSTNAME];
   /* points to host if host is available, otherwise points to ip */
   const char *host_or_ip;
+  uint8 sasl_mech;
   ulong master_access;                 /* Global privileges from mysql.user */
   ulong db_access;                     /* Privileges for current db */
 
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql/sql_parse.cc ../../mysql-5.0.34/sql/sql_parse.cc
--- ./sql/sql_parse.cc	2007-01-17 12:52:35.000000000 +0300
+++ ../../mysql-5.0.34/sql/sql_parse.cc	2007-02-22 07:37:13.000000000 +0300
@@ -33,6 +33,10 @@
 #include "sp.h"
 #include "sp_cache.h"
 
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 #ifdef HAVE_OPENSSL
 /*
   Without SSL the handshake consists of one packet. This packet
@@ -826,6 +830,11 @@
   NET *net= &thd->net;
   ulong pkt_len= 0;
   char *end;
+#ifdef HAVE_SASL
+  int use_sasl = 0;
+  thd->security_ctx->sasl_mech = 0;
+#endif
+  
 
   DBUG_PRINT("info",
              ("New connection received on %s", vio_description(net->vio)));
@@ -913,6 +922,9 @@
     end[2]=(char) default_charset_info->number;
     int2store(end+3, thd->server_status);
     bzero(end+5, 13);
+#ifdef HAVE_SASL
+    end[5] |= 0x01;  /* Non-standard: indicates that SASL is available */
+#endif
     end+= 18;
     /* write scramble tail */
     end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
@@ -944,6 +956,13 @@
     DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
     thd_init_client_charset(thd, (uint) net->read_pos[8]);
     thd->update_charset();
+#ifdef HAVE_SASL
+    use_sasl = net->read_pos[9] & 0x01;
+    DBUG_PRINT("info", ("SASL required= %i, sasl_used =%i",global_system_variables.require_sasl, use_sasl));
+    if (global_system_variables.require_sasl && (!use_sasl)){
+	return(ER_HANDSHAKE_ERROR);
+     }
+#endif
     end= (char*) net->read_pos+32;
   }
   else
@@ -1044,6 +1063,116 @@
     user_len-= 2;
   }
 
+#ifdef HAVE_SASL
+  if (use_sasl) {
+    sasl_conn_t *conn;
+    const char *mechs;
+    unsigned int mechlen;
+    int result;
+    const char *out;
+    unsigned int outlen;
+    DBUG_PRINT("info", ("SASL: localhost: %s", my_localhost));
+    result = sasl_server_new("mysql",
+			     NULL, /* localhost */
+			     NULL, /* realm */
+			     NULL, NULL, /* IP Address information strings */
+			     NULL, /* Callbacks supported only for this connection */
+			     0,   /* Flags */
+			     &conn);
+    if (result != SASL_OK) {
+    sasl_error:
+      out = conn ? sasl_errdetail(conn) : NULL;
+      DBUG_PRINT("info",("SASL: %s (%s)", sasl_errstring(result, NULL, NULL),
+			 out ? out : "null" ));
+      return(ER_HANDSHAKE_ERROR);
+    }
+    result = sasl_listmech(conn, NULL, "", " ", ".", 
+			   &mechs, &mechlen, NULL);
+    if (result != SASL_OK)
+      goto sasl_error;
+    DBUG_PRINT("info", ("SASL: mechs: %.*s", mechlen, mechs));
+
+    /* Send 'C' {mechlist} '.' */
+    /*2*/
+    if (net_write_command(net, 'C', "", 0, mechs, mechlen))
+      return(ER_HANDSHAKE_ERROR);
+
+    /* Receive {mechlen} {haveout} {mechanism} '.' [{datalen}] */
+    /*3*/
+    if ((pkt_len = my_net_read(net)) == packet_error || pkt_len < 3)
+      return(ER_HANDSHAKE_ERROR);
+    mechlen = net->read_pos[0];
+    DBUG_PRINT("info", ("SASL: mechlen: %i, %s", mechlen,net->read_pos));
+    if (mechlen + 3 > pkt_len || net->read_pos[2 + mechlen] != '.')
+      return(ER_HANDSHAKE_ERROR);
+    net->read_pos[2 + mechlen] = '\0';
+    DBUG_PRINT("info", ("SASL: client mech: %s", net->read_pos + 2));
+    DBUG_PRINT("info",("Start server 1, %i, %s", net->read_pos[1], (const char *)(net->read_pos + mechlen + 3)));
+    result = sasl_server_start(conn, (const char *)net->read_pos + 2,
+			       net->read_pos[1] ? (const char *)(net->read_pos + mechlen + 3) : NULL,
+			       net->read_pos[1] ? pkt_len - (mechlen + 3) : 0,
+			       &out, &outlen);
+    DBUG_PRINT("info",("Start server 2\n"));
+    if (result != SASL_OK && result != SASL_CONTINUE) {
+      const char *errtxt = sasl_errdetail(conn);
+      DBUG_PRINT("info", ("SASL: fail: %s", errtxt));
+      if (net_write_command(net, 'F', "", 0, errtxt, 
+			    errtxt == NULL ?  0 : strlen(errtxt)))
+	return(ER_HANDSHAKE_ERROR);
+      use_sasl = 0;
+      goto sasl_done;
+    }
+
+    while (result == SASL_CONTINUE) {
+      /*4+2n*/
+       if (net_write_command(net, '+', "", 0, out, outlen))
+	return(ER_HANDSHAKE_ERROR);
+      DBUG_PRINT("info",("Write client: %s,%i",out,outlen));
+      /*5+2n*/
+      if ((pkt_len = my_net_read(net)) == packet_error)
+	return(ER_HANDSHAKE_ERROR);
+      DBUG_PRINT("info",("Read Client: %s,%i",(const char *)net->read_pos,pkt_len));
+      result = sasl_server_step(conn, (const char *)net->read_pos, pkt_len,
+				&out, &outlen);
+      if (result != SASL_OK && result != SASL_CONTINUE) {
+	const char *errtxt = sasl_errdetail(conn);
+	DBUG_PRINT("info", ("SASL: fail: %s", errtxt));
+	if (net_write_command(net, 'F', "", 0, errtxt, 
+			      errtxt == NULL ?  0 : strlen(errtxt)))
+	  return(ER_HANDSHAKE_ERROR);
+	use_sasl = 0;
+	goto sasl_done;
+      }
+    }
+    
+    DBUG_PRINT("info", ("SASL: client authenticated"));
+    if (net_write_command(net, 'A', "", 0, out, outlen))
+      return(ER_HANDSHAKE_ERROR);
+
+    /* At this point, SASL authentication is complete */
+    /* XXX add a vio layer for sasl */
+    /* XXX use sasl_getprop to get user@realm */
+    {
+      const char *auth_user = NULL;
+      const char *auth_realm = NULL;
+      const char *auth_mech = NULL;
+      sasl_getprop(conn, SASL_USERNAME, (const void **)&auth_user);
+      sasl_getprop(conn, SASL_DEFUSERREALM, (const void **)&auth_realm);
+      sasl_getprop(conn, SASL_MECHNAME, (const void **)&auth_mech);
+      DBUG_PRINT("info", ("SASL: authenticated user=%s realm=%s mech=%s",
+			  auth_user ? auth_user : "<null>",
+			  auth_realm ? auth_realm : "<null>",
+			  auth_mech ? auth_mech : "<null>"));
+    end = (char *) auth_user;
+    }
+
+  sasl_done: ;
+        thd->security_ctx->sasl_mech=use_sasl;
+	/*security layer is not yet supported so we done with sasl right now*/
+	sasl_dispose(&conn);
+  }
+#endif /* HAVE_SASL */
+
   if (thd->main_security_ctx.user)
     x_free(thd->main_security_ctx.user);
   if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
diff -ur --strip --ignore-all-space --ignore-space-change --ignore-blank-lines ./sql-common/client.c ../../mysql-5.0.34/sql-common/client.c
--- ./sql-common/client.c	2007-01-17 12:51:53.000000000 +0300
+++ ../../mysql-5.0.34/sql-common/client.c	2007-02-22 07:37:13.000000000 +0300
@@ -113,6 +113,10 @@
 #include "client_settings.h"
 #include <sql_common.h>
 
+#ifdef HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 uint		mysql_port=0;
 char		*mysql_unix_port= 0;
 const char	*unknown_sqlstate= "HY000";
@@ -935,6 +938,9 @@
   "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
   "multi-results", "multi-statements", "multi-queries", "secure-auth",
   "report-data-truncation",
+  //#ifdef HAVE_SASL
+"sasl",
+  //#endif
   NullS
 };
 
@@ -1149,6 +1155,11 @@
         case 34: /* report-data-truncation */
           options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
           break;
+#ifdef HAVE_SASL
+	case 35: /*allow sasl authentication in clients*/
+	  options->sasl=opt_arg ? atoi(opt_arg) : 1;
+	  break;
+#endif
 	default:
 	  DBUG_PRINT("warning",("unknown option: %s",option[0]));
 	}
@@ -1493,6 +1504,9 @@
 #ifdef HAVE_SMEM
   mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;
 #endif
+#ifdef HAVE_SASL
+  int           use_sasl = 0;
+#endif
 
   mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
   mysql->options.report_data_truncation= TRUE;  /* default */
@@ -1778,13 +1792,81 @@
 }
 C_MODE_END
 
+#ifdef HAVE_SASL
+static int simple(void *context __attribute__((unused)),
+                  int id,
+                  const char **result,
+                  unsigned *len)
+{
+    char * name=strdup((char*)context); 
+    int z;
+    *result = name;
+    DBUG_PRINT("info",("CB simple: name = %s", name));
+    if(len) *len=strlen(name);
+    return SASL_OK;
+}
+
+static int getrealm(void *context __attribute__((unused)), 
+                    int id,
+                    const char **availrealms,
+                    const char **result)
+{
+
+    DBUG_PRINT("info",("CB getrealm: name = %s", availrealms[0]));    
+    return SASL_OK;
+}
+
+static int
+getsecret(sasl_conn_t *conn,
+          void *context __attribute__((unused)),
+          int id,
+          sasl_secret_t **psecret)
+{
+    char *password = context;
+    size_t len;
+    static sasl_secret_t *x;
+    DBUG_PRINT("info",("CB secret: pass = %s", password));
+    len = strlen(password);
+
+    x = (sasl_secret_t *) realloc(x, sizeof(sasl_secret_t) + len);
+  
+    if (!x) {
+        memset(password, 0, len);
+        return SASL_NOMEM;
+    }
+
+    x->len = len;
+    strcpy(x->data, password);
+    memset(password, 0, len);
+    
+    *psecret = x;
+    return SASL_OK;
+}
+
+static int canon(sasl_conn_t *conn,
+                              void *context,
+                              const char *in, unsigned inlen,
+                              unsigned flags,
+                              const char *user_realm,
+                              char *out,
+			     unsigned out_max, unsigned *out_len){
+  DBUG_PRINT("info",("CB canon: in = %s , %i", in, inlen));
+  out=strncpy(out,in,out_max);
+  *out_len=inlen;
+  return SASL_OK;
+}
+#endif
 
 MYSQL * STDCALL 
 CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
 		       const char *passwd, const char *db,
 		       uint port, const char *unix_socket,ulong client_flag)
 {
+#ifdef HAVE_SASL
+  char		buff[NAME_LEN+USERNAME_LENGTH+1000];
+#else
   char		buff[NAME_LEN+USERNAME_LENGTH+100];
+#endif
   char		*end,*host_info;
   my_socket	sock;
   in_addr_t	ip_addr;
@@ -1801,6 +1883,10 @@
 #ifdef HAVE_SYS_UN_H
   struct	sockaddr_un UNIXaddr;
 #endif
+#ifdef HAVE_SASL
+  int           use_sasl = 1;
+#endif
+ 
   init_sigpipe_variables
   DBUG_ENTER("mysql_real_connect");
   LINT_INIT(host_info);
@@ -2109,7 +2195,14 @@
     /* New protocol with 16 bytes to describe server characteristics */
     mysql->server_language=end[2];
     mysql->server_status=uint2korr(end+3);
+#ifdef HAVE_SASL
+      /*SASL negotiation is supported by the server and will be used by client if password is empty*/
+    DBUG_PRINT("info",("SASL available %i", mysql->options.sasl));
+    use_sasl = (end[5] & 0x01) && mysql->options.sasl;
+	//&(passwd=="");
+#endif 
   }
+ 
   end+= 18;
   if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 
                            (char *) net->read_pos))
@@ -2187,6 +2280,13 @@
     int4store(buff+4, net->max_packet_size);
     buff[8]= (char) mysql->charset->number;
     bzero(buff+9, 32-9);
+#if HAVE_SASL
+      if (use_sasl) {
+	/* Sasl should be used by the server*/
+	buff[9] |= 0x01;
+      } 
+      DBUG_PRINT("info: ",("SASL caps %i", (uint) buff[9]));
+#endif
     end= buff+32;
   }
   else
@@ -2263,6 +2363,11 @@
 #endif
   DBUG_PRINT("info",("user: %s",end));
   end= strend(end) + 1;
+#ifdef HAVE_SASL
+  if (use_sasl){
+    *end++= '\0';
+  } else
+#endif
   if (passwd[0])
   {
     if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
@@ -2298,6 +2402,130 @@
                              errno);
     goto error;
   }
+#ifdef HAVE_SASL
+  if (use_sasl)
+    {
+      sasl_conn_t *conn = NULL;
+      unsigned int pkt_len;
+      int result;
+      sasl_interact_t *client_interact = NULL;
+      const char *out, *mechusing;
+      unsigned int outlen;
+      char * user1, * passwd1;
+      static sasl_callback_t callbacks[] = {
+	{ SASL_CB_GETREALM, &getrealm, NULL },
+	{ SASL_CB_USER, &simple, NULL }, 
+	{ SASL_CB_AUTHNAME, &simple, NULL }, 
+	{ SASL_CB_PASS, &getsecret, NULL },
+	{ SASL_CB_CANON_USER, &canon, NULL },
+	{ SASL_CB_LIST_END, NULL, NULL }
+      };
+      DBUG_PRINT("info",("SASL: user: %s", user));
+      callbacks[1].context=user;
+      callbacks[2].context=callbacks[1].context;
+      callbacks[3].context=passwd;
+      if ((result = sasl_client_init(callbacks)) != SASL_OK)
+	goto sasl_error;
+      DBUG_PRINT("info",("SASL: host=%s", host ? host : "(null)"));
+      /* Initialise SASL */
+      if ((result = sasl_client_new("mysql", host ? host : "localhost",
+				    NULL, NULL, NULL, 0, &conn)) != SASL_OK)
+	{
+	sasl_error:
+	  out = conn ? sasl_errdetail(conn) : NULL;
+	  sprintf(net->last_error, "SASL error: %s",
+		  out ? out : sasl_errstring(result, NULL, NULL));
+	  DBUG_PRINT("info",("SASL: %s (%s)", 
+			     sasl_errstring(result, NULL, NULL),
+			     out ? out : "null" ));
+	  set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+	  goto error;
+	}
+
+      /* Receive 'C' {mechlist} '.' */
+      /*2*/
+      if ((pkt_len = cli_safe_read(mysql)) == packet_error)
+	goto error;
+      if (pkt_len == 0 || net->read_pos[0] != 'C' 
+	  || net->read_pos[pkt_len - 1] != '.') {
+	set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+	goto error;
+      }
+      net->read_pos[pkt_len - 1] = '\0';
+
+      DBUG_PRINT("info",("SASL: server mechs: %s", net->read_pos + 1));
+      /* Ask SASL to select a mechanism */
+      result = sasl_client_start(conn, net->read_pos + 1, NULL,
+				   &out, &outlen, &mechusing);
+      if (result != SASL_CONTINUE && result != SASL_OK) {
+	 result = sasl_client_start(conn, "PLAIN", NULL,
+				   &out, &outlen, &mechusing);	  
+      }
+      if (result != SASL_CONTINUE && result != SASL_OK)
+	    goto sasl_error;
+      DBUG_PRINT("info",("SASL: using mech %s", mechusing));
+      /* Send: {mechlen} {haveout} {mechanism} '.' [{out}]} */
+      buff[0] = (char) strlen(mechusing);
+      buff[1] = (out != NULL);
+      pkt_len = 2;
+      memcpy(buff + pkt_len, mechusing, buff[0]); pkt_len += buff[0];
+      buff[pkt_len] = '.'; pkt_len++;
+      if (out) {
+	DBUG_PRINT("info",("SASL: Out %s, %i", (char *) (buff+pkt_len), outlen));
+	memcpy(buff + pkt_len, out, outlen); pkt_len += outlen;
+      }
+      /*3*/
+      if (my_net_write(net, buff, pkt_len) || net_flush(net)) {
+	set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+	goto error;
+      }
+
+      /* Enter SASL negotiation loop while command byte is '+' */
+      /*4*/
+      DBUG_PRINT("info",("SASL:Negotiation Start: %s, %i", (const char *) net->read_pos, pkt_len));
+      
+     if ((pkt_len = cli_safe_read(mysql)) == packet_error){
+	DBUG_PRINT("info",("SASL:Negotiation Fail: %i", packet_error));
+	goto error;
+	}
+     DBUG_PRINT("info",("SASL:Server reply 4: %s, %i", (const char *) net->read_pos, pkt_len));
+     while (net->read_pos[0] == '+') {
+       DBUG_PRINT("info",("SASL:Client step: a"));
+	result = sasl_client_step(conn, (const char *) (net->read_pos + 1),
+				  pkt_len - 1, &client_interact, &out, &outlen);
+	DBUG_PRINT("info",("SASL:Client step: %i", outlen));
+	if (result != SASL_OK && result != SASL_CONTINUE) {
+	  DBUG_PRINT("info",("SASL:Negotiation Fail: %i", packet_error));
+	  goto error;
+	}
+	/*5+2n*/
+	if (my_net_write(net, out, outlen) || net_flush(net)) {
+	  set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+	  goto error;
+	}
+	/*6+2n*/
+	if ((pkt_len = cli_safe_read(mysql)) == packet_error)
+		goto error;	 
+      }
+     DBUG_PRINT("info",("Exit loop!"));
+      if (net->read_pos[0] == 'F') { /* Failed */
+        DBUG_PRINT("info",("SASL: fail (%s)", (char *) (net->read_pos+1)));
+	use_sasl = 0;
+	goto error;
+      }
+      if (net->read_pos[0] != 'A') {
+	set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
+	goto error;
+      }
+      DBUG_PRINT("info",("SASL: authenticated"));
+
+      /* At this point, SASL authentication is complete */
+      /* XXX add a vio layer for sasl */
+
+    sasl_done: ;
+      
+    }
+#endif /* HAVE_SASL */
   
   /*
     Part 3: Authorization data's been sent. Now server can reply with
