/* SSSD KCM Server - the KCM ccache operations Copyright (C) Red Hat, 2016 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef _KCMSRV_CCACHE_H_ #define _KCMSRV_CCACHE_H_ #include "config.h" #include #include #include "util/util.h" #include "util/sss_iobuf.h" #include "util/util_creds.h" #include "providers/krb5/krb5_common.h" #include "responder/kcm/kcmsrv_pvt.h" #define UUID_BYTES 16 #define UUID_STR_SIZE 37 /* Just to keep the name of the ccache readable */ #define MAX_CC_NUM 99999 /* * Credentials are opaque to the KCM server * * Each ccache has a unique UUID. */ struct kcm_cred; /* * An opaque ccache type and its operations * * Contains zero or some KCM credentials. One credential in the cache * is marked as the default one. The client can set and get the default * cache (e.g. with kswitch) but one cache is always the default -- we * fall back to the one created first. * * Each cache has a name and a UUID. Heimdal allows the name to be changed, * we don't (yet, because the MIT client doesn't allow that either) * * Each ccache also stores a client principal. */ struct kcm_ccache; /* * Create a new KCM ccache owned by mem_ctx on the * memory level. * * When created, the ccache contains no credentials */ errno_t kcm_cc_new(TALLOC_CTX *mem_ctx, krb5_context k5c, struct cli_creds *owner, const char *name, krb5_principal princ, struct kcm_ccache **_cc); /* * Duplicate the ccache. Only ccache and credentials are duplicated, * but their data are a shallow copy. */ struct kcm_ccache *kcm_cc_dup(TALLOC_CTX *mem_ctx, const struct kcm_ccache *cc); /* * Returns true if a client can access a ccache. * * Note that root can access any ccache */ bool kcm_cc_access(struct kcm_ccache *cc, struct cli_creds *client); /* * Since the kcm_ccache structure is opaque, the kcmsrv_ccache * layer contains a number of getsetters to read and write * properties of the kcm_ccache structure */ const char *kcm_cc_get_name(struct kcm_ccache *cc); errno_t kcm_cc_get_uuid(struct kcm_ccache *cc, uuid_t _uuid); krb5_principal kcm_cc_get_client_principal(struct kcm_ccache *cc); int32_t kcm_cc_get_offset(struct kcm_ccache *cc); /* Mainly useful for creating a cred structure from a persistent * storage */ struct kcm_cred *kcm_cred_new(TALLOC_CTX *mem_ctx, uuid_t uuid, struct sss_iobuf *cred_blob); /* Add a cred to ccache */ errno_t kcm_cc_store_creds(struct kcm_ccache *cc, struct kcm_cred *crd); /* Set cc header information from sec key and client */ errno_t kcm_cc_set_header(struct kcm_ccache *cc, const char *sec_key, struct cli_creds *client); krb5_creds **kcm_cc_unmarshal(TALLOC_CTX *mem_ctx, krb5_context krb_context, struct kcm_ccache *cc); errno_t kcm_cred_get_uuid(struct kcm_cred *crd, uuid_t uuid); /* * At the moment, the credentials are stored without unmarshalling * them, just as the clients sends the credentials. */ struct sss_iobuf *kcm_cred_get_creds(struct kcm_cred *crd); errno_t kcm_cc_store_cred_blob(struct kcm_ccache *cc, struct sss_iobuf *cred_blob); /* * The KCM server can call kcm_cred_get_creds to fetch the first * credential, then iterate over the credentials with * kcm_cc_next_cred until it returns NULL */ struct kcm_cred *kcm_cc_get_cred(struct kcm_ccache *cc); struct kcm_cred *kcm_cc_next_cred(struct kcm_cred *crd); /* An opaque database that contains all the ccaches */ struct kcm_ccdb; /* * Initialize a ccache database of type cc_be */ struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct confdb_ctx *cdb, const char *confdb_service_path, enum kcm_ccdb_be cc_be); /* * Prepare KCM ccache list for renewals */ errno_t kcm_ccdb_renew_tgts(TALLOC_CTX *mem_ctx, struct krb5_ctx *kctx, struct tevent_context *ev, struct kcm_ccdb *cdb, struct kcm_ccache ***_cc_list); /* * In KCM, each ccache name is usually in the form of "UID: * * The is generated by the KCM ccache database. Use this function * to retrieve the next number */ struct tevent_req *kcm_ccdb_nextid_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client); errno_t kcm_ccdb_nextid_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, char **_nextid); /* * List all ccaches that belong to a given client * * The cc_list the recv function returns is NULL-terminated. * * NOTE: Contrary to how Heimdal behaves, root CAN NOT list all ccaches * of all users. This is a deliberate decision to treat root as any other * user, except it can access a ccache of another user by name, just not * list them. * * If a client has no ccaches, the function returns OK, but an empty list * containing just the NULL sentinel. */ struct tevent_req *kcm_ccdb_list_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client); errno_t kcm_ccdb_list_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uuid_t **_uuid_list); /* * Retrieve a ccache by name. * * If there is no such ccache, return EOK, but a NULL _cc pointer */ struct tevent_req *kcm_ccdb_getbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, const char *name); errno_t kcm_ccdb_getbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct kcm_ccache **_cc); /* * Retrieve a ccache by UUID * * If there is no such ccache, return EOK, but a NULL _cc pointer */ struct tevent_req *kcm_ccdb_getbyuuid_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, uuid_t uuid); errno_t kcm_ccdb_getbyuuid_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct kcm_ccache **_cc); /* * Retrieve the default ccache. If there is no default cache, * return EOK, but a NULL UUID. */ struct tevent_req *kcm_ccdb_get_default_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client); errno_t kcm_ccdb_get_default_recv(struct tevent_req *req, uuid_t *uuid); /* * Translating name to UUID is often considerably faster than doing a full * CC retrieval, hence this function and the converse. If the UUID cannot * be found in the database, return ERR_KCM_CC_END */ struct tevent_req *kcm_ccdb_name_by_uuid_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, uuid_t uuid); errno_t kcm_ccdb_name_by_uuid_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, const char **_name); /* * Translating UUID to name is often considerably faster than doing a full * CC retrieval, hence this function and the converse. If the UUID cannot * be found in the database, return ERR_KCM_CC_END */ struct tevent_req *kcm_ccdb_uuid_by_name_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, const char *name); errno_t kcm_ccdb_uuid_by_name_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uuid_t _uuid); /* * Set the default ccache. Passing a NULL UUID is a legal operation * that 'unsets' the default ccache. */ struct tevent_req *kcm_ccdb_set_default_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, uuid_t uuid); errno_t kcm_ccdb_set_default_recv(struct tevent_req *req); /* * Add a ccache to the database. */ struct tevent_req *kcm_ccdb_create_cc_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, struct kcm_ccache *cc); errno_t kcm_ccdb_create_cc_recv(struct tevent_req *req); /* * Modify cache properties in a db */ struct kcm_mod_ctx { int32_t kdc_offset; krb5_principal client; /* More settable properties (like name, when we support renames * will be added later */ }; struct kcm_mod_ctx *kcm_mod_ctx_new(TALLOC_CTX *mem_ctx); errno_t kcm_mod_cc(struct kcm_ccache *cc, struct kcm_mod_ctx *mod_ctx); struct tevent_req *kcm_ccdb_mod_cc_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, uuid_t uuid, struct kcm_mod_ctx *mod_cc); errno_t kcm_ccdb_mod_cc_recv(struct tevent_req *req); /* * Store a credential in a cache */ struct tevent_req *kcm_ccdb_store_cred_blob_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, uuid_t uuid, struct sss_iobuf *cred_blob); errno_t kcm_ccdb_store_cred_blob_recv(struct tevent_req *req); /* * Delete a ccache from the database */ struct tevent_req *kcm_ccdb_delete_cc_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct kcm_ccdb *db, struct cli_creds *client, uuid_t uuid); errno_t kcm_ccdb_delete_cc_recv(struct tevent_req *req); void kcm_debug_uuid(uuid_t uuid); /* * The KCM clients are not allowed (except root) to create ccaches * with arbitrary names. Instead, we assert that the ccache name * begins with UID where UID is the stringified representation of * the client's UID number */ errno_t kcm_check_name(const char *name, struct cli_creds *client); /* * ccahe marshalling to and from JSON. This is used when the ccaches * are stored in the secrets store */ /* * The secrets store is a key-value store at heart. We store the UUID * and the name in the key to allow easy lookups be either key */ bool sec_key_match_name(const char *sec_key, const char *name); bool sec_key_match_uuid(const char *sec_key, uuid_t uuid); errno_t sec_key_parse(TALLOC_CTX *mem_ctx, const char *sec_key, const char **_name, uuid_t uuid); const char *sec_key_get_name(const char *sec_key); errno_t sec_key_get_uuid(const char *sec_key, uuid_t uuid); const char *sec_key_create(TALLOC_CTX *mem_ctx, const char *name, uuid_t uuid); /* * sec_key is a concatenation of the ccache's UUID and name * sec_value is the binary representation of ccache. */ errno_t sec_kv_to_ccache_binary(TALLOC_CTX *mem_ctx, const char *sec_key, struct sss_iobuf *sec_value, struct cli_creds *client, struct kcm_ccache **_cc); /* Convert a kcm_ccache to its binary representation. */ errno_t kcm_ccache_to_sec_input_binary(TALLOC_CTX *mem_ctx, struct kcm_ccache *cc, struct sss_iobuf **_payload); errno_t bin_to_krb_data(TALLOC_CTX *mem_ctx, struct sss_iobuf *buf, krb5_data *out); #endif /* _KCMSRV_CCACHE_H_ */