mirror of
https://github.com/darlinghq/darling-MITKerberosShim.git
synced 2024-11-23 04:29:57 +00:00
1314 lines
34 KiB
C
1314 lines
34 KiB
C
/*
|
|
* Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
|
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the Institute nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "mit-CredentialsCache.h"
|
|
#include <string.h>
|
|
#include <syslog.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
#include "heim.h"
|
|
|
|
static cc_time_t context_change_time = 0;
|
|
|
|
void
|
|
update_time(cc_time_t *change_time)
|
|
{
|
|
cc_time_t now = (cc_time_t)time(NULL);
|
|
if (*change_time >= now)
|
|
*change_time += 1;
|
|
else
|
|
*change_time = now;
|
|
}
|
|
|
|
static cc_int32
|
|
string_release(cc_string_t io_string)
|
|
{
|
|
free((char *)io_string->data);
|
|
free(io_string);
|
|
return ccNoError;
|
|
}
|
|
|
|
|
|
cc_string_f string_functions = {
|
|
.release = string_release
|
|
};
|
|
|
|
static cc_string_t
|
|
create_string(const char *string)
|
|
{
|
|
cc_string_t s;
|
|
s = mshim_malloc(sizeof(*s));
|
|
s->functions = &string_functions;
|
|
s->data = strdup(string);
|
|
return s;
|
|
}
|
|
|
|
|
|
#define KRB5_CCAPI_TKT_FLG_FORWARDABLE 0x40000000
|
|
#define KRB5_CCAPI_TKT_FLG_FORWARDED 0x20000000
|
|
#define KRB5_CCAPI_TKT_FLG_PROXIABLE 0x10000000
|
|
#define KRB5_CCAPI_TKT_FLG_PROXY 0x08000000
|
|
#define KRB5_CCAPI_TKT_FLG_MAY_POSTDATE 0x04000000
|
|
#define KRB5_CCAPI_TKT_FLG_POSTDATED 0x02000000
|
|
#define KRB5_CCAPI_TKT_FLG_INVALID 0x01000000
|
|
#define KRB5_CCAPI_TKT_FLG_RENEWABLE 0x00800000
|
|
#define KRB5_CCAPI_TKT_FLG_INITIAL 0x00400000
|
|
#define KRB5_CCAPI_TKT_FLG_PRE_AUTH 0x00200000
|
|
#define KRB5_CCAPI_TKT_FLG_HW_AUTH 0x00100000
|
|
#define KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000
|
|
#define KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE 0x00040000
|
|
#define KRB5_CCAPI_TKT_FLG_ANONYMOUS 0x00020000
|
|
|
|
static krb5_error_code
|
|
make_cred_from_ccred(krb5_context context,
|
|
const cc_credentials_v5_t *incred,
|
|
krb5_creds *cred)
|
|
{
|
|
krb5_error_code ret;
|
|
unsigned int i;
|
|
|
|
memset(cred, 0, sizeof(*cred));
|
|
|
|
ret = heim_krb5_parse_name(context, incred->client, &cred->client);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
ret = heim_krb5_parse_name(context, incred->server, &cred->server);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
cred->session.keytype = incred->keyblock.type;
|
|
cred->session.keyvalue.length = incred->keyblock.length;
|
|
cred->session.keyvalue.data = malloc(incred->keyblock.length);
|
|
if (cred->session.keyvalue.data == NULL)
|
|
goto nomem;
|
|
memcpy(cred->session.keyvalue.data, incred->keyblock.data,
|
|
incred->keyblock.length);
|
|
|
|
cred->times.authtime = incred->authtime;
|
|
cred->times.starttime = incred->starttime;
|
|
cred->times.endtime = incred->endtime;
|
|
cred->times.renew_till = incred->renew_till;
|
|
|
|
ret = heim_krb5_data_copy(&cred->ticket,
|
|
incred->ticket.data,
|
|
incred->ticket.length);
|
|
if (ret)
|
|
goto nomem;
|
|
|
|
ret = heim_krb5_data_copy(&cred->second_ticket,
|
|
incred->second_ticket.data,
|
|
incred->second_ticket.length);
|
|
if (ret)
|
|
goto nomem;
|
|
|
|
cred->authdata.val = NULL;
|
|
cred->authdata.len = 0;
|
|
|
|
cred->addresses.val = NULL;
|
|
cred->addresses.len = 0;
|
|
|
|
for (i = 0; incred->authdata && incred->authdata[i]; i++)
|
|
;
|
|
|
|
if (i) {
|
|
cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0]));
|
|
if (cred->authdata.val == NULL)
|
|
goto nomem;
|
|
cred->authdata.len = i;
|
|
for (i = 0; i < cred->authdata.len; i++) {
|
|
cred->authdata.val[i].ad_type = incred->authdata[i]->type;
|
|
ret = heim_krb5_data_copy(&cred->authdata.val[i].ad_data,
|
|
incred->authdata[i]->data,
|
|
incred->authdata[i]->length);
|
|
if (ret)
|
|
goto nomem;
|
|
}
|
|
}
|
|
|
|
for (i = 0; incred->addresses && incred->addresses[i]; i++)
|
|
;
|
|
|
|
if (i) {
|
|
cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0]));
|
|
if (cred->addresses.val == NULL)
|
|
goto nomem;
|
|
cred->addresses.len = i;
|
|
|
|
for (i = 0; i < cred->addresses.len; i++) {
|
|
cred->addresses.val[i].addr_type = incred->addresses[i]->type;
|
|
ret = heim_krb5_data_copy(&cred->addresses.val[i].address,
|
|
incred->addresses[i]->data,
|
|
incred->addresses[i]->length);
|
|
if (ret)
|
|
goto nomem;
|
|
}
|
|
}
|
|
|
|
cred->flags.i = 0;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE)
|
|
cred->flags.b.forwardable = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED)
|
|
cred->flags.b.forwarded = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE)
|
|
cred->flags.b.proxiable = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY)
|
|
cred->flags.b.proxy = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE)
|
|
cred->flags.b.may_postdate = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED)
|
|
cred->flags.b.postdated = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID)
|
|
cred->flags.b.invalid = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE)
|
|
cred->flags.b.renewable = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL)
|
|
cred->flags.b.initial = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH)
|
|
cred->flags.b.pre_authent = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH)
|
|
cred->flags.b.hw_authent = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED)
|
|
cred->flags.b.transited_policy_checked = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE)
|
|
cred->flags.b.ok_as_delegate = 1;
|
|
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS)
|
|
cred->flags.b.anonymous = 1;
|
|
|
|
return 0;
|
|
|
|
nomem:
|
|
ret = ENOMEM;
|
|
krb5_set_error_message((mit_krb5_context)context, ret, "malloc: out of memory");
|
|
|
|
fail:
|
|
heim_krb5_free_cred_contents(context, cred);
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
free_ccred(cc_credentials_v5_t *cred)
|
|
{
|
|
int i;
|
|
|
|
if (cred->addresses) {
|
|
for (i = 0; cred->addresses[i] != 0; i++) {
|
|
if (cred->addresses[i]->data)
|
|
free(cred->addresses[i]->data);
|
|
free(cred->addresses[i]);
|
|
}
|
|
free(cred->addresses);
|
|
}
|
|
if (cred->server)
|
|
free(cred->server);
|
|
if (cred->client)
|
|
free(cred->client);
|
|
memset(cred, 0, sizeof(*cred));
|
|
}
|
|
|
|
static krb5_error_code
|
|
make_ccred_from_cred(krb5_context context,
|
|
const krb5_creds *incred,
|
|
cc_credentials_v5_t *cred)
|
|
{
|
|
krb5_error_code ret;
|
|
int i;
|
|
|
|
memset(cred, 0, sizeof(*cred));
|
|
|
|
ret = heim_krb5_unparse_name(context, incred->client, &cred->client);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
ret = heim_krb5_unparse_name(context, incred->server, &cred->server);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
cred->keyblock.type = incred->session.keytype;
|
|
cred->keyblock.length = (cc_uint32)incred->session.keyvalue.length;
|
|
cred->keyblock.data = incred->session.keyvalue.data;
|
|
|
|
cred->authtime = (cc_time_t)incred->times.authtime;
|
|
cred->starttime = (cc_time_t)incred->times.starttime;
|
|
cred->endtime = (cc_time_t)incred->times.endtime;
|
|
cred->renew_till = (cc_time_t)incred->times.renew_till;
|
|
|
|
cred->ticket.length = (cc_int32)incred->ticket.length;
|
|
cred->ticket.data = incred->ticket.data;
|
|
|
|
cred->second_ticket.length = (cc_int32)incred->second_ticket.length;
|
|
cred->second_ticket.data = incred->second_ticket.data;
|
|
|
|
/* XXX this one should also be filled in */
|
|
cred->authdata = NULL;
|
|
|
|
cred->addresses = calloc(incred->addresses.len + 1,
|
|
sizeof(cred->addresses[0]));
|
|
if (cred->addresses == NULL) {
|
|
|
|
ret = ENOMEM;
|
|
goto fail;
|
|
}
|
|
|
|
for (i = 0; i < incred->addresses.len; i++) {
|
|
cc_data *addr;
|
|
addr = malloc(sizeof(*addr));
|
|
if (addr == NULL) {
|
|
ret = ENOMEM;
|
|
goto fail;
|
|
}
|
|
addr->type = incred->addresses.val[i].addr_type;
|
|
addr->length = (cc_int32)incred->addresses.val[i].address.length;
|
|
addr->data = malloc(addr->length);
|
|
if (addr->data == NULL) {
|
|
free(addr);
|
|
ret = ENOMEM;
|
|
goto fail;
|
|
}
|
|
memcpy(addr->data, incred->addresses.val[i].address.data,
|
|
addr->length);
|
|
cred->addresses[i] = addr;
|
|
}
|
|
cred->addresses[i] = NULL;
|
|
|
|
cred->ticket_flags = 0;
|
|
if (incred->flags.b.forwardable)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE;
|
|
if (incred->flags.b.forwarded)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED;
|
|
if (incred->flags.b.proxiable)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE;
|
|
if (incred->flags.b.proxy)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY;
|
|
if (incred->flags.b.may_postdate)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE;
|
|
if (incred->flags.b.postdated)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED;
|
|
if (incred->flags.b.invalid)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID;
|
|
if (incred->flags.b.renewable)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE;
|
|
if (incred->flags.b.initial)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL;
|
|
if (incred->flags.b.pre_authent)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH;
|
|
if (incred->flags.b.hw_authent)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH;
|
|
if (incred->flags.b.transited_policy_checked)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED;
|
|
if (incred->flags.b.ok_as_delegate)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE;
|
|
if (incred->flags.b.anonymous)
|
|
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS;
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
free_ccred(cred);
|
|
|
|
krb5_clear_error_message((mit_krb5_context)context);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
struct cred {
|
|
cc_credentials_union *data;
|
|
cc_credentials_f *functions;
|
|
cc_credentials_f *otherFunctions;
|
|
krb5_creds cred;
|
|
};
|
|
|
|
|
|
|
|
static cc_int32
|
|
cred_release(cc_credentials_t io_credentials)
|
|
{
|
|
struct cred *c = (struct cred *)io_credentials;
|
|
heim_krb5_free_cred_contents(milcontext, &c->cred);
|
|
free(c->data->credentials.credentials_v5);
|
|
free(c->data);
|
|
free(c);
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
cred_compare (cc_credentials_t in_credentials,
|
|
cc_credentials_t in_compare_to_credentials,
|
|
cc_uint32 *out_equal)
|
|
{
|
|
*out_equal = 1;
|
|
return ccErrNoMem;
|
|
}
|
|
|
|
cc_credentials_f credential_functions = {
|
|
.release = cred_release,
|
|
.compare = cred_compare
|
|
};
|
|
|
|
|
|
|
|
static cc_credentials_t
|
|
create_credentials(krb5_creds *cred)
|
|
{
|
|
struct cred *c;
|
|
|
|
c = calloc(1, sizeof(*c));
|
|
c->data = calloc(1, sizeof(*c->data));
|
|
c->data->version = cc_credentials_v5;
|
|
c->data->credentials.credentials_v5 = calloc(1, sizeof(*c->data->credentials.credentials_v5));
|
|
c->functions = &credential_functions;
|
|
|
|
heim_krb5_copy_creds_contents(milcontext, cred, &c->cred);
|
|
make_ccred_from_cred(milcontext, &c->cred, c->data->credentials.credentials_v5);
|
|
|
|
return (cc_credentials_t)c;
|
|
}
|
|
|
|
|
|
struct cred_iterator {
|
|
cc_credentials_iterator_d iterator;
|
|
krb5_ccache id;
|
|
krb5_cc_cursor cursor;
|
|
};
|
|
|
|
static cc_int32
|
|
cred_iter_release(cc_credentials_iterator_t io_credentials_iterator)
|
|
{
|
|
struct cred_iterator *ci = (struct cred_iterator *)io_credentials_iterator;
|
|
LOG_ENTRY();
|
|
if (ci->id)
|
|
krb5_cc_end_seq_get ((mit_krb5_context)milcontext,
|
|
(mit_krb5_ccache)ci->id,
|
|
(mit_krb5_cc_cursor *)&ci->cursor);
|
|
free(ci);
|
|
return ccNoError;
|
|
}
|
|
|
|
cc_int32
|
|
cred_iter_next(cc_credentials_iterator_t in_credentials_iterator, cc_credentials_t *out_credentials)
|
|
{
|
|
struct cred_iterator *ci = (struct cred_iterator *)in_credentials_iterator;
|
|
krb5_error_code ret;
|
|
krb5_creds cred;
|
|
LOG_ENTRY();
|
|
|
|
ret = heim_krb5_cc_next_cred(milcontext, ci->id, &ci->cursor, &cred);
|
|
if (ret == KRB5_CC_END)
|
|
return ccIteratorEnd;
|
|
else if (ret)
|
|
return ret; /* XXX */
|
|
|
|
*out_credentials = create_credentials(&cred);
|
|
heim_krb5_free_cred_contents(milcontext, &cred);
|
|
if (*out_credentials == NULL)
|
|
return ccErrNoMem;
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
cc_int32
|
|
cred_iter_clone (cc_credentials_iterator_t in_credentials_iterator,
|
|
cc_credentials_iterator_t *out_credentials_iterator)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
return ccErrNoMem;
|
|
}
|
|
|
|
|
|
struct cc_credentials_iterator_f cred_iter_functions = {
|
|
.release = cred_iter_release,
|
|
.next = cred_iter_next,
|
|
.clone = cred_iter_clone
|
|
};
|
|
|
|
|
|
|
|
struct cc_ccache {
|
|
cc_ccache_d ccache;
|
|
krb5_ccache id;
|
|
cc_time_t change_time;
|
|
cc_time_t last_default_time;
|
|
};
|
|
|
|
cc_int32
|
|
ccache_release(cc_ccache_t io_ccache)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
LOG_ENTRY();
|
|
if (c->id)
|
|
heim_krb5_cc_close(milcontext, c->id);
|
|
free(c);
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_destroy(cc_ccache_t io_ccache)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
LOG_ENTRY();
|
|
update_time(&context_change_time);
|
|
if (c->id) {
|
|
krb5_cc_destroy((mit_krb5_context)milcontext, (mit_krb5_ccache)c->id);
|
|
c->id = NULL;
|
|
}
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_set_default(cc_ccache_t io_ccache)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
LOG_ENTRY();
|
|
if (io_ccache == NULL || c->id == NULL)
|
|
return ccErrBadParam;
|
|
heim_krb5_cc_switch(milcontext, c->id);
|
|
update_time(&c->change_time);
|
|
update_time(&c->last_default_time);
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_get_credentials_version(cc_ccache_t in_ccache, cc_uint32 *out_credentials_version)
|
|
{
|
|
if (out_credentials_version == NULL)
|
|
return ccErrBadParam;
|
|
*out_credentials_version = cc_credentials_v5;
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_get_name(cc_ccache_t in_ccache, cc_string_t *out_name)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)in_ccache;
|
|
const char *name;
|
|
LOG_ENTRY();
|
|
|
|
if (out_name == NULL)
|
|
return ccErrBadParam;
|
|
if (c->id == NULL)
|
|
return ccErrInvalidCCache;
|
|
|
|
name = heim_krb5_cc_get_name(milcontext, c->id);
|
|
if (name == NULL)
|
|
return ccErrInvalidCCache;
|
|
*out_name = create_string(name);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_get_principal(cc_ccache_t in_ccache, cc_uint32 in_credentials_version, cc_string_t *out_principal)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)in_ccache;
|
|
krb5_principal princ;
|
|
krb5_error_code ret;
|
|
char *name;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (out_principal == NULL)
|
|
return ccErrBadParam;
|
|
if (in_credentials_version != cc_credentials_v5)
|
|
return LOG_FAILURE(ccErrBadCredentialsVersion, "wrong version");
|
|
if (c->id == NULL)
|
|
return ccErrInvalidCCache;
|
|
|
|
ret = heim_krb5_cc_get_principal(milcontext, c->id, &princ);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "get principal");
|
|
ret = heim_krb5_unparse_name(milcontext, princ, &name);
|
|
heim_krb5_free_principal(milcontext, princ);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "unparse name");
|
|
*out_principal = create_string(name);
|
|
free(name);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_set_principal(cc_ccache_t io_ccache, cc_uint32 in_credentials_version, const char *in_principal)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
krb5_error_code ret;
|
|
krb5_principal p;
|
|
LOG_ENTRY();
|
|
|
|
if (in_principal == NULL)
|
|
return ccErrBadParam;
|
|
if (in_credentials_version != cc_credentials_v5)
|
|
return LOG_FAILURE(ccErrBadCredentialsVersion, "wrong version");
|
|
|
|
update_time(&c->change_time);
|
|
update_time(&context_change_time);
|
|
|
|
ret = heim_krb5_parse_name(milcontext, in_principal, &p);
|
|
if (ret)
|
|
return LOG_FAILURE(ccErrBadParam, "parse name");
|
|
|
|
ret = heim_krb5_cc_initialize(milcontext, c->id, p);
|
|
heim_krb5_free_principal(milcontext, p);
|
|
if (ret)
|
|
return LOG_FAILURE(ccErrInvalidCCache, "init cache");
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_store_credentials(cc_ccache_t io_ccache, const cc_credentials_union *in_credentials_union)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
krb5_error_code ret;
|
|
krb5_creds hcred;
|
|
LOG_ENTRY();
|
|
|
|
if (in_credentials_union == NULL)
|
|
return ccErrBadParam;
|
|
if (in_credentials_union->version != cc_credentials_v5)
|
|
return LOG_FAILURE(ccErrBadCredentialsVersion, "wrong version");
|
|
if (in_credentials_union->credentials.credentials_v5->client == NULL)
|
|
return ccErrBadParam;
|
|
|
|
update_time(&c->change_time);
|
|
update_time(&context_change_time);
|
|
|
|
make_cred_from_ccred(milcontext, in_credentials_union->credentials.credentials_v5, &hcred);
|
|
|
|
ret = heim_krb5_cc_store_cred(milcontext, c->id, &hcred);
|
|
heim_krb5_free_cred_contents(milcontext, &hcred);
|
|
if (ret)
|
|
return LOG_FAILURE(ccErrInvalidCCache, "store cred");
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_remove_credentials(cc_ccache_t io_ccache, cc_credentials_t in_credentials)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
const cc_credentials_v5_t *incred;
|
|
krb5_creds cred;
|
|
krb5_error_code ret;
|
|
|
|
LOG_ENTRY();
|
|
|
|
update_time(&c->change_time);
|
|
update_time(&context_change_time);
|
|
|
|
memset(&cred, 0, sizeof(cred));
|
|
|
|
if (c->id == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "bad argument");
|
|
|
|
if (in_credentials == NULL || in_credentials->data == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "remove with no cred?");
|
|
if (in_credentials->data->version != cc_credentials_v5)
|
|
return LOG_FAILURE(ccErrBadParam, "wrong version");
|
|
|
|
incred = in_credentials->data->credentials.credentials_v5;
|
|
if (incred->client == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "no client to remove");
|
|
if (incred->server == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "no server to remove");
|
|
|
|
ret = heim_krb5_parse_name(milcontext, incred->client, &cred.client);
|
|
if (ret)
|
|
goto fail;
|
|
ret = heim_krb5_parse_name(milcontext, incred->server, &cred.server);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
ret = heim_krb5_cc_remove_cred(milcontext, c->id, 0, &cred);
|
|
|
|
update_time(&context_change_time);
|
|
fail:
|
|
heim_krb5_free_cred_contents(milcontext, &cred);
|
|
if (ret)
|
|
return ccErrCredentialsNotFound;
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_new_credentials_iterator(cc_ccache_t in_ccache, cc_credentials_iterator_t *out_credentials_iterator)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)in_ccache;
|
|
struct cred_iterator *ci;
|
|
krb5_error_code ret;
|
|
LOG_ENTRY();
|
|
|
|
if (c == NULL || c->id == NULL)
|
|
return ccErrInvalidCCache;
|
|
if (out_credentials_iterator == NULL)
|
|
return ccErrBadParam;
|
|
|
|
ci = calloc(1, sizeof(*ci));
|
|
ci->iterator.functions = &cred_iter_functions;
|
|
ci->id = c->id;
|
|
ret = krb5_cc_start_seq_get((mit_krb5_context)milcontext,
|
|
(mit_krb5_ccache)c->id,
|
|
(mit_krb5_cc_cursor *)&ci->cursor);
|
|
if (ret) {
|
|
free(ci);
|
|
return LOG_FAILURE(ccErrInvalidCCache, "start seq");
|
|
}
|
|
*out_credentials_iterator = (cc_credentials_iterator_t)ci;
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_move(cc_ccache_t io_source_ccache, cc_ccache_t io_destination_ccache)
|
|
{
|
|
struct cc_ccache *s = (struct cc_ccache *)io_source_ccache;
|
|
struct cc_ccache *d = (struct cc_ccache *)io_destination_ccache;
|
|
krb5_error_code ret;
|
|
|
|
if (s->id == NULL)
|
|
return ccErrInvalidCCache;
|
|
if (d == NULL)
|
|
return ccErrBadParam;
|
|
|
|
if (d->id == NULL) {
|
|
ret = heim_krb5_cc_new_unique(milcontext,
|
|
heim_krb5_cc_get_type(milcontext, s->id),
|
|
NULL, &d->id);
|
|
if (ret)
|
|
return ccErrInvalidCCache;
|
|
}
|
|
|
|
ret = heim_krb5_cc_move(milcontext, s->id, d->id);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "move cache");
|
|
s->id = NULL;
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_lock(cc_ccache_t io_ccache, cc_uint32 in_lock_type, cc_uint32 in_block)
|
|
{
|
|
LOG_ENTRY();
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_unlock(cc_ccache_t io_ccache)
|
|
{
|
|
LOG_ENTRY();
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_get_last_default_time(cc_ccache_t in_ccache, cc_time_t *out_last_default_time)
|
|
{
|
|
struct cc_ccache *s = (struct cc_ccache *)in_ccache;
|
|
LOG_ENTRY();
|
|
|
|
if (out_last_default_time == NULL)
|
|
return ccErrBadParam;
|
|
if (s->id == NULL)
|
|
return ccErrInvalidCCache;
|
|
if (s->last_default_time == 0)
|
|
return ccErrNeverDefault;
|
|
|
|
*out_last_default_time = s->last_default_time;
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_get_change_time(cc_ccache_t in_ccache, cc_time_t *out_change_time)
|
|
{
|
|
struct cc_ccache *s = (struct cc_ccache *)in_ccache;
|
|
LOG_ENTRY();
|
|
|
|
if (out_change_time == NULL)
|
|
return ccErrBadParam;
|
|
*out_change_time = s->change_time;
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_compare(cc_ccache_t in_ccache, cc_ccache_t in_compare_to_ccache, cc_uint32 *out_equal)
|
|
{
|
|
struct cc_ccache *s1 = (struct cc_ccache *)in_ccache;
|
|
struct cc_ccache *s2 = (struct cc_ccache *)in_compare_to_ccache;
|
|
krb5_error_code ret;
|
|
char *n1, *n2;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (out_equal == NULL || s2 == NULL)
|
|
return ccErrBadParam;
|
|
if (s1 == s2) {
|
|
*out_equal = 1;
|
|
return ccNoError;
|
|
}
|
|
if (s1->id == NULL || s2->id == NULL)
|
|
return ccErrInvalidCCache;
|
|
|
|
ret = heim_krb5_cc_get_full_name(milcontext, s1->id, &n1);
|
|
if (ret)
|
|
return ccErrInvalidCCache;
|
|
ret = heim_krb5_cc_get_full_name(milcontext, s2->id, &n2);
|
|
if (ret) {
|
|
free(n1);
|
|
return ccErrInvalidCCache;
|
|
}
|
|
|
|
*out_equal = (strcmp(n1, n2) == 0);
|
|
|
|
free(n1);
|
|
free(n2);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_get_kdc_time_offset(cc_ccache_t in_ccache,
|
|
cc_uint32 in_credentials_version,
|
|
cc_time_t *out_time_offset)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)in_ccache;
|
|
krb5_deltat sec = 0;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (c->id == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "bad credential");
|
|
if (in_credentials_version != cc_credentials_v5)
|
|
return LOG_FAILURE(ccErrBadCredentialsVersion, "wrong version");
|
|
if (out_time_offset == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "bad argument");
|
|
|
|
heim_krb5_cc_get_kdc_offset(milcontext, c->id, &sec);
|
|
*out_time_offset = (cc_time_t)sec;
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_set_kdc_time_offset(cc_ccache_t io_ccache, cc_uint32 in_credentials_version, cc_time_t in_time_offset)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
LOG_ENTRY();
|
|
|
|
if (c->id == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "bad credential");
|
|
|
|
if (in_credentials_version != cc_credentials_v5)
|
|
return LOG_FAILURE(ccErrBadCredentialsVersion, "wrong version");
|
|
|
|
heim_krb5_cc_set_kdc_offset(milcontext, c->id, in_time_offset);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_clear_kdc_time_offset(cc_ccache_t io_ccache, cc_uint32 in_credentials_version)
|
|
{
|
|
struct cc_ccache *c = (struct cc_ccache *)io_ccache;
|
|
LOG_ENTRY();
|
|
|
|
if (c->id == NULL)
|
|
return LOG_FAILURE(ccErrBadParam, "bad credential");
|
|
|
|
heim_krb5_cc_set_kdc_offset(milcontext, c->id, 0);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
ccache_wait_for_change(cc_ccache_t in_ccache)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
return ccErrNoMem;
|
|
}
|
|
|
|
static cc_ccache_f ccache_functions = {
|
|
.release = ccache_release,
|
|
.destroy = ccache_destroy,
|
|
.set_default = ccache_set_default,
|
|
.get_credentials_version = ccache_get_credentials_version,
|
|
.get_name = ccache_get_name,
|
|
.get_principal = ccache_get_principal,
|
|
.set_principal = ccache_set_principal,
|
|
.store_credentials = ccache_store_credentials,
|
|
.remove_credentials = ccache_remove_credentials,
|
|
.new_credentials_iterator = ccache_new_credentials_iterator,
|
|
.move = ccache_move,
|
|
.lock = ccache_lock,
|
|
.unlock = ccache_unlock,
|
|
.get_last_default_time = ccache_get_last_default_time,
|
|
.get_change_time = ccache_get_change_time,
|
|
.compare = ccache_compare,
|
|
.get_kdc_time_offset = ccache_get_kdc_time_offset,
|
|
.set_kdc_time_offset = ccache_set_kdc_time_offset,
|
|
.clear_kdc_time_offset = ccache_clear_kdc_time_offset,
|
|
.wait_for_change = ccache_wait_for_change
|
|
};
|
|
|
|
static cc_ccache_t
|
|
create_ccache(krb5_ccache id)
|
|
{
|
|
struct cc_ccache *c;
|
|
|
|
c = mshim_malloc(sizeof(*c));
|
|
c->ccache.functions = &ccache_functions;
|
|
c->id = id;
|
|
update_time(&c->change_time);
|
|
return (cc_ccache_t)c;
|
|
}
|
|
|
|
struct cc_iter {
|
|
cc_ccache_iterator_d iterator;
|
|
mit_krb5_cccol_cursor cursor;
|
|
};
|
|
|
|
static cc_int32
|
|
cc_iterator_release(cc_ccache_iterator_t io_ccache_iterator)
|
|
{
|
|
struct cc_iter *c = (struct cc_iter *)io_ccache_iterator;
|
|
LOG_ENTRY();
|
|
krb5_cccol_cursor_free((mit_krb5_context)milcontext, &c->cursor);
|
|
free(c);
|
|
return ccNoError;
|
|
}
|
|
|
|
cc_int32
|
|
cc_iterator_next(cc_ccache_iterator_t in_ccache_iterator,
|
|
cc_ccache_t *out_ccache)
|
|
{
|
|
struct cc_iter *c = (struct cc_iter *)in_ccache_iterator;
|
|
krb5_error_code ret;
|
|
krb5_ccache id;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (out_ccache == NULL)
|
|
return ccErrBadParam;
|
|
|
|
|
|
while (1) {
|
|
ret = krb5_cccol_cursor_next((mit_krb5_context)milcontext, c->cursor, (mit_krb5_ccache *)&id);
|
|
if (ret == KRB5_CC_END || id == NULL)
|
|
return ccIteratorEnd;
|
|
else if (ret)
|
|
return LOG_FAILURE(ret, "ccol next cursor");
|
|
|
|
const char *type = heim_krb5_cc_get_type(milcontext, id);
|
|
if (strcmp(type, "API") == 0 || strcmp(type, "KCM") == 0)
|
|
break;
|
|
heim_krb5_cc_close(milcontext, id);
|
|
}
|
|
*out_ccache = create_ccache(id);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
cc_iterator_clone(cc_ccache_iterator_t in_ccache_iterator,
|
|
cc_ccache_iterator_t *out_ccache_iterator)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
if (out_ccache_iterator == NULL)
|
|
return ccErrBadParam;
|
|
return ccErrNoMem;
|
|
}
|
|
|
|
static cc_ccache_iterator_f ccache_iterator_functions = {
|
|
.release = cc_iterator_release,
|
|
.next = cc_iterator_next,
|
|
.clone = cc_iterator_clone
|
|
};
|
|
|
|
|
|
|
|
|
|
static cc_int32
|
|
context_release(cc_context_t io_context)
|
|
{
|
|
LOG_ENTRY();
|
|
memset(io_context, 0, sizeof(*io_context));
|
|
free(io_context);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_get_change_time(cc_context_t in_context,
|
|
cc_time_t *out_time)
|
|
{
|
|
LOG_ENTRY();
|
|
if (out_time == NULL)
|
|
return ccErrBadParam;
|
|
*out_time = context_change_time;
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_get_default_ccache_name(cc_context_t in_context,
|
|
cc_string_t *out_name)
|
|
{
|
|
const char *name;
|
|
name = krb5_cc_default_name((mit_krb5_context)milcontext);
|
|
if (name == NULL)
|
|
return ccErrNoMem; /* XXX */
|
|
if (out_name == NULL)
|
|
return ccErrBadParam;
|
|
if (strncmp("API:", name, 4) == 0)
|
|
name += 4;
|
|
|
|
*out_name = create_string(name);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
/*
|
|
* Probe for client principal to make sure the cache really
|
|
* exists.
|
|
*/
|
|
|
|
static cc_int32
|
|
check_exists(krb5_ccache id)
|
|
{
|
|
krb5_principal princ;
|
|
int ret;
|
|
|
|
ret = heim_krb5_cc_get_principal(milcontext, id, &princ);
|
|
if (ret)
|
|
return 0;
|
|
heim_krb5_free_principal(milcontext, princ);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
static cc_int32
|
|
context_open_ccache (cc_context_t in_context,
|
|
const char *in_name,
|
|
cc_ccache_t *out_ccache)
|
|
{
|
|
char *name;
|
|
krb5_error_code ret;
|
|
krb5_ccache id;
|
|
|
|
if (out_ccache == NULL || in_name == NULL || in_context == NULL)
|
|
return ccErrBadParam;
|
|
|
|
asprintf(&name, "API:%s", in_name);
|
|
|
|
ret = heim_krb5_cc_resolve(milcontext, name, &id);
|
|
free(name);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "open cache");
|
|
|
|
if (!check_exists(id)) {
|
|
heim_krb5_cc_close(milcontext, id);
|
|
return ccErrCCacheNotFound;
|
|
}
|
|
|
|
*out_ccache = create_ccache(id);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_open_default_ccache(cc_context_t in_context,
|
|
cc_ccache_t *out_ccache)
|
|
{
|
|
krb5_error_code ret;
|
|
krb5_ccache id;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (out_ccache == NULL)
|
|
return ccErrBadParam;
|
|
|
|
ret = heim_krb5_cc_default(milcontext, &id);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "cc default");
|
|
|
|
if (!check_exists(id)) {
|
|
heim_krb5_cc_close(milcontext, id);
|
|
return ccErrCCacheNotFound;
|
|
}
|
|
|
|
*out_ccache = create_ccache(id);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_create_ccache(cc_context_t in_context,
|
|
const char *in_name,
|
|
cc_uint32 in_cred_vers,
|
|
const char *in_principal,
|
|
cc_ccache_t *out_ccache)
|
|
{
|
|
krb5_principal principal;
|
|
krb5_error_code ret;
|
|
krb5_ccache id;
|
|
|
|
if (in_cred_vers != cc_credentials_v5)
|
|
return ccErrBadCredentialsVersion;
|
|
if (out_ccache == NULL || in_name == NULL || in_context == NULL || in_principal == NULL)
|
|
return ccErrBadParam;
|
|
|
|
update_time(&context_change_time);
|
|
|
|
ret = heim_krb5_parse_name(milcontext, in_principal, &principal);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "parse name");
|
|
|
|
ret = heim_krb5_cc_resolve(milcontext, in_name, &id);
|
|
if (ret) {
|
|
heim_krb5_free_principal(milcontext, principal);
|
|
return LOG_FAILURE(ret, "open cache");
|
|
}
|
|
|
|
ret = heim_krb5_cc_initialize(milcontext, id, principal);
|
|
heim_krb5_free_principal(milcontext, principal);
|
|
if (ret) {
|
|
krb5_cc_destroy((mit_krb5_context)milcontext, (mit_krb5_ccache)id);
|
|
return LOG_FAILURE(ret, "cc init");
|
|
}
|
|
|
|
*out_ccache = create_ccache(id);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_create_default_ccache(cc_context_t in_context,
|
|
cc_uint32 in_cred_vers,
|
|
const char *in_principal,
|
|
cc_ccache_t *out_ccache)
|
|
{
|
|
krb5_principal principal;
|
|
krb5_error_code ret;
|
|
struct cc_ccache *c;
|
|
krb5_ccache id;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (in_cred_vers != cc_credentials_v5)
|
|
return ccErrBadCredentialsVersion;
|
|
if (out_ccache == NULL || in_principal == NULL)
|
|
return ccErrBadParam;
|
|
|
|
*out_ccache = NULL;
|
|
|
|
update_time(&context_change_time);
|
|
|
|
ret = heim_krb5_cc_default(milcontext, &id);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "cc default");
|
|
|
|
ret = heim_krb5_parse_name(milcontext, in_principal, &principal);
|
|
if (ret) {
|
|
heim_krb5_cc_close(milcontext, id);
|
|
return LOG_FAILURE(ret, "parse name");
|
|
}
|
|
|
|
ret = heim_krb5_cc_initialize(milcontext, id, principal);
|
|
heim_krb5_free_principal(milcontext, principal);
|
|
if (ret) {
|
|
krb5_cc_destroy((mit_krb5_context)milcontext, (mit_krb5_ccache)id);
|
|
return LOG_FAILURE(ret, "cc init");
|
|
}
|
|
|
|
c = (struct cc_ccache *)create_ccache(id);
|
|
|
|
update_time(&c->last_default_time);
|
|
|
|
*out_ccache = (cc_ccache_t)c;
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_create_new_ccache(cc_context_t in_context,
|
|
cc_uint32 in_cred_vers,
|
|
const char *in_principal,
|
|
cc_ccache_t *out_ccache)
|
|
{
|
|
krb5_principal principal;
|
|
krb5_error_code ret;
|
|
krb5_ccache id;
|
|
|
|
LOG_ENTRY();
|
|
|
|
if (in_cred_vers != cc_credentials_v5)
|
|
return ccErrBadCredentialsVersion;
|
|
|
|
if (out_ccache == NULL || in_principal == NULL)
|
|
return ccErrBadParam;
|
|
|
|
update_time(&context_change_time);
|
|
|
|
ret = heim_krb5_parse_name(milcontext, in_principal, &principal);
|
|
if (ret)
|
|
return LOG_FAILURE(ret, "parse name");
|
|
|
|
ret = heim_krb5_cc_new_unique(milcontext, NULL, NULL, &id);
|
|
if (ret) {
|
|
heim_krb5_free_principal(milcontext, principal);
|
|
return LOG_FAILURE(ret, "new unique");
|
|
}
|
|
|
|
ret = heim_krb5_cc_initialize(milcontext, id, principal);
|
|
heim_krb5_free_principal(milcontext, principal);
|
|
if (ret) {
|
|
krb5_cc_destroy((mit_krb5_context)milcontext, (mit_krb5_ccache)id);
|
|
return LOG_FAILURE(ret, "cc init");
|
|
}
|
|
|
|
*out_ccache = create_ccache(id);
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_new_ccache_iterator(cc_context_t in_context,
|
|
cc_ccache_iterator_t *out_iterator)
|
|
{
|
|
LOG_ENTRY();
|
|
|
|
krb5_error_code ret;
|
|
struct cc_iter *c;
|
|
|
|
if (out_iterator == NULL)
|
|
return ccErrBadParam;
|
|
|
|
c = calloc(1, sizeof(*c));
|
|
c->iterator.functions = &ccache_iterator_functions;
|
|
|
|
ret = krb5_cccol_cursor_new((mit_krb5_context)milcontext, &c->cursor);
|
|
if (ret) {
|
|
free(c);
|
|
return ccErrNoMem;
|
|
}
|
|
|
|
*out_iterator = (cc_ccache_iterator_t)c;
|
|
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_lock(cc_context_t in_context,
|
|
cc_uint32 in_lock_type,
|
|
cc_uint32 in_block)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_unlock(cc_context_t in_context)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
return ccNoError;
|
|
}
|
|
|
|
static cc_int32
|
|
context_compare(cc_context_t in_cc_context,
|
|
cc_context_t in_compare_to_context,
|
|
cc_uint32 *out_equal)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
if (out_equal == NULL || in_compare_to_context == NULL)
|
|
return ccErrBadParam;
|
|
*out_equal = (in_cc_context == in_compare_to_context);
|
|
return 0;
|
|
}
|
|
|
|
static cc_int32
|
|
context_wait_for_change(cc_context_t in_cc_context)
|
|
{
|
|
LOG_UNIMPLEMENTED();
|
|
return ccErrNoMem;
|
|
}
|
|
|
|
|
|
|
|
cc_context_f cc_functions = {
|
|
.release = context_release,
|
|
.get_change_time = context_get_change_time,
|
|
.get_default_ccache_name = context_get_default_ccache_name,
|
|
.open_ccache = context_open_ccache,
|
|
.open_default_ccache = context_open_default_ccache,
|
|
.create_ccache = context_create_ccache,
|
|
.create_default_ccache = context_create_default_ccache,
|
|
.create_new_ccache = context_create_new_ccache,
|
|
.new_ccache_iterator = context_new_ccache_iterator,
|
|
.lock = context_lock,
|
|
.unlock = context_unlock,
|
|
.compare = context_compare,
|
|
.wait_for_change = context_wait_for_change
|
|
};
|
|
|
|
|
|
cc_int32
|
|
cc_initialize(cc_context_t *out_context,
|
|
cc_int32 in_version,
|
|
cc_int32 *out_supported_version,
|
|
char const **out_vendor)
|
|
{
|
|
LOG_ENTRY();
|
|
|
|
update_time(&context_change_time);
|
|
|
|
if (in_version < ccapi_version_3 || in_version > ccapi_version_7)
|
|
return ccErrBadAPIVersion;
|
|
if (out_context == NULL)
|
|
return ccErrBadParam;
|
|
|
|
*out_context = calloc(1, sizeof(**out_context));
|
|
(*out_context)->functions = &cc_functions;
|
|
|
|
if (out_supported_version)
|
|
*out_supported_version = ccapi_version_7;
|
|
if (out_vendor)
|
|
*out_vendor = "Apple Heimdal shim layer";
|
|
|
|
return 0;
|
|
}
|
|
|
|
|