Skip to content

Commit

Permalink
Escape shell command arguments.
Browse files Browse the repository at this point in the history
  • Loading branch information
matsuu committed May 5, 2013
1 parent c7c4e4f commit 82f9a80
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 172 deletions.
81 changes: 47 additions & 34 deletions lib/serverspec/commands/base.rb
Original file line number Diff line number Diff line change
@@ -1,138 +1,151 @@
require 'shellwords'

module Serverspec
module Commands
class Base
class NotImplementedError < Exception; end

def escape target
Shellwords.shellescape(target.to_s())
end

def check_enabled service
raise NotImplementedError.new
end

def check_mounted path
"mount | grep -w 'on #{path}'"
regexp = "on #{path}"
"mount | grep -w -- #{escape(regexp)}"
end

def check_reachable host, port, proto, timeout
if port.nil?
"ping -n #{host} -w #{timeout} -c 2"
"ping -n #{escape(host)} -w #{escape(timeout)} -c 2"
else
"nc -vvvvz#{proto[0].chr} #{host} #{port} -w #{timeout}"
"nc -vvvvz#{escape(proto[0].chr)} #{escape(host)} #{escape(port)} -w #{escape(timeout)}"
end
end

def check_resolvable name, type
if type == "dns"
"nslookup -timeout=1 #{name}"
"nslookup -timeout=1 #{escape(name)}"
elsif type == "hosts"
"grep -w #{name} /etc/hosts"
"grep -w -- #{escape(name)} /etc/hosts"
else
"getent hosts #{name}"
"getent hosts #{escape(name)}"
end
end

def check_file file
"test -f #{file}"
"test -f #{escape(file)}"
end

def check_directory directory
"test -d #{directory}"
"test -d #{escape(directory)}"
end

def check_user user
"id #{user}"
"id #{escape(user)}"
end

def check_group group
"getent group | grep -wq #{group}"
"getent group | grep -wq -- #{escape(group)}"
end

def check_installed package
raise NotImplementedError.new
end

def check_listening port
"netstat -tunl | grep ':#{port} '"
regexp = ":#{port} "
"netstat -tunl | grep -- #{escape(regexp)}"
end

def check_running service
"service #{service} status"
"service #{escape(service)} status"
end

def check_running_under_supervisor service
"supervisorctl status #{service}"
"supervisorctl status #{escape(service)}"
end

def check_process process
"ps aux | grep -w #{process} | grep -qv grep"
"ps aux | grep -w -- #{escape(process)} | grep -qv grep"
end

def check_file_contain file, expected_pattern
"grep -q '#{expected_pattern}' #{file}"
"grep -q -- #{escape(expected_pattern)} #{escape(file)}"
end

def check_file_contain_within file, expected_pattern, from=nil, to=nil
from ||= '1'
to ||= '$'
checker = check_file_contain("-", expected_pattern)
"sed -n '#{from},#{to}p' #{file} | #{checker}"
"sed -n #{escape(from)},#{escape(to)}p #{escape(file)} | #{checker}"
end

def check_mode file, mode
"stat -c %a #{file} | grep '^#{mode}$'"
regexp = "^#{mode}$"
"stat -c %a #{escape(file)} | grep -- #{escape(regexp)}"
end

def check_owner file, owner
"stat -c %U #{file} | grep '^#{owner}$'"
regexp = "^#{owner}$"
"stat -c %U #{escape(file)} | grep -- #{escape(regexp)}"
end

def check_grouped file, group
"stat -c %G #{file} | grep '^#{group}$'"
regexp = "^#{group}$"
"stat -c %G #{escape(file)} | grep -- #{escape(regexp)}"
end

def check_cron_entry user, entry
entry_escaped = entry.gsub(/\*/, '\\*')
"crontab -u #{user} -l | grep \"#{entry_escaped}\""
"crontab -u #{escape(user)} -l | grep -- #{escape(entry_escaped)}"
end

def check_link link, target
"stat -c %N #{link} | grep #{target}"
"stat -c %N #{escape(link)} | grep -- #{escape(target)}"
end

