diff --git a/acl/lang/en b/acl/lang/en
index a0194c54a..a983c7e24 100644
--- a/acl/lang/en
+++ b/acl/lang/en
@@ -230,6 +230,8 @@ log_pass=Changed password restrictions
log_unix=Changed unix user authentication
log_sync=Changed unix user synchronization
log_sql=Changed user and group database
+log_twofactor=Enrolled user $1 with two-factor provider $2
+log_onefactor=Dis-enrolled user $1 for two-factor authentication
gedit_ecannot=You are not allowed to edit groups
gedit_title=Edit Webmin Group
@@ -461,5 +463,8 @@ twofactor_already=Your Webmin login already has two-factor authentication enable
twofactor_desc=This page allows you to enable two-factor authentication for your Webmin login using $1. Once active, an additional authentication token will be required when logging into Webmin.
twofactor_enable=Enroll For Two-Factor Authentication
twofactor_header=Two-factor authentication enrollment details
+twofactor_enrolling=Enrolling for two-factor authentication with provider $1 ..
+twofactor_failed=.. enrollment failed : $1
+twofactor_done=.. complete. Your ID with this provider is $1.
__norefs=1
diff --git a/acl/log_parser.pl b/acl/log_parser.pl
index ae2870e81..c34d335b8 100755
--- a/acl/log_parser.pl
+++ b/acl/log_parser.pl
@@ -51,6 +51,9 @@ elsif ($action eq 'cert') {
elsif ($action eq 'switch') {
return &text('log_switch', "".&html_escape($object)."");
}
+elsif ($action eq 'twofactor') {
+ return &text('log_twofactor', $object, $p->{'provider'}, $p->{'id'});
+ }
else {
return $text{'log_'.$action};
}
diff --git a/acl/save_twofactor.cgi b/acl/save_twofactor.cgi
new file mode 100644
index 000000000..c8ddefe10
--- /dev/null
+++ b/acl/save_twofactor.cgi
@@ -0,0 +1,57 @@
+#!/usr/local/bin/perl
+# Activate or de-activate twofactor
+
+require './acl-lib.pl';
+&foreign_require("webmin");
+&error_setup($text{'twofactor_err'});
+&get_miniserv_config(\%miniserv);
+&ReadParse();
+
+# Get the user
+($user) = grep { $_->{'name'} eq $base_remote_user } &list_users();
+$user || &error($twxt{'twofactor_euser'});
+
+if ($in{'enable'}) {
+ # Validate enrollment inputs
+ $vfunc = "webmin::parse_twofactor_form_".$miniserv{'twofactor_provider'};
+ $details = &$vfunc(\%in, $user);
+ &error($details) if (!ref($details));
+
+ &ui_print_header(undef, $text{'twofactor_title'}, "");
+ ($prov) = grep { $_->[0] eq $miniserv{'twofactor_provider'} }
+ &webmin::list_twofactor_providers();
+
+ # Register user
+ print &text('twofactor_enrolling', $prov->[1]),"
\n";
+ $efunc = "webmin::enroll_twofactor_".$miniserv{'twofactor_provider'};
+ $err = &$efunc($details, $user);
+ if ($err) {
+ # Failed!
+ print &text('twofactor_failed', $err),"
\n"; + } + else { + print &text('twofactor_done', $user->{'twofactor_id'}),"
\n"; + + # Save user + $user->{'twofactor_provider'} = $miniserv{'twofactor_provider'}; + &modify_user($user->{'name'}, $user); + &reload_miniserv(); + &webmin_log("twofactor", "user", $user->{'name'}, + { 'provider' => $user->{'twofactor_provider'}, + 'id' => $user->{'twofactor_id'} }); + } + + &ui_print_footer("", $text{'index_return'}); + } +elsif ($in{'disable'}) { + # Turn off for this user + $user->{'twofactor_provider'} = undef; + $user->{'twofactor_id'} = undef; + &modify_user($user->{'name'}, $user); + &reload_miniserv(); + &webmin_log("onefactor", "user", $user->{'name'}); + &redirect(""); + } +else { + &error($text{'twofactor_ebutton'}); + } diff --git a/webmin/change_twofactor.cgi b/webmin/change_twofactor.cgi index 55af8df45..2e1115937 100644 --- a/webmin/change_twofactor.cgi +++ b/webmin/change_twofactor.cgi @@ -22,6 +22,7 @@ if ($in{'twofactor_provider'}) { &get_miniserv_config(\%miniserv); $miniserv{'twofactor_provider'} = $in{'twofactor_provider'}; $miniserv{'twofactor_apikey'} = $in{'twofactor_apikey'}; +$miniserv{'twofactor_test'} = $in{'twofactor_test'}; &put_miniserv_config(\%miniserv); &unlock_file($ENV{'MINISERV_CONFIG'}); diff --git a/webmin/edit_twofactor.cgi b/webmin/edit_twofactor.cgi index 27f605bd5..bbe0ffd6f 100644 --- a/webmin/edit_twofactor.cgi +++ b/webmin/edit_twofactor.cgi @@ -21,6 +21,10 @@ print ui_table_row($text{'twofactor_provider'}, print ui_table_row($text{'twofactor_apikey'}, ui_textbox("twofactor_apikey", $miniserv{'twofactor_apikey'}, 40)); +# Test mode? +print ui_table_row($text{'twofactor_test'}, + ui_yesno_radio("twofactor_test", $miniserv{'twofactor_test'})); + print ui_table_end(); print ui_form_end([ [ "save", $text{'save'} ] ]); diff --git a/webmin/lang/en b/webmin/lang/en index 9544cb2b9..8381749b6 100644 --- a/webmin/lang/en +++ b/webmin/lang/en @@ -1026,6 +1026,7 @@ twofactor_header=Two-factor authentication sessions twofactor_provider=Authentication provider twofactor_none=None twofactor_apikey=Provider API key +twofactor_test=Use provider's test mode? twofactor_desc=Two-factor authentication allows Webmin users to enable use of an additional authentication device when logging in, such as a one-time passcode generator. Users must individually enroll with the selected authentication provider after it is enabled on this page. twofactor_err=Failed to save two-factor authentication twofactor_eprovider=Invalid provider! diff --git a/webmin/webmin-lib.pl b/webmin/webmin-lib.pl index d15cccba7..dfd1a6f45 100755 --- a/webmin/webmin-lib.pl +++ b/webmin/webmin-lib.pl @@ -2188,8 +2188,8 @@ return $rv; } # parse_twofactor_form_authy(&in, &user) -# Parses inputs from show_twofactor_form_authy, and returns a hash ref with enrollment -# details on success, or an error message on failure. +# Parses inputs from show_twofactor_form_authy, and returns a hash ref with +# enrollment details on success, or an error message on failure. sub parse_twofactor_form_authy { my ($in, $user) = @_; @@ -2203,11 +2203,26 @@ return { 'email' => $in->{'email'}, } # enroll_twofactor_authy(&details, &user) -# Attempts to enroll a user for Authy two-factor. Returns undef on success and sets -# twofactor_id in &user, or an error message on failure. +# Attempts to enroll a user for Authy two-factor. Returns undef on success and +# sets twofactor_id in &user, or an error message on failure. sub enroll_twofactor_authy { my ($details, $user) = @_; +my %miniserv; +&get_miniserv_config(\%miniserv); +my $host = $miniserv{'twofactor_test'} ? "sandbox-api.authy.com" : "api.authy.com"; +my $port = $miniserv{'twofactor_test'} ? 80 : 443; +my $page = "/protected/xml/users/new?api_key=".$miniserv{'twofactor_apikey'}; +my $ssl = $miniserv{'twofactor_test'} ? 0 : 1; +my $content = "user[email]=".&urlize($details->{'email'})."&". + "user[country_code]=".&urlize($details->{'country'})."&". + "user[cellphone]=".&urlize($details->{'phone'}); +my ($out, $err); +&http_post($host, $port, $page, $content, \$out, \$err, undef, $ssl, undef, + undef, 60, 0, 1); +return $err if ($err); +print STDERR $out; +return undef; } 1;