IPCd: file ordering.

master
Karchnu 2020-11-03 19:01:16 +01:00
parent da683e96fa
commit 01fdb317c1
5 changed files with 327 additions and 254 deletions

View File

@ -1,21 +1,64 @@
require "baguette-crystal-base"
require "./rules"
require "./ipcd_cli_parser"
require "option_parser"
require "ipc"
require "uri"
require "baguette-crystal-base"
require "./lib_modifications" # All standard library modifications.
require "./ipcd/*"
Baguette::Context.verbosity = 4
class IPCd::Service < IPC::Server
class Baguette::Configuration
class IPC < Base
property rules_directory : String = "/etc/baguette/ipcd/rules" # default
property redirections_directory : String = "/etc/baguette/ipcd/redirections" # default
property verbosity : Int32 = 2
property ipc_timer : Int32 = 30_000 # 30 seconds
property print_ipc_timer : Bool = false
property print_ipc_connection : Bool = false
property print_ipc_disconnection : Bool = false
property print_ipc_extra_socket : Bool = false
property print_ipc_message_received : Bool = false
property print_ipc_message_sent : Bool = false
property print_ipc_switch : Bool = false
def initialize
end
end
end
module IPCd
class Service < IPC::Server
@rules = RuleSet.new
@redirections = RedirectionSet.new
def parse_cli (argv : Array(String))
IPCdCLIParser.parse_rules argv, @rules, @redirections
CLIParser.parse_rules argv, @rules, @redirections
end
def parse_rule_files(directory : String)
unless File.directory? directory
raise "not a valid directory: #{directory}"
end
Array(Rule).from_yaml_files(Dir.new(directory).entries).each do |r|
@rules << r
end
end
def parse_redirection_files(directory : String)
unless File.directory? directory
raise "not a valid directory: #{directory}"
end
Array(Redirection).from_yaml_files(Dir.new(directory).entries).each do |r|
@redirections << r
end
end
def to_s(io : IO)
io << "ipcd\n"
io << @rules.to_s + "\n" + @redirections.to_s
@ -115,8 +158,21 @@ class IPCd::Service < IPC::Server
service.close
end
end
end
def main
simulation, no_configuration, configuration_file = Baguette::Configuration.option_parser
config = if no_configuration
Baguette::Configuration::IPC.new
elsif c = Baguette::Configuration::IPC.get configuration_file
c
else
Baguette::Configuration::IPC.new
end
ipcd = IPCd::Service.new "network"
# --deny <in|out> <service> <url>
@ -125,27 +181,35 @@ ipcd = IPCd::Service.new "network"
# --redirect <service-name> <new-service-name> <origin-url> <dest-url>
ipcd.parse_cli ARGV
ipcd.parse_rule_files config.rules_directory
ipcd.parse_redirection_files config.redirections_directory
Baguette::Log.debug ipcd.to_s
ipcd.base_timer = 30_000
ipcd.timer = 30_000
ipcd.base_timer = config.ipc_timer
ipcd.timer = config.ipc_timer
if simulation
pp! config
ipcd.close
exit 0
end
ipcd.loop do |event|
case event
when IPC::Event::Connection
Baguette::Log.debug "Connection: fd #{event.fd}"
Baguette::Log.debug "Connection: fd #{event.fd}" if config.print_ipc_connection
when IPC::Event::Disconnection
Baguette::Log.debug "Disconnection: fd #{event.fd}"
Baguette::Log.debug "Disconnection: fd #{event.fd}" if config.print_ipc_disconnection
when IPC::Event::ExtraSocket
Baguette::Log.debug "Extrasocket: fd #{event.fd}"
Baguette::Log.debug "Extrasocket: fd #{event.fd}" if config.print_ipc_extra_socket
when IPC::Event::Switch
Baguette::Log.debug "Switch"
Baguette::Log.debug "Switch" if config.print_ipc_switch
when IPC::Event::MessageReceived
Baguette::Log.debug "Message received: #{event.fd}"
Baguette::Log.debug "Message received: #{event.fd}" if config.print_ipc_message_received
Baguette::Log.debug event.message.to_s
begin
ipcd.service_lookup event.message, event.fd
@ -161,10 +225,10 @@ ipcd.loop do |event|
end
when IPC::Event::MessageSent
Baguette::Log.debug "Message sent: #{event.fd}"
Baguette::Log.debug "Message sent: #{event.fd}" if config.print_ipc_message_sent
when IPC::Event::Timer
Baguette::Log.debug "Timer"
Baguette::Log.debug "Timer" if config.print_ipc_timer
when IPC::Exception
Baguette::Log.debug "IPC::Exception: #{event}"
@ -172,3 +236,6 @@ ipcd.loop do |event|
end
# pp! rules.authorized? Rule::Direction::In, "authd", "tls:192.168.0.42"
end
main

39
src/ipcd/cli-parser.cr Normal file
View File

