You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2017/08/02 23:21:06 UTC

svn commit: r1803935 - /vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm

Author: arkurth
Date: Wed Aug  2 23:21:06 2017
New Revision: 1803935

URL: http://svn.apache.org/viewvc?rev=1803935&view=rev
Log:
VCL-1068
Added Windows.pm::_escape_password.

Updated subroutines in Windows.pm to use result of _escape_password in command:
* set_password
set_scheduled_task_credentials
create_startup_scheduled_task
set_service_credentials

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1803935&r1=1803934&r2=1803935&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Wed Aug  2 23:21:06 2017
@@ -2250,6 +2250,16 @@ sub set_password {
 		return;
 	}
 	
+	# IMPORTANT: be sure to test passwords containing the following:
+	# $!
+	# \ (single backslash)
+	# '
+	# "
+	# ~
+	# `
+	# Special bash/Linux variables: = $0, $1, $#, $*, $@, $-, $!, $_, $?, $$
+	# my $test_password = '$0, $1 $# $* $@ $- $! $_ $? $$\ !@#$%^&*()_+-={}[]":;<>?/.,`~' . "'";
+	
 	my $computer_node_name   = $self->data->get_computer_node_name();
 	my $system32_path        = $self->get_system32_path() || return;
 	
@@ -2273,20 +2283,21 @@ sub set_password {
 	}
 
 	# Attempt to set the password
-	notify($ERRORS{'DEBUG'}, 0, "setting password of $username to $password on $computer_node_name");
-	my ($set_password_exit_status, $set_password_output) = $self->execute("$system32_path/net.exe user $username '$password'");
+	my $password_escaped = _escape_password($password);
+	my $set_password_command = "$system32_path/net.exe user $username \"$password_escaped\"";
+	notify($ERRORS{'DEBUG'}, 0, "setting password of $username to '$password' on $computer_node_name, command:\n$set_password_command");
+	my ($set_password_exit_status, $set_password_output) = $self->execute($set_password_command);
 	if ($set_password_exit_status == 0) {
-		notify($ERRORS{'OK'}, 0, "password changed to '$password' for user '$username' on $computer_node_name");
+		notify($ERRORS{'OK'}, 0, "password changed to '$password' for user '$username' on $computer_node_name, command: '$set_password_command', output:\n" . join("\n", @$set_password_output));
 	}
 	elsif (defined $set_password_exit_status) {
-		notify($ERRORS{'WARNING'}, 0, "failed to change password to '$password' for user '$username' on $computer_node_name, exit status: $set_password_exit_status, output:\n" . join("\n", @$set_password_output));
+		notify($ERRORS{'WARNING'}, 0, "failed to change password to '$password' (escaped: '$password_escaped') for user '$username' on $computer_node_name, exit status: $set_password_exit_status, command: '$set_password_command', output:\n" . join("\n", @$set_password_output));
 		return 0;
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to change password to '$password' for user '$username' on $computer_node_name");
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to change password to '$password' for user '$username' on $computer_node_name");
 		return 0;
 	}
-	
 	return 1 if $user_password_only;
 	
 	# Get the list of services
@@ -3480,10 +3491,11 @@ sub set_scheduled_task_credentials {
 	
 	my $system32_path = $self->get_system32_path() || return;
 	
-	my $command = "$system32_path/schtasks.exe /Change /RU \"$username\" /RP \"$password\" /TN \"$task_name\"";
+	my $password_escaped = _escape_password($password);
+	my $command = "$system32_path/schtasks.exe /Change /RU \"$username\" /RP \"$password_escaped\" /TN \"$task_name\"";
 	my ($exit_status, $output) = $self->execute($command);
 	if (!defined($output)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to change password for scheduled task: $task_name");
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to change password for scheduled task: $task_name");
 		return;
 	}
 	elsif (grep (/^SUCCESS:/, @$output)) {
@@ -3608,12 +3620,24 @@ sub create_startup_scheduled_task {
 	# Run schtasks.exe to add the task
 	# Occasionally see this error even though it schtasks.exe returns exit status 0:
 	# WARNING: The Scheduled task "System Startup Script" has been created, but may not run because the account information could not be set.
-	my $command = "$system32_path/schtasks.exe /Create /RU \"$task_user\" /RP \"$task_password\" /RL HIGHEST /SC ONSTART /TN \"$task_name\" /TR \"$task_command\"";
+	my $password_escaped = _escape_password($task_password);
+	my $command = "$system32_path/schtasks.exe /Create /RU \"$task_user\" /RP \"$password_escaped\" /RL HIGHEST /SC ONSTART /TN \"$task_name\" /TR \"$task_command\"";
 	my ($exit_status, $output) = $self->execute($command);
 	if (!defined($output)) {
 		notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command created scheduled task '$task_name' on $computer_node_name");
 		return;
 	}
+	elsif (grep(/password is incorrect/, @$output)) {
+		# ERROR: The user name or password is incorrect.
+		notify($ERRORS{'WARNING'}, 0, "failed to create scheduled task '$task_name' on $computer_node_name\n" .
+			"username         : '$task_user'\n" .
+			"password         : '$task_password'\n" .
+			"escaped password : '$password_escaped'\n" .
+			"command:\n$command\n" .
+			"output:\n" . join("\n", @$output)
+		);
+		return 0;
+	}
 	elsif ($exit_status != 0) {
 		notify($ERRORS{'WARNING'}, 0, "failed to create scheduled task '$task_name' on $computer_node_name, exit status: $exit_status, command: '$command', output:\n@$output");
 		return 0;
@@ -4265,7 +4289,8 @@ sub set_service_credentials {
 	}
 
 	# Attempt to set the service logon user name and password
-	my $service_logon_command = $system32_path . '/sc.exe config ' . $service_name . ' obj= ".\\' . $username . '" password= "' . $password . '"';
+	my $password_escaped = _escape_password($password);
+	my $service_logon_command = "$system32_path/sc.exe config $service_name obj= \".\\$username\" password= \"$password_escaped\"";
 	my ($service_logon_exit_status, $service_logon_output) = $self->execute($service_logon_command);
 	if (defined($service_logon_exit_status) && $service_logon_exit_status == 0) {
 		notify($ERRORS{'OK'}, 0, "changed logon credentials for '$service_name' service to $username ($password) on $computer_node_name");
@@ -4278,7 +4303,7 @@ sub set_service_credentials {
 		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to change $service_name service logon credentials to $username ($password) on $computer_node_name");
 		return;
 	}
-
+	
 	return 1;
 } ## end sub set_service_credentials
 
@@ -14755,6 +14780,33 @@ sub revoke_administrative_access {
 }
 
 #//////////////////////////////////////////////////////////////////////////////
+
+=head2 _escape_password
+
+ Parameters  : $password
+ Returns     : string
+ Description : Adds a backslash before all of the following characters in a
+               password:
+                  * " (double quote)
+                  * $ (dollar sign)
+                  * \ (backslash)
+                  * ` (backtick)
+
+=cut
+
+sub _escape_password {
+	my $password_argument = shift;
+	my $password_escaped = $password_argument;
+	$password_escaped =~ s/(["\$\\`])/\\$1/gx;
+	
+	#notify($ERRORS{'DEBUG'}, 0, "escaped password:\n" .
+	#	"original : '$password_argument'\n" .
+	#	"escaped  : '$password_escaped'"
+	#);
+	return $password_escaped;
+}
+
+#//////////////////////////////////////////////////////////////////////////////
 
 1;
 __END__