--- imap.rb	2009-07-18 23:35:39.959311223 +0200
+++ /usr/lib/ruby/1.8/net/imap.rb	2009-07-19 01:33:09.779255462 +0200
@@ -16,6 +16,7 @@
 require "socket"
 require "monitor"
 require "digest/md5"
+require "gss"
 begin
   require "openssl"
 rescue LoadError
@@ -3185,6 +3186,62 @@
     end
     add_authenticator "CRAM-MD5", CramMD5Authenticator
 
+    # Authenticator for Kerberos (GSSAPI). Pass the hostname as password,
+    # we need it to create the servicename (imap@hostname). See authenticate()
+    class GSSAPIAuthenticator
+      def process(data)
+        case @state
+        when STATE_CRED_EX_FIRST
+          input = Gss::Step.new(nil, nil, Gss::SEQUENCE_FLAG | Gss::MUTUAL_FLAG)
+          output = Gss::Step.new
+          @context = Gss::Context.new
+
+          @status = @context.init(nil, @service_name, input, nil, output).check
+          @state = STATE_CRED_EX_CONT
+
+          return output.token
+        when STATE_CRED_EX_CONT
+          input = Gss::Step.new(data, nil, Gss::SEQUENCE_FLAG | Gss::MUTUAL_FLAG)
+          output = Gss::Step.new
+          @status = @context.init(nil, @service_name, input, nil, output).check
+
+          if @status.major != Gss::S_CONTINUE_NEEDED
+            @state = STATE_UNWRAP
+          end
+
+          return output.token
+        when STATE_UNWRAP
+          output = Gss::Step.new
+          @context.unwrap(Gss::Step.new(data), output).check
+
+          # TODO: We should check here if the first byte contains \1, meaning
+          # that no security level is necessary (we want authentication only)
+          max_size = "\0" + output.token[1,3]
+
+          # build authorization request
+          request = "\1" + max_size[1,3] + @user
+          output = Gss::Step.new
+          @context.wrap(0, Gss::QOP_DEFAULT, Gss::Step.new(request), output).check
+
+          return output.token
+        end
+      end
+
+      private
+
+      STATE_CRED_EX_FIRST = :CRED_EX_FIRST
+      STATE_CRED_EX_CONT = :CRED_EX_CONT
+      STATE_UNWRAP = :UNWRAP
+
+      def initialize(user, password)
+        @user = user
+        @service_name = Gss::Name::import(Gss::Oid::NT_HOSTBASED_SERVICE, "imap@" + password)
+        @state = STATE_CRED_EX_FIRST
+      end
+    end
+
+    add_authenticator 'GSSAPI', GSSAPIAuthenticator
+
     # Superclass of IMAP errors.
     class Error < StandardError
     end
