Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Projets publics
Ravada-Mirror
Commits
0875b65d
Commit
0875b65d
authored
Dec 19, 2019
by
Francesc Guasch
Browse files
Merge branch 'develop' of
https://github.com/UPC/ravada
into develop
parents
d4312028
fa87dfd2
Changes
4
Hide whitespace changes
Inline
Side-by-side
lib/Ravada.pm
View file @
0875b65d
...
...
@@ -1434,6 +1434,12 @@ sub _check_config($config_orig = {} , $valid_config = \%VALID_CONFIG ) {
warn
"
Error: Unknown config entry
\n
"
.
Dumper
(
\
%config
)
if
!
$
0
=~
/\.t$/
;
return
0
;
}
warn
"
Warning: LDAP authentication with match is discouraged. Try bind.
\n
"
if
exists
$config_orig
->
{
ldap
}
&&
exists
$config_orig
->
{
ldap
}
->
{
auth
}
&&
$config_orig
->
{
ldap
}
->
{
auth
}
=~
/match/
&&
$
0
!~
/\.t$/
;
return
1
;
}
...
...
lib/Ravada/Auth/LDAP.pm
View file @
0875b65d
...
...
@@ -13,7 +13,10 @@ use Authen::Passphrase;
use
Authen::Passphrase::
SaltedDigest
;
use
Carp
qw(carp)
;
use
Data::
Dumper
;
use
Digest::
SHA
qw(sha1_hex)
;
use
Digest::
SHA
qw(sha1_hex sha256_hex)
;
use
Encode
;
use
PBKDF2::
Tiny
qw/derive/
;
use
MIME::
Base64
;
use
Moose
;
use
Net::
LDAP
;
use
Net::
LDAPS
;
...
...
@@ -43,6 +46,11 @@ our $STATUS_EOF = 1;
our
$STATUS_DISCONNECTED
=
81
;
our
$STATUS_BAD_FILTER
=
89
;
our
$PBKDF2_SALT_LENGTH
=
64
;
our
$PBKDF2_ITERATIONS_LENGTH
=
4
;
our
$PBKDF2_HASH_LENGTH
=
256
;
our
$PBKDF2_LENGTH
=
$PBKDF2_SALT_LENGTH
+
$PBKDF2_ITERATIONS_LENGTH
+
$PBKDF2_HASH_LENGTH
;
=head2 BUILD
Internal OO build
...
...
@@ -64,8 +72,7 @@ Adds a new user in the LDAP directory
=cut
sub
add_user
{
my
(
$name
,
$password
,
$is_admin
)
=
@_
;
sub
add_user
($name, $password, $storage='rfc2307', $algorithm=undef ) {
_init_ldap_admin
();
...
...
@@ -76,8 +83,6 @@ sub add_user {
if
!
_dc_base
();
my
(
$givenName
,
$sn
)
=
$name
=~
m{(\w+)\.(.*)}
;
my
$apr
=
Authen::Passphrase::
SaltedDigest
->
new
(
passphrase
=>
$password
,
algorithm
=>
"
MD5
");
my
%entry
=
(
cn
=>
$name
,
uid
=>
$name
...
...
@@ -87,7 +92,7 @@ sub add_user {
,
givenName
=>
(
$givenName
or
$name
)
,
sn
=>
(
$sn
or
$name
)
# , homeDirectory => "/home/$name"
,
userPassword
=>
$apr
->
as_rfc2307
(
)
,
userPassword
=>
_password_store
(
$password
,
$storage
,
$algorithm
)
);
my
$dn
=
"
cn=
$name
,
"
.
_dc_base
();
...
...
@@ -97,6 +102,51 @@ sub add_user {
}
}
sub
_password_store
($password, $storage, $algorithm) {
return
_password_rfc2307
(
$password
,
$algorithm
)
if
lc
(
$storage
)
eq
'
rfc2307
';
return
_password_pbkdf2
(
$password
,
$algorithm
)
if
lc
(
$storage
)
eq
'
pbkdf2
';
confess
"
Error: Unknown storage '
$storage
'
";
}
sub
_password_pbkdf2
($password, $algorithm='SHA-256') {
$algorithm
=
'
SHA-256
'
if
!
defined
$algorithm
;
my
$salt
=
encode
('
ascii
',
Ravada::Utils::
random_name
(
$PBKDF2_SALT_LENGTH
));
die
"
wrong salt length
"
.
length
(
$salt
)
.
"
!=
$PBKDF2_SALT_LENGTH
"
if
length
(
$salt
)
!=
$PBKDF2_SALT_LENGTH
;
my
$iterations
=
1024
;
my
$derive
=
derive
(
$algorithm
,
encode
('
ascii
',
$password
)
,
$salt
,
$iterations
,
$PBKDF2_HASH_LENGTH
);
my
$iterations_n
=
pack
('
N
',
$iterations
);
die
"
wrong iterations length
"
.
length
(
$iterations_n
)
.
"
!=
$PBKDF2_ITERATIONS_LENGTH
"
if
length
(
$iterations_n
)
!=
$PBKDF2_ITERATIONS_LENGTH
;
my
$pbkdf2
=
$iterations_n
.
$salt
.
$derive
;
die
"
wrong pass length
"
.
length
(
$pbkdf2
)
.
"
!=
$PBKDF2_LENGTH
"
if
length
(
$pbkdf2
)
!=
$PBKDF2_LENGTH
;
$algorithm
=~
s/-//
;
return
"
\
{PBKDF2_
$algorithm
}
"
.
encode_base64
(
$pbkdf2
,"");
}
sub
_password_rfc2307
($password, $algorithm='MD5') {
my
$apr
=
Authen::Passphrase::
SaltedDigest
->
new
(
passphrase
=>
$password
,
algorithm
=>
(
$algorithm
or
'
MD5
'));
return
$apr
->
as_rfc2307
();
}
=head2 remove_user
Removes the user
...
...
@@ -348,10 +398,11 @@ sub login($self) {
}
$user_ok
=
$self
->
_login_bind
()
if
!
exists
$$CONFIG
->
{
ldap
}
->
{
auth
}
||
!
$$CONFIG
->
{
ldap
}
->
{
auth
}
||
$$CONFIG
->
{
ldap
}
->
{
auth
}
=~
/bind|all/i
;
$user_ok
=
$self
->
_login_match
()
if
!
$user_ok
;
if
!
exists
$$CONFIG
->
{
ldap
}
->
{
auth
}
||
$$CONFIG
->
{
ldap
}
->
{
auth
}
=~
/bind|all/i
;
$user_ok
=
$self
->
_login_match
()
if
!
$user_ok
&&
exists
$$CONFIG
->
{
ldap
}
->
{
auth
}
&&
$$CONFIG
->
{
ldap
}
->
{
auth
}
=~
/match|all/i
;
$self
->
_check_user_profile
(
$self
->
name
)
if
$user_ok
;
$LDAP_ADMIN
->
unbind
if
$LDAP_ADMIN
&&
exists
$self
->
{
_auth
}
&&
$self
->
{
_auth
}
eq
'
bind
';
...
...
@@ -454,7 +505,47 @@ sub _match_password {
# ."\n"
# .sha1_hex($password);
return
Authen::
Passphrase
->
from_rfc2307
(
$password_ldap
)
->
match
(
$password
);
my
(
$storage
)
=
$password_ldap
=~
/^{([a-z0-9]+)[_}]/i
;
my
(
$password_ldap_hex
)
=
$password_ldap
=~
/.*?}(.*)/
;
return
Authen::
Passphrase
->
from_rfc2307
(
$password_ldap
)
->
match
(
$password
)
if
$storage
=~
/rfc2307|md5/i
;
return
_match_pbkdf2
(
$password_ldap
,
$password
)
if
$storage
=~
/pbkdf2|SSHA/i
;
confess
"
Error: storage
$storage
can't do match. Use bind.
";
}
sub
_ntohl
{
return
unless
defined
wantarray
;
confess
"
Wrong number of arguments ($#_) to
"
.
__PACKAGE__
.
"
::ntohl, called
"
if
@
_
!=
1
and
!
wantarray
;
unpack
('
L*
',
pack
('
N*
',
@
_
));
}
sub
_match_pbkdf2
($password_db_64, $password) {
my
(
$sign
,
$password_db
)
=
$password_db_64
=~
/(\{.*?})(.*)/
;
$password_db
=
decode_base64
(
$password_db
);
my
(
$algorithm
,
$n
)
=
$sign
=~
/_(.*?)(\d+)}/
;
die
"
password_db length wrong:
"
.
length
(
$password_db
)
.
"
!=
$PBKDF2_LENGTH
"
if
length
(
$password_db
)
!=
$PBKDF2_LENGTH
;
my
(
$iterations_db
)
=
substr
(
$password_db
,
0
,
$PBKDF2_ITERATIONS_LENGTH
);
my
$iterations
=
unpack
'
V
',
$iterations_db
;
(
$iterations
)
=
_ntohl
(
$iterations
);
my
(
$salt
)
=
substr
(
$password_db
,
$PBKDF2_ITERATIONS_LENGTH
,
$PBKDF2_SALT_LENGTH
);
my
$derive
=
derive
("
$algorithm
-
$n
",
encode
('
ascii
',
$password
),
$salt
,
$iterations
,
$PBKDF2_HASH_LENGTH
);
my
$match
=
$sign
.
encode_base64
(
$iterations_db
.
$salt
.
$derive
,"");
return
$password_db_64
eq
$match
;
}
sub
_dc_base
{
...
...
t/65_user_ldap.t
View file @
0875b65d
...
...
@@ -47,11 +47,7 @@ sub _remove_user_ldap($name) {
}
}
sub
test_user
{
my
$name
=
(
shift
or
'
jimmy.mcnulty
');
my
$with_posix_group
=
(
shift
or
0
);
my
$password
=
'
jameson
';
sub
test_user
($name, $with_posix_group=0, $password='jameson', $storage=undef, $algorithm=undef) {
if
(
Ravada::Auth::LDAP::
search_user
(
$name
)
)
{
diag
("
Removing
$name
");
Ravada::Auth::LDAP::
remove_user
(
$name
)
...
...
@@ -72,7 +68,11 @@ sub test_user{
ok
(
!
$row
->
{
name
},"
I shouldn't find
$name
in the SQL db
"
.
Dumper
(
$row
));
eval
{
Ravada::Auth::LDAP::
add_user
(
$name
,
$password
)
};
my
@options
;
push
@options
,
(
$storage
)
if
defined
$storage
;
push
@options
,
(
$algorithm
)
if
defined
$algorithm
;
eval
{
Ravada::Auth::LDAP::
add_user
(
$name
,
$password
,
@options
)
};
push
@USERS
,(
$name
);
ok
(
!
$@
,
$@
)
or
return
;
...
...
@@ -155,6 +155,7 @@ sub remove_users {
sub
test_add_group
{
Ravada::Auth::LDAP::
init
();
my
$name
=
"
grup.test
";
Ravada::Auth::LDAP::
remove_group
(
$name
)
...
...
@@ -202,6 +203,7 @@ sub test_manage_group {
ok
(
!
$@
,
$@
);
ok
(
!
$is_admin
,"
User
$uid
should not be admin
");
Ravada::Auth::LDAP::
init
();
Ravada::Auth::LDAP::
add_to_group
(
$uid
,
$name
);
if
(
$with_admin
)
{
...
...
@@ -492,6 +494,35 @@ sub test_login_fields($data) {
}
}
sub
test_pass_storage
($with_posix_group) {
my
%data
=
(
rfc2307
=>
'
MD5
'
,
PBKDF2
=>
'
SHA-256
'
);
for
my
$storage
(
keys
%data
)
{
for
my
$algorithm
(
undef
,
$data
{
$storage
}
)
{
my
$name
=
"
tst_
"
.
lc
(
$storage
)
.
"
_
"
.
lc
(
$algorithm
or
'
none
');
my
@args
=
(
$name
,
$with_posix_group
,
$$
,
$storage
);
push
@args
,
(
$algorithm
)
if
$algorithm
;
Ravada::Auth::LDAP::
init
();
my
$user
=
test_user
(
@args
);
my
$sign
=
$storage
;
$sign
=
$data
{
$storage
}
if
$sign
eq
'
rfc2307
';
like
(
$user
->
{
_ldap_entry
}
->
get_value
('
userPassword
'),
qr/^{$sign/
);
$user
->
_login_match
();
$user
->
_login_bind
();
$user
->
_login_match
();
$user
->
_login_bind
();
_remove_user_ldap
(
$name
);
}
}
Ravada::Auth::LDAP::
init
();
}
SKIP:
{
test_filter
();
my
$file_config
=
"
t/etc/ravada_ldap.conf
";
...
...
@@ -524,6 +555,8 @@ SKIP: {
ok
(
$ldap
)
and
do
{
test_user_fail
();
test_pass_storage
(
$with_posix_group
);
my
$user
=
test_user
(
'
pepe.mcnulty
',
$with_posix_group
);
test_add_group
();
...
...
@@ -532,7 +565,6 @@ SKIP: {
test_user_bind
(
$user
,
$fly_config
,
$with_posix_group
);
remove_users
();
};
unlink
(
$fly_config
)
if
-
e
$fly_config
;
...
...
t/etc/ravada_ldap.conf
View file @
0875b65d
...
...
@@ -4,6 +4,5 @@ ldap:
admin_user
:
dn
:
cn
=
Directory
Manager
password
:
12345678
auth
:
match
base
:
'dc=example,dc=com'
ravada_posix_group
:
rvd_posix_group
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment