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
master
Daniel Berteaud 11 years ago
parent 7a7ee8603b
commit a5837dac98
  1. 6
      lib/Vroom/I18N/en.pm
  2. 6
      lib/Vroom/I18N/fr.pm
  3. 84
      public/js/vroom.js
  4. 36
      public/vroom.pl
  5. 22
      templates/default/join.html.ep

@ -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",

@ -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",

@ -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();

@ -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,14 +517,20 @@ 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'){
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'
}
);

@ -106,6 +106,28 @@
</div>
</div>
</li>
<li class="divider">
</li>
<li>
<div class="navbar-form">
<center>
<p><%=l 'OWNER_PASSWORD_MAKES_PERSISTENT' %></p>
</center>
<div class="input-group">
<input type="password" id="ownerPass" class="form-control help" placeholder="<%=l 'PASSWORD' %>" data-toggle="tooltip" data-placement="bottom" title="<%=l 'OWNER_PASSWORD' %>"/>
<span class="input-group-btn">
<button id="setOwnerPassButton" type="button" class="btn btn-default help disabled" data-toggle="tooltip" data-placement="bottom" title="<%=l 'OWNER_PASSWORD' %>">
<span class="glyphicon glyphicon-ok"
</span>
</button>
<button id="removeOwnerPassButton" type="button" class="btn btn-default help" data-toggle="tooltip" data-placement="bottom" title="<%=l 'REMOVE_OWNER_PASSWORD' %>">
<span class="glyphicon glyphicon-remove"
</span>
</button>
</span>
</div>
</div>
</li>
</ul>
</div>
<div class="btn-group navbar-form navbar-right" data-toggle="buttons" >

Loading…
Cancel
Save