diff -BN -ru config.h.in config.h.in
--- config.h.in	2005-03-13 11:35:53.000000000 +0100
+++ config.h.in	2005-07-10 20:13:29.000000000 +0200
@@ -14,6 +14,9 @@
 /* Define this if you enable imap support */
 #undef ENABLE_IMAP
 
+/* Define this if you enable GSSAPI support */
+#undef HAVE_GSSAPI
+
 /* Define this if you enable maildir support */
 #undef ENABLE_MAILDIR
 
diff -BN -ru imap4d/fetch.c imap4d/fetch.c
--- imap4d/fetch.c	2004-06-02 09:30:52.000000000 +0200
+++ imap4d/fetch.c	2005-07-17 13:06:55.000000000 +0200
@@ -63,8 +63,6 @@
 static int fetch_header_fields_not __P ((message_t, char **, unsigned long, unsigned long));
 static int fetch_send_address      __P ((const char *));
 
-static struct fetch_command* fetch_getcommand __P ((char *, struct fetch_command[]));
-
 struct fetch_command
 {
   const char *name;
@@ -101,6 +99,8 @@
   { NULL, 0, 0}
 };
 
+static struct fetch_command* fetch_getcommand __P ((char *, struct fetch_command[]));
+
 /* Go through the fetch array sub command and returns the the structure.  */
 
 static struct fetch_command *
diff -BN -ru include/mailutils/errno.h include/mailutils/errno.h
--- include/mailutils/errno.h	2005-03-08 23:30:04.000000000 +0100
+++ include/mailutils/errno.h	2005-07-15 23:47:52.000000000 +0200
@@ -76,6 +76,9 @@
 #define MU_ERR_BAD_COLUMN (MU_ERR_BASE+45)
 #define MU_ERR_NO_RESULT (MU_ERR_BASE+46)
 #define MU_ERR_NO_INTERFACE (MU_ERR_BASE+47)
+#ifdef WITH_GSSAPI
+#define MU_ERR_GSSAPI_GENERIC (MU_ERR_BASE+48)
+#endif
   
 const char *mu_errname __P((int e));
 const char *mu_strerror __P((int e));
diff -BN -ru mailbox/imap/folder.c mailbox/imap/folder.c
--- mailbox/imap/folder.c	2004-11-17 14:24:19.000000000 +0100
+++ mailbox/imap/folder.c	2005-08-06 14:49:13.000000000 +0200
@@ -51,13 +51,39 @@
 #include <mailutils/argcv.h>
 #include <mailutils/tls.h>
 
+#ifdef WITH_GSSAPI
+#include <netinet/in.h>
+# ifdef WITH_GSS
+#  include <gss.h>
+# else
+#  include <krb5.h>
+#  ifdef HAVE_GSSAPI_H
+#   include <gssapi.h>
+#  else
+#   ifdef HAVE_GSSAPI_GSSAPI_H
+#    include <gssapi/gssapi.h>
+#   endif
+#   ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#    include <gssapi/gssapi_generic.h>
+#   endif
+#  endif
+# endif
+#endif
+
+/* See RFC 2222 §7.2.3 */
+#define GSS_AUTH_P_NONE      1
+#define GSS_AUTH_P_INTEGRITY 2
+#define GSS_AUTH_P_PRIVACY   4
+
+#define SUPPORTED_P_MECH GSS_AUTH_P_NONE
+
 /* For dbg purposes set to one to see different level of traffic.  */
 /* Print to stderr the command sent to the IMAP server.  */
-#define DEBUG_SHOW_COMMAND 0
+#define DEBUG_SHOW_COMMAND 1
 /* Print to stderr the responses received from the IMAP server.  */
-#define DEBUG_SHOW_RESPONSE 0
+#define DEBUG_SHOW_RESPONSE 1
 /* Print to stderr the literal/quoted string received from the IMAP server.  */
-#define DEBUG_SHOW_DATA 0
+#define DEBUG_SHOW_DATA 1
 
 /* Variable use for the registrar.  */
 static struct _record _imap_record =
