krb5: Improve cccol sub naming; add gss_store_cred_into2()
- Formalize the TYPE:collection_name:subsidiary_name naming scheme for ccaches in ccache collections - KEYRING: ccaches are weird because they have one more optional field: the "anchor", so rather than just assume a naming convention everywhere, we add new functions as well - Add krb5_cc_{resolve,default}_sub() that allows one to specify a "subsidiary" ccache name in a collection separately from the collection name - Add krb5_cc_{resolve,default}_for() which take a principal name, unparse it, and use it as the subsidiary ccache name (with colons replaced) - Make kinit use the new interfaces - Add missing DIR ccache iteration functionality - Revamps test_cc - Add krb5_cc_get_collection() and krb5_cc_get_subsidiary() - Bump the ccops SPI version number - Add gss_store_cred_into2() - Make MEMORY:anonymous not linked into the global MEMORY ccache collection, and uses this for delegated cred handles TBD: - Split this up into a krb5 change and gss mech_krb5 change? - Add krb5_cc_init_and_store() utility, per Greg's suggestion?
This commit is contained in:
@@ -38,7 +38,8 @@
|
||||
typedef struct krb5_mcache {
|
||||
char *name;
|
||||
unsigned int refcnt;
|
||||
int dead;
|
||||
unsigned int anonymous:1;
|
||||
unsigned int dead:1;
|
||||
krb5_principal primary_principal;
|
||||
struct link {
|
||||
krb5_creds cred;
|
||||
@@ -57,42 +58,89 @@ static struct krb5_mcache *mcc_head;
|
||||
|
||||
#define MISDEAD(X) ((X)->dead)
|
||||
|
||||
static const char* KRB5_CALLCONV
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
mcc_get_name(krb5_context context,
|
||||
krb5_ccache id)
|
||||
krb5_ccache id,
|
||||
const char **name,
|
||||
const char **col,
|
||||
const char **sub)
|
||||
{
|
||||
return MCACHE(id)->name;
|
||||
if (name)
|
||||
*name = MCACHE(id)->name;
|
||||
if (col)
|
||||
*col = NULL;
|
||||
if (sub)
|
||||
*sub = MCACHE(id)->name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_mcache * KRB5_CALLCONV
|
||||
mcc_alloc(const char *name)
|
||||
static krb5_error_code
|
||||
mcc_alloc(krb5_context context, const char *name, krb5_mcache **out)
|
||||
{
|
||||
krb5_mcache *m, *m_c;
|
||||
size_t counter = 0;
|
||||
int ret = 0;
|
||||
|
||||
*out = NULL;
|
||||
ALLOC(m, 1);
|
||||
if(m == NULL)
|
||||
return NULL;
|
||||
return krb5_enomem(context);
|
||||
|
||||
again:
|
||||
if (counter > 3) {
|
||||
free(m->name);
|
||||
free(m);
|
||||
return EAGAIN; /* XXX */
|
||||
}
|
||||
if(name == NULL)
|
||||
ret = asprintf(&m->name, "%p", m);
|
||||
ret = asprintf(&m->name, "u%p-%llu", m, (unsigned long long)counter);
|
||||
else
|
||||
m->name = strdup(name);
|
||||
if(ret < 0 || m->name == NULL) {
|
||||
free(m);
|
||||
return NULL;
|
||||
return krb5_enomem(context);
|
||||
}
|
||||
if (strcmp(m->name, "anonymous") == 0) {
|
||||
m->anonymous = 1;
|
||||
m->dead = 0;
|
||||
m->refcnt = 1;
|
||||
m->primary_principal = NULL;
|
||||
m->creds = NULL;
|
||||
m->mtime = time(NULL);
|
||||
m->kdc_offset = 0;
|
||||
m->next = NULL;
|
||||
*out = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for dups first */
|
||||
HEIMDAL_MUTEX_lock(&mcc_mutex);
|
||||
for (m_c = mcc_head; m_c != NULL; m_c = m_c->next)
|
||||
if (strcmp(m->name, m_c->name) == 0)
|
||||
break;
|
||||
if (strcmp(m->name, m_c->name) == 0)
|
||||
break;
|
||||
if (m_c) {
|
||||
free(m->name);
|
||||
free(m);
|
||||
HEIMDAL_MUTEX_unlock(&mcc_mutex);
|
||||
return NULL;
|
||||
free(m->name);
|
||||
free(m);
|
||||
if (name) {
|
||||
/* We raced with another thread to create this cache */
|
||||
m = m_c;
|
||||
HEIMDAL_MUTEX_lock(&(m->mutex));
|
||||
m->refcnt++;
|
||||
HEIMDAL_MUTEX_unlock(&(m->mutex));
|
||||
} else {
|
||||
/* How likely are we to conflict on new_unique anyways?? */
|
||||
counter++;
|
||||
free(m->name);
|
||||
m->name = NULL;
|
||||
HEIMDAL_MUTEX_unlock(&mcc_mutex);
|
||||
goto again;
|
||||
}
|
||||
HEIMDAL_MUTEX_unlock(&mcc_mutex);
|
||||
*out = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
m->anonymous = 0;
|
||||
m->dead = 0;
|
||||
m->refcnt = 1;
|
||||
m->primary_principal = NULL;
|
||||
@@ -103,35 +151,21 @@ mcc_alloc(const char *name)
|
||||
HEIMDAL_MUTEX_init(&(m->mutex));
|
||||
mcc_head = m;
|
||||
HEIMDAL_MUTEX_unlock(&mcc_mutex);
|
||||
return m;
|
||||
*out = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
|
||||
mcc_resolve(krb5_context context,
|
||||
krb5_ccache *id,
|
||||
const char *res,
|
||||
const char *sub)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_mcache *m;
|
||||
|
||||
HEIMDAL_MUTEX_lock(&mcc_mutex);
|
||||
for (m = mcc_head; m != NULL; m = m->next)
|
||||
if (strcmp(m->name, res) == 0)
|
||||
break;
|
||||
HEIMDAL_MUTEX_unlock(&mcc_mutex);
|
||||
|
||||
if (m != NULL) {
|
||||
HEIMDAL_MUTEX_lock(&(m->mutex));
|
||||
m->refcnt++;
|
||||
HEIMDAL_MUTEX_unlock(&(m->mutex));
|
||||
(*id)->data.data = m;
|
||||
(*id)->data.length = sizeof(*m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m = mcc_alloc(res);
|
||||
if (m == NULL) {
|
||||
krb5_set_error_message(context, KRB5_CC_NOMEM,
|
||||
N_("malloc: out of memory", ""));
|
||||
return KRB5_CC_NOMEM;
|
||||
}
|
||||
if ((ret = mcc_alloc(context, sub && *sub ? sub : res, &m)))
|
||||
return ret;
|
||||
|
||||
(*id)->data.data = m;
|
||||
(*id)->data.length = sizeof(*m);
|
||||
@@ -143,15 +177,11 @@ mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
mcc_gen_new(krb5_context context, krb5_ccache *id)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_mcache *m;
|
||||
|
||||
m = mcc_alloc(NULL);
|
||||
|
||||
if (m == NULL) {
|
||||
krb5_set_error_message(context, KRB5_CC_NOMEM,
|
||||
N_("malloc: out of memory", ""));
|
||||
return KRB5_CC_NOMEM;
|
||||
}
|
||||
if ((ret = mcc_alloc(context, NULL, &m)))
|
||||
return ret;
|
||||
|
||||
(*id)->data.data = m;
|
||||
(*id)->data.length = sizeof(*m);
|
||||
@@ -221,7 +251,7 @@ mcc_close_internal(krb5_mcache *m)
|
||||
return 0;
|
||||
}
|
||||
if (MISDEAD(m)) {
|
||||
free (m->name);
|
||||
free(m->name);
|
||||
HEIMDAL_MUTEX_unlock(&(m->mutex));
|
||||
return 1;
|
||||
}
|
||||
@@ -248,6 +278,18 @@ mcc_destroy(krb5_context context,
|
||||
{
|
||||
krb5_mcache **n, *m = MCACHE(id);
|
||||
|
||||
if (m->anonymous) {
|
||||
HEIMDAL_MUTEX_lock(&(m->mutex));
|
||||
if (m->refcnt == 0) {
|
||||
HEIMDAL_MUTEX_unlock(&(m->mutex));
|
||||
krb5_abortx(context, "mcc_destroy: refcnt already 0");
|
||||
}
|
||||
if (!MISDEAD(m))
|
||||
mcc_destroy_internal(context, m);
|
||||
HEIMDAL_MUTEX_unlock(&(m->mutex));
|
||||
return 0;
|
||||
}
|
||||
|
||||
HEIMDAL_MUTEX_lock(&mcc_mutex);
|
||||
HEIMDAL_MUTEX_lock(&(m->mutex));
|
||||
if (m->refcnt == 0)
|
||||
@@ -290,12 +332,8 @@ mcc_store_cred(krb5_context context,
|
||||
}
|
||||
|
||||
l = malloc (sizeof(*l));
|
||||
if (l == NULL) {
|
||||
krb5_set_error_message(context, KRB5_CC_NOMEM,
|
||||
N_("malloc: out of memory", ""));
|
||||
HEIMDAL_MUTEX_unlock(&(m->mutex));
|
||||
return KRB5_CC_NOMEM;
|
||||
}
|
||||
if (l == NULL)
|
||||
return krb5_enomem(context);
|
||||
l->next = m->creds;
|
||||
m->creds = l;
|
||||
memset (&l->cred, 0, sizeof(l->cred));
|
||||
|
Reference in New Issue
Block a user