Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,23 @@ an additional message that provides more context.

- **Enable with:** GssapiPublishErrors On
- **Default:** GssapiPublishErrors Off


### GssapiAcceptorName

This option is used to force the server to accept only for a specific name.

This allows, for example to select to use a specific credential when multiple
keys are provided in a keytab.

Note: By default no name is set and any name in a keytab or mechanism specific
acceptor credential will be allowed.

Note: Global gssapi options set in krb5.conf like 'ignore_acceptor_hostname'
may affect the ability to restrict names.

Note: The GSS_C_NT_HOSTBASED_SERVICE format is used for names (see example).

#### Example
GssapiAcceptorName HTTP@www.example.com

4 changes: 2 additions & 2 deletions src/environ.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static bool mag_get_name_attr(request_rec *req,
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
"gss_get_name_attribute() failed on %.*s%s",
(int)attr->name.length, (char *)attr->name.value,
mag_error(req, "", maj, min));
mag_error(req->pool, "", maj, min));
return false;
}

Expand Down Expand Up @@ -209,7 +209,7 @@ void mag_get_name_attributes(request_rec *req, struct mag_config *cfg,

maj = gss_inquire_name(&min, name, NULL, NULL, &attrs);
if (GSS_ERROR(maj)) {
error = mag_error(req, "gss_inquire_name() failed", maj, min);
error = mag_error(req->pool, "gss_inquire_name() failed", maj, min);
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", error);
apr_table_set(mc->env, "GSS_NAME_ATTR_ERROR", error);
return;
Expand Down
44 changes: 32 additions & 12 deletions src/mod_auth_gssapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module AP_MODULE_DECLARE_DATA auth_gssapi_module;

APLOG_USE_MODULE(auth_gssapi);

static char *mag_status(request_rec *req, int type, uint32_t err)
static char *mag_status(apr_pool_t *pool, int type, uint32_t err)
{
uint32_t maj_ret, min_ret;
gss_buffer_desc text;
Expand All @@ -47,25 +47,25 @@ static char *mag_status(request_rec *req, int type, uint32_t err)

len = text.length;
if (msg_ret) {
msg_ret = apr_psprintf(req->pool, "%s, %*s",
msg_ret = apr_psprintf(pool, "%s, %*s",
msg_ret, len, (char *)text.value);
} else {
msg_ret = apr_psprintf(req->pool, "%*s", len, (char *)text.value);
msg_ret = apr_psprintf(pool, "%*s", len, (char *)text.value);
}
gss_release_buffer(&min_ret, &text);
} while (msg_ctx != 0);

return msg_ret;
}

char *mag_error(request_rec *req, const char *msg, uint32_t maj, uint32_t min)
char *mag_error(apr_pool_t *pool, const char *msg, uint32_t maj, uint32_t min)
{
char *msg_maj;
char *msg_min;

msg_maj = mag_status(req, GSS_C_GSS_CODE, maj);
msg_min = mag_status(req, GSS_C_MECH_CODE, min);
return apr_psprintf(req->pool, "%s: [%s (%s)]", msg, msg_maj, msg_min);
msg_maj = mag_status(pool, GSS_C_GSS_CODE, maj);
msg_min = mag_status(pool, GSS_C_MECH_CODE, min);
return apr_psprintf(pool, "%s: [%s (%s)]", msg, msg_maj, msg_min);
}

enum mag_err_code {
Expand Down Expand Up @@ -98,7 +98,7 @@ static void mag_post_error(request_rec *req, struct mag_config *cfg,
const char *text = NULL;

if (maj)
text = mag_error(req, msg, maj, min);
text = mag_error(req->pool, msg, maj, min);

if (cfg->enverrs)
mag_publish_error(req, maj, min, text ? text : msg, mag_err_text(err));
Expand Down Expand Up @@ -189,11 +189,11 @@ static bool mag_acquire_creds(request_rec *req,
#ifdef HAVE_CRED_STORE
gss_const_key_value_set_t store = cfg->cred_store;

maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
maj = gss_acquire_cred_from(&min, cfg->acceptor_name, GSS_C_INDEFINITE,
desired_mechs, cred_usage, store, creds,
actual_mechs, NULL);
#else
maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
maj = gss_acquire_cred(&min, cfg->acceptor_name, GSS_C_INDEFINITE,
desired_mechs, cred_usage, creds,
actual_mechs, NULL);
#endif
Expand Down Expand Up @@ -288,7 +288,7 @@ static void mag_store_deleg_creds(request_rec *req, const char *ccname,
GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
if (GSS_ERROR(maj)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
mag_error(req, "failed to store delegated creds",
mag_error(req->pool, "failed to store delegated creds",
maj, min));
}
}
Expand Down Expand Up @@ -598,7 +598,7 @@ static bool mag_auth_basic(request_rec *req,
if (maj != GSS_S_COMPLETE) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req,
"Failed to restore per-thread ccache, %s",
mag_error(req, "gss_krb5_ccache_name() "
mag_error(req->pool, "gss_krb5_ccache_name() "
"failed", maj, min));
}
}
Expand Down Expand Up @@ -1706,6 +1706,24 @@ static const char *mag_basic_auth_mechs(cmd_parms *parms, void *mconfig,
}
#endif

static const char *mag_acceptor_name(cmd_parms *parms, void *mconfig,
const char *w)
{
struct mag_config *cfg = (struct mag_config *)mconfig;
gss_buffer_desc bufnam = { strlen(w), (void *)w };
uint32_t maj, min;

maj = gss_import_name(&min, &bufnam, GSS_C_NT_HOSTBASED_SERVICE,
&cfg->acceptor_name);
if (GSS_ERROR(maj)) {
return apr_psprintf(parms->pool, "[%s] Failed to import name '%s' %s",
parms->cmd->name, w,
mag_error(parms->pool, "", maj, min));
}

return NULL;
}

static void *mag_create_server_config(apr_pool_t *p, server_rec *s)
{
struct mag_server_config *scfg;
Expand Down Expand Up @@ -1780,6 +1798,8 @@ static const command_rec mag_commands[] = {
AP_INIT_FLAG("GssapiPublishErrors", ap_set_flag_slot,
(void *)APR_OFFSETOF(struct mag_config, enverrs), OR_AUTHCFG,
"Publish GSSAPI Errors in Envionment Variables"),
AP_INIT_RAW_ARGS("GssapiAcceptorName", mag_acceptor_name, NULL, OR_AUTHCFG,
"Name of the acceptor credentials."),
{ NULL }
};

Expand Down
3 changes: 2 additions & 1 deletion src/mod_auth_gssapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct mag_config {
bool negotiate_once;
struct mag_name_attributes *name_attributes;
bool enverrs;
gss_name_t acceptor_name;
};

struct mag_server_config {
Expand Down Expand Up @@ -136,4 +137,4 @@ struct mag_conn {

struct mag_conn *mag_new_conn_ctx(apr_pool_t *pool);
const char *mag_str_auth_type(int auth_type);
char *mag_error(request_rec *req, const char *msg, uint32_t maj, uint32_t min);
char *mag_error(apr_pool_t *pool, const char *msg, uint32_t maj, uint32_t min);
11 changes: 11 additions & 0 deletions tests/httpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,17 @@ CoreDumpDirectory "${HTTPROOT}"
Require valid-user
</Location>

<Location /bad_acceptor_name>
AuthType GSSAPI
AuthName "Bad Acceptor Name"
GssapiSSLonly Off
GssapiCredStore ccache:${HTTPROOT}/tmp/httpd_krb5_ccache
GssapiCredStore client_keytab:${HTTPROOT}/http.keytab
GssapiCredStore keytab:${HTTPROOT}/http.keytab
GssapiAcceptorName BAD@example.com
Require valid-user
</Location>

<VirtualHost *:${PROXYPORT}>
ProxyRequests On
ProxyVia On
Expand Down
19 changes: 19 additions & 0 deletions tests/magtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,23 @@ def test_basic_auth_krb5(testdir, testenv, testlog):
sys.stderr.write('BASIC Proxy Auth: SUCCESS\n')


def test_bad_acceptor_name(testdir, testenv, testlog):

bandir = os.path.join(testdir, 'httpd', 'html', 'bad_acceptor_name')
os.mkdir(bandir)
shutil.copy('tests/index.html', bandir)

with (open(testlog, 'a')) as logfile:
ban = subprocess.Popen(["tests/t_bad_acceptor_name.py"],
stdout=logfile, stderr=logfile,
env=testenv, preexec_fn=os.setsid)
ban.wait()
if ban.returncode != 0:
sys.stderr.write('BAD ACCEPTOR: SUCCESS\n')
else:
sys.stderr.write('BAD ACCEPTOR: FAILED\n')


if __name__ == '__main__':

args = parse_args()
Expand Down Expand Up @@ -425,6 +442,8 @@ def test_basic_auth_krb5(testdir, testenv, testlog):

test_spnego_negotiate_once(testdir, testenv, testlog)

test_bad_acceptor_name(testdir, testenv, testlog)

testenv = {'MAG_USER_NAME': USR_NAME,
'MAG_USER_PASSWORD': USR_PWD,
'MAG_USER_NAME_2': USR_NAME_2,
Expand Down