From 48f8d87418052b5bb05f157063181c6004aa5f09 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 5 Jul 2026 07:55:39 +0900 Subject: [PATCH] OpenBSD: add FFS volume formatting support Expose FFS as the native OpenBSD filesystem option for volume creation and accept FFS/UFS on the command line, mapping mounts to the OpenBSD ffs filesystem type. Run newfs through the elevated core service on vnd raw devices, then temporarily mount the new filesystem to transfer root directory ownership back to the invoking user. Keep the non-interactive creation default as FAT on OpenBSD so existing unattended scripts do not start requiring elevation. --- src/Core/Unix/CoreService.cpp | 187 ++++++++++++++++++ src/Core/Unix/CoreService.h | 4 + src/Core/Unix/CoreServiceRequest.cpp | 29 +++ src/Core/Unix/CoreServiceRequest.h | 16 ++ src/Core/Unix/CoreServiceResponse.cpp | 15 ++ src/Core/Unix/CoreServiceResponse.h | 8 + src/Core/VolumeCreator.h | 7 +- src/Main/CommandLineInterface.cpp | 6 + src/Main/Forms/VolumeCreationWizard.cpp | 43 ++-- .../Forms/VolumeFormatOptionsWizardPage.cpp | 3 + src/Main/OpenBSDFormatterDevice.h | 123 ++++++++++++ src/Main/TextUserInterface.cpp | 51 +++-- src/Main/UserInterface.cpp | 4 + 13 files changed, 471 insertions(+), 25 deletions(-) create mode 100644 src/Main/OpenBSDFormatterDevice.h diff --git a/src/Core/Unix/CoreService.cpp b/src/Core/Unix/CoreService.cpp index fd7bc577..ae7381ff 100644 --- a/src/Core/Unix/CoreService.cpp +++ b/src/Core/Unix/CoreService.cpp @@ -914,6 +914,168 @@ namespace VeraCrypt } #endif +#ifdef TC_OPENBSD + static bool ParseOpenBSDVndDevicePath (const string &path, bool rawDevice, string &deviceNumber) + { + const string prefix = rawDevice ? "/dev/rvnd" : "/dev/vnd"; + if (path.find (prefix) != 0) + return false; + + size_t numberStart = prefix.size(); + size_t numberEnd = numberStart; + while (numberEnd < path.size() && path[numberEnd] >= '0' && path[numberEnd] <= '9') + ++numberEnd; + + if (numberEnd == numberStart) + return false; + + if (numberEnd + 1 != path.size() || path[numberEnd] != 'c') + return false; + + deviceNumber = path.substr (numberStart, numberEnd - numberStart); + return true; + } + + static string GetOpenBSDVndBlockDevicePath (const DevicePath &rawDevice) + { + string deviceNumber; + if (!ParseOpenBSDVndDevicePath (string (rawDevice), true, deviceNumber)) + throw ParameterIncorrect (SRC_POS); + + return string ("/dev/vnd") + deviceNumber + "c"; + } + + static void ValidateOpenBSDVndDeviceNode (const string &path, bool rawDevice) + { + string deviceNumber; + if (!ParseOpenBSDVndDevicePath (path, rawDevice, deviceNumber)) + throw ParameterIncorrect (SRC_POS); + + struct stat sb; + if (lstat (path.c_str(), &sb) != 0) + throw ParameterIncorrect (SRC_POS); + + if (rawDevice) + { + if (!S_ISCHR (sb.st_mode)) + throw ParameterIncorrect (SRC_POS); + } + else if (!S_ISBLK (sb.st_mode)) + throw ParameterIncorrect (SRC_POS); + } + + static void ValidateOpenBSDFFSFormatterRequest (const ExecuteOpenBSDFFSFormatterRequest &request) + { + ValidateOpenBSDVndDeviceNode (string (request.Device), true); + ValidateOpenBSDVndDeviceNode (GetOpenBSDVndBlockDevicePath (request.Device), false); + + if (request.OwnerUserId > static_cast ((uid_t) -1) + || request.OwnerGroupId > static_cast ((gid_t) -1)) + { + throw ParameterIncorrect (SRC_POS); + } + } + + static list BuildOpenBSDFFSFormatterArguments (const ExecuteOpenBSDFFSFormatterRequest &request) + { + ValidateOpenBSDFFSFormatterRequest (request); + + list arguments; + arguments.push_back (string (request.Device)); + return arguments; + } + + static DirectoryPath CreateOpenBSDFFSTemporaryMountPoint () + { + string mountPointTemplate = "/tmp/veracrypt-ffs.XXXXXXXXXX"; + vector mountPoint (mountPointTemplate.begin(), mountPointTemplate.end()); + mountPoint.push_back ('\0'); + + char *createdPath = mkdtemp (&mountPoint.front()); + throw_sys_sub_if (!createdPath, mountPointTemplate); + + return DirectoryPath (createdPath); + } + + static void RemoveOpenBSDFFSTemporaryMountPoint (const DirectoryPath &mountPoint) + { + if (!mountPoint.IsEmpty()) + rmdir (string (mountPoint).c_str()); + } + + static void MountOpenBSDFFSTemporaryFilesystem (const DevicePath &devicePath, const DirectoryPath &mountPoint) + { + list args; + args.push_back ("-t"); + args.push_back ("ffs"); + args.push_back ("-o"); + args.push_back ("nodev,nosuid,noexec"); + args.push_back ("--"); + args.push_back (devicePath); + args.push_back (mountPoint); + + Process::Execute ("mount", args); + } + + static void DismountOpenBSDFFSTemporaryFilesystem (const DirectoryPath &mountPoint) + { + list args; + args.push_back ("--"); + args.push_back (mountPoint); + + for (int attempt = 0; true; ++attempt) + { + try + { + Process::Execute ("umount", args); + return; + } + catch (ExecutedProcessFailed&) + { + if (attempt >= 5) + throw; + Thread::Sleep (200); + } + } + } + + static void SetOpenBSDFFSRootOwner (const ExecuteOpenBSDFFSFormatterRequest &request) + { + ValidateOpenBSDFFSFormatterRequest (request); + + DirectoryPath mountPoint = CreateOpenBSDFFSTemporaryMountPoint(); + bool mounted = false; + + try + { + MountOpenBSDFFSTemporaryFilesystem (DevicePath (GetOpenBSDVndBlockDevicePath (request.Device)), mountPoint); + mounted = true; + + string mountPointStr = mountPoint; + throw_sys_sub_if (chown (mountPointStr.c_str(), static_cast (request.OwnerUserId), static_cast (request.OwnerGroupId)) == -1, mountPointStr); + + DismountOpenBSDFFSTemporaryFilesystem (mountPoint); + mounted = false; + + throw_sys_sub_if (rmdir (mountPointStr.c_str()) == -1, mountPointStr); + } + catch (...) + { + if (mounted) + { + try + { + DismountOpenBSDFFSTemporaryFilesystem (mountPoint); + } + catch (...) { } + } + + RemoveOpenBSDFFSTemporaryMountPoint (mountPoint); + throw; + } + } +#endif + unique_ptr CoreService::GetResponseObject () { unique_ptr deserializedObject (Serializable::DeserializeNew (ServiceOutputStream)); @@ -1131,6 +1293,18 @@ namespace VeraCrypt } #endif +#ifdef TC_OPENBSD + // ExecuteOpenBSDFFSFormatterRequest + ExecuteOpenBSDFFSFormatterRequest *executeFFSFormatterRequest = dynamic_cast (request.get()); + if (executeFFSFormatterRequest) + { + Process::Execute (CoreService::GetOpenBSDFFSFormatterPath(), BuildOpenBSDFFSFormatterArguments (*executeFFSFormatterRequest)); + SetOpenBSDFFSRootOwner (*executeFFSFormatterRequest); + ExecuteOpenBSDFFSFormatterResponse().Serialize (outputStream); + continue; + } +#endif + // MountVolumeRequest MountVolumeRequest *mountRequest = dynamic_cast (request.get()); if (mountRequest) @@ -1237,6 +1411,19 @@ namespace VeraCrypt } #endif +#ifdef TC_OPENBSD + const char *CoreService::GetOpenBSDFFSFormatterPath () + { + return "/sbin/newfs"; + } + + void CoreService::RequestExecuteOpenBSDFFSFormatter (const DevicePath &devicePath, uint64 userId, uint64 groupId) + { + ExecuteOpenBSDFFSFormatterRequest request (devicePath, userId, groupId); + SendRequest (request); + } +#endif + shared_ptr CoreService::RequestMountVolume (MountOptions &options) { MountVolumeRequest request (&options); diff --git a/src/Core/Unix/CoreService.h b/src/Core/Unix/CoreService.h index 1979a589..f11f259c 100644 --- a/src/Core/Unix/CoreService.h +++ b/src/Core/Unix/CoreService.h @@ -38,6 +38,10 @@ namespace VeraCrypt #ifdef TC_MACOSX static const char *GetMacOSXAPFSFormatterPath (); static void RequestExecuteMacOSXAPFSFormatter (const DevicePath &devicePath, uint64 userId, uint64 groupId); +#endif +#ifdef TC_OPENBSD + static const char *GetOpenBSDFFSFormatterPath (); + static void RequestExecuteOpenBSDFFSFormatter (const DevicePath &devicePath, uint64 userId, uint64 groupId); #endif static shared_ptr RequestMountVolume (MountOptions &options); static void RequestSetFileOwner (const FilesystemPath &path, const UserId &owner); diff --git a/src/Core/Unix/CoreServiceRequest.cpp b/src/Core/Unix/CoreServiceRequest.cpp index 84fdfd5c..e9fcc112 100644 --- a/src/Core/Unix/CoreServiceRequest.cpp +++ b/src/Core/Unix/CoreServiceRequest.cpp @@ -245,6 +245,32 @@ namespace VeraCrypt } #endif +#ifdef TC_OPENBSD + // ExecuteOpenBSDFFSFormatterRequest + void ExecuteOpenBSDFFSFormatterRequest::Deserialize (shared_ptr stream) + { + CoreServiceRequest::Deserialize (stream); + Serializer sr (stream); + Device = sr.DeserializeWString ("Device"); + sr.Deserialize ("OwnerGroupId", OwnerGroupId); + sr.Deserialize ("OwnerUserId", OwnerUserId); + } + + bool ExecuteOpenBSDFFSFormatterRequest::RequiresElevation () const + { + return !Core->HasAdminPrivileges(); + } + + void ExecuteOpenBSDFFSFormatterRequest::Serialize (shared_ptr stream) const + { + CoreServiceRequest::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("Device", wstring (Device)); + sr.Serialize ("OwnerGroupId", OwnerGroupId); + sr.Serialize ("OwnerUserId", OwnerUserId); + } +#endif + // MountVolumeRequest void MountVolumeRequest::Deserialize (shared_ptr stream) { @@ -322,6 +348,9 @@ namespace VeraCrypt TC_SERIALIZER_FACTORY_ADD_CLASS (ExitRequest); #ifdef TC_MACOSX TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteMacOSXAPFSFormatterRequest); +#endif +#ifdef TC_OPENBSD + TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteOpenBSDFFSFormatterRequest); #endif TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSectorSizeRequest); TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeRequest); diff --git a/src/Core/Unix/CoreServiceRequest.h b/src/Core/Unix/CoreServiceRequest.h index 7222ea32..10e4eeb4 100644 --- a/src/Core/Unix/CoreServiceRequest.h +++ b/src/Core/Unix/CoreServiceRequest.h @@ -142,6 +142,22 @@ namespace VeraCrypt }; #endif +#ifdef TC_OPENBSD + struct ExecuteOpenBSDFFSFormatterRequest : CoreServiceRequest + { + ExecuteOpenBSDFFSFormatterRequest () { } + ExecuteOpenBSDFFSFormatterRequest (const DevicePath &devicePath, uint64 userId, uint64 groupId) + : Device (devicePath), OwnerGroupId (groupId), OwnerUserId (userId) { } + TC_SERIALIZABLE (ExecuteOpenBSDFFSFormatterRequest); + + virtual bool RequiresElevation () const; + + DevicePath Device; + uint64 OwnerGroupId; + uint64 OwnerUserId; + }; +#endif + struct MountVolumeRequest : CoreServiceRequest { MountVolumeRequest () { } diff --git a/src/Core/Unix/CoreServiceResponse.cpp b/src/Core/Unix/CoreServiceResponse.cpp index e14eea2b..0209635d 100644 --- a/src/Core/Unix/CoreServiceResponse.cpp +++ b/src/Core/Unix/CoreServiceResponse.cpp @@ -110,6 +110,18 @@ namespace VeraCrypt } #endif +#ifdef TC_OPENBSD + // ExecuteOpenBSDFFSFormatterResponse + void ExecuteOpenBSDFFSFormatterResponse::Deserialize (shared_ptr stream) + { + } + + void ExecuteOpenBSDFFSFormatterResponse::Serialize (shared_ptr stream) const + { + Serializable::Serialize (stream); + } +#endif + // MountVolumeResponse void MountVolumeResponse::Deserialize (shared_ptr stream) { @@ -143,6 +155,9 @@ namespace VeraCrypt TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesResponse); #ifdef TC_MACOSX TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteMacOSXAPFSFormatterResponse); +#endif +#ifdef TC_OPENBSD + TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteOpenBSDFFSFormatterResponse); #endif TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeResponse); TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerResponse); diff --git a/src/Core/Unix/CoreServiceResponse.h b/src/Core/Unix/CoreServiceResponse.h index d6c318ba..61c7d31f 100644 --- a/src/Core/Unix/CoreServiceResponse.h +++ b/src/Core/Unix/CoreServiceResponse.h @@ -83,6 +83,14 @@ namespace VeraCrypt }; #endif +#ifdef TC_OPENBSD + struct ExecuteOpenBSDFFSFormatterResponse : CoreServiceResponse + { + ExecuteOpenBSDFFSFormatterResponse () { } + TC_SERIALIZABLE (ExecuteOpenBSDFFSFormatterResponse); + }; +#endif + struct MountVolumeResponse : CoreServiceResponse { MountVolumeResponse () { } diff --git a/src/Core/VolumeCreator.h b/src/Core/VolumeCreator.h index 0e842556..78862a72 100644 --- a/src/Core/VolumeCreator.h +++ b/src/Core/VolumeCreator.h @@ -55,7 +55,8 @@ namespace VeraCrypt Btrfs, MacOsExt, APFS, - UFS + UFS, + FFS }; static Enum GetPlatformNative () @@ -68,6 +69,8 @@ namespace VeraCrypt return VolumeCreationOptions::FilesystemType::MacOsExt; #elif defined (TC_FREEBSD) || defined (TC_SOLARIS) return VolumeCreationOptions::FilesystemType::UFS; +#elif defined (TC_OPENBSD) + return VolumeCreationOptions::FilesystemType::FFS; #else return VolumeCreationOptions::FilesystemType::FAT; #endif @@ -90,6 +93,8 @@ namespace VeraCrypt case VolumeCreationOptions::FilesystemType::APFS: return "newfs_apfs"; #elif defined (TC_FREEBSD) || defined (TC_SOLARIS) case VolumeCreationOptions::FilesystemType::UFS: return "newfs" ; + #elif defined (TC_OPENBSD) + case VolumeCreationOptions::FilesystemType::FFS: return "newfs" ; #endif default: return NULL; } diff --git a/src/Main/CommandLineInterface.cpp b/src/Main/CommandLineInterface.cpp index 754146b7..17b9b940 100644 --- a/src/Main/CommandLineInterface.cpp +++ b/src/Main/CommandLineInterface.cpp @@ -415,6 +415,12 @@ namespace VeraCrypt ArgFilesystem = VolumeCreationOptions::FilesystemType::NTFS; else if (str.IsSameAs (L"exFAT", false)) ArgFilesystem = VolumeCreationOptions::FilesystemType::exFAT; +#elif defined (TC_OPENBSD) + else if (str.IsSameAs (L"FFS", false) || str.IsSameAs (L"UFS", false)) + { + ArgMountOptions.FilesystemType = L"ffs"; + ArgFilesystem = VolumeCreationOptions::FilesystemType::FFS; + } #endif else throw_err (LangString["UNKNOWN_OPTION"] + L": " + str); diff --git a/src/Main/Forms/VolumeCreationWizard.cpp b/src/Main/Forms/VolumeCreationWizard.cpp index 730d3306..6fdbf418 100644 --- a/src/Main/Forms/VolumeCreationWizard.cpp +++ b/src/Main/Forms/VolumeCreationWizard.cpp @@ -25,6 +25,9 @@ #ifdef TC_MACOSX #include "Main/MacOSXFormatterDevice.h" #endif +#ifdef TC_OPENBSD +#include "Main/OpenBSDFormatterDevice.h" +#endif #include "Main/Resources.h" #include "VolumeCreationWizard.h" #include "EncryptionOptionsWizardPage.h" @@ -857,9 +860,11 @@ namespace VeraCrypt // Temporarily take ownership of the device if the user is not an administrator DevicePath virtualDevice = volume->VirtualDevice; + DevicePath formatterDevice = virtualDevice; #ifdef TC_MACOSX string virtualDeviceStr = virtualDevice; virtualDevice = GetMacOSXRawDevicePath (virtualDeviceStr); + formatterDevice = virtualDevice; MacOSXFormatterDeviceOwnerRestoreList changedDeviceOwners; finally_do_arg (MacOSXFormatterDeviceOwnerRestoreList *, &changedDeviceOwners, @@ -868,25 +873,37 @@ namespace VeraCrypt }); bool useElevatedAPFSFormatter = UseElevatedMacOSXAPFSFormatter (fsFormatter); if (!useElevatedAPFSFormatter) - PrepareMacOSXFormatterDevice (virtualDevice, changedDeviceOwners); + PrepareMacOSXFormatterDevice (formatterDevice, changedDeviceOwners); #else +#ifdef TC_OPENBSD + if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::FFS) + formatterDevice = GetOpenBSDRawFormatterDevicePath (virtualDevice); +#endif + bool prepareFormatterDeviceOwnership = true; +#ifdef TC_OPENBSD + if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::FFS) + prepareFormatterDeviceOwnership = false; +#endif UserId origDeviceOwner ((uid_t) -1); - try + if (prepareFormatterDeviceOwnership) { - File file; - file.Open (virtualDevice, File::OpenReadWrite); - } - catch (...) - { - if (!Core->HasAdminPrivileges()) + try { - origDeviceOwner = virtualDevice.GetOwner(); - Core->SetFileOwner (virtualDevice, UserId (getuid())); + File file; + file.Open (formatterDevice, File::OpenReadWrite); + } + catch (...) + { + if (!Core->HasAdminPrivileges()) + { + origDeviceOwner = formatterDevice.GetOwner(); + Core->SetFileOwner (formatterDevice, UserId (getuid())); + } } } - finally_do_arg2 (FilesystemPath, virtualDevice, UserId, origDeviceOwner, + finally_do_arg2 (FilesystemPath, formatterDevice, UserId, origDeviceOwner, { if (finally_arg2.SystemId != (uid_t) -1) Core->SetFileOwner (finally_arg, finally_arg2); @@ -921,11 +938,13 @@ namespace VeraCrypt AddMacOSXAPFSFormatterUserArgs (args); #endif - args.push_back (string (virtualDevice)); + args.push_back (string (formatterDevice)); SetCreationProgressText (StringFormatter (LangString["FORMAT_STAGE_CREATING_FILESYSTEM"], fsFormatter)); #ifdef TC_MACOSX ExecuteMacOSXFilesystemFormatter (fsFormatter, args); +#elif defined (TC_OPENBSD) + ExecuteOpenBSDFilesystemFormatter (fsFormatter, args); #else Process::Execute (fsFormatter, args); #endif diff --git a/src/Main/Forms/VolumeFormatOptionsWizardPage.cpp b/src/Main/Forms/VolumeFormatOptionsWizardPage.cpp index 1c78a56e..d3506030 100644 --- a/src/Main/Forms/VolumeFormatOptionsWizardPage.cpp +++ b/src/Main/Forms/VolumeFormatOptionsWizardPage.cpp @@ -52,6 +52,8 @@ namespace VeraCrypt FilesystemTypeChoice->Append (L"APFS", (void *) VolumeCreationOptions::FilesystemType::APFS); #elif defined (TC_FREEBSD) || defined (TC_SOLARIS) FilesystemTypeChoice->Append (L"UFS", (void *) VolumeCreationOptions::FilesystemType::UFS); +#elif defined (TC_OPENBSD) + FilesystemTypeChoice->Append (L"FFS", (void *) VolumeCreationOptions::FilesystemType::FFS); #endif if (!disable32bitFilesystems && filesystemSize <= TC_MAX_FAT_SECTOR_COUNT * sectorSize) @@ -94,6 +96,7 @@ namespace VeraCrypt case VolumeCreationOptions::FilesystemType::MacOsExt: FilesystemTypeChoice->SetStringSelection (L"Mac OS Extended"); break; case VolumeCreationOptions::FilesystemType::APFS: FilesystemTypeChoice->SetStringSelection (L"APFS"); break; case VolumeCreationOptions::FilesystemType::UFS: FilesystemTypeChoice->SetStringSelection (L"UFS"); break; + case VolumeCreationOptions::FilesystemType::FFS: FilesystemTypeChoice->SetStringSelection (L"FFS"); break; default: throw ParameterIncorrect (SRC_POS); diff --git a/src/Main/OpenBSDFormatterDevice.h b/src/Main/OpenBSDFormatterDevice.h new file mode 100644 index 00000000..250e836b --- /dev/null +++ b/src/Main/OpenBSDFormatterDevice.h @@ -0,0 +1,123 @@ +/* + VeraCrypt source code + Copyright (c) 2026 AM Crypto + + This file is part of VeraCrypt and is governed by the Apache License 2.0 + the full text of which is contained in the file License.txt included in + VeraCrypt binary and source code distribution packages. +*/ + +#ifndef TC_HEADER_Main_OpenBSDFormatterDevice +#define TC_HEADER_Main_OpenBSDFormatterDevice + +#include "Main/Main.h" + +#ifdef TC_OPENBSD +#include +#include +#include +#include "Core/Unix/CoreService.h" +#include "Core/Unix/UnixUser.h" +#include "Platform/Unix/Process.h" + +namespace VeraCrypt +{ + inline bool IsOpenBSDVndDevicePath (const string &path, bool rawDevice) + { + const string prefix = rawDevice ? "/dev/rvnd" : "/dev/vnd"; + if (path.find (prefix) != 0) + return false; + + size_t numberStart = prefix.size(); + size_t numberEnd = numberStart; + while (numberEnd < path.size() && path[numberEnd] >= '0' && path[numberEnd] <= '9') + ++numberEnd; + + return numberEnd > numberStart + && numberEnd + 1 == path.size() + && path[numberEnd] == 'c'; + } + + inline DevicePath GetOpenBSDRawFormatterDevicePath (const DevicePath &path) + { + string pathStr = path; + + if (IsOpenBSDVndDevicePath (pathStr, true)) + return path; + + if (IsOpenBSDVndDevicePath (pathStr, false)) + return DevicePath (string ("/dev/r") + pathStr.substr (5)); + + return path; + } + + inline string GetOpenBSDFormatterName (const string &fsFormatter) + { + size_t namePos = fsFormatter.find_last_of ('/'); + return namePos == string::npos ? fsFormatter : fsFormatter.substr (namePos + 1); + } + + inline bool IsOpenBSDFFSFormatter (const string &fsFormatter) + { + return GetOpenBSDFormatterName (fsFormatter) == "newfs"; + } + + inline bool GetOpenBSDFormatterEnvId (const char *name, uint64 &id) + { + const char *env = getenv (name); + if (!env || !env[0]) + return false; + + char *endPtr = nullptr; + errno = 0; + unsigned long long value = strtoull (env, &endPtr, 10); + if (errno != 0 || !endPtr || *endPtr != '\0') + return false; + + id = static_cast (value); + return true; + } + + inline uint64 GetOpenBSDFormatterOwnerUserId () + { + uint64 id; + if (GetOpenBSDFormatterEnvId ("SUDO_UID", id)) + return id; + + uid_t doasUid; + if (GetDoasUserIds (&doasUid, nullptr)) + return static_cast (doasUid); + + return static_cast (getuid()); + } + + inline uint64 GetOpenBSDFormatterOwnerGroupId () + { + uint64 id; + if (GetOpenBSDFormatterEnvId ("SUDO_GID", id)) + return id; + + gid_t doasGid; + if (GetDoasUserIds (nullptr, &doasGid)) + return static_cast (doasGid); + + return static_cast (getgid()); + } + + inline void ExecuteOpenBSDFilesystemFormatter (const string &fsFormatter, const list &args) + { + if (IsOpenBSDFFSFormatter (fsFormatter)) + { + if (args.empty()) + throw ParameterIncorrect (SRC_POS); + + CoreService::RequestExecuteOpenBSDFFSFormatter (DevicePath (args.back()), GetOpenBSDFormatterOwnerUserId(), GetOpenBSDFormatterOwnerGroupId()); + return; + } + + Process::Execute (fsFormatter, args); + } +} +#endif // TC_OPENBSD + +#endif // TC_HEADER_Main_OpenBSDFormatterDevice diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index e99c8474..aba0aa15 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -29,6 +29,9 @@ #ifdef TC_MACOSX #include "Main/MacOSXFormatterDevice.h" #endif +#ifdef TC_OPENBSD +#include "Main/OpenBSDFormatterDevice.h" +#endif #include "TextUserInterface.h" namespace VeraCrypt @@ -933,7 +936,13 @@ namespace VeraCrypt { if (Preferences.NonInteractive) { +#ifdef TC_OPENBSD + // Preserve the historical OpenBSD batch default. Native FFS + // formatting requires elevation, so scripts should opt in. + options->Filesystem = VolumeCreationOptions::FilesystemType::FAT; +#else options->Filesystem = VolumeCreationOptions::FilesystemType::GetPlatformNative(); +#endif } else { @@ -974,6 +983,8 @@ namespace VeraCrypt } #elif defined (TC_FREEBSD) || defined (TC_SOLARIS) ShowInfo (wxString::Format (L" %li) %s", filesystems.size() + 1, "UFS")); filesystems.push_back (VolumeCreationOptions::FilesystemType::UFS); +#elif defined (TC_OPENBSD) + ShowInfo (wxString::Format (L" %li) %s", filesystems.size() + 1, "FFS")); filesystems.push_back (VolumeCreationOptions::FilesystemType::FFS); #endif ssize_t defaultFilesystem = fatAvailable ? 2 : 1; @@ -1123,9 +1134,11 @@ namespace VeraCrypt // Temporarily take ownership of the device if the user is not an administrator DevicePath virtualDevice = volume->VirtualDevice; + DevicePath formatterDevice = virtualDevice; #ifdef TC_MACOSX string virtualDeviceStr = virtualDevice; virtualDevice = GetMacOSXRawDevicePath (virtualDeviceStr); + formatterDevice = virtualDevice; MacOSXFormatterDeviceOwnerRestoreList changedDeviceOwners; finally_do_arg (MacOSXFormatterDeviceOwnerRestoreList *, &changedDeviceOwners, @@ -1134,25 +1147,37 @@ namespace VeraCrypt }); bool useElevatedAPFSFormatter = UseElevatedMacOSXAPFSFormatter (fsFormatter); if (!useElevatedAPFSFormatter) - PrepareMacOSXFormatterDevice (virtualDevice, changedDeviceOwners); + PrepareMacOSXFormatterDevice (formatterDevice, changedDeviceOwners); #else +#ifdef TC_OPENBSD + if (options->Filesystem == VolumeCreationOptions::FilesystemType::FFS) + formatterDevice = GetOpenBSDRawFormatterDevicePath (virtualDevice); +#endif + bool prepareFormatterDeviceOwnership = true; +#ifdef TC_OPENBSD + if (options->Filesystem == VolumeCreationOptions::FilesystemType::FFS) + prepareFormatterDeviceOwnership = false; +#endif UserId origDeviceOwner ((uid_t) -1); - try + if (prepareFormatterDeviceOwnership) { - File file; - file.Open (virtualDevice, File::OpenReadWrite); - } - catch (...) - { - if (!Core->HasAdminPrivileges()) + try { - origDeviceOwner = virtualDevice.GetOwner(); - Core->SetFileOwner (virtualDevice, UserId (getuid())); + File file; + file.Open (formatterDevice, File::OpenReadWrite); + } + catch (...) + { + if (!Core->HasAdminPrivileges()) + { + origDeviceOwner = formatterDevice.GetOwner(); + Core->SetFileOwner (formatterDevice, UserId (getuid())); + } } } - finally_do_arg2 (FilesystemPath, virtualDevice, UserId, origDeviceOwner, + finally_do_arg2 (FilesystemPath, formatterDevice, UserId, origDeviceOwner, { if (finally_arg2.SystemId != (uid_t) -1) Core->SetFileOwner (finally_arg, finally_arg2); @@ -1187,10 +1212,12 @@ namespace VeraCrypt AddMacOSXAPFSFormatterUserArgs (args); #endif - args.push_back (string (virtualDevice)); + args.push_back (string (formatterDevice)); #ifdef TC_MACOSX ExecuteMacOSXFilesystemFormatter (fsFormatter, args); +#elif defined (TC_OPENBSD) + ExecuteOpenBSDFilesystemFormatter (fsFormatter, args); #else Process::Execute (fsFormatter, args); #endif diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index 665a7941..57ec848f 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -1373,6 +1373,10 @@ const FileManager fileManagers[] = { " with option -t. Default type is 'auto'. When creating a new volume, this\n" " option specifies the filesystem to be created on the new volume.\n" " Filesystem type 'none' disables mounting or creating a filesystem.\n" +#ifdef TC_OPENBSD + " On OpenBSD, filesystem type 'FFS' creates a native FFS volume and\n" + " mounts with filesystem type 'ffs'.\n" +#endif #ifdef TC_LINUX " On Linux, filesystem type 'ntfs3' mounts with the in-kernel ntfs3\n" " driver and bypasses mount helpers. Filesystem type 'kernel-ntfs'\n"