diff --git a/security/acme-client/pkg-descr b/security/acme-client/pkg-descr
index d9d83c57b..8f7f21ace 100644
--- a/security/acme-client/pkg-descr
+++ b/security/acme-client/pkg-descr
@@ -13,10 +13,12 @@ Plugin Changelog
Added:
* new automation to reload www/caddy (#4692)
* add support for Websupport.sk DNS API (#4540)
+* add SFTP option: Preserve Modification Time (#3862)
Changed:
* automatically fix account config if CERT_HOME is set (#4622)
* automatically resolve cron job mismatch (#4627)
+* change default SFTP options to NOT preserve modification time (#3862)
Fixed:
* deploy hooks may use the old CERT_HOME (#4622)
diff --git a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml
index a2fb434eb..292fd9c23 100644
--- a/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml
+++ b/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient/forms/dialogAction.xml
@@ -68,6 +68,12 @@
The path can be absolute or relative to home and must exist.
Leave blank to not change path after login.
+
+ action.sftp_modtime
+
+ checkbox
+ Preserves modification times from the source file. Note that this is not supported by all SFTP servers and may cause the upload to fail, e.g. on VMware
+ action.sftp_chmod
diff --git a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/SftpUploader.php b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/SftpUploader.php
index 353495880..d7b5df79a 100644
--- a/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/SftpUploader.php
+++ b/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/SftpUploader.php
@@ -1,6 +1,7 @@
$local_file,
"target" => $remote_file,
"mode" => $chmod,
- "group" => $chgrp
+ "group" => $chgrp,
+ "modtime" => $modtime
];
return $local_file;
@@ -94,9 +99,10 @@ class SftpUploader
* @param int $content_last_modified the unix timestamp when the content was last modified (is preserved when chmod is also specified).
* @param bool $chmod the 4 digit unix permission to apply or false to leave it unchanged.
* @param bool $chgrp the numeric group on the remote server to apply or false to leave it unchanged.
+ * @param bool $modtime a boolean to indicate that the modification times should be preserved.
* @return string the name of the remote file.
*/
- public function addContent(string $content, string $remote_file = "", $content_last_modified = 0, $chmod = false, $chgrp = false): string
+ public function addContent(string $content, string $remote_file = "", $content_last_modified = 0, $chmod = false, $chgrp = false, $modtime = false): string
{
$local_file = $this->temporaryFile();
Utils::requireThat($local_file, "Failed creating temporary file for '$remote_file'");
@@ -113,7 +119,7 @@ class SftpUploader
$remote_file = basename($local_file);
}
- $local_file = $this->addFile($local_file, $remote_file, $chmod, $chgrp);
+ $local_file = $this->addFile($local_file, $remote_file, $chmod, $chgrp, $modtime);
$this->pending_files[$local_file]["delete_source"] = true;
return $remote_file;
@@ -252,16 +258,24 @@ class SftpUploader
$chmod = $file["mode"] ?? "";
$chmod = preg_match('/^0\d{3}$/', $chmod) ? (string)$chmod : false;
+ // Preserving the modification time is not supported by all SFTP servers.
+ $preserve = $file["modtime"];
+ if ($preserve !== false) {
+ LeUtils::log("Sftp upload will try to preserve file modification time");
+ } else {
+ LeUtils::log("Sftp upload will not preserve file modification time");
+ }
// Initial upload when permissions are properly set.
$should_upload_with_permission_change =
$chmod !== false
&& isset($remote_files[$remote_filename]);
+ // Upload file.
if (!$remote_is_readonly) {
$preserve_times_and_mod = $chmod !== false;
- if ($error = $this->sftp->put($local_file, $remote_filename, $preserve_times_and_mod)->lastError()) {
+ if ($error = $this->sftp->put($local_file, $remote_filename, $preserve)->lastError()) {
if ($error["permission_denied"] !== true) {
$should_upload_with_permission_change = false;
}
@@ -281,11 +295,13 @@ class SftpUploader
if ($should_upload_with_permission_change && $this->isFileOwnedByConnection($remote_file, $connection)) {
Utils::log()->info("Trying to upload file '{$local_file}' to '{$file["target"]}' with adjusted permissions");
+ // Change file permission to make it writable.
if ($error = $this->sftp->chmod($remote_filename, '0600')->lastError()) {
Utils::log()->error("Failed changing permission to '0600' for '{$file["target"]}'. ", $error);
$this->sftp->clearError();
}
+ // Try again to upload file.
if ($error = $this->sftp->put($local_file, $remote_filename)->lastError()) {
Utils::log()->error("Failed uploading file (with adjusted permissions) '{$local_file}' to '{$file["target"]}'", $error);
return self::UPLOAD_ERROR_NO_PERMISSION;
diff --git a/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml b/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml
index 4a3a31dcf..8d4b88475 100644
--- a/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml
+++ b/security/acme-client/src/opnsense/mvc/app/models/OPNsense/AcmeClient/AcmeClient.xml
@@ -1,6 +1,6 @@
//OPNsense/AcmeClient
- 4.2.0
+ 4.3.0A secure ACME Client plugin
@@ -1410,6 +1410,10 @@
/^0[0-9]{3}$/uA unix permission, 4 digits (e.g. 0400).
+
+ N
+ 0
+ N/^(?![\/\\])[\w\d_\-@.\/{}%]{1,255}(?<![\/\\])$/ui