The krb5_cc_ops structure is an extensible structure to which new
functionality has been added over the years.
Version zero was the original. It included all functions up to
and including get_default_name().
Version one added set_default().
Version two added lastchange().
Version three added set_kdc_offset() and get_kdc_offset().
Version four broke compatibility by modifying the signatures
of get_name() and resolve(). This was in change
7bf4d76e75e904dd65a0fbb90c9cad981245f714 ("krb5: Improve cccol sub
naming; add gss_store_cred_into2()").
Version five restores the original signatures of get_name()
and resolve() and introduces get_name_2() and resolve_2() that
provide the additional cccol functionality.
This change
* introduces version five
* documents which functions are part of each version
* replaces KRB5_CC_OPS_VERSION with KRB5_CC_OPS_VERSION_0,
KRB5_CC_OPS_VERSION_1, KRB5_CC_OPS_VERSION_2, KRB5_CC_OPS_VERSION_3,
and KRB5_CC_OPS_VERSION_5. KRB5_CC_OPS_VERSION_4 is skipped
because of the aforementioned breakage.
* compatibility logic is added to permit ccache plugins to implement
any of version one, two, three, five or a future version.
* all in-tree krb5_cc_ops implementations are updated to version 5.
Change-Id: Iadfce01d10834bc6151939e4d9d196f03001626e
static krb5_error_code KRB5_CALLCONV
-acc_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **colname,
- const char **subsidiary)
+acc_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **colname,
+ const char **subsidiary)
{
krb5_error_code ret = 0;
krb5_acc *a = ACACHE(id);
}
static krb5_error_code KRB5_CALLCONV
-acc_resolve(krb5_context context, krb5_ccache *id, const char *res, const char *sub)
+acc_resolve_2(krb5_context context, krb5_ccache *id, const char *res, const char *sub)
{
krb5_error_code ret;
cc_time_t offset;
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_acc_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"API",
- acc_get_name,
- acc_resolve,
+ NULL,
+ NULL,
acc_gen_new,
acc_initialize,
acc_destroy,
acc_lastchange,
NULL,
NULL,
+ acc_get_name_2,
+ acc_resolve_2
};
#endif
return ret;
}
- ret = (*id)->ops->resolve(context, id, residual, subsidiary);
- if(ret) {
+ if ((*id)->ops->version < KRB5_CC_OPS_VERSION_5
+ || (*id)->ops->resolve_2 == NULL) {
+ ret = (*id)->ops->resolve(context, id, residual);
+ } else {
+ ret = (*id)->ops->resolve_2(context, id, residual, subsidiary);
+ }
+ if (ret) {
free(*id);
*id = NULL;
}
krb5_cc_get_name(krb5_context context,
krb5_ccache id)
{
- const char *name;
-
- (void) id->ops->get_name(context, id, &name, NULL, NULL);
- return name;
+ return id->ops->get_name(context, id);
}
/**
krb5_cc_get_collection(krb5_context context, krb5_ccache id)
{
const char *name;
+ int ret;
+
+ if (id->ops->version < KRB5_CC_OPS_VERSION_5
+ || id->ops->get_name_2 == NULL)
+ return NULL;
+
+ ret = id->ops->get_name_2(context, id, NULL, &name, NULL);
+ if (ret)
+ return NULL;
- (void) id->ops->get_name(context, id, NULL, &name, NULL);
return name;
}
_krb5_set_default_cc_name_to_registry(context, id);
#endif
- if (id->ops->set_default == NULL)
+ if (id->ops->version == KRB5_CC_OPS_VERSION_0
+ || id->ops->set_default == NULL)
return 0;
return (*id->ops->set_default)(context, id);
const krb5_cc_ops *ops;
ops = krb5_cc_get_prefix_ops(context, type);
- if (ops && ops->set_default)
+ if (ops && ops->version > KRB5_CC_OPS_VERSION_0 && ops->set_default)
return 1;
return FALSE;
}
krb5_timestamp *mtime)
{
*mtime = 0;
+
+ if (id->ops->version < KRB5_CC_OPS_VERSION_2
+ || id->ops->lastchange == NULL)
+ return KRB5_CC_NOSUPP;
+
return (*id->ops->lastchange)(context, id, mtime);
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat offset)
{
- if (id->ops->set_kdc_offset == NULL) {
+ if (id->ops->version < KRB5_CC_OPS_VERSION_3
+ || id->ops->set_kdc_offset == NULL) {
context->kdc_sec_offset = offset;
context->kdc_usec_offset = 0;
return 0;
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cc_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *offset)
{
- if (id->ops->get_kdc_offset == NULL) {
+ if (id->ops->version < KRB5_CC_OPS_VERSION_3
+ || id->ops->get_kdc_offset == NULL) {
*offset = context->kdc_sec_offset;
return 0;
}
static krb5_error_code KRB5_CALLCONV
-dcc_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **dir,
- const char **sub)
+dcc_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **dir,
+ const char **sub)
{
krb5_dcache *dc = DCACHE(id);
}
static krb5_error_code KRB5_CALLCONV
-dcc_resolve(krb5_context context,
- krb5_ccache *id,
- const char *res,
- const char *sub)
+dcc_resolve_2(krb5_context context,
+ krb5_ccache *id,
+ const char *res,
+ const char *sub)
{
krb5_error_code ret;
krb5_dcache *dc = NULL;
if (ret == 0 && (fd = mkstemp(name + sizeof("DIR::") - 1)) == -1)
ret = errno;
if (ret == 0)
- ret = dcc_resolve(context, id, name + sizeof("DIR:") - 1, NULL);
+ ret = dcc_resolve_2(context, id, name + sizeof("DIR:") - 1, NULL);
free(def_dir);
free(name);
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_dcc_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"DIR",
- dcc_get_name,
- dcc_resolve,
+ NULL,
+ NULL,
dcc_gen_new,
dcc_initialize,
dcc_destroy,
dcc_set_default,
dcc_lastchange,
dcc_set_kdc_offset,
- dcc_get_kdc_offset
+ dcc_get_kdc_offset,
+ dcc_get_name_2,
+ dcc_resolve_2
};
#define FCC_CURSOR(C) ((struct fcc_cursor*)(C))
static krb5_error_code KRB5_CALLCONV
-fcc_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **colname,
- const char **sub)
+fcc_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **colname,
+ const char **sub)
{
if (FCACHE(id) == NULL)
return KRB5_CC_NOTFOUND;
if (exclusive == FALSE)
return 0;
- ret = fcc_get_name(context, id, &name, NULL, NULL);
+ ret = fcc_get_name_2(context, id, &name, NULL, NULL);
if (ret == 0)
ret = _krb5_xlock(context, fd, exclusive, name);
return ret;
#define FILESUBSEPCHR ((FILESUBSEP)[0])
static krb5_error_code KRB5_CALLCONV
-fcc_resolve(krb5_context context,
- krb5_ccache *id,
- const char *res,
- const char *sub)
+fcc_resolve_2(krb5_context context,
+ krb5_ccache *id,
+ const char *res,
+ const char *sub)
{
krb5_fcache *f;
char *freeme = NULL;
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_fcc_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"FILE",
- fcc_get_name,
- fcc_resolve,
+ NULL,
+ NULL,
fcc_gen_new,
fcc_initialize,
fcc_destroy,
fcc_set_default_cache,
fcc_lastchange,
fcc_set_kdc_offset,
- fcc_get_kdc_offset
+ fcc_get_kdc_offset,
+ fcc_get_name_2,
+ fcc_resolve_2
};
}
static krb5_error_code KRB5_CALLCONV
-kcm_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **col,
- const char **sub)
+kcm_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **col,
+ const char **sub)
{
/*
* TODO:
}
static krb5_error_code
-kcm_resolve(krb5_context context,
- krb5_ccache *id,
- const char *res,
- const char *sub)
+kcm_resolve_2(krb5_context context,
+ krb5_ccache *id,
+ const char *res,
+ const char *sub)
{
/*
* For now, for KCM the `res' is the `sub'.
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"KCM",
kcm_get_name,
kcm_resolve,
kcm_set_default,
kcm_lastchange,
kcm_set_kdc_offset,
- kcm_get_kdc_offset
+ kcm_get_kdc_offset,
+ kcm_get_name_2,
+ kcm_resolve_2
};
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"API",
- kcm_get_name,
- kcm_resolve,
+ NULL,
+ NULL,
kcm_gen_new,
kcm_initialize,
kcm_destroy,
kcm_set_default,
kcm_lastchange,
NULL,
- NULL
+ NULL,
+ kcm_get_name_2,
+ kcm_resolve_2
};
typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor;
-#define KRB5_CC_OPS_VERSION 4
+#define KRB5_CC_OPS_VERSION_0 0
+#define KRB5_CC_OPS_VERSION_1 1
+#define KRB5_CC_OPS_VERSION_2 2
+#define KRB5_CC_OPS_VERSION_3 3
+#define KRB5_CC_OPS_VERSION_5 5
+/* Only extend the structure. Do not change signatures. */
typedef struct krb5_cc_ops {
+ /* Version 0 */
int version;
const char *prefix;
- krb5_error_code (KRB5_CALLCONV * get_name)(krb5_context, krb5_ccache,
- const char **, const char **,
- const char **);
- krb5_error_code (KRB5_CALLCONV * resolve)(krb5_context, krb5_ccache *, const char *,
- const char *);
+ const char* (KRB5_CALLCONV * get_name)(krb5_context, krb5_ccache);
+ krb5_error_code (KRB5_CALLCONV * resolve)(krb5_context, krb5_ccache *, const char *);
krb5_error_code (KRB5_CALLCONV * gen_new)(krb5_context, krb5_ccache *);
krb5_error_code (KRB5_CALLCONV * init)(krb5_context, krb5_ccache, krb5_principal);
krb5_error_code (KRB5_CALLCONV * destroy)(krb5_context, krb5_ccache);
krb5_error_code (KRB5_CALLCONV * end_cache_get)(krb5_context, krb5_cc_cursor);
krb5_error_code (KRB5_CALLCONV * move)(krb5_context, krb5_ccache, krb5_ccache);
krb5_error_code (KRB5_CALLCONV * get_default_name)(krb5_context, char **);
+ /* Version 1 */
krb5_error_code (KRB5_CALLCONV * set_default)(krb5_context, krb5_ccache);
+ /* Version 2 */
krb5_error_code (KRB5_CALLCONV * lastchange)(krb5_context, krb5_ccache, krb5_timestamp *);
+ /* Version 3 */
krb5_error_code (KRB5_CALLCONV * set_kdc_offset)(krb5_context, krb5_ccache, krb5_deltat);
krb5_error_code (KRB5_CALLCONV * get_kdc_offset)(krb5_context, krb5_ccache, krb5_deltat *);
+ /* Version 5 */
+ krb5_error_code (KRB5_CALLCONV * get_name_2)(krb5_context, krb5_ccache,
+ const char **id, const char **res,
+ const char **sub);
+ krb5_error_code (KRB5_CALLCONV * resolve_2)(krb5_context, krb5_ccache *id, const char *res,
+ const char *sub);
+ /* Add new functions here for versions 6 and above */
} krb5_cc_ops;
typedef struct heim_config_binding krb5_config_binding;
/* Create a keyring ccache handle for the given residual string. */
static krb5_error_code KRB5_CALLCONV
-krcc_resolve(krb5_context context,
- krb5_ccache *id,
- const char *residual,
- const char *sub)
+krcc_resolve_2(krb5_context context,
+ krb5_ccache *id,
+ const char *residual,
+ const char *sub)
{
krb5_error_code ret;
key_serial_t collection_id, cache_id;
/* Return an alias to the residual string of the cache. */
static krb5_error_code KRB5_CALLCONV
-krcc_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **collection_name,
- const char **subsidiary_name)
+krcc_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **collection_name,
+ const char **subsidiary_name)
{
krb5_krcache *data = KRCACHE(id);
* be stored at the process or thread level respectively.
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_krcc_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"KEYRING",
- krcc_get_name,
- krcc_resolve,
+ NULL,
+ NULL,
krcc_gen_new,
krcc_initialize,
krcc_destroy,
krcc_lastchange,
krcc_set_kdc_offset,
krcc_get_kdc_offset,
+ krcc_get_name_2,
+ krcc_resolve_2
};
#endif /* HAVE_KEYUTILS_H */
#define MISDEAD(X) ((X)->dead)
static krb5_error_code KRB5_CALLCONV
-mcc_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **col,
- const char **sub)
+mcc_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **col,
+ const char **sub)
{
if (name)
*name = MCACHE(id)->name;
}
static krb5_error_code KRB5_CALLCONV
-mcc_resolve(krb5_context context,
- krb5_ccache *id,
- const char *res,
- const char *sub)
+mcc_resolve_2(krb5_context context,
+ krb5_ccache *id,
+ const char *res,
+ const char *sub)
{
krb5_error_code ret;
krb5_mcache *m;
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_mcc_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"MEMORY",
- mcc_get_name,
- mcc_resolve,
+ NULL,
+ NULL,
mcc_gen_new,
mcc_initialize,
mcc_destroy,
NULL,
mcc_lastchange,
mcc_set_kdc_offset,
- mcc_get_kdc_offset
+ mcc_get_kdc_offset,
+ mcc_get_name_2,
+ mcc_resolve_2
};
krb5_cc_ops *ccops = (krb5_cc_ops *)plugctx;
krb5_error_code ret;
- if (ccops == NULL || ccops->version < KRB5_CC_OPS_VERSION)
+ if (ccops == NULL)
return KRB5_PLUGIN_NO_HANDLE;
ret = krb5_cc_register(context, ccops, TRUE);
*/
static krb5_error_code KRB5_CALLCONV
-scc_get_name(krb5_context context,
- krb5_ccache id,
- const char **name,
- const char **file,
- const char **sub)
+scc_get_name_2(krb5_context context,
+ krb5_ccache id,
+ const char **name,
+ const char **file,
+ const char **sub)
{
if (name)
*name = SCACHE(id)->name;
}
static krb5_error_code KRB5_CALLCONV
-scc_resolve(krb5_context context,
- krb5_ccache *id,
- const char *res,
- const char *sub)
+scc_resolve_2(krb5_context context,
+ krb5_ccache *id,
+ const char *res,
+ const char *sub)
{
krb5_error_code ret;
krb5_scache *s;
ret = _krb5_cc_allocate(context, &krb5_scc_ops, id);
if (ret == 0)
- ret = scc_resolve(context, id, ctx->file, name);
+ ret = scc_resolve_2(context, id, ctx->file, name);
if (ret) {
free(*id);
*id = NULL;
*/
KRB5_LIB_VARIABLE const krb5_cc_ops krb5_scc_ops = {
- KRB5_CC_OPS_VERSION,
+ KRB5_CC_OPS_VERSION_5,
"SCC",
- scc_get_name,
- scc_resolve,
+ NULL,
+ NULL,
scc_gen_new,
scc_initialize,
scc_destroy,
scc_set_default,
NULL,
NULL,
- NULL
+ NULL,
+ scc_get_name_2,
+ scc_resolve_2
};
#endif