From a5837dac988c6c64b46088ac26366df4f4406cb8 Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Tue, 13 May 2014 19:22:47 +0200 Subject: [PATCH] Implement owner password auth Owner passwords are salt+sha256 hashed (unlike join password) as they do not need cleartext access For now, you also have to set a join password if you want to be able to auth as an owner Need to implement a password popup if there's an owner password but no join password --- lib/Vroom/I18N/en.pm | 6 ++- lib/Vroom/I18N/fr.pm | 6 ++- public/js/vroom.js | 84 ++++++++++++++++++++++++++++++++++++++++-- public/vroom.pl | 38 +++++++++++++++++-- templates/default/join.html.ep | 22 +++++++++++ 5 files changed, 145 insertions(+), 11 deletions(-) diff --git a/lib/Vroom/I18N/en.pm b/lib/Vroom/I18N/en.pm index 5d45f87..21869b2 100644 --- a/lib/Vroom/I18N/en.pm +++ b/lib/Vroom/I18N/en.pm @@ -35,6 +35,8 @@ our %Lexicon = ( "ONE_OF_THE_PEERS" => "one of the peers", "PASSWORD_PROTECT_ON_BY_s" => "%s password protected the room", "PASSWORD_PROTECT_OFF_BY_s" => "%s removed password protection", + "OWNER_PASSWORD_CHANGED_BY_s" => "%s changed the room manager password", + "OWNER_PASSWORD_REMOVED_BY_s" => "%s removed the room manager password, so this room isn't persistent anymore", "OOOPS" => "Ooops", "GOODBY" => "Goodby", "THANKS_SEE_YOU_SOON" => "Thanks and see you soon", @@ -63,8 +65,8 @@ our %Lexicon = ( "PASSWORD" => "Password", "PASSWORD_PROTECT" => "Password protect", "REMOVE_PASSWORD" => "Remove the password", - "JOIN_PASSWORD_SET" => "This room is now password protected", - "JOIN_PASSWORD_REMOVED" => "This room isn't password protected anymore", + "PASSWORD_SET" => "Password updated", + "PASSWORD_REMOVED" => "Password removed", "NOT_ALLOWED" => "You are not allowed to do this", "WRONG_PASSWORD" => "Wrong password", "PASSWORD_REQUIRED" => "Password required", diff --git a/lib/Vroom/I18N/fr.pm b/lib/Vroom/I18N/fr.pm index 7a1f9ef..877540e 100644 --- a/lib/Vroom/I18N/fr.pm +++ b/lib/Vroom/I18N/fr.pm @@ -38,6 +38,8 @@ our %Lexicon = ( "ONE_OF_THE_PEERS" => "un des participants", "PASSWORD_PROTECT_ON_BY_s" => "%s a protégé le salon par un mot de passe", "PASSWORD_PROTECT_OFF_BY_s" => "%s a supprimé la protection par mot de passe", + "OWNER_PASSWORD_CHANGED_BY_s" => "%s a modifié le mot de passe du gestionnaire du salon", + "OWNER_PASSWORD_REMOVED_BY_s" => "%s a supprimé le mot de passe du gestionnaire du salon. Ce salon n'est donc plus persistant", "OOOPS" => "Oups", "GOODBY" => "Au revoir", "THANKS_SEE_YOU_SOON" => "Merci et à bientôt", @@ -69,8 +71,8 @@ our %Lexicon = ( "PASSWORD" => "Mot de passe", "PASSWORD_PROTECT" => "Protéger par mot de passe", "REMOVE_PASSWORD" => "Supprimer le mot de passe", - "JOIN_PASSWORD_SET" => "Le salon est protégé par mot de passe", - "JOIN_PASSWORD_REMOVED" => "Le salon n'est plus protégé par mot de passe", + "PASSWORD_SET" => "Le mot de passe a été mis à jour", + "PASSWORD_REMOVED" => "Le mot de passe a été supprimé", "NOT_ALLOWED" => "Vous n'êtes pas autorisé à faire ceci", "WRONG_PASSWORD" => "Mauvais mot de passe", "PASSWORD_REQUIRED" => "Mot de passe requis", diff --git a/public/js/vroom.js b/public/js/vroom.js index ea2e8e0..96c1430 100644 --- a/public/js/vroom.js +++ b/public/js/vroom.js @@ -27,6 +27,8 @@ var locale = { ONE_OF_THE_PEERS: '', PASSWORD_PROTECT_ON_BY_s: '', PASSWORD_PROTECT_OFF_BY_s: '', + OWNER_PASSWORD_CHANGED_BY_s: '', + OWNER_PASSWORD_REMOVED_BY_s: '', CANT_SEND_TO_s: '', SCREEN_s: '', TO_INVITE_SHARE_THIS_URL: '' @@ -442,13 +444,23 @@ function initVroom(room) { $(el).remove(); }); + // A few notif on password set/unset webrtc.on('password_protect_on', function(data){ $.notify(sprintf(locale.PASSWORD_PROTECT_ON_BY_s, stringEscape(peers[data.id].displayName)), 'info'); }); - webrtc.on('password_protect_off', function(data){ $.notify(sprintf(locale.PASSWORD_PROTECT_OFF_BY_s, stringEscape(peers[data.id].displayName)), 'info'); }); + webrtc.on('owner_password_changed', function(data){ + if (peers.local.role == 'owner'){ + $.notify(sprintf(locale.OWNER_PASSWORD_CHANGED_BY_s, stringEscape(peers[data.id].displayName)), 'warn'); + } + }); + webrtc.on('owner_password_removed', function(data){ + if (peers.local.role == 'owner'){ + $.notify(sprintf(locale.OWNER_PASSWORD_REMOVED_BY_s, stringEscape(peers[data.id].displayName)), 'warn'); + } + }); // Handle the readyToCall event: join the room webrtc.once('readyToCall', function () { @@ -628,8 +640,9 @@ function initVroom(room) { $('#setJoinPassButton').addClass('disabled'); $.ajax({ data: { - action: 'setJoinPassword', + action: 'setPassword', password: pass, + type: 'join', room: roomName }, error: function() { @@ -653,7 +666,8 @@ function initVroom(room) { $('#removeJoinPassButton').click(function(event) { $.ajax({ data: { - action: 'setJoinPassword', + action: 'setPassword', + type: 'join', room: roomName }, error: function() { @@ -673,6 +687,70 @@ function initVroom(room) { }); }); + + $('#ownerPass').on('input', function() { + if ($('#ownerPass').val() == ''){ + $('#setOwnerPassButton').addClass('disabled'); + } + else{ + $('#setOwnerPassButton').removeClass('disabled'); + } + }); + + // Set owner password + $('#setOwnerPassButton').click(function(event) { + var pass = $('#ownerPass').val(); + $('#ownerPass').val(''); + $('#setOwnerPassButton').addClass('disabled'); + $.ajax({ + data: { + action: 'setPassword', + password: pass, + type: 'owner', + room: roomName + }, + error: function() { + var msg = locale.ERROR_OCCURED; + $.notify(msg, 'error'); + }, + success: function(data) { + $('#ownerPass').val(''); + if (data.status == 'success'){ + $.notify(data.msg, 'success'); + webrtc.sendToAll('owner_password_changed', {}); + } + else{ + $.notify(data.msg, 'error'); + } + } + }); + }); + + // Remove the owner password + $('#removeOwnerPassButton').click(function(event) { + $.ajax({ + data: { + action: 'setPassword', + type: 'owner', + room: roomName + }, + error: function() { + var msg = locale.ERROR_OCCURED; + $.notify(msg, 'error'); + }, + success: function(data) { + $('#ownerPass').val(''); + if (data.status == 'success'){ + $.notify(data.msg, 'success'); + webrtc.sendToAll('owner_password_removed', {}); + } + else{ + $.notify(data.msg, 'error'); + } + } + }); + }); + // Choose another color. Useful if two peers have the same $('#changeColorButton').click(function(){ peers.local.color = chooseColor(); diff --git a/public/vroom.pl b/public/vroom.pl index 3cb32d6..84233de 100755 --- a/public/vroom.pl +++ b/public/vroom.pl @@ -12,6 +12,7 @@ use Mojo::JSON; use DBI; use Data::GUID qw(guid_string); use Digest::MD5 qw(md5_hex); +use Crypt::SaltedHash; use MIME::Base64; use Email::Sender::Transport::Sendmail; use Encode; @@ -253,6 +254,25 @@ helper set_join_pass => sub { return 1; }; +# Set owner password +helper set_owner_pass => sub { + my $self = shift; + my ($room,$pass) = @_; + return undef unless ( %{ $self->get_room($room) }); + if ($pass){ + my $sth = eval { $self->db->prepare("UPDATE rooms SET owner_password=?,persistent='1' where name=?;") } || return undef; + my $csh = Crypt::SaltedHash->new(algorithm => 'SHA-256'); + $csh->add($pass); + $sth->execute($csh->generate,$room) || return undef; + $self->app->log->debug($self->session('name') . " has set an owner password on room $room, which is now persistent"); + } + else{ + my $sth = eval { $self->db->prepare("UPDATE rooms SET owner_password=?,persistent='0' where name=?;") } || return undef; + $sth->execute(undef,$room) || return undef; + $self->app->log->debug($self->session('name') . " has removed the owner password on room $room, which is not persistent anymore"); + } +}; + any '/' => 'index'; get '/about' => sub { @@ -356,7 +376,11 @@ post '/password/(:room)' => sub { ); } my $pass = $self->param('password'); - if ($pass eq $data->{join_password}){ + if ($data->{owner_password} && Crypt::SaltedHash->validate($data->{owner_password}, $pass)){ + $self->session($room => {role => 'owner'}); + $self->redirect_to($self->url_for('/') . $room); + } + elsif ($pass eq $data->{join_password}){ $self->session($room => {role => 'participant'}); $self->redirect_to($self->url_for('/') . $room); } @@ -493,13 +517,19 @@ post '/action' => sub { ); } } - elsif ($action eq 'setJoinPassword'){ + elsif ($action eq 'setPassword'){ my $pass = $self->param('password'); + my $type = $self->param('type') || 'join'; $pass = undef if ($pass && $pass eq ''); my $res = undef; my $errmsg = 'ERROR_OCCURED'; if ($self->session($room)->{role} eq 'owner'){ - $res = $self->set_join_pass($room,$pass); + if ($type eq 'owner'){ + $res = $self->set_owner_pass($room,$pass); + } + else{ + $res = $self->set_join_pass($room,$pass); + } } else{ $errmsg = 'NOT_ALLOWED'; @@ -515,7 +545,7 @@ post '/action' => sub { else{ return $self->render( json => { - msg => ($pass) ? $self->l('JOIN_PASSWORD_SET') : $self->l('JOIN_PASSWORD_REMOVED'), + msg => ($pass) ? $self->l('PASSWORD_SET') : $self->l('PASSWORD_REMOVED'), status => 'success' } ); diff --git a/templates/default/join.html.ep b/templates/default/join.html.ep index ec6783b..a80e3e6 100644 --- a/templates/default/join.html.ep +++ b/templates/default/join.html.ep @@ -106,6 +106,28 @@ +
  • +
  • +
  • + +