Passed
Push — master ( fbfab0...faf6fc )
by
unknown
13:17
created

AuthenticationService::sendEmail()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 15
rs 9.8666
cc 3
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace TYPO3\CMS\Install\Authentication;
19
20
use Psr\Http\Message\ServerRequestInterface;
21
use Symfony\Component\Mailer\Exception\TransportException;
22
use Symfony\Component\Mime\Address;
23
use Symfony\Component\Mime\Exception\RfcComplianceException;
24
use Symfony\Component\Mime\RawMessage;
25
use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
26
use TYPO3\CMS\Core\Log\LogManager;
27
use TYPO3\CMS\Core\Mail\FluidEmail;
28
use TYPO3\CMS\Core\Mail\Mailer;
29
use TYPO3\CMS\Core\Utility\GeneralUtility;
30
use TYPO3\CMS\Core\Utility\MailUtility;
31
use TYPO3\CMS\Fluid\View\TemplatePaths;
32
use TYPO3\CMS\Install\Service\SessionService;
33
34
/**
35
 * Authenticates a user (currently comparing it through the install tool password, but could be extended)
36
 * @internal only to be used within EXT:install
37
 */
38
class AuthenticationService
39
{
40
    /**
41
     * @var SessionService
42
     */
43
    protected $sessionService;
44
45
    /**
46
     * @var TemplatePaths
47
     */
48
    protected $templatePaths;
49
50
    /**
51
     * @param SessionService $sessionService
52
     */
53
    public function __construct(SessionService $sessionService)
54
    {
55
        $this->sessionService = $sessionService;
56
        $templateConfiguration = $GLOBALS['TYPO3_CONF_VARS']['MAIL'];
57
        $templateConfiguration['templateRootPaths'][20] = 'EXT:install/Resources/Private/Templates/Email/';
58
        $this->templatePaths = new TemplatePaths($templateConfiguration);
59
    }
60
61
    /**
62
     * Checks against a given password
63
     *
64
     * @param string|null $password
65
     * @param ServerRequestInterface $request
66
     * @return bool if authentication was successful, otherwise false
67
     */
68
    public function loginWithPassword($password, ServerRequestInterface $request): bool
69
    {
70
        $validPassword = false;
71
        if ($password !== null && $password !== '') {
72
            $installToolPassword = $GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'];
73
            $hashFactory = GeneralUtility::makeInstance(PasswordHashFactory::class);
74
            // Throws an InvalidPasswordHashException if no hash mechanism for the stored password is found
75
            $hashInstance = $hashFactory->get($installToolPassword, 'BE');
76
            // @todo: This code should check required hash updates and update the hash if needed
77
            $validPassword = $hashInstance->checkPassword($password, $installToolPassword);
78
        }
79
        if ($validPassword) {
80
            $this->sessionService->setAuthorized();
81
            $this->sendLoginSuccessfulMail($request);
82
            return true;
83
        }
84
        $this->sendLoginFailedMail($request);
85
        return false;
86
    }
87
88
    /**
89
     * If install tool login mail is set, send a mail for a successful login.
90
     *
91
     * @param ServerRequestInterface $request
92
     */
93
    protected function sendLoginSuccessfulMail(ServerRequestInterface $request)
94
    {
95
        $warningEmailAddress = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
96
        if (!$warningEmailAddress) {
97
            return;
98
        }
99
        $email = GeneralUtility::makeInstance(FluidEmail::class, $this->templatePaths);
100
        $email
101
            ->to($warningEmailAddress)
102
            ->subject('Install Tool Login at \'' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '\'')
103
            ->from(new Address($this->getSenderEmailAddress(), $this->getSenderEmailName()))
104
            ->setTemplate('Security/InstallToolLogin')
105
            ->setRequest($request);
106
        $this->sendEmail($email);
107
    }
108
109
    /**
110
     * If install tool login mail is set, send a mail for a failed login.
111
     *
112
     * @param ServerRequestInterface $request
113
     */
114
    protected function sendLoginFailedMail(ServerRequestInterface $request)
115
    {
116
        $warningEmailAddress = $GLOBALS['TYPO3_CONF_VARS']['BE']['warning_email_addr'];
117
        if (!$warningEmailAddress) {
118
            return;
119
        }
120
        $formValues = GeneralUtility::_GP('install');
121
        $email = GeneralUtility::makeInstance(FluidEmail::class, $this->templatePaths);
122
        $email
123
            ->to($warningEmailAddress)
124
            ->subject('Install Tool Login ATTEMPT at \'' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '\'')
125
            ->from(new Address($this->getSenderEmailAddress(), $this->getSenderEmailName()))
126
            ->setTemplate('Security/InstallToolLoginAttempt')
127
            ->assign('lastCharactersOfPassword', substr(md5($formValues['password']), -5))
128
            ->setRequest($request);
129
        $this->sendEmail($email);
130
    }
131
132
    /**
133
     * Sends an email and gracefully logs if the mail could not be sent due to configuration errors.
134
     *
135
     * @param RawMessage $email
136
     * @throws \Symfony\Component\Mailer\Exception\TransportExceptionInterface
137
     */
138
    protected function sendEmail(RawMessage $email): void
139
    {
140
        try {
141
            GeneralUtility::makeInstance(Mailer::class)->send($email);
142
        } catch (TransportException $e) {
143
            $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
144
            $logger->warning('Could not send notification email to ' . $this->getSenderEmailAddress() . ' due to mailer settings error', [
145
                'recipientList' => $this->getSenderEmailAddress(),
146
                'exception' => $e
147
            ]);
148
        } catch (RfcComplianceException $e) {
149
            $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
150
            $logger->warning('Could not send notification email to ' . $this->getSenderEmailAddress() . ' due to invalid email address', [
151
                'recipientList' => $this->getSenderEmailAddress(),
152
                'exception' => $e
153
            ]);
154
        }
155
    }
156
157
    /**
158
     * Get sender address from configuration
159
     * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']
160
     * If this setting is empty fall back to '[email protected]'
161
     *
162
     * @return string Returns an email address
163
     */
164
    protected function getSenderEmailAddress()
165
    {
166
        return MailUtility::getSystemFromAddress();
167
    }
168
169
    /**
170
     * Gets sender name from configuration
171
     * ['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']
172
     * If this setting is empty, it falls back to a default string.
173
     *
174
     * @return string
175
     */
176
    protected function getSenderEmailName()
177
    {
178
        return MailUtility::getSystemFromName() ?: 'TYPO3 CMS install tool';
179
    }
180
}
181