Hi there.

update_usersfile does not only update the usersfile but also overwrites
owner/permissions. this is bad (i think in general). in particular this
is a show stopper for the private usersfile implementation (which is not
complete yet).

the attached patch works around this in my case, but may fail. for
example chown requires some privileges...

i don't know how to seamlessly update a file in place, maybe the proper
solution is to not replace that file at all.

cheers
felix
>From 6f49e1d7527cef3508bfc58cc2d1eb91e8663f61 Mon Sep 17 00:00:00 2001
From: Felix Salfelder <[email protected]>
Date: Sat, 6 Dec 2014 23:13:06 +0100
Subject: [PATCH] restore mode/ownership after rewriting usersfile (workaround)

---
 liboath/oath.h.in   | 4 +++-
 liboath/usersfile.c | 9 +++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/liboath/oath.h.in b/liboath/oath.h.in
index 173592a..8853a8e 100644
--- a/liboath/oath.h.in
+++ b/liboath/oath.h.in
@@ -91,6 +91,7 @@ extern "C"
  * @OATH_FILE_FLUSH_ERROR: System error when flushing file buffer
  * @OATH_FILE_SYNC_ERROR: System error when syncing file to disk
  * @OATH_FILE_CLOSE_ERROR: System error when closing file
+ * @OATH_FILE_MODE_ERROR: System error when closing file
  * @OATH_LAST_ERROR: Meta-error indicating the last error code, for use
  *   when iterating over all error codes or similar.
  *
@@ -129,9 +130,10 @@ typedef enum
   OATH_FILE_FLUSH_ERROR = -23,
   OATH_FILE_SYNC_ERROR = -24,
   OATH_FILE_CLOSE_ERROR = -25,
+  OATH_FILE_MODE_ERROR = -26,
   /* When adding anything here, update OATH_LAST_ERROR, errors.c
      and tests/tst_errors.c. */
-  OATH_LAST_ERROR = -25
+  OATH_LAST_ERROR = -26
 } oath_rc;
 
 /* Global */
diff --git a/liboath/usersfile.c b/liboath/usersfile.c
index 57d9e2a..d8121ce 100644
--- a/liboath/usersfile.c
+++ b/liboath/usersfile.c
@@ -308,6 +308,10 @@ update_usersfile (const char *usersfile,
   FILE *outfh, *lockfh;
   int rc;
   char *newfilename, *lockfile;
+  struct stat ufstat;
+
+  if (fstat(fileno(infh), &ufstat))
+    return OATH_FILE_SEEK_ERROR;
 
   /* Rewind input file. */
   {
@@ -389,6 +393,11 @@ update_usersfile (const char *usersfile,
   if (rc == OATH_OK && fsync (fileno (outfh)) != 0)
     rc = OATH_FILE_SYNC_ERROR;
 
+  /* set mode */
+  if (fchmod(fileno(outfh), ufstat.st_mode) != 0
+    ||fchown(fileno(outfh), ufstat.st_uid, ufstat.st_gid) != 0)
+    rc = OATH_FILE_MODE_ERROR;
+
   /* Close the file regardless of success. */
   if (fclose (outfh) != 0)
     rc = OATH_FILE_CLOSE_ERROR;
-- 
2.0.0

Reply via email to