diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2014-08-26 09:43:09 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-08-26 16:45:38 +0200 |
commit | 5c075562ac687f7102c7c940fec2e82da378bfff (patch) | |
tree | c4627ef46ceae84b6223ce78f970b5372935f9ab /src | |
parent | ad9d65039fd15a9b63b5772c0c4cdc29ffac93fa (diff) | |
download | sssd-5c075562ac687f7102c7c940fec2e82da378bfff.tar.gz sssd-5c075562ac687f7102c7c940fec2e82da378bfff.tar.xz sssd-5c075562ac687f7102c7c940fec2e82da378bfff.zip |
LDAP: Use randomized ccname for storing credentials
https://fedorahosted.org/sssd/ticket/2410
If two ldap_child processes attempt to prime the ccache at the same time
for the same domain, the ldap_child might fail with:
[ldap_child_get_tgt_sync] (0x0040): Failed to init ccache: Internal credentials cache error
[main] (0x0020): ldap_child_get_tgt_sync failed.
To avoid the race-condition, the ldap_child process now creates the
ccache randomized and before returning to the caller, renames the
randomized ccache to a permanent one.
Reviewed-by: Sumit Bose <sbose@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/providers/ldap/ldap_child.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c index d0552d57c..6ef7bd204 100644 --- a/src/providers/ldap/ldap_child.c +++ b/src/providers/ldap/ldap_child.c @@ -168,7 +168,9 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, const char **ccname_out, time_t *expire_time_out) { + int fd; char *ccname; + char *ccname_dummy; char *realm_name = NULL; char *full_princ = NULL; char *default_realm = NULL; @@ -185,6 +187,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, int kdc_time_offset_usec; int ret; TALLOC_CTX *tmp_ctx; + char *ccname_file_dummy; + char *ccname_file; krberr = krb5_init_context(&context); if (krberr) { @@ -290,14 +294,34 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, goto done; } - ccname = talloc_asprintf(tmp_ctx, "FILE:%s/ccache_%s", DB_PATH, realm_name); - if (!ccname) { - krberr = KRB5KRB_ERR_GENERIC; + ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX", + DB_PATH, realm_name); + ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s", + DB_PATH, realm_name); + if (ccname_file_dummy == NULL || ccname_file == NULL) { + ret = ENOMEM; goto done; } - DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname); - krberr = krb5_cc_resolve(context, ccname, &ccache); + fd = mkstemp(ccname_file_dummy); + if (fd == -1) { + ret = errno; + goto done; + } + /* We only care about creating a unique file name here, we don't + * need the fd + */ + close(fd); + + ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy); + ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file); + if (ccname_dummy == NULL || ccname == NULL) { + krberr = ENOMEM; + goto done; + } + DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy); + + krberr = krb5_cc_resolve(context, ccname_dummy, &ccache); if (krberr) { DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n", sss_krb5_get_error_message(context, krberr)); @@ -368,6 +392,16 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, kdc_time_offset = 0; #endif + DEBUG(SSSDBG_TRACE_INTERNAL, + "Renaming [%s] to [%s]\n", ccname_file_dummy, ccname_file); + ret = rename(ccname_file_dummy, ccname_file); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "rename failed [%d][%s].\n", ret, strerror(ret)); + goto done; + } + krberr = 0; *ccname_out = talloc_steal(memctx, ccname); *expire_time_out = my_creds.times.endtime - kdc_time_offset; |