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
Sympa
Commits
66680ad4
Unverified
Commit
66680ad4
authored
Mar 02, 2019
by
IKEDA Soji
Committed by
GitHub
Mar 02, 2019
Browse files
Merge pull request #557 from ikedas/deprecate_ciphersaber by ikedas
Deprecate CipherSaber RC4 encryption (#87)
parents
273d572f
18bdba2a
Changes
8
Hide whitespace changes
Inline
Side-by-side
default/mail_tt2/listmaster_notification.tt2
View file @
66680ad4
...
...
@@ -65,6 +65,11 @@ Subject: [% FILTER qencode %][%|loc%]Upgrade procedures failed[%END%][%END%]
[%|loc%]Check log file for further details.[%END%]
[% ELSIF type == 'password_encrypted' -%]
Subject: [% FILTER qencode %][%|loc%]Password should be rehashed[%END%][%END%]
[%|loc%]Password in database seems encrypted. Run upgrade_sympa_password.pl to rehash passwords.[%END%]
[% ELSIF type == 'db_struct_updated' -%]
Subject: [% FILTER qencode %][%|loc%]Database structure updated[%END%][%END%]
X-Sympa-NoWrap: yes
...
...
src/bin/upgrade_sympa_password.pl.in
View file @
66680ad4
...
...
@@ -9,8 +9,8 @@
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
# Copyright 2017, 2018 The Sympa Community. See the AUTHORS.md file at
the
# top-level directory of this distribution and at
# Copyright 2017, 2018
, 2019
The Sympa Community. See the AUTHORS.md file at
#
the
top-level directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
#
# This program is free software; you can redistribute it and/or modify
...
...
@@ -29,14 +29,16 @@
use
lib
split
(
/:/
,
$ENV
{
SYMPALIB
}
||
''),
'
--modulesdir--
';
use
strict
;
use
warnings
;
use
Digest::
MD5
;
use
Getopt::
Long
;
use
MIME::
Base64
qw()
;
use
Time::
HiRes
qw(gettimeofday tv_interval)
;
BEGIN
{
eval
'
use Crypt::CipherSaber
';
}
use
Conf
;
use
Sympa::
DatabaseManager
;
use
Sympa::Tools::
Password
;
use
Sympa::
User
;
use
Digest::
MD5
;
use
Getopt::
Long
;
use
Time::
HiRes
qw(gettimeofday tv_interval)
;
my
$usage
=
"
Usage: $0 [--dry_run|n] [--debug|d] [--verbose|v] [--config file] [--cache file] [--nosavecache] [--noupdateuser] [--limit|l]
\n
";
...
...
@@ -77,8 +79,6 @@ if ($dry_run) {
$savecache
=
$updateuser
=
0
;
}
die
"
Crypt::CipherSaber not installed ; cannot crypt passwords
"
unless
$
Crypt::CipherSaber::
VERSION
;
die
'
Error in configuration
'
unless
Conf::
load
(
$config
,
'
no_db
');
...
...
@@ -104,8 +104,17 @@ $dry_run && print "dry_run: database will *not* be updated.\n";
my
$sdm
=
Sympa::
DatabaseManager
->
instance
or
die
'
Can
\'
t connect to database
';
my
$sth
;
# Check if RC4 decryption required.
$sth
=
$sdm
->
do_prepared_query
(
q{SELECT COUNT(*) FROM user_table WHERE password_user LIKE 'crypt.%'}
);
my
(
$encrypted
)
=
$sth
->
fetchrow_array
;
if
(
$encrypted
and
not
$
Crypt::CipherSaber::
VERSION
)
{
die
"
Password seems encrypted while Crypt::CipherSaber is not installed!
\n
";
}
my
$sth
=
$sdm
->
do_query
(
q{SELECT email_user, password_user from user_table}
);
$sth
=
$sdm
->
do_query
(
q{SELECT email_user, password_user from user_table}
);
unless
(
$sth
)
{
die
'
Unable to prepare SQL statement
';
}
...
...
@@ -139,10 +148,11 @@ while (my $user = $sth->fetchrow_hashref('NAME_lc')) {
next
;
}
if
(
$user
->
{'
password_user
'}
=~
/^crypt.(.*)$/
)
{
$clear_password
=
Sympa::Tools::Password::
decrypt_password
(
$user
->
{'
password_user
'});
}
else
{
## Old style cleartext passwords
if
(
$user
->
{'
password_user
'}
=~
/\Acrypt[.](.*)\z/
)
{
# Old style RC4 encrypted password.
$clear_password
=
_decrypt_rc4_password
(
$user
->
{'
password_user
'});
}
else
{
# Old style cleartext password.
$clear_password
=
$user
->
{'
password_user
'};
}
...
...
@@ -253,6 +263,20 @@ if ($total->{'prehashes'}) {
exit
0
;
my
$rc4
;
# decrypt RC4 encrypted password.
# Old name: Sympa::Tools::Password::decrypt_password().
sub
_decrypt_rc4_password
{
my
$inpasswd
=
shift
;
return
$inpasswd
unless
$inpasswd
=~
/\Acrypt[.](.*)\z/
;
$inpasswd
=
$
1
;
$rc4
=
Crypt::
CipherSaber
->
new
(
$
Conf::
Conf
{'
cookie
'})
unless
$rc4
;
return
$rc4
->
decrypt
(
MIME::Base64::
decode
(
$inpasswd
));
}
#
# Here we use MD5 as a quick way to make sure that a precalculated hash
# is still valid.
...
...
src/lib/Sympa/List.pm
View file @
66680ad4
...
...
@@ -64,7 +64,6 @@ use Sympa::Ticket;
use Sympa::Tools::Data;
use Sympa::Tools::Domains;
use Sympa::Tools::File;
use Sympa::Tools::Password;
use Sympa::Tools::SMIME;
use Sympa::Tools::Text;
use Sympa::User;
...
...
@@ -3878,14 +3877,6 @@ sub add_list_member {
$new_user->{'custom_attribute'}
);
# Crypt password if it was not crypted.
unless (
Sympa::Tools::Data::smart_eq($new_user->{'password'}, qr/^crypt/))
{
$new_user->{'password'} = Sympa::Tools::Password::crypt_password(
$new_user->{'password'});
}
## Either is_included or is_subscribed must be set
## default is is_subscriber for backward compatibility reason
unless ($new_user->{'included'}) {
...
...
src/lib/Sympa/Tools/Password.pm
View file @
66680ad4
...
...
@@ -8,6 +8,9 @@
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
# Copyright 2019 The Sympa Community. See the AUTHORS.md file at
# the top-level directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
...
...
@@ -27,15 +30,10 @@ package Sympa::Tools::Password;
use
strict
;
use
warnings
;
use
Digest::
MD5
;
use
MIME::
Base64
qw()
;
BEGIN
{
eval
'
use Crypt::CipherSaber
';
}
BEGIN
{
eval
'
use Data::Password
';
}
use
Conf
;
use
Sympa::
Language
;
use
Sympa::
Log
;
my
$log
=
Sympa::
Log
->
instance
;
sub
tmp_passwd
{
my
$email
=
shift
;
...
...
@@ -47,46 +45,14 @@ sub tmp_passwd {
'
init
'
.
substr
(
Digest::MD5::
md5_hex
(
join
'
/
',
$cookie
,
$email
),
-
8
));
}
# global var to store a CipherSaber object
my
$cipher
;
# create a cipher
sub
ciphersaber_installed
{
return
$cipher
if
defined
$cipher
;
if
(
$
Crypt::CipherSaber::
VERSION
)
{
$cipher
=
Crypt::
CipherSaber
->
new
(
$
Conf::
Conf
{'
cookie
'});
}
else
{
$cipher
=
'';
}
return
$cipher
;
}
# No longer used, Use _decrypt_rc4_password() in upgrade_sympa_password.pl.
#sub ciphersaber_installed;
## encrypt a password
sub
crypt_password
{
my
$inpasswd
=
shift
;
# No longer used.
#sub crypt_password;
ciphersaber_installed
();
return
$inpasswd
unless
$cipher
;
return
("
crypt.
"
.
MIME::Base64::
encode
(
$cipher
->
encrypt
(
$inpasswd
)));
}
## decrypt a password
sub
decrypt_password
{
my
$inpasswd
=
shift
;
$log
->
syslog
('
debug2
',
'
(%s)
',
$inpasswd
);
return
$inpasswd
unless
(
$inpasswd
=~
/^crypt\.(.*)$/
);
$inpasswd
=
$
1
;
ciphersaber_installed
();
unless
(
$cipher
)
{
$log
->
syslog
('
info
',
'
Password seems crypted while CipherSaber is not installed !
');
return
$inpasswd
;
}
return
(
$cipher
->
decrypt
(
MIME::Base64::
decode
(
$inpasswd
)));
}
# Moved: Use _decrypt_rc4_password() in upgrade_sympa_password.pl.
#sub decrypt_password;
# Old name: Sympa::Session::get_random().
sub
get_random
{
...
...
src/lib/Sympa/User.pm
View file @
66680ad4
...
...
@@ -39,7 +39,6 @@ use Sympa::DatabaseManager;
use
Sympa::
Language
;
use
Sympa::
Log
;
use
Sympa::Tools::
Data
;
use
Sympa::Tools::
Password
;
use
Sympa::Tools::
Text
;
my
$log
=
Sympa::
Log
->
instance
;
...
...
@@ -535,13 +534,7 @@ sub get_global_user {
$sth
=
pop
@sth_stack
;
if
(
defined
$user
)
{
## decrypt password
if
(
$user
->
{'
password
'})
{
$user
->
{'
password
'}
=
Sympa::Tools::Password::
decrypt_password
(
$user
->
{'
password
'});
}
## Canonicalize lang if possible
# Canonicalize lang if possible.
if
(
$user
->
{'
lang
'})
{
$user
->
{'
lang
'}
=
Sympa::Language::
canonic_lang
(
$user
->
{'
lang
'})
||
$user
->
{'
lang
'};
...
...
src/lib/Sympa/WWW/Auth.pm
View file @
66680ad4
...
...
@@ -152,6 +152,15 @@ sub authentication {
## the user passwords
## Other backends are Single Sign-On solutions
if
(
$auth_service
->
{'
auth_type
'}
eq
'
user_table
')
{
# Old style RC4 encrypted password.
if
(
$user
->
{'
password
'}
and
$user
->
{'
password
'}
=~
/\Acrypt[.]/
)
{
$log
->
syslog
('
notice
',
'
Password in database seems encrypted. Run upgrade_sympa_password.pl to rehash passwords
'
);
Sympa::
send_notify_to_listmaster
('
*
',
'
password_encrypted
');
return
undef
;
}
my
$fingerprint
=
Sympa::User::
password_fingerprint
(
$pwd
,
$user
->
{'
password
'});
...
...
src/lib/Sympa/WWW/SOAP.pm
View file @
66680ad4
...
...
@@ -193,12 +193,8 @@ sub login {
}
## Create Sympa::WWW::Session object
my
$session
=
Sympa::WWW::
Session
->
new
(
$robot
,
{
'
cookie
'
=>
Sympa::WWW::Session::
encrypt_session_id
(
$ENV
{'
SESSION_ID
'})
}
);
my
$session
=
Sympa::WWW::
Session
->
new
(
$robot
,
{
cookie
=>
$ENV
{
SESSION_ID
}});
$ENV
{'
USER_EMAIL
'}
=
$email
;
$session
->
{'
email
'}
=
$email
;
$session
->
store
();
...
...
@@ -208,7 +204,7 @@ sub login {
## Also return the cookie value
return
SOAP::
Data
->
name
('
result
')
->
type
('
string
')
->
value
(
Sympa::WWW::Session::
encrypt_session_id
(
$ENV
{
'
SESSION_ID
'})
);
->
value
(
$ENV
{
SESSION_ID
}
);
}
sub
casLogin
{
...
...
@@ -289,12 +285,8 @@ sub casLogin {
}
## Create Sympa::WWW::Session object
my
$session
=
Sympa::WWW::
Session
->
new
(
$robot
,
{
'
cookie
'
=>
Sympa::WWW::Session::
encrypt_session_id
(
$ENV
{'
SESSION_ID
'})
}
);
my
$session
=
Sympa::WWW::
Session
->
new
(
$robot
,
{
cookie
=>
$ENV
{
SESSION_ID
}});
$ENV
{'
USER_EMAIL
'}
=
$email
;
$session
->
{'
email
'}
=
$email
;
$session
->
store
();
...
...
@@ -304,7 +296,7 @@ sub casLogin {
## Also return the cookie value
return
SOAP::
Data
->
name
('
result
')
->
type
('
string
')
->
value
(
Sympa::WWW::Session::
encrypt_session_id
(
$ENV
{
'
SESSION_ID
'})
);
->
value
(
$ENV
{
SESSION_ID
}
);
}
## Used to call a service as an authenticated user without using HTTP cookies
...
...
@@ -330,7 +322,7 @@ sub authenticateAndRun {
## Provided email is not trusted, we fetch the user email from the
## session_table instead
my
$session
=
Sympa::WWW::
Session
->
new
(
$ENV
{'
SYMPA_ROBOT
'},
{
'
cookie
'
=>
$cookie
});
Sympa::WWW::
Session
->
new
(
$ENV
{'
SYMPA_ROBOT
'},
{
cookie
=>
$cookie
});
if
(
defined
$session
)
{
$email
=
$session
->
{'
email
'};
$session_id
=
$session
->
{'
id_session
'};
...
...
src/lib/Sympa/WWW/Session.pm
View file @
66680ad4
...
...
@@ -116,125 +116,77 @@ sub new {
}
sub
load
{
$log
->
syslog
('
debug2
',
'
(%s, %s)
',
@
_
);
my
$self
=
shift
;
my
$cookie
=
shift
;
$log
->
syslog
('
debug
',
'
(%s)
',
$cookie
);
unless
(
$cookie
)
{
$log
->
syslog
('
err
',
'
Internal error. Undefined id_session
');
return
undef
;
}
my
$sth
;
my
$statement
;
my
$id_session
;
my
$is_old_session
=
0
;
my
$sdm
=
Sympa::
DatabaseManager
->
instance
;
my
$sth
;
## Load existing session.
if
(
$cookie
and
$cookie
!~
/[^0-9]/
and
length
$cookie
<=
16
)
{
## Compatibility: session by older releases of Sympa.
$id_session
=
$cookie
;
$is_old_session
=
1
;
## Session by older releases of Sympa doesn't have refresh_date.
unless
(
$sdm
and
$sth
=
$sdm
->
do_prepared_query
(
q{SELECT id_session AS id_session, id_session AS prev_id,
date_session AS "date",
remote_addr_session AS remote_addr,
email_session AS email,
data_session AS data, hit_session AS hit,
start_date_session AS start_date,
date_session AS refresh_date
FROM session_table
WHERE id_session = ? AND
refresh_date_session IS NULL}
,
$id_session
)
)
{
$log
->
syslog
('
err
',
'
Unable to load session %s
',
$id_session
);
return
undef
;
}
}
else
{
$id_session
=
decrypt_session_id
(
$cookie
);
unless
(
$id_session
)
{
$log
->
syslog
('
err
',
'
Internal error. Undefined id_session
');
return
undef
;
}
## Cookie may contain current or previous session ID.
unless
(
$sdm
and
$sth
=
$sdm
->
do_prepared_query
(
q{SELECT id_session AS id_session, prev_id_session AS prev_id,
date_session AS "date",
remote_addr_session AS remote_addr,
email_session AS email,
data_session AS data, hit_session AS hit,
start_date_session AS start_date,
refresh_date_session AS refresh_date
FROM session_table
WHERE id_session = ? AND prev_id_session IS NOT NULL OR
prev_id_session = ?}
,
$id_session
,
$id_session
)
)
{
$log
->
syslog
('
err
',
'
Unable to load session %s
',
$id_session
);
return
undef
;
}
my
$session_id
=
_cookie2id
(
$cookie
);
unless
(
$session_id
)
{
$log
->
syslog
('
info
',
'
Undefined session ID in cookie "%s"
',
$cookie
);
return
undef
;
}
my
$session
=
undef
;
my
$new_session
=
undef
;
my
$counter
=
0
;
while
(
$new_session
=
$sth
->
fetchrow_hashref
('
NAME_lc
'))
{
if
(
$counter
>
0
)
{
$log
->
syslog
('
err
',
'
The SQL statement did return more than one session
');
$session
->
{'
email
'}
=
'';
last
;
}
$session
=
$new_session
;
$counter
++
;
## Cookie may contain current or previous session ID.
unless
(
$sdm
and
$sth
=
$sdm
->
do_prepared_query
(
q{SELECT id_session AS id_session, prev_id_session AS prev_id,
date_session AS "date",
remote_addr_session AS remote_addr,
email_session AS email,
data_session AS data, hit_session AS hit,
start_date_session AS start_date,
refresh_date_session AS refresh_date
FROM session_table
WHERE id_session = ? AND prev_id_session IS NOT NULL OR
prev_id_session = ?}
,
$session_id
,
$session_id
)
)
{
$log
->
syslog
('
err
',
'
Unable to load session %s
',
$session_id
);
return
undef
;
}
unless
(
$session
)
{
return
'
not_found
';
my
$session
=
$sth
->
fetchrow_hashref
('
NAME_lc
');
return
'
not_found
'
unless
$session
;
if
(
$sth
->
fetchrow_hashref
('
NAME_lc
'))
{
$log
->
syslog
('
err
',
'
The SQL statement did return more than one session
');
$session
->
{'
email
'}
=
'';
#FIXME
}
$sth
->
finish
;
## Compatibility: Upgrade session by older releases of Sympa.
if
(
$is_old_session
)
{
$sdm
->
do_prepared_query
(
q{UPDATE session_table
SET prev_id_session = id_session
WHERE id_session = ? AND prev_id_session IS NULL AND
refresh_date_session IS NULL}
,
$id_session
);
}
my
@keys
;
my
%datas
=
Sympa::Tools::Data::
string_2_hash
(
$session
->
{'
data
'});
@keys
=
keys
%datas
;
@
{
$self
}{
@keys
}
=
@datas
{
@keys
};
# Canonicalize lang if possible.
$self
->
{
lang
}
=
Sympa::Language::
canonic_lang
(
$self
->
{
lang
})
||
$self
->
{
lang
}
if
$self
->
{
lang
};
@keys
=
qw(id_session prev_id date refresh_date start_date hit
remote_addr email)
;
@
{
$self
}{
@keys
}
=
@
{
$session
}{
@keys
};
# Update hit count.
$self
->
{
hit
}
++
;
## canonicalize lang if possible.
$datas
{'
lang
'}
=
Sympa::Language::
canonic_lang
(
$datas
{'
lang
'})
||
$datas
{'
lang
'}
if
$datas
{'
lang
'};
foreach
my
$key
(
keys
%datas
)
{
$self
->
{
$key
}
=
$datas
{
$key
};
}
return
$self
;
}
$self
->
{'
id_session
'}
=
$session
->
{'
id_session
'};
$self
->
{'
prev_id
'}
=
$session
->
{'
prev_id
'};
$self
->
{'
date
'}
=
$session
->
{'
date
'};
$self
->
{'
refresh_date
'}
=
$session
->
{'
refresh_date
'};
$self
->
{'
start_date
'}
=
$session
->
{'
start_date
'};
$self
->
{'
hit
'}
=
$session
->
{'
hit
'}
+
1
;
$self
->
{'
remote_addr
'}
=
$session
->
{'
remote_addr
'};
$self
->
{'
email
'}
=
$session
->
{'
email
'};
# Get correct session ID from sympa_session cookie value.
sub
_cookie2id
{
my
$cookie
=
shift
;
return
(
$self
);
return
undef
unless
$cookie
;
return
$
1
if
$cookie
=~
/\A5e55([0-9]{14,16})\z/
;
# Compat. < 6.2.42
return
$cookie
if
$cookie
=~
/\A[0-9]{14,16}\z/
;
return
undef
;
}
## This method will both store the session information in the database
...
...
@@ -560,15 +512,13 @@ sub set_cookie {
$expiration
=
'
+
'
.
$expires
.
'
m
';
}
my
$value
=
encrypt_session_id
(
$self
->
{'
id_session
'});
my
$cookie
=
CGI::
Cookie
->
new
(
-
name
=>
'
sympa_session
',
-
domain
=>
((
$dom
eq
'
localhost
')
?
''
:
$dom
),
-
path
=>
'
/
',
-
secure
=>
$use_ssl
,
-
httponly
=>
1
,
-
value
=>
$
value
,
-
value
=>
$
self
->
{
id_session
}
,
(
$expiration
?
(
-
expires
=>
$expiration
)
:
()),
);
...
...
@@ -580,11 +530,6 @@ sub set_cookie {
sub
soap_cookie2
{
my
(
$session_id
,
$http_domain
,
$expire
)
=
@_
;
my
$cookie
;
my
$value
;
# WARNING : to check the cookie the SOAP services does not gives
# all the cookie, only it's value so we need ':'
$value
=
encrypt_session_id
(
$session_id
);
## With set-cookie2 max-age of 0 means removing the cookie
## Maximum cookie lifetime is the session
...
...
@@ -593,14 +538,14 @@ sub soap_cookie2 {
if
(
$http_domain
eq
'
localhost
')
{
$cookie
=
CGI::
Cookie
->
new
(
-
name
=>
'
sympa_session
',
-
value
=>
$
value
,
-
value
=>
$
session_id
,
-
path
=>
'
/
',
);
$cookie
->
max_age
(
time
+
$expire
);
# needs CGI >= 3.51.
}
else
{
$cookie
=
CGI::
Cookie
->
new
(
-
name
=>
'
sympa_session
',
-
value
=>
$
value
,
-
value
=>
$
session_id
,
-
domain
=>
$http_domain
,
-
path
=>
'
/
',
);
...
...
@@ -637,29 +582,12 @@ sub is_anonymous {
}
## Generate cookie from session ID.
sub
encrypt_session_id
{
my
$id_session
=
shift
;
my
$cipher
=
Sympa::Tools::Password::
ciphersaber_installed
();
unless
(
$cipher
)
{
return
"
5e55
$id_session
";
}
return
unpack
'
H*
',
$cipher
->
encrypt
(
pack
'
H*
',
$id_session
);
}
# No longer used.
#sub encrypt_session_id;
## Get session ID from cookie.
sub
decrypt_session_id
{
my
$cookie
=
shift
;
return
undef
unless
$cookie
and
$cookie
=~
/\A(?:[0-9a-f]{2})+\z/
;
my
$cipher
=
Sympa::Tools::Password::
ciphersaber_installed
();
unless
(
$cipher
)
{
return
undef
unless
$cookie
=~
s/\A5e55//
;
return
$cookie
;
}
return
unpack
'
H*
',
$cipher
->
decrypt
(
pack
'
H*
',
$cookie
);
}
# No longer used
#sub decrypt_session_id;
## Generic subroutine to set a cookie
# DEPRECATED: No longer used. Use CGI::Cookie::new().
...
...
@@ -944,12 +872,12 @@ Deprecated.
=item decrypt_session_id ( )
I<Function>.
TBD
.
Deprecated
.
=item encrypt_session_id ( )
I<Function>.
TBD
.
Deprecated
.
=item list_sessions ( )
...
...
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