summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/FallocFileAllocationIterator.cc19
-rw-r--r--src/FallocFileAllocationIterator.h4
-rw-r--r--src/Platform.cc82
-rw-r--r--src/util.cc71
-rw-r--r--src/util.h4
5 files changed, 98 insertions, 82 deletions
diff --git a/src/FallocFileAllocationIterator.cc b/src/FallocFileAllocationIterator.cc
index febcf19b..04590557 100644
--- a/src/FallocFileAllocationIterator.cc
+++ b/src/FallocFileAllocationIterator.cc
@@ -34,14 +34,33 @@
/* copyright --> */
#include "FallocFileAllocationIterator.h"
#include "DlAbortEx.h"
+#include "util.h"
+#include "LogFactory.h"
namespace aria2 {
+#ifdef __MINGW32__
+bool FallocFileAllocationIterator::gainPrivilegeAttempted_ = false;
+#endif // __MINGW32__
+
FallocFileAllocationIterator::FallocFileAllocationIterator(BinaryStream* stream,
int64_t offset,
int64_t totalLength)
: stream_(stream), offset_(offset), totalLength_(totalLength)
{
+#ifdef __MINGW32__
+ // Windows build: --file-allocation=falloc uses SetFileValidData
+ // which requires SE_MANAGE_VOLUME_NAME privilege. SetFileValidData
+ // has security implications (see
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365544%28v=vs.85%29.aspx).
+ if (!gainPrivilegeAttempted_) {
+ if (!util::gainPrivilege(SE_MANAGE_VOLUME_NAME)) {
+ A2_LOG_WARN("--file-allocation=falloc will not work properly.");
+ }
+
+ gainPrivilegeAttempted_ = true;
+ }
+#endif // __MINGW32__
}
void FallocFileAllocationIterator::allocateChunk()
diff --git a/src/FallocFileAllocationIterator.h b/src/FallocFileAllocationIterator.h
index fb306af1..08b8b4a1 100644
--- a/src/FallocFileAllocationIterator.h
+++ b/src/FallocFileAllocationIterator.h
@@ -47,6 +47,10 @@ private:
int64_t offset_;
int64_t totalLength_;
+#ifdef __MINGW32__
+ static bool gainPrivilegeAttempted_;
+#endif // __MINGW32__
+
public:
FallocFileAllocationIterator(BinaryStream* stream, int64_t offset,
int64_t totalLength);
diff --git a/src/Platform.cc b/src/Platform.cc
index 94ec86f2..cbeab9e9 100644
--- a/src/Platform.cc
+++ b/src/Platform.cc
@@ -94,79 +94,6 @@ Platform::Platform() { setUp(); }
Platform::~Platform() { tearDown(); }
-#ifdef __MINGW32__
-namespace {
-bool gainPrivilege(LPCTSTR privName)
-{
- LUID luid;
- TOKEN_PRIVILEGES tp;
-
- if (!LookupPrivilegeValue(nullptr, privName, &luid)) {
- auto errNum = GetLastError();
- A2_LOG_WARN(fmt("Lookup for privilege name %s failed. cause: %s", privName,
- util::formatLastError(errNum).c_str()));
- return false;
- }
-
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Luid = luid;
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- HANDLE token;
- if (!OpenProcessToken(GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
- auto errNum = GetLastError();
- A2_LOG_WARN(fmt("Getting process token failed. cause: %s",
- util::formatLastError(errNum).c_str()));
- return false;
- }
-
- auto tokenCloser = defer(token, CloseHandle);
-
- if (!AdjustTokenPrivileges(token, FALSE, &tp, 0, NULL, NULL)) {
- auto errNum = GetLastError();
- A2_LOG_WARN(fmt("Gaining privilege %s failed. cause: %s", privName,
- util::formatLastError(errNum).c_str()));
- return false;
- }
-
- // Check privilege was really gained
- DWORD bufsize = 0;
- GetTokenInformation(token, TokenPrivileges, nullptr, 0, &bufsize);
- if (bufsize == 0) {
- A2_LOG_WARN("Checking privilege failed.");
- return false;
- }
-
- auto buf = make_unique<char[]>(bufsize);
- if (!GetTokenInformation(token, TokenPrivileges, buf.get(), bufsize,
- &bufsize)) {
- auto errNum = GetLastError();
- A2_LOG_WARN(fmt("Checking privilege failed. cause: %s",
- util::formatLastError(errNum).c_str()));
- return false;
- }
-
- auto privs = reinterpret_cast<TOKEN_PRIVILEGES*>(buf.get());
- for (size_t i = 0; i < privs->PrivilegeCount; ++i) {
- auto& priv = privs->Privileges[i];
- if (memcmp(&priv.Luid, &luid, sizeof(luid)) != 0) {
- continue;
- }
- if (priv.Attributes == SE_PRIVILEGE_ENABLED) {
- return true;
- }
-
- break;
- }
-
- A2_LOG_WARN(fmt("Gaining privilege %s failed.", privName));
-
- return false;
-}
-} // namespace
-#endif // __MINGW32__
-
bool Platform::setUp()
{
if (initialized_) {
@@ -239,15 +166,6 @@ bool Platform::setUp()
(void)_setmode(_fileno(stdin), _O_BINARY);
(void)_setmode(_fileno(stdout), _O_BINARY);
(void)_setmode(_fileno(stderr), _O_BINARY);
-
- // Windows build: --file-allocation=falloc uses SetFileValidData
- // which requires SE_MANAGE_VOLUME_NAME privilege. SetFileValidData
- // has security implications (see
- // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365544%28v=vs.85%29.aspx).
- if (!gainPrivilege(SE_MANAGE_VOLUME_NAME)) {
- A2_LOG_WARN("--file-allocation=falloc will not work properly.");
- }
-
#endif // __MINGW32__
return true;
diff --git a/src/util.cc b/src/util.cc
index 045aa014..2f9e7d38 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -2121,6 +2121,77 @@ void make_fd_cloexec(int fd)
#endif // !__MINGW32__
}
+#ifdef __MINGW32__
+bool gainPrivilege(LPCTSTR privName)
+{
+ LUID luid;
+ TOKEN_PRIVILEGES tp;
+
+ if (!LookupPrivilegeValue(nullptr, privName, &luid)) {
+ auto errNum = GetLastError();
+ A2_LOG_WARN(fmt("Lookup for privilege name %s failed. cause: %s", privName,
+ util::formatLastError(errNum).c_str()));
+ return false;
+ }
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ HANDLE token;
+ if (!OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
+ auto errNum = GetLastError();
+ A2_LOG_WARN(fmt("Getting process token failed. cause: %s",
+ util::formatLastError(errNum).c_str()));
+ return false;
+ }
+
+ auto tokenCloser = defer(token, CloseHandle);
+
+ if (!AdjustTokenPrivileges(token, FALSE, &tp, 0, NULL, NULL)) {
+ auto errNum = GetLastError();
+ A2_LOG_WARN(fmt("Gaining privilege %s failed. cause: %s", privName,
+ util::formatLastError(errNum).c_str()));
+ return false;
+ }
+
+ // Check privilege was really gained
+ DWORD bufsize = 0;
+ GetTokenInformation(token, TokenPrivileges, nullptr, 0, &bufsize);
+ if (bufsize == 0) {
+ A2_LOG_WARN("Checking privilege failed.");
+ return false;
+ }
+
+ auto buf = make_unique<char[]>(bufsize);
+ if (!GetTokenInformation(token, TokenPrivileges, buf.get(), bufsize,
+ &bufsize)) {
+ auto errNum = GetLastError();
+ A2_LOG_WARN(fmt("Checking privilege failed. cause: %s",
+ util::formatLastError(errNum).c_str()));
+ return false;
+ }
+
+ auto privs = reinterpret_cast<TOKEN_PRIVILEGES*>(buf.get());
+ for (size_t i = 0; i < privs->PrivilegeCount; ++i) {
+ auto& priv = privs->Privileges[i];
+ if (memcmp(&priv.Luid, &luid, sizeof(luid)) != 0) {
+ continue;
+ }
+ if (priv.Attributes == SE_PRIVILEGE_ENABLED) {
+ return true;
+ }
+
+ break;
+ }
+
+ A2_LOG_WARN(fmt("Gaining privilege %s failed.", privName));
+
+ return false;
+}
+#endif // __MINGW32__
+
} // namespace util
} // namespace aria2
diff --git a/src/util.h b/src/util.h
index 14b5d146..25183b5c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -867,6 +867,10 @@ std::string formatLastError(int errNum);
// CreateProcess call.
void make_fd_cloexec(int fd);
+#ifdef __MINGW32__
+bool gainPrivilege(LPCTSTR privName);
+#endif // __MINGW32__
+
} // namespace util
} // namespace aria2