From ab73d921f43a18769d55b2fdbd2e201963f5a443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Wed, 26 Mar 2008 14:43:11 +0000 Subject: [PATCH] Make the storing credential an atomic write(2) to avoid signal races, bug traced by Harald Bart and Lars Malinowsky. git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@22792 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/krb5/fcache.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/krb5/fcache.c b/lib/krb5/fcache.c index 2b948e7a6..8e3b50a0a 100644 --- a/lib/krb5/fcache.c +++ b/lib/krb5/fcache.c @@ -134,6 +134,30 @@ _krb5_xunlock(krb5_context context, int fd) return ret; } +static krb5_error_code +write_storage(krb5_context context, krb5_storage *sp, int fd) +{ + krb5_error_code ret; + krb5_data data; + ssize_t sret; + + ret = krb5_storage_to_data(sp, &data); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + return ret; + } + sret = write(fd, data.data, data.length); + ret = (sret != data.length); + krb5_data_free(&data); + if (ret) { + ret = errno; + krb5_set_error_string(context, "Failed to write FILE credential data"); + return ret; + } + return 0; +} + + static krb5_error_code fcc_lock(krb5_context context, krb5_ccache id, int fd, krb5_boolean exclusive) @@ -368,7 +392,7 @@ fcc_initialize(krb5_context context, return ret; { krb5_storage *sp; - sp = krb5_storage_from_fd(fd); + sp = krb5_storage_emem(); krb5_storage_set_eof_code(sp, KRB5_CC_END); if(context->fcache_vno != 0) f->version = context->fcache_vno; @@ -391,6 +415,8 @@ fcc_initialize(krb5_context context, } ret |= krb5_store_principal(sp, primary_principal); + ret |= write_storage(context, sp, fd); + krb5_storage_free(sp); } fcc_unlock(context, fd); @@ -433,7 +459,8 @@ fcc_store_cred(krb5_context context, return ret; { krb5_storage *sp; - sp = krb5_storage_from_fd(fd); + + sp = krb5_storage_emem(); krb5_storage_set_eof_code(sp, KRB5_CC_END); storage_set_flags(context, sp, FCACHE(id)->version); if (!krb5_config_get_bool_default(context, NULL, TRUE, @@ -442,15 +469,18 @@ fcc_store_cred(krb5_context context, NULL)) krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER); ret = krb5_store_creds(sp, creds); + if (ret == 0) + ret = write_storage(context, sp, fd); krb5_storage_free(sp); } fcc_unlock(context, fd); - if (close(fd) < 0) + if (close(fd) < 0) { if (ret == 0) { ret = errno; krb5_set_error_string (context, "close %s: %s", FILENAME(id), strerror(ret)); } + } return ret; }