2016-09-17 08:18:59 +00:00
|
|
|
#include "first.h"
|
|
|
|
|
|
|
|
/* mod_authn_gssapi
|
|
|
|
*
|
|
|
|
* - provides http_auth_backend_t "gssapi" for HTTP auth Basic realm="Kerberos"
|
|
|
|
* - provides http_auth_scheme_t "Negotiate"
|
|
|
|
* - (does not provide http_auth_backend_t for HTTP auth Digest)
|
|
|
|
*
|
|
|
|
* Note: Credentials cache (KRB5CCNAME) is exported into CGI and SSI environment
|
|
|
|
* as well as passed to FastCGI and SCGI (useful if on same machine
|
|
|
|
* and running under same user account with access to KRB5CCNAME file).
|
|
|
|
* Credentials are clean up at the end of each request.
|
|
|
|
*
|
|
|
|
* LIMITATIONS:
|
|
|
|
* - no rate limiting of auth requests, so remote attacker can send many auth
|
|
|
|
* requests very quickly if attempting brute force password cracking attack
|
|
|
|
*
|
|
|
|
* FUTURE POTENTIAL PERFORMANCE ENHANCEMENTS:
|
|
|
|
* - Kerberos auth is synchronous and blocks waiting for response
|
|
|
|
* TODO: attempt async?
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "plugin.h"
|
|
|
|
|
|
|
|
#include <krb5.h>
|
|
|
|
#include <gssapi.h>
|
|
|
|
#include <gssapi/gssapi_krb5.h>
|
|
|
|
|
|
|
|
#include "http_auth.h"
|
2018-09-09 05:50:33 +00:00
|
|
|
#include "http_header.h"
|
2016-09-17 08:18:59 +00:00
|
|
|
#include "base.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "base64.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2017-06-22 01:41:59 +00:00
|
|
|
#include <unistd.h>
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
typedef struct {
|
2019-11-07 00:37:11 +00:00
|
|
|
const buffer *auth_gssapi_keytab;
|
|
|
|
const buffer *auth_gssapi_principal;
|
|
|
|
unsigned int auth_gssapi_store_creds;
|
2016-09-17 08:18:59 +00:00
|
|
|
} plugin_config;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
PLUGIN_DATA;
|
2019-11-07 00:37:11 +00:00
|
|
|
plugin_config defaults;
|
2016-09-17 08:18:59 +00:00
|
|
|
plugin_config conf;
|
|
|
|
} plugin_data;
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_check(request_st *r, void *p_d, const struct http_auth_require_t *require, const struct http_auth_backend_t *backend);
|
|
|
|
static handler_t mod_authn_gssapi_basic(request_st *r, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
INIT_FUNC(mod_authn_gssapi_init) {
|
|
|
|
static http_auth_scheme_t http_auth_scheme_gssapi =
|
|
|
|
{ "gssapi", mod_authn_gssapi_check, NULL };
|
|
|
|
static http_auth_backend_t http_auth_backend_gssapi =
|
2016-09-23 08:23:25 +00:00
|
|
|
{ "gssapi", mod_authn_gssapi_basic, NULL, NULL };
|
2016-09-17 08:18:59 +00:00
|
|
|
plugin_data *p = calloc(1, sizeof(*p));
|
|
|
|
|
|
|
|
/* register http_auth_scheme_gssapi and http_auth_backend_gssapi */
|
|
|
|
http_auth_scheme_gssapi.p_d = p;
|
|
|
|
http_auth_scheme_set(&http_auth_scheme_gssapi);
|
|
|
|
http_auth_backend_gssapi.p_d = p;
|
|
|
|
http_auth_backend_set(&http_auth_backend_gssapi);
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2019-11-07 00:37:11 +00:00
|
|
|
static void mod_authn_gssapi_merge_config_cpv(plugin_config * const pconf, const config_plugin_value_t * const cpv) {
|
|
|
|
switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
|
|
|
|
case 0: /* auth.backend.gssapi.keytab */
|
|
|
|
pconf->auth_gssapi_keytab = cpv->v.b;
|
|
|
|
break;
|
|
|
|
case 1: /* auth.backend.gssapi.principal */
|
|
|
|
pconf->auth_gssapi_principal = cpv->v.b;
|
|
|
|
break;
|
|
|
|
case 2: /* auth.backend.gssapi.store-creds */
|
|
|
|
pconf->auth_gssapi_store_creds = cpv->v.u;
|
|
|
|
break;
|
|
|
|
default:/* should not happen */
|
|
|
|
return;
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
2019-11-07 00:37:11 +00:00
|
|
|
}
|
2016-09-17 08:18:59 +00:00
|
|
|
|
2019-11-07 00:37:11 +00:00
|
|
|
static void mod_authn_gssapi_merge_config(plugin_config * const pconf, const config_plugin_value_t *cpv) {
|
|
|
|
do {
|
|
|
|
mod_authn_gssapi_merge_config_cpv(pconf, cpv);
|
|
|
|
} while ((++cpv)->k_id != -1);
|
|
|
|
}
|
2016-09-17 08:18:59 +00:00
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static void mod_authn_gssapi_patch_config(request_st * const r, plugin_data * const p) {
|
2020-01-11 16:07:43 +00:00
|
|
|
p->conf = p->defaults; /* copy small struct instead of memcpy() */
|
|
|
|
/*memcpy(&p->conf, &p->defaults, sizeof(plugin_config));*/
|
2019-11-07 00:37:11 +00:00
|
|
|
for (int i = 1, used = p->nconfig; i < used; ++i) {
|
2020-01-13 02:51:12 +00:00
|
|
|
if (config_check_cond(r, (uint32_t)p->cvlist[i].k_id))
|
2019-11-07 00:37:11 +00:00
|
|
|
mod_authn_gssapi_merge_config(&p->conf,
|
|
|
|
p->cvlist + p->cvlist[i].v.u2[0]);
|
|
|
|
}
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SETDEFAULTS_FUNC(mod_authn_gssapi_set_defaults) {
|
2019-11-07 00:37:11 +00:00
|
|
|
static const config_plugin_keys_t cpk[] = {
|
|
|
|
{ CONST_STR_LEN("auth.backend.gssapi.keytab"),
|
|
|
|
T_CONFIG_STRING,
|
|
|
|
T_CONFIG_SCOPE_CONNECTION }
|
|
|
|
,{ CONST_STR_LEN("auth.backend.gssapi.principal"),
|
|
|
|
T_CONFIG_STRING,
|
|
|
|
T_CONFIG_SCOPE_CONNECTION }
|
|
|
|
,{ CONST_STR_LEN("auth.backend.gssapi.store-creds"),
|
|
|
|
T_CONFIG_BOOL,
|
|
|
|
T_CONFIG_SCOPE_CONNECTION }
|
|
|
|
,{ NULL, 0,
|
|
|
|
T_CONFIG_UNSET,
|
|
|
|
T_CONFIG_SCOPE_UNSET }
|
2016-09-17 08:18:59 +00:00
|
|
|
};
|
|
|
|
|
2019-11-07 00:37:11 +00:00
|
|
|
plugin_data * const p = p_d;
|
|
|
|
if (!config_plugin_values_init(srv, p, cpk, "mod_authn_gssapi"))
|
|
|
|
return HANDLER_ERROR;
|
2016-09-17 08:18:59 +00:00
|
|
|
|
2019-11-07 00:37:11 +00:00
|
|
|
/* default enabled for backwards compatibility; disable in future */
|
|
|
|
p->defaults.auth_gssapi_store_creds = 1;
|
2016-09-17 08:18:59 +00:00
|
|
|
|
2019-11-07 00:37:11 +00:00
|
|
|
/* initialize p->defaults from global config context */
|
|
|
|
if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
|
|
|
|
const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
|
|
|
|
if (-1 != cpv->k_id)
|
|
|
|
mod_authn_gssapi_merge_config(&p->defaults, cpv);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
__attribute_cold__
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_send_400_bad_request (request_st * const r)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
2020-01-13 02:51:12 +00:00
|
|
|
r->http_status = 400;
|
|
|
|
r->handler_module = NULL;
|
2016-09-17 08:18:59 +00:00
|
|
|
return HANDLER_FINISHED;
|
|
|
|
}
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
__attribute_cold__
|
|
|
|
static void mod_authn_gssapi_log_gss_error(log_error_st *errh, const char *file, unsigned int line, const char *func, const char *extra, OM_uint32 err_maj, OM_uint32 err_min)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
buffer * const msg = buffer_init_string(func);
|
|
|
|
OM_uint32 maj_stat, min_stat;
|
|
|
|
OM_uint32 msg_ctx = 0;
|
|
|
|
gss_buffer_desc status_string;
|
|
|
|
|
|
|
|
buffer_append_string_len(msg, CONST_STR_LEN("("));
|
|
|
|
if (extra) buffer_append_string(msg, extra);
|
|
|
|
buffer_append_string_len(msg, CONST_STR_LEN("):"));
|
|
|
|
|
|
|
|
do {
|
|
|
|
maj_stat = gss_display_status(&min_stat, err_maj, GSS_C_GSS_CODE,
|
|
|
|
GSS_C_NO_OID, &msg_ctx, &status_string);
|
|
|
|
if (GSS_ERROR(maj_stat))
|
|
|
|
break;
|
|
|
|
|
|
|
|
buffer_append_string(msg, status_string.value);
|
|
|
|
gss_release_buffer(&min_stat, &status_string);
|
|
|
|
|
|
|
|
maj_stat = gss_display_status(&min_stat, err_min, GSS_C_MECH_CODE,
|
|
|
|
GSS_C_NULL_OID, &msg_ctx, &status_string);
|
|
|
|
if (!GSS_ERROR(maj_stat)) {
|
2018-09-23 23:16:06 +00:00
|
|
|
buffer_append_string_len(msg, CONST_STR_LEN(" ("));
|
2016-09-17 08:18:59 +00:00
|
|
|
buffer_append_string(msg, status_string.value);
|
2018-09-23 23:16:06 +00:00
|
|
|
buffer_append_string_len(msg, CONST_STR_LEN(")"));
|
2016-09-17 08:18:59 +00:00
|
|
|
gss_release_buffer(&min_stat, &status_string);
|
|
|
|
}
|
|
|
|
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, file, line, "%s", msg->ptr);
|
2016-09-17 08:18:59 +00:00
|
|
|
buffer_free(msg);
|
|
|
|
}
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
__attribute_cold__
|
|
|
|
static void mod_authn_gssapi_log_krb5_error(log_error_st *errh, const char *file, unsigned int line, const char *func, const char *extra, krb5_context context, int code)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
UNUSED(context);
|
|
|
|
/*(extra might be NULL)*/
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, file, line,
|
|
|
|
"%s (%s): %s", func, extra ? extra : "", error_message(code));
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static int mod_authn_gssapi_create_krb5_ccache(request_st * const r, plugin_data * const p, krb5_context kcontext, krb5_principal princ, krb5_ccache * const ccache)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
buffer * const kccname = buffer_init_string("FILE:/tmp/krb5cc_gssapi_XXXXXX");
|
|
|
|
char * const ccname = kccname->ptr + sizeof("FILE:")-1;
|
|
|
|
const size_t ccnamelen = buffer_string_length(kccname)-(sizeof("FILE:")-1);
|
2016-10-28 18:24:11 +00:00
|
|
|
/*(future: might consider using server.upload-dirs instead of /tmp)*/
|
2017-08-12 19:39:12 +00:00
|
|
|
#ifdef __COVERITY__
|
|
|
|
/* POSIX-2008 requires mkstemp create file with 0600 perms */
|
|
|
|
umask(0600);
|
|
|
|
#endif
|
2016-10-28 18:24:11 +00:00
|
|
|
/* coverity[secure_temp : FALSE] */
|
2016-09-17 08:18:59 +00:00
|
|
|
int fd = mkstemp(ccname);
|
|
|
|
if (fd < 0) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_perror(r->conf.errh, __FILE__, __LINE__, "mkstemp(): %s", ccname);
|
2016-09-17 08:18:59 +00:00
|
|
|
buffer_free(kccname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
do {
|
|
|
|
krb5_error_code problem;
|
|
|
|
|
|
|
|
problem = krb5_cc_resolve(kcontext, kccname->ptr, ccache);
|
|
|
|
if (problem) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_cc_resolve", NULL, kcontext, problem);
|
2016-09-17 08:18:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
problem = krb5_cc_initialize(kcontext, *ccache, princ);
|
|
|
|
if (problem) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_cc_initialize", kccname->ptr, kcontext, problem);
|
2016-09-17 08:18:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
r->plugin_ctx[p->id] = kccname;
|
2016-09-17 08:18:59 +00:00
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
http_header_env_set(r, CONST_STR_LEN("KRB5CCNAME"), ccname, ccnamelen);
|
|
|
|
http_header_request_set(r, HTTP_HEADER_OTHER, CONST_STR_LEN("X-Forwarded-Keytab"), ccname, ccnamelen);
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
if (*ccache) {
|
|
|
|
krb5_cc_destroy(kcontext, *ccache);
|
|
|
|
*ccache = NULL;
|
|
|
|
}
|
|
|
|
unlink(ccname);
|
|
|
|
buffer_free(kccname);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HTTP auth Negotiate
|
|
|
|
*/
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
__attribute_cold__
|
|
|
|
static handler_t mod_authn_gssapi_send_500_server_error (request_st * const r)
|
2019-09-07 20:37:00 +00:00
|
|
|
{
|
2020-01-13 02:51:12 +00:00
|
|
|
r->http_status = 500;
|
|
|
|
r->handler_module = NULL;
|
2019-09-07 20:37:00 +00:00
|
|
|
return HANDLER_FINISHED;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_send_401_unauthorized_negotiate (request_st * const r)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
2020-01-13 02:51:12 +00:00
|
|
|
r->http_status = 401;
|
|
|
|
r->handler_module = NULL;
|
2020-09-13 02:23:16 +00:00
|
|
|
http_header_response_set(r, HTTP_HEADER_WWW_AUTHENTICATE,
|
|
|
|
CONST_STR_LEN("WWW-Authenticate"),
|
|
|
|
CONST_STR_LEN("Negotiate"));
|
2016-09-17 08:18:59 +00:00
|
|
|
return HANDLER_FINISHED;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static int mod_authn_gssapi_store_gss_creds(request_st * const r, plugin_data * const p, char * const princ_name, gss_cred_id_t delegated_cred)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
OM_uint32 maj_stat, min_stat;
|
|
|
|
krb5_principal princ = NULL;
|
|
|
|
krb5_ccache ccache = NULL;
|
|
|
|
krb5_error_code problem;
|
|
|
|
krb5_context context;
|
|
|
|
|
|
|
|
problem = krb5_init_context(&context);
|
|
|
|
if (problem) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_init_context", NULL, context, problem);
|
2016-09-17 08:18:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
problem = krb5_parse_name(context, princ_name, &princ);
|
|
|
|
if (problem) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_parse_name", NULL, context, problem);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
if (mod_authn_gssapi_create_krb5_ccache(r, p, context, princ, &ccache))
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
|
|
|
|
maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, ccache);
|
|
|
|
if (GSS_ERROR(maj_stat)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_gss_error(r->conf.errh, __FILE__, __LINE__, "gss_krb5_copy_ccache", princ_name, maj_stat, min_stat);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
krb5_cc_close(context, ccache);
|
|
|
|
krb5_free_principal(context, princ);
|
|
|
|
krb5_free_context(context);
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (princ)
|
|
|
|
krb5_free_principal(context, princ);
|
|
|
|
if (ccache)
|
|
|
|
krb5_cc_destroy(context, ccache);
|
|
|
|
krb5_free_context(context);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_check_spnego(request_st * const r, plugin_data * const p, const http_auth_require_t * const require, const char * const realm_str)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
OM_uint32 st_major, st_minor, acc_flags;
|
|
|
|
gss_buffer_desc token_s = GSS_C_EMPTY_BUFFER;
|
|
|
|
gss_buffer_desc token_in = GSS_C_EMPTY_BUFFER;
|
|
|
|
gss_buffer_desc token_out = GSS_C_EMPTY_BUFFER;
|
|
|
|
gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
|
|
|
|
gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL;
|
|
|
|
gss_ctx_id_t context = GSS_C_NO_CONTEXT;
|
|
|
|
gss_name_t server_name = GSS_C_NO_NAME;
|
|
|
|
gss_name_t client_name = GSS_C_NO_NAME;
|
|
|
|
|
|
|
|
buffer *sprinc;
|
2019-09-07 20:37:00 +00:00
|
|
|
handler_t rc = HANDLER_UNSET;
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
buffer *t_in = buffer_init();
|
|
|
|
if (!buffer_append_base64_decode(t_in, realm_str, strlen(realm_str), BASE64_STANDARD)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "decoding GSSAPI authentication header failed %s", realm_str);
|
2016-09-17 08:18:59 +00:00
|
|
|
buffer_free(t_in);
|
2020-01-13 02:51:12 +00:00
|
|
|
return mod_authn_gssapi_send_400_bad_request(r);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_patch_config(r, p);
|
2016-09-17 08:18:59 +00:00
|
|
|
|
2016-11-02 08:23:47 +00:00
|
|
|
{
|
|
|
|
/* ??? Should code = krb5_kt_resolve(kcontext, p->conf.auth_gssapi_keytab->ptr, &keytab);
|
|
|
|
* be used, instead of putenv() of KRB5_KTNAME=...? See mod_authn_gssapi_basic() */
|
2020-01-13 02:51:12 +00:00
|
|
|
/* ??? Should KRB5_KTNAME go into r->env instead ??? */
|
2016-11-02 08:23:47 +00:00
|
|
|
/* ??? Should KRB5_KTNAME be added to mod_authn_gssapi_basic(), too? */
|
|
|
|
buffer ktname;
|
|
|
|
memset(&ktname, 0, sizeof(ktname));
|
|
|
|
buffer_copy_string(&ktname, "KRB5_KTNAME=");
|
|
|
|
buffer_append_string_buffer(&ktname, p->conf.auth_gssapi_keytab);
|
|
|
|
putenv(ktname.ptr);
|
|
|
|
/* ktname.ptr becomes part of the environment, do not free */
|
|
|
|
}
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
sprinc = buffer_init_buffer(p->conf.auth_gssapi_principal);
|
|
|
|
if (strchr(sprinc->ptr, '/') == NULL) {
|
|
|
|
/*(copy HTTP Host, omitting port if port is present)*/
|
2020-01-13 02:51:12 +00:00
|
|
|
/* ??? Should r->server_name be used if http_host not present?
|
|
|
|
* ??? What if r->server_name is not set?
|
2016-11-28 03:18:15 +00:00
|
|
|
* ??? Will this work below if IPv6 provided in Host? probably not */
|
2020-01-13 02:51:12 +00:00
|
|
|
if (!buffer_is_empty(r->http_host)) {
|
2018-09-23 23:16:06 +00:00
|
|
|
buffer_append_string_len(sprinc, CONST_STR_LEN("/"));
|
2020-01-13 02:51:12 +00:00
|
|
|
buffer_append_string_len(sprinc, r->http_host->ptr, strcspn(r->http_host->ptr, ":"));
|
2016-11-28 03:18:15 +00:00
|
|
|
}
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
if (strchr(sprinc->ptr, '@') == NULL) {
|
2018-09-23 23:16:06 +00:00
|
|
|
buffer_append_string_len(sprinc, CONST_STR_LEN("@"));
|
2016-09-17 08:18:59 +00:00
|
|
|
buffer_append_string_buffer(sprinc, require->realm);
|
|
|
|
}
|
|
|
|
/*#define GSS_C_NT_USER_NAME gss_nt_user_name*/
|
|
|
|
/*#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name*/
|
|
|
|
#define GSS_KRB5_NT_PRINCIPAL_NAME gss_nt_krb5_name
|
|
|
|
|
|
|
|
token_s.value = sprinc->ptr;
|
|
|
|
token_s.length = buffer_string_length(sprinc);
|
|
|
|
st_major = gss_import_name(&st_minor, &token_s, (gss_OID) GSS_KRB5_NT_PRINCIPAL_NAME, &server_name);
|
|
|
|
if (GSS_ERROR(st_major)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_gss_error(r->conf.errh, __FILE__, __LINE__, "gss_import_name", NULL, st_major, st_minor);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&token_s, 0, sizeof(token_s));
|
|
|
|
st_major = gss_display_name(&st_minor, server_name, &token_s, NULL);
|
|
|
|
if (GSS_ERROR(st_major)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_gss_error(r->conf.errh, __FILE__, __LINE__, "gss_display_name", NULL, st_major, st_minor);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* acquire server's own credentials */
|
|
|
|
st_major = gss_acquire_cred(&st_minor, server_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_cred, NULL, NULL);
|
|
|
|
if (GSS_ERROR(st_major)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_gss_error(r->conf.errh, __FILE__, __LINE__, "gss_acquire_cred", sprinc->ptr, st_major, st_minor);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* accept the user's context */
|
|
|
|
token_in.length = buffer_string_length(t_in);
|
|
|
|
token_in.value = t_in->ptr;
|
|
|
|
st_major = gss_accept_sec_context(&st_minor, &context, server_cred, &token_in, GSS_C_NO_CHANNEL_BINDINGS,
|
|
|
|
&client_name, NULL, &token_out, &acc_flags, NULL, &client_cred);
|
|
|
|
if (GSS_ERROR(st_major)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_gss_error(r->conf.errh, __FILE__, __LINE__, "gss_accept_sec_context", NULL, st_major, st_minor);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fetch the username */
|
|
|
|
st_major = gss_display_name(&st_minor, client_name, &token_out, NULL);
|
|
|
|
if (GSS_ERROR(st_major)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_gss_error(r->conf.errh, __FILE__, __LINE__, "gss_display_name", NULL, st_major, st_minor);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(acc_flags & GSS_C_CONF_FLAG)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "No confidentiality for user: %s", (char *)token_out.value);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2016-11-28 03:18:15 +00:00
|
|
|
/* check the allow-rules */
|
|
|
|
if (!http_auth_match_rules(require, token_out.value, NULL, NULL)) {
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2019-09-07 21:59:21 +00:00
|
|
|
if (p->conf.auth_gssapi_store_creds) {
|
2019-09-07 20:37:00 +00:00
|
|
|
if (!(acc_flags & GSS_C_DELEG_FLAG)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "Unable to delegate credentials for user: %s", (char *)token_out.value);
|
2019-09-07 20:37:00 +00:00
|
|
|
goto end;
|
|
|
|
}
|
2020-01-13 02:51:12 +00:00
|
|
|
else if (!mod_authn_gssapi_store_gss_creds(r, p, token_out.value, client_cred)) {
|
|
|
|
rc = mod_authn_gssapi_send_500_server_error(r);
|
2019-09-07 20:37:00 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
http_auth_setenv(r, token_out.value, token_out.length, CONST_STR_LEN("GSSAPI"));
|
2019-09-07 20:37:00 +00:00
|
|
|
rc = HANDLER_GO_ON; /* success */
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
end:
|
|
|
|
buffer_free(t_in);
|
2016-12-05 08:20:42 +00:00
|
|
|
buffer_free(sprinc);
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
if (context != GSS_C_NO_CONTEXT)
|
|
|
|
gss_delete_sec_context(&st_minor, &context, GSS_C_NO_BUFFER);
|
|
|
|
|
|
|
|
if (client_cred != GSS_C_NO_CREDENTIAL)
|
|
|
|
gss_release_cred(&st_minor, &client_cred);
|
|
|
|
if (server_cred != GSS_C_NO_CREDENTIAL)
|
|
|
|
gss_release_cred(&st_minor, &server_cred);
|
|
|
|
|
|
|
|
if (client_name != GSS_C_NO_NAME)
|
|
|
|
gss_release_name(&st_minor, &client_name);
|
|
|
|
if (server_name != GSS_C_NO_NAME)
|
|
|
|
gss_release_name(&st_minor, &server_name);
|
|
|
|
|
|
|
|
if (token_s.length)
|
|
|
|
gss_release_buffer(&st_minor, &token_s);
|
|
|
|
/* if (token_in.length)
|
|
|
|
* gss_release_buffer(&st_minor, &token_in); */
|
|
|
|
if (token_out.length)
|
|
|
|
gss_release_buffer(&st_minor, &token_out);
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
return rc != HANDLER_UNSET ? rc : mod_authn_gssapi_send_401_unauthorized_negotiate(r);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_check (request_st * const r, void *p_d, const struct http_auth_require_t * const require, const struct http_auth_backend_t * const backend)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
2020-01-13 02:51:12 +00:00
|
|
|
const buffer *vb = http_header_request_get(r, HTTP_HEADER_AUTHORIZATION, CONST_STR_LEN("Authorization"));
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
UNUSED(backend);
|
2018-09-09 05:50:33 +00:00
|
|
|
if (NULL == vb) {
|
2020-01-13 02:51:12 +00:00
|
|
|
return mod_authn_gssapi_send_401_unauthorized_negotiate(r);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2019-06-06 05:49:38 +00:00
|
|
|
if (!buffer_eq_icase_ssn(vb->ptr, CONST_STR_LEN("Negotiate "))) {
|
2020-01-13 02:51:12 +00:00
|
|
|
return mod_authn_gssapi_send_400_bad_request(r);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
return mod_authn_gssapi_check_spnego(r, (plugin_data *)p_d, require, vb->ptr+sizeof("Negotiate ")-1);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HTTP auth Basic realm="kerberos"
|
|
|
|
*/
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
static krb5_error_code mod_authn_gssapi_verify_krb5_init_creds(krb5_context context, krb5_creds *creds, krb5_principal ap_req_server, krb5_keytab ap_req_keytab, log_error_st *errh)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
krb5_error_code ret;
|
|
|
|
krb5_data req;
|
|
|
|
krb5_ccache local_ccache = NULL;
|
|
|
|
krb5_creds *new_creds = NULL;
|
|
|
|
krb5_auth_context auth_context = NULL;
|
|
|
|
krb5_keytab keytab = NULL;
|
|
|
|
char *server_name;
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
|
|
|
|
if (ap_req_keytab == NULL) {
|
|
|
|
ret = krb5_kt_default(context, &keytab);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
} else
|
|
|
|
keytab = ap_req_keytab;
|
|
|
|
|
|
|
|
ret = krb5_cc_resolve(context, "MEMORY:", &local_ccache);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_cc_resolve() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
/* return ret; */
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = krb5_cc_initialize(context, local_ccache, creds->client);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_cc_initialize() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = krb5_cc_store_cred(context, local_ccache, creds);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_cc_store_cred() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = krb5_unparse_name(context, ap_req_server, &server_name);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_unparse_name() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
2016-11-28 03:18:15 +00:00
|
|
|
krb5_free_unparsed_name(context, server_name);
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
if (!krb5_principal_compare(context, ap_req_server, creds->server)) {
|
|
|
|
krb5_creds match_cred;
|
|
|
|
|
|
|
|
memset(&match_cred, 0, sizeof(match_cred));
|
|
|
|
|
|
|
|
match_cred.client = creds->client;
|
|
|
|
match_cred.server = ap_req_server;
|
|
|
|
|
|
|
|
ret = krb5_get_credentials(context, 0, local_ccache, &match_cred, &new_creds);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_get_credentials() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
creds = new_creds;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = krb5_mk_req_extended(context, &auth_context, 0, NULL, creds, &req);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_mk_req_extended() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
krb5_auth_con_free(context, auth_context);
|
|
|
|
auth_context = NULL;
|
|
|
|
ret = krb5_auth_con_init(context, &auth_context);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_auth_con_init() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* use KRB5_AUTH_CONTEXT_DO_SEQUENCE to skip replay cache checks */
|
|
|
|
krb5_auth_con_setflags(context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE);
|
|
|
|
ret = krb5_rd_req(context, &auth_context, &req, ap_req_server, keytab, 0, NULL);
|
|
|
|
if (ret) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(errh, __FILE__, __LINE__, "krb5_rd_req() failed when verifying KDC");
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
krb5_free_data_contents(context, &req);
|
|
|
|
if (auth_context)
|
|
|
|
krb5_auth_con_free(context, auth_context);
|
|
|
|
if (new_creds)
|
|
|
|
krb5_free_creds(context, new_creds);
|
|
|
|
if (ap_req_keytab == NULL && keytab)
|
|
|
|
krb5_kt_close(context, keytab);
|
|
|
|
if (local_ccache)
|
|
|
|
krb5_cc_destroy(context, local_ccache);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static int mod_authn_gssapi_store_krb5_creds(request_st * const r, plugin_data * const p,
|
2016-09-17 08:18:59 +00:00
|
|
|
krb5_context kcontext, krb5_ccache delegated_cred)
|
|
|
|
{
|
|
|
|
krb5_error_code problem;
|
|
|
|
krb5_principal princ = NULL;
|
|
|
|
krb5_ccache ccache = NULL;
|
|
|
|
|
|
|
|
problem = krb5_cc_get_principal(kcontext, delegated_cred, &princ);
|
|
|
|
if (problem) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_cc_get_principal", NULL, kcontext, problem);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
if (mod_authn_gssapi_create_krb5_ccache(r, p, kcontext, princ, &ccache)) {
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
problem = krb5_cc_copy_creds(kcontext, delegated_cred, ccache);
|
|
|
|
if (problem) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_cc_copy_creds", NULL, kcontext, problem);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
krb5_free_principal(kcontext, princ);
|
|
|
|
krb5_cc_close(kcontext, ccache);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (princ)
|
|
|
|
krb5_free_principal(kcontext, princ);
|
|
|
|
if (ccache)
|
|
|
|
krb5_cc_destroy(kcontext, ccache);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_send_401_unauthorized_basic (request_st * const r)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
2020-01-13 02:51:12 +00:00
|
|
|
r->http_status = 401;
|
|
|
|
r->handler_module = NULL;
|
2020-09-13 02:23:16 +00:00
|
|
|
http_header_response_set(r, HTTP_HEADER_WWW_AUTHENTICATE,
|
|
|
|
CONST_STR_LEN("WWW-Authenticate"),
|
|
|
|
CONST_STR_LEN("Basic realm=\"Kerberos\""));
|
2016-09-17 08:18:59 +00:00
|
|
|
return HANDLER_FINISHED;
|
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
static handler_t mod_authn_gssapi_basic(request_st * const r, void *p_d, const http_auth_require_t * const require, const buffer * const username, const char * const pw)
|
2016-09-17 08:18:59 +00:00
|
|
|
{
|
|
|
|
krb5_context kcontext = NULL;
|
|
|
|
krb5_keytab keytab = NULL;
|
|
|
|
krb5_principal s_princ = NULL;
|
|
|
|
krb5_principal c_princ = NULL;
|
|
|
|
krb5_creds c_creds;
|
|
|
|
krb5_ccache c_ccache = NULL;
|
|
|
|
krb5_ccache ret_ccache = NULL;
|
|
|
|
krb5_error_code code;
|
|
|
|
int ret;
|
|
|
|
buffer *sprinc;
|
|
|
|
buffer *user_at_realm = NULL;
|
|
|
|
plugin_data * const p = (plugin_data *)p_d;
|
|
|
|
|
|
|
|
if (*pw == '\0') {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "Empty passwords are not accepted");
|
|
|
|
return mod_authn_gssapi_send_401_unauthorized_basic(r);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_patch_config(r, p);
|
2016-09-17 08:18:59 +00:00
|
|
|
|
|
|
|
code = krb5_init_context(&kcontext);
|
|
|
|
if (code) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "krb5_init_context(): %d", code);
|
|
|
|
return mod_authn_gssapi_send_401_unauthorized_basic(r); /*(well, should be 500)*/
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
2019-11-07 00:37:11 +00:00
|
|
|
if (buffer_string_is_empty(p->conf.auth_gssapi_keytab)) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "auth.backend.gssapi.keytab not configured");
|
|
|
|
return mod_authn_gssapi_send_401_unauthorized_basic(r); /*(well, should be 500)*/
|
2019-11-07 00:37:11 +00:00
|
|
|
}
|
|
|
|
|
2016-09-17 08:18:59 +00:00
|
|
|
code = krb5_kt_resolve(kcontext, p->conf.auth_gssapi_keytab->ptr, &keytab);
|
|
|
|
if (code) {
|
2020-01-13 02:51:12 +00:00
|
|
|
log_error(r->conf.errh, __FILE__, __LINE__, "krb5_kt_resolve(): %d %s", code, p->conf.auth_gssapi_keytab->ptr);
|
|
|
|
return mod_authn_gssapi_send_401_unauthorized_basic(r); /*(well, should be 500)*/
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sprinc = buffer_init_buffer(p->conf.auth_gssapi_principal);
|
|
|
|
if (strchr(sprinc->ptr, '/') == NULL) {
|
|
|
|
/*(copy HTTP Host, omitting port if port is present)*/
|
2020-01-13 02:51:12 +00:00
|
|
|
/* ??? Should r->server_name be used if http_host not present?
|
|
|
|
* ??? What if r->server_name is not set?
|
2016-11-28 03:18:15 +00:00
|
|
|
* ??? Will this work below if IPv6 provided in Host? probably not */
|
2020-01-13 02:51:12 +00:00
|
|
|
if (!buffer_is_empty(r->http_host)) {
|
2018-09-23 23:16:06 +00:00
|
|
|
buffer_append_string_len(sprinc, CONST_STR_LEN("/"));
|
2020-01-13 02:51:12 +00:00
|
|
|
buffer_append_string_len(sprinc, r->http_host->ptr, strcspn(r->http_host->ptr, ":"));
|
2016-11-28 03:18:15 +00:00
|
|
|
}
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*(init c_creds before anything which might krb5_free_cred_contents())*/
|
|
|
|
memset(&c_creds, 0, sizeof(c_creds));
|
|
|
|
|
|
|
|
ret = krb5_parse_name(kcontext, sprinc->ptr, &s_princ);
|
|
|
|
if (ret) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_parse_name", sprinc->ptr, kcontext, ret);
|
2016-09-17 08:18:59 +00:00
|
|
|
ret = -1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr(username->ptr, '@') == NULL) {
|
|
|
|
user_at_realm = buffer_init_buffer(username);
|
|
|
|
BUFFER_APPEND_STRING_CONST(user_at_realm, "@");
|
2016-09-28 10:36:38 +00:00
|
|
|
buffer_append_string_buffer(user_at_realm, require->realm);
|
2016-09-17 08:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = krb5_parse_name(kcontext, (user_at_realm ? user_at_realm->ptr : username->ptr), &c_princ);
|
|
|
|
if (ret) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_parse_name", (user_at_realm ? user_at_realm->ptr : username->ptr), kcontext, ret);
|
2016-09-17 08:18:59 +00:00
|
|
|
if (user_at_realm) buffer_free(user_at_realm);
|
|
|
|
ret = -1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (user_at_realm) buffer_free(user_at_realm);
|
|
|
|
/* XXX: if the qualified username with @realm should be in REMOTE_USER,
|
|
|
|
* then http_auth_backend_t basic interface needs to change to pass
|
|
|
|
* modifiable buffer *username, but note that const char *pw follows
|
|
|
|
* in the truncated buffer *username, so pw would need to be copied
|
|
|
|
* before modifying buffer *username */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* char *name = NULL;
|
|
|
|
* ret = krb5_unparse_name(kcontext, c_princ, &name);
|
|
|
|
* if (ret == 0) {
|
2020-01-13 02:51:12 +00:00
|
|
|
* log_error(r->conf.errh, __FILE__, __LINE__, "Trying to get TGT for user: %s password: %s", username->ptr, pw);
|
2016-09-17 08:18:59 +00:00
|
|
|
* }
|
2016-11-28 03:18:15 +00:00
|
|
|
* krb5_free_unparsed_name(kcontext, name);
|
2016-09-17 08:18:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
ret = krb5_get_init_creds_password(kcontext, &c_creds, c_princ, pw, NULL, NULL, 0, NULL, NULL);
|
|
|
|
if (ret) {
|
2020-01-13 02:51:12 +00:00
|
|
|
mod_authn_gssapi_log_krb5_error(r->conf.errh, __FILE__, __LINE__, "krb5_get_init_creds_password", NULL, kcontext, ret);
|
2016-09-17 08:18:59 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|