Use default NTLM domain cc config

The NTLM GSS mechanism now supports default credential handles (and
acquiring handles for default credentials with desired_name ==
GSS_C_NO_NAME).
This commit is contained in:
Nicolas Williams
2015-04-17 10:48:22 -05:00
parent a449b7ef5e
commit 08724496ff
2 changed files with 64 additions and 34 deletions

View File

@@ -33,18 +33,18 @@
#include "ntlm.h" #include "ntlm.h"
OM_uint32 GSSAPI_CALLCONV _gss_ntlm_acquire_cred OM_uint32 GSSAPI_CALLCONV
(OM_uint32 * min_stat, _gss_ntlm_acquire_cred(OM_uint32 *min_stat,
gss_const_name_t desired_name, gss_const_name_t desired_name,
OM_uint32 time_req, OM_uint32 time_req,
const gss_OID_set desired_mechs, const gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage, gss_cred_usage_t cred_usage,
gss_cred_id_t * output_cred_handle, gss_cred_id_t *output_cred_handle,
gss_OID_set * actual_mechs, gss_OID_set *actual_mechs,
OM_uint32 * time_rec OM_uint32 *time_rec)
)
{ {
ntlm_name name = (ntlm_name) desired_name; ntlm_name name = (ntlm_name) desired_name;
const char *domain = NULL;
OM_uint32 maj_stat; OM_uint32 maj_stat;
ntlm_ctx ctx; ntlm_ctx ctx;
@@ -55,17 +55,14 @@ OM_uint32 GSSAPI_CALLCONV _gss_ntlm_acquire_cred
if (time_rec) if (time_rec)
*time_rec = GSS_C_INDEFINITE; *time_rec = GSS_C_INDEFINITE;
if (desired_name == NULL)
return GSS_S_NO_CRED;
if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) { if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) {
maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx); maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx);
if (maj_stat != GSS_S_COMPLETE) if (maj_stat != GSS_S_COMPLETE)
return maj_stat; return maj_stat;
maj_stat = (*ctx->server->nsi_probe)(min_stat, ctx->ictx, domain = name != NULL ? name->domain : NULL;
name->domain); maj_stat = (*ctx->server->nsi_probe)(min_stat, ctx->ictx, domain);
{ {
gss_ctx_id_t context = (gss_ctx_id_t)ctx; gss_ctx_id_t context = (gss_ctx_id_t)ctx;
OM_uint32 junk; OM_uint32 junk;
@@ -79,7 +76,7 @@ OM_uint32 GSSAPI_CALLCONV _gss_ntlm_acquire_cred
*min_stat = _gss_ntlm_get_user_cred(name, &cred); *min_stat = _gss_ntlm_get_user_cred(name, &cred);
if (*min_stat) if (*min_stat)
return GSS_S_FAILURE; return GSS_S_NO_CRED;
cred->usage = cred_usage; cred->usage = cred_usage;
*output_cred_handle = (gss_cred_id_t)cred; *output_cred_handle = (gss_cred_id_t)cred;

View File

@@ -35,11 +35,13 @@
static int static int
from_file(const char *fn, const char *target_domain, from_file(const char *fn, const char *target_domain,
char **username, struct ntlm_buf *key) char **domainp, char **usernamep, struct ntlm_buf *key)
{ {
char *str, buf[1024]; char *str, buf[1024];
FILE *f; FILE *f;
*domainp = NULL;
f = fopen(fn, "r"); f = fopen(fn, "r");
if (f == NULL) if (f == NULL)
return ENOENT; return ENOENT;
@@ -52,14 +54,20 @@ from_file(const char *fn, const char *target_domain,
continue; continue;
str = NULL; str = NULL;
d = strtok_r(buf, ":", &str); d = strtok_r(buf, ":", &str);
if (d && strcasecmp(target_domain, d) != 0) free(*domainp);
if (d && target_domain != NULL && strcasecmp(target_domain, d) != 0)
continue; continue;
*domainp = strdup(d);
if (*domainp == NULL)
return ENOMEM;
u = strtok_r(NULL, ":", &str); u = strtok_r(NULL, ":", &str);
p = strtok_r(NULL, ":", &str); p = strtok_r(NULL, ":", &str);
if (u == NULL || p == NULL) if (u == NULL || p == NULL)
continue; continue;
*username = strdup(u); *usernamep = strdup(u);
if (*usernamep == NULL)
return ENOMEM;
heim_ntlm_nt_key(p, key); heim_ntlm_nt_key(p, key);
@@ -74,17 +82,22 @@ from_file(const char *fn, const char *target_domain,
static int static int
get_user_file(const ntlm_name target_name, get_user_file(const ntlm_name target_name,
char **username, struct ntlm_buf *key) char **domainp, char **usernamep, struct ntlm_buf *key)
{ {
const char *domain;
const char *fn; const char *fn;
*domainp = NULL;
if (issuid()) if (issuid())
return ENOENT; return ENOENT;
domain = target_name != NULL ? target_name->domain : NULL;
fn = getenv("NTLM_USER_FILE"); fn = getenv("NTLM_USER_FILE");
if (fn == NULL) if (fn == NULL)
return ENOENT; return ENOENT;
if (from_file(fn, target_name->domain, username, key) == 0) if (from_file(fn, domain, domainp, usernamep, key) == 0)
return 0; return 0;
return ENOENT; return ENOENT;
@@ -95,7 +108,7 @@ get_user_file(const ntlm_name target_name,
*/ */
static int static int
get_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key) get_user_ccache(const ntlm_name name, char **domainp, char **usernamep, struct ntlm_buf *key)
{ {
krb5_context context = NULL; krb5_context context = NULL;
krb5_principal client; krb5_principal client;
@@ -105,7 +118,8 @@ get_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key)
krb5_data data; krb5_data data;
int aret; int aret;
*username = NULL; *domainp = NULL;
*usernamep = NULL;
krb5_data_zero(&data); krb5_data_zero(&data);
key->length = 0; key->length = 0;
key->data = NULL; key->data = NULL;
@@ -124,22 +138,40 @@ get_user_ccache(const ntlm_name name, char **username, struct ntlm_buf *key)
ret = krb5_unparse_name_flags(context, client, ret = krb5_unparse_name_flags(context, client,
KRB5_PRINCIPAL_UNPARSE_NO_REALM, KRB5_PRINCIPAL_UNPARSE_NO_REALM,
username); usernamep);
krb5_free_principal(context, client); krb5_free_principal(context, client);
if (ret) if (ret)
goto out; goto out;
aret = asprintf(&confname, "ntlm-key-%s", name->domain); if (name != NULL) {
if (aret == -1) { *domainp = strdup(name->domain);
krb5_clear_error_message(context); } else {
ret = ENOMEM; krb5_data data_domain;
krb5_data_zero(&data_domain);
ret = krb5_cc_get_config(context, id, NULL, "default-ntlm-domain",
&data_domain);
if (ret)
goto out;
*domainp = strndup(data_domain.data, data_domain.length);
krb5_data_free(&data_domain);
}
if (*domainp == NULL) {
ret = krb5_enomem(context);
goto out; goto out;
} }
ret = krb5_cc_get_config(context, id, NULL, aret = asprintf(&confname, "ntlm-key-%s", *domainp);
confname, &data); if (aret == -1) {
if (ret) ret = krb5_enomem(context);
goto out; goto out;
}
ret = krb5_cc_get_config(context, id, NULL, confname, &data);
if (ret)
goto out;
key->data = malloc(data.length); key->data = malloc(data.length);
if (key->data == NULL) { if (key->data == NULL) {
@@ -170,15 +202,16 @@ _gss_ntlm_get_user_cred(const ntlm_name target_name,
if (cred == NULL) if (cred == NULL)
return ENOMEM; return ENOMEM;
ret = get_user_file(target_name, &cred->username, &cred->key); ret = get_user_file(target_name,
&cred->domain, &cred->username, &cred->key);
if (ret) if (ret)
ret = get_user_ccache(target_name, &cred->username, &cred->key); ret = get_user_ccache(target_name,
&cred->domain, &cred->username, &cred->key);
if (ret) { if (ret) {
free(cred); free(cred);
return ret; return ret;
} }
cred->domain = strdup(target_name->domain);
*rcred = cred; *rcred = cred;
return ret; return ret;