]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
ixfrutils: Set a strong umask before writing a zone file
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 31 Aug 2023 12:52:46 +0000 (14:52 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 10 Nov 2023 16:27:15 +0000 (17:27 +0100)
pdns/ixfrutils.cc

index 4c8e37fa6bc6bd9781bc6ebf8159b08331b677d1..12b0a3e11b4e2bf706cefd47d66af3a224b6e96f 100644 (file)
@@ -23,6 +23,8 @@
 #include <cinttypes>
 #include <dirent.h>
 #include <cerrno>
+#include <sys/stat.h>
+
 #include "ixfrutils.hh"
 #include "sstuff.hh"
 #include "dnssecinfra.hh"
@@ -127,32 +129,35 @@ void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::s
 {
   DNSRecord soa;
   auto serial = getSerialFromRecords(records, soa);
-  string fname=directory +"/"+std::to_string(serial);
-  auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fopen((fname+".partial").c_str(), "w"), fclose);
-  if (!fp) {
+  string fname = directory + "/" + std::to_string(serial);
+  /* ensure that the partial zone file will only be accessible by the current user, not even
+     by other users in the same group, and certainly not by other users. */
+  umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+  auto filePtr = std::unique_ptr<FILE, int(*)(FILE*)>(fopen((fname+".partial").c_str(), "w"), fclose);
+  if (!filePtr) {
     throw runtime_error("Unable to open file '"+fname+".partial' for writing: "+stringerror());
   }
 
   records_t soarecord;
   soarecord.insert(soa);
-  if (fprintf(fp.get(), "$ORIGIN %s\n", zone.toString().c_str()) < 0) {
+  if (fprintf(filePtr.get(), "$ORIGIN %s\n", zone.toString().c_str()) < 0) {
     string error = "Error writing to zone file for " + zone.toLogString() + " in file " + fname + ".partial" + ": " + stringerror();
-    fp.reset();
+    filePtr.reset();
     unlink((fname+".partial").c_str());
     throw std::runtime_error(error);
   }
 
   try {
-    writeRecords(fp.get(), soarecord);
-    writeRecords(fp.get(), records);
-    writeRecords(fp.get(), soarecord);
+    writeRecords(filePtr.get(), soarecord);
+    writeRecords(filePtr.get(), records);
+    writeRecords(filePtr.get(), soarecord);
   } catch (runtime_error &e) {
-    fp.reset();
+    filePtr.reset();
     unlink((fname+".partial").c_str());
     throw runtime_error("Error closing zone file for " + zone.toLogString() + " in file " + fname + ".partial" + ": " + e.what());
   }
 
-  if (fclose(fp.release()) != 0) {
+  if (fclose(filePtr.release()) != 0) {
     string error = "Error closing zone file for " + zone.toLogString() + " in file " + fname + ".partial" + ": " + stringerror();
     unlink((fname+".partial").c_str());
     throw std::runtime_error(error);