Auth-Kokolores
view release on metacpan or search on metacpan
lib/Auth/Kokolores.pm view on Meta::CPAN
sub configure {
my $self = shift;
my $server = $self->{'server'};
return if(@_);
if( ! defined $server->{'config_file'} ) {
$server->{'config_file'} = '/etc/kokolores/kokolores.conf';
}
$self->{'program_name'} = $0;
$server->{'background'} = 1;
$server->{'setsid'} = 1;
$server->{'no_close_by_child'} = 1;
# commandline options
my $cmdline = {};
GetOptions( $cmdline,
"help|h",
"config|c:s",
"foreground|f",
"loglevel|l:i",
);
if ($cmdline->{'help'}) {
$self->print_usage;
exit 0;
}
if (defined($cmdline->{'config'}) && $cmdline->{'config'} ne "") {
$server->{'config_file'} = $cmdline->{'config'};
}
# read and apply configuration file
my $config = Auth::Kokolores::Config->new_from_file( $server->{'config_file'} );
$config->apply_config( $self );
$server->{'port'} = $self->{'socket_path'}.'|unix';
$self->{'plugins'} = Auth::Kokolores::Plugins->new_from_config( $self, $config->Plugin );
# cmdline values which overwrite config/defaults
if ($cmdline->{'foreground'}) {
$server->{'background'} = undef;
$server->{'setsid'} = undef;
$server->{'log_file'} = undef;
}
if( $cmdline->{'loglevel'} ) {
$server->{'log_level'} = $cmdline->{'loglevel'};
}
return;
}
sub post_configure_hook {
my $self = shift;
$self->{'plugins'}->init( $self );
return;
}
sub post_bind_hook {
my $self = shift;
$self->_set_process_stat('master');
$self->set_socket_permissions;
return;
}
sub set_socket_permissions {
my $self = shift;
if( ! defined $self->{'socket_mode'} ) {
return;
}
my $mode = oct($self->{'socket_mode'});
$self->log(2, sprintf('setting socket mode to: %o', $mode));
chmod( $mode, $self->{'socket_path'} )
or $self->log(1, 'could not change mode of socket: '.$!);
return;
}
sub child_init_hook {
my $self = shift;
$self->{'plugins'}->child_init( $self );
$self->_set_process_stat('virgin child');
return;
}
sub child_finish_hook {
my $self = shift;
$self->{'plugins'}->shutdown( $self );
return;
}
sub authenticate {
my ( $self, $r ) = @_;
my $failed = 0;
foreach my $plugin ( $self->{'plugins'}->all_plugins ) {
my $ok = $plugin->authenticate( $r );
if( ! defined $ok ) {
$self->log(3, 'plugin '.$plugin->name.': next');
next;
} elsif( $ok && $self->{'satisfy'} eq 'any' ) {
$self->log(3, 'plugin '.$plugin->name.': success (any)');
return Auth::Kokolores::Response->new_success;
} elsif( !$ok && $self->{'satisfy'} ne 'any' ) {
$self->log(3, 'plugin '.$plugin->name.': failed (all)');
return Auth::Kokolores::Response->new_fail;
} elsif( $ok ) {
$self->log(3, 'plugin '.$plugin->name.': success');
} else {
$self->log(3, 'plugin '.$plugin->name.': failed');
$failed++;
}
}
if( $failed == 0 ) {
return Auth::Kokolores::Response->new_success;
}
return Auth::Kokolores::Response->new_fail;
}
sub pre_process_kokolores_request {
my ( $self, $r ) = @_;
foreach my $plugin ( $self->{'plugins'}->all_plugins ) {
my $pre_response = $plugin->pre_process( $r );
if( defined $pre_response ) {
return $pre_response;
}
}
return;
}
sub post_process_kokolores_request {
my ( $self, $r, $response ) = @_;
foreach my $plugin ( $self->{'plugins'}->all_plugins ) {
my $post_response = $plugin->post_process( $r, $response );
if( defined $post_response ) {
return $post_response;
}
}
return;
}
sub process_kokolores_request {
my ( $self, $r ) = @_;
my $pre_response = $self->pre_process_kokolores_request( $r );
if( defined $pre_response ) {
# if there is a response from a pre_process object
# return with this response
return $pre_response;
}
my $response = $self->authenticate( $r );
my $post_response = $self->post_process_kokolores_request( $r, $response );
if( defined $post_response ) {
return $post_response;
}
return $response;
}
sub get_protocol_handler {
my ( $self, $conn, $port ) = @_;
# TODO: make this configurable per socket
my $protocol = $self->{'protocol'};
my $protocol_class = "Auth::Kokolores::Protocol::".$protocol;
return $protocol_class->new(
server => $self,
handle => $conn,
);
}
sub process_request {
my ( $self, $conn ) = @_;
my $port = $conn->NS_port;
$self->log(4, "accepted new client on port $port");
my $protocol = $self->get_protocol_handler( $conn, $port );
$protocol->init_connection;
$self->_set_process_stat('waiting request');
my $r = $protocol->read_request;
$self->_set_process_stat('processing request');
my $response;
eval { $response = $self->process_kokolores_request( $r ); };
if( $@ ) {
$self->log(1, 'processing request failed: '.$@);
return;
}
$protocol->write_response( $response );
$protocol->shutdown_connection;
$self->_set_process_stat('idle');
return;
}
sub _set_process_stat {
my ( $self, $stat ) = @_;
$0 = $self->{'program_name'}.' ('.$stat.')';
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Auth::Kokolores - an alternative saslauthd
=head1 VERSION
version 1.01
=head1 AUTHOR
Markus Benning <ich@markusbenning.de>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2016 by Markus Benning <ich@markusbenning.de>.
This is free software, licensed under:
The GNU General Public License, Version 2, June 1991
=cut
( run in 1.445 second using v1.01-cache-2.11-cpan-302cb4679cc )