def check_installed_by_gem name
"gem list --local | grep '^#{name} '"
gem_name = "^#{name} "
"gem list --local | grep -- #{escape(gem_name)}"
end

def check_belonging_group user, group
"id #{user} | awk '{print $3}' | grep #{group}"
"id #{escape(user)} | awk '{print $3}' | grep -- #{escape(group)}"
end

def check_gid group, gid
"getent group | grep -w ^#{group} | cut -f 3 -d ':' | grep -w #{gid}"
regexp = "^#{group}"
"getent group | grep -w -- #{escape(regexp)} | cut -f 3 -d ':' | grep -w -- #{escape(gid)}"
end

def check_uid user, uid
"id #{user} | grep '^uid=#{uid}('"
regexp = "^uid=#{uid}("
"id #{escape(user)} | grep -- #{escape(regexp)}"
end

def check_login_shell user, path_to_shell
"getent passwd #{user} | cut -f 7 -d ':' | grep -w #{path_to_shell}"
"getent passwd #{escape(user)} | cut -f 7 -d ':' | grep -w -- #{escape(path_to_shell)}"
end

def check_home_directory user, path_to_home
"getent passwd #{user} | cut -f 6 -d ':' | grep -w #{path_to_home}"
"getent passwd #{escape(user)} | cut -f 6 -d ':' | grep -w -- #{escape(path_to_home)}"
end

def check_authorized_key user, key
key.sub!(/\s+\S*$/, '') if key.match(/^\S+\s+\S+\s+\S*$/)
"grep -w '#{key}' ~#{user}/.ssh/authorized_keys"
"grep -w -- #{escape(key)} ~#{escape(user)}/.ssh/authorized_keys"
end

def check_iptables_rule rule, table=nil, chain=nil
cmd = "iptables"
cmd += " -t #{table}" if table
cmd += " -t #{escape(table)}" if table
cmd += " -S"
cmd += " #{chain}" if chain
rule.gsub!(/\-/, '\\-')
cmd += " | grep '#{rule}'"
cmd += " #{escape(chain)}" if chain
cmd += " | grep -- #{escape(rule)}"
cmd
end

Expand All @@ -141,7 +154,7 @@ def check_zfs zfs, property=nil, value=nil
end

def get_mode(file)
"stat -c %a #{file}"
"stat -c %a #{escape(file)}"
end

def check_ipfilter_rule rule
Expand All @@ -161,7 +174,7 @@ def check_svcprops svc, property
end

def check_selinux mode
"/usr/sbin/getenforce | grep -i '#{mode}'"
"/usr/sbin/getenforce | grep -i -- #{escape(mode)}"
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/serverspec/commands/debian.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ module Serverspec
module Commands
class Debian < Base
def check_enabled service
"ls /etc/rc3.d/ | grep #{service}"
"ls /etc/rc3.d/ | grep -- #{escape(service)}"
end

def check_installed package
"dpkg -s #{package}"
"dpkg -s #{escape(package)}"
end
end
end
Expand Down
7 changes: 4 additions & 3 deletions lib/serverspec/commands/gentoo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ module Serverspec
module Commands
class Gentoo < Base
def check_enabled service
"/sbin/rc-update show | grep '^\\s*#{service}\\s*|\\s*\\(boot\\|default\\)'"
regexp = "^\\s*#{service}\\s*|\\s*\\(boot\\|default\\)"
"/sbin/rc-update show | grep -- #{escape(regexp)}"
end

def check_installed package
"/usr/bin/eix #{package} --installed"
"/usr/bin/eix #{escape(package)} --installed"
end

def check_running service
"/etc/init.d/#{service} status"
"/etc/init.d/#{escape(service)} status"
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/serverspec/commands/redhat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ module Serverspec
module Commands
class RedHat < Base
def check_enabled service
"chkconfig --list #{service} | grep 3:on"
"chkconfig --list #{escape(service)} | grep 3:on"
end

def check_installed package
"rpm -q #{package}"
"rpm -q #{escape(package)}"
end
end
end
Expand Down
38 changes: 22 additions & 16 deletions lib/serverspec/commands/solaris.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,59 @@ module Serverspec
module Commands
class Solaris < Base
def check_enabled service
"svcs -l #{service} 2> /dev/null | grep 'enabled true'"
"svcs -l #{escape(service)} 2> /dev/null | grep 'enabled true'"
end

