Viewing file: sshd-lib.pl (8.51 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/perl # sshd-lib.pl # Common functions for the ssh daemon config file
BEGIN { push(@INC, ".."); }; use WebminCore; &init_config();
# Get version information if (!&read_file("$module_config_directory/version", \%version)) { %version = &get_sshd_version(); }
# get_sshd_version() # Returns a hash containing the version type, number and full version sub get_sshd_version { local %version; local $out = &backquote_command( "e_path($config{'sshd_path'})." -h 2>&1 </dev/null"); if ($config{'sshd_version'}) { # Forced version $version{'type'} = 'openssh'; $version{'number'} = $version{'full'} = $config{'sshd_version'}; } elsif ($out =~ /(sshd\s+version\s+([0-9\.]+))/i || $out =~ /(ssh\s+secure\s+shell\s+([0-9\.]+))/i) { # Classic commercial SSH $version{'type'} = 'ssh'; $version{'number'} = $2; $version{'full'} = $1; } elsif ($out =~ /(OpenSSH.([0-9\.]+))/i) { # OpenSSH .. assume all versions are supported $version{'type'} = 'openssh'; $version{'number'} = $2; $version{'full'} = $1; } elsif ($out =~ /(Sun_SSH_([0-9\.]+))/i) { # Solaris 9 SSH is actually OpenSSH 2.x $version{'type'} = 'openssh'; $version{'number'} = 2.0; $version{'full'} = $1; } elsif (($out = $config{'sshd_version'}) && ($out =~ /(Sun_SSH_([0-9\.]+))/i)) { # Probably Solaris 10 SSHD that didn't display version. Use it. $version{'type'} = 'openssh'; $version{'number'} = 2.0; $version{'full'} = $1; } return %version; }
# get_sshd_config() # Returns a reference to an array of SSHD config file options sub get_sshd_config { local @rv = ( { 'dummy' => 1, 'indent' => 0, 'file' => $config{'sshd_config'}, 'line' => -1, 'eline' => -1 } ); local $lnum = 0; open(CONF, $config{'sshd_config'}); while(<CONF>) { s/\r|\n//g; s/^\s*#.*$//g; local ($name, @values) = split(/\s+/, $_); if ($name) { local $dir = { 'name' => $name, 'values' => \@values, 'file' => $config{'sshd_config'}, 'line' => $lnum }; push(@rv, $dir); } $lnum++; } close(CONF); return \@rv; }
# find_value(name, &config) sub find_value { foreach $c (@{$_[1]}) { if (lc($c->{'name'}) eq lc($_[0])) { return wantarray ? @{$c->{'values'}} : $c->{'values'}->[0]; } } return wantarray ? ( ) : undef; }
# find(value, &config) sub find { local @rv; foreach $c (@{$_[1]}) { if (lc($c->{'name'}) eq lc($_[0])) { push(@rv, $c); } } return wantarray ? @rv : $rv[0]; }
# save_directive(name, &config, [value*|&values], [before]) sub save_directive { local @o = &find($_[0], $_[1]); local @n = ref($_[2]) ? grep { defined($_) } @{$_[2]} : grep { defined($_) } @_[2..@_-1]; local $lref = &read_file_lines($_[1]->[0]->{'file'}); local $id = ("\t" x $_[1]->[0]->{'indent'}); local $i; local $before = $_[3] && ref($_[2]) ? &find($_[3], $_[1]) : undef; for($i=0; $i<@o || $i<@n; $i++) { if ($o[$i] && $n[$i]) { # Replacing a line $lref->[$o[$i]->{'line'}] = "$id$_[0] $n[$i]"; } elsif ($o[$i]) { # Removing a line splice(@$lref, $o[$i]->{'line'}, 1); foreach $c (@{$_[1]}) { if ($c->{'line'} > $o[$i]->{'line'}) { $c->{'line'}--; } } } elsif ($n[$i] && !$before) { # Adding a line at the end, but before the first Match directive local $ll = $_[1]->[@{$_[1]}-1]->{'line'}; foreach my $m (&find("Match", $_[1])) { $ll = $m->{'line'} - 1; last; } splice(@$lref, $ll+1, 0, "$id$_[0] $n[$i]"); } elsif ($n[$i] && $before) { # Adding a line before the first instance of some directive splice(@$lref, $before->{'line'}, 0, "$id$_[0] $n[$i]"); foreach $c (@{$_[1]}) { if ($c->{'line'} >= $before->{'line'}) { $c->{'line'}--; } } } } }
# scmd(double) sub scmd { if ($cmd_count % 2 == 0) { print "<tr>\n"; } elsif ($_[0]) { print "<td colspan=2></td> </tr>\n"; print "<tr>\n"; $cmd_count = 0; } $cmd_count += ($_[0] ? 2 : 1); }
# ecmd() sub ecmd { if ($cmd_count % 2 == 0) { print "</tr>\n"; } }
# get_client_config() # Returns a list of structures, one for each host sub get_client_config { local @rv = ( { 'dummy' => 1, 'indent' => 0, 'file' => $config{'client_config'}, 'line' => -1, 'eline' => -1 } ); local $host; local $lnum = 0; open(CLIENT, $config{'client_config'}); while(<CLIENT>) { s/\r|\n//g; s/^\s*#.*$//g; s/^\s*//g; local ($name, @values) = split(/\s+/, $_); if (lc($name) eq 'host') { # Start of new host $host = { 'name' => $name, 'values' => \@values, 'file' => $config{'client_config'}, 'line' => $lnum, 'eline' => $lnum, 'members' => [ { 'dummy' => 1, 'indent' => 1, 'file' => $config{'client_config'}, 'line' => $lnum } ] }; push(@rv, $host); } elsif ($name) { # A directive inside a host local $dir = { 'name' => $name, 'values' => \@values, 'file' => $config{'client_config'}, 'line' => $lnum }; push(@{$host->{'members'}}, $dir); $host->{'eline'} = $lnum; } $lnum++; } close(CLIENT); return \@rv; }
# create_host(&host) sub create_host { local $lref = &read_file_lines($config{'client_config'}); $_[0]->{'line'} = $_[0]->{'eline'} = scalar(@$lref); push(@$lref, "Host ".join(" ", @{$_[0]->{'values'}})); $_[0]->{'members'} = [ { 'dummy' => 1, 'indent' => 1, 'file' => $config{'client_config'}, 'line' => $_[0]->{'line'} } ]; }
# modify_host(&host) sub modify_host { local $lref = &read_file_lines($config{'client_config'}); $lref->[$_[0]->{'line'}] = "Host ".join(" ", @{$_[0]->{'values'}}); }
# delete_host(&host) sub delete_host { local $lref = &read_file_lines($config{'client_config'}); splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1); }
# restart_sshd() # Re-starts the SSH server, and returns an error message on failure or # undef on success sub restart_sshd { if ($config{'restart_cmd'}) { local $out = `$config{'restart_cmd'} 2>&1 </dev/null`; return "<pre>$out</pre>" if ($?); } else { local $pid = &get_sshd_pid(); $pid || return $text{'apply_epid'}; &kill_logged('HUP', $pid); } return undef; }
# stop_sshd() # Kills the SSH server, and returns an error message on failure or # undef on success sub stop_sshd { if ($config{'stop_cmd'}) { local $out = `$config{'stop_cmd'} 2>&1 </dev/null`; return "<pre>$out</pre>" if ($?); } else { local $pid = &get_sshd_pid(); $pid || return $text{'apply_epid'}; &kill_logged('TERM', $pid); } return undef; }
# start_sshd() # Attempts to start the SSH server, returning undef on success or an error # message on failure. sub start_sshd { # Remove PID file if invalid if (-f $config{'pid_file'} && !&check_pid_file($config{'pid_file'})) { &unlink_file($config{'pid_file'}); }
if ($config{'start_cmd'}) { $out = &backquote_logged("$config{'start_cmd'} 2>&1 </dev/null"); if ($?) { return "<pre>$out</pre>"; } } else { $out = &backquote_logged("$config{'sshd_path'} 2>&1 </dev/null"); if ($?) { return "<pre>$out</pre>"; } } return undef; }
# get_pid_file() # Returns the SSH server PID file sub get_pid_file { local $conf = &get_sshd_config(); local $pidfile = &find_value("PidFile", $conf); $pidfile ||= $config{'pid_file'}; return $pidfile; }
# get_sshd_pid() # Returns the PID of the running SSHd process sub get_sshd_pid { local $file = &get_pid_file(); if ($file) { return &check_pid_file($file); } else { local ($rv) = &find_byname("sshd"); return $rv; } }
# get_mlvalues(file, id, [splitchar]) # Return an array with values from a file, where the # values are one per line with an id preceeding them sub get_mlvalues { local @rv; local $_; local $split = defined($_[2]) ? $_[2] : " "; local $realfile = &translate_filename($_[0]); &open_readfile(ARFILE, $_[0]) || return 0; while(<ARFILE>) { chomp; local $hash = index($_, "#"); local $eq = index($_, $split); if ($hash != 0 && $eq >= 0) { local $n = substr($_, 0, $eq); local $v = substr($_, $eq+1); chomp($v); if ($n eq $_[1]) { push(@rv, $v); } } } close(ARFILE); return @rv; }
# list_syslog_facilities() # Returns an upper-case list of syslog facility names sub list_syslog_facilities { local @facils; if (&foreign_check("syslog")) { local %sconfig = &foreign_config("syslog"); @facils = map { uc($_) } split(/\s+/, $sconfig{'facilities'}); } if (!@facils) { @facils = ( 'DAEMON', 'USER', 'AUTH', 'AUTHPRIV', 'LOCAL0', 'LOCAL1', 'LOCAL2', 'LOCAL3', 'LOCAL4', 'LOCAL5', 'LOCAL6', 'LOCAL7' ); } return @facils; }
sub list_logging_levels { return ('QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE', 'DEBUG'); }
sub yes_no_default_radio { local ($name, $value) = @_; return &ui_radio($name, lc($value) eq 'yes' ? 1 : lc($value) eq 'no' ? 0 : 2, [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ], [ 2, $text{'default'} ] ]); }
1;
|