@@ -130,6 +156,192 @@
 static int  check_capa              __P ((f_imap_t f_imap, char *capa));
 
 
+#ifdef WITH_GSSAPI
+static void
+display_status_1 (char *m, OM_uint32 code, int type)
+{
+  OM_uint32 maj_stat, min_stat;
+  gss_buffer_desc msg;
+  OM_uint32 msg_ctx;
+
+  msg_ctx = 0;
+  do
+    {
+      maj_stat = gss_display_status (&min_stat, code,
+				     type, GSS_C_NO_OID, &msg_ctx, &msg);
+      if (GSS_ERROR (maj_stat))
+	{
+	  asprintf ((char**)&msg.value, "code %d", code);
+	  msg.length = strlen (msg.value);
+	}
+
+      printf ("GSS-API error %s (%s): %.*s\n",
+	      m, type == GSS_C_GSS_CODE ? "major" : "minor",
+	      (int) msg.length, (char *) msg.value);
+
+      if (GSS_ERROR (maj_stat))
+	free (msg.value);
+      else
+        gss_release_buffer (&min_stat, &msg);
+    }
+  while (!GSS_ERROR (maj_stat) && msg_ctx);
+}
+
+static void
+display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+  display_status_1 (msg, maj_stat, GSS_C_GSS_CODE);
+  display_status_1 (msg, min_stat, GSS_C_MECH_CODE);
+}
+
+/* Here we construct the GSSAPI service name (service@host) */
+gss_name_t construct_service_name (folder_t folder, const char *service_name)
+{
+  gss_buffer_desc buffer;
+  gss_name_t service = GSS_C_NO_NAME;
+  OM_uint32 maj_stat, min_stat, dummy_stat;
+  size_t host_name_len;
+
+  /* Fetch the server name in the url_t.
+     The url has been already parsed so we guess everything is OK (ie host_name_len > 0).
+  */
+  (void) url_get_host (folder->url, NULL, 0, &host_name_len);
+  
+  buffer.length = host_name_len + strlen (service_name) + 1; /* one more byte for the '@' */
+  buffer.value = malloc (buffer.length + 1); /* one more byte for the final \0 */
+  if (buffer.value == NULL)
+    return GSS_C_NO_NAME; /* out of memory ! */
+
+  (void) memcpy (buffer.value, service_name, strlen (service_name));
+  ((char *) buffer.value)[strlen (service_name)] = '@';
+  (void) url_get_host (folder->url, buffer.value + strlen(service_name) + 1, host_name_len + 1, NULL);
+  
+  maj_stat = gss_import_name (&min_stat, &buffer, GSS_C_NT_HOSTBASED_SERVICE, &service);
+  (void) gss_release_buffer(&dummy_stat, &buffer);
+  
+  if (GSS_ERROR(maj_stat))
+    {
+      display_status ("import name", maj_stat, min_stat);
+      return GSS_C_NO_NAME;
+    }
+
+  return service;
+}
+
+void abort_auth (f_imap_t f_imap)
+{
+  OM_uint32 dummy_stat;
+
+  (void) imap_send (f_imap);
+
+  if (f_imap->gss_context != GSS_C_NO_CONTEXT)
+    (void) gss_delete_sec_context(&dummy_stat, &f_imap->gss_context, GSS_C_NO_BUFFER);
+}
+
+int send_token (f_imap_t f_imap, const gss_buffer_t input_tok, const unsigned int protection)
+{
+  gss_buffer_desc output_tok;
+  unsigned char *buffer;
+  size_t len;
+  OM_uint32 dummy_stat;
+
+  if (input_tok->length > 0)
+    {      
+      switch (protection)
+	{
+	case GSS_AUTH_P_PRIVACY:
+	  {
+	    OM_uint32 maj_stat, min_stat;
+
+	    maj_stat = gss_wrap (&min_stat, f_imap->gss_context, 1, GSS_C_QOP_DEFAULT, input_tok, (int *) NULL, &output_tok);
+	    break;
+	  }
+	case GSS_AUTH_P_INTEGRITY:
+	  {
+	    OM_uint32 maj_stat, min_stat;
+
+	    maj_stat = gss_wrap (&min_stat, f_imap->gss_context, 0, GSS_C_QOP_DEFAULT, input_tok, (int *) NULL, &output_tok);
+	    break;
+	  }	  
+	case GSS_AUTH_P_NONE:
+	default:
+	  output_tok = *input_tok;
+	}
+
+      (void) util_base64_encode ((unsigned char *) output_tok.value, output_tok.length, &buffer, &len);
+
+      if (protection != GSS_AUTH_P_NONE) /* gss_wrap had allocated a new token so release it */
+	(void) gss_release_buffer (&dummy_stat, &output_tok);
+
+      (void) imap_writeline (f_imap, "%s\r\n", buffer);
+      free (buffer);
+    }
+  else 
+    (void) imap_writeline (f_imap, "\r\n");
+
+  (void) imap_send (f_imap);
+  return 0; /* SUCCESS */
+}
+
+gss_buffer_t recv_token (f_imap_t f_imap, const unsigned int protection)
+{
+  gss_buffer_desc input_tok, *output_tok;
+  size_t len;
+
+  output_tok = malloc (sizeof (gss_buffer_desc));
+  if (output_tok == NULL)
+    return GSS_C_NO_BUFFER; /* out of memory ! */
+
+  output_tok->length = 0;
+  output_tok->value = NULL;
+
+  (void) imap_readline (f_imap);
+  f_imap->ptr = f_imap->buffer;
+  
+  /* We except a continuation tag
+     another response means probably NO */
+  if (*f_imap->ptr != '+')
+    {
+      OM_uint32 dummy_stat;
+      (void) gss_release_buffer (&dummy_stat, output_tok);
+      free (output_tok);
+      return GSS_C_NO_BUFFER;
+    }
+  
+  len = f_imap->nl - f_imap->buffer - 3;
+  
+  if (len > 0)
+    {
+      (void) util_base64_decode ((unsigned char *) f_imap->buffer + 2, len, (unsigned char **) &input_tok.value, &input_tok.length);
+
+      switch (protection)
+	{
+	case GSS_AUTH_P_INTEGRITY:
+	case GSS_AUTH_P_PRIVACY:
+	  {
+	    OM_uint32 maj_stat, min_stat;
+
+	    maj_stat = gss_unwrap (&min_stat, f_imap->gss_context, &input_tok, output_tok, (int *) NULL, (gss_qop_t *) NULL);
+	    (void) gss_release_buffer (&min_stat, &input_tok);
+	    if (GSS_ERROR (maj_stat))
+	      {
+		(void) gss_release_buffer (&min_stat, output_tok);
+		free (output_tok);
+		return GSS_C_NO_BUFFER;
+	      }
+	    break;
+	  }
+	case GSS_AUTH_P_NONE:
+	  *output_tok = input_tok; /* copy */
+	  break;
+	}
+    }
+  
+  return output_tok;
+}
+
+#endif /* WITH_GSSAPI */
+
 /* Authentication methods */
 
 typedef int (*auth_method_t) __P((authority_t));
