1 |
cb7d18d5
|
Renato Botelho
|
#!/usr/local/bin/php-cgi -f
|
2 |
5b237745
|
Scott Ullrich
|
<?php
|
3 |
|
|
/*
|
4 |
ac24dc24
|
Renato Botelho
|
* sshd
|
5 |
|
|
*
|
6 |
|
|
* part of pfSense (https://www.pfsense.org)
|
7 |
c5d81585
|
Renato Botelho
|
* Copyright (c) 2004 Fred Mol <fredmol@xs4all.nl>.
|
8 |
38809d47
|
Renato Botelho do Couto
|
* Copyright (c) 2004-2013 BSD Perimeter
|
9 |
|
|
* Copyright (c) 2013-2016 Electric Sheep Fencing
|
10 |
37d60e23
|
Luiz Souza
|
* Copyright (c) 2014-2025 Rubicon Communications, LLC (Netgate)
|
11 |
ac24dc24
|
Renato Botelho
|
* All rights reserved.
|
12 |
|
|
*
|
13 |
b12ea3fb
|
Renato Botelho
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
14 |
|
|
* you may not use this file except in compliance with the License.
|
15 |
|
|
* You may obtain a copy of the License at
|
16 |
ac24dc24
|
Renato Botelho
|
*
|
17 |
b12ea3fb
|
Renato Botelho
|
* http://www.apache.org/licenses/LICENSE-2.0
|
18 |
ac24dc24
|
Renato Botelho
|
*
|
19 |
b12ea3fb
|
Renato Botelho
|
* Unless required by applicable law or agreed to in writing, software
|
20 |
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
21 |
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22 |
|
|
* See the License for the specific language governing permissions and
|
23 |
|
|
* limitations under the License.
|
24 |
ac24dc24
|
Renato Botelho
|
*/
|
25 |
|
|
|
26 |
|
|
require_once("globals.inc");
|
27 |
|
|
require_once("config.inc");
|
28 |
|
|
require_once("functions.inc");
|
29 |
|
|
require_once("shaper.inc");
|
30 |
|
|
|
31 |
63d6bb4f
|
Marcos Mendoza
|
global $ssh_keys, $sshConfigDir;
|
32 |
dc22e511
|
Viktor G
|
|
33 |
63d6bb4f
|
Marcos Mendoza
|
if (!config_path_enabled('system/ssh')) {
|
34 |
ac24dc24
|
Renato Botelho
|
return;
|
35 |
|
|
}
|
36 |
|
|
|
37 |
|
|
$keyfiles = array();
|
38 |
dc22e511
|
Viktor G
|
foreach ($ssh_keys as $key) {
|
39 |
ac24dc24
|
Renato Botelho
|
$keyfiles[] = "ssh_host_{$key['suffix']}key";
|
40 |
|
|
$keyfiles[] = "ssh_host_{$key['suffix']}key.pub";
|
41 |
|
|
}
|
42 |
|
|
|
43 |
|
|
/* if any of these files are 0 bytes then they are corrupted.
|
44 |
|
|
* remove them
|
45 |
|
|
*/
|
46 |
|
|
foreach ($keyfiles as $f2c) {
|
47 |
|
|
if (!file_exists("{$sshConfigDir}/{$f2c}") || filesize("{$sshConfigDir}/{$f2c}") == 0) {
|
48 |
|
|
/* Make sure we remove both files */
|
49 |
|
|
unlink_if_exists($sshConfigDir . '/' . basename($f2c, ".pub"));
|
50 |
|
|
unlink_if_exists($sshConfigDir . '/' . $f2c);
|
51 |
|
|
}
|
52 |
|
|
}
|
53 |
|
|
|
54 |
|
|
if (!is_dir("/var/empty")) {
|
55 |
|
|
/* make ssh home directory */
|
56 |
|
|
mkdir("/var/empty", 0555);
|
57 |
|
|
}
|
58 |
|
|
|
59 |
|
|
if (!file_exists("/var/log/lastlog")) {
|
60 |
|
|
/* Login related files. */
|
61 |
|
|
@touch("/var/log/lastlog");
|
62 |
|
|
}
|
63 |
|
|
|
64 |
63d6bb4f
|
Marcos Mendoza
|
if (!empty(config_get_path('system/ssh/port'))) {
|
65 |
|
|
$sshport = config_get_path('system/ssh/port');
|
66 |
ac24dc24
|
Renato Botelho
|
} else {
|
67 |
|
|
$sshport = 22;
|
68 |
|
|
}
|
69 |
|
|
|
70 |
|
|
/* Include default configuration for pfSense */
|
71 |
|
|
/* Taken from https://stribika.github.io/2015/01/04/secure-secure-shell.html */
|
72 |
|
|
$sshconf = "# This file is automatically generated at startup\n";
|
73 |
|
|
$sshconf .= "KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256\n";
|
74 |
|
|
/* Run the server on another port if we have one defined */
|
75 |
|
|
$sshconf .= "Port $sshport\n";
|
76 |
|
|
/* Only allow protocol 2, because we say so */
|
77 |
|
|
$sshconf .= "Protocol 2\n";
|
78 |
dc22e511
|
Viktor G
|
foreach ($ssh_keys as $key) {
|
79 |
ac24dc24
|
Renato Botelho
|
$sshconf .= "HostKey {$sshConfigDir}/ssh_host_{$key['suffix']}key\n";
|
80 |
|
|
}
|
81 |
4cad9a5b
|
jim-p
|
$sshconf .= "Compression delayed\n";
|
82 |
ac24dc24
|
Renato Botelho
|
$sshconf .= "ClientAliveInterval 30\n";
|
83 |
5d0c974d
|
jim-p
|
if (is_account_disabled("admin") || is_account_expired("admin")) {
|
84 |
|
|
$permitroot = 'no';
|
85 |
|
|
} else {
|
86 |
|
|
$permitroot = 'yes';
|
87 |
|
|
}
|
88 |
|
|
$sshconf .= "PermitRootLogin {$permitroot}\n";
|
89 |
63d6bb4f
|
Marcos Mendoza
|
if (config_get_path('system/ssh/sshdkeyonly') == "both") {
|
90 |
d6fdfd78
|
reb00tz
|
$sshconf .= "# Login via both Key and Password only\n";
|
91 |
aa9971a3
|
robjarsen
|
$sshconf .= "AuthenticationMethods publickey,password\n";
|
92 |
d6fdfd78
|
reb00tz
|
$sshconf .= "ChallengeResponseAuthentication yes\n";
|
93 |
|
|
$sshconf .= "PasswordAuthentication yes\n";
|
94 |
|
|
$sshconf .= "PubkeyAuthentication yes\n";
|
95 |
|
|
$sshconf .= "UsePAM yes\n";
|
96 |
63d6bb4f
|
Marcos Mendoza
|
} else if (config_path_enabled('system/ssh', 'sshdkeyonly')) {
|
97 |
ac24dc24
|
Renato Botelho
|
$sshconf .= "# Login via Key only\n";
|
98 |
|
|
$sshconf .= "ChallengeResponseAuthentication no\n";
|
99 |
|
|
$sshconf .= "PasswordAuthentication no\n";
|
100 |
|
|
$sshconf .= "PubkeyAuthentication yes\n";
|
101 |
b35fc433
|
jim-p
|
$sshconf .= "UsePAM no\n";
|
102 |
ac24dc24
|
Renato Botelho
|
} else {
|
103 |
d6fdfd78
|
reb00tz
|
$sshconf .= "# Login via Key or Password\n";
|
104 |
ac24dc24
|
Renato Botelho
|
$sshconf .= "ChallengeResponseAuthentication yes\n";
|
105 |
|
|
$sshconf .= "PasswordAuthentication yes\n";
|
106 |
|
|
$sshconf .= "PubkeyAuthentication yes\n";
|
107 |
|
|
}
|
108 |
|
|
$sshconf .= "UseDNS no\n";
|
109 |
|
|
$sshconf .= "LoginGraceTime 30s\n";
|
110 |
|
|
/* Hide FreeBSD version */
|
111 |
|
|
$sshconf .= "VersionAddendum none\n";
|
112 |
63d6bb4f
|
Marcos Mendoza
|
if (config_path_enabled('system/ssh', 'sshdagentforwarding')) {
|
113 |
1d835d94
|
Sorin Sbarnea
|
$sshconf .= "AllowAgentForwarding yes\n";
|
114 |
|
|
} else {
|
115 |
|
|
$sshconf .= "AllowAgentForwarding no\n";
|
116 |
|
|
}
|
117 |
ac24dc24
|
Renato Botelho
|
$sshconf .= "X11Forwarding no\n";
|
118 |
|
|
$sshconf .= "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr\n";
|
119 |
c16a2fe1
|
Renato Botelho
|
$sshconf .= "MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com\n";
|
120 |
ac24dc24
|
Renato Botelho
|
$sshconf .= "# override default of no subsystems\n";
|
121 |
|
|
$sshconf .= "Subsystem\tsftp\t/usr/libexec/sftp-server\n";
|
122 |
|
|
|
123 |
|
|
/* Apply package SSHDCond settings if config file exists */
|
124 |
|
|
if (file_exists("/etc/sshd_extra")) {
|
125 |
|
|
$fdExtra = fopen("/etc/sshd_extra", 'r');
|
126 |
|
|
$szExtra = fread($fdExtra, 1048576); // Read up to 1MB from extra file
|
127 |
|
|
$sshconf .= $szExtra;
|
128 |
|
|
fclose($fdExtra);
|
129 |
|
|
}
|
130 |
|
|
|
131 |
|
|
/* Write the new sshd config file */
|
132 |
|
|
@file_put_contents("{$sshConfigDir}/sshd_config", $sshconf);
|
133 |
|
|
|
134 |
|
|
/* mop up from a badly implemented ssh keys -> cf backup */
|
135 |
63d6bb4f
|
Marcos Mendoza
|
if (config_path_enabled('ssh', 'dsa_key')) {
|
136 |
|
|
config_del_path('ssh/dsa_key');
|
137 |
|
|
config_del_path('ssh/ecdsa_key');
|
138 |
|
|
config_del_path('ssh/ed25519_key');
|
139 |
|
|
config_del_path('ssh/rsa_key');
|
140 |
|
|
config_del_path('ssh/rsa1_key');
|
141 |
|
|
config_del_path('ssh/dsa');
|
142 |
|
|
config_del_path('ssh/rsa');
|
143 |
|
|
config_del_path('ssh/rsa1');
|
144 |
|
|
config_del_path('ssh/ak');
|
145 |
ac24dc24
|
Renato Botelho
|
write_config("Clearing SSH keys from config.xml");
|
146 |
|
|
}
|
147 |
|
|
|
148 |
|
|
/* are we already running? if so exit */
|
149 |
cf38c37a
|
Viktor G
|
if (is_subsystem_dirty('sshdkeys') && is_process_running("ssh-keygen")) {
|
150 |
dc22e511
|
Viktor G
|
unset($keyfiles);
|
151 |
ac24dc24
|
Renato Botelho
|
return;
|
152 |
|
|
}
|
153 |
|
|
|
154 |
|
|
// Check for all needed key files. If any are missing, the keys need to be regenerated.
|
155 |
|
|
$generate_keys = array();
|
156 |
dc22e511
|
Viktor G
|
foreach ($ssh_keys as $key) {
|
157 |
ac24dc24
|
Renato Botelho
|
if (!file_exists("{$sshConfigDir}/ssh_host_{$key['suffix']}key") ||
|
158 |
|
|
!file_exists("{$sshConfigDir}/ssh_host_{$key['suffix']}key.pub")) {
|
159 |
|
|
$generate_keys[] = $key;
|
160 |
|
|
}
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
if (!empty($generate_keys)) {
|
164 |
|
|
/* remove previous keys and regen later */
|
165 |
573ec19d
|
Renato Botelho do Couto
|
file_notice("SSH", "{$g['product_label']} has started creating missing SSH keys. SSH Startup will be delayed. Please note that reloading the filter rules and changes will be delayed until this operation is completed.", "SSH KeyGen", "");
|
166 |
ac24dc24
|
Renato Botelho
|
mark_subsystem_dirty('sshdkeys');
|
167 |
|
|
echo " Generating Keys:\n";
|
168 |
|
|
foreach ($generate_keys as $key) {
|
169 |
|
|
$_gb = exec("/usr/bin/nice -n20 /usr/bin/ssh-keygen -t {$key['type']} -b 4096 -N '' -f {$sshConfigDir}/ssh_host_{$key['suffix']}key");
|
170 |
|
|
}
|
171 |
|
|
clear_subsystem_dirty('sshdkeys');
|
172 |
573ec19d
|
Renato Botelho do Couto
|
file_notice("SSH", "{$g['product_label']} has completed creating your SSH keys. SSH is now started.", "SSH Startup", "");
|
173 |
ac24dc24
|
Renato Botelho
|
}
|
174 |
|
|
|
175 |
f3f98e97
|
Phil Davis
|
/* kill existing sshd process, server only, not the children */
|
176 |
ac24dc24
|
Renato Botelho
|
$sshd_pid = exec("ps ax | egrep '/usr/sbin/[s]shd' | awk '{print $1}'");
|
177 |
|
|
if ($sshd_pid <> "") {
|
178 |
|
|
echo "stopping ssh process $sshd_pid \n";
|
179 |
|
|
@posix_kill($sshd_pid, SIGTERM);
|
180 |
|
|
}
|
181 |
|
|
/* Launch new server process */
|
182 |
|
|
$status = mwexec("/usr/sbin/sshd");
|
183 |
|
|
if ($status <> 0) {
|
184 |
|
|
file_notice("sshd_startup", "SSHD failed to start.", "SSHD Daemon", "");
|
185 |
|
|
echo "error!\n";
|
186 |
|
|
} else {
|
187 |
|
|
echo "done.\n";
|
188 |
|
|
}
|
189 |
|
|
|
190 |
dc22e511
|
Viktor G
|
unset($keyfiles);
|
191 |
06e28ceb
|
Ermal Lu?i
|
?>
|