Merge pull request #9365 from chrisroberts/e-smb-cred-check

Check SMB credentials
This commit is contained in:
Chris Roberts 2018-01-16 20:00:57 -08:00 committed by GitHub
commit 933694d986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 96 additions and 10 deletions

View File

@ -17,6 +17,16 @@ module VagrantPlugins
true true
end end
def self.smb_validate_password(env, machine, username, password)
script_path = File.expand_path("../../scripts/check_credentials.ps1", __FILE__)
args = []
args << "-username" << "'#{username.gsub("'", "''")}'"
args << "-password" << "'#{password.gsub("'", "''")}'"
r = Vagrant::Util::PowerShell.execute(script_path, *args)
r.exit_code == 0
end
def self.smb_cleanup(env, machine, opts) def self.smb_cleanup(env, machine, opts)
script_path = File.expand_path("../../scripts/unset_share.ps1", __FILE__) script_path = File.expand_path("../../scripts/unset_share.ps1", __FILE__)

View File

@ -46,6 +46,11 @@ module VagrantPlugins
Cap::SMB Cap::SMB
end end
host_capability("windows", "smb_cleanup") do
require_relative "cap/smb"
Cap::SMB
end
host_capability("windows", "configured_ip_addresses") do host_capability("windows", "configured_ip_addresses") do
require_relative "cap/configured_ip_addresses" require_relative "cap/configured_ip_addresses"
Cap::ConfiguredIPAddresses Cap::ConfiguredIPAddresses

View File

@ -0,0 +1,19 @@
Param(
[Parameter(Mandatory=$true)]
[string]$username,
[Parameter(Mandatory=$true)]
[string]$password
)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$DSContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext(
[System.DirectoryServices.AccountManagement.ContextType]::Machine,
$env:COMPUTERNAME
)
if ( $DSContext.ValidateCredentials( $username, $password ) ) {
exit 0
} else {
exit 1
}

View File

@ -26,6 +26,10 @@ module VagrantPlugins
error_key(:name_error) error_key(:name_error)
end end
class CredentialsRequestError < SMBError
error_key(:credentials_request_error)
end
class DefineShareFailed < SMBError class DefineShareFailed < SMBError
error_key(:define_share_failed) error_key(:define_share_failed)
end end

View File

@ -11,6 +11,10 @@ require_relative "errors"
module VagrantPlugins module VagrantPlugins
module SyncedFolderSMB module SyncedFolderSMB
class SyncedFolder < Vagrant.plugin("2", :synced_folder) class SyncedFolder < Vagrant.plugin("2", :synced_folder)
# Maximum number of times to retry requesting username/password
CREDENTIAL_RETRY_MAX = 5
def initialize(*args) def initialize(*args)
super super
@ -30,11 +34,6 @@ module VagrantPlugins
def prepare(machine, folders, opts) def prepare(machine, folders, opts)
machine.ui.output(I18n.t("vagrant_sf_smb.preparing")) machine.ui.output(I18n.t("vagrant_sf_smb.preparing"))
# Check if this host can start and SMB service
if machine.env.host.capability?(:smb_start)
machine.env.host.capability(:smb_start)
end
smb_username = smb_password = nil smb_username = smb_password = nil
# If we need auth information, then ask the user. # If we need auth information, then ask the user.
@ -49,9 +48,32 @@ module VagrantPlugins
end end
if !have_auth if !have_auth
machine.env.ui.detail(I18n.t("vagrant_sf_smb.warning_password") + "\n ") machine.ui.detail(I18n.t("vagrant_sf_smb.warning_password") + "\n ")
smb_username = machine.env.ui.ask("Username: ") retries = 0
smb_password = machine.env.ui.ask("Password (will be hidden): ", echo: false) while retries < CREDENTIAL_RETRY_MAX do
smb_username = machine.ui.ask("Username: ")
smb_password = machine.ui.ask("Password (will be hidden): ", echo: false)
auth_success = true
if machine.env.host.capability?(:smb_validate_password)
Vagrant::Util::CredentialScrubber.sensitive(smb_password)
auth_success = machine.env.host.capability(:smb_validate_password,
smb_username, smb_password)
end
break if auth_success
machine.ui.output(I18n.t("vagrant_sf_smb.incorrect_credentials") + "\n ")
retries += 1
end
if retries >= CREDENTIAL_RETRY_MAX
raise Errors::CredentialsRequestError
end
end
# Check if this host can start and SMB service
if machine.env.host.capability?(:smb_start)
machine.env.host.capability(:smb_start)
end end
folders.each do |id, data| folders.each do |id, data|

View File

@ -15,6 +15,8 @@ en:
You will be asked for the username and password to use for the SMB You will be asked for the username and password to use for the SMB
folders shortly. Please use the proper username/password of your folders shortly. Please use the proper username/password of your
account. account.
incorrect_credentials: |-
Credentials incorrect. Please try again.
uac: uac:
prune_warning: |- prune_warning: |-
@ -37,6 +39,9 @@ en:
Vagrant SMB synced folders require the account password to be stored Vagrant SMB synced folders require the account password to be stored
in an NT compatible format. Please update your sharing settings to in an NT compatible format. Please update your sharing settings to
enable a Windows compatible password and try again. enable a Windows compatible password and try again.
credentials_request_error: |-
Vagrant failed to receive credential information required for preparing
an SMB share.
define_share_failed: |- define_share_failed: |-
Exporting an SMB share failed! Details about the failure are shown Exporting an SMB share failed! Details about the failure are shown
below. Please inspect the error message and correct any problems. below. Please inspect the error message and correct any problems.

View File

@ -71,8 +71,8 @@ describe VagrantPlugins::SyncedFolderSMB::SyncedFolder do
context "without credentials provided" do context "without credentials provided" do
before do before do
expect(machine.env.ui).to receive(:ask).and_return('username') expect(machine.env.ui).to receive(:ask).with(/name/, any_args).and_return('username').at_least(1)
expect(machine.env.ui).to receive(:ask).and_return('password') expect(machine.env.ui).to receive(:ask).with(/word/, any_args).and_return('password').at_least(1)
end end
it "should prompt for credentials" do it "should prompt for credentials" do
@ -91,6 +91,27 @@ describe VagrantPlugins::SyncedFolderSMB::SyncedFolder do
expect(host).to receive(:capability).with(:smb_start, any_args) expect(host).to receive(:capability).with(:smb_start, any_args)
subject.prepare(machine, folders, options) subject.prepare(machine, folders, options)
end end
context "with host smb_validate_password capability" do
let(:host_caps){ [:smb_start, :smb_prepare, :smb_validate_password] }
it "should validate the password" do
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(true)
subject.prepare(machine, folders, options)
end
it "should retry when validation fails" do
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(false)
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(true)
subject.prepare(machine, folders, options)
end
it "should raise an error if it exceeds the maximum number of retries" do
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(false).
exactly(VagrantPlugins::SyncedFolderSMB::SyncedFolder::CREDENTIAL_RETRY_MAX).times
expect{ subject.prepare(machine, folders, options) }.to raise_error(VagrantPlugins::SyncedFolderSMB::Errors::CredentialsRequestError)
end
end
end end
context "with credentials provided" do context "with credentials provided" do