1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9package Kernel::Output::HTML::Preferences::Password;
10
11use strict;
12use warnings;
13
14use Kernel::Language qw(Translatable);
15
16our $ObjectManagerDisabled = 1;
17
18sub new {
19    my ( $Type, %Param ) = @_;
20
21    # allocate new hash for object
22    my $Self = {%Param};
23    bless( $Self, $Type );
24
25    for my $Needed (qw(UserID UserObject ConfigItem)) {
26        die "Got no $Needed!" if !$Self->{$Needed};
27    }
28
29    return $Self;
30}
31
32sub Param {
33    my ( $Self, %Param ) = @_;
34
35    # check if we need to show password change option
36
37    # define AuthModule for frontend
38    my $AuthModule = $Self->{ConfigItem}->{Area} eq 'Agent'
39        ? 'AuthModule'
40        : 'Customer::AuthModule';
41
42    # get config object
43    my $ConfigObject = $Kernel::OM->Get('Kernel::Config');
44
45    # get auth module
46    my $Module      = $ConfigObject->Get($AuthModule);
47    my $AuthBackend = $Param{UserData}->{UserAuthBackend};
48    if ($AuthBackend) {
49        $Module = $ConfigObject->Get( $AuthModule . $AuthBackend );
50    }
51
52    # return on no pw reset backends
53    return if $Module =~ /(LDAP|HTTPBasicAuth|Radius)/i;
54
55    my @Params;
56    push(
57        @Params,
58        {
59            %Param,
60            Key          => Translatable('Current password'),
61            Name         => 'CurPw',
62            Raw          => 1,
63            Block        => 'Password',
64            Autocomplete => 'current-password',
65        },
66        {
67            %Param,
68            Key          => Translatable('New password'),
69            Name         => 'NewPw',
70            Raw          => 1,
71            Block        => 'Password',
72            Autocomplete => 'new-password',
73        },
74        {
75            %Param,
76            Key          => Translatable('Verify password'),
77            Name         => 'NewPw1',
78            Raw          => 1,
79            Block        => 'Password',
80            Autocomplete => 'current-password',
81        },
82    );
83
84    # set the TwoFactorModue setting name depending on the interface
85    my $AuthTwoFactorModule = $Self->{ConfigItem}->{Area} eq 'Agent'
86        ? 'AuthTwoFactorModule'
87        : 'Customer::AuthTwoFactorModule';
88
89    # show 2 factor password input if we have at least one backend enabled
90    COUNT:
91    for my $Count ( '', 1 .. 10 ) {
92        next COUNT if !$ConfigObject->Get( $AuthTwoFactorModule . $Count );
93
94        push @Params, {
95            %Param,
96            Key   => '2 Factor Token',
97            Name  => 'TwoFactorToken',
98            Raw   => 1,
99            Block => 'Input',
100        };
101
102        last COUNT;
103    }
104
105    return @Params;
106}
107
108sub Run {
109    my ( $Self, %Param ) = @_;
110
111    my $ConfigObject   = $Kernel::OM->Get('Kernel::Config');
112    my $LanguageObject = $Kernel::OM->Get('Kernel::Language');
113
114    # pref update db
115    return 1 if $ConfigObject->Get('DemoSystem');
116
117    # get password from form
118    my $CurPw;
119    if ( $Param{GetParam}->{CurPw} && $Param{GetParam}->{CurPw}->[0] ) {
120        $CurPw = $Param{GetParam}->{CurPw}->[0];
121    }
122    my $Pw;
123    if ( $Param{GetParam}->{NewPw} && $Param{GetParam}->{NewPw}->[0] ) {
124        $Pw = $Param{GetParam}->{NewPw}->[0];
125    }
126    my $Pw1;
127    if ( $Param{GetParam}->{NewPw1} && $Param{GetParam}->{NewPw1}->[0] ) {
128        $Pw1 = $Param{GetParam}->{NewPw1}->[0];
129    }
130
131    # get the two factor token from form
132    my $TwoFactorToken;
133    if ( $Param{GetParam}->{TwoFactorToken} && $Param{GetParam}->{TwoFactorToken}->[0] ) {
134        $TwoFactorToken = $Param{GetParam}->{TwoFactorToken}->[0];
135    }
136
137    # define AuthModule for frontend
138    my $AuthModule = $Self->{ConfigItem}->{Area} eq 'Agent'
139        ? 'Auth'
140        : 'CustomerAuth';
141
142    my $AuthObject = $Kernel::OM->Get( 'Kernel::System::' . $AuthModule );
143    return 1 if !$AuthObject;
144
145    # validate current password
146    if (
147        !$AuthObject->Auth(
148            User           => $Param{UserData}->{UserLogin},
149            Pw             => $CurPw,
150            TwoFactorToken => $TwoFactorToken || '',
151        )
152        )
153    {
154        $Self->{Error} = $LanguageObject->Translate('The current password is not correct. Please try again!');
155        return;
156    }
157
158    # check if pw is true
159    if ( !$Pw || !$Pw1 ) {
160        $Self->{Error} = $LanguageObject->Translate('Please supply your new password!');
161        return;
162    }
163
164    # compare pws
165    if ( $Pw ne $Pw1 ) {
166        $Self->{Error}
167            = $LanguageObject->Translate('Can\'t update password, your new passwords do not match. Please try again!');
168        return;
169    }
170
171    # check pw
172    my $Config = $Self->{ConfigItem};
173
174    # check if password is not matching PasswordRegExp
175    if ( $Config->{PasswordRegExp} && $Pw !~ /$Config->{PasswordRegExp}/ ) {
176        $Self->{Error} = $LanguageObject->Translate(
177            'This password is forbidden by the current system configuration. Please contact the administrator if you have additional questions.'
178        );
179        return;
180    }
181
182    # check min size of password
183    if ( $Config->{PasswordMinSize} && length $Pw < $Config->{PasswordMinSize} ) {
184        $Self->{Error} = $LanguageObject->Translate(
185            'Can\'t update password, it must be at least %s characters long!',
186            $Config->{PasswordMinSize}
187        );
188        return;
189    }
190
191    # check min 2 lower and 2 upper char
192    if (
193        $Config->{PasswordMin2Lower2UpperCharacters}
194        && ( $Pw !~ /[A-Z].*[A-Z]/ || $Pw !~ /[a-z].*[a-z]/ )
195        )
196    {
197        $Self->{Error} = $LanguageObject->Translate(
198            'Can\'t update password, it must contain at least 2 lowercase and 2 uppercase letter characters!'
199        );
200        return;
201    }
202
203    # check min 1 digit password
204    if ( $Config->{PasswordNeedDigit} && $Pw !~ /\d/ ) {
205        $Self->{Error} = $LanguageObject->Translate('Can\'t update password, it must contain at least 1 digit!');
206        return;
207    }
208
209    # check min 2 char password
210    if ( $Config->{PasswordMin2Characters} && $Pw !~ /[A-z][A-z]/ ) {
211        $Self->{Error}
212            = $LanguageObject->Translate('Can\'t update password, it must contain at least 2 letter characters!');
213        return;
214    }
215
216    # set new password
217    my $Success = $Self->{UserObject}->SetPassword(
218        UserLogin => $Param{UserData}->{UserLogin},
219        PW        => $Pw,
220    );
221    return if !$Success;
222
223    $Self->{Message} = $LanguageObject->Translate('Preferences updated successfully!');
224    return 1;
225}
226
227sub Error {
228    my ( $Self, %Param ) = @_;
229
230    return $Self->{Error} || '';
231}
232
233sub Message {
234    my ( $Self, %Param ) = @_;
235
236    return $Self->{Message} || '';
237}
238
2391;
240