Passed
Push — develop ( 31ebc6...f6a1e0 )
by Nikolay
04:27
created

SSHConf::sendNotify()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 13
rs 9.9666
cc 3
nc 3
nop 2
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright © 2017-2023 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\Core\System\Configs;
21
22
23
use MikoPBX\Core\System\MikoPBXConfig;
24
use MikoPBX\Core\System\Notifications;
25
use MikoPBX\Core\System\Processes;
26
use MikoPBX\Core\System\Util;
27
use MikoPBX\Core\Workers\WorkerPrepareAdvices;
28
use Phalcon\Di\Injectable;
29
30
/**
31
 * Class SSHConf
32
 *
33
 * Represents the SSH configuration.
34
 *
35
 * @package MikoPBX\Core\System\Configs
36
 */
37
class SSHConf extends Injectable
38
{
39
    private MikoPBXConfig $mikoPBXConfig;
40
41
    /**
42
     * SSHConf constructor.
43
     */
44
    public function __construct()
45
    {
46
        $this->mikoPBXConfig = new MikoPBXConfig();
47
    }
48
49
    /**
50
     * Configures SSH settings.
51
     *
52
     * @return bool
53
     */
54
    public function configure(): bool
55
    {
56
        $lofFile = '/var/log/lastlog';
57
        if(!file_exists($lofFile)){
58
            file_put_contents($lofFile, '');
59
        }
60
        $dropBearDir = '/etc/dropbear';
61
        Util::mwMkdir($dropBearDir);
62
63
        $keytypes = [
64
            "rsa"   => "SSHRsaKey",
65
            "dss"   => "SSHDssKey",
66
            "ecdsa" => "SSHecdsaKey"
67
        ];
68
69
        $options = ($this->mikoPBXConfig->getGeneralSettings('SSHDisablePasswordLogins') === '1')?'-s':'';
70
        // Get keys from DB
71
        $dropbearkeyPath = Util::which('dropbearkey');
72
        $dropbearPath    = Util::which('dropbear');
73
        foreach ($keytypes as $keytype => $db_key) {
74
            $res_keyfilepath = "{$dropBearDir}/dropbear_" . $keytype . "_host_key";
75
            $key             = $this->mikoPBXConfig->getGeneralSettings($db_key);
76
            $key             = (isset($key) && is_string($key)) ? trim($key) : "";
77
            if (strlen($key) > 100) {
78
                // Store key to file
79
                file_put_contents($res_keyfilepath, base64_decode($key));
80
            }
81
            // If key not exists, we will generate and store new one into file and database
82
            if ( ! file_exists($res_keyfilepath)) {
83
                // Generation
84
                Processes::mwExec("{$dropbearkeyPath} -t $keytype -f $res_keyfilepath");
85
                // Storing
86
                $new_key = base64_encode(file_get_contents($res_keyfilepath));
87
                $this->mikoPBXConfig->setGeneralSettings($db_key, $new_key);
88
            }
89
        }
90
        $ssh_port = escapeshellcmd($this->mikoPBXConfig->getGeneralSettings('SSHPort'));
91
        // Set root password
92
        $this->updateShellPassword();
93
        // Restart ssh  server
94
        Processes::killByName('dropbear');
95
        usleep(500000);
96
        $result = Processes::mwExec("{$dropbearPath} -p '{$ssh_port}' $options -c /etc/rc/hello > /var/log/dropbear_start.log");
97
        $this->generateAuthorizedKeys();
98
99
        return ($result === 0);
100
    }
101
102
    /**
103
     * Stores authorized_keys from DB to files.
104
     *
105
     * @return void
106
     */
107
    public function generateAuthorizedKeys(): void
108
    {
109
        $ssh_dir = '/root/.ssh';
110
        Util::mwMkdir($ssh_dir);
111
        $conf_data = $this->mikoPBXConfig->getGeneralSettings('SSHAuthorizedKeys');
112
        file_put_contents("{$ssh_dir}/authorized_keys", $conf_data);
113
    }
114
115
    /**
116
     * Sets up the root user password.
117
     *
118
     * @return void
119
     */
120
    public function updateShellPassword(): void
121
    {
122
        $password           = $this->mikoPBXConfig->getGeneralSettings('SSHPassword');
123
        $hashString         = $this->mikoPBXConfig->getGeneralSettings('SSHPasswordHashString');
124
        $disablePassLogin   = $this->mikoPBXConfig->getGeneralSettings('SSHDisablePasswordLogins');
125
126
        $echoPath       = Util::which('echo');
127
        $chPasswdPath   = Util::which('chpasswd');
128
        $passwdPath   = Util::which('passwd');
129
        Processes::mwExec("{$passwdPath} -l www");
130
        if($disablePassLogin === '1'){
131
            Processes::mwExec("{$passwdPath} -l root");
132
        }else{
133
            Processes::mwExec("{$echoPath} 'root:$password' | {$chPasswdPath}");
134
        }
135
        $this->mikoPBXConfig->setGeneralSettings('SSHPasswordHash',       md5_file('/etc/passwd'));
136
        if($hashString !== md5($password)){
137
            $this->mikoPBXConfig->setGeneralSettings('SSHPasswordHashString', md5($password));
138
            Notifications::sendAdminNotification('adv_SSHPasswordWasChangedSubject', ['adv_SSHPasswordWasChangedBody'],true);
139
            WorkerPrepareAdvices::afterChangeSSHConf();
140
        }
141
    }
142
143
}