HEX
Server: Apache
System: Linux server.enlacediseno.com 4.18.0-553.62.1.el8_10.x86_64 #1 SMP Wed Jul 16 04:08:25 EDT 2025 x86_64
User: maor (1069)
PHP: 7.3.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //var/lib/puppet/lib/puppet/provider/csf/parsed.rb
require 'puppet/util/logging'
require 'facter'

#Provider is very important to have
Puppet::Type.type(:csf).provide(:csf, :parent => Puppet::Provider)  do
	desc "Setup allowed IPs, TCP/UDP ports, CSF state, and ICMP settings"

	attr_accessor :tcp_out #Array of TCP_OUT ports
	attr_accessor :tcp_in #Array of TCP_IN ports
	attr_accessor :udp_out #Array of UDP_OUT ports
	attr_accessor :udp_in #Array of UDP_IN ports
	attr_accessor :closed_ports #Array of blocked ports
	attr_accessor :allowed_ips #Array of ips for csf.allow
	attr_accessor :blocked_ips #Array of ips for csf.deny
	attr_accessor :allow_icmp #Boolean whether or not to use ICMP
	attr_accessor :icmp_rate #ICMP rate in the form '\d+/s'
	attr_accessor :purge #This will enforce that the given settings, and only the given settings are present. Make sure all ports and IPs are present!
	attr_accessor :enabled #Whether to force CSF to be enabled or disabled
 
	attr_accessor :skip_enable_check #If the file /etc/.csf_disabled is present, and has been touched less than 24 hours ago, skip the 'enable' check

	def initialize(resource)
		super(resource)

		@tcp_out = []
		@tcp_in = []
		@udp_out = []
		@udp_in = []
		@allowed_ips = []
		@blocked_ips = []
		@allow_icmp = true
		@icmp_rate = '10/s'
		@enabled = Facter.value('csf_enabled')
		@skip_enable_check = false
	end

	def self.prefetch(resources = nil)
		if not File.exists?('/usr/sbin/csf')
			raise Puppet::Error "Could not find csf binary"
		end

		if not File.exists?('/etc/csf/csf.conf')
			raise Puppet::Error "Could not find csf configuration"
		end

		#Resources are the individual instances of type... I think
		if resources != nil

			begin
				f = File.new('/etc/csf/csf.conf','r')
				while( line = f.gets ) do
					if line =~ /^\s*#/
						next
					elsif line =~ /^TCP_OUT\s*=\s*"(\d+(:\d+)?(,\d+(:\d+)?)*)?"\s*$/
						resources.each do |hash, instance|
							instance.provider.tcp_out= $1.split(',')
						end
					elsif line =~ /^TCP_IN\s*=\s*"(\d+(:\d+)?(,\d+(:\d+)?)*)?"\s*$/
						resources.each do |hash, instance|
							instance.provider.tcp_in= $1.split(',')
						end
					elsif line =~ /^UDP_OUT\s*=\s*"(\d+(:\d+)?(,\d+(:\d+)?)*)?"\s*$/
						resources.each do |hash, instance|
							instance.provider.udp_out= $1.split(',')
						end
					elsif line =~ /^UDP_IN\s*=\s*"(\d+(:\d+)?(,\d+(:\d+)?)*)?"\s*$/
						resources.each do |hash, instance|
							instance.provider.udp_in= $1.split(',')
						end
					elsif line =~ /^ICMP_IN\s*=\s*"(0|1)"\s*$/
						resources.each do |hash, instance|
							instance.provider.allow_icmp= ( $1 == "1" ? true : false )
						end
					elsif line =~ /^ICMP_IN_RATE\s*=\s*"(\d+\/s)"\s*$/
						resources.each do |hash, instance|
							instance.provider.icmp_rate= $1.chomp
						end
					end
					
				end
				f.close
			rescue IOError => e
				raise Puppet::Error "Could not read csf configuration file (#{e})"
			end

			skip_check = false
			if File.exists?('/etc/.csf_disabled') 
				if Time.now.to_i - File.mtime("/etc/.csf_disabled").to_i > 86400
					begin
						File.unlink("/etc/.csf_disabled")
					rescue
					end
				else
					skip_check = true
				end
			end
			resources.each do |hash, instance|
				instance.provider.skip_enable_check= skip_check
			end


			begin
				f = File.new('/etc/csf/csf.allow','r')
				while( line = f.gets ) do
					if line =~ /^\s*#/
						next
					elsif line =~ /^(\d+\.\d+\.\d+\.\d+)/
						resources.each do |hash, instance|
							instance.provider.allowed_ips.push $1.chomp
						end
					end
				end
				f.close
			rescue IOError => e
				raise Puppet::Error "Could not read csf allowed ips file (#{e})"
			end
			
			begin
				f = File.new('/etc/csf/csf.deny','r')
				while( line = f.gets ) do
					if line =~ /^\s*#/
						next
					elsif line =~ /^(\d+\.\d+\.\d+\.\d+)/
						resources.each do |hash, instance|
							instance.provider.blocked_ips.push $1.chomp
						end
					end
				end
				f.close
			rescue IOError => e
				raise Puppet::Error "Could not read csf denied ips file (#{e})"
			end

			
		end
	end

	def flush
		if ! @skip_enable_check
			if @resource.should(:enabled) == :true and Facter.value(:csf_enabled) == "false"
				Puppet.info "Enabling CSF"
				output = %x{/usr/sbin/csf -e}
				ret = $?.success?
			elsif @resource.should(:enabled) == :false and Facter.value(:csf_enabled) == "true"
				Puppet.info "Disabling CSF"
				output = %x{/usr/sbin/csf -x}
				ret = $?.success?
			end
		end


		begin
			fin = File.new('/etc/csf/csf.conf','r')
			fout = File.new('/etc/csf/csf.conf.puppetnew','w')
			while( line = fin.gets ) do
				if line =~ /^\s*#/
					fout.write(line)
				#elsif line =~ /^((?:TCP|UDP)_(?:IN|OUT))\s*=\s*"(\d+(?:,\d+)*)?"\s*$/
				elsif line =~ /^((?:TCP|UDP)_(?:IN|OUT))\s*=\s*"(\d+(?::\d+)?(?:,\d+(?::\d+)?)*)?"\s*$/
					type = $1
					case $1
						when 'TCP_OUT':
							desired_ports = @resource.value(:tcp_out)
						when 'TCP_IN':
							desired_ports = @resource.value(:tcp_in)
						when 'UDP_OUT':
							desired_ports = @resource.value(:udp_out)
						when 'UDP_IN':
							desired_ports = @resource.value(:udp_in)
					end

					real_ports = $2.split(',')
					if @resource.value(:closed_ports) != [:absent] and @resource.value(:closed_ports) != :absent
						@resource.value(:closed_ports).each do |p|
							if (loc = real_ports.index(p) ) != nil
								real_ports.delete_at(loc)
							end
						end
					end

					if desired_ports != [:absent] and desired_ports != :absent
						if @resource.value(:purge) == :true
							ports = desired_ports
						else
							ports = real_ports
							desired_ports.each do |p|
								if ! real_ports.include?(p)
									ports.push(p)
								end
							end
						end
						fout.write("#{type} = \"#{ports.join(',')}\"\n")
					else
						fout.write(line)
					end
				elsif line =~ /^ICMP_IN\s*=\s*"(0|1)"\s*$/
					if @resource.value(:allow_icmp) == true
						fout.write("ICMP_IN = \"1\"\n")
					elsif @resource.value(:allow_icmp) == false
						fout.write("ICMP_IN = \"0\"\n")
					else
						fout.write(line)
					end
				elsif line =~ /^ICMP_IN_RATE\s*=\s*"(\d+\/s)"\s*$/
					if @resource.value(:icmp_rate) != [:absent] and @resource.value(:icmp_rate) != :absent
						fout.write("ICMP_IN_RATE = \"#{@resource.value(:icmp_rate)}\"\n")
					else
						fout.write(line)
					end
				else
					fout.write(line)
				end
				
			end

			fin.close
			fout.close
			File.rename('/etc/csf/csf.conf.puppetnew','/etc/csf/csf.conf')
		rescue IOError => e
			raise Puppet::Error "Could not read csf configuration file (#{e})"
		end

		#Denied ips
		if @resource.should(:blocked_ips) != [:absent] and @resource.should(:blocked_ips) != :absent
			begin
				fin = File.new('/etc/csf/csf.deny','r')
				fout = File.new('/etc/csf/csf.deny.puppetnew','w')

				desired_ips = @resource.value(:blocked_ips)
				if @resource.value(:purge) != :true
					while( line = fin.gets ) do
						fout.write(line)
						if line =~ /^\s*((\d{1,3}\.){3}(\d{1,3}))/
							#Requested IP already exists
							if (loc = desired_ips.index($1)) != nil
								desired_ips.delete_at(loc)
							end
						end
					end
				end

				desired_ips.each do |ip|
					fout.write("#{ip}\n")
				end

				fin.close
				fout.close
				File.rename('/etc/csf/csf.deny.puppetnew','/etc/csf/csf.deny')
			rescue IOError => e
				raise Puppet::Error "Could not write denied ips file (#{e})"
			end
		end

		#Allowed ips
		if @resource.value(:allowed_ips) != [:absent] and @resource.value(:allowed_ips) != :absent
			begin
				fin = File.new('/etc/csf/csf.allow','r')
				fout = File.new('/etc/csf/csf.allow.puppetnew','w')

				desired_ips = @resource.value(:allowed_ips)
				if @resource.value(:purge) != :true
					while( line = fin.gets ) do
						fout.write(line)
						if line =~ /^\s*((\d{1,3}\.){3}(\d{1,3}))/
							#Requested IP already exists
							if (loc = desired_ips.index($1)) != nil
								desired_ips.delete_at(loc)
							end
						end
					end
				end

				desired_ips.each do |ip|
					fout.write("#{ip}\n")
				end

				fin.close
				fout.close
				File.rename('/etc/csf/csf.allow.puppetnew','/etc/csf/csf.allow')
			rescue IOError => e
				raise Puppet::Error "Could not write allowed ips file (#{e})"
			end
		end

	end

end