@@ -275,10 +487,10 @@
 
   assert (f_imap->state == IMAP_AUTH);
 
-  if (check_capa (f_imap, "AUTH=ANONYMOUS"))
+  if (check_capa (f_imap, "AUTH=GSSAPI"))
     {
       FOLDER_DEBUG0 (folder, MU_DEBUG_PROT,
-		     "ANONYMOUS capability not present\n");
+		     "GSSAPI capability not present\n");
       return ENOSYS;
     }
 
@@ -339,6 +551,240 @@
   return 0;
 }
 
+/* 
+   The SASL GSSAPI mechanism is defined in rfc 2222 §7.2.
+   We focus here on the client side implementation as described in §7.2.1.
+*/
+
+#ifdef WITH_GSSAPI
+
+static int
+authenticate_imap_gssapi (authority_t auth)
+{
+  folder_t folder = authority_get_owner (auth);
+  f_imap_t f_imap = folder->data;
+  ticket_t ticket;
+  int status = 0;
+
+  const char *SERVICE_NAME = "imap";
+
+  static int protection_mech;
+  size_t server_buffer_size;
+  size_t client_buffer_size = 1 << 13;
+
+  assert ((client_buffer_size  & 0xff000000) == 0);
+  assert (f_imap->state == IMAP_AUTH);
+  assert (f_imap->gss_context == GSS_C_NO_CONTEXT);
+
+  if (check_capa (f_imap, "AUTH=GSSAPI"))
+    {
+      FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, "AUTH=GSSAPI capability not present\n");
+      return ENOSYS;
+    }
+
+  switch (f_imap->state)
+    {
+    case IMAP_AUTH:
+      {
+	/* Grab authorization identity */
+	size_t len = 0;
+	
+	authority_get_ticket (auth, &ticket);
+	if (f_imap->user)
+	  free (f_imap->user);
+	if (f_imap->passwd)
+	  free (f_imap->passwd);
+	/* Was it in the URL?  */
+	status = url_get_user (folder->url, NULL, 0, &len);
+	if (status != 0 || len == 0)
+	  ticket_pop (ticket, folder->url, "Imap User: ",  &f_imap->user);
+	else
+	  {
+	    f_imap->user = malloc (len + 1);
+	    url_get_user (folder->url, f_imap->user, len + 1, NULL);
+	  }
+	  
+	if (f_imap->user == NULL)
+	  return MU_ERR_NOUSERNAME;
+	
+	/* sending AUTHENTICATE command */
+	status = imap_writeline (f_imap, "g%u AUTHENTICATE GSSAPI\r\n", f_imap->seq);
+	CHECK_EAGAIN(f_imap, status);
+		
+	status = imap_send (f_imap);
+	CHECK_EAGAIN(f_imap, status);
+
+	f_imap->seq++;
+	f_imap->state = IMAP_LOGIN;
+      }
+
+    case IMAP_LOGIN:
+      {
+	gss_buffer_desc *input_tok, output_tok;
+	OM_uint32 maj_stat, min_stat, dummy_stat;
+	gss_name_t service_name;
+
+	service_name = construct_service_name (folder, SERVICE_NAME);
+	if (service_name == GSS_C_NO_NAME)
+	  return MU_ERR_GSSAPI_GENERIC;
+
+	if (recv_token (f_imap, GSS_AUTH_P_NONE) == GSS_C_NO_BUFFER)
+	  /* AUTHENTICATE GSSAPI was rejected so try another method */
+	  return ENOSYS;
+	
+	input_tok = GSS_C_NO_BUFFER;
+
+	do {
+	  maj_stat =
+	    gss_init_sec_context(&min_stat,
+				 GSS_C_NO_CREDENTIAL,
+				 &f_imap->gss_context,
+				 service_name,
+				 GSS_C_NO_OID,
+				 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
+				 0,
+				 GSS_C_NO_CHANNEL_BINDINGS,	/* no channel bindings */
+				 input_tok,
+				 NULL,	                        /* ignore mech type */
+				 &output_tok,
+				 NULL,                          /* ignore ret_flags */
+				 NULL);	                        /* ignore time_rec */
+
+	  if (input_tok != GSS_C_NO_BUFFER && input_tok->length > 0)
+	    (void) gss_release_buffer (&dummy_stat, input_tok);
+
+	  if (GSS_ERROR (maj_stat)) /* if we have an error fallback to another authentication method */
+	    {
+	      if (output_tok.length >0)
+		(void) gss_release_buffer (&dummy_stat, &output_tok);
+
+	      abort_auth (f_imap);
+	      
+	      (void) gss_release_name(&dummy_stat, &service_name);
+
+	      display_status ("init context", maj_stat, min_stat);
+
+	      /* this doesn't seems to work */
+	      if (GSS_ROUTINE_ERROR (maj_stat) == GSS_S_NO_CRED)
+		{
+		  FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, "GSSAPI: No credential found\n");
+		}
+	      
+	      return ENOSYS; /* Fallback to another authentication method */
+	    }
+
+	  if (output_tok.length > 0)
+	    {
+	      (void) send_token (f_imap, &output_tok, GSS_AUTH_P_NONE);
+	      (void) gss_release_buffer (&dummy_stat, &output_tok);
+	    }
+	  
+	  if (GSS_SUPPLEMENTARY_INFO (maj_stat) == GSS_S_CONTINUE_NEEDED)
+	    if ((input_tok = recv_token (f_imap, GSS_AUTH_P_NONE)) == GSS_C_NO_BUFFER)
+	      {
+		/* We have received a NO */
+		abort_auht (f_imap);
+		(void) gss_release_name(&dummy_stat, &service_name);
+		FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, "GSSAPI: Rejected by host\n");
+		
+		return ENOSYS; /* Fallback to another authentication method */
+	      }
+	  
+	
+	} while (GSS_SUPPLEMENTARY_INFO (maj_stat) == GSS_S_CONTINUE_NEEDED);
+
+	(void) gss_release_name(&dummy_stat, &service_name);
+
+	/* RFC 2222: If the last call to GSS_Init_sec_context
+	   returned an output_token, then the client responds with the
+	   output_token, otherwise the client responds with no data.
+	*/
+	send_token (f_imap, &output_tok, GSS_AUTH_P_NONE);
+	(void) gss_release_buffer (&min_stat, &output_tok);
+
+	/* Next we should receive a token containing the security layer 
+	   and the maximum size of message to send to the server.
+	*/
+	input_tok = recv_token (f_imap, GSS_AUTH_P_PRIVACY);
+
+	if (input_tok->length != 4)
+	  {
+	    abort_auth (f_imap);
+	    return MU_ERR_GSSAPI_GENERIC;
+	  }
+	
+	protection_mech = *(uint32_t *) input_tok->value & 0x000000ff;
+	/* this is useless until we support GSS_AUTH_P_PRIVACY or GSS_AUTH_P_INTEGRITY */
+	server_buffer_size = ntohl (*(uint32_t *) input_tok->value & 0xffffff00);
+
+	(void) gss_release_buffer (&dummy_stat, input_tok);
+	free (input_tok);
+
+	/* RFC 2222: We now construct a new token with the first octet containing the
+	   bit-mask specifying the selected security layer, the second through
+	   fourth octets containing in network byte order the maximum size
+	   output_message the client is able to receive, and the remaining
+	   octets containing the authorization identity.
+	*/
+
+	if (protection_mech & GSS_AUTH_P_PRIVACY)
+	  protection_mech = GSS_AUTH_P_PRIVACY;
+	else if (protection_mech & GSS_AUTH_P_INTEGRITY)
+	  protection_mech = GSS_AUTH_P_INTEGRITY;
+	else if (protection_mech & GSS_AUTH_P_NONE)
+	  protection_mech = GSS_AUTH_P_NONE;
+	else
+	  {
+	    abort_auth (f_imap);
+	    return MU_ERR_GSSAPI_GENERIC;
+	  }
+
+	output_tok.length = 1 + 3 + strlen (f_imap->user);
+	output_tok.value = malloc (output_tok.length);
+
+	*(uint32_t *)output_tok.value = protection_mech;
+
+	{
+	  uint32_t sec_level;
+
+	  sec_level = htonl (client_buffer_size);
+	  memcpy ((void *) (output_tok.value + 1), (void *) &sec_level,  3);
+	  memcpy ((void *) (output_tok.value + 4), (void *) f_imap->user, output_tok.length - 1 - 3);
+	}
+	(void) send_token (f_imap, &output_tok, GSS_AUTH_P_INTEGRITY);
+	(void) gss_release_buffer (&dummy_stat, &output_tok);
+
+	/* Don't need password */
+	if (f_imap->passwd)
+	  {
+	    free (f_imap->passwd);
+	    f_imap->passwd = NULL;
+	  }
+
+	f_imap->seq++;
+	f_imap->state = IMAP_LOGIN;
+      }
+
+    case IMAP_LOGIN_ACK:
+      memset (f_imap->buffer, '\0', f_imap->buflen);
+      f_imap->state = IMAP_LOGIN_ACK;
+
+      /* Get the login ack.  */
+      status = imap_parse (f_imap);
+      if (status)
+	return status;
+      FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer);
+      f_imap->state = IMAP_AUTH_DONE;
+
+    default:
+      break;  /* We're outta here.  */
+    }
+  CLEAR_STATE (f_imap);
+  return 0;
+
+}
+#endif /* WITH_GSSAPI */
+
 struct auth_tab
 {
   char *name;
@@ -349,6 +795,9 @@
    to less secure. */
 
 static struct auth_tab auth_tab[] = {
+#ifdef WITH_GSSAPI
+  { "gssapi", authenticate_imap_gssapi },
+#endif
   { "login", authenticate_imap_login },
   { "anon", authenticate_imap_sasl_anon },
   { NULL }
@@ -407,6 +856,9 @@
 
   f_imap->folder = folder;
   f_imap->state = IMAP_NO_STATE;
+#ifdef WITH_GSSAPI
+  f_imap->gss_context = GSS_C_NO_CONTEXT;
+#endif
 
   folder->_destroy = folder_imap_destroy;
 
@@ -434,6 +886,13 @@
 	free (f_imap->buffer);
       if (f_imap->capav)
 	argcv_free (f_imap->capac, f_imap->capav);
+#ifdef WITH_GSSAPI
+      if (f_imap->gss_context != GSS_C_NO_CONTEXT)
+	{
+	  OM_uint32 dummy_stat;
+	  (void) gss_delete_sec_context(&dummy_stat, &f_imap->gss_context, GSS_C_NO_BUFFER);
+	}
+#endif
       free (f_imap);
       folder->data = NULL;
     }
@@ -2036,13 +2495,15 @@
 imap_writeline (f_imap_t f_imap, const char *format, ...)
 {
   int len;
-  va_list ap;
+  va_list ap, tmp;
   int done = 1;
 
   va_start(ap, format);
   do
     {
-      len = vsnprintf (f_imap->buffer, f_imap->buflen - 1, format, ap);
+      va_copy (tmp, ap);
+      len = vsnprintf (f_imap->buffer, f_imap->buflen - 1, format, tmp);
+      va_end (tmp);
       if (len < 0 || len >= (int)f_imap->buflen
           || !memchr (f_imap->buffer, '\0', len + 1))
         {
diff -BN -ru mailbox/imap/Makefile.am mailbox/imap/Makefile.am
--- mailbox/imap/Makefile.am	2003-09-20 17:21:34.000000000 +0200
+++ mailbox/imap/Makefile.am	2005-06-15 17:33:58.000000000 +0200
@@ -19,12 +19,15 @@
 
 INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/mailbox \
  -I${top_srcdir}/mailbox/include -I${top_builddir}/include/mailutils/gnu \
- @INTLINCS@
+ @INTLINCS@ @SERV_AUTHINCS@
 
 lib_LTLIBRARIES = libmu_imap.la
 
+libmu_imap_la_LIBADD = @SERV_AUTHLIBS@
+
 libmu_imap_la_SOURCES = \
  folder.c\
  mbox.c\
- url.c
+ url.c \
+ base64.c
 
diff -BN -ru mailbox/imap/util.c mailbox/imap/util.c
--- mailbox/imap/util.c	1970-01-01 01:00:00.000000000 +0100
+++ mailbox/imap/util.c	2005-07-26 15:02:50.000000000 +0200
@@ -0,0 +1,106 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA  */
+
+
+#include <stdlib.h>
+
+#ifndef WITH_GSSAPI
+void dummy (int x) { dummy (x -1) }
+#else
+int
+util_base64_encode (const unsigned char *input, size_t input_len,
+		    unsigned char **output, size_t * output_len)
+{
+  static char b64tab[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  size_t olen = 4 * (input_len + 2) / 3;
+  unsigned char *out = malloc (olen + 1); /* one more byte for the final \0 */
+
+  if (!out)
+    return 1;
+  *output = out;
+  while (input_len >= 3)
+    {
+      *out++ = b64tab[input[0] >> 2];
+      *out++ = b64tab[((input[0] << 4) & 0x30) | (input[1] >> 4)];
+      *out++ = b64tab[((input[1] << 2) & 0x3c) | (input[2] >> 6)];
+      *out++ = b64tab[input[2] & 0x3f];
+      olen -= 4;
+      input_len -= 3;
+      input += 3;
+    }
+
+  if (input_len > 0)
+    {
+      unsigned char c = (input[0] << 4) & 0x30;
+      *out++ = b64tab[input[0] >> 2];
+      if (input_len > 1)
+	c |= input[1] >> 4;
+      *out++ = b64tab[c];
+      *out++ = (input_len < 2) ? '=' : b64tab[(input[1] << 2) & 0x3c];
+      *out++ = '=';
+    }
+
+  *out = '\0';
+  *output_len = out - *output;
+  return 0;
+}
+
+int
+util_base64_decode (const unsigned char *input, size_t input_len,
+		    unsigned char **output, size_t * output_len)
+{
+  static int b64val[128] = {
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
+  };
+  int olen = input_len;
+  unsigned char *out = malloc (olen + 1); /* one more byte for the final \0 */
+
+  if (!out)
+    return 1;
+  *output = out;
+  do
+    {
+      if (input[0] > 127 || b64val[input[0]] == -1
+	  || input[1] > 127 || b64val[input[1]] == -1
+	  || input[2] > 127 || ((input[2] != '=') && (b64val[input[2]] == -1))
+	  || input[3] > 127 || ((input[3] != '=')
+				&& (b64val[input[3]] == -1)))
+	return -1;
+      *out++ = (b64val[input[0]] << 2) | (b64val[input[1]] >> 4);
+      if (input[2] != '=')
+	{
+	  *out++ = ((b64val[input[1]] << 4) & 0xf0) | (b64val[input[2]] >> 2);
+	  if (input[3] != '=')
+	    *out++ = ((b64val[input[2]] << 6) & 0xc0) | b64val[input[3]];
+	}
+      input += 4;
+      input_len -= 4;
+    }
+  while (input_len > 0);
+  *out = '\0';
+  *output_len = out - *output;
+  return 0;
+}
+#endif
diff -BN -ru mailbox/include/imap0.h mailbox/include/imap0.h
--- mailbox/include/imap0.h	2004-08-07 09:37:45.000000000 +0200
+++ mailbox/include/imap0.h	2005-07-19 02:30:47.000000000 +0200
@@ -27,6 +27,24 @@
 #include <registrar0.h>
 #include <auth0.h>
 
+#ifdef WITH_GSSAPI
+# ifdef WITH_GSS
+#  include <gss.h>
+# else
+#  include <krb5.h>
+#  ifdef HAVE_GSSAPI_H
+#   include <gssapi.h>
+#  else
+#   ifdef HAVE_GSSAPI_GSSAPI_H
+#    include <gssapi/gssapi.h>
+#   endif
+#   ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#    include <gssapi/gssapi_generic.h>
+#   endif
+#  endif
+# endif
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -176,6 +194,10 @@
   char *user;
   char *passwd;
 
+#ifdef WITH_GSSAPI
+  gss_ctx_id_t gss_context;
+#endif
+
   /* AUTHENTICATE states */
   enum imap_auth_state auth_state;
 };
@@ -229,6 +251,15 @@
 int imap_readline     __P ((f_imap_t));
 char *section_name    __P ((msg_imap_t));
 
+extern int util_base64_encode __P((const unsigned char *input,
+				   size_t input_len,
+				   unsigned char **output,
+				   size_t *output_len));
+extern int util_base64_decode __P((const unsigned char *input,
+				   size_t input_len,
+				   unsigned char **output,
+				   size_t *output_len));
+
 #ifdef __cplusplus
 }
 #endif
