blob: c5125b617fd8ad3432c9ec662a3da0b553eb426b [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/smbfs_bootstrap_impl.h"
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include "smbfs/smb_credential.h"
#include "smbfs/smb_filesystem.h"
#include "smbfs/smbfs_impl.h"
namespace smbfs {
namespace {
mojom::MountError ConnectErrorToMountError(SmbFilesystem::ConnectError error) {
switch (error) {
case SmbFilesystem::ConnectError::kNotFound:
return mojom::MountError::kNotFound;
case SmbFilesystem::ConnectError::kAccessDenied:
return mojom::MountError::kAccessDenied;
case SmbFilesystem::ConnectError::kSmb1Unsupported:
return mojom::MountError::kInvalidProtocol;
default:
return mojom::MountError::kUnknown;
}
}
std::unique_ptr<password_provider::Password> MakePasswordFromMojoHandle(
mojo::ScopedHandle handle, int32_t length) {
base::ScopedFD fd = mojo::UnwrapPlatformHandle(std::move(handle)).TakeFD();
return password_provider::Password::CreateFromFileDescriptor(fd.get(),
length);
}
} // namespace
SmbFsBootstrapImpl::SmbFsBootstrapImpl(mojom::SmbFsBootstrapRequest request,
Delegate* delegate)
: binding_(this, std::move(request)), delegate_(delegate) {
DCHECK(delegate_);
binding_.set_connection_error_handler(base::Bind(
&Delegate::OnBootstrapConnectionError, base::Unretained(delegate)));
}
SmbFsBootstrapImpl::~SmbFsBootstrapImpl() = default;
void SmbFsBootstrapImpl::MountShare(mojom::MountOptionsPtr options,
mojom::SmbFsDelegatePtr smbfs_delegate,
const MountShareCallback& callback) {
if (options->share_path.find("smb://") != 0) {
// TODO(amistry): More extensive URL validation.
LOG(ERROR) << "Invalid share path: " << options->share_path;
callback.Run(mojom::MountError::kInvalidUrl, nullptr);
return;
}
std::unique_ptr<SmbCredential> credential = std::make_unique<SmbCredential>(
options->workgroup, options->username, nullptr);
if (options->kerberos_config) {
delegate_->SetupKerberos(
std::move(options->kerberos_config),
base::BindOnce(&SmbFsBootstrapImpl::OnCredentialsSetup,
base::Unretained(this), std::move(options),
std::move(smbfs_delegate), callback,
std::move(credential), true /* use_kerberos */));
return;
}
if (options->password) {
credential->password = MakePasswordFromMojoHandle(
std::move(options->password->fd), options->password->length);
}
OnCredentialsSetup(std::move(options), std::move(smbfs_delegate), callback,
std::move(credential), false /* use_kerberos */,
true /* setup_success */);
}
void SmbFsBootstrapImpl::OnCredentialsSetup(
mojom::MountOptionsPtr options,
mojom::SmbFsDelegatePtr smbfs_delegate,
const MountShareCallback& callback,
std::unique_ptr<SmbCredential> credential,
bool use_kerberos,
bool setup_success) {
if (!setup_success) {
callback.Run(mojom::MountError::kUnknown, nullptr);
return;
}
auto fs = delegate_->CreateSmbFilesystem(options->share_path,
std::move(credential));
// Don't use the resolved address if Kerberos is set up. Kerberos requires the
// full hostname to obtain auth tickets.
if (options->resolved_host && !use_kerberos) {
if (options->resolved_host->address_bytes.size() != 4) {
LOG(ERROR) << "Invalid IP address size: "
<< options->resolved_host->address_bytes.size();
callback.Run(mojom::MountError::kInvalidOptions, nullptr);
return;
}
fs->SetResolvedAddress(options->resolved_host->address_bytes);
}
if (!options->skip_connect) {
SmbFilesystem::ConnectError error = fs->EnsureConnected();
if (error != SmbFilesystem::ConnectError::kOk) {
LOG(ERROR) << "Unable to connect to SMB share " << options->share_path
<< ": " << error;
callback.Run(ConnectErrorToMountError(error), nullptr);
return;
}
}
mojom::SmbFsPtr smbfs_ptr;
fs->SetSmbFsImpl(std::make_unique<SmbFsImpl>(
fs.get(), std::move(smbfs_delegate), mojo::MakeRequest(&smbfs_ptr)));
if (!delegate_->StartFuseSession(std::move(fs))) {
callback.Run(mojom::MountError::kUnknown, nullptr);
return;
}
callback.Run(mojom::MountError::kOk, std::move(smbfs_ptr));
}
} // namespace smbfs