blob: c0c20492348e3f920cbfa607b65a0a527327f9dd [file] [log] [blame]
// Copyright 2020 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 "smbfs/mojo_session.h"
#include <unistd.h>
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <mojo/public/cpp/bindings/binding.h>
#include "smbfs/authpolicy_client.h"
#include "smbfs/fuse_session.h"
#include "smbfs/kerberos_artifact_synchronizer.h"
#include "smbfs/kerberos_client.h"
#include "smbfs/smb_filesystem.h"
#include "smbfs/smbfs.h"
#include "smbfs/smbfs_impl.h"
namespace smbfs {
namespace {
constexpr char kKerberosConfDir[] = ".krb";
constexpr char kKrb5ConfFile[] = "krb5.conf";
constexpr char kCCacheFile[] = "ccache";
constexpr char kKrbTraceFile[] = "krb_trace.txt";
constexpr char kDaemonStoreDirectory[] = "/run/daemon-store/smbfs";
} // namespace
MojoSession::MojoSession(scoped_refptr<dbus::Bus> bus,
const base::FilePath& temp_dir,
fuse_chan* chan,
mojom::SmbFsBootstrapRequest bootstrap_request,
uid_t uid,
gid_t gid,
base::OnceClosure shutdown_callback)
: bus_(std::move(bus)),
temp_dir_(temp_dir),
chan_(chan),
uid_(uid),
gid_(gid),
shutdown_callback_(std::move(shutdown_callback)),
bootstrap_impl_(std::make_unique<SmbFsBootstrapImpl>(
std::move(bootstrap_request),
base::BindRepeating(&MojoSession::CreateSmbFilesystem,
base::Unretained(this)),
this,
base::FilePath(kDaemonStoreDirectory))) {
DCHECK(!temp_dir_.empty());
DCHECK(chan_);
DCHECK(shutdown_callback_);
// Setup locations of Kerberos configuration files.
base::File::Error error;
bool success = base::CreateDirectoryAndGetError(
temp_dir_.Append(kKerberosConfDir), &error);
CHECK(success) << "Failed to create kerberos configuration directory: "
<< base::File::ErrorToString(error);
PCHECK(setenv("KRB5_CONFIG",
KerberosConfFilePath(kKrb5ConfFile).value().c_str(),
1 /* overwrite */) == 0);
PCHECK(setenv("KRB5CCNAME", KerberosConfFilePath(kCCacheFile).value().c_str(),
1 /* overwrite */) == 0);
PCHECK(setenv("KRB5_TRACE",
KerberosConfFilePath(kKrbTraceFile).value().c_str(),
1 /* overwrite */) == 0);
bootstrap_impl_->Start(base::BindOnce(&MojoSession::OnBootstrapComplete,
base::Unretained(this)));
}
MojoSession::~MojoSession() = default;
base::FilePath MojoSession::KerberosConfFilePath(const std::string& file_name) {
return temp_dir_.Append(kKerberosConfDir).Append(file_name);
}
void MojoSession::SetupKerberos(
mojom::KerberosConfigPtr kerberos_config,
base::OnceCallback<void(bool success)> callback) {
DCHECK(!kerberos_sync_);
DCHECK(kerberos_config);
std::unique_ptr<KerberosArtifactClientInterface> client;
switch (kerberos_config->source) {
case mojom::KerberosConfig::Source::kActiveDirectory:
client = std::make_unique<AuthPolicyClient>(bus_);
break;
case mojom::KerberosConfig::Source::kKerberos:
client = std::make_unique<KerberosClient>(bus_);
break;
}
DCHECK(client);
kerberos_sync_ = std::make_unique<KerberosArtifactSynchronizer>(
KerberosConfFilePath(kKrb5ConfFile), KerberosConfFilePath(kCCacheFile),
kerberos_config->identity, std::move(client));
kerberos_sync_->SetupKerberos(std::move(callback));
}
void MojoSession::OnPasswordFilePathSet(const base::FilePath& path) {
password_file_path_ = path;
}
std::unique_ptr<SmbFilesystem> MojoSession::CreateSmbFilesystem(
SmbFilesystem::Options options) {
options.uid = uid_;
options.gid = gid_;
options.use_kerberos = kerberos_sync_.get();
return std::make_unique<SmbFilesystem>(this, std::move(options));
}
void MojoSession::OnBootstrapComplete(std::unique_ptr<SmbFilesystem> fs,
mojom::SmbFsRequest smbfs_request,
mojom::SmbFsDelegatePtr delegate_ptr) {
if (!fs) {
LOG(ERROR) << "Connection error during Mojo bootstrap.";
DoShutdown();
return;
}
DCHECK(!fuse_session_);
DCHECK(chan_);
smbfs_impl_ = std::make_unique<SmbFsImpl>(
fs->GetWeakPtr(), std::move(smbfs_request), password_file_path_);
smbfs_delegate_ = std::move(delegate_ptr);
smbfs_delegate_.set_connection_error_handler(
base::BindOnce(&MojoSession::DoShutdown, base::Unretained(this)));
fuse_session_ = std::make_unique<FuseSession>(std::move(fs), chan_);
chan_ = nullptr;
CHECK(fuse_session_->Start(
base::BindOnce(&MojoSession::DoShutdown, base::Unretained(this))));
}
void MojoSession::DoShutdown() {
if (!shutdown_callback_) {
return;
}
std::move(shutdown_callback_).Run();
}
void MojoSession::RequestCredentials(RequestCredentialsCallback callback) {
DCHECK(smbfs_delegate_);
smbfs_delegate_->RequestCredentials(
base::Bind(&MojoSession::OnRequestCredentialsDone, base::Unretained(this),
base::Passed(&callback)));
}
void MojoSession::OnRequestCredentialsDone(RequestCredentialsCallback callback,
mojom::CredentialsPtr credentials) {
if (!credentials) {
std::move(callback).Run(nullptr);
return;
}
std::unique_ptr<SmbCredential> smb_cred = std::make_unique<SmbCredential>(
credentials->workgroup, credentials->username, nullptr);
if (credentials->password) {
smb_cred->password = std::move(credentials->password.value());
}
std::move(callback).Run(std::move(smb_cred));
}
} // namespace smbfs