3 # Common functions for the ssh daemon config file
5 BEGIN { push(@INC, ".."); };
9 # Get version information
10 if (!&read_file("$module_config_directory/version", \%version)) {
11 %version = &get_sshd_version();
15 # Returns a hash containing the version type, number and full version
19 local $out = &backquote_command(
20 "e_path($config{'sshd_path'})." -h 2>&1 </dev/null");
21 if ($config{'sshd_version'}) {
23 $version{'type'} = 'openssh';
24 $version{'number'} = $version{'full'} = $config{'sshd_version'};
26 elsif ($out =~ /(sshd\s+version\s+([0-9\.]+))/i ||
27 $out =~ /(ssh\s+secure\s+shell\s+([0-9\.]+))/i) {
28 # Classic commercial SSH
29 $version{'type'} = 'ssh';
30 $version{'number'} = $2;
31 $version{'full'} = $1;
33 elsif ($out =~ /(OpenSSH.([0-9\.]+))/i) {
34 # OpenSSH .. assume all versions are supported
35 $version{'type'} = 'openssh';
36 $version{'number'} = $2;
37 $version{'full'} = $1;
39 elsif ($out =~ /(Sun_SSH_([0-9\.]+))/i) {
40 # Solaris 9 SSH is actually OpenSSH 2.x
41 $version{'type'} = 'openssh';
42 $version{'number'} = 2.0;
43 $version{'full'} = $1;
45 elsif (($out = $config{'sshd_version'}) && ($out =~ /(Sun_SSH_([0-9\.]+))/i)) {
46 # Probably Solaris 10 SSHD that didn't display version. Use it.
47 $version{'type'} = 'openssh';
48 $version{'number'} = 2.0;
49 $version{'full'} = $1;
55 # Returns a reference to an array of SSHD config file options
58 local @rv = ( { 'dummy' => 1,
60 'file' => $config{'sshd_config'},
64 open(CONF, $config{'sshd_config'});
68 local ($name, @values) = split(/\s+/, $_);
70 local $dir = { 'name' => $name,
72 'file' => $config{'sshd_config'},
82 # find_value(name, &config)
85 foreach $c (@{$_[1]}) {
86 if (lc($c->{'name'}) eq lc($_[0])) {
87 return wantarray ? @{$c->{'values'}} : $c->{'values'}->[0];
90 return wantarray ? ( ) : undef;
93 # find(value, &config)
97 foreach $c (@{$_[1]}) {
98 if (lc($c->{'name'}) eq lc($_[0])) {
102 return wantarray ? @rv : $rv[0];
105 # save_directive(name, &config, [value*|&values], [before])
108 local @o = &find($_[0], $_[1]);
109 local @n = ref($_[2]) ?
110 grep { defined($_) } @{$_[2]} :
111 grep { defined($_) } @_[2..@_-1];
112 local $lref = &read_file_lines($_[1]->[0]->{'file'});
113 local $id = ("\t" x $_[1]->[0]->{'indent'});
115 local $before = $_[3] && ref($_[2]) ? &find($_[3], $_[1]) : undef;
116 for($i=0; $i<@o || $i<@n; $i++) {
117 if ($o[$i] && $n[$i]) {
119 $lref->[$o[$i]->{'line'}] = "$id$_[0] $n[$i]";
123 splice(@$lref, $o[$i]->{'line'}, 1);
124 foreach $c (@{$_[1]}) {
125 if ($c->{'line'} > $o[$i]->{'line'}) {
130 elsif ($n[$i] && !$before) {
131 # Adding a line at the end, but before the last Match directive
132 local $ll = $_[1]->[@{$_[1]}-1]->{'line'};
133 foreach my $m (&find("Match", $_[1])) {
134 $ll = $m->{'line'} - 1;
136 splice(@$lref, $ll+1, 0, "$id$_[0] $n[$i]");
138 elsif ($n[$i] && $before) {
139 # Adding a line before the first instance of some directive
140 splice(@$lref, $before->{'line'}, 0, "$id$_[0] $n[$i]");
141 foreach $c (@{$_[1]}) {
142 if ($c->{'line'} >= $before->{'line'}) {
153 if ($cmd_count % 2 == 0) {
157 print "<td colspan=2></td> </tr>\n";
161 $cmd_count += ($_[0] ? 2 : 1);
167 if ($cmd_count % 2 == 0) {
172 # get_client_config()
173 # Returns a list of structures, one for each host
174 sub get_client_config
176 local @rv = ( { 'dummy' => 1,
178 'file' => $config{'client_config'},
183 open(CLIENT, $config{'client_config'});
188 local ($name, @values) = split(/\s+/, $_);
189 if (lc($name) eq 'host') {
191 $host = { 'name' => $name,
192 'values' => \@values,
193 'file' => $config{'client_config'},
196 'members' => [ { 'dummy' => 1,
198 'file' => $config{'client_config'},
199 'line' => $lnum } ] };
203 # A directive inside a host
204 local $dir = { 'name' => $name,
205 'values' => \@values,
206 'file' => $config{'client_config'},
208 push(@{$host->{'members'}}, $dir);
209 $host->{'eline'} = $lnum;
220 local $lref = &read_file_lines($config{'client_config'});
221 $_[0]->{'line'} = $_[0]->{'eline'} = scalar(@$lref);
222 push(@$lref, "Host ".join(" ", @{$_[0]->{'values'}}));
223 $_[0]->{'members'} = [ { 'dummy' => 1,
225 'file' => $config{'client_config'},
226 'line' => $_[0]->{'line'} } ];
232 local $lref = &read_file_lines($config{'client_config'});
233 $lref->[$_[0]->{'line'}] = "Host ".join(" ", @{$_[0]->{'values'}});
239 local $lref = &read_file_lines($config{'client_config'});
240 splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1);
244 # Re-starts the SSH server, and returns an error message on failure or
248 if ($config{'restart_cmd'}) {
249 local $out = `$config{'restart_cmd'} 2>&1 </dev/null`;
250 return "<pre>$out</pre>" if ($?);
253 local $pid = &get_sshd_pid();
254 $pid || return $text{'apply_epid'};
255 &kill_logged('HUP', $pid);
261 # Kills the SSH server, and returns an error message on failure or
265 if ($config{'stop_cmd'}) {
266 local $out = `$config{'stop_cmd'} 2>&1 </dev/null`;
267 return "<pre>$out</pre>" if ($?);
270 local $pid = &get_sshd_pid();
271 $pid || return $text{'apply_epid'};
272 &kill_logged('TERM', $pid);
278 # Attempts to start the SSH server, returning undef on success or an error
279 # message on failure.
282 # Remove PID file if invalid
283 if (-f $config{'pid_file'} && !&check_pid_file($config{'pid_file'})) {
284 &unlink_file($config{'pid_file'});
287 if ($config{'start_cmd'}) {
288 $out = &backquote_logged("$config{'start_cmd'} 2>&1 </dev/null");
289 if ($?) { return "<pre>$out</pre>"; }
292 $out = &backquote_logged("$config{'sshd_path'} 2>&1 </dev/null");
293 if ($?) { return "<pre>$out</pre>"; }
299 # Returns the SSH server PID file
302 local $conf = &get_sshd_config();
303 local $pidfile = &find_value("PidFile", $conf);
304 $pidfile ||= $config{'pid_file'};
309 # Returns the PID of the running SSHd process
312 local $file = &get_pid_file();
314 return &check_pid_file($file);
317 local ($rv) = &find_byname("sshd");
322 # get_mlvalues(file, id, [splitchar])
323 # Return an array with values from a file, where the
324 # values are one per line with an id preceeding them
329 local $split = defined($_[2]) ? $_[2] : " ";
330 local $realfile = &translate_filename($_[0]);
331 &open_readfile(ARFILE, $_[0]) || return 0;
334 local $hash = index($_, "#");
335 local $eq = index($_, $split);
336 if ($hash != 0 && $eq >= 0) {
337 local $n = substr($_, 0, $eq);
338 local $v = substr($_, $eq+1);
349 # list_syslog_facilities()
350 # Returns an upper-case list of syslog facility names
351 sub list_syslog_facilities
354 if (&foreign_check("syslog")) {
355 local %sconfig = &foreign_config("syslog");
356 @facils = map { uc($_) } split(/\s+/, $sconfig{'facilities'});
359 @facils = ( 'DAEMON', 'USER', 'AUTH', 'LOCAL0', 'LOCAL1', 'LOCAL2',
360 'LOCAL3', 'LOCAL4', 'LOCAL5', 'LOCAL6', 'LOCAL7' );
365 sub list_logging_levels
367 return ('QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE', 'DEBUG');
370 sub yes_no_default_radio
372 local ($name, $value) = @_;
373 return &ui_radio($name, lc($value) eq 'yes' ? 1 :
374 lc($value) eq 'no' ? 0 : 2,
375 [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ],
376 [ 2, $text{'default'} ] ]);