| // Copyright 2021 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "shill/vpn/vpn_util.h" |
| |
| #include <sys/mman.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| |
| #include <memory> |
| #include <utility> |
| |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_file.h> |
| #include <base/logging.h> |
| #include <base/strings/stringprintf.h> |
| |
| namespace shill { |
| |
| class VPNUtilImpl : public VPNUtil { |
| public: |
| bool WriteConfigFile(const base::FilePath& filename, |
| const std::string& contents) const override; |
| std::pair<base::ScopedFD, base::FilePath> WriteAnonymousConfigFile( |
| const std::string& contents) const override; |
| base::ScopedTempDir CreateScopedTempDir( |
| const base::FilePath& parent_path) const override; |
| }; |
| |
| bool VPNUtilImpl::WriteConfigFile(const base::FilePath& filename, |
| const std::string& contents) const { |
| if (!base::WriteFile(filename, contents)) { |
| LOG(ERROR) << "Failed to write config file"; |
| return false; |
| } |
| |
| if (chmod(filename.value().c_str(), S_IRUSR | S_IRGRP) != 0) { |
| PLOG(ERROR) << "Failed to make config file group-readable"; |
| return false; |
| } |
| |
| if (chown(filename.value().c_str(), -1, kVPNGid) != 0) { |
| PLOG(ERROR) << "Failed to change gid of config file"; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| std::pair<base::ScopedFD, base::FilePath> VPNUtilImpl::WriteAnonymousConfigFile( |
| const std::string& contents) const { |
| // The first parameter is the name of this file. This name is only used for |
| // debugging purposes, and it does not have any side effect that multiple |
| // files share the same name |
| int fd = memfd_create("vpn_file", /*flags=*/0); |
| if (fd == -1) { |
| PLOG(ERROR) << "Failed to create file with memfd_create"; |
| return {}; |
| } |
| |
| base::ScopedFD scoped_fd(fd); |
| if (!base::WriteFileDescriptor(fd, contents)) { |
| PLOG(ERROR) << "Failed to write config file"; |
| return {}; |
| } |
| |
| base::FilePath path(base::StringPrintf("/proc/self/fd/%d", fd)); |
| return {std::move(scoped_fd), path}; |
| } |
| |
| base::ScopedTempDir VPNUtilImpl::CreateScopedTempDir( |
| const base::FilePath& parent_path) const { |
| base::ScopedTempDir temp_dir; |
| |
| if (!temp_dir.CreateUniqueTempDirUnderPath(parent_path)) { |
| PLOG(ERROR) << "Failed to create temp dir under path " << parent_path; |
| return base::ScopedTempDir{}; |
| } |
| |
| if (chmod(temp_dir.GetPath().value().c_str(), S_IRWXU | S_IRWXG) != 0) { |
| PLOG(ERROR) << "Failed to change the permission of temp dir"; |
| return base::ScopedTempDir{}; |
| } |
| |
| if (chown(temp_dir.GetPath().value().c_str(), -1, VPNUtil::kVPNGid) != 0) { |
| PLOG(ERROR) << "Failed to change gid of temp dir"; |
| return base::ScopedTempDir{}; |
| } |
| return temp_dir; |
| } |
| |
| std::unique_ptr<VPNUtil> VPNUtil::New() { |
| return std::make_unique<VPNUtilImpl>(); |
| } |
| |
| } // namespace shill |