def check_installed package
"pkg list -H #{package} 2> /dev/null"
"pkg list -H #{escape(package)} 2> /dev/null"
end

def check_listening port
"netstat -an 2> /dev/null | egrep 'LISTEN|Idle' | grep '\.#{port} '"
regexp = "\.#{port} "
"netstat -an 2> /dev/null | egrep 'LISTEN|Idle' | grep -- #{escape(regexp)}"
end

def check_running service
"svcs -l #{service} status 2> /dev/null |grep 'state online'"
"svcs -l #{escape(service)} status 2> /dev/null |grep 'state online'"
end

def check_cron_entry user, entry
entry_escaped = entry.gsub(/\*/, '\\*')
"crontab -l #{user} | grep '#{entry_escaped}'"
"crontab -l #{escape(user)} | grep -- #{escape(entry_escaped)}"
end

def check_zfs zfs, property=nil
if property.nil?
"/sbin/zfs list -H #{zfs}"
"/sbin/zfs list -H #{escape(zfs)}"
else
commands = []
property.sort.each do |key, value|
commands << "/sbin/zfs list -H -o #{key} #{zfs} | grep ^#{value}$"
regexp = "^#{value}$"
commands << "/sbin/zfs list -H -o #{escape(key)} #{escape(zfs)} | grep -- #{escape(regexp)}"
end
commands.join(' && ')
end
end

def check_ipfilter_rule rule
"/sbin/ipfstat -io 2> /dev/null | grep '#{rule}'"
"/sbin/ipfstat -io 2> /dev/null | grep -- #{escape(rule)}"
end

def check_ipnat_rule rule
"/sbin/ipnat -l 2> /dev/null | grep '^#{rule}$'"
regexp = "^#{rule}$"
"/sbin/ipnat -l 2> /dev/null | grep -- #{escape(regexp)}"
end

def check_svcprop svc, property, value
"svcprop -p #{property} #{svc} | grep ^#{value}$"
regexp = "^#{value}$"
"svcprop -p #{escape(property)} #{escape(svc)} | grep -- #{escape(regexp)}"
end

def check_svcprops svc, property
commands = []
property.sort.each do |key, value|
commands << "svcprop -p #{key} #{svc} | grep ^#{value}$"
regexp = "^#{value}$"
commands << "svcprop -p #{escape(key)} #{escape(svc)} | grep -- #{escape(regexp)}"
end
commands.join(' && ')
end
Expand All @@ -58,23 +63,24 @@ def check_file_contain_within file, expected_pattern, from=nil, to=nil
from ||= '1'
to ||= '$'
checker = check_file_contain("/dev/stdin", expected_pattern)
"sed -n '#{from},#{to}p' #{file} | #{checker}"
"sed -n #{escape(from)},#{escape(to)}p #{escape(file)} | #{checker}"
end

def check_belonging_group user, group
"id -Gn #{user} | grep #{group}"
"id -Gn #{escape(user)} | grep -- #{escape(group)}"
end

def check_gid group, gid
"getent group | grep ^#{group}: | cut -f 3 -d ':' | grep -w #{gid}"
regexp = "^#{group}:"
"getent group | grep -- #{escape(regexp)} | cut -f 3 -d ':' | grep -w -- #{escape(gid)}"
end

def check_home_directory user, path_to_home
"getent passwd #{user} | cut -f 6 -d ':' | grep -w #{path_to_home}"
"getent passwd #{escape(user)} | cut -f 6 -d ':' | grep -w -- #{escape(path_to_home)}"
end

def check_login_shell user, path_to_shell
"getent passwd #{user} | cut -f 7 -d ':' | grep -w #{path_to_shell}"
"getent passwd #{escape(user)} | cut -f 7 -d ':' | grep -w -- #{escape(path_to_shell)}"
end
end
end
Expand Down
Loading

0 comments on commit 82f9a80

Please sign in to comment.