Add Auth::PAM (#closes: #1196)

This commit is contained in:
Xavier Guimard 2017-03-14 15:34:10 +00:00
parent 625ea22266
commit a07e92759c
11 changed files with 146 additions and 9 deletions

View File

@ -148,6 +148,8 @@ sub defaultValues {
'openIdSreg_fullname' => 'cn',
'openIdSreg_nickname' => 'uid',
'openIdSreg_timezone' => '_timezone',
'pamAuthnLevel' => 2,
'pamService' => 'login',
'passwordDB' => 'Demo',
'portal' => 'http://auth.example.com/',
'portalAntiFrame' => 1,

View File

@ -42,6 +42,7 @@ our $authParameters = {
nullParams => [qw(nullAuthnLevel)],
oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],
openidParams => [qw(openIdAuthnLevel openIdExportedVars openIdSecret openIdIDPList)],
pamParams => [qw(pamService pamAuthnLevel)],
proxyParams => [qw(proxyAuthService proxySessionService remoteCookieName proxyAuthnLevel proxyUseSoap)],
radiusParams => [qw(radiusAuthnLevel radiusSecret radiusServer)],
remoteParams => [qw(remotePortal remoteCookieName remoteGlobalStorage remoteGlobalStorageOptions)],

View File

@ -27,7 +27,7 @@ sub types {
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval "$s $val";
my $err = join(
@ -308,6 +308,10 @@ sub attributes {
'k' => 'LDAP',
'v' => 'LDAP'
},
{
'k' => 'PAM',
'v' => 'PAM'
},
{
'k' => 'Null',
'v' => 'None'
@ -498,6 +502,10 @@ sub attributes {
'k' => 'LDAP',
'v' => 'LDAP'
},
{
'k' => 'PAM',
'v' => 'PAM'
},
{
'k' => 'Radius',
'v' => 'Radius'
@ -707,6 +715,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'k' => 'LDAP',
'v' => 'LDAP'
},
{
'k' => 'PAM',
'v' => 'PAM'
},
{
'k' => 'Radius',
'v' => 'Radius'
@ -927,7 +939,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval $s;
my $err = join(
@ -996,7 +1008,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval "$s $val";
my $err = join(
@ -1019,7 +1031,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval "$s $val";
my $err = join(
@ -1331,7 +1343,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval $s;
my $err = join(
@ -1368,7 +1380,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval "$s $val";
my $err = join(
@ -1862,6 +1874,14 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
'default' => '_timezone',
'type' => 'lmAttrOrMacro'
},
'pamAuthnLevel' => {
'default' => 2,
'type' => 'int'
},
'pamService' => {
'default' => 'login',
'type' => 'text'
},
'passwordDB' => {
'default' => 'Demo',
'select' => [
@ -2018,7 +2038,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
BEGIN {
${^WARNING_BITS} =
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55\x05";
"\x54\x55\x55\x55\x15\x55\x55\x55\x55\x55\x51\x55\x55\x55\x55\x55\x55";
}
eval "$s $val";
my $err = join(

View File

@ -1756,6 +1756,7 @@ sub attributes {
{ k => 'Facebook', v => 'Facebook' },
{ k => 'Google', v => 'Google' },
{ k => 'LDAP', v => 'LDAP' },
{ k => 'PAM', v => 'PAM' },
{ k => 'Radius', v => 'Radius' },
{ k => 'REST', v => 'REST' },
{ k => 'SSL', v => 'SSL' },
@ -2020,6 +2021,18 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
keyMsgFail => '__badCasProxyId__',
},
# PAM
pamAuthnLevel => {
type => 'int',
default => 2,
documentation => 'PAM authentication level',
},
pamService => {
type => 'text',
default => 'login',
documentation => 'PAM service',
},
# Radius
radiusAuthnLevel => {
type => 'int',
@ -2219,6 +2232,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
{ k => 'Facebook', v => 'Facebook' },
{ k => 'Google', v => 'Google' },
{ k => 'LDAP', v => 'LDAP' },
{ k => 'PAM', v => 'PAM' },
{ k => 'Null', v => 'None' },
{ k => 'OpenID', v => 'OpenID' },
{ k => 'OpenIDConnect', v => 'OpenID Connect' },
@ -2281,6 +2295,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
{ k => 'Facebook', v => 'Facebook' },
{ k => 'Google', v => 'Google' },
{ k => 'LDAP', v => 'LDAP' },
{ k => 'PAM', v => 'PAM' },
{ k => 'Radius', v => 'Radius' },
{ k => 'REST', v => 'REST' },
{ k => 'SSL', v => 'SSL' },

View File

@ -287,6 +287,12 @@ sub tree {
'proxyUseSoap'
]
},
{
title => 'pamParams',
help => 'authpam.html',
form => 'simpleInputContainer',
nodes => [ 'pamService', 'pamAuthnLevel', ]
},
{
title => 'radiusParams',
help => 'authradius.html',

View File

@ -509,6 +509,9 @@
"OpenIDConnect_OP": "Provider key",
"OptionalTitle": "Optional title",
"overPrm": "Overloaded parameters",
"pamAuthnLevel": "Authentication level",
"pamParams": "PAM parameters",
"pamService": "PAM service",
"password": "Password",
"passwordDB": "Password module",
"passwordManagement": "Password management",

View File

@ -509,6 +509,9 @@
"OpenIDConnect_OP": "Clef du fournisseur",
"OptionalTitle": "Titre optionnel",
"overPrm": "Paramètres surchargés",
"pamAuthnLevel": "Niveau d'authentification",
"pamParams": "Paramètres PAM",
"pamService": "Service PAM",
"password": "Mot-de-passe",
"passwordDB": "Module de mot de passe",
"passwordManagement": "Gestion des mots de passe",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -23,6 +23,7 @@ lib/Lemonldap/NG/Portal/Auth/LDAP.pm
lib/Lemonldap/NG/Portal/Auth/Null.pm
lib/Lemonldap/NG/Portal/Auth/OpenID.pm
lib/Lemonldap/NG/Portal/Auth/OpenIDConnect.pm
lib/Lemonldap/NG/Portal/Auth/PAM.pm
lib/Lemonldap/NG/Portal/Auth/Proxy.pm
lib/Lemonldap/NG/Portal/Auth/Radius.pm
lib/Lemonldap/NG/Portal/Auth/Remote.pm

View File

@ -0,0 +1,86 @@
package Lemonldap::NG::Portal::Auth::PAM;
use strict;
use Mouse;
use Authen::PAM;
use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADCREDENTIALS
PE_ERROR
PE_OK
);
extends qw(Lemonldap::NG::Portal::Auth::_WebForm);
our $VERSION = '2.0.0';
# INITIALIZATION
has service => (
is => 'rw',
default => sub {
return $_[0]->{conf}->{pamService} || 'login';
}
);
# RUNNING METHODS
sub authenticate {
my ( $self, $req ) = @_;
no strict 'subs';
# Handler to dial with Authen::PAM
my $handler = sub {
my @response = ();
while (@_) {
my $code = shift;
my $msg = shift;
my $res;
if ( $code == PAM_PROMPT_ECHO_ON ) {
$res = $req->user;
}
elsif ( $code == PAM_PROMPT_ECHO_OFF ) {
$res = $req->datas->{password};
}
push( @response, PAM_SUCCESS, $res );
}
return ( @response, PAM_SUCCESS );
};
# Launch PAM service
my $pam = Authen::PAM->new( $self->service, $req->user, $handler );
unless ( ref $pam ) {
$self->logger->error(
'PAM failed: ' . Authen::PAM->pam_strerror($pam) );
return PE_ERROR;
}
# Check for authentication and authorization
foreach my $sub (qw(pam_authenticate pam_acct_mgmt)) {
my $res = $pam->$sub;
unless ( $res == PAM_SUCCESS ) {
$self->userLogger->warn( "PAM failed to authenticate $req->{user}: "
. $pam->pam_strerror($res) );
return PE_BADCREDENTIALS;
}
}
$self->userLogger->notice("Good PAM authentication for $req->{user}");
return PE_OK;
}
sub setAuthSessionInfo {
my ( $self, $req ) = @_;
$req->sessionInfo->{authenticationLevel} = $self->conf->{pamAuthnLevel};
PE_OK;
}
sub authLogout {
PE_OK;
}
1;