diff options
author | Simo Sorce <simo@redhat.com> | 2013-08-28 22:12:07 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2013-08-28 22:28:35 -0400 |
commit | c0b30b30d087cfa1051b86c432fdbda8c03e9f9d (patch) | |
tree | 6517a0e29576afe39249301d691b8abd6c8f0d8c | |
parent | 44a9fd23f1da009e03f60e4d297a5e1d51caa533 (diff) | |
download | sssd-c0b30b30d087cfa1051b86c432fdbda8c03e9f9d.tar.gz sssd-c0b30b30d087cfa1051b86c432fdbda8c03e9f9d.tar.xz sssd-c0b30b30d087cfa1051b86c432fdbda8c03e9f9d.zip |
krb5: Add helper to destroy ccache as user
This function safely destroy a ccache given a cache name and user crdentials.
It becomes the user so no possible races can compromise the system, then
uses libkrb5 functions to properly destroy a ccache, independently of the
cache type.
Finally restores the original credentials after closing the ccache handlers.
Resolves:
https://fedorahosted.org/sssd/ticket/2061
-rw-r--r-- | src/providers/krb5/krb5_utils.c | 112 | ||||
-rw-r--r-- | src/providers/krb5/krb5_utils.h | 2 |
2 files changed, 114 insertions, 0 deletions
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c index dc4c448ef..52eb075bc 100644 --- a/src/providers/krb5/krb5_utils.c +++ b/src/providers/krb5/krb5_utils.c @@ -833,6 +833,118 @@ done: } +struct sss_krb5_ccache { + struct sss_creds *creds; + krb5_context context; + krb5_ccache ccache; +}; + +static errno_t sss_close_ccache(struct sss_krb5_ccache *cc); + +static errno_t sss_open_ccache_as_user(const char *ccname, + uid_t uid, gid_t gid, + struct sss_krb5_ccache **ccache) +{ + struct sss_krb5_ccache *cc; + krb5_error_code kerr; + errno_t ret; + + cc = calloc(sizeof(struct sss_krb5_ccache), 1); + if (!cc) { + return ENOMEM; + } + + ret = switch_creds(uid, gid, 0, NULL, &cc->creds); + if (ret) { + free(cc); + return ret; + } + + kerr = krb5_init_context(&cc->context); + if (kerr) { + ret = EIO; + goto done; + } + + kerr = krb5_cc_resolve(cc->context, ccname, &cc->ccache); + if (kerr == KRB5_FCC_NOFILE || cc->ccache == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, ("ccache %s is missing or empty\n", ccname)); + ret = ERR_NOT_FOUND; + goto done; + } else if (kerr != 0) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr); + DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n")); + ret = EIO; + goto done; + } + + ret = EOK; + +done: + if (ret) { + sss_close_ccache(cc); + } else { + *ccache = cc; + } + return ret; +} + +static errno_t sss_destroy_ccache(struct sss_krb5_ccache *cc) +{ + krb5_error_code kerr; + errno_t ret; + + kerr = krb5_cc_destroy(cc->context, cc->ccache); + if (kerr) { + KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr); + DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_destroy failed.\n")); + ret = EIO; + } + + /* krb5_cc_destroy frees cc->ccache in all events */ + cc->ccache = NULL; + + return ret; +} + +static errno_t sss_close_ccache(struct sss_krb5_ccache *cc) +{ + krb5_error_code kerr = 0; + errno_t ret; + + if (cc->ccache) { + kerr = krb5_cc_close(cc->context, cc->ccache); + } + krb5_free_context(cc->context); + + ret = restore_creds(cc->creds); + + free(cc->creds); + free(cc); + + if (kerr) return EIO; + return ret; +} + +errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid) +{ + struct sss_krb5_ccache *cc = NULL; + errno_t ret; + + ret = sss_open_ccache_as_user(ccname, uid, gid, &cc); + if (ret) { + return ret; + } + + ret = sss_destroy_ccache(cc); + if (ret) { + sss_close_ccache(cc); + return ret; + } + + return sss_close_ccache(cc); +} + /*======== ccache back end utilities ========*/ struct sss_krb5_cc_be * diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h index a05c0dfcd..f7088481f 100644 --- a/src/providers/krb5/krb5_utils.h +++ b/src/providers/krb5/krb5_utils.h @@ -86,6 +86,8 @@ errno_t switch_creds(uid_t uid, gid_t gid, struct sss_creds **saved_creds); errno_t restore_creds(struct sss_creds *saved_creds); +errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid); + errno_t get_ccache_file_data(const char *ccache_file, const char *client_name, struct tgt_times *tgtt); |