summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2014-08-26 09:43:09 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-08-26 16:53:19 +0200
commitba327d62561c86284328f86d7a3317998329dffd (patch)
tree31458b1e6b7b785dc6cbddedb9c6fefae42a7628
parent0234400240d1dbdc05ed0faccf8330b2c0528d6d (diff)
downloadsssd-ba327d62561c86284328f86d7a3317998329dffd.tar.gz
sssd-ba327d62561c86284328f86d7a3317998329dffd.tar.xz
sssd-ba327d62561c86284328f86d7a3317998329dffd.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>
-rw-r--r--src/providers/ldap/ldap_child.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index 7d793bbe4..fbdf89a26 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;