Commit 62d29359 authored by sympa-authors's avatar sympa-authors
Browse files

[John-Paul Robinson] New feature: When using generic_sso, Sympa is now able to...

[John-Paul Robinson] New feature: When using generic_sso, Sympa is now able to verify the user's email address when it is provided by the SSO. If no email is provided, the user is asked.


git-svn-id: https://subversion.renater.fr/sympa/trunk@3586 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent 210a9a6a
From: [% conf.sympa %]
Reply-to: [% conf.request %]
To: [% newuser.email %]
Subject: [% FILTER qencode %][%|loc(conf.title)%]%1 / your environment[%END%][%END%]
[%|loc%]To complete your account setup actions you need to confirm that you have
supplied a working email address. Please enter the following email and password
in the setup wizard to complete your account configuration.[%END%]
[%|loc(newuser.email)%]your email address : %1[%END%]
[%|loc(newuser.password)%]your password : %1[%END%]
[% conf.title %]: [% base_url %][% path_cgi %]
[%|loc(base_url,path_cgi)%]Help on Sympa: %1%2[%END%]/help
......@@ -670,8 +670,11 @@ sub _load_auth {
'ldap_email_attribute' => '\w+',
'ldap_use_ssl' => '1',
'ldap_ssl_version' => 'sslv2/3|sslv2|sslv3|tlsv1',
'ldap_ssl_ciphers' => '[\w:]+'
}
'ldap_ssl_ciphers' => '[\w:]+',
'force_email_verify' => '1',
'internal_email_by_netid' => '1',
'netid_http_header' => '\w+',
'id_to_email_map' => 'idp_xref' }
);
......
......@@ -131,7 +131,7 @@ sub PopLang {
sub SetLang {
###########
my $locale = shift;
&do_log('debug', 'Language::SetLang(%s)', $locale);
&do_log('debug2', 'Language::SetLang(%s)', $locale);
my $lang = $locale;
......
......@@ -10246,6 +10246,81 @@ sub get_which_db {
return \%which;
}
## get idp xref to locally validated email address
sub get_netidtoemail_db {
my $robot = shift;
my $netid = shift;
my $idpname = shift;
do_log('debug', 'List::get_netidtoemail_db(%s, %s)', $netid, $idpname);
unless ($List::use_db) {
&do_log('err', 'Sympa not setup to use DBI');
return undef;
}
my ($l, %which, $statement, $email);
## Check database connection
unless ($dbh and $dbh->ping) {
return undef unless &db_connect();
}
$statement = sprintf "SELECT email_netidmap FROM netidmap_table WHERE netid_netidmap = %s and serviceid_netidmap = %s and robot_netidmap = %s", $dbh->quote($netid), $dbh->quote($idpname), $dbh->quote($robot);
push @sth_stack, $sth;
unless ($sth = $dbh->prepare($statement)) {
do_log('err','Unable to prepare SQL statement : %s', $dbh->errstr);
return undef;
}
unless ($sth->execute) {
do_log('err','Unable to execute SQL statement "%s" : %s', $statement, $dbh->errstr);
return undef;
}
$email = $sth->fetchrow;
$sth->finish();
$sth = pop @sth_stack;
return $email;
}
## set idp xref to locally validated email address
sub set_netidtoemail_db {
my $robot = shift;
my $netid = shift;
my $idpname = shift;
my $email = shift;
do_log('debug', 'List::set_netidtoemail_db(%s, %s, %s)', $netid, $idpname, $email);
unless ($List::use_db) {
&do_log('info', 'Sympa not setup to use DBI');
return undef;
}
my ($l, %which, $statement);
## Check database connection
unless ($dbh and $dbh->ping) {
return undef unless &db_connect();
}
$statement = sprintf "INSERT INTO netidmap_table (netid_netidmap,serviceid_netidmap,email_netidmap,robot_netidmap) VALUES (%s, %s, %s, %s)", $dbh->quote($netid), $dbh->quote($idpname), $dbh->quote($email), $dbh->quote($robot);
push @sth_stack, $sth;
unless ($dbh->do($statement)) {
do_log('err','Unable to execute SQL statement "%s" : %s', $statement, $dbh->errstr);
return undef;
}
return 1;
}
## List of lists where $1 (an email) is $3 (owner, editor or subscriber)
sub get_which {
my $email = shift;
......@@ -10508,7 +10583,11 @@ sub probe_db {
'included_admin' => "int(1)",
'include_sources_admin' => 'varchar(50)',
'info_admin' => 'varchar(150)',
'profile_admin' => "enum('privileged','normal')"}
'profile_admin' => "enum('privileged','normal')"},
'netidmap_table' => {'netid_netidmap' => 'varchar(100)',
'serviceid_netidmap' => 'varchar(100)',
'email_netidmap' => 'varchar(100)',
'robot_netidmap' => 'varchar(80)'},
},
'SQLite' => {'user_table' => {'email_user' => 'varchar(100)',
'gecos_user' => 'varchar(150)',
......@@ -10543,7 +10622,11 @@ sub probe_db {
'included_admin' => "boolean",
'include_sources_admin' => 'varchar(50)',
'info_admin' => 'varchar(150)',
'profile_admin' => "varchar(15)"}
'profile_admin' => "varchar(15)"},
'netidmap_table' => {'netid_netidmap' => 'varchar(100)',
'serviceid_netidmap' => 'varchar(100)',
'email_netidmap' => 'varchar(100)',
'robot_netidmap' => 'varchar(80)'},
},
);
......@@ -10556,7 +10639,17 @@ sub probe_db {
'robot_admin' => 1,
'user_admin' => 1,
'role_admin' => 1,
'date_admin' => 1);
'date_admin' => 1,
'netid_netidmap' => 1,
'serviceid_netidmap' => 1,
'robot_netidmap' => 1
);
my %primary = ('user_table' => ['email_user'],
'subscriber_table' => ['list_subscriber','robot_subscriber','user_subscriber'],
'admin_table' => ['list_admin','robot_admin','user_admin','role_admin'],
'netidmap_table' => ['netid_netidmap','serviceid_netidmap','robot_netidmap']
);
## Is the Database defined
unless ($Conf{'db_name'}) {
......@@ -10734,6 +10827,8 @@ sub probe_db {
return undef;
}
my %added_fields;
foreach my $f (sort keys %{$db_struct{$Conf{'db_type'}}{$t}}) {
unless ($real_struct{$t}{$f}) {
&do_log('info', 'Field \'%s\' (table \'%s\' ; database \'%s\') was NOT found. Attempting to add it...', $f, $t, $Conf{'db_name'});
......@@ -10750,41 +10845,9 @@ sub probe_db {
return undef;
}
if ($f eq 'email_user') {
&do_log('info', 'Setting %s field as PRIMARY', $f);
unless ($dbh->do("ALTER TABLE $t ADD PRIMARY KEY ($f)")) {
&do_log('err', 'Could not set field \'%s\' as PRIMARY KEY, table \'%s\'.', $f, $t);
return undef;
}
}
## We should DROP existing indexes
if ($f eq 'user_subscriber') {
&do_log('info', 'Setting list_subscriber,user_subscriber fields as PRIMARY');
unless ($dbh->do("ALTER TABLE $t ADD PRIMARY KEY (list_subscriber,user_subscriber,robot_subscriber)")) {
&do_log('err', 'Could not set field \'list_subscriber,user_subscriber,robot_subscriber\' as PRIMARY KEY, table\'%s\'.', $t);
return undef;
}
unless ($dbh->do("ALTER TABLE $t ADD INDEX (user_subscriber,list_subscriber,robot_subscriber)")) {
&do_log('err', 'Could not set INDEX on field \'user_subscriber,list_subscriber,robot_subscriber\', table\'%s\'.', $t);
return undef;
}
}
if ($f eq 'user_admin') {
&do_log('info', 'Setting list_admin,user_admin,robot_admin,role_admin fields as PRIMARY');
unless ($dbh->do("ALTER TABLE $t ADD PRIMARY KEY (list_admin,user_admin,robot_admin,role_admin)")) {
&do_log('err', 'Could not set field \'list_admin,user_admin,robot_admin,role_admin\' as PRIMARY KEY, table\'%s\'.', $t);
return undef;
}
unless ($dbh->do("ALTER TABLE $t ADD INDEX (user_admin,list_admin,robot_admin,role_admin)")) {
&do_log('err', 'Could not set INDEX on field \'user_admin,list_admin,robot_admin,role_admin\', table\'%s\'.', $t);
return undef;
}
}
&do_log('info', 'Field %s added to table %s', $f, $t);
$added_fields{$f} = 1;
## Remove temporary DB field
if ($real_struct{$t}{'temporary'}) {
unless ($dbh->do("ALTER TABLE $t DROP temporary")) {
......@@ -10824,6 +10887,37 @@ sub probe_db {
}
}
}
## Create required INDEX and PRIMARY KEY
my $should_update;
foreach my $field (@{$primary{$t}}) {
if ($added_fields{$field}) {
$should_update = 1;
last;
}
}
if ($should_update) {
my $fields = join ',',@{$primary{$t}};
## Add primary key
unless ($dbh->do("ALTER TABLE $t ADD PRIMARY KEY ($fields)")) {
&do_log('err', 'Could not set field \'%s\' as PRIMARY KEY, table\'%s\'.', $fields, $t);
return undef;
}
&do_log('info', 'Table %s, PRIMARY KEY set on %s', $t, $fields);
## We should DROP existing indexes
## Add INDEX
unless ($dbh->do("ALTER TABLE $t ADD INDEX ($fields)")) {
&do_log('err', 'Could not set INDEX on field \'%s\', table\'%s\'.', $fields, $t);
return undef;
}
&do_log('info', 'Table %s, INDEX set on %s', $t, $fields);
}
}
## Try to run the create_db.XX script
......
......@@ -56,7 +56,15 @@ CREATE TABLE admin_table (
include_sources_admin varchar2(50),
info_admin varchar2(150),
profile_admin varchar2(20),
CONSTRAINT ind_admin PRIMARY KEY (list_admin,user_admin,robot_admin,role_admin),
CONSTRAINT ind_admin PRIMARY KEY (list_admin,user_admin,robot_admin,role_admin)
);
CREATE TABLE netidmap_table (
netid_netidmap varchar (100) NOT NULL,
idp_netidmap varchar (100) NOT NULL,
robot_netidmap varchar (80) NOT NULL,
email_netidmap varchar (100),
CONSTRAINT ind_netidmap PRIMARY KEY (netid_netidmap, idp_netidmap, robot_netidmap)
);
!
......@@ -56,3 +56,12 @@ CREATE TABLE admin_table (
);
CREATE INDEX admin_idx ON admin_table(list_admin, user_admin,robot_admin, role_admin);
DROP TABLE netidmap_table;
CREATE TABLE netidmap_table (
netid_netidmap varchar (100) NOT NULL,
idp_netidmap varchar (100) NOT NULL,
robot_netidmap varchar (80) NOT NULL,
email_netidmap varchar (100),
CONSTRAINT ind_netidmap PRIMARY KEY (netid_netidmap, idp_netidmap, robot_netidmap)
);
CREATE INDEX netidmap_idx ON netidmap_table(netid_netidmap, idp_netidmap, robot_netidmap);
......@@ -46,3 +46,12 @@ CREATE TABLE admin_table (
PRIMARY KEY (list_admin, user_admin, robot_admin, role_admin)
);
CREATE INDEX admin_idx ON admin_table(list_admin, user_admin, robot_admin, role_admin);
CREATE TABLE netidmap_table (
netid_netidmap varchar (100) NOT NULL,
idp_netidmap varchar (100) NOT NULL,
robot_netidmap varchar (80) NOT NULL,
email_netidmap varchar (100),
PRIMARY KEY (netid_netidmap, idp_netidmap, robot_netidmap)
);
CREATE INDEX netidmap_idx ON netidmap_table(netid_netidmap, idp_netidmap, robot_netidmap);
......@@ -83,5 +83,22 @@ go
create index role_admin_fk on admin_table (role_admin)
go
create table netidmap_table
(
netid_netidmap varchar (100) NOT NULL,
idp_netidmap varchar (100) NOT NULL,
robot_netidmap varchar (80) NOT NULL,
email_netidmap varchar (100),
constraint ind_netidmap primary key (netid_netidmap, idp_netidmap, robot_netidmap)
)
go
create index netid_netidmap_fk on admin_table (netid_netidmap)
go
create index serviceid_netidmap_fk on admin_table (serviceid_netidmap)
go
create index robot_netidmap_fk on admin_table (robot_netidmap)
go
......@@ -53,7 +53,13 @@ CREATE TABLE admin_table (
INDEX (list_admin, user_admin,robot_admin,role_admin)
);
CREATE TABLE netidmap_table (
netid_netidmap varchar (100) NOT NULL,
idp_netidmap varchar (100) NOT NULL,
robot_netidmap varchar (80) NOT NULL,
email_netidmap varchar (100),
PRIMARY KEY (netid_netidmap, idp_netidmap, robot_netidmap)
);
# CREATE TABLE log_table (
# id INT UNSIGNED DEFAULT 0 NOT NULL auto_increment,
......
......@@ -17,6 +17,8 @@
[% ELSIF i_err.msg == 'cannot_unzip' %][%|loc(name)%]Cannot unzip file '%1'.[%END%]
[% ELSIF i_err.msg == 'auth_msg_failed' %][%|loc(i_err.key)%]Unable to access the message authenticated with key %1[%END%]
[% ELSIF i_err.msg == 'err_404' %][%|loc(i_err.key)%]File not found.[%END%]
[% ELSIF i_err.msg == 'db_update_failed' %][%|loc(i_err.key)%]Failed to update database.[%END%]
[% ELSIF i_err.msg == 'file_update_failed' %][%|loc(i_err.key)%]Failed to update a file.[%END%]
[% END %]
<br />
......
......@@ -39,7 +39,7 @@
<input type="hidden" name="referer" value="[% referer %]" />
<input type="hidden" name="list" value="[% list %]" />
<input type="hidden" name="action" value="sso_login" />
[% IF sso_number == '1' %]
[% IF sso_number == 1 %]
<strong><div class="menuInactive2">[%|loc%]Magic authentification[%END%]</div></strong>
[% FOREACH server = sso %]
<input type="hidden" name="auth_service_name" value="[% server.key %]" />
......
......@@ -29,7 +29,7 @@ If it is not listed or if you don't have any, login using your email and passwor
[% IF use_sso %]
[% IF sso_number == '1' %]
[% IF sso_number == 1 %]
<P>
<form action="[% path_cgi %]" method="post">
<input type="hidden" name="previous_action" value="[% previous_action %]" />
......
[% IF subaction == 'requestemail' %]
[%|loc%]Participation in the virtual organizations hosted on this site requires a working email address. Please provide your email address below. <p><i>Please note:</i> the email field may be pre-populated. If it is, then your Identity Provider has supplied an email address it associates with you. Wether you enter an address manually or accept the one provided, you will still need to confirm that this is a working email address by entering a confirmation password that will be sent to you. Please press the "Send me a confirmation password" to continue to the confirmation step.[%END%]<br /><p>
[%|loc%]A confirmation password will be sent to the address you supply, after pressing the button. This will take you to the next screen to confirm that your address is operational.[%END%]
<form action="[% path_cgi %]" method="post">
<input type="hidden" name="previous_action" value="[% previous_action %]" />
<input type="hidden" name="previous_list" value="[% previous_list %]" />
<input type="hidden" name="referer" value="[% referer %]" />
<input type="hidden" name="subaction" value="validateemail" />
<input type="hidden" name="action" value="sso_login" />
<input type="hidden" name="nomenu" value="[% nomenu %]" />
<input type="hidden" name="auth_service_name" value="[% server.key %]" />
<label><strong>[%|loc%]Your e-mail address:</strong> :<br />
[% IF init_email %]
[% email %]
<input type="text" name="email" value="[% init_email %]" />
[% ELSE %]
<input type="text" name="email" value="" />
[% END %]
[% END %]
</label>&nbsp; &nbsp; &nbsp;<input type="submit" name="action_sso_login" value="[%|loc%]Send me a confirmation password[%END%]"/>
</form>
[% ELSIF subaction == 'validateemail' %]
<br />
[%|loc(init_email)%]A confirmation password has been sent to your email address %1.<br />Please check your e-mail box to provide the confirmation password below.[%END%]
<br /><br />
<table border="1" style="width: 100%;" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">
<table border="0" style="width: 100%;" cellspacing="0" cellpadding="0">
<tr><td>
<form action="[% path_cgi %]" method="post">
<input type="hidden" name="previous_action" value="[% previous_action %]" />
<input type="hidden" name="previous_list" value="[% previous_list %]" />
<input type="hidden" name="referer" value="[% referer %]" />
<input type="hidden" name="auth_service_name" value="[% server.key %]" />
<input type="hidden" name="subaction" value="confirmemail" />
<input type="hidden" name="action" value="sso_login" />
<input type="hidden" name="nomenu" value="[% nomenu %]" />
<table border="0" style="width: 100%;" cellspacing="0" cellpadding="0">
<tr style="background-color: [% light_color %];">
<td style="white-space: nowrap; text-align: center;">
<input type="hidden" name="list" value="[% list %]" />
<label><strong><span style="font-size: smaller; color: [% selected_color %];">[%|loc%]email address[%END%] :</span></strong><input type="text" name="email" size="30" value="[% init_email %]" /></label>
<label><strong><span style="font-size: smaller; color: [% selected_color %];">[%|loc%]password[%END%] :</span></strong><input type="password" name="passwd" size="8" /></label>
&nbsp;&nbsp;
<input type="submit" name="action_sso_login" value="[%|loc%]Validate Address[%END%]" />
</td>
</tr>
</table>
</form>
</table>
</td>
</tr>
</table>
[% END %]
......@@ -336,9 +336,20 @@ sub get_email_by_net_id {
my $robot = shift;
my $auth_id = shift;
my $attributes = shift;
do_log ('info',"Auth::get_email_by_net_id($auth_id,$attributes->{'uid'})");
do_log ('debug',"Auth::get_email_by_net_id($auth_id,$attributes->{'uid'})");
if (defined $Conf{'auth_services'}{$robot}[$auth_id]{'internal_email_by_netid'}) {
my $sso_config = @{$Conf{'auth_services'}{$robot}}[$auth_id];
my $netid_cookie = $sso_config->{'netid_http_header'} ;
$netid_cookie =~ s/(\w+)/$attributes->{$1}/ig;
$email = &List::get_netidtoemail_db($robot, $netid_cookie, $Conf{'auth_services'}{$robot}[$auth_id]{'service_id'});
return $email;
}
unless (eval "require Net::LDAP") {
do_log ('err',"Unable to use LDAP library, Net::LDAP required, install perl-ldap (CPAN) first");
return undef;
......
......@@ -278,7 +278,7 @@ my %action_args = ('default' => ['list'],
'latest_lists' => ['topic','subtopic'],
'active_lists' => ['topic','subtopic'],
'login' => ['email','passwd','previous_action','previous_list'],
'sso_login' => ['auth_service_name','previous_action','previous_list'],
'sso_login' => ['auth_service_name','subaction','previous_action','previous_list', 'email', 'passwd'],
'sso_login_succeeded' => ['auth_service_name','previous_action','previous_list'],
'loginrequest' => ['previous_action','previous_list'],
'logout' => ['previous_action','previous_list'],
......@@ -1212,7 +1212,7 @@ sub get_header_field {
if ($ENV{'REQUEST_METHOD'} eq 'GET') {
my $path_info = $ENV{'PATH_INFO'};
&do_log('debug2', "PATH_INFO: %s",$ENV{'PATH_INFO'});
&do_log('debug', "PATH_INFO: %s",$ENV{'PATH_INFO'});
$path_info =~ s+^/++;
......@@ -1289,6 +1289,7 @@ sub get_header_field {
$in{'action'} = $in{'javascript_action'};
}
foreach my $p (keys %in) {
do_log('debug2',"POST key $p value $in{$p}");
if ($p =~ /^action_(\w+)((\.\w+)*)$/) {
$in{'action'} = $1;
......@@ -1941,12 +1942,25 @@ sub do_sso_login {
## If contacted via POST, then redirect the user to the URL for the access control to apply
if ($ENV{'REQUEST_METHOD'} eq 'POST') {
my $path = '';
my $service;
if ($param->{'nomenu'}) {
$path = "/nomenu";
}
$path .= "/sso_login_succeeded/$in{'auth_service_name'}";
&wwslog('info', 'do_sso_login(): POST request processing');
if ($in{'subaction'} eq 'validateemail') {
$path .= "/validateemail/sso_login_succeeded/$in{'auth_service_name'}/$in{'email'}";
}elsif ($in{'subaction'} eq 'confirmemail') {
$path .= "/$in{'subaction'}/sso_login_succeeded/$in{'auth_service_name'}/$in{'email'}/$in{'passwd'}";
}else {
$path .= "/init/sso_login_succeeded/$in{'auth_service_name'}";
}
my $service = "$param->{'base_url'}$param->{'path_cgi'}/sso_login/$in{'auth_service_name'}".$path;
&wwslog('info', 'do_sso_login: redirect user to %s', $service);
......@@ -1959,17 +1973,139 @@ sub do_sso_login {
}
my $email;
if (defined $Conf{'auth_services'}{$robot}[$sso_id]{'email_http_header'}) {
$email = lc($ENV{$Conf{'auth_services'}{$robot}[$sso_id]{'email_http_header'}});
}else {
unless (defined $Conf{'auth_services'}{$robot}[$sso_id]{'ldap_host'} &&
defined $Conf{'auth_services'}{$robot}[$sso_id]{'ldap_get_email_by_uid_filter'}) {
##
if (defined $Conf{'auth_services'}{$robot}[$sso_id]{'force_email_verify'}) {
my $emailvalid;
## the subactions order is : init, requestemail, validateemail, sendssopasswd, confirmemail
## get email from NetiD table
if (defined $Conf{'auth_services'}{$robot}[$sso_id]{'internal_email_by_netid'}) {
&wwslog('debug', 'do_sso_login(): lookup email internal: %s', $sso_id);
$email = &Auth::get_email_by_net_id($robot, $sso_id, \%ENV);
if ($email) {
$emailvalid = 1;
}else {
$emailvalid = 0;
}
}
## get email from authN module
if (defined $Conf{'auth_services'}{$robot}[$sso_id]{'email_http_header'} && ! $emailvalid) {
$email = lc($ENV{$Conf{'auth_services'}{$robot}[$sso_id]{'email_http_header'}});
$emailvalid = 0;
}
## No email at all, ask for one
if (! $emailvalid and $in{'subaction'} eq 'init') {
&wwslog('info', 'do_sso_login(): return request email');
$param->{'auth'} = 'generic_sso';
$param->{'server'}{'key'} = $in{'auth_service_name'};
$param->{'subaction'} = 'requestemail';
$param->{'init_email'} = $email;
return 1;
}
if (defined($in{'email'}) and !($in{'subaction'} eq 'init')) {
$email = $in{'email'};
}
## Send a confirmation email and request it on the web interface
if ($in{'subaction'} eq 'validateemail') {
$param->{'auth'} = 'generic_sso';
$param->{'server'}{'key'} = $in{'auth_service_name'};
$param->{'init_email'} = $email;
unless (&sendssopasswd($email)) {
&report::reject_report_web('user','incorrect_email',{'email' => $email},$param->{'action'});
$param->{'subaction'} = 'requestemail';
return 1;
}
$param->{'subaction'} = 'validateemail';
return 1;
}
if ($in{'subaction'} eq 'confirmemail') {
$param->{'auth'} = 'generic_sso';
$param->{'server'}{'key'} = $in{'auth_service_name'};
$param->{'init_email'} = $email;
$in{'email'} = $email;
#
# Check input parameters and verify passwd for email, stolen from do_login
#
unless ($in{'email'}) {
&report::reject_report_web('user','no_email',{},$param->{'action'});
&wwslog('info','do_sso_login: confirmemail: no email');
# &List::db_log('wwsympa','nobody',$param->{'auth_method'},$ip,'login','',$robot,'','no email');
$param->{'subaction'} = 'validateemail';
return 1;
}
unless ($in{'passwd'}) {
$in{'init_email'} = $in{'email'};
$param->{'init_email'} = $in{'email'};
$param->{'escaped_init_email'} = &tools::escape_chars($in{'email'});
&report::reject_report_web('user','missing_arg',{'argument' => 'passwd'},$param->{'action'});
&wwslog('info','do_sso_login: confirmemail: missing parameter passwd');
$param->{'subaction'} = 'validateemail';
return 1;
}
##authentication of the sender
my $data;
unless($data = &Auth::check_auth($robot, $in{'email'},$in{'passwd'})){
&report::reject_report_web('user','auth_failed',{},$param->{'action'});
# &List::db_log('wwsympa',$in{'email'},'null',$ip,'login','',$robot,'','failed');
&wwslog('err', "Authentication failed\n");
$param->{'subaction'} = 'validateemail';
return 1;
}
&wwslog('info', 'do_sso_login: confirmemail: email validation succeeded');
# need to create netid to email map entry
$email = $in{'email'};
# everything is ok to proceed to with possible sympa account created and traddional sso login