Project

General

Profile

Download (6.63 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php-cgi -f
2
<?php
3
/*
4
 * sshd
5
 *
6
 * part of pfSense (https://www.pfsense.org)
7
 * Copyright (c) 2004 Fred Mol <fredmol@xs4all.nl>.
8
 * Copyright (c) 2004-2013 BSD Perimeter
9
 * Copyright (c) 2013-2016 Electric Sheep Fencing
10
 * Copyright (c) 2014-2022 Rubicon Communications, LLC (Netgate)
11
 * All rights reserved.
12
 *
13
 * 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
 *
17
 * http://www.apache.org/licenses/LICENSE-2.0
18
 *
19
 * 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
 */
25

    
26
require_once("globals.inc");
27
require_once("config.inc");
28
require_once("functions.inc");
29
require_once("shaper.inc");
30

    
31
global $config, $ssh_keys, $sshConfigDir;
32

    
33
if (!isset($config['system']['ssh']['enable'])) {
34
	return;
35
}
36

    
37
$keyfiles = array();
38
foreach ($ssh_keys as $key) {
39
	$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
if (is_array($config['system']['ssh']) && !empty($config['system']['ssh']['port'])) {
65
	$sshport = $config['system']['ssh']['port'];
66
} 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
foreach ($ssh_keys as $key) {
79
	$sshconf .= "HostKey {$sshConfigDir}/ssh_host_{$key['suffix']}key\n";
80
}
81
$sshconf .= "Compression delayed\n";
82
$sshconf .= "ClientAliveInterval 30\n";
83
if (is_account_disabled("admin") || is_account_expired("admin")) {
84
	$permitroot = 'no';
85
} else {
86
	$permitroot = 'yes';
87
}
88
$sshconf .= "PermitRootLogin {$permitroot}\n";
89
if ($config['system']['ssh']['sshdkeyonly'] == "both") {
90
	$sshconf .= "# Login via both Key and Password only\n";
91
	$sshconf .= "AuthenticationMethods publickey,password\n";
92
	$sshconf .= "ChallengeResponseAuthentication yes\n";
93
	$sshconf .= "PasswordAuthentication yes\n";
94
	$sshconf .= "PubkeyAuthentication yes\n";
95
	$sshconf .= "UsePAM yes\n";
96
} else if (isset($config['system']['ssh']['sshdkeyonly'])) {
97
	$sshconf .= "# Login via Key only\n";
98
	$sshconf .= "ChallengeResponseAuthentication no\n";
99
	$sshconf .= "PasswordAuthentication no\n";
100
	$sshconf .= "PubkeyAuthentication yes\n";
101
	$sshconf .= "UsePAM no\n";
102
} else {
103
	$sshconf .= "# Login via Key or Password\n";
104
	$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
if (isset($config['system']['ssh']['sshdagentforwarding'])) {
113
	$sshconf .= "AllowAgentForwarding yes\n";
114
} else {
115
	$sshconf .= "AllowAgentForwarding no\n";
116
}
117
$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
$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
$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
if ($config['ssh']['dsa_key'] <> "") {
136
	unset($config['ssh']['dsa_key']);
137
	unset($config['ssh']['ecdsa_key']);
138
	unset($config['ssh']['ed25519_key']);
139
	unset($config['ssh']['rsa_key']);
140
	unset($config['ssh']['rsa1_key']);
141
	unset($config['ssh']['dsa']);
142
	unset($config['ssh']['rsa']);
143
	unset($config['ssh']['rsa1']);
144
	unset($config['ssh']['ak']);
145
	write_config("Clearing SSH keys from config.xml");
146
}
147

    
148
/* are we already running?  if so exit */
149
if (is_subsystem_dirty('sshdkeys') && is_process_running("ssh-keygen")) {
150
	unset($keyfiles);
151
	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
foreach ($ssh_keys as $key) {
157
	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
	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
	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
	file_notice("SSH", "{$g['product_label']} has completed creating your SSH keys.  SSH is now started.", "SSH Startup", "");
173
}
174

    
175
/* kill existing sshd process, server only, not the children */
176
$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
unset($keyfiles);
191
?>
(84-84/85)