[dovecot-cvs]
dovecot/src/auth Makefile.am, 1.48, 1.49 auth.c, 1.19,
1.20 mech-anonymous.c, 1.13, 1.14 mech-apop.c, 1.16,
1.17 mech-cram-md5.c, 1.20, 1.21 mech-digest-md5.c, 1.34,
1.35 mech-gssapi.c, NONE, 1.1 mech-login.c, 1.12,
1.13 mech-ntlm.c, 1.19, 1.20 mech-plain.c, 1.31,
1.32 mech-rpa.c, 1.19, 1.20 mech.c, 1.54, 1.55 mech.h, 1.35, 1.36
cras at dovecot.org
cras at dovecot.org
Thu Oct 27 17:57:57 EEST 2005
Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv20814/src/auth
Modified Files:
Makefile.am auth.c mech-anonymous.c mech-apop.c
mech-cram-md5.c mech-digest-md5.c mech-login.c mech-ntlm.c
mech-plain.c mech-rpa.c mech.c mech.h
Added Files:
mech-gssapi.c
Log Message:
Added GSSAPI support. Patch by Jelmer Vernooij and some fixes by
pod at herald.ox.ac.uk
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- Makefile.am 19 Oct 2005 13:38:36 -0000 1.48
+++ Makefile.am 27 Oct 2005 14:57:50 -0000 1.49
@@ -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: auth.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- auth.c 16 Oct 2005 14:06:59 -0000 1.19
+++ auth.c 27 Oct 2005 14:57:50 -0000 1.20
@@ -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,8 @@
struct mech_module_list *list;
for (list = auth->mech_modules; list != NULL; list = list->next) {
+ if (list->module.need_passdb && auth->passdbs == NULL)
+ break;
if (list->module.passdb_need_plain &&
!auth_passdb_list_have_plain(auth))
break;
Index: mech-anonymous.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-anonymous.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- mech-anonymous.c 23 Apr 2005 09:11:49 -0000 1.13
+++ mech-anonymous.c 27 Oct 2005 14:57:50 -0000 1.14
@@ -57,6 +57,7 @@
MEMBER(flags) MECH_SEC_ANONYMOUS,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) FALSE,
MEMBER(passdb_need_credentials) FALSE,
Index: mech-apop.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-apop.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mech-apop.c 23 Apr 2005 09:11:49 -0000 1.16
+++ mech-apop.c 27 Oct 2005 14:57:50 -0000 1.17
@@ -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: mech-cram-md5.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-cram-md5.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- mech-cram-md5.c 8 Jan 2005 21:37:32 -0000 1.20
+++ mech-cram-md5.c 27 Oct 2005 14:57:50 -0000 1.21
@@ -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: mech-digest-md5.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-digest-md5.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- mech-digest-md5.c 8 Jan 2005 21:37:32 -0000 1.34
+++ mech-digest-md5.c 27 Oct 2005 14:57:51 -0000 1.35
@@ -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,
--- NEW FILE: mech-gssapi.c ---
/*
* GSSAPI Module
*
* Copyright (c) 2005 Jelmer Vernooij <jelmer at samba.org>
*
* 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 "str-sanitize.h"
#include "buffer.h"
#include "hex-binary.h"
#include "safe-memset.h"
#include "hostpid.h"
#ifdef HAVE_GSSAPI
#include <gssapi/gssapi.h>
/* Non-zero flags defined in RFC 2222 */
enum sasl_gssapi_qop {
SASL_GSSAPI_QOP_UNSPECIFIED = 0x00,
SASL_GSSAPI_QOP_AUTH_ONLY = 0x01,
SASL_GSSAPI_QOP_AUTH_INT = 0x02,
SASL_GSSAPI_QOP_AUTH_CONF = 0x04
};
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 authn_name;
gss_name_t authz_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,
str_sanitize(status_string.value, (size_t)-1));
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(128);
str_append(principal_name, t_str_lcase(request->service));
str_append_c(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 = str_c_modifyable(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 gss_name_t
import_name(struct auth_request *request, void *str, size_t len)
{
OM_uint32 major_status, minor_status;
gss_buffer_desc name_buf;
gss_name_t name;
name_buf.value = str;
name_buf.length = len;
major_status = gss_import_name(&minor_status,
&name_buf,
GSS_C_NO_OID,
&name);
if (GSS_ERROR(major_status)) {
auth_request_log_gss_error(request, major_status,
GSS_C_GSS_CODE, "gss_import_name");
return GSS_C_NO_NAME;
}
return name;
}
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->authn_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;
unsigned char ret[4];
/* The clients return data should be empty here */
/* Only authentication, no integrity or confidentiality
protection (yet?) */
ret[0] = (SASL_GSSAPI_QOP_UNSPECIFIED |
SASL_GSSAPI_QOP_AUTH_ONLY);
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;
int equal_authn_authz = 0;
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->authz_name = import_name(&request->auth_request,
(unsigned char *)outbuf.value + 4,
outbuf.length - 4);
if ((request->authn_name == GSS_C_NO_NAME) ||
(request->authz_name == GSS_C_NO_NAME)) {
/* XXX (pod): is this check necessary? */
auth_request_log_error(&request->auth_request, "gssapi",
"one of authn_name or authz_name not determined");
auth_request_fail(&request->auth_request);
return;
}
major_status = gss_compare_name(&minor_status,
request->authn_name,
request->authz_name,
&equal_authn_authz);
if (equal_authn_authz == 0) {
auth_request_log_error(&request->auth_request, "gssapi",
"authn_name and authz_name differ: not supported");
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 = (void *)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->authn_name = GSS_C_NO_NAME;
gssapi_request->authz_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);
major_status = gss_release_name(&minor_status,
&gssapi_request->authn_name);
major_status = gss_release_name(&minor_status,
&gssapi_request->authz_name);
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: mech-login.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-login.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mech-login.c 23 Apr 2005 09:11:49 -0000 1.12
+++ mech-login.c 27 Oct 2005 14:57:51 -0000 1.13
@@ -87,6 +87,7 @@
MEMBER(flags) MECH_SEC_PLAINTEXT,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) TRUE,
MEMBER(passdb_need_credentials) FALSE,
Index: mech-ntlm.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-ntlm.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- mech-ntlm.c 23 Apr 2005 09:11:49 -0000 1.19
+++ mech-ntlm.c 27 Oct 2005 14:57:51 -0000 1.20
@@ -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: mech-plain.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-plain.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- mech-plain.c 23 Apr 2005 09:11:49 -0000 1.31
+++ mech-plain.c 27 Oct 2005 14:57:51 -0000 1.32
@@ -103,6 +103,7 @@
MEMBER(flags) MECH_SEC_PLAINTEXT,
+ MEMBER(need_passdb) TRUE,
MEMBER(passdb_need_plain) TRUE,
MEMBER(passdb_need_credentials) FALSE,
Index: mech-rpa.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-rpa.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- mech-rpa.c 23 Apr 2005 09:11:49 -0000 1.19
+++ mech-rpa.c 27 Oct 2005 14:57:51 -0000 1.20
@@ -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: mech.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- mech.c 7 Jan 2005 19:55:50 -0000 1.54
+++ mech.c 27 Oct 2005 14:57:51 -0000 1.55
@@ -54,6 +54,9 @@
extern struct mech_module mech_ntlm;
extern struct mech_module mech_rpa;
extern struct mech_module mech_anonymous;
+#ifdef HAVE_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 HAVE_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 HAVE_GSSAPI
+ mech_unregister_module(&mech_gssapi);
+#endif
}
Index: mech.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- mech.h 9 Jan 2005 16:54:48 -0000 1.35
+++ mech.h 27 Oct 2005 14:57:51 -0000 1.36
@@ -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;
More information about the dovecot-cvs
mailing list