-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
Attached is a patch against current CVS that adds support for the
GSSAPI SASL mechanism. It was written from scratch, after reading the
patch from Colin Walters against a much older version of dovecot.
Other then support for the 'GSSAPI' mechanism, it contains the
following changes:
- - Added 'auth_krb5_keytab' option for overriding default keytab
location. The gssapi library already uses the environment variable
KRB5_KTNAME to allow overriding of the keytab location, so I didn't
have to make any changes on the login process side.
- - Added 'need_passdb' member to mech_module and allow having no
passdb's specified if no mechanisms need them (only useful for GSSAPI
at the moment)
Cheers,
Jelmer
- --
Jelmer Vernooij
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFDVgaEPa9Uoh7vUnYRAscGAJ9Fa4E5ze5IX3UeAfjwg7kzj5tgtQCcDva7
O5VTeOeJ7zpmHullxQN6q1Y=
=60w7
-----END PGP SIGNATURE-----
Index: configure.in
===================================================================
RCS file: /home/cvs/dovecot/configure.in,v
retrieving revision 1.214
diff -u -r1.214 configure.in
--- configure.in 23 Sep 2005 13:28:40 -0000 1.214
+++ configure.in 19 Oct 2005 08:25:31 -0000
@@ -118,6 +118,15 @@
fi,
want_bsdauth=yes)
+AC_ARG_WITH(gssapi,
+[ --with-gssapi Build with GSSAPI authentication support (default)],
+ if test x$withval = xno; then
+ want_gssapi=no
+ else
+ want_gssapi_yes
+ fi,
+ want_gssapi=yes)
+
AC_ARG_WITH(ldap,
[ --with-ldap Build with LDAP support],
if test x$withval = xno; then
@@ -1192,6 +1201,17 @@
])
fi
+have_gssapi=no
+if test $want_gssapi = yes; then
+ AC_CHECK_PROG(KRB5CONFIG, krb5-config, YES, NO)
+ if test $KRB5CONFIG = YES; then
+ AUTH_LIBS="$AUTH_LIBS `krb5-config --libs gssapi`"
+ AUTH_CFLAGS="$AUTH_CFLAGS `krb5-config --cflags gssapi`"
+ AC_DEFINE(MECH_GSSAPI,, Build with GSSAPI support)
+ have_gssapi=yes
+ fi
+fi
+
if test $want_ldap = yes; then
AC_CHECK_LIB(ldap, ldap_init, [
AC_CHECK_HEADER(ldap.h, [
@@ -1486,5 +1506,6 @@
echo "Building with IPv6 support .......... : $want_ipv6"
echo "Building with pop3 server ........... : $want_pop3d"
echo "Building with mail delivery agent .. : $want_deliver"
+echo "Building with GSSAPI support ........ : $have_gssapi"
echo "Building with user database modules . :$userdb"
echo "Building with password lookup modules :$passdb"
Index: dovecot-example.conf
===================================================================
RCS file: /home/cvs/dovecot/dovecot-example.conf,v
retrieving revision 1.155
diff -u -r1.155 dovecot-example.conf
--- dovecot-example.conf 16 Oct 2005 14:59:12 -0000 1.155
+++ dovecot-example.conf 19 Oct 2005 08:25:31 -0000
@@ -568,9 +568,13 @@
# automatically created and destroyed as needed.
#auth_worker_max_count = 30
+# Kerberos keytab to use for the GSSAPI mechanism. Will use the system
+# default (usually /etc/krb5.keytab) if not specified.
+#auth_krb5_keytab =
+
auth default {
# Space separated list of wanted authentication mechanisms:
- # plain digest-md5 cram-md5 apop anonymous
+ # plain digest-md5 cram-md5 apop anonymous gssapi
mechanisms = plain
#
Index: src/auth/Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.47
diff -u -r1.47 Makefile.am
--- src/auth/Makefile.am 7 Aug 2005 11:41:19 -0000 1.47
+++ src/auth/Makefile.am 19 Oct 2005 08:25:31 -0000
@@ -54,6 +54,7 @@
mech-cram-md5.c \
mech-digest-md5.c \
mech-ntlm.c \
+ mech-gssapi.c \
mech-rpa.c \
mech-apop.c \
passdb.c \
Index: src/auth/auth.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/auth.c,v
retrieving revision 1.19
diff -u -r1.19 auth.c
--- src/auth/auth.c 16 Oct 2005 14:06:59 -0000 1.19
+++ src/auth/auth.c 19 Oct 2005 08:25:31 -0000
@@ -56,8 +56,6 @@
}
t_pop();
- if (auth->passdbs == NULL)
- i_fatal("No password databases set");
if (auth->userdbs == NULL)
i_fatal("No user databases set");
return auth;
@@ -130,6 +128,9 @@
struct mech_module_list *list;
for (list = auth->mech_modules; list != NULL; list = list->next) {
+ if (list->module.need_passdb &&
+ !auth->passdbs)
+ break;
if (list->module.passdb_need_plain &&
!auth_passdb_list_have_plain(auth))
break;
Index: src/auth/mech-anonymous.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-anonymous.c,v
retrieving revision 1.13
diff -u -r1.13 mech-anonymous.c
--- src/auth/mech-anonymous.c 23 Apr 2005 09:11:49 -0000 1.13
+++ src/auth/mech-anonymous.c 19 Oct 2005 08:25:31 -0000
@@ -57,6 +57,7 @@
MEMBER(flags) MECH_SEC_ANONYMOUS,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) FALSE,
Index: src/auth/mech-apop.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-apop.c,v
retrieving revision 1.16
diff -u -r1.16 mech-apop.c
--- src/auth/mech-apop.c 23 Apr 2005 09:11:49 -0000 1.16
+++ src/auth/mech-apop.c 19 Oct 2005 08:25:31 -0000
@@ -162,6 +162,7 @@
MEMBER(flags) MECH_SEC_PRIVATE | MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
Index: src/auth/mech-cram-md5.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-cram-md5.c,v
retrieving revision 1.20
diff -u -r1.20 mech-cram-md5.c
--- src/auth/mech-cram-md5.c 8 Jan 2005 21:37:32 -0000 1.20
+++ src/auth/mech-cram-md5.c 19 Oct 2005 08:25:32 -0000
@@ -191,6 +191,7 @@
MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
Index: src/auth/mech-digest-md5.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-digest-md5.c,v
retrieving revision 1.34
diff -u -r1.34 mech-digest-md5.c
--- src/auth/mech-digest-md5.c 8 Jan 2005 21:37:32 -0000 1.34
+++ src/auth/mech-digest-md5.c 19 Oct 2005 08:25:32 -0000
@@ -619,6 +619,7 @@
MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE |
MECH_SEC_MUTUAL_AUTH,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
Index: src/auth/mech-login.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-login.c,v
retrieving revision 1.12
diff -u -r1.12 mech-login.c
--- src/auth/mech-login.c 23 Apr 2005 09:11:49 -0000 1.12
+++ src/auth/mech-login.c 19 Oct 2005 08:25:32 -0000
@@ -87,6 +87,7 @@
MEMBER(flags) MECH_SEC_PLAINTEXT,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) TRUE,
MEMBER(passdb_need_credentials) FALSE,
Index: src/auth/mech-ntlm.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-ntlm.c,v
retrieving revision 1.19
diff -u -r1.19 mech-ntlm.c
--- src/auth/mech-ntlm.c 23 Apr 2005 09:11:49 -0000 1.19
+++ src/auth/mech-ntlm.c 19 Oct 2005 08:25:32 -0000
@@ -281,6 +281,7 @@
MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
Index: src/auth/mech-plain.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-plain.c,v
retrieving revision 1.31
diff -u -r1.31 mech-plain.c
--- src/auth/mech-plain.c 23 Apr 2005 09:11:49 -0000 1.31
+++ src/auth/mech-plain.c 19 Oct 2005 08:25:32 -0000
@@ -103,6 +103,7 @@
MEMBER(flags) MECH_SEC_PLAINTEXT,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) TRUE,
MEMBER(passdb_need_credentials) FALSE,
Index: src/auth/mech-rpa.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech-rpa.c,v
retrieving revision 1.19
diff -u -r1.19 mech-rpa.c
--- src/auth/mech-rpa.c 23 Apr 2005 09:11:49 -0000 1.19
+++ src/auth/mech-rpa.c 19 Oct 2005 08:25:32 -0000
@@ -614,6 +614,7 @@
MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE |
MECH_SEC_MUTUAL_AUTH,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) TRUE,
Index: src/auth/mech.c
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech.c,v
retrieving revision 1.54
diff -u -r1.54 mech.c
--- src/auth/mech.c 7 Jan 2005 19:55:50 -0000 1.54
+++ src/auth/mech.c 19 Oct 2005 08:25:32 -0000
@@ -54,6 +54,9 @@
extern struct mech_module mech_ntlm;
extern struct mech_module mech_rpa;
extern struct mech_module mech_anonymous;
+#ifdef MECH_GSSAPI
+extern struct mech_module mech_gssapi;
+#endif
void mech_init(void)
{
@@ -65,6 +68,9 @@
mech_register_module(&mech_ntlm);
mech_register_module(&mech_rpa);
mech_register_module(&mech_anonymous);
+#ifdef MECH_GSSAPI
+ mech_register_module(&mech_gssapi);
+#endif
}
void mech_deinit(void)
@@ -77,4 +83,7 @@
mech_unregister_module(&mech_ntlm);
mech_unregister_module(&mech_rpa);
mech_unregister_module(&mech_anonymous);
+#ifdef MECH_GSSAPI
+ mech_unregister_module(&mech_gssapi);
+#endif
}
Index: src/auth/mech.h
===================================================================
RCS file: /home/cvs/dovecot/src/auth/mech.h,v
retrieving revision 1.35
diff -u -r1.35 mech.h
--- src/auth/mech.h 9 Jan 2005 16:54:48 -0000 1.35
+++ src/auth/mech.h 19 Oct 2005 08:25:32 -0000
@@ -24,6 +24,7 @@
const char *mech_name;
enum mech_security_flags flags;
+ unsigned int need_passdb:1;
unsigned int passdb_need_plain:1;
unsigned int passdb_need_credentials:1;
Index: src/master/auth-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/auth-process.c,v
retrieving revision 1.82
diff -u -r1.82 auth-process.c
--- src/master/auth-process.c 1 Oct 2005 10:52:16 -0000 1.82
+++ src/master/auth-process.c 19 Oct 2005 08:25:33 -0000
@@ -458,6 +458,8 @@
env_put("SSL_REQUIRE_CLIENT_CERT=1");
if (set->ssl_username_from_cert)
env_put("SSL_USERNAME_FROM_CERT=1");
+ if (set->krb5_keytab)
+ env_put(t_strconcat("KRB5_KTNAME=", set->krb5_keytab, NULL));
restrict_process_size(set->process_size, (unsigned int)-1);
}
Index: src/master/master-settings.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-settings.c,v
retrieving revision 1.92
diff -u -r1.92 master-settings.c
--- src/master/master-settings.c 16 Oct 2005 14:59:17 -0000 1.92
+++ src/master/master-settings.c 19 Oct 2005 08:25:33 -0000
@@ -155,6 +155,7 @@
DEF(SET_STR, username_chars),
DEF(SET_STR, username_translation),
DEF(SET_STR, anonymous_username),
+ DEF(SET_STR, krb5_keytab),
DEF(SET_BOOL, verbose),
DEF(SET_BOOL, debug),
@@ -353,6 +354,7 @@
MEMBER(username_chars) "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@",
MEMBER(username_translation) "",
MEMBER(anonymous_username) "anonymous",
+ MEMBER(krb5_keytab) NULL,
MEMBER(verbose) FALSE,
MEMBER(debug) FALSE,
Index: src/master/master-settings.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-settings.h,v
retrieving revision 1.60
diff -u -r1.60 master-settings.h
--- src/master/master-settings.h 1 Oct 2005 10:52:16 -0000 1.60
+++ src/master/master-settings.h 19 Oct 2005 08:25:33 -0000
@@ -162,6 +162,7 @@
const char *username_chars;
const char *username_translation;
const char *anonymous_username;
+ const char *krb5_keytab;
int verbose, debug;
int ssl_require_client_cert;
--- /dev/null 2005-10-17 12:49:06.896857000 +0200
+++ src/auth/mech-gssapi.c 2005-10-19 10:17:45.000000000 +0200
@@ -0,0 +1,321 @@
+/*
+ * GSSAPI Module
+ *
+ * Copyright (c) 2005 Jelmer Vernooij
+ *
+ * Related standards:
+ * - draft-ietf-sasl-gssapi-03
+ * - RFC2222
+ *
+ * Some parts inspired by an older patch from Colin Walters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "common.h"
+#include "mech.h"
+#include "passdb.h"
+#include "str.h"
+#include "buffer.h"
+#include "hex-binary.h"
+#include "safe-memset.h"
+#include "hostpid.h"
+
+#ifdef MECH_GSSAPI
+
+#include
+
+struct gssapi_auth_request {
+ struct auth_request auth_request;
+ gss_ctx_id_t gss_ctx;
+ gss_cred_id_t service_cred;
+
+ enum {
+ GSS_STATE_SEC_CONTEXT,
+ GSS_STATE_WRAP,
+ GSS_STATE_UNWRAP
+ } sasl_gssapi_state;
+
+ gss_name_t src_name;
+
+ pool_t pool;
+};
+
+static void auth_request_log_gss_error(struct auth_request *request, OM_uint32 status_value, int status_type, const char *description)
+{
+ OM_uint32 message_context = 0;
+ OM_uint32 major_status, minor_status;
+ gss_buffer_desc status_string;
+
+ do {
+ major_status = gss_display_status(&minor_status, status_value,
+ status_type, GSS_C_NO_OID, &message_context,
+ &status_string);
+
+ auth_request_log_error(request, "gssapi", "While %s: %s",
+ description, (char *)status_string.value);
+
+ major_status = gss_release_buffer(&minor_status, &status_string);
+ } while (message_context != 0);
+}
+
+static struct auth_request *mech_gssapi_auth_new(void)
+{
+ struct gssapi_auth_request *request;
+ pool_t pool;
+
+ pool = pool_alloconly_create("gssapi_auth_request", 512);
+ request = p_new(pool, struct gssapi_auth_request, 1);
+ request->pool = pool;
+
+ request->gss_ctx = GSS_C_NO_CONTEXT;
+
+ request->auth_request.pool = pool;
+ return &request->auth_request;
+}
+
+static OM_uint32 obtain_service_credentials(struct auth_request *request, gss_cred_id_t *ret)
+{
+ OM_uint32 major_status, minor_status;
+ string_t *principal_name;
+ gss_buffer_desc inbuf;
+ gss_name_t gss_principal;
+
+ principal_name = t_str_new(40);
+ str_append(principal_name, t_str_lcase(request->service));
+ str_append(principal_name, "@");
+ str_append(principal_name, my_hostname);
+
+ auth_request_log_info(request, "gssapi",
+ "Obtaining credentials for %s", str_c(principal_name));
+
+ inbuf.length = str_len(principal_name);
+ inbuf.value = (void*) str_c(principal_name);
+
+ major_status = gss_import_name(&minor_status, &inbuf,
+ GSS_C_NT_HOSTBASED_SERVICE, &gss_principal);
+
+ str_free(principal_name);
+
+ if (GSS_ERROR(major_status)) {
+ auth_request_log_gss_error(request, major_status, GSS_C_GSS_CODE,
+ "importing principal name");
+ return major_status;
+ }
+
+ major_status = gss_acquire_cred(&minor_status, gss_principal, 0,
+ GSS_C_NULL_OID_SET, GSS_C_ACCEPT, ret, NULL, NULL);
+
+ if (GSS_ERROR(major_status)) {
+ auth_request_log_gss_error(request, major_status, GSS_C_GSS_CODE,
+ "acquiring service credentials");
+ auth_request_log_gss_error(request, minor_status, GSS_C_MECH_CODE,
+ "acquiring service credentials");
+ return major_status;
+ }
+
+ gss_release_name(&minor_status, gss_principal);
+
+ return major_status;
+}
+
+static void gssapi_sec_context(struct gssapi_auth_request *request,
+ gss_buffer_desc inbuf)
+{
+ OM_uint32 major_status, minor_status;
+ gss_buffer_desc outbuf;
+
+ major_status = gss_accept_sec_context (
+ &minor_status,
+ &request->gss_ctx,
+ request->service_cred,
+ &inbuf,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &request->src_name,
+ NULL, /* mech_type */
+ &outbuf,
+ NULL, /* ret_flags */
+ NULL, /* time_rec */
+ NULL /* delegated_cred_handle */
+ );
+
+ if (GSS_ERROR(major_status)) {
+ auth_request_log_gss_error(&request->auth_request, major_status, GSS_C_GSS_CODE,
+ "processing incoming data");
+ auth_request_log_gss_error(&request->auth_request, minor_status, GSS_C_MECH_CODE,
+ "processing incoming data");
+
+ auth_request_fail(&request->auth_request);
+ return;
+ }
+
+ if (major_status == GSS_S_COMPLETE) {
+ request->sasl_gssapi_state = GSS_STATE_WRAP;
+ auth_request_log_info(&request->auth_request, "gssapi",
+ "security context state completed.");
+ } else {
+ auth_request_log_info(&request->auth_request, "gssapi",
+ "Processed incoming packet correctly, waiting for another.");
+ }
+
+ request->auth_request.callback(&request->auth_request,
+ AUTH_CLIENT_RESULT_CONTINUE,
+ outbuf.value, outbuf.length);
+
+ major_status = gss_release_buffer(&minor_status, &outbuf);
+}
+
+static void gssapi_wrap(struct gssapi_auth_request *request,
+ gss_buffer_desc inbuf)
+{
+ OM_uint32 major_status, minor_status;
+ gss_buffer_desc outbuf;
+ char ret[4];
+
+ /* The clients return data should be empty here */
+
+ ret[0] = 0x01; /* Only authentication, no integrity or confidentiality protection (yet?) */
+ ret[1] = 0xFF;
+ ret[2] = 0xFF;
+ ret[3] = 0xFF;
+
+ inbuf.length = 4;
+ inbuf.value = ret;
+
+ major_status = gss_wrap(&minor_status, request->gss_ctx, 0,
+ GSS_C_QOP_DEFAULT,
+ &inbuf, NULL, &outbuf);
+
+ if (GSS_ERROR(major_status)) {
+ auth_request_log_gss_error(&request->auth_request, major_status, GSS_C_GSS_CODE,
+ "sending security layer negotiation");
+ auth_request_log_gss_error(&request->auth_request, minor_status, GSS_C_MECH_CODE,
+ "sending security layer negotiation");
+ auth_request_fail(&request->auth_request);
+ return;
+ }
+
+ auth_request_log_info(&request->auth_request, "gssapi",
+ "Negotiated security layer");
+
+ request->auth_request.callback(&request->auth_request,
+ AUTH_CLIENT_RESULT_CONTINUE,
+ outbuf.value, outbuf.length);
+
+ major_status = gss_release_buffer(&minor_status, &outbuf);
+
+ request->sasl_gssapi_state = GSS_STATE_UNWRAP;
+}
+
+static void gssapi_unwrap(struct gssapi_auth_request *request,
+ gss_buffer_desc inbuf)
+{
+ OM_uint32 major_status, minor_status;
+ gss_buffer_desc outbuf;
+
+ major_status = gss_unwrap(&minor_status, request->gss_ctx,
+ &inbuf, &outbuf, NULL, NULL);
+
+ if (GSS_ERROR(major_status)) {
+ auth_request_log_gss_error(&request->auth_request, major_status, GSS_C_GSS_CODE,
+ "final negotiation: gss_unwrap");
+ auth_request_fail(&request->auth_request);
+ return;
+ }
+
+ if (outbuf.length <= 4) {
+ auth_request_log_error(&request->auth_request, "gssapi",
+ "Invalid response length");
+ auth_request_fail(&request->auth_request);
+ return;
+ }
+
+ request->auth_request.user = p_strndup(request->auth_request.pool,
+ ((unsigned char*) outbuf.value)+4,
+ outbuf.length-4);
+
+ auth_request_success(&request->auth_request, NULL, 0);
+}
+
+static void
+mech_gssapi_auth_continue(struct auth_request *request,
+ const unsigned char *data, size_t data_size)
+{
+ struct gssapi_auth_request *gssapi_request =
+ (struct gssapi_auth_request *)request;
+ gss_buffer_desc inbuf;
+
+ inbuf.value = (char*) data;
+ inbuf.length = data_size;
+
+ switch (gssapi_request->sasl_gssapi_state) {
+ case GSS_STATE_SEC_CONTEXT: gssapi_sec_context(gssapi_request, inbuf); break;
+ case GSS_STATE_WRAP: gssapi_wrap(gssapi_request, inbuf); break;
+ case GSS_STATE_UNWRAP: gssapi_unwrap(gssapi_request, inbuf); break;
+ }
+}
+
+static void
+mech_gssapi_auth_initial(struct auth_request *request,
+ const unsigned char *data, size_t data_size)
+{
+ OM_uint32 major_status;
+ struct gssapi_auth_request *gssapi_request =
+ (struct gssapi_auth_request *)request;
+
+ major_status = obtain_service_credentials(request, &gssapi_request->service_cred);
+
+ if (GSS_ERROR(major_status)) {
+ auth_request_internal_failure(request);
+ return;
+ }
+ gssapi_request->src_name = GSS_C_NO_NAME;
+
+ gssapi_request->sasl_gssapi_state = GSS_STATE_SEC_CONTEXT;
+
+ if (data_size == 0) {
+ /* The client should go first */
+ request->callback(request,
+ AUTH_CLIENT_RESULT_CONTINUE,
+ NULL, 0);
+ } else {
+ mech_gssapi_auth_continue(request, data, data_size);
+ }
+}
+
+
+static void
+mech_gssapi_auth_free(struct auth_request *request)
+{
+ OM_uint32 major_status, minor_status;
+ struct gssapi_auth_request *gssapi_request =
+ (struct gssapi_auth_request *)request;
+
+ major_status = gss_delete_sec_context(&minor_status,
+ &gssapi_request->gss_ctx,
+ GSS_C_NO_BUFFER);
+
+ major_status = gss_release_cred(&minor_status, &gssapi_request->service_cred);
+
+ pool_unref(request->pool);
+}
+
+const struct mech_module mech_gssapi = {
+ "GSSAPI",
+
+ MEMBER(flags) 0,
+
+ MEMBER(need_passdb) FALSE,
+ MEMBER(passdb_need_plain) FALSE,
+ MEMBER(passdb_need_credentials) FALSE,
+
+ mech_gssapi_auth_new,
+ mech_gssapi_auth_initial,
+ mech_gssapi_auth_continue,
+ mech_gssapi_auth_free
+};
+
+#endif
Index: AUTHORS
===================================================================
RCS file: /home/cvs/dovecot/AUTHORS,v
retrieving revision 1.11
diff -u -r1.11 AUTHORS
--- AUTHORS 19 Aug 2004 03:56:01 -0000 1.11
+++ AUTHORS 19 Oct 2005 08:38:49 -0000
@@ -12,6 +12,8 @@
Joshua Goodall (src/auth/password-scheme-cram-md5.c,
src/util/dovecotpw.c)
+Jelmer Vernooij (src/auth/mech-gssapi.c)
+
This product includes software developed by Computing Services
at Carnegie Mellon University (http://www.cmu.edu/computing/).
(src/lib/base64.c, src/lib/mkgmtime.c)