@ -0,0 +1,39 @@
module IPCd
class CLIParser
def self.pack_args (argv : Array(String))
last_flag = nil : String?
argv.chunks do |x|
if x[0..1] == "--"
last_flag = x
end
last_flag
end
end
def self.parse_rules (argv : Array(String), rules : RuleSet, redirections : RedirectionSet)
args = IPCd::CLIParser.pack_args argv
args.each do |flag, parameters|
# puts "flag: #{flag}, params: #{parameters.join(' ')}"
if flag == "--allow" || flag == "--deny"
parameters[3] # will crash if non-existant
rules << Rule.from_args parameters
elsif flag == "--redirect"
if parameters.size == 3
redirections << Redirection.new parameters[1], parameters[2]
elsif parameters.size == 5
raise "--redirect with 4 parameters not implemented, yet"
else
raise "--redirect <service> <newservice> [<origin-url> <dest-url>]"
end
else
raise "cannot understand flag: #{flag}"
end
end
end
end
end

90
src/ipcd/rules.cr Normal file
View File

@ -0,0 +1,90 @@
module IPCd
class Redirection
include YAML::Serializable
property origin : String
property destination : String
property originurl : String?
property destinationurl : String?
def initialize (@origin, @destination)
end
def initialize (@origin, @destination, @originurl, @destinationurl)
end
def to_s
"Redirection #{origin} #{destination}"
# if @originurl
# "#{origin} #{destination}"
# else
# "#{origin} #{destination} #{originurl} #{destinationurl}"
# end
end
end
class RedirectionSet < Array(Redirection)
def to_s
map(&.to_s).join("\n")
end
end
class Rule
include YAML::Serializable
enum Type
Allow
Deny
end
enum Direction
In
Out
end
getter service : String
getter url : String
getter type : Type
getter direction : Direction
def initialize (@type, @direction, @service, @url)
end
def matches_service?(service : String)
@service == "*" || @service == service
end
def matches_uri?(uri)
u = Regex.new @url
!@u.match(uri).nil?
end
def self.from_args(args : Array(String))
Rule.new(
Type.parse(args[0][2..]),
Rule::Direction.parse(args[1]),
args[2],
args[3]
)
end
def to_s
"#{type} #{direction} #{service} #{url}"
end
end
class RuleSet < Array(Rule)
def authorized?(direction : Rule::Direction, service : String, uri : String) : Bool
self.select(&.direction.==(direction))
.select(&.matches_service?(service))
.select(&.matches_uri?(uri))
.[0]?.try &.type.allow? || false
end
def to_s
map(&.to_s).join("\n")
end
end
end

View File

@ -1,38 +0,0 @@
class IPCdCLIParser
def self.pack_args (argv : Array(String))
last_flag = nil : String?
argv.chunks do |x|
if x[0..1] == "--"
last_flag = x
end
last_flag
end
end
def self.parse_rules (argv : Array(String), rules : RuleSet, redirections : RedirectionSet)
args = IPCdCLIParser.pack_args argv
args.each do |flag, parameters|
# puts "flag: #{flag}, params: #{parameters.join(' ')}"
if flag == "--allow" || flag == "--deny"
parameters[3] # will crash if non-existant
rules << Rule.from_args parameters
elsif flag == "--redirect"
if parameters.size == 3
redirections << Redirection.new parameters[1], parameters[2]
elsif parameters.size == 5
raise "--redirect with 4 parameters not implemented, yet"
else
raise "--redirect <service> <newservice> [<origin-url> <dest-url>]"
end
else
raise "oh no"
end
end
end
end

View File

@ -1,85 +0,0 @@
class Redirection
property origin : String
property destination : String
property originurl : String | Nil
property destinationurl : String | Nil
def initialize (@origin, @destination)
end
def initialize (@origin, @destination, @originurl, @destinationurl)
end
def to_s
"Redirection #{origin} #{destination}"
# if @originurl
# "#{origin} #{destination}"
# else
# "#{origin} #{destination} #{originurl} #{destinationurl}"
# end
end
end
class RedirectionSet < Array(Redirection)
def to_s
map(&.to_s).join("\n")
end
end
class Rule
enum Type
Allow
Deny
end
enum Direction
In
Out
end
getter service : String
getter url : Regex
getter type : Type
getter direction : Direction
def initialize (@type, @direction, @service, @url)
end
def matches_service?(service : String)
@service == "*" || @service == service
end
def matches_uri?(uri)
!@url.match(uri).nil?
end
def self.from_args(args : Array(String))
Rule.new(
Type.parse(args[0][2..]),
Rule::Direction.parse(args[1]),
args[2],
Regex.new args[3]
)
end
def to_s
"#{type} #{direction} #{service} #{url}"
end
end
class RuleSet < Array(Rule)
def authorized?(direction : Rule::Direction, service : String, uri : String) : Bool
self.select(&.direction.==(direction))
.select(&.matches_service?(service))
.select(&.matches_uri?(uri))
.[0]?.try &.type.allow? || false
end
def to_s
map(&.to_s).join("\n")
end
end