From: Timo Sirainen Date: Sun, 4 May 2008 01:27:41 +0000 (+0300) Subject: Support cross-realm krb5 authentication. Based on patch by Zachary Kotlarek. X-Git-Tag: 1.1.rc5~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c5b99a8a85370e7d1f7edb1fcb18a9d44616f726;p=thirdparty%2Fdovecot%2Fcore.git Support cross-realm krb5 authentication. Based on patch by Zachary Kotlarek. --HG-- branch : HEAD --- diff --git a/src/auth/mech-gssapi.c b/src/auth/mech-gssapi.c index c4307a287f..4c5765f95a 100644 --- a/src/auth/mech-gssapi.c +++ b/src/auth/mech-gssapi.c @@ -23,10 +23,21 @@ #ifdef HAVE_GSSAPI +#ifndef HAVE___GSS_USEROK +# define USE_KRB5_USEROK +# include +#endif + #ifdef HAVE_GSSAPI_GSSAPI_H # include +# ifdef USE_KRB5_USEROK +# include +# endif #elif defined (HAVE_GSSAPI_H) # include +# ifdef USE_KRB5_USEROK +# include +# endif #endif #ifdef HAVE_GSSAPI_GSSAPI_EXT_H @@ -156,6 +167,7 @@ static OM_uint32 obtain_service_credentials(struct auth_request *request, return major_status; } +#ifndef HAVE___GSS_USEROK static gss_name_t import_name(struct auth_request *request, void *str, size_t len) { @@ -177,6 +189,7 @@ import_name(struct auth_request *request, void *str, size_t len) return name; } +#endif static void gssapi_sec_context(struct gssapi_auth_request *request, gss_buffer_desc inbuf) @@ -271,6 +284,58 @@ static void gssapi_wrap(struct gssapi_auth_request *request, request->sasl_gssapi_state = GSS_STATE_UNWRAP; } +#ifdef USE_KRB5_USEROK +static bool gssapi_krb5_userok(struct gssapi_auth_request *request) +{ + krb5_context ctx; + krb5_principal princ; + krb5_error_code krb5_err; + OM_uint32 major_status, minor_status; + gss_buffer_desc princ_name; + gss_OID name_type; + const char *princ_display_name; + bool ret = FALSE; + + /* Parse out the principal's username */ + major_status = gss_display_name(&minor_status, request->authn_name, + &princ_name, &name_type); + if (major_status != GSS_S_COMPLETE) { + auth_request_log_gss_error(&request->auth_request, major_status, + GSS_C_GSS_CODE, + "gssapi_krb5_userok"); + return FALSE; + } + if (name_type != GSS_KRB5_NT_PRINCIPAL_NAME) { + auth_request_log_error(&request->auth_request, "gssapi", + "OID not kerberos principal name"); + return FALSE; + } + princ_display_name = t_strndup(princ_name.value, princ_name.length); + gss_release_buffer(&minor_status, &princ_name); + + /* Init a krb5 context and parse the principal username */ + krb5_err = krb5_init_context(&ctx); + if (krb5_err != 0) { + auth_request_log_error(&request->auth_request, "gssapi", + "krb5_init_context() failed: %d", (int)krb5_err); + return FALSE; + } + krb5_err = krb5_parse_name(ctx, princ_display_name, &princ); + if (krb5_err != 0) { + auth_request_log_error(&request->auth_request, "gssapi", + "krb5_parse_name() failed: %s", + krb5_get_error_message(ctx, krb5_err)); + } else { + /* See if the principal is authorized to act as the + specified user */ + ret = krb5_kuserok(ctx, princ, request->auth_request.user); + krb5_free_principal(ctx, princ); + } + krb5_free_context(ctx); + return ret; +} +#endif + static void gssapi_unwrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf) { @@ -344,6 +409,10 @@ static void gssapi_unwrap(struct gssapi_auth_request *request, request->authn_name, request->authz_name, &equal_authn_authz); +#ifdef USE_KRB5_USEROK + if (equal_authn_authz == 0) + equal_authn_authz = gssapi_krb5_userok(request); +#endif if (equal_authn_authz == 0) { auth_request_log_error(&request->auth_request, "gssapi", "authn_name and authz_name differ: not supported");