Project

General

Profile

Download (6.02 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-2016 Rubicon Communications, LLC (Netgate)
9
 * All rights reserved.
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 * http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23

    
24
require_once("globals.inc");
25
require_once("config.inc");
26
require_once("functions.inc");
27
require_once("shaper.inc");
28

    
29
if (!isset($config['system']['enablesshd'])) {
30
	return;
31
}
32

    
33
$sshConfigDir = "/etc/ssh";
34

    
35
$keys = array(
36
	array('type' => 'rsa',     'suffix' => 'rsa_'),
37
	array('type' => 'ed25519', 'suffix' => 'ed25519_')
38
);
39

    
40
$keyfiles = array();
41
foreach ($keys as $key) {
42
	$keyfiles[] = "ssh_host_{$key['suffix']}key";
43
	$keyfiles[] = "ssh_host_{$key['suffix']}key.pub";
44
}
45

    
46
/*    if any of these files are 0 bytes then they are corrupted.
47
 *    remove them
48
 */
49
foreach ($keyfiles as $f2c) {
50
	if (!file_exists("{$sshConfigDir}/{$f2c}") || filesize("{$sshConfigDir}/{$f2c}") == 0) {
51
		/* Make sure we remove both files */
52
		unlink_if_exists($sshConfigDir . '/' . basename($f2c, ".pub"));
53
		unlink_if_exists($sshConfigDir . '/' . $f2c);
54
	}
55
}
56

    
57
if (!is_dir("/var/empty")) {
58
	/* make ssh home directory */
59
	mkdir("/var/empty", 0555);
60
}
61

    
62
if (!file_exists("/var/log/lastlog")) {
63
	/* Login related files. */
64
	@touch("/var/log/lastlog");
65
}
66

    
67
if (is_array($config['system']['ssh']) && !empty($config['system']['ssh']['port'])) {
68
	$sshport = $config['system']['ssh']['port'];
69
} else {
70
	$sshport = 22;
71
}
72

    
73
/* Include default configuration for pfSense */
74
/* Taken from https://stribika.github.io/2015/01/04/secure-secure-shell.html */
75
$sshconf = "# This file is automatically generated at startup\n";
76
$sshconf .= "KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256\n";
77
/* Run the server on another port if we have one defined */
78
$sshconf .= "Port $sshport\n";
79
/* Only allow protocol 2, because we say so */
80
$sshconf .= "Protocol 2\n";
81
foreach ($keys as $key) {
82
	$sshconf .= "HostKey {$sshConfigDir}/ssh_host_{$key['suffix']}key\n";
83
}
84
$sshconf .= "Compression yes\n";
85
$sshconf .= "ClientAliveInterval 30\n";
86
$sshconf .= "PermitRootLogin yes\n";
87
if (isset($config['system']['ssh']['sshdkeyonly'])) {
88
	$sshconf .= "# Login via Key only\n";
89
	$sshconf .= "ChallengeResponseAuthentication no\n";
90
	$sshconf .= "PasswordAuthentication no\n";
91
	$sshconf .= "PubkeyAuthentication yes\n";
92
	$sshconf .= "UsePAM no\n";
93
} else {
94
	$sshconf .= "# Login via Key and Password\n";
95
	$sshconf .= "ChallengeResponseAuthentication yes\n";
96
	$sshconf .= "PasswordAuthentication yes\n";
97
	$sshconf .= "PubkeyAuthentication yes\n";
98
}
99
$sshconf .= "UseDNS no\n";
100
$sshconf .= "LoginGraceTime 30s\n";
101
/* Hide FreeBSD version */
102
$sshconf .= "VersionAddendum none\n";
103
$sshconf .= "X11Forwarding no\n";
104
$sshconf .= "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr\n";
105
$sshconf .= "MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com\n";
106
$sshconf .= "# override default of no subsystems\n";
107
$sshconf .= "Subsystem\tsftp\t/usr/libexec/sftp-server\n";
108

    
109
/* Apply package SSHDCond settings if config file exists */
110
if (file_exists("/etc/sshd_extra")) {
111
	$fdExtra = fopen("/etc/sshd_extra", 'r');
112
	$szExtra = fread($fdExtra, 1048576); // Read up to 1MB from extra file
113
	$sshconf .= $szExtra;
114
	fclose($fdExtra);
115
}
116

    
117
/* Write the new sshd config file */
118
@file_put_contents("{$sshConfigDir}/sshd_config", $sshconf);
119

    
120
/* mop up from a badly implemented ssh keys -> cf backup */
121
if ($config['ssh']['dsa_key'] <> "") {
122
	unset($config['ssh']['dsa_key']);
123
	unset($config['ssh']['ecdsa_key']);
124
	unset($config['ssh']['ed25519_key']);
125
	unset($config['ssh']['rsa_key']);
126
	unset($config['ssh']['rsa1_key']);
127
	unset($config['ssh']['dsa']);
128
	unset($config['ssh']['rsa']);
129
	unset($config['ssh']['rsa1']);
130
	unset($config['ssh']['ak']);
131
	write_config("Clearing SSH keys from config.xml");
132
}
133

    
134
/* are we already running?  if so exit */
135
if (is_subsystem_dirty('sshdkeys')) {
136
	unset($keys, $keyfiles);
137
	return;
138
}
139

    
140
// Check for all needed key files. If any are missing, the keys need to be regenerated.
141
$generate_keys = array();
142
foreach ($keys as $key) {
143
	if (!file_exists("{$sshConfigDir}/ssh_host_{$key['suffix']}key") ||
144
	    !file_exists("{$sshConfigDir}/ssh_host_{$key['suffix']}key.pub")) {
145
		$generate_keys[] = $key;
146
	}
147
}
148

    
149
if (!empty($generate_keys)) {
150
	/* remove previous keys and regen later */
151
	file_notice("SSH", "{$g['product_name']} 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", "");
152
	mark_subsystem_dirty('sshdkeys');
153
	echo " Generating Keys:\n";
154
	foreach ($generate_keys as $key) {
155
		$_gb = exec("/usr/bin/nice -n20 /usr/bin/ssh-keygen -t {$key['type']} -b 4096 -N '' -f {$sshConfigDir}/ssh_host_{$key['suffix']}key");
156
	}
157
	clear_subsystem_dirty('sshdkeys');
158
	file_notice("SSH", "{$g['product_name']} has completed creating your SSH keys.  SSH is now started.", "SSH Startup", "");
159
}
160

    
161
/* kill existing sshd process, server only, not the childs */
162
$sshd_pid = exec("ps ax | egrep '/usr/sbin/[s]shd' | awk '{print $1}'");
163
if ($sshd_pid <> "") {
164
	echo "stopping ssh process $sshd_pid \n";
165
	@posix_kill($sshd_pid, SIGTERM);
166
}
167
/* Launch new server process */
168
$status = mwexec("/usr/sbin/sshd");
169
if ($status <> 0) {
170
	file_notice("sshd_startup", "SSHD failed to start.", "SSHD Daemon", "");
171
	echo "error!\n";
172
} else {
173
	echo "done.\n";
174
}
175

    
176
unset($keys, $keyfiles);
177
?>
(78-78/79)