Files
selima-perl/lib/perl5/Selima/Passwd.pm
2026-03-10 21:31:43 +08:00

130 lines
4.0 KiB
Perl

# 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 <imacat@mail.imacat.idv.tw>
# 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;