# Selima Website Content Management System # Passwd.pm: The subroutines to manipulate passwords that are temporarily stored between password forms. # Copyright (c) 2004-2018 imacat. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Author: imacat # First written: 2004-09-26 package Selima::Passwd; use 5.008; use strict; use warnings; use base qw(Exporter); use vars qw(@EXPORT @EXPORT_OK); BEGIN { @EXPORT = qw(sync_saved_passwd); @EXPORT_OK = @EXPORT; # Prototype declaration sub sync_saved_passwd($$); sub suspend($); sub ret($); sub prev_valid($$); } use Selima::DataVars qw($SESSION); use Selima::Encrypt; use Selima::NewSN; # This use symmetric encryption/decryption. It is not safe. # Nothing is exported. Use it by the full package name # sync_saved_passwd: Set the passwords with the password registry sub sync_saved_passwd($$) { local ($_, %_); my ($FORM, $dummy); ($FORM, $dummy) = @_; # Do not process again return if defined $FORM->param("_sync_saved_passwd"); # The passwd field if (defined $FORM->param("passwd")) { # Empty password is provided. Restore to the old password. if ($FORM->param("passwd") eq "") { $FORM->delete("passid"); # A new password is provided } elsif ($FORM->param("passwd") ne $dummy) { $FORM->param("passid", suspend $FORM->param("passwd")); # A previous valid password exists } elsif (prev_valid "passid", $FORM) { $FORM->param("passwd", ret $FORM->param("passid")); # Invalid previous password. Restore to the old password. } else { $FORM->delete("passid"); $FORM->param("passwd", ""); } } # The passwd2 field if (defined $FORM->param("passwd2")) { # Empty password is provided. Restore to the old password. if ($FORM->param("passwd2") eq "") { $FORM->delete("passid2"); # A new password is provided } elsif ($FORM->param("passwd2") ne $dummy) { $FORM->param("passid2", suspend $FORM->param("passwd2")); # A previous valid password exists } elsif (prev_valid "passid2", $FORM) { $FORM->param("passwd2", ret $FORM->param("passid2")); # Invalid previous password. Restore to the old password. } else { $FORM->delete("passid2"); $FORM->param("passwd2", ""); } } $FORM->param("_sync_saved_passwd", 1); return; } # suspend: Suspend a password sub suspend($) { local ($_, %_); my ($password, $passid); $password = $_[0]; # Initialize the password registry $$SESSION{"savepass"} = {} if !defined $$SESSION{"savepass"}; # Generate a new random password ID $passid = newsn_hash %{$$SESSION{"savepass"}}; ${$$SESSION{"savepass"}}{$passid} = encrypt $password; $SESSION->flush; return $passid; } # ret: Retrieve a password sub ret($) { local ($_, %_); my $passid; $passid = $_[0]; return decrypt ${$$SESSION{"savepass"}}{$passid}; } # prev_valid: If there is a previously-saved password sub prev_valid($$) { my ($col, $FORM); ($col, $FORM) = @_; # Password ID does not exist return 0 if !defined $FORM->param($col); # Password registry not initialized yet return 0 if !defined $$SESSION{"savepass"}; # Password does not exists in the registry return 0 if !exists ${$$SESSION{"savepass"}}{$FORM->param($col)}; return 1; } return 1;