dovecot-2.2: gssapi: Allow logging in as users listed in "k5prin...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jun 27 12:04:01 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/183adc90781c
changeset: 14690:183adc90781c
user: Timo Sirainen <tss at iki.fi>
date: Wed Jun 27 12:03:51 2012 +0300
description:
gssapi: Allow logging in as users listed in "k5principals" extra field.
This also enables other passdb extra fields for gssapi mechanism.
Based on patch by Sam Morris.
diffstat:
src/auth/mech-gssapi.c | 87 ++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 78 insertions(+), 9 deletions(-)
diffs (139 lines):
diff -r 096e4c4d62bb -r 183adc90781c src/auth/mech-gssapi.c
--- a/src/auth/mech-gssapi.c Wed Jun 27 04:24:53 2012 +0300
+++ b/src/auth/mech-gssapi.c Wed Jun 27 12:03:51 2012 +0300
@@ -380,6 +380,29 @@
#ifdef USE_KRB5_USEROK
static bool
+k5_principal_is_authorized(struct auth_request *request, const char *name)
+{
+ const char *value, *const *authorized_names, *const *tmp;
+
+ if (request->extra_fields == NULL)
+ return FALSE;
+
+ value = auth_stream_reply_find(request->extra_fields, "k5principals");
+ if (value == NULL)
+ return FALSE;
+
+ authorized_names = t_strsplit_spaces(value, ",");
+ for (tmp = authorized_names; *tmp != NULL; tmp++) {
+ if (strcmp(*tmp, name) == 0) {
+ auth_request_log_debug(request, "gssapi",
+ "authorized by k5principals field: %s", name);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static bool
mech_gssapi_krb5_userok(struct gssapi_auth_request *request,
gss_name_t name, const char *login_user,
bool check_name_type)
@@ -389,7 +412,7 @@
krb5_error_code krb5_err;
gss_OID name_type;
const char *princ_display_name;
- bool ret = FALSE;
+ bool authorized = FALSE;
/* Parse out the principal's username */
if (!get_display_name(&request->auth_request, name, &name_type,
@@ -419,13 +442,20 @@
"krb5_parse_name() failed: %d",
(int)krb5_err);
} else {
+ /* See if the principal is in the list of authorized
+ * principals for the user */
+ authorized = k5_principal_is_authorized(&request->auth_request,
+ princ_display_name);
+
/* See if the principal is authorized to act as the
- specified user */
- ret = krb5_kuserok(ctx, princ, login_user);
+ specified (UNIX) user */
+ if (!authorized)
+ authorized = krb5_kuserok(ctx, princ, login_user);
+
krb5_free_principal(ctx, princ);
}
krb5_free_context(ctx);
- return ret;
+ return authorized;
}
#endif
@@ -483,11 +513,45 @@
#else
auth_request_log_info(auth_request, "gssapi",
"Cross-realm authentication not supported "
- "(authz_name=%s)", login_user);
+ "(authn_name=%s, authz_name=%s)", request->auth_request.original_username, login_user);
return -1;
#endif
}
+static void
+gssapi_credentials_callback(enum passdb_result result,
+ const unsigned char *credentials ATTR_UNUSED,
+ size_t size ATTR_UNUSED,
+ struct auth_request *request)
+{
+ struct gssapi_auth_request *gssapi_request =
+ (struct gssapi_auth_request *)request;
+
+ /* We don't care much whether the lookup succeeded or not because GSSAPI
+ * does not strictly require a passdb. But if a passdb is configured,
+ * now the k5principals field will have been filled in. */
+ switch (result) {
+ case PASSDB_RESULT_INTERNAL_FAILURE:
+ auth_request_internal_failure(request);
+ return;
+ case PASSDB_RESULT_USER_DISABLED:
+ case PASSDB_RESULT_PASS_EXPIRED:
+ /* user is explicitly disabled, don't allow it to log in */
+ auth_request_fail(request);
+ return;
+ case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
+ case PASSDB_RESULT_USER_UNKNOWN:
+ case PASSDB_RESULT_PASSWORD_MISMATCH:
+ case PASSDB_RESULT_OK:
+ break;
+ }
+
+ if (mech_gssapi_userok(gssapi_request, request->user) == 0)
+ auth_request_success(request, NULL, 0);
+ else
+ auth_request_fail(request);
+}
+
static int
mech_gssapi_unwrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf)
{
@@ -531,16 +595,21 @@
return -1;
}
- if (mech_gssapi_userok(request, login_user) < 0)
- return -1;
-
+ /* Set username early, so that the credential lookup is for the
+ * authorizing user. This means the username in subsequent log
+ * messagess will be the authorization name, not the authentication
+ * name, which may mean that future log messages should be adjusted
+ * to log the right thing. */
if (!auth_request_set_username(auth_request, login_user, &error)) {
auth_request_log_info(auth_request, "gssapi",
"authz_name: %s", error);
return -1;
}
- auth_request_success(auth_request, NULL, 0);
+ /* Continue in callback once auth_request is populated with passdb
+ information. */
+ auth_request_lookup_credentials(&request->auth_request, "",
+ gssapi_credentials_callback);
return 0;
}
More information about the dovecot-cvs
mailing list