|
rpm-build |
8f3b0f |
/* Copyright (C) 2014, 2016, 2020 mod_auth_gssapi contributors
|
|
rpm-build |
8f3b0f |
* See COPYING for (C) terms */
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#include "mod_auth_gssapi.h"
|
|
Packit Service |
466431 |
#include "mag_parse.h"
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
const gss_OID_desc gss_mech_spnego = {
|
|
Packit Service |
466431 |
6, "\x2b\x06\x01\x05\x05\x02"
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_GSSAPI_GSSAPI_NTLMSSP_H
|
|
Packit Service |
466431 |
const gss_OID_desc gss_mech_ntlmssp_desc = {
|
|
Packit Service |
466431 |
GSS_NTLMSSP_OID_LENGTH, GSS_NTLMSSP_OID_STRING
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
gss_const_OID gss_mech_ntlmssp = &gss_mech_ntlmssp_desc;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
const gss_OID_set_desc gss_mech_set_ntlmssp_desc = {
|
|
Packit Service |
466431 |
1, discard_const(&gss_mech_ntlmssp_desc)
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
gss_const_OID_set gss_mech_set_ntlmssp = &gss_mech_set_ntlmssp_desc;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#else
|
|
Packit Service |
466431 |
gss_OID gss_mech_ntlmssp = GSS_C_NO_OID;
|
|
Packit Service |
466431 |
gss_OID_set gss_mech_set_ntlmssp = GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#define MOD_AUTH_GSSAPI_VERSION PACKAGE_NAME "/" PACKAGE_VERSION
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
module AP_MODULE_DECLARE_DATA auth_gssapi_module;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
APLOG_USE_MODULE(auth_gssapi);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static char *mag_status(apr_pool_t *pool, int type, uint32_t err)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
uint32_t maj_ret, min_ret;
|
|
Packit Service |
466431 |
gss_buffer_desc text;
|
|
Packit Service |
466431 |
uint32_t msg_ctx;
|
|
Packit Service |
466431 |
char *msg_ret;
|
|
Packit Service |
466431 |
int len;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
msg_ret = NULL;
|
|
Packit Service |
466431 |
msg_ctx = 0;
|
|
Packit Service |
466431 |
do {
|
|
Packit Service |
466431 |
maj_ret = gss_display_status(&min_ret, err, type,
|
|
Packit Service |
466431 |
GSS_C_NO_OID, &msg_ctx, &text);
|
|
Packit Service |
466431 |
if (maj_ret != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
return msg_ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
len = text.length;
|
|
Packit Service |
466431 |
if (msg_ret) {
|
|
Packit Service |
466431 |
msg_ret = apr_psprintf(pool, "%s, %*s",
|
|
Packit Service |
466431 |
msg_ret, len, (char *)text.value);
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
msg_ret = apr_psprintf(pool, "%*s", len, (char *)text.value);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
gss_release_buffer(&min_ret, &text);
|
|
Packit Service |
466431 |
} while (msg_ctx != 0);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return msg_ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
char *mag_error(apr_pool_t *pool, const char *msg, uint32_t maj, uint32_t min)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
char *msg_maj;
|
|
Packit Service |
466431 |
char *msg_min;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
msg_maj = mag_status(pool, GSS_C_GSS_CODE, maj);
|
|
Packit Service |
466431 |
msg_min = mag_status(pool, GSS_C_MECH_CODE, min);
|
|
Packit Service |
466431 |
return apr_psprintf(pool, "%s: [%s (%s)]", msg, msg_maj, msg_min);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
enum mag_err_code {
|
|
Packit Service |
466431 |
MAG_NO_AUTH = 1,
|
|
Packit Service |
466431 |
MAG_GSS_ERR,
|
|
Packit Service |
466431 |
MAG_INTERNAL,
|
|
Packit Service |
466431 |
MAG_AUTH_NOT_ALLOWED
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_err_text(enum mag_err_code err)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
switch (err) {
|
|
Packit Service |
466431 |
case MAG_NO_AUTH:
|
|
Packit Service |
466431 |
return "NO AUTH DATA";
|
|
Packit Service |
466431 |
case MAG_GSS_ERR:
|
|
Packit Service |
466431 |
return "GSS ERROR";
|
|
Packit Service |
466431 |
case MAG_INTERNAL:
|
|
Packit Service |
466431 |
return "INTERNAL ERROR";
|
|
Packit Service |
466431 |
case MAG_AUTH_NOT_ALLOWED:
|
|
Packit Service |
466431 |
return "AUTH NOT ALLOWED";
|
|
Packit Service |
466431 |
default:
|
|
Packit Service |
466431 |
return "INVALID ERROR CODE";
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void mag_post_info(request_rec *req, struct mag_config *cfg,
|
|
Packit Service |
466431 |
enum mag_err_code err, const char *msg)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
const char *text = NULL;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->enverrs) {
|
|
Packit Service |
466431 |
mag_publish_error(req, 0, 0, text ? text : msg, mag_err_text(err));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req, "%s %s", mag_err_text(err),
|
|
Packit Service |
466431 |
text ? text : msg);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void mag_post_error(request_rec *req, struct mag_config *cfg,
|
|
Packit Service |
466431 |
enum mag_err_code err, uint32_t maj, uint32_t min,
|
|
Packit Service |
466431 |
const char *msg)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
const char *text = NULL;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (maj)
|
|
Packit Service |
466431 |
text = mag_error(req->pool, msg, maj, min);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->enverrs)
|
|
Packit Service |
466431 |
mag_publish_error(req, maj, min, text ? text : msg, mag_err_text(err));
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s %s", mag_err_text(err),
|
|
Packit Service |
466431 |
text ? text : msg);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static APR_OPTIONAL_FN_TYPE(ssl_is_https) *mag_is_https = NULL;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static int mag_post_config(apr_pool_t *cfgpool, apr_pool_t *log,
|
|
Packit Service |
466431 |
apr_pool_t *temp, server_rec *s)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
/* FIXME: create mutex to deal with connections and contexts ? */
|
|
Packit Service |
466431 |
mag_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
|
|
Packit Service |
466431 |
mag_post_config_session();
|
|
Packit Service |
466431 |
ap_add_version_component(cfgpool, MOD_AUTH_GSSAPI_VERSION);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return OK;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static int mag_pre_connection(conn_rec *c, void *csd)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_conn *mc;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc = mag_new_conn_ctx(c->pool);
|
|
Packit Service |
466431 |
mc->is_preserved = true;
|
|
Packit Service |
466431 |
ap_set_module_config(c->conn_config, &auth_gssapi_module, (void*)mc);
|
|
Packit Service |
466431 |
return OK;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static apr_status_t mag_conn_destroy(void *ptr)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_conn *mc = (struct mag_conn *)ptr;
|
|
Packit Service |
466431 |
uint32_t min;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (mc->ctx) {
|
|
Packit Service |
466431 |
(void)gss_delete_sec_context(&min, &mc->ctx, GSS_C_NO_BUFFER);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return APR_SUCCESS;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
struct mag_conn *mag_new_conn_ctx(apr_pool_t *pool)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_conn *mc;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc = apr_pcalloc(pool, sizeof(struct mag_conn));
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
apr_pool_create(&mc->pool, pool);
|
|
Packit Service |
466431 |
mc->env = apr_table_make(mc->pool, 1);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* register the context in the memory pool, so it can be freed
|
|
Packit Service |
466431 |
* when the connection/request is terminated */
|
|
Packit Service |
466431 |
apr_pool_cleanup_register(mc->pool, (void *)mc,
|
|
Packit Service |
466431 |
mag_conn_destroy, apr_pool_cleanup_null);
|
|
Packit Service |
466431 |
return mc;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void mag_conn_clear(struct mag_conn *mc)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
(void)mag_conn_destroy(mc);
|
|
Packit Service |
466431 |
apr_pool_t *temp;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
apr_pool_clear(mc->pool);
|
|
Packit Service |
466431 |
temp = mc->pool;
|
|
Packit Service |
466431 |
memset(mc, 0, sizeof(struct mag_conn));
|
|
Packit Service |
466431 |
mc->pool = temp;
|
|
Packit Service |
466431 |
mc->env = apr_table_make(mc->pool, 1);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static bool mag_conn_is_https(conn_rec *c)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
if (mag_is_https) {
|
|
Packit Service |
466431 |
if (mag_is_https(c)) return true;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static bool mag_acquire_creds(request_rec *req,
|
|
Packit Service |
466431 |
struct mag_config *cfg,
|
|
Packit Service |
466431 |
gss_OID_set desired_mechs,
|
|
Packit Service |
466431 |
gss_cred_usage_t cred_usage,
|
|
Packit Service |
466431 |
gss_cred_id_t *creds,
|
|
Packit Service |
466431 |
gss_OID_set *actual_mechs)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_name_t acceptor_name = GSS_C_NO_NAME;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
bool ret;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->acceptor_name_from_req) {
|
|
Packit Service |
466431 |
gss_buffer_desc bufnam;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
bufnam.value = apr_psprintf(req->pool, "HTTP@%s", req->hostname);
|
|
Packit Service |
466431 |
bufnam.length = strlen(bufnam.value);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req, "GSS Server Name: %s",
|
|
Packit Service |
466431 |
(char *)bufnam.value);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_import_name(&min, &bufnam, GSS_C_NT_HOSTBASED_SERVICE,
|
|
Packit Service |
466431 |
&acceptor_name);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"gss_import_name() failed to import hostnname");
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
acceptor_name = cfg->acceptor_name;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
gss_const_key_value_set_t store = cfg->cred_store;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_acquire_cred_from(&min, acceptor_name, GSS_C_INDEFINITE,
|
|
Packit Service |
466431 |
desired_mechs, cred_usage, store, creds,
|
|
Packit Service |
466431 |
actual_mechs, NULL);
|
|
Packit Service |
466431 |
#else
|
|
Packit Service |
466431 |
maj = gss_acquire_cred(&min, acceptor_name, GSS_C_INDEFINITE,
|
|
Packit Service |
466431 |
desired_mechs, cred_usage, creds,
|
|
Packit Service |
466431 |
actual_mechs, NULL);
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"gss_acquire_cred[_from]() failed to get server creds");
|
|
Packit Service |
466431 |
ret = false;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ret = true;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->acceptor_name_from_req) {
|
|
Packit Service |
466431 |
gss_release_name(&min, &acceptor_name);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
static char *escape(apr_pool_t *pool, const char *name,
|
|
Packit Service |
466431 |
char find, const char *replace)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
char *escaped = NULL;
|
|
Packit Service |
466431 |
char *namecopy;
|
|
Packit Service |
466431 |
char *n;
|
|
Packit Service |
466431 |
char *p;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
namecopy = apr_pstrdup(pool, name);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
p = strchr(namecopy, find);
|
|
Packit Service |
466431 |
if (!p) return namecopy;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* first segment */
|
|
Packit Service |
466431 |
n = namecopy;
|
|
Packit Service |
466431 |
while (p) {
|
|
Packit Service |
466431 |
/* terminate previous segment */
|
|
Packit Service |
466431 |
*p = '\0';
|
|
Packit Service |
466431 |
if (escaped) {
|
|
Packit Service |
466431 |
escaped = apr_pstrcat(pool, escaped, n, replace, NULL);
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
escaped = apr_pstrcat(pool, n, replace, NULL);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
/* move to next segment */
|
|
Packit Service |
466431 |
n = p + 1;
|
|
Packit Service |
466431 |
p = strchr(n, find);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
/* append last segment if any */
|
|
Packit Service |
466431 |
if (*n) {
|
|
Packit Service |
466431 |
escaped = apr_pstrcat(pool, escaped, n, NULL);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return escaped;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static char *get_ccache_name(request_rec *req, char *dir, const char *gss_name,
|
|
Packit Service |
466431 |
bool use_unique, struct mag_conn *mc)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
char *ccname, *escaped;
|
|
Packit Service |
466431 |
int ccachefd;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* We need to escape away '/', we can't have path separators in
|
|
Packit Service |
466431 |
* a ccache file name */
|
|
Packit Service |
466431 |
/* first double escape the esacping char (~) if any */
|
|
Packit Service |
466431 |
escaped = escape(req->pool, gss_name, '~', "~~");
|
|
Packit Service |
466431 |
/* then escape away the separator (/) if any */
|
|
Packit Service |
466431 |
escaped = escape(req->pool, escaped, '/', "~");
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (use_unique == false) {
|
|
Packit Service |
466431 |
return apr_psprintf(mc->pool, "%s/%s", dir, escaped);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ccname = apr_psprintf(mc->pool, "%s/%s-XXXXXX", dir, escaped);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ccachefd = mkstemp(ccname);
|
|
Packit Service |
466431 |
if (ccachefd == -1) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
|
|
Packit Service |
466431 |
"creating unique ccache file %s failed", ccname);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
close(ccachefd);
|
|
Packit Service |
466431 |
return ccname;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void mag_store_deleg_creds(request_rec *req, const char *ccname,
|
|
Packit Service |
466431 |
gss_cred_id_t delegated_cred)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_key_value_element_desc element;
|
|
Packit Service |
466431 |
gss_key_value_set_desc store;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
element.key = "ccache";
|
|
Packit Service |
466431 |
store.elements = &element;
|
|
Packit Service |
466431 |
store.count = 1;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
element.value = apr_psprintf(req->pool, "FILE:%s", ccname);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
|
|
Packit Service |
466431 |
GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
|
|
Packit Service |
466431 |
mag_error(req->pool, "failed to store delegated creds",
|
|
Packit Service |
466431 |
maj, min));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static bool parse_auth_header(apr_pool_t *pool, const char **auth_header,
|
|
Packit Service |
466431 |
gss_buffer_t value)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
char *auth_header_value;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
auth_header_value = ap_getword_white(pool, auth_header);
|
|
Packit Service |
466431 |
if (!auth_header_value) return false;
|
|
Packit Service |
466431 |
value->length = apr_base64_decode_len(auth_header_value) + 1;
|
|
Packit Service |
466431 |
value->value = apr_pcalloc(pool, value->length);
|
|
Packit Service |
466431 |
if (!value->value) return false;
|
|
Packit Service |
466431 |
value->length = apr_base64_decode(value->value, auth_header_value);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return true;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static bool is_mech_allowed(gss_OID_set allowed_mechs, gss_const_OID mech,
|
|
Packit Service |
466431 |
bool multi_step_supported)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
if (mech == GSS_C_NO_OID) return false;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!multi_step_supported && gss_oid_equal(gss_mech_ntlmssp, mech))
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (allowed_mechs == GSS_C_NO_OID_SET) return true;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
for (int i = 0; i < allowed_mechs->count; i++) {
|
|
Packit Service |
466431 |
if (gss_oid_equal(&allowed_mechs->elements[i], mech)) {
|
|
Packit Service |
466431 |
return true;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#define AUTH_TYPE_NEGOTIATE 0
|
|
Packit Service |
466431 |
#define AUTH_TYPE_BASIC 1
|
|
Packit Service |
466431 |
#define AUTH_TYPE_RAW_NTLM 2
|
|
Packit Service |
466431 |
#define AUTH_TYPE_IMPERSONATE 3
|
|
Packit Service |
466431 |
const char *auth_types[] = {
|
|
Packit Service |
466431 |
"Negotiate",
|
|
Packit Service |
466431 |
"Basic",
|
|
Packit Service |
466431 |
"NTLM",
|
|
Packit Service |
466431 |
"Impersonate",
|
|
Packit Service |
466431 |
NULL
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
const char *mag_str_auth_type(int auth_type)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
return auth_types[auth_type];
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
gss_OID_set mag_filter_unwanted_mechs(gss_OID_set src)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_const_OID unwanted_mechs[] = {
|
|
Packit Service |
466431 |
&gss_mech_spnego,
|
|
Packit Service |
466431 |
gss_mech_krb5_old,
|
|
Packit Service |
466431 |
gss_mech_krb5_wrong,
|
|
Packit Service |
466431 |
gss_mech_iakerb,
|
|
Packit Service |
466431 |
GSS_C_NO_OID
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
gss_OID_set dst;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
int present = 0;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (src == GSS_C_NO_OID_SET) return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
for (int i = 0; unwanted_mechs[i] != GSS_C_NO_OID; i++) {
|
|
Packit Service |
466431 |
maj = gss_test_oid_set_member(&min,
|
|
Packit Service |
466431 |
discard_const(unwanted_mechs[i]),
|
|
Packit Service |
466431 |
src, &present);
|
|
Packit Service |
466431 |
if (present) break;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (present) {
|
|
Packit Service |
466431 |
maj = gss_create_empty_oid_set(&min, &dst);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
for (int i = 0; i < src->count; i++) {
|
|
Packit Service |
466431 |
present = 0;
|
|
Packit Service |
466431 |
for (int j = 0; unwanted_mechs[j] != GSS_C_NO_OID; j++) {
|
|
Packit Service |
466431 |
if (gss_oid_equal(&src->elements[i], unwanted_mechs[j])) {
|
|
Packit Service |
466431 |
present = 1;
|
|
Packit Service |
466431 |
break;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (present) continue;
|
|
Packit Service |
466431 |
maj = gss_add_oid_set_member(&min, &src->elements[i], &dst);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
gss_release_oid_set(&min, &dst);
|
|
Packit Service |
466431 |
return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return dst;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return src;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static uint32_t mag_context_loop(uint32_t *min,
|
|
Packit Service |
466431 |
request_rec *req,
|
|
Packit Service |
466431 |
struct mag_config *cfg,
|
|
Packit Service |
466431 |
gss_cred_id_t init_cred,
|
|
Packit Service |
466431 |
gss_cred_id_t accept_cred,
|
|
Packit Service |
466431 |
gss_OID mech_type,
|
|
Packit Service |
466431 |
uint32_t req_lifetime,
|
|
Packit Service |
466431 |
gss_name_t *client,
|
|
Packit Service |
466431 |
uint32_t *lifetime,
|
|
Packit Service |
466431 |
gss_cred_id_t *delegated_cred)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_ctx_id_t init_ctx = GSS_C_NO_CONTEXT;
|
|
Packit Service |
466431 |
gss_ctx_id_t accept_ctx = GSS_C_NO_CONTEXT;
|
|
Packit Service |
466431 |
gss_buffer_desc init_token = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
gss_buffer_desc accept_token = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
gss_name_t accept_name = GSS_C_NO_NAME;
|
|
Packit Service |
466431 |
uint32_t maj, tmin;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_inquire_cred_by_mech(min, accept_cred, mech_type, &accept_name,
|
|
Packit Service |
466431 |
NULL, NULL, NULL);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, *min,
|
|
Packit Service |
466431 |
"gss_inquired_cred_by_mech() failed");
|
|
Packit Service |
466431 |
return maj;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
do {
|
|
Packit Service |
466431 |
/* output and input are inverted here, this is intentional */
|
|
Packit Service |
466431 |
maj = gss_init_sec_context(min, init_cred, &init_ctx,
|
|
Packit Service |
466431 |
accept_name, mech_type, GSS_C_DELEG_FLAG,
|
|
Packit Service |
466431 |
req_lifetime, GSS_C_NO_CHANNEL_BINDINGS,
|
|
Packit Service |
466431 |
&accept_token, NULL, &init_token, NULL,
|
|
Packit Service |
466431 |
NULL);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, *min,
|
|
Packit Service |
466431 |
"gss_init_sec_context()");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
gss_release_buffer(&tmin, &accept_token);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_accept_sec_context(min, &accept_ctx, accept_cred,
|
|
Packit Service |
466431 |
&init_token, GSS_C_NO_CHANNEL_BINDINGS,
|
|
Packit Service |
466431 |
client, NULL, &accept_token, NULL,
|
|
Packit Service |
466431 |
lifetime, delegated_cred);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, *min,
|
|
Packit Service |
466431 |
"gss_accept_sec_context()");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
gss_release_buffer(&tmin, &init_token);
|
|
Packit Service |
466431 |
} while (maj == GSS_S_CONTINUE_NEEDED);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
done:
|
|
Packit Service |
466431 |
gss_release_name(&tmin, &accept_name);
|
|
Packit Service |
466431 |
gss_release_buffer(&tmin, &init_token);
|
|
Packit Service |
466431 |
gss_release_buffer(&tmin, &accept_token);
|
|
Packit Service |
466431 |
gss_delete_sec_context(&tmin, &init_ctx, GSS_C_NO_BUFFER);
|
|
Packit Service |
466431 |
gss_delete_sec_context(&tmin, &accept_ctx, GSS_C_NO_BUFFER);
|
|
Packit Service |
466431 |
return maj;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
rpm-build |
67bb15 |
static int mag_complete(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
|
|
rpm-build |
67bb15 |
gss_name_t client, gss_OID mech_type,
|
|
rpm-build |
67bb15 |
uint32_t vtime, gss_cred_id_t delegated_cred);
|
|
rpm-build |
67bb15 |
|
|
rpm-build |
67bb15 |
static int mag_auth_basic(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
|
|
rpm-build |
67bb15 |
gss_buffer_desc ba_user, gss_buffer_desc ba_pwd)
|
|
Packit Service |
466431 |
{
|
|
rpm-build |
67bb15 |
struct mag_config *cfg = req_cfg->cfg;
|
|
rpm-build |
67bb15 |
request_rec *req = req_cfg->req;
|
|
Packit Service |
466431 |
const char *user_ccache = NULL;
|
|
Packit Service |
466431 |
const char *orig_ccache = NULL;
|
|
Packit Service |
466431 |
long long unsigned int rndname;
|
|
Packit Service |
466431 |
apr_status_t rs;
|
|
Packit Service |
466431 |
gss_name_t user = GSS_C_NO_NAME;
|
|
Packit Service |
466431 |
gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
gss_OID_set allowed_mechs;
|
|
Packit Service |
466431 |
gss_OID_set filtered_mechs;
|
|
Packit Service |
466431 |
gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
|
|
rpm-build |
67bb15 |
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
|
|
rpm-build |
67bb15 |
gss_name_t client = GSS_C_NO_NAME;
|
|
rpm-build |
67bb15 |
uint32_t vtime;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
int present = 0;
|
|
rpm-build |
67bb15 |
int ret = HTTP_UNAUTHORIZED;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &user);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In Basic Auth: gss_import_name() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->basic_mechs) {
|
|
Packit Service |
466431 |
allowed_mechs = cfg->basic_mechs;
|
|
Packit Service |
466431 |
} else if (cfg->allowed_mechs) {
|
|
Packit Service |
466431 |
allowed_mechs = cfg->allowed_mechs;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
struct mag_server_config *scfg;
|
|
Packit Service |
466431 |
/* Try to fetch the default set if not explicitly configured,
|
|
Packit Service |
466431 |
* We need to do this because gss_acquire_cred_with_password()
|
|
Packit Service |
466431 |
* is currently limited to acquire creds for a single "default"
|
|
Packit Service |
466431 |
* mechanism if no desired mechanisms are passed in. This causes
|
|
Packit Service |
466431 |
* authentication to fail for secondary mechanisms as no user
|
|
Packit Service |
466431 |
* credentials are generated for those. */
|
|
Packit Service |
466431 |
scfg = ap_get_module_config(req->server->module_config,
|
|
Packit Service |
466431 |
&auth_gssapi_module);
|
|
Packit Service |
466431 |
/* In the worst case scenario default_mechs equals to GSS_C_NO_OID_SET.
|
|
Packit Service |
466431 |
* This generally causes only the krb5 mechanism to be tried due
|
|
Packit Service |
466431 |
* to implementation constraints, but may change in future. */
|
|
Packit Service |
466431 |
allowed_mechs = scfg->default_mechs;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* Remove Spnego if present, or we'd repeat failed authentiations
|
|
Packit Service |
466431 |
* multiple times, one within Spnego and then again with an explicit
|
|
Packit Service |
466431 |
* mechanism. We would normally just force Spnego and use
|
|
Packit Service |
466431 |
* gss_set_neg_mechs, but due to the way we source the server name
|
|
Packit Service |
466431 |
* and the fact MIT up to 1.14 at least does no handle union names,
|
|
Packit Service |
466431 |
* we can't provide spnego with a server name that can be used by
|
|
Packit Service |
466431 |
* multiple mechanisms, causing any but the first mechanism to fail.
|
|
Packit Service |
466431 |
* Also remove unwanted krb mechs, or AS requests will be repeated
|
|
Packit Service |
466431 |
* multiple times uselessly.
|
|
Packit Service |
466431 |
*/
|
|
Packit Service |
466431 |
filtered_mechs = mag_filter_unwanted_mechs(allowed_mechs);
|
|
Packit Service |
466431 |
if (filtered_mechs == allowed_mechs) {
|
|
Packit Service |
466431 |
/* in case filtered_mechs was not allocated here don't free it */
|
|
Packit Service |
466431 |
filtered_mechs = GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
} else if (filtered_mechs == GSS_C_NO_OID_SET) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0, 0,
|
|
Packit Service |
466431 |
"Fatal failure while filtering mechs, aborting");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
/* use the filtered list */
|
|
Packit Service |
466431 |
allowed_mechs = filtered_mechs;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* If we are using the krb5 mechanism make sure to set a per thread
|
|
Packit Service |
466431 |
* memory ccache so that there can't be interferences between threads.
|
|
Packit Service |
466431 |
* Also make sure we have new cache so no cached results end up being
|
|
Packit Service |
466431 |
* used. Some implementations of gss_acquire_cred_with_password() do
|
|
Packit Service |
466431 |
* not reacquire creds if cached ones are around, failing to check
|
|
Packit Service |
466431 |
* again for the password. */
|
|
Packit Service |
466431 |
maj = gss_test_oid_set_member(&min, discard_const(gss_mech_krb5),
|
|
Packit Service |
466431 |
allowed_mechs, &present);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In Basic Auth: gss_test_oid_set_member() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (present) {
|
|
Packit Service |
466431 |
rs = apr_generate_random_bytes((unsigned char *)(&rndname),
|
|
Packit Service |
466431 |
sizeof(long long unsigned int));
|
|
Packit Service |
466431 |
if (rs != APR_SUCCESS) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0, 0,
|
|
Packit Service |
466431 |
"Failed to generate random ccache name");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname);
|
|
Packit Service |
466431 |
maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In Basic Auth: gss_krb5_ccache_name() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_acquire_cred_with_password(&min, user, &ba_pwd,
|
|
rpm-build |
8f3b0f |
cfg->basic_timeout,
|
|
Packit Service |
466431 |
allowed_mechs,
|
|
Packit Service |
466431 |
GSS_C_INITIATE,
|
|
Packit Service |
466431 |
&user_cred, &actual_mechs, NULL);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In Basic Auth: gss_acquire_cred_with_password() "
|
|
Packit Service |
466431 |
"failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* must acquire creds based on the actual mechs we want to try */
|
|
Packit Service |
466431 |
if (!mag_acquire_creds(req, cfg, actual_mechs,
|
|
Packit Service |
466431 |
GSS_C_ACCEPT, &server_cred, NULL)) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
for (int i = 0; i < actual_mechs->count; i++) {
|
|
Packit Service |
466431 |
maj = mag_context_loop(&min, req, cfg, user_cred, server_cred,
|
|
rpm-build |
8f3b0f |
&actual_mechs->elements[i], cfg->basic_timeout,
|
|
rpm-build |
8f3b0f |
&client, &vtime, &delegated_cred);
|
|
Packit Service |
466431 |
if (maj == GSS_S_COMPLETE) {
|
|
rpm-build |
67bb15 |
ret = mag_complete(req_cfg, mc, client, &actual_mechs->elements[i],
|
|
rpm-build |
67bb15 |
vtime, delegated_cred);
|
|
rpm-build |
67bb15 |
if (ret == OK) {
|
|
rpm-build |
67bb15 |
mag_basic_cache(req_cfg, mc, ba_user, ba_pwd);
|
|
rpm-build |
67bb15 |
}
|
|
Packit Service |
466431 |
break;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
done:
|
|
rpm-build |
67bb15 |
gss_release_cred(&min, &delegated_cred);
|
|
rpm-build |
67bb15 |
gss_release_name(&min, &client);
|
|
Packit Service |
466431 |
gss_release_cred(&min, &server_cred);
|
|
Packit Service |
466431 |
gss_release_name(&min, &user);
|
|
Packit Service |
466431 |
gss_release_cred(&min, &user_cred);
|
|
Packit Service |
466431 |
gss_release_oid_set(&min, &actual_mechs);
|
|
Packit Service |
466431 |
gss_release_oid_set(&min, &filtered_mechs);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (user_ccache != NULL) {
|
|
Packit Service |
466431 |
maj = gss_krb5_ccache_name(&min, orig_ccache, NULL);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req,
|
|
Packit Service |
466431 |
"Failed to restore per-thread ccache, %s",
|
|
Packit Service |
466431 |
mag_error(req->pool, "gss_krb5_ccache_name() "
|
|
Packit Service |
466431 |
"failed", maj, min));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
struct mag_req_cfg *mag_init_cfg(request_rec *req)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_server_config *scfg;
|
|
Packit Service |
466431 |
struct mag_req_cfg *req_cfg = apr_pcalloc(req->pool,
|
|
Packit Service |
466431 |
sizeof(struct mag_req_cfg));
|
|
Packit Service |
466431 |
req_cfg->req = req;
|
|
Packit Service |
466431 |
req_cfg->cfg = ap_get_module_config(req->per_dir_config,
|
|
Packit Service |
466431 |
&auth_gssapi_module);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
scfg = ap_get_module_config(req->server->module_config,
|
|
Packit Service |
466431 |
&auth_gssapi_module);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (req_cfg->cfg->allowed_mechs) {
|
|
Packit Service |
466431 |
req_cfg->desired_mechs = req_cfg->cfg->allowed_mechs;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
/* Use the default set if not explicitly configured */
|
|
Packit Service |
466431 |
req_cfg->desired_mechs = scfg->default_mechs;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (req_cfg->cfg->mag_skey) {
|
|
Packit Service |
466431 |
req_cfg->mag_skey = req_cfg->cfg->mag_skey;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
/* Use server random key if not explicitly configured */
|
|
Packit Service |
466431 |
req_cfg->mag_skey = scfg->mag_skey;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (req->proxyreq == PROXYREQ_PROXY) {
|
|
Packit Service |
466431 |
req_cfg->req_proto = "Proxy-Authorization";
|
|
Packit Service |
466431 |
req_cfg->rep_proto = "Proxy-Authenticate";
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
req_cfg->req_proto = "Authorization";
|
|
Packit Service |
466431 |
req_cfg->rep_proto = "WWW-Authenticate";
|
|
Packit Service |
466431 |
req_cfg->use_sessions = req_cfg->cfg->use_sessions;
|
|
Packit Service |
466431 |
req_cfg->send_persist = req_cfg->cfg->send_persist;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return req_cfg;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
static bool use_s4u2proxy(struct mag_req_cfg *req_cfg) {
|
|
Packit Service |
466431 |
if (req_cfg->cfg->use_s4u2proxy) {
|
|
Packit Service |
466431 |
if (req_cfg->cfg->deleg_ccache_dir != NULL) {
|
|
Packit Service |
466431 |
return true;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req_cfg->req,
|
|
Packit Service |
466431 |
"S4U2 Proxy requested but GssapiDelegCcacheDir "
|
|
Packit Service |
466431 |
"is not set. Constrained delegation disabled!");
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static apr_status_t mag_s4u2self(request_rec *req)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
apr_status_t ret = DECLINED;
|
|
Packit Service |
466431 |
const char *type;
|
|
Packit Service |
466431 |
struct mag_config *cfg;
|
|
Packit Service |
466431 |
struct mag_req_cfg *req_cfg;
|
|
Packit Service |
466431 |
gss_OID mech_type = discard_const(gss_mech_krb5);
|
|
Packit Service |
466431 |
gss_OID_set_desc gss_mech_krb5_set = { 1, mech_type };
|
|
Packit Service |
466431 |
gss_buffer_desc user_name = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
gss_name_t user = GSS_C_NO_NAME;
|
|
Packit Service |
466431 |
gss_name_t client = GSS_C_NO_NAME;
|
|
Packit Service |
466431 |
gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
struct mag_conn *mc = NULL;
|
|
Packit Service |
466431 |
uint32_t vtime;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
req_cfg = mag_init_cfg(req);
|
|
Packit Service |
466431 |
cfg = req_cfg->cfg;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!cfg->s4u2self) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"GSSapiImpersonate not On, skipping impersonation.");
|
|
Packit Service |
466431 |
return DECLINED;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
type = ap_auth_type(req);
|
|
Packit Service |
466431 |
if (type && (strcasecmp(type, "GSSAPI") == 0)) {
|
|
Packit Service |
466431 |
/* do not try to impersonate if GSSAPI is handling real auth */
|
|
Packit Service |
466431 |
return DECLINED;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!req->user) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req,
|
|
Packit Service |
466431 |
"Authentication user not found, "
|
|
Packit Service |
466431 |
"skipping impersonation.");
|
|
Packit Service |
466431 |
return DECLINED;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Using user %s for impersonation.", req->user);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!mag_acquire_creds(req, cfg, &gss_mech_krb5_set,
|
|
Packit Service |
466431 |
GSS_C_BOTH, &server_cred, NULL)) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
user_name.value = req->user;
|
|
Packit Service |
466431 |
user_name.length = strlen(user_name.value);
|
|
Packit Service |
466431 |
maj = gss_import_name(&min, &user_name, GSS_C_NT_USER_NAME, &user);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In S4U2Self: gss_import_name()");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_acquire_cred_impersonate_name(&min, server_cred, user,
|
|
Packit Service |
466431 |
GSS_C_INDEFINITE,
|
|
Packit Service |
466431 |
&gss_mech_krb5_set,
|
|
Packit Service |
466431 |
GSS_C_INITIATE, &user_cred,
|
|
Packit Service |
466431 |
NULL, NULL);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In S4U2Self: gss_acquire_cred_impersonate_name()");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* the following exchange is needed to decrypt the ticket and get named
|
|
Packit Service |
466431 |
* attributes as well as check if the ticket is forwardable when
|
|
Packit Service |
466431 |
* delegated credentials are requested */
|
|
Packit Service |
466431 |
maj = mag_context_loop(&min, req, cfg, user_cred, server_cred,
|
|
Packit Service |
466431 |
discard_const(gss_mech_krb5), GSS_C_INDEFINITE,
|
|
Packit Service |
466431 |
&client, &vtime, &delegated_cred);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj))
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->deleg_ccache_dir && delegated_cred == GSS_C_NO_CREDENTIAL) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0, 0,
|
|
Packit Service |
466431 |
"Failed to obtain delegated credentials, "
|
|
Packit Service |
466431 |
"does service have +ok_to_auth_as_delegate?");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc = mag_new_conn_ctx(req->pool);
|
|
Packit Service |
466431 |
mc->auth_type = AUTH_TYPE_IMPERSONATE;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ret = mag_complete(req_cfg, mc, client, mech_type, vtime, delegated_cred);
|
|
Packit Service |
466431 |
if (ret != OK) ret = DECLINED;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
done:
|
|
Packit Service |
466431 |
gss_release_cred(&min, &user_cred);
|
|
Packit Service |
466431 |
gss_release_name(&min, &user);
|
|
Packit Service |
466431 |
gss_release_name(&min, &client);
|
|
Packit Service |
466431 |
gss_release_cred(&min, &server_cred);
|
|
Packit Service |
466431 |
gss_release_cred(&min, &delegated_cred);
|
|
Packit Service |
466431 |
return ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static apr_status_t mag_oid_set_destroy(void *ptr)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
uint32_t min;
|
|
Packit Service |
466431 |
gss_OID_set set = (gss_OID_set)ptr;
|
|
Packit Service |
466431 |
(void)gss_release_oid_set(&min, &set);
|
|
Packit Service |
466431 |
return APR_SUCCESS;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static gss_OID_set mag_get_negotiate_mechs(apr_pool_t *p, gss_OID_set desired)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_OID spnego_oid = discard_const(&gss_mech_spnego);
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
int present = 0;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_test_oid_set_member(&min, spnego_oid, desired, &present);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (present) {
|
|
Packit Service |
466431 |
return desired;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
gss_OID_set set;
|
|
Packit Service |
466431 |
maj = gss_create_empty_oid_set(&min, &set);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
apr_pool_cleanup_register(p, (void *)set,
|
|
Packit Service |
466431 |
mag_oid_set_destroy,
|
|
Packit Service |
466431 |
apr_pool_cleanup_null);
|
|
Packit Service |
466431 |
maj = gss_add_oid_set_member(&min, spnego_oid, &set);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
for (int i = 0; i < desired->count; i++) {
|
|
Packit Service |
466431 |
maj = gss_add_oid_set_member(&min, &desired->elements[i], &set);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
return GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return set;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static int mag_auth(request_rec *req)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
const char *type;
|
|
Packit Service |
466431 |
int auth_type = -1;
|
|
Packit Service |
466431 |
struct mag_req_cfg *req_cfg;
|
|
Packit Service |
466431 |
struct mag_config *cfg;
|
|
Packit Service |
466431 |
const char *auth_header;
|
|
Packit Service |
466431 |
char *auth_header_type;
|
|
Packit Service |
466431 |
int ret = HTTP_UNAUTHORIZED;
|
|
Packit Service |
466431 |
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
|
|
Packit Service |
466431 |
gss_ctx_id_t *pctx;
|
|
Packit Service |
466431 |
gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
gss_buffer_desc ba_user;
|
|
Packit Service |
466431 |
gss_buffer_desc ba_pwd;
|
|
Packit Service |
466431 |
gss_name_t client = GSS_C_NO_NAME;
|
|
Packit Service |
466431 |
gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
|
|
Packit Service |
466431 |
gss_cred_usage_t cred_usage = GSS_C_ACCEPT;
|
|
Packit Service |
466431 |
uint32_t vtime;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
char *reply;
|
|
Packit Service |
466431 |
size_t replen;
|
|
Packit Service |
466431 |
gss_OID mech_type = GSS_C_NO_OID;
|
|
Packit Service |
466431 |
gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
struct mag_conn *mc = NULL;
|
|
Packit Service |
466431 |
int i;
|
|
Packit Service |
466431 |
bool send_nego_header = true;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
type = ap_auth_type(req);
|
|
Packit Service |
466431 |
if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) {
|
|
Packit Service |
466431 |
return DECLINED;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
req_cfg = mag_init_cfg(req);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
cfg = req_cfg->cfg;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if ((req_cfg->desired_mechs == GSS_C_NO_OID_SET) ||
|
|
Packit Service |
466431 |
(req_cfg->desired_mechs->count == 0)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0, 0,
|
|
Packit Service |
466431 |
"List of desired mechs is missing or empty, "
|
|
Packit Service |
466431 |
"can't proceed!");
|
|
Packit Service |
466431 |
return HTTP_UNAUTHORIZED;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"URI: %s, %s main, %s prev", req->uri ?: "no-uri",
|
|
Packit Service |
466431 |
req->main ? "with" : "no", req->prev ? "with" : "no");
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* implicit auth for subrequests if main auth already happened */
|
|
Packit Service |
466431 |
if (!ap_is_initial_req(req)) {
|
|
Packit Service |
466431 |
request_rec *main_req = req;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* Not initial means either a subrequest or an internal redirect */
|
|
Packit Service |
466431 |
while (!ap_is_initial_req(main_req))
|
|
Packit Service |
466431 |
if (main_req->main)
|
|
Packit Service |
466431 |
main_req = main_req->main;
|
|
Packit Service |
466431 |
else
|
|
Packit Service |
466431 |
main_req = main_req->prev;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
type = ap_auth_type(main_req);
|
|
Packit Service |
466431 |
if ((type != NULL) && (strcasecmp(type, "GSSAPI") == 0)) {
|
|
Packit Service |
466431 |
/* warn if the subrequest location and the main request
|
|
Packit Service |
466431 |
* location have different configs */
|
|
Packit Service |
466431 |
if (cfg != ap_get_module_config(main_req->per_dir_config,
|
|
Packit Service |
466431 |
&auth_gssapi_module)) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0,
|
|
Packit Service |
466431 |
req, "Subrequest authentication bypass on "
|
|
Packit Service |
466431 |
"location with different configuration!");
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (main_req->user) {
|
|
Packit Service |
466431 |
apr_table_t *env;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
req->user = apr_pstrdup(req->pool, main_req->user);
|
|
Packit Service |
466431 |
req->ap_auth_type = main_req->ap_auth_type;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
env = ap_get_module_config(main_req->request_config,
|
|
Packit Service |
466431 |
&auth_gssapi_module);
|
|
Packit Service |
466431 |
if (!env) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req,
|
|
Packit Service |
466431 |
"Failed to lookup env table in subrequest");
|
|
Packit Service |
466431 |
} else
|
|
Packit Service |
466431 |
mag_export_req_env(req, env);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return OK;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
|
|
Packit Service |
466431 |
"The main request is tasked to establish the "
|
|
Packit Service |
466431 |
"security context, can't proceed!");
|
|
Packit Service |
466431 |
return HTTP_UNAUTHORIZED;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Subrequest GSSAPI auth with no auth on the main "
|
|
Packit Service |
466431 |
"request. This operation may fail if other "
|
|
Packit Service |
466431 |
"subrequests already established a context or the "
|
|
Packit Service |
466431 |
"mechanism requires multiple roundtrips.");
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* check if admin wants to disable negotiate with this client */
|
|
Packit Service |
466431 |
if (apr_table_get(req->subprocess_env, "gssapi-no-negotiate")) {
|
|
Packit Service |
466431 |
send_nego_header = false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->ssl_only) {
|
|
Packit Service |
466431 |
if (!mag_conn_is_https(req->connection)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_AUTH_NOT_ALLOWED, 0, 0,
|
|
Packit Service |
466431 |
"Not a TLS connection, refusing to authenticate!");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->gss_conn_ctx) {
|
|
Packit Service |
466431 |
mc = (struct mag_conn *)ap_get_module_config(
|
|
Packit Service |
466431 |
req->connection->conn_config,
|
|
Packit Service |
466431 |
&auth_gssapi_module);
|
|
Packit Service |
466431 |
if (!mc) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Failed to retrieve connection context!");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* if available, session always supersedes connection bound data */
|
|
Packit Service |
466431 |
if (req_cfg->use_sessions) {
|
|
Packit Service |
466431 |
mag_check_session(req_cfg, &mc);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
auth_header = apr_table_get(req->headers_in, req_cfg->req_proto);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (mc) {
|
|
Packit Service |
466431 |
if (mc->established &&
|
|
Packit Service |
466431 |
(auth_header == NULL) &&
|
|
Packit Service |
466431 |
(mc->auth_type != AUTH_TYPE_BASIC)) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Already established context found!");
|
|
Packit Service |
466431 |
mag_set_req_data(req, cfg, mc);
|
|
Packit Service |
466431 |
ret = OK;
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
pctx = &mc->ctx;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
/* no preserved mc, create one just for this request */
|
|
Packit Service |
466431 |
mc = mag_new_conn_ctx(req->pool);
|
|
Packit Service |
466431 |
pctx = &ctx;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* We can proceed only if we do have an auth header */
|
|
Packit Service |
466431 |
if (!auth_header) {
|
|
Packit Service |
466431 |
mag_post_info(req, cfg, MAG_NO_AUTH,
|
|
Packit Service |
466431 |
"Client did not send any authentication headers");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
auth_header_type = ap_getword_white(req->pool, &auth_header);
|
|
Packit Service |
466431 |
if (!auth_header_type) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_NO_AUTH, 0, 0,
|
|
Packit Service |
466431 |
"Client sent malformed authentication headers");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* We got auth header, sending auth header would mean re-auth */
|
|
Packit Service |
466431 |
if (cfg->negotiate_once) {
|
|
Packit Service |
466431 |
send_nego_header = false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
for (i = 0; auth_types[i] != NULL; i++) {
|
|
Packit Service |
466431 |
if (strcasecmp(auth_header_type, auth_types[i]) == 0) {
|
|
Packit Service |
466431 |
auth_type = i;
|
|
Packit Service |
466431 |
break;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
switch (auth_type) {
|
|
Packit Service |
466431 |
case AUTH_TYPE_NEGOTIATE:
|
|
Packit Service |
466431 |
if (!parse_auth_header(req->pool, &auth_header, &input)) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
desired_mechs = mag_get_negotiate_mechs(req->pool,
|
|
Packit Service |
466431 |
req_cfg->desired_mechs);
|
|
Packit Service |
466431 |
if (desired_mechs == GSS_C_NO_OID_SET) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Failed to get negotiate_mechs");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
break;
|
|
Packit Service |
466431 |
case AUTH_TYPE_BASIC:
|
|
Packit Service |
466431 |
if (!cfg->use_basic_auth) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ba_pwd.value = ap_pbase64decode(req->pool, auth_header);
|
|
Packit Service |
466431 |
if (!ba_pwd.value) goto done;
|
|
Packit Service |
466431 |
ba_user.value = ap_getword_nulls_nc(req->pool,
|
|
Packit Service |
466431 |
(char **)&ba_pwd.value, ':');
|
|
Packit Service |
466431 |
if (!ba_user.value) goto done;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (((char *)ba_user.value)[0] == '\0' ||
|
|
Packit Service |
466431 |
((char *)ba_pwd.value)[0] == '\0') {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Invalid empty user or password for Basic Auth");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
ba_user.length = strlen(ba_user.value);
|
|
Packit Service |
466431 |
ba_pwd.length = strlen(ba_pwd.value);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (mc->is_preserved && mc->established &&
|
|
Packit Service |
466431 |
mag_basic_check(req_cfg, mc, ba_user, ba_pwd)) {
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"Already established BASIC AUTH context found!");
|
|
Packit Service |
466431 |
mag_set_req_data(req, cfg, mc);
|
|
Packit Service |
466431 |
ret = OK;
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
break;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
case AUTH_TYPE_RAW_NTLM:
|
|
Packit Service |
466431 |
if (!is_mech_allowed(desired_mechs, gss_mech_ntlmssp,
|
|
Packit Service |
466431 |
cfg->gss_conn_ctx)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_AUTH_NOT_ALLOWED, 0, 0,
|
|
Packit Service |
466431 |
"NTLM Authentication is not allowed!");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!parse_auth_header(req->pool, &auth_header, &input)) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
desired_mechs = discard_const(gss_mech_set_ntlmssp);
|
|
Packit Service |
466431 |
if (desired_mechs == GSS_C_NO_OID_SET) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0 ,0,
|
|
Packit Service |
466431 |
"No support for ntlmssp mech");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
break;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
default:
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_NO_AUTH, 0, 0,
|
|
Packit Service |
466431 |
"Client sent unknown authentication headers");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (mc->established) {
|
|
Packit Service |
466431 |
/* if we are re-authenticating make sure the conn context
|
|
Packit Service |
466431 |
* is cleaned up so we do not accidentally reuse an existing
|
|
Packit Service |
466431 |
* established context */
|
|
Packit Service |
466431 |
mag_conn_clear(mc);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc->auth_type = auth_type;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
if (use_s4u2proxy(req_cfg)) {
|
|
Packit Service |
466431 |
cred_usage = GSS_C_BOTH;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (auth_type == AUTH_TYPE_BASIC) {
|
|
rpm-build |
67bb15 |
ret = mag_auth_basic(req_cfg, mc, ba_user, ba_pwd);
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!mag_acquire_creds(req, cfg, desired_mechs,
|
|
Packit Service |
466431 |
cred_usage, &acquired_cred, NULL)) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (auth_type == AUTH_TYPE_NEGOTIATE &&
|
|
Packit Service |
466431 |
cfg->allowed_mechs != GSS_C_NO_OID_SET) {
|
|
Packit Service |
466431 |
maj = gss_set_neg_mechs(&min, acquired_cred, cfg->allowed_mechs);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In Negotiate Auth: gss_set_neg_mechs() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_accept_sec_context(&min, pctx, acquired_cred,
|
|
Packit Service |
466431 |
&input, GSS_C_NO_CHANNEL_BINDINGS,
|
|
Packit Service |
466431 |
&client, &mech_type, &output, NULL, &vtime,
|
|
Packit Service |
466431 |
&delegated_cred);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"In Negotiate Auth: gss_accept_sec_context() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
} else if (maj == GSS_S_CONTINUE_NEEDED) {
|
|
Packit Service |
466431 |
if (!mc->is_preserved) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0, 0,
|
|
Packit Service |
466431 |
"Mechanism needs continuation but neither "
|
|
Packit Service |
466431 |
"GssapiConnectionBound nor "
|
|
Packit Service |
466431 |
"GssapiUseSessions are configured");
|
|
Packit Service |
466431 |
gss_release_buffer(&min, &output);
|
|
Packit Service |
466431 |
output.length = 0;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
/* auth not complete send token and wait next packet */
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ret = mag_complete(req_cfg, mc, client, mech_type, vtime, delegated_cred);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (ret == OK && req_cfg->send_persist)
|
|
Packit Service |
466431 |
apr_table_set(req->err_headers_out, "Persistent-Auth",
|
|
Packit Service |
466431 |
cfg->gss_conn_ctx ? "true" : "false");
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
done:
|
|
Packit Service |
466431 |
if ((auth_type != AUTH_TYPE_BASIC) && (output.length != 0)) {
|
|
Packit Service |
466431 |
int prefixlen = strlen(mag_str_auth_type(auth_type)) + 1;
|
|
Packit Service |
466431 |
replen = apr_base64_encode_len(output.length) + 1;
|
|
Packit Service |
466431 |
reply = apr_pcalloc(req->pool, prefixlen + replen);
|
|
Packit Service |
466431 |
if (reply) {
|
|
Packit Service |
466431 |
memcpy(reply, mag_str_auth_type(auth_type), prefixlen - 1);
|
|
Packit Service |
466431 |
reply[prefixlen - 1] = ' ';
|
|
Packit Service |
466431 |
apr_base64_encode(&reply[prefixlen], output.value, output.length);
|
|
Packit Service |
466431 |
apr_table_add(req->err_headers_out, req_cfg->rep_proto, reply);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else if (ret == HTTP_UNAUTHORIZED) {
|
|
Packit Service |
466431 |
if (send_nego_header) {
|
|
Packit Service |
466431 |
apr_table_add(req->err_headers_out,
|
|
Packit Service |
466431 |
req_cfg->rep_proto, "Negotiate");
|
|
Packit Service |
466431 |
if (is_mech_allowed(desired_mechs, gss_mech_ntlmssp,
|
|
Packit Service |
466431 |
cfg->gss_conn_ctx)) {
|
|
Packit Service |
466431 |
apr_table_add(req->err_headers_out, req_cfg->rep_proto,
|
|
Packit Service |
466431 |
"NTLM");
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (cfg->use_basic_auth) {
|
|
Packit Service |
466431 |
apr_table_add(req->err_headers_out, req_cfg->rep_proto,
|
|
Packit Service |
466431 |
apr_psprintf(req->pool, "Basic realm=\"%s\"",
|
|
Packit Service |
466431 |
ap_auth_name(req)));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (ctx != GSS_C_NO_CONTEXT)
|
|
Packit Service |
466431 |
gss_delete_sec_context(&min, &ctx, GSS_C_NO_BUFFER);
|
|
Packit Service |
466431 |
gss_release_cred(&min, &acquired_cred);
|
|
Packit Service |
466431 |
gss_release_cred(&min, &delegated_cred);
|
|
Packit Service |
466431 |
gss_release_buffer(&min, &output);
|
|
Packit Service |
466431 |
gss_release_name(&min, &client);
|
|
Packit Service |
466431 |
return ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static int mag_complete(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
|
|
Packit Service |
466431 |
gss_name_t client, gss_OID mech_type,
|
|
Packit Service |
466431 |
uint32_t vtime, gss_cred_id_t delegated_cred)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_buffer_desc lname = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
|
|
Packit Service |
466431 |
struct mag_config *cfg = req_cfg->cfg;
|
|
Packit Service |
466431 |
request_rec *req = req_cfg->req;
|
|
Packit Service |
466431 |
int r, ret = HTTP_UNAUTHORIZED;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_display_name(&min, client, &name, NULL);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"gss_display_name() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc->gss_name = apr_pstrndup(req->pool, name.value, name.length);
|
|
Packit Service |
466431 |
if (vtime == GSS_C_INDEFINITE || vtime < MIN_SESS_EXP_TIME) {
|
|
Packit Service |
466431 |
vtime = MIN_SESS_EXP_TIME;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
mc->expiration = time(NULL) + vtime;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mag_get_name_attributes(req, cfg, client, mc);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
r = mag_verify_name_attributes(cfg->required_na_expr,
|
|
Packit Service |
466431 |
mc->required_name_attrs,
|
|
Packit Service |
466431 |
mc->required_name_vals);
|
|
Packit Service |
466431 |
if (r == -1) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_INTERNAL, 0, 0,
|
|
Packit Service |
466431 |
"Error verifying name attributes!");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
} else if (r == 0) {
|
|
Packit Service |
466431 |
ret = HTTP_FORBIDDEN;
|
|
Packit Service |
466431 |
mag_set_req_attr_fail(req, cfg, mc);
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
if (cfg->deleg_ccache_dir &&
|
|
Packit Service |
466431 |
delegated_cred != GSS_C_NO_CREDENTIAL) {
|
|
Packit Service |
466431 |
char *ccache_path;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc->ccname = 0;
|
|
Packit Service |
466431 |
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
|
|
Packit Service |
466431 |
"requester: %s", mc->gss_name);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ccache_path = get_ccache_name(req, cfg->deleg_ccache_dir, mc->gss_name,
|
|
Packit Service |
466431 |
cfg->deleg_ccache_unique, mc);
|
|
Packit Service |
466431 |
if (ccache_path == NULL) {
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mag_store_deleg_creds(req, ccache_path, delegated_cred);
|
|
Packit Service |
466431 |
mc->delegated = true;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!req_cfg->use_sessions && cfg->deleg_ccache_unique) {
|
|
Packit Service |
466431 |
/* queue removing ccache to avoid littering filesystem */
|
|
Packit Service |
466431 |
apr_pool_cleanup_register(mc->pool, ccache_path,
|
|
Packit Service |
466431 |
(int (*)(void *)) unlink,
|
|
Packit Service |
466431 |
apr_pool_cleanup_null);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* extract filename from full path */
|
|
Packit Service |
466431 |
mc->ccname = strrchr(ccache_path, '/') + 1;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->map_to_local) {
|
|
Packit Service |
466431 |
maj = gss_localname(&min, client, mech_type, &lname);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
mag_post_error(req, cfg, MAG_GSS_ERR, maj, min,
|
|
Packit Service |
466431 |
"gss_localname() failed");
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
mc->user_name = apr_pstrndup(mc->pool, lname.value, lname.length);
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
mc->user_name = apr_pstrdup(mc->pool, mc->gss_name);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
mc->established = true;
|
|
Packit Service |
466431 |
if (req_cfg->use_sessions) {
|
|
Packit Service |
466431 |
mag_attempt_session(req_cfg, mc);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
/* Now set request data and env vars */
|
|
Packit Service |
466431 |
mag_set_req_data(req, cfg, mc);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ret = OK;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
done:
|
|
Packit Service |
466431 |
gss_release_buffer(&min, &name);
|
|
Packit Service |
466431 |
gss_release_buffer(&min, &lname);
|
|
Packit Service |
466431 |
return ret;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void *mag_create_dir_config(apr_pool_t *p, char *dir)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
cfg = (struct mag_config *)apr_pcalloc(p, sizeof(struct mag_config));
|
|
Packit Service |
466431 |
cfg->pool = p;
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
cfg->ccname_envvar = "KRB5CCNAME";
|
|
Packit Service |
466431 |
#endif
|
|
rpm-build |
8f3b0f |
cfg->basic_timeout = 300;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return cfg;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_ssl_only(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->ssl_only = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_map_to_local(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->map_to_local = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_conn_ctx(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->gss_conn_ctx = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_send_persist(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->send_persist = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->use_sessions = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
static const char *mag_use_s4u2p(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->use_s4u2proxy = on ? true : false;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_deleg_ccache_unique(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
cfg->deleg_ccache_unique = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#define SESS_KEYS_TOT_LEN 32
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void create_sess_key_file(cmd_parms *parms, const char *name)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
apr_status_t ret;
|
|
Packit Service |
466431 |
apr_file_t *fd = NULL;
|
|
Packit Service |
466431 |
unsigned char keys[SESS_KEYS_TOT_LEN];
|
|
Packit Service |
466431 |
apr_size_t bw;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ret = apr_file_open(&fd, name,
|
|
Packit Service |
466431 |
APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL,
|
|
Packit Service |
466431 |
APR_FPROT_UREAD | APR_FPROT_UWRITE, parms->temp_pool);
|
|
Packit Service |
466431 |
if (ret != APR_SUCCESS) {
|
|
Packit Service |
466431 |
char err[256];
|
|
Packit Service |
466431 |
apr_strerror(ret, err, sizeof(err));
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Failed to create key file %s: %s", name, err);
|
|
Packit Service |
466431 |
return;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
ret = apr_generate_random_bytes(keys, SESS_KEYS_TOT_LEN);
|
|
Packit Service |
466431 |
if (ret != OK) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Failed to generate random sealing key!");
|
|
Packit Service |
466431 |
ret = APR_INCOMPLETE;
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
ret = apr_file_write_full(fd, keys, SESS_KEYS_TOT_LEN, &bw;;
|
|
Packit Service |
466431 |
if ((ret != APR_SUCCESS) || (bw != SESS_KEYS_TOT_LEN)) {
|
|
Packit Service |
466431 |
char err[256];
|
|
Packit Service |
466431 |
apr_strerror(ret, err, sizeof(err));
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Failed to store key in %s: %s", name, err);
|
|
Packit Service |
466431 |
ret = APR_INCOMPLETE;
|
|
Packit Service |
466431 |
goto done;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
done:
|
|
Packit Service |
466431 |
apr_file_close(fd);
|
|
Packit Service |
466431 |
if (ret != APR_SUCCESS) apr_file_remove(name, parms->temp_pool);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
struct databuf keys;
|
|
Packit Service |
466431 |
unsigned char *val;
|
|
Packit Service |
466431 |
apr_status_t rc;
|
|
Packit Service |
466431 |
int l;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (strncmp(w, "key:", 4) == 0) {
|
|
Packit Service |
466431 |
const char *k = w + 4;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
l = apr_base64_decode_len(k);
|
|
Packit Service |
466431 |
val = apr_palloc(parms->temp_pool, l);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
keys.length = (int)apr_base64_decode_binary(val, k);
|
|
Packit Service |
466431 |
keys.value = (unsigned char *)val;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (keys.length != SESS_KEYS_TOT_LEN) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid key length, expected 32 got %d",
|
|
Packit Service |
466431 |
keys.length);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else if (strncmp(w, "file:", 5) == 0) {
|
|
Packit Service |
466431 |
apr_status_t ret;
|
|
Packit Service |
466431 |
apr_file_t *fd = NULL;
|
|
Packit Service |
466431 |
apr_int32_t ronly = APR_FOPEN_READ;
|
|
Packit Service |
466431 |
const char *fname;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
keys.length = SESS_KEYS_TOT_LEN;
|
|
Packit Service |
466431 |
keys.value = apr_palloc(parms->temp_pool, keys.length);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
fname = w + 5;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ret = apr_file_open(&fd, fname, ronly, 0, parms->temp_pool);
|
|
Packit Service |
466431 |
if (APR_STATUS_IS_ENOENT(ret)) {
|
|
Packit Service |
466431 |
create_sess_key_file(parms, fname);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
ret = apr_file_open(&fd, fname, ronly, 0, parms->temp_pool);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (ret == APR_SUCCESS) {
|
|
Packit Service |
466431 |
apr_size_t br;
|
|
Packit Service |
466431 |
ret = apr_file_read_full(fd, keys.value, keys.length, &br);
|
|
Packit Service |
466431 |
apr_file_close(fd);
|
|
Packit Service |
466431 |
if ((ret != APR_SUCCESS) || (br != keys.length)) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Failed to read sealing key from %s!", fname);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Failed to open key file %s", fname);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid key format, unexpected prefix in %s'", w);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &keys);
|
|
Packit Service |
466431 |
if (rc != OK) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Failed to import sealing key!");
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#define MAX_CRED_OPTIONS 10
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
gss_key_value_element_desc *elements;
|
|
Packit Service |
466431 |
uint32_t count;
|
|
Packit Service |
466431 |
size_t size;
|
|
Packit Service |
466431 |
const char *p;
|
|
Packit Service |
466431 |
char *value;
|
|
Packit Service |
466431 |
char *key;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
p = strchr(w, ':');
|
|
Packit Service |
466431 |
if (!p) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"%s [%s]", "Invalid syntax for GssapiCredStore option", w);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
key = apr_pstrndup(parms->pool, w, (p-w));
|
|
Packit Service |
466431 |
value = apr_pstrdup(parms->pool, p + 1);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!cfg->cred_store) {
|
|
Packit Service |
466431 |
cfg->cred_store = apr_pcalloc(parms->pool,
|
|
Packit Service |
466431 |
sizeof(gss_key_value_set_desc));
|
|
Packit Service |
466431 |
size = sizeof(gss_key_value_element_desc) * MAX_CRED_OPTIONS;
|
|
Packit Service |
466431 |
cfg->cred_store->elements = apr_palloc(parms->pool, size);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
elements = cfg->cred_store->elements;
|
|
Packit Service |
466431 |
count = cfg->cred_store->count;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (count >= MAX_CRED_OPTIONS) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Too many GssapiCredStore options (MAX: %d)",
|
|
Packit Service |
466431 |
MAX_CRED_OPTIONS);
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
cfg->cred_store->count++;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
elements[count].key = key;
|
|
Packit Service |
466431 |
elements[count].value = value;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *value)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
cfg->deleg_ccache_dir = apr_pstrdup(parms->pool, value);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
#define CCMODE "mode:"
|
|
Packit Service |
466431 |
#define CCUID "uid:"
|
|
Packit Service |
466431 |
#define CCGID "gid:"
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (strncmp(w, CCMODE, sizeof(CCMODE) - 1) == 0) {
|
|
Packit Service |
466431 |
const char *p = w + sizeof(CCMODE) -1;
|
|
Packit Service |
466431 |
errno = 0;
|
|
Packit Service |
466431 |
/* mode is traditionally represented in octal, but the actual
|
|
Packit Service |
466431 |
* permission bit are using the 3 least significant bit of each quartet
|
|
Packit Service |
466431 |
* so effectively if we read an octal number as hex we get the correct
|
|
Packit Service |
466431 |
* mode bits */
|
|
Packit Service |
466431 |
cfg->deleg_ccache_mode = strtol(p, NULL, 16);
|
|
Packit Service |
466431 |
if (errno != 0) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid GssapiDelegCcachePerms mode value [%s]", p);
|
|
Packit Service |
466431 |
/* reset to the default */
|
|
Packit Service |
466431 |
cfg->deleg_ccache_mode = 0;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else if (strncmp(w, CCUID, sizeof(CCUID) - 1) == 0) {
|
|
Packit Service |
466431 |
const char *p = w + sizeof(CCUID) - 1;
|
|
Packit Service |
466431 |
errno = 0;
|
|
Packit Service |
466431 |
if (isdigit(*p)) {
|
|
Packit Service |
466431 |
char *endptr;
|
|
Packit Service |
466431 |
cfg->deleg_ccache_uid = strtol(p, &endptr, 0);
|
|
Packit Service |
466431 |
if (errno != 0 || (endptr && *endptr != '\0')) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid GssapiDelegCcachePerms uid value [%s]",
|
|
Packit Service |
466431 |
p);
|
|
Packit Service |
466431 |
/* reset to the default */
|
|
Packit Service |
466431 |
cfg->deleg_ccache_uid = 0;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
int ret = mag_get_user_uid(p, &cfg->deleg_ccache_uid);
|
|
Packit Service |
466431 |
if (ret != 0) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid GssapiDelegCcachePerms uid value [%s](%s)",
|
|
Packit Service |
466431 |
p, strerror(ret));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else if (strncmp(w, CCGID, sizeof(CCGID) - 1) == 0) {
|
|
Packit Service |
466431 |
const char *p = w + sizeof(CCGID) - 1;
|
|
Packit Service |
466431 |
errno = 0;
|
|
Packit Service |
466431 |
if (isdigit(*p)) {
|
|
Packit Service |
466431 |
char *endptr;
|
|
Packit Service |
466431 |
cfg->deleg_ccache_gid = strtol(p, &endptr, 0);
|
|
Packit Service |
466431 |
if (errno != 0 || (endptr && *endptr != '\0')) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid GssapiDelegCcachePerms gid value [%s]",
|
|
Packit Service |
466431 |
p);
|
|
Packit Service |
466431 |
/* reset to the default */
|
|
Packit Service |
466431 |
cfg->deleg_ccache_gid = 0;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
int ret = mag_get_group_gid(p, &cfg->deleg_ccache_gid);
|
|
Packit Service |
466431 |
if (ret != 0) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid GssapiDelegCcachePerms gid value [%s](%s)",
|
|
Packit Service |
466431 |
p, strerror(ret));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid GssapiDelegCcachePerms directive [%s]", w);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_use_basic_auth(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
cfg->use_basic_auth = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static bool mag_list_of_mechs(cmd_parms *parms, gss_OID_set *oidset,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
gss_buffer_desc buf = { 0 };
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
gss_OID_set set;
|
|
Packit Service |
466431 |
gss_OID oid;
|
|
Packit Service |
466431 |
bool release_oid = false;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (NULL == *oidset) {
|
|
Packit Service |
466431 |
maj = gss_create_empty_oid_set(&min, &set);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"gss_create_empty_oid_set() failed.");
|
|
Packit Service |
466431 |
*oidset = GSS_C_NO_OID_SET;
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
/* register in the pool so it can be released once the server
|
|
Packit Service |
466431 |
* winds down */
|
|
Packit Service |
466431 |
apr_pool_cleanup_register(parms->pool, (void *)set,
|
|
Packit Service |
466431 |
mag_oid_set_destroy,
|
|
Packit Service |
466431 |
apr_pool_cleanup_null);
|
|
Packit Service |
466431 |
*oidset = set;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
set = *oidset;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (strcmp(w, "krb5") == 0) {
|
|
Packit Service |
466431 |
oid = discard_const(gss_mech_krb5);
|
|
Packit Service |
466431 |
} else if (strcmp(w, "iakerb") == 0) {
|
|
Packit Service |
466431 |
oid = discard_const(gss_mech_iakerb);
|
|
Packit Service |
466431 |
} else if (strcmp(w, "ntlmssp") == 0) {
|
|
Packit Service |
466431 |
oid = discard_const(gss_mech_ntlmssp);
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
buf.value = discard_const(w);
|
|
Packit Service |
466431 |
buf.length = strlen(w);
|
|
Packit Service |
466431 |
maj = gss_str_to_oid(&min, &buf, &oid;;
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Unrecognized GSSAPI Mechanism: [%s]", w);
|
|
Packit Service |
466431 |
return false;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
release_oid = true;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
maj = gss_add_oid_set_member(&min, oid, &set);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"gss_add_oid_set_member() failed for [%s].", w);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (release_oid) {
|
|
Packit Service |
466431 |
(void)gss_release_oid(&min, &oid;;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return true;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_allow_mech(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!mag_list_of_mechs(parms, &cfg->allowed_mechs, w))
|
|
Packit Service |
466431 |
return "Failed to apply GssapiAllowedMech directive";
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_negotiate_once(cmd_parms *parms, void *mconfig, int on)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
cfg->negotiate_once = on ? true : false;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static apr_status_t mag_name_attrs_cleanup(void *data)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)data;
|
|
Packit Service |
466431 |
free(cfg->name_attributes);
|
|
Packit Service |
466431 |
cfg->name_attributes = NULL;
|
|
Packit Service |
466431 |
return 0;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_name_attrs(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
void *tmp_na;
|
|
Packit Service |
466431 |
size_t size = 0;
|
|
Packit Service |
466431 |
char *p;
|
|
Packit Service |
466431 |
int c;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!cfg->name_attributes) {
|
|
Packit Service |
466431 |
size = sizeof(struct mag_name_attributes)
|
|
Packit Service |
466431 |
+ (sizeof(struct mag_na_map) * 16);
|
|
Packit Service |
466431 |
} else if (cfg->name_attributes->map_count % 16 == 0) {
|
|
Packit Service |
466431 |
size = sizeof(struct mag_name_attributes)
|
|
Packit Service |
466431 |
+ (sizeof(struct mag_na_map)
|
|
Packit Service |
466431 |
* (cfg->name_attributes->map_count + 16));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
if (size) {
|
|
Packit Service |
466431 |
tmp_na = realloc(cfg->name_attributes, size);
|
|
Packit Service |
466431 |
if (!tmp_na) apr_pool_abort_get(cfg->pool)(ENOMEM);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (cfg->name_attributes) {
|
|
Packit Service |
466431 |
size_t empty = (sizeof(struct mag_na_map) * 16);
|
|
Packit Service |
466431 |
memset(tmp_na + size - empty, 0, empty);
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
memset(tmp_na, 0, size);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
cfg->name_attributes = (struct mag_name_attributes *)tmp_na;
|
|
Packit Service |
466431 |
apr_pool_userdata_setn(cfg, GSS_NAME_ATTR_USERDATA,
|
|
Packit Service |
466431 |
mag_name_attrs_cleanup, cfg->pool);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
p = strchr(w, ' ');
|
|
Packit Service |
466431 |
if (p == NULL) {
|
|
Packit Service |
466431 |
if (strcmp(w, "json") == 0) {
|
|
Packit Service |
466431 |
cfg->name_attributes->output_json = true;
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"Invalid Name Attributes value [%s].", w);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
c = cfg->name_attributes->map_count;
|
|
Packit Service |
466431 |
cfg->name_attributes->map[c].env_name = apr_pstrndup(cfg->pool, w, p-w);
|
|
Packit Service |
466431 |
p++;
|
|
Packit Service |
466431 |
cfg->name_attributes->map[c].attr_name = apr_pstrdup(cfg->pool, p);
|
|
Packit Service |
466431 |
cfg->name_attributes->map_count += 1;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *required_name_attrs(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!mag_check_name_attr_expr(w)) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
|
|
Packit Service |
466431 |
"syntax error in [%s].", w);
|
|
Packit Service |
466431 |
return "Failed to verify required name attribute expression";
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
cfg->required_na_expr = apr_pstrdup(cfg->pool, w);
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_basic_auth_mechs(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (!mag_list_of_mechs(parms, &cfg->basic_mechs, w))
|
|
Packit Service |
466431 |
return "Failed to apply GssapiBasicAuthMech directive";
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const char *mag_acceptor_name(cmd_parms *parms, void *mconfig,
|
|
Packit Service |
466431 |
const char *w)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
Packit Service |
466431 |
gss_buffer_desc bufnam = { strlen(w), (void *)w };
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
if (strcmp(w, "{HOSTNAME}") == 0) {
|
|
Packit Service |
466431 |
cfg->acceptor_name_from_req = true;
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_import_name(&min, &bufnam, GSS_C_NT_HOSTBASED_SERVICE,
|
|
Packit Service |
466431 |
&cfg->acceptor_name);
|
|
Packit Service |
466431 |
if (GSS_ERROR(maj)) {
|
|
Packit Service |
466431 |
return apr_psprintf(parms->pool, "[%s] Failed to import name '%s' %s",
|
|
Packit Service |
466431 |
parms->cmd->name, w,
|
|
Packit Service |
466431 |
mag_error(parms->pool, "", maj, min));
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return NULL;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
rpm-build |
8f3b0f |
static const char *mag_basic_timeout(cmd_parms *parms, void *mconfig,
|
|
rpm-build |
8f3b0f |
const char *w)
|
|
rpm-build |
8f3b0f |
{
|
|
rpm-build |
8f3b0f |
struct mag_config *cfg = (struct mag_config *)mconfig;
|
|
rpm-build |
8f3b0f |
unsigned long int value;
|
|
rpm-build |
8f3b0f |
|
|
rpm-build |
8f3b0f |
value = strtoul(w, NULL, 10);
|
|
rpm-build |
8f3b0f |
if (value >= UINT32_MAX) {
|
|
rpm-build |
8f3b0f |
cfg->basic_timeout = GSS_C_INDEFINITE;
|
|
rpm-build |
8f3b0f |
return NULL;
|
|
rpm-build |
8f3b0f |
}
|
|
rpm-build |
8f3b0f |
cfg->basic_timeout = value;
|
|
rpm-build |
8f3b0f |
return NULL;
|
|
rpm-build |
8f3b0f |
}
|
|
rpm-build |
8f3b0f |
|
|
Packit Service |
466431 |
static void *mag_create_server_config(apr_pool_t *p, server_rec *s)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
struct mag_server_config *scfg;
|
|
Packit Service |
466431 |
uint32_t maj, min;
|
|
Packit Service |
466431 |
apr_status_t rc;
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
scfg = apr_pcalloc(p, sizeof(struct mag_server_config));
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
maj = gss_indicate_mechs(&min, &scfg->default_mechs);
|
|
Packit Service |
466431 |
if (maj != GSS_S_COMPLETE) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
|
|
Packit Service |
466431 |
"gss_indicate_mechs() failed");
|
|
Packit Service |
466431 |
} else {
|
|
Packit Service |
466431 |
/* Register the set in pool */
|
|
Packit Service |
466431 |
apr_pool_cleanup_register(p, (void *)scfg->default_mechs,
|
|
Packit Service |
466431 |
mag_oid_set_destroy, apr_pool_cleanup_null);
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
rc = SEAL_KEY_CREATE(p, &scfg->mag_skey, NULL);
|
|
Packit Service |
466431 |
if (rc != OK) {
|
|
Packit Service |
466431 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
|
|
Packit Service |
466431 |
"Failed to generate random sealing key!");
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
return scfg;
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static const command_rec mag_commands[] = {
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiSSLonly", mag_ssl_only, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Work only if connection is SSL Secured"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiLocalName", mag_map_to_local, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Translate principals to local names"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiConnectionBound", mag_conn_ctx, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Authentication is bound to the TCP connection"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiSignalPersistentAuth", mag_send_persist, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Send Persitent-Auth header according to connection bound"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiUseSessions", mag_use_sess, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Authentication uses mod_sessions to hold status"),
|
|
Packit Service |
466431 |
AP_INIT_RAW_ARGS("GssapiSessionKey", mag_sess_key, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Key Used to seal session data."),
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiUseS4U2Proxy", mag_use_s4u2p, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Initializes credentials for s4u2proxy usage"),
|
|
Packit Service |
466431 |
AP_INIT_ITERATE("GssapiCredStore", mag_cred_store, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Credential Store"),
|
|
Packit Service |
466431 |
AP_INIT_RAW_ARGS("GssapiDelegCcacheDir", mag_deleg_ccache_dir, NULL,
|
|
Packit Service |
466431 |
OR_AUTHCFG, "Directory to store delegated credentials"),
|
|
Packit Service |
466431 |
AP_INIT_ITERATE("GssapiDelegCcachePerms", mag_deleg_ccache_perms, NULL,
|
|
Packit Service |
466431 |
OR_AUTHCFG, "Permissions to assign to Ccache files"),
|
|
Packit Service |
466431 |
AP_INIT_TAKE1("GssapiDelegCcacheEnvVar", ap_set_string_slot,
|
|
Packit Service |
466431 |
(void *)APR_OFFSETOF(struct mag_config, ccname_envvar),
|
|
Packit Service |
466431 |
OR_AUTHCFG, "Environment variable to receive ccache name"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiDelegCcacheUnique", mag_deleg_ccache_unique, NULL,
|
|
Packit Service |
466431 |
OR_AUTHCFG, "Use unique ccaches for delgation"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiImpersonate", ap_set_flag_slot,
|
|
Packit Service |
466431 |
(void *)APR_OFFSETOF(struct mag_config, s4u2self), OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Do impersonation call (S4U2Self) "
|
|
Packit Service |
466431 |
"based on already authentication username"),
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiBasicAuth", mag_use_basic_auth, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Allows use of Basic Auth for authentication"),
|
|
Packit Service |
466431 |
AP_INIT_ITERATE("GssapiBasicAuthMech", mag_basic_auth_mechs, NULL,
|
|
Packit Service |
466431 |
OR_AUTHCFG, "Mechanisms to use for basic auth"),
|
|
Packit Service |
466431 |
AP_INIT_ITERATE("GssapiAllowedMech", mag_allow_mech, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Allowed Mechanisms"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiNegotiateOnce", mag_negotiate_once, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Don't resend negotiate header on negotiate failure"),
|
|
Packit Service |
466431 |
AP_INIT_RAW_ARGS("GssapiNameAttributes", mag_name_attrs, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Name Attributes to be exported as environ variables"),
|
|
Packit Service |
466431 |
AP_INIT_RAW_ARGS("GssapiRequiredNameAttributes", required_name_attrs, NULL,
|
|
Packit Service |
466431 |
OR_AUTHCFG, "Name Attributes required to be present"),
|
|
Packit Service |
466431 |
AP_INIT_FLAG("GssapiPublishErrors", ap_set_flag_slot,
|
|
Packit Service |
466431 |
(void *)APR_OFFSETOF(struct mag_config, enverrs), OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Publish GSSAPI Errors in Envionment Variables"),
|
|
Packit Service |
466431 |
AP_INIT_RAW_ARGS("GssapiAcceptorName", mag_acceptor_name, NULL, OR_AUTHCFG,
|
|
Packit Service |
466431 |
"Name of the acceptor credentials."),
|
|
rpm-build |
8f3b0f |
AP_INIT_TAKE1("GssapiBasicTicketTimeout", mag_basic_timeout, NULL,
|
|
rpm-build |
8f3b0f |
OR_AUTHCFG, "Ticket Validity Timeout with Basic Auth."),
|
|
Packit Service |
466431 |
{ NULL }
|
|
Packit Service |
466431 |
};
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
static void
|
|
Packit Service |
466431 |
mag_register_hooks(apr_pool_t *p)
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
#ifdef AP_AUTH_INTERNAL_PER_CONF
|
|
Packit Service |
466431 |
ap_hook_check_authn(mag_auth, NULL, NULL, APR_HOOK_MIDDLE,
|
|
Packit Service |
466431 |
AP_AUTH_INTERNAL_PER_CONF);
|
|
Packit Service |
466431 |
#else
|
|
Packit Service |
466431 |
ap_hook_check_user_id(mag_auth, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
ap_hook_post_config(mag_post_config, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
466431 |
ap_hook_pre_connection(mag_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
466431 |
#ifdef HAVE_CRED_STORE
|
|
Packit Service |
466431 |
ap_hook_fixups(mag_s4u2self, NULL, NULL, APR_HOOK_MIDDLE);
|
|
Packit Service |
466431 |
#endif
|
|
Packit Service |
466431 |
}
|
|
Packit Service |
466431 |
|
|
Packit Service |
466431 |
module AP_MODULE_DECLARE_DATA auth_gssapi_module =
|
|
Packit Service |
466431 |
{
|
|
Packit Service |
466431 |
STANDARD20_MODULE_STUFF,
|
|
Packit Service |
466431 |
mag_create_dir_config,
|
|
Packit Service |
466431 |
NULL,
|
|
Packit Service |
466431 |
mag_create_server_config,
|
|
Packit Service |
466431 |
NULL,
|
|
Packit Service |
466431 |
mag_commands,
|
|
Packit Service |
466431 |
mag_register_hooks
|
|
Packit Service |
466431 |
};
|