0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen/*
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen * GSSAPI Module
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen *
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen * Copyright (c) 2005 Jelmer Vernooij <jelmer@samba.org>
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen *
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen * Related standards:
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen * - draft-ietf-sasl-gssapi-03
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen * - RFC2222
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen *
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen * Some parts inspired by an older patch from Colin Walters
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen *
e074ffeaee1ce283bd42f167c6810e3d013f8218Timo Sirainen * This software is released under the MIT license.
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "env-util.h"
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen#include "str.h"
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen#include "str-sanitize.h"
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen#include "hex-binary.h"
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen#include "safe-memset.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "mech.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "passdb.h"
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
24c4835905c0a7ba5a7caa1666af5daef6233303Timo Sirainen
44fc0a34c39f1ddb3a776918630010867a5dd04eTimo Sirainen#if defined(BUILTIN_GSSAPI) || defined(PLUGIN_BUILD)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen#ifndef HAVE___GSS_USEROK
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen# define USE_KRB5_USEROK
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen# include <krb5.h>
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen#endif
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen
405aa3bff8ca00739ebeaab59afb593bcfc8edccTimo Sirainen#ifdef HAVE_GSSAPI_GSSAPI_H
405aa3bff8ca00739ebeaab59afb593bcfc8edccTimo Sirainen# include <gssapi/gssapi.h>
405aa3bff8ca00739ebeaab59afb593bcfc8edccTimo Sirainen#elif defined (HAVE_GSSAPI_H)
405aa3bff8ca00739ebeaab59afb593bcfc8edccTimo Sirainen# include <gssapi.h>
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen#endif
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen# include <gssapi/gssapi_krb5.h>
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen#elif defined (HAVE_GSSAPI_KRB5_H)
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen# include <gssapi_krb5.h>
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen#else
01ff322068d8cb54d37b478efc1348087b1f9f78Timo Sirainen# undef USE_KRB5_USEROK
405aa3bff8ca00739ebeaab59afb593bcfc8edccTimo Sirainen#endif
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen# include <gssapi/gssapi_ext.h>
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen#endif
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch#define krb5_boolean2bool(X) ((X) != 0)
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen/* Non-zero flags defined in RFC 2222 */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenenum sasl_gssapi_qop {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen SASL_GSSAPI_QOP_UNSPECIFIED = 0x00,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen SASL_GSSAPI_QOP_AUTH_ONLY = 0x01,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen SASL_GSSAPI_QOP_AUTH_INT = 0x02,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen SASL_GSSAPI_QOP_AUTH_CONF = 0x04
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen};
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenstruct gssapi_auth_request {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen struct auth_request auth_request;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_ctx_id_t gss_ctx;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_cred_id_t service_cred;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen enum {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_STATE_SEC_CONTEXT,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_STATE_WRAP,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_STATE_UNWRAP
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen } sasl_gssapi_state;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_name_t authn_name;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_name_t authz_name;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen pool_t pool;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen};
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainenstatic bool gssapi_initialized = FALSE;
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen
1fb790b0dadd9d7c226e5ff116355f447d68f31cTimo Sirainenstatic gss_OID_desc mech_gssapi_krb5_oid =
1fb790b0dadd9d7c226e5ff116355f447d68f31cTimo Sirainen { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
1fb790b0dadd9d7c226e5ff116355f447d68f31cTimo Sirainen
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainenstatic int
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainenmech_gssapi_wrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf);
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainenstatic void mech_gssapi_log_error(struct auth_request *request,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen OM_uint32 status_value, int status_type,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen const char *description)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen OM_uint32 message_context = 0;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen OM_uint32 minor_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_buffer_desc status_string;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen do {
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_display_status(&minor_status, status_value,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen status_type, GSS_C_NO_OID,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen &message_context, &status_string);
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(request, AUTH_SUBSYS_MECH,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen "While %s: %s", description,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen str_sanitize(status_string.value, (size_t)-1));
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_release_buffer(&minor_status, &status_string);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen } while (message_context != 0);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
1500468f62b0963974f1ba42a6ecf9c9be4381f4Timo Sirainenstatic void mech_gssapi_initialize(const struct auth_settings *set)
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen{
1500468f62b0963974f1ba42a6ecf9c9be4381f4Timo Sirainen const char *path = set->krb5_keytab;
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*path != '\0') {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* environment may be used by Kerberos 5 library directly */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen env_put(t_strconcat("KRB5_KTNAME=", path, NULL));
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen#ifdef HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen gsskrb5_register_acceptor_identity(path);
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen#elif defined (HAVE_KRB5_GSS_REGISTER_ACCEPTOR_IDENTITY)
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen krb5_gss_register_acceptor_identity(path);
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen#endif
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen }
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen}
448723dc1c12b126dd2d348d4ce385203abbaa7dTimo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenstatic struct auth_request *mech_gssapi_auth_new(void)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen struct gssapi_auth_request *request;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen pool_t pool;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
1b81b28b2e7856748cffd7d01052a944b6c80b23Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"gssapi_auth_request", 2048);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen request = p_new(pool, struct gssapi_auth_request, 1);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen request->pool = pool;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen request->gss_ctx = GSS_C_NO_CONTEXT;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen request->auth_request.pool = pool;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return &request->auth_request;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainenstatic OM_uint32
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainenobtain_service_credentials(struct auth_request *request, gss_cred_id_t *ret_r)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen OM_uint32 major_status, minor_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen string_t *principal_name;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_buffer_desc inbuf;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_name_t gss_principal;
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen const char *service_name;
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (!gssapi_initialized) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen gssapi_initialized = TRUE;
1500468f62b0963974f1ba42a6ecf9c9be4381f4Timo Sirainen mech_gssapi_initialize(request->set);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if (strcmp(request->set->gssapi_hostname, "$ALL") == 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(request, AUTH_SUBSYS_MECH,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "Using all keytab entries");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen *ret_r = GSS_C_NO_CREDENTIAL;
bde5b40c4fcc20e812a7caff9c0ed55e7090ced9Timo Sirainen return GSS_S_COMPLETE;
bde5b40c4fcc20e812a7caff9c0ed55e7090ced9Timo Sirainen }
bde5b40c4fcc20e812a7caff9c0ed55e7090ced9Timo Sirainen
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen if (strcasecmp(request->service, "POP3") == 0) {
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen /* The standard POP3 service name with GSSAPI is called
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen just "pop". */
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen service_name = "pop";
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen } else {
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen service_name = t_str_lcase(request->service);
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen principal_name = t_str_new(128);
893f7d52acc42058045f188b625449981bd7f9bcTimo Sirainen str_append(principal_name, service_name);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen str_append_c(principal_name, '@');
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen str_append(principal_name, request->set->gssapi_hostname);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(request, AUTH_SUBSYS_MECH,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen "Obtaining credentials for %s", str_c(principal_name));
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen inbuf.length = str_len(principal_name);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen inbuf.value = str_c_modifiable(principal_name);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen major_status = gss_import_name(&minor_status, &inbuf,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_C_NT_HOSTBASED_SERVICE,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen &gss_principal);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen str_free(&principal_name);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(request, major_status, GSS_C_GSS_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "importing principal name");
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return major_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen major_status = gss_acquire_cred(&minor_status, gss_principal, 0,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen ret_r, NULL, NULL);
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(request, major_status, GSS_C_GSS_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "acquiring service credentials");
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(request, minor_status, GSS_C_MECH_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "acquiring service credentials");
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return major_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
da3f943e93b0ea5a8256a2e850f4738ad161f71dTimo Sirainen gss_release_name(&minor_status, &gss_principal);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return major_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenstatic gss_name_t
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenimport_name(struct auth_request *request, void *str, size_t len)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen OM_uint32 major_status, minor_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_buffer_desc name_buf;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_name_t name;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen name_buf.value = str;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen name_buf.length = len;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen major_status = gss_import_name(&minor_status, &name_buf,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen GSS_C_NO_OID, &name);
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(request, major_status, GSS_C_GSS_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "gss_import_name");
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return GSS_C_NO_NAME;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return name;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainenstatic gss_name_t
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainenduplicate_name(struct auth_request *request, gss_name_t old)
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen{
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen OM_uint32 major_status, minor_status;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen gss_name_t new;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen major_status = gss_duplicate_name(&minor_status, old, &new);
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen mech_gssapi_log_error(request, major_status, GSS_C_GSS_CODE,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen "gss_duplicate_name");
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen return GSS_C_NO_NAME;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen }
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen return new;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen}
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainenstatic bool data_has_nuls(const void *data, size_t len)
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen{
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen const unsigned char *c = data;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t i;
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen
39f34a5a2c99a61aacb7e755e40d1cd221f68e86Timo Sirainen /* apparently all names end with NUL? */
39f34a5a2c99a61aacb7e755e40d1cd221f68e86Timo Sirainen if (len > 0 && c[len-1] == '\0')
39f34a5a2c99a61aacb7e755e40d1cd221f68e86Timo Sirainen len--;
39f34a5a2c99a61aacb7e755e40d1cd221f68e86Timo Sirainen
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen for (i = 0; i < len; i++) {
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen if (c[i] == '\0')
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen return TRUE;
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen }
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen return FALSE;
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen}
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainenstatic int get_display_name(struct auth_request *auth_request, gss_name_t name,
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen gss_OID *name_type_r, const char **display_name_r)
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen{
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen OM_uint32 major_status, minor_status;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen gss_buffer_desc buf;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen major_status = gss_display_name(&minor_status, name,
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen &buf, name_type_r);
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen if (major_status != GSS_S_COMPLETE) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(auth_request, major_status,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen GSS_C_GSS_CODE, "gss_display_name");
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen return -1;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen }
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen if (data_has_nuls(buf.value, buf.length)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen "authn_name has NULs");
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen return -1;
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen }
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen *display_name_r = t_strndup(buf.value, buf.length);
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen (void)gss_release_buffer(&minor_status, &buf);
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen return 0;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen}
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainenstatic bool mech_gssapi_oid_cmp(const gss_OID_desc *oid1,
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen const gss_OID_desc *oid2)
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen{
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen return oid1->length == oid2->length &&
ace06232cfa0e99ecca1040e8553b3216d025768Timo Sirainen mem_equals_timing_safe(oid1->elements, oid2->elements, oid1->length);
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen}
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenstatic int
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenmech_gssapi_sec_context(struct gssapi_auth_request *request,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen gss_buffer_desc inbuf)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen struct auth_request *auth_request = &request->auth_request;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen OM_uint32 major_status, minor_status;
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen gss_buffer_desc output_token;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen gss_OID name_type;
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen gss_OID mech_type;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen const char *username, *error;
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen int ret = 0;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen major_status = gss_accept_sec_context (
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen &minor_status,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen &request->gss_ctx,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen request->service_cred,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen &inbuf,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_C_NO_CHANNEL_BINDINGS,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen &request->authn_name,
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen &mech_type,
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen &output_token,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen NULL, /* ret_flags */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen NULL, /* time_rec */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen NULL /* delegated_cred_handle */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen );
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(auth_request, major_status,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen GSS_C_GSS_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "processing incoming data");
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(auth_request, minor_status,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen GSS_C_MECH_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "processing incoming data");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen switch (major_status) {
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen case GSS_S_COMPLETE:
1fb790b0dadd9d7c226e5ff116355f447d68f31cTimo Sirainen if (!mech_gssapi_oid_cmp(mech_type, &mech_gssapi_krb5_oid)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen "GSSAPI mechanism not Kerberos5");
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen ret = -1;
5f94d41239988988d70ed6ed7578306c60e77ed6Timo Sirainen } else if (get_display_name(auth_request, request->authn_name,
5f94d41239988988d70ed6ed7578306c60e77ed6Timo Sirainen &name_type, &username) < 0)
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen ret = -1;
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen else if (!auth_request_set_username(auth_request, username,
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen &error)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen "authn_name: %s", error);
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen ret = -1;
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen } else {
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen request->sasl_gssapi_state = GSS_STATE_WRAP;
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(auth_request, AUTH_SUBSYS_MECH,
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen "security context state completed.");
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen }
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen break;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen case GSS_S_CONTINUE_NEEDED:
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(auth_request, AUTH_SUBSYS_MECH,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "Processed incoming packet correctly, "
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "waiting for another.");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen break;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen default:
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_MECH,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "Received unexpected major status %d", major_status);
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen break;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen if (ret == 0) {
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen if (output_token.length > 0) {
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen auth_request_handler_reply_continue(auth_request,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen output_token.value,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen output_token.length);
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen } else {
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen /* If there is no output token, go straight to wrap,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen which is expecting an empty input token. */
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen ret = mech_gssapi_wrap(request, output_token);
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen }
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen }
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen (void)gss_release_buffer(&minor_status, &output_token);
aef258ab477801df25b12929a7b9ab6d740d52f2Timo Sirainen return ret;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainenstatic int
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenmech_gssapi_wrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen OM_uint32 major_status, minor_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_buffer_desc outbuf;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen unsigned char ret[4];
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen /* The client's return data should be empty here */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen /* Only authentication, no integrity or confidentiality
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen protection (yet?) */
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen ret[0] = (SASL_GSSAPI_QOP_UNSPECIFIED |
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen SASL_GSSAPI_QOP_AUTH_ONLY);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen ret[1] = 0xFF;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen ret[2] = 0xFF;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen ret[3] = 0xFF;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen inbuf.length = 4;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen inbuf.value = ret;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen major_status = gss_wrap(&minor_status, request->gss_ctx, 0,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_C_QOP_DEFAULT, &inbuf, NULL, &outbuf);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(&request->auth_request, major_status,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_C_GSS_CODE, "sending security layer negotiation");
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(&request->auth_request, minor_status,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen GSS_C_MECH_CODE, "sending security layer negotiation");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(&request->auth_request, AUTH_SUBSYS_MECH,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "Negotiated security layer");
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply_continue(&request->auth_request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen outbuf.value, outbuf.length);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_release_buffer(&minor_status, &outbuf);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen request->sasl_gssapi_state = GSS_STATE_UNWRAP;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return 0;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen#ifdef USE_KRB5_USEROK
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainenstatic bool
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainenk5_principal_is_authorized(struct auth_request *request, const char *name)
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen{
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen const char *value, *const *authorized_names, *const *tmp;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
8521def0d87912647884064f4c549935cbdd0c7eTimo Sirainen value = auth_fields_find(request->extra_fields, "k5principals");
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen if (value == NULL)
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen return FALSE;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen authorized_names = t_strsplit_spaces(value, ",");
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen for (tmp = authorized_names; *tmp != NULL; tmp++) {
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen if (strcmp(*tmp, name) == 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_debug(request, AUTH_SUBSYS_MECH,
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen "authorized by k5principals field: %s", name);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen return TRUE;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen }
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen }
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen return FALSE;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen}
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
6edf77bf423fe09849a79fd4077a697b8dc14a41Timo Sirainenstatic bool
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenmech_gssapi_krb5_userok(struct gssapi_auth_request *request,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen gss_name_t name, const char *login_user,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen bool check_name_type)
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen{
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_context ctx;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_principal princ;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_error_code krb5_err;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen gss_OID name_type;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen const char *princ_display_name;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen bool authorized = FALSE;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen /* Parse out the principal's username */
b1f02eab20719cda8ec4efe229dfd3c6967970f1Timo Sirainen if (get_display_name(&request->auth_request, name, &name_type,
b1f02eab20719cda8ec4efe229dfd3c6967970f1Timo Sirainen &princ_display_name) < 0)
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen return FALSE;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen if (!mech_gssapi_oid_cmp(name_type, GSS_KRB5_NT_PRINCIPAL_NAME) &&
9c9332454f40a8c0ff53074d98ff86d607f76362Timo Sirainen check_name_type) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(&request->auth_request, AUTH_SUBSYS_MECH,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "OID not kerberos principal name");
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen return FALSE;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen }
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen /* Init a krb5 context and parse the principal username */
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_err = krb5_init_context(&ctx);
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen if (krb5_err != 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(&request->auth_request, AUTH_SUBSYS_MECH,
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen "krb5_init_context() failed: %d", (int)krb5_err);
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen return FALSE;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen }
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_err = krb5_parse_name(ctx, princ_display_name, &princ);
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen if (krb5_err != 0) {
c869c075b0b558e82a613a8320b3b3a7e120741bTimo Sirainen /* writing the error string would be better, but we probably
c869c075b0b558e82a613a8320b3b3a7e120741bTimo Sirainen rarely get here and there doesn't seem to be a standard
c869c075b0b558e82a613a8320b3b3a7e120741bTimo Sirainen way of getting it */
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(&request->auth_request, AUTH_SUBSYS_MECH,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen "krb5_parse_name() failed: %d",
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (int)krb5_err);
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen } else {
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen /* See if the principal is in the list of authorized
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen * principals for the user */
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen authorized = k5_principal_is_authorized(&request->auth_request,
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen princ_display_name);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen /* See if the principal is authorized to act as the
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen specified (UNIX) user */
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (!authorized) {
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch authorized = krb5_boolean2bool(krb5_kuserok(ctx, princ, login_user));
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch }
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_free_principal(ctx, princ);
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen }
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen krb5_free_context(ctx);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen return authorized;
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen}
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen#endif
c5b99a8a85370e7d1f7edb1fcb18a9d44616f726Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainenstatic int
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenmech_gssapi_userok(struct gssapi_auth_request *request, const char *login_user)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen struct auth_request *auth_request = &request->auth_request;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen OM_uint32 major_status, minor_status;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen int equal_authn_authz;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen#ifdef HAVE___GSS_USEROK
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen int login_ok;
6edf77bf423fe09849a79fd4077a697b8dc14a41Timo Sirainen#endif
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen /* if authn and authz names equal, don't bother checking further. */
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen major_status = gss_compare_name(&minor_status,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen request->authn_name,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen request->authz_name,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen &equal_authn_authz);
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(auth_request, major_status,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen GSS_C_GSS_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "gss_compare_name failed");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen }
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen if (equal_authn_authz != 0)
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen return 0;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen /* handle cross-realm authentication */
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen#ifdef HAVE___GSS_USEROK
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen /* Solaris */
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen major_status = __gss_userok(&minor_status, request->authn_name,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen login_user, &login_ok);
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(auth_request, major_status,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen GSS_C_GSS_CODE, "__gss_userok failed");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen }
44a9b5fc1b57e5cc0a113f8cada9d9011747cadcTimo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen if (login_ok == 0) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen "User not authorized to log in as %s", login_user);
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen return 0;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen#elif defined(USE_KRB5_USEROK)
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen if (!mech_gssapi_krb5_userok(request, request->authn_name,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen login_user, TRUE)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen "User not authorized to log in as %s", login_user);
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
6edf77bf423fe09849a79fd4077a697b8dc14a41Timo Sirainen }
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen return 0;
6edf77bf423fe09849a79fd4077a697b8dc14a41Timo Sirainen#else
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen "Cross-realm authentication not supported "
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen "(authn_name=%s, authz_name=%s)", request->auth_request.original_username, login_user);
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen return -1;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen#endif
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen}
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainenstatic void
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainengssapi_credentials_callback(enum passdb_result result,
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen const unsigned char *credentials ATTR_UNUSED,
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen size_t size ATTR_UNUSED,
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen struct auth_request *request)
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen{
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen struct gssapi_auth_request *gssapi_request =
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen (struct gssapi_auth_request *)request;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen /* We don't care much whether the lookup succeeded or not because GSSAPI
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen * does not strictly require a passdb. But if a passdb is configured,
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen * now the k5principals field will have been filled in. */
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen switch (result) {
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_INTERNAL_FAILURE:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen auth_request_internal_failure(request);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen return;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_USER_DISABLED:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_PASS_EXPIRED:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen /* user is explicitly disabled, don't allow it to log in */
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen auth_request_fail(request);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen return;
ec18e7378947c601cb75ba01261d7787ccd8e4adAki Tuomi case PASSDB_RESULT_NEXT:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_USER_UNKNOWN:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_PASSWORD_MISMATCH:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen case PASSDB_RESULT_OK:
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen break;
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen }
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen if (mech_gssapi_userok(gssapi_request, request->user) == 0)
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen auth_request_success(request, NULL, 0);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen else
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen auth_request_fail(request);
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen}
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenstatic int
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainenmech_gssapi_unwrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf)
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen{
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen struct auth_request *auth_request = &request->auth_request;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen OM_uint32 major_status, minor_status;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen gss_buffer_desc outbuf;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen const char *login_user, *error;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen unsigned char *name;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t name_len;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen major_status = gss_unwrap(&minor_status, request->gss_ctx,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen &inbuf, &outbuf, NULL, NULL);
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen mech_gssapi_log_error(auth_request, major_status,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen GSS_C_GSS_CODE,
f622620587322fda179727c06df79e162eb5ea8cTimo Sirainen "final negotiation: gss_unwrap");
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen return -1;
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen }
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen /* outbuf[0] contains bitmask for selected security layer,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen outbuf[1..3] contains maximum output_message size */
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen if (outbuf.length < 4) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_error(auth_request, AUTH_SUBSYS_MECH,
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen "Invalid response length");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen }
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen if (outbuf.length > 4) {
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen name = (unsigned char *)outbuf.value + 4;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen name_len = outbuf.length - 4;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen if (data_has_nuls(name, name_len)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen "authz_name has NULs");
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen return -1;
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen }
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen login_user = p_strndup(auth_request->pool, name, name_len);
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen request->authz_name = import_name(auth_request, name, name_len);
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen } else {
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen request->authz_name = duplicate_name(auth_request,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen request->authn_name);
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen if (get_display_name(auth_request, request->authz_name,
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen NULL, &login_user) < 0)
0da7ec741f53fa8a2244421f6c63e0617b0cbf06Timo Sirainen return -1;
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen }
31803cddc7ad83490dbb71e84ed56954af64b8ceTimo Sirainen
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen if (request->authz_name == GSS_C_NO_NAME) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen "no authz_name");
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return -1;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen /* Set username early, so that the credential lookup is for the
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen * authorizing user. This means the username in subsequent log
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi * messages will be the authorization name, not the authentication
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen * name, which may mean that future log messages should be adjusted
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen * to log the right thing. */
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen if (!auth_request_set_username(auth_request, login_user, &error)) {
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen "authz_name: %s", error);
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen return -1;
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen }
7e770ce56e9123b9cadb3bff9d645b4420865a1aTimo Sirainen
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen /* Continue in callback once auth_request is populated with passdb
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen information. */
8521def0d87912647884064f4c549935cbdd0c7eTimo Sirainen auth_request->passdb_success = TRUE; /* default to success */
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen auth_request_lookup_credentials(&request->auth_request, "",
00ef253647b45487e75b8a4a2636f38909eaee51Timo Sirainen gssapi_credentials_callback);
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen return 0;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenstatic void
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenmech_gssapi_auth_continue(struct auth_request *request,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen const unsigned char *data, size_t data_size)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen struct gssapi_auth_request *gssapi_request =
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen (struct gssapi_auth_request *)request;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gss_buffer_desc inbuf;
c14f183857b32b26aaea6a31b57eb801d1fcd386Timo Sirainen int ret = -1;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen inbuf.value = (void *)data;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen inbuf.length = data_size;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen switch (gssapi_request->sasl_gssapi_state) {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen case GSS_STATE_SEC_CONTEXT:
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen ret = mech_gssapi_sec_context(gssapi_request, inbuf);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen break;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen case GSS_STATE_WRAP:
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen ret = mech_gssapi_wrap(gssapi_request, inbuf);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen break;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen case GSS_STATE_UNWRAP:
b55f6e163c6f20505bf4a57ccd085ee0609e92afTimo Sirainen ret = mech_gssapi_unwrap(gssapi_request, inbuf);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen break;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen default:
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen i_unreached();
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen }
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen if (ret < 0)
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen auth_request_fail(request);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenstatic void
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenmech_gssapi_auth_initial(struct auth_request *request,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen const unsigned char *data, size_t data_size)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen struct gssapi_auth_request *gssapi_request =
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen (struct gssapi_auth_request *)request;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen OM_uint32 major_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen major_status =
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen obtain_service_credentials(request,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen &gssapi_request->service_cred);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
9a4542801f04f81385e554ba79b12f50eba1d460Stephan Bosch if (GSS_ERROR(major_status) != 0) {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen auth_request_internal_failure(request);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen return;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gssapi_request->authn_name = GSS_C_NO_NAME;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gssapi_request->authz_name = GSS_C_NO_NAME;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen gssapi_request->sasl_gssapi_state = GSS_STATE_SEC_CONTEXT;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen if (data_size == 0) {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen /* The client should go first */
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply_continue(request, NULL, 0);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen } else {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen mech_gssapi_auth_continue(request, data, data_size);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenstatic void
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenmech_gssapi_auth_free(struct auth_request *request)
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen{
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen struct gssapi_auth_request *gssapi_request =
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen (struct gssapi_auth_request *)request;
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen OM_uint32 minor_status;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
9e3f0cc69cbc4af74d08d1e52aa5ed8a7675b8f1Timo Sirainen if (gssapi_request->gss_ctx != GSS_C_NO_CONTEXT) {
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_delete_sec_context(&minor_status,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen &gssapi_request->gss_ctx,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen GSS_C_NO_BUFFER);
9e3f0cc69cbc4af74d08d1e52aa5ed8a7675b8f1Timo Sirainen }
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_release_cred(&minor_status, &gssapi_request->service_cred);
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen if (gssapi_request->authn_name != GSS_C_NO_NAME) {
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_release_name(&minor_status,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen &gssapi_request->authn_name);
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen }
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen if (gssapi_request->authz_name != GSS_C_NO_NAME) {
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen (void)gss_release_name(&minor_status,
fb51b3deffb527a6703b2077d5fc385fe31ea721Timo Sirainen &gssapi_request->authz_name);
00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbfTimo Sirainen }
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&request->pool);
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainenconst struct mech_module mech_gssapi = {
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen "GSSAPI",
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .flags = 0,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .passdb_need = MECH_PASSDB_NEED_NOTHING,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen mech_gssapi_auth_new,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen mech_gssapi_auth_initial,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen mech_gssapi_auth_continue,
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen mech_gssapi_auth_free
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen};
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen/* MTI Kerberos v1.5+ and Heimdal v0.7+ supports SPNEGO for Kerberos tickets
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen internally. Nothing else needs to be done here. Note however that this does
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen not support SPNEGO when the only available credential is NTLM.. */
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainenconst struct mech_module mech_gssapi_spnego = {
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen "GSS-SPNEGO",
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .flags = 0,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .passdb_need = MECH_PASSDB_NEED_NOTHING,
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen mech_gssapi_auth_new,
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen mech_gssapi_auth_initial,
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen mech_gssapi_auth_continue,
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen mech_gssapi_auth_free
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen};
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen#ifndef BUILTIN_GSSAPI
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainenvoid mech_gssapi_init(void);
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainenvoid mech_gssapi_deinit(void);
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainenvoid mech_gssapi_init(void)
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen{
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen mech_register_module(&mech_gssapi);
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen#ifdef HAVE_GSSAPI_SPNEGO
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen /* load if we already didn't load it using winbind */
3bc82073c6bc12195e4bb63c11ce546fdc0e8db3Timo Sirainen if (mech_module_find(mech_gssapi_spnego.mech_name) == NULL)
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen mech_register_module(&mech_gssapi_spnego);
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen#endif
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen}
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainenvoid mech_gssapi_deinit(void)
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen{
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen#ifdef HAVE_GSSAPI_SPNEGO
3bc82073c6bc12195e4bb63c11ce546fdc0e8db3Timo Sirainen const struct mech_module *mech;
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen
3bc82073c6bc12195e4bb63c11ce546fdc0e8db3Timo Sirainen mech = mech_module_find(mech_gssapi_spnego.mech_name);
3bc82073c6bc12195e4bb63c11ce546fdc0e8db3Timo Sirainen if (mech != NULL && mech->auth_new == mech_gssapi_auth_new)
6e873f135368bcfdd1de4458dded791d0c4d00cdTimo Sirainen mech_unregister_module(&mech_gssapi_spnego);
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen#endif
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen mech_unregister_module(&mech_gssapi);
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen}
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen#endif
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen#endif