pax_global_header00006660000000000000000000000064147747455330014535gustar00rootroot0000000000000052 comment=bc6e63d7c2d1df934922e8425d17b5532e970358 libconfig-model-openssh-perl-2.9.9.1/000077500000000000000000000000001477474553300173645ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/.gitignore000066400000000000000000000002131477474553300213500ustar00rootroot00000000000000Config-Model-OpenSsh* lib/Config/Model/models/*.pod lib/Config/Model/models/Ssh/*.pod lib/Config/Model/models/Sshd/*.pod wr_root .build *~ libconfig-model-openssh-perl-2.9.9.1/Build.PL000066400000000000000000000037521477474553300206670ustar00rootroot00000000000000# Copyright (c) 2008-2013 Dominique Dumont. # # This file is part of Config-Model-OpenSsh. # # Config-Model is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser Public License as # published by the Free Software Foundation; either version 2.1 of # the License, or (at your option) any later version. # # Config-Model is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser Public License for more details. # # You should have received a copy of the GNU Lesser Public License # along with Config-Model; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA use Module::Build; use warnings FATAL => qw(all) ; use strict ; require 5.010; my %appli_files = map { ( $_, $_ ) } glob("lib/Config/Model/*.d/*"); # check that pod docs are up-to-date this is redundant with work done by # dzil. But this enable to re-build the docs downstream. # Use $^X in there as requested in # https://rt.cpan.org/Public/Bug/Display.html?id=74891 my $class = Module::Build->subclass( class => "Module::Build::Custom", code => <<'SUBCLASS' ); sub ACTION_build { my $self = shift; # below requires Config::Model 2.026 system ($^X, '-MConfig::Model::Utils::GenClassPod', '-e','gen_class_pod();') == 0 or die "gen-class-pod failed: $?"; $self->SUPER::ACTION_build; } SUBCLASS my $build = $class->new ( module_name => 'Config::Model::OpenSsh', license => 'lgpl', dist_author => "Dominique Dumont (ddumont at cpan dot org)", dist_abstract => "OpenSsh configuration files graphical editor", appli_files => \%appli_files , ##{ $plugin->get_prereqs ##} add_to_cleanup => [qw/wr_root/] , ); $build->add_build_element('pl'); $build->add_build_element('appli'); $build->create_build_script; libconfig-model-openssh-perl-2.9.9.1/Changes000066400000000000000000000363121477474553300206640ustar00rootroot00000000000000{{$NEXT}} 2.9.9.1 2025-04-07 2.9.8.1 2024-09-04 2.9.4.1 2023-10-14 Update: * Add support for OpenSsh 9.4 Generation of SSh model: * man2html is now used instead of roff2html. The program parsing parameter description (parse-man.pl) to extract parameter properties was updated to cope with this change. 2.9.0.2 2022-08-07 Fix test: * remove obsolete "backend" constructor parameter (Debian #1016295) 2.9.0.1 2022-05-10 Update: * Add support for OpenSsh 9.0 2.8.7.1 2021-12-22 Update: * Support for OpenSsh 8.7 * Added migration instructions for some parameters deprecated between OpenSsh 8.4 and 8.7 Bug fix related to generation of OpenSsh model: * fix (model generation): add deprecated elements * fix (ParseMan): handle description like "supported keywords are..." * fix (model generation): override value types of PerSource* * fix (model): improve warning about identity file * fix (parse-man.pl): improve user messages * fix (model generation): avoid long unbreakable lines (origin/master) Other changes: * build depends on Config::Model 2.146 2.8.4.3 2021-05-07 Bug fixes: * Keep order of Host and Match sections (fix #6) * No longer use content of /etc/ssh/ssh_config as upstream default values for ~/.ssh/config. See commit 766442b log for details * Fix crash when starting with empty user file (fix #5) * docs: fix typos and grammar 2.8.4.2 2021-01-13 Update: * Support for OpenSsh 8.4 * update copyright year 2.8.0.1 2019-09-08 Update: * Support for OpenSsh 8.0 Bug fix related to generation of OpenSsh model: * fix storage of description text * change quoted text to text with bold font * replace utf-8 quote with ascii quote 2.7.9.2 2019-06-14 This release fixes CI/CD bugs: * Work around Dzil bug that break tests on travis. * Fix statement in test not compatible with perl 5.12 2.7.9.1 2019-06-10 The main visible changes of this release are: * Support for OpenSsh 7.9 * A new version number scheme: v... Under the hood, the major change of this release is the way Ssh and Sshd model are updated. It used to be a manual work (which explain why only OpenSsh 6.4 parameters were supported). Now the model is generated from ssh_config and sshd_config manuel pages. All parameters from OpenSsh 7.9 are supported and obsolete parameters are silently dropped or migrated to new parameters. Other changes: * update test specifications (requires Config::Model::Tester 4.001) * require Config::Model 2.134 1.241 2018-12-01 * Tests require Config::Model 2.128 (gh #4) 1.240 2018-11-30 Fix behavior of 'cme -force' so user can load ssh config files containing errors: * allow force load when Match block contain bad data * propagate 'check' when setting check_list parameter (require Config::Model 2.127) Model update: * PortForward parameter: port must be alphanumeric 1.239 2018-05-08 * OpenSsh backend: fix backend (broke with Config::Model 2.123, requires Config::Model 2.123. Sorry about the mess). * added t/README.md * remove deprecated suffix method 1.238 2017-10-08 * udpated models to use new rw_config parameter (requires Config::Model 2.111) * update Ciphers parameter * UseLogin parameter is deprecated 1.237 2016-03-07 * Fix tests broken by Config::Model 2.080 changes (RT #112736) * Build.PL: avoid dependency on cme to build doc * dist.ini: * updated to use github's bug tracker - removed build dependency on Tk * updated README.pod to use cme meta edit 1.236 2014-05-22 * removed experience parameters from OpenSsh model with config-model-edit * removed build time dependency on AnyEvent * warn and propose a fix when public key is used as IdendityFile 1.235 2014-04-04 * tweak test to be compatible with Config::Model >= or < 2.052 * fix man pages abstract section (for Pod::Weaver) 1.234 2014-03-01 * fixed skipped test count in ssh_config.t to enable cpanm installation (RT 93314) * test $inst->has_warning (requires Config::Model 2.050) 1.233 2014-02-13 * Ssh backends: send a clear error message when unknown parameters are found (RT 92639) * Ssh: added deprecated UseRSh and FallBackToRsh (RT 92639) 1.232 2013-12-29 * Ssh::GSSAPI* params: set upstream_default to 0 (instead of default) * fixed typo in Sshd::MatchCondition description (tx gregoa) 1.231 2013-12-23 * Added parameters supported by OpenSsh 6.4 (i.e. IgnoreUnknown ForwardX11Timeout GatewayPorts GSSAPIKeyExchange GSSAPIClientIdentity GSSAPIServerIdentity GSSAPIDelegateCredentials GSSAPIRenewalForcesRekey GSSAPITrustDns IPQoS KexAlgorithms PKCS11Provider AllowAgentForwarding AuthenticationMethods AuthorizedKeysCommand AuthorizedKeysCommandUser AuthorizedPrincipalsFile ChrootDirectory GSSAPIStoreCredentialsOnRekey HostCertificate HostKeyAgent MaxSessions PermitBlacklistedKeys PubkeyAuthentication RekeyLimit RevokedKeys RhostsRSAAuthentication TrustedUserCAKeys VersionAddendum) 1.230 2013-08-27 This new release now works on MacOS X. It does take into account the different location of ssh configuration files compared to Linux or BSD. * Fixed tests for MacOS X 1.230_04 2013-08-19 * Depends on Config::Model 2.041 * Build depends on Config::Model::Tester 2.042 1.230_03 2013-08-09 * Load EV at beginning of test to avoid failure in CPAN smoke tests. 1.230_02 2013-08-08 * Load AnyEvent at beginning of test to avoid failure in CPAN smoke tests. 1.230_01 2013-08-07 * Fixed dist.ini to tweak $VERSION in all module files 1.229 2013-07-23 * fixed dist::zilla files to include .ssh dir needed for tests 1.228 2013-07-21 [ Usage changes ] * 'cme edit ssh|sshd|system-ssh' is now working on MacOS X * '/etc/ssh/ssh_config' is now handled by system-ssh. I.e. use 'cme edit system-ssh' to change this file * root user can edit its ~/.ssh/config file like any other user with 'cme edit ssh'. [ Bug fixes ] * corrected OpenSSH project name (was OpenSsh) * ssh backend: fix bug that prevented reading user file with global parameters * Ssh model: allow config file creation [ Other changes ] * renamed ChangeLog in Changes * Ssh model: use new default layer from C::M 2.040 to read system config file (hence the updated requirement on Config::Model 2.040) * All backends: removed custom code to open file. Lets Config::Model::BackendMgr handle this 2013-04-04 - 1.227 * Removed Augeas backend (no longer needed, comments are handled by Config::Model::Backend::OpenSsh) * Removed unused deps (File::Slurp) * Replaced Any::Moose with Mouse. Directly depend on Mouse. Removed dependency on Any::Mooose 2012-12-07 - 1.226 * ssh model: + added ControlPersist parameter + added Re-Build parameter (fix RT #81346) * Changed experience of Control* parameters to beginner * backend: ensure clear error message if Host is used in sshd_config * updated demos to use cme * use cme gen-class-pod to re-build when necessary * updated Config::Model dependency to 2.026 for this 2012-10-28 Dominique Dumont v 1.225 Doc and demo fix release * updated demos to use cme instead of deprecated config-edit * likewise, clean up pod doc to use cme command * removed non utf-8 char from ssh doc (Fix RT 79077) 2012-05-22 Dominique Dumont v 1.224 * Backend: make sure that AuthorizedKeysFile items are written on a single line. * Depends on Config::Model 2.017 (which has a correct dependency list). * Note to distro packagers: this dependency on Config::Model 2.017 is required for people installing this module with cpanm and for Perl smoke tests. From a feature point of view, this module requires only Config::Model 2.015 2012-05-18 Dominique Dumont v 1.223 * Added build-dependencies required by t/model_test.t (which use Config::Model::Tester) * Fix sshd-test-conf.pl to avoid test failure due to Text::Balanced warnings with perl 5.15 2012-05-16 Dominique Dumont v 1.222 * added AuthorizedKeysFile2 parameter (See Debian #671367) and migration from AuthorizedKeysFile2 to AuthorizedKeysFile to help migration from Debian Squeeze to Wheezy * replaced deprecated get_all_indexes with fetch_all_indexes * depends on Config::Model 2.015 2012-04-25 Dominique Dumont v 1.221 * Ssh model: ControlMaster also supports auto keyword (tx to harleypig and Daniel Dehennin) Closes Debian #670319 * Test: Fix skip count when test is run as root (fix smoke test failures) 2012-02-20 Dominique Dumont v 1.220 * Fix test to force write back even if no data were changed in the test (Fix FTBS Debian #660371 and Ubuntu #935221) * This fix depends on Config::Model 2.004 * Requires perl 5.10 * Move runtime dependencies in configure-requires as config::model is called by Build.PL to (re)generate pod (see also RT73611) 2011-12-07 Dominique Dumont v 1.219 * Ssh model: do not warp LocalForward with GatewayPorts. They are independant * Ssh backend: store root config in layered data instead of preset data (also fix RT#72916) * Depends on Config::Model 1.265 2011-07-22 Dominique Dumont v 1.218 * OpenSsh backend: Fix bug that tried to open a file in /etc when saving ssh config as a regular user. 2011-05-11 Dominique Dumont v 1.217 * All Backend: test value with length instead of defined (avoid keyword without value lines) * added Test::Difference build dependency * lib/Config/Model/user.d/ssh: added forgotten user file for ssh 2011-04-11 Dominique Dumont v 1.216 * All: use Any::Moose instead of plain Moose * depends on Any::Moose (fix RT# 67307) 2011-04-04 Dominique Dumont v 1.215 * All models: Added author, license and class_description * Added generated documentation from configuration classes. * Requires Config::Model 1.236 2011-03-03 Dominique Dumont v 1.214 * Fixed Build.PL to install files from lib/.../system.d/ * Fixed Ssh backend to write Host pattern annotations/comments 2011-02-28 Dominique Dumont v 1.213 * Fixed MANIFEST.SKIP to remove cruft shipped by Dist::Zilla. As downstream packager, I was not amused :/ 2011-02-23 Dominique Dumont v 1.212 * Fixed Build.PL to include prereqs computed by Dist::Zilla 2011-02-21 Dominique Dumont v 1.211 * *.t: fixed tests (Fix Debian bug #605792) * demo: split user and maintainer demo * removed config-edit-*. config-edit now has auto-completion and can be invoked with '-application ssh' or '-application sshd' * removed dependency on Parse::RecDescent * depend on Config::Model 1.234 * Single backend was split in 3 (OpenSsh, Ssh and Sshd) to benefit from C::M::Backend::Any 2010-02-02 Dominique Dumont * demo/demo.pl (my_system): new demo (requires Config::Model::Itself) 2010-01-24 Dominique Dumont * lib/Config/Model/models/Ssh/PortForward.pl: host and hostport are mandatory 2010-01-22 Dominique Dumont v1.210 * lib/Config/Model/OpenSsh.pm: Modified to read and write Port forward information from PortForward config class. * lib/Config/Model/models/Ssh/PortForward.pl: New configuration class to make ssh port forwarding configuration easier. 2010-01-18 Dominique Dumont v1.209 * lib/Config/Model/models/Sshd.pl: Added automatic migration of data from deprecated KeepAlive parameter to TCPKeepAlive parameter. This enables an automatic migration from old sshd config to new syntax. * lib/Config/Model/models/Ssh/HostElement.pl: Since ssh_config doc mentions that LocalForward and RemoteForward can be specified several times, these 2 parameters are changed from leaf to a list of leaf. * lib/Config/Model/models/Ssh.pl: As specifying Host block as list of patterns and content was not practical, the Host element in Ssh model was changed from list of HostBlock nodes to hash of HostElement. The Host patterns is used as the key of the hash. This enables a better view of shh configuration in the GUI. * lib/Config/Model/OpenSsh.pm (assign): Store value in uniline leaf even with embedded white spaces. (write_all_host_block): adapted to Host structure change in model 2009-09-10 Dominique Dumont v1.208 * lib/Config/Model/models/**.pl: Changed 'level' of some elements to 'important' so the new wizard provided by C::M::TkUI will show the most imporant ssh and sshd configuration parameters. 2009-07-29 Dominique Dumont v1.207 * t/ssh_config.t: When run as root, skip the tests that must be run as regular user. (Fix Debian FTBS) * lib/Config/Model/models/Ssh/HostElement.pl: Fix model error: ServerAliveInterval is an integer, not a boolean 2009-06-24 Dominique Dumont v1.206 * Build.PL: added forgotten dependency on Parse::RecDescent. Depends on Config::Model 0.637 2009-06-23 Dominique Dumont * lib/Config/Model/models/**.pl: replaced deprecated 'built_in' model parameter with 'upstream_default'. (In fact I just had to run "config-model-edit -model Ssh -save" (from Config::Model::Itself)) 2009-04-11 Dominique Dumont v1.205 * lib/Config/Model/OpenSsh.pm (read_ssh_file): fix bug that breaks with Config::Model 0.635 2009-03-09 Dominique Dumont v1.204 * t/ssh_config.t: Removed unused options that broke with Config::Model 0.634 * config-edit-ssh: Update documentation 2009-02-03 Dominique Dumont v1.203 * t/augeas_*.t: Do the exec only if Augeas part can be tested. Use $^X in exec instead of 'perl'. This should also fix tests in CPAN. 2009-02-02 Dominique Dumont v1.202 * t/augeas*.t : Changed Augeas locale workaround to reduce the number of test failures in CPAN tests. 2009-01-29 Dominique Dumont v1.201 * config-edit-sshd: added workaround Augeas locale bug * Sshd files: Major bug fixes for Augeas integration * lib/Config/Model/OpenSsh.pm (read_ssh_file): Fix: Host names are separated by white spaces and not comma 2008-11-16 Domi * lib/Config/Model/models/Sshd.pl: Added write through Augeas so comment in /etc/ssh/sshd_config can be preserved (requires Augeas and Config::Model::Backend::Augeas) * config-edit-ssh: new command line to edit ~/.ssh/config file (as normal user) or /etc/ssh/ssh_config (as root) 2008-05-26 Dominique Dumont v0.104 * all: changed module name from Sshd to OpenSsh 2008-05-24 Dominique Dumont v0.103 * lib/Config/Model/Sshd.pm (): Added doc * config-edit-sshd: new file libconfig-model-openssh-perl-2.9.9.1/MANIFEST.SKIP000066400000000000000000000001611477474553300212600ustar00rootroot00000000000000debian/ ~$ \.ptkdb$ \.old$ dist.ini libconfig _build \.orig$ ^MYMETA.yml$ blib wr_root wr_test demo/lib demo/etc libconfig-model-openssh-perl-2.9.9.1/README-build-from-git.md000066400000000000000000000037241477474553300234700ustar00rootroot00000000000000# How to build Config::Model::OpenSsh from git repository `Config::Model::OpenSsh` is build with [Dist::Zilla](http://dzil.org/). This page details how to install the tools and dependencies required to build this module. ## Install tools and dependencies ### Debian, Ubuntu and derivatives Run $ sudo apt install libdist-zilla-perl libdist-zilla-app-command-authordebs-perl $ dzil authordebs --install $ sudo apt build-dep libconfig-model-openssh-perl The [libdist-zilla-app-command-authordebs-perl package](https://tracker.debian.org/pkg/libdist-zilla-app-command-authordebs-perl) is quite recent (uploaded on Dec 2016 in Debian/unstable) and may not be available yet on your favorite distribution. ### Other systems Run $ cpamn Dist::Zilla $ dzil authordeps -missing | cpanm --notest $ dzil listdeps --missing | cpanm --notest NB: The author would welcome pull requests that explains how to install these tools and dependencies using native package of other distributions. ## Build Config::Model::OpenSsh Run dzil build or dzil test `dzil` may complain about missing `EmailNotify` or `Twitter` plugin. You may ignore this or edit [dist.ini](dist.ini) to comment out the last 2 sections. These are useful only to the author when releasing a new version. `dzil` may also return an error like `Cannot determine local time zone`. In this case, you should specify explicitely your timezone in a `TZ` environement variable. E.g run `dzil` this way: TZ="Europe/Paris" dzil test The list of possible timezones is provided by [DateTime::TimeZone::Catalog](https://metacpan.org/pod/DateTime::TimeZone::Catalog) documentation. ## Model generation Ssh model can be regenerated from ssh man pages with the following steps: * make sure that `ssh_config` and `sshd_config` man pages are available * Run `perl contrib/parse-man.pl` * Inspect the result * Then build the module as shown above For more details, see this [readme file](contrib/README.org) libconfig-model-openssh-perl-2.9.9.1/README.pod000066400000000000000000000045231477474553300210310ustar00rootroot00000000000000=head1 Config::Model::OpenSsh - OpenSSH graphical configuration editor This module provides a graphical configuration editor for: =over =item C =item C =item C<~/.ssh/config> =back =head1 Installation =head2 Debian or Ubuntu As root,type: sudo apt install cme libconfig-model-openssh-perl To get the GUI, you should also do: sudo apt install libconfig-model-tkui-perl =head2 On Mac or Windows The easiest way is to: =over =item * install Perl from L, =item * Run PPM =item * Select and install C, C and C =back =head2 Other You can also install these modules from CPAN: cpanm App::Cme cpanm Config::Model::OpenSsh cpanm Config::Model::TkUI =head1 Usage Once this module is installed, you can launch a GUI to edit C with: $ sudo cme edit sshd If L fails to load your C, you can try L with C<-force> option. Likewise, you can edit your C<~/.ssh/config> file with: $ cme edit ssh Or to edit C, run as root: $ sudo cme edit system-ssh More details are given in L wiki page. =head1 Build from git repository See L. =head1 More information For more information, see: =over =item * L wiki page =item * L wiki page =item * L =back =head1 Installation from git L is built with L. Please follow the L to install all modules related to L. Then, make sure that L is installed. On debian or ubuntu, do: sudo apt-get build-dep libconfig-model-openssh-perl Then run: dzil build If you want to install this software without packaging, you can also run: dzil install libconfig-model-openssh-perl-2.9.9.1/contrib/000077500000000000000000000000001477474553300210245ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/contrib/README.org000066400000000000000000000024041477474553300224720ustar00rootroot00000000000000This directory contains a utility to regenerate ssh and sshd model using the data provided by ssh_config and sshd_config man page. The ~parse-man.pl~ program works this way: - ssh man page is converted to HTML with ~roff2html~ - The list of configuration parameter and its description is extracted from the HTML - The description is parsed to generate ssh model - the same steps are applied for ~sshd_config~ man page Unfortunately, extracting a model from unstructured data (like a parameter description) is not bullet proof so: - the model of some parameter is hardcoded in ~lib/ParseMan.pm~ - extra information is hardcoded in yaml files. Here's the content of this directory: - ~parse-man.pl~ : the generator program - ~lib/ParseMan.pm~: a Perl library for ~parse-man.pl~ - ~ssh-fixup.yaml~: extra model information for ssh model - ~sshd-fixup.yaml~: likewise for sshd - ~systemssh.yml~: skeleton model for system ssh model - ~fixup-element-ipqos.yml~: extra information for ~IPQoS~ parameter used by both ssh and sshd models - ~sshd-matchblock.yml~: skeleton model for ~Sshd::MatchBlock~ configuration class - ~sshd-matchcondition.yml~: model for ~Sshd::MatchCondition~ configuration class - ~ssh-portforward.yml~: model for ~Ssh::PortForward~ configuration class libconfig-model-openssh-perl-2.9.9.1/contrib/fixup-element-ipqos.yml000066400000000000000000000012741477474553300254660ustar00rootroot00000000000000--- assert: 1_or_2: code: | return 1 unless defined $_; my @v = (/(\w+)/g); return (@v < 3) ? 1 : 0; msg: value must not have more than 2 fields. accepted_values: code: | return 1 unless defined $_; my @v = (/(\S+)/g); my @good = grep {/^(af[1-4][1-3]|cs[0-7]|ef|lowdelay|throughput|reliability|\d+)/} @v ; return @good == @v ? 1 : 0; msg: | Unexpected value "$_". Expected 1 or 2 occurences of: "af11", "af12", "af13", "af21", "af22", "af23", "af31", "af32", "af33", "af41", "af42", "af43", "cs0", "cs1", "cs2", "cs3", "cs4", "cs5", "cs6", "cs7", "ef", "lowdelay", "throughput", "reliability", or numeric value. libconfig-model-openssh-perl-2.9.9.1/contrib/lib/000077500000000000000000000000001477474553300215725ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/contrib/lib/ParseMan.pm000066400000000000000000000243161477474553300236440ustar00rootroot00000000000000use strict; use warnings; package ParseMan; # This module is used by parse_man.pl to generate Ssh models # and should not be shippped to CPAN use 5.22.0; use utf8; use English; use lib qw(lib contrib/lib); use experimental qw/postderef signatures/ ; use XML::Twig; use List::MoreUtils qw/any/; use Text::Wrap; $Text::Wrap::columns = 80; use Exporter 'import'; our @EXPORT = qw(parse_html_man_page create_load_data create_class_boilerplate); sub parse_html_man_page ($html_man_page) { my %data = ( element_list => [], element_data => {}, ); my $config_class; my $parameter ; my $manpage = sub ($t, $elt) { my $man = $elt->first_child('refentrytitle')->text; my $nb = $elt->first_child('manvolnum')->text; $elt->set_text( qq!L<$man($nb)>!); }; my $turn_to_pod_c = sub { my $t = $_->text(); $_->set_text("C<$t>");}; my $ssh_param = sub { $parameter = $_->text(); $parameter =~ s/\s//g; say "Found parameter «$parameter»"; push $data{element_list}->@*, $parameter; $data{element_data}{$parameter} = []; }; my $store_ssh_data = sub ($text) { $text =~ s/([\w-]+)\((\d+)\)/L<$1($2)>/g; # replace utf-8 quotes with B<> $text =~ s/\x{201c}(\w+)\x{201d}/B<$1>/g; # replace single utf-8 quote with ascii quote $text =~ s/\x{2019}/'/g; # replace backquote with quote $text =~ s/`/'/g; # avoid long unbreakable lines $text =~ s/,(\w)/, $1/g; # avoid leading whitespace $text =~ s/^\s+//mg; # avoid trailing whitespace $text =~ s/\s+$//mg; # convert a roff tag missed by man2html $text =~ s/^Sx\s(.*)$/I<$1>/mg; # put text in a single line (roff conversion lead to a lot of \n) $text =~ s/\n+/ /g; $text =~ s/\s*<<>>\s*/\n\n/g; my $desc = fill('','', $text); push $data{element_data}{$parameter}->@*, $desc if $parameter; }; my $buggy_ssh_param = sub { # a bug in man2html sometimes (for # CanonicalizePermittedCNAMEs) adds part of the description in # DT element outside of my $desc_part = $_->text(); # remove B<> that was handled by $ssh_param $desc_part =~ s!B<.*>\s*!!i; $store_ssh_data->($desc_part) if $desc_part; }; my $ssh_data = sub { $store_ssh_data->($_->text()); }; my $twig = XML::Twig->new; my $handlers = { 'html/body/h2' => sub { # de-installing handler at the end of DESCRIPTION section $twig->setTwigHandlers({}); }, 'html/body/p/dl/dt/b' => $ssh_param, 'html/body/p/dl/dt' => $buggy_ssh_param, 'html/body/p/dl/dd' => $ssh_data, 'b' => sub { my $t = $_->text; $t =~ s/^\s+|\s+$//g; $_->set_text("B<$t> ")}, 'i' => sub { my $t = $_->text; $_->set_text("I<$t> ")}, 'p' => sub { my $t = $_->text; $_->set_text("\n<<>>\n$t")}, }; $twig->setTwigHandlers({ 'html/body/h2[string() = "DESCRIPTION"]' => sub { # installing handler"; $twig->setTwigHandlers($handlers); } }); $twig->parse_html($html_man_page); return \%data; } sub setup_choice { my (@choices, %choice_hash) ; return ( sub { foreach my $v (@_) { next if $choice_hash{$v}; push @choices, $v; $choice_hash{$v} = 1; } }, sub { return @choices;} ); } my $ssh_host = 'type=hash index_type=string ordered=1 cargo type=node ' .'config_class_name=Ssh::HostElement'; my $ssh_forward = 'type=list cargo type=node config_class_name="Ssh::PortForward"'; my $uniline = 'type=leaf value_type=uniline'; my $uniline_list = "type=list cargo $uniline"; my $yes_no_leaf = "type=leaf value_type=boolean write_as=no,yes"; my %override = ( all => { IPQoS => 'type=leaf value_type=uniline upstream_default="af21 cs1"', KbdInteractiveAuthentication => "$yes_no_leaf upstream_default=yes", }, ssh => { # description is too complex to parse ControlPersist => $uniline, EscapeChar => $uniline, GlobalKnownHostsFile => $uniline.' default="/etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2"', Host => $ssh_host, IdentityFile => $uniline_list, KbdInteractiveDevices => $uniline_list, LocalForward => $ssh_forward, Match => $ssh_host, ObscureKeystrokeTiming => 'type=leaf value_type=uniline upstream_default="interval:20"', PreferredAuthentications => $uniline_list, RemoteForward => $ssh_forward, StrictHostKeyChecking => 'type=leaf value_type=enum ' . 'choice=yes,accept-new,no,off,ask upstream_default=ask', UserKnownHostsFile => "$uniline_list", }, sshd => { AuthenticationMethods => $uniline, AuthorizedKeysFile => $uniline_list, AuthorizedPrincipalsFile => 'type=leaf value_type=uniline upstream_default="none"', ChrootDirectory => 'type=leaf value_type=uniline upstream_default="none"', ForceCommand => 'type=leaf value_type=uniline upstream_default="none"', GSSAPIStoreCredentialsOnRekey => "$yes_no_leaf upstream_default=no", IgnoreUserKnownHosts => "$yes_no_leaf upstream_default=no", MaxStartups => 'type=leaf value_type=uniline upstream_default=10', PAMServiceName => 'type=leaf value_type=uniline level=hidden ' . # this parameter shows up only when UsePAM is true 'warp follow:use_pam="- UsePAM" rules:"$use_pam" level=normal', ForceCommand => 'type=leaf value_type=uniline upstream_default="none"', PasswordAuthentication => 'type=leaf value_type=uniline upstream_default=sshd', PerSourcePenalties => 'type=leaf value_type=uniline', Subsystem => 'type=hash index_type=string ' . 'cargo type=leaf value_type=uniline mandatory=1 - - ', VersionAddendum => $uniline, } ); sub create_load_data ($ssh_system, $name, @desc) { my $desc = join('', @desc); if ($override{$ssh_system}{$name}) { say "Parameter $ssh_system $name is overridden"; return $override{$ssh_system}{$name}; } if ($override{'all'}{$name}) { say "Parameter $ssh_system $name is overridden in ssh and sshd"; return $override{'all'}{$name}; } say "Parameter $ssh_system $name: analysing description"; # trim description (which is not saved in this sub) to simplify # the regexp below $desc =~ s/[\s\n]+/ /g; my (%choice_hash, $value_type); my @load_extra; my ($set_choice, $get_choices) = setup_choice(); # handle "The argument must be B, B (the default) or B" # since man2html is used, dot after B<> are no longer found. if ($desc =~ /(?:argument|option)s? (?:to this keyword )?(?:are|\w+ be)(?: one of)?(?:[\s:]+)(?=B<)([^.]+)/i) { my $str = $1; $set_choice->( $str =~ /(?/g ); } if ($desc =~ /supported keywords are(?:[\s:]+)(?=B<)([^.]+)\./i) { my $str = $1; $set_choice->( $str =~ /B<(\w[\w-]*)>/g ); } if (my @values = ($desc =~ /(?:(?:if|when|with) (?:(?:B<$name>|th(?:e|is) option) (?:is )?)?set to|A value of|setting this to|The default(?: is|,)|Accepted values are) B<([a-z]\w+)>/gi)) { $set_choice->(@values); } if (my @values = ($desc =~ /The possible values are:([^.]+)\./gi)) { my $str = $1; $set_choice->( $str =~ /([A-Z\d]+)/g ); } my @choices = $get_choices->(); if (@choices == 1 and $choices[0] eq 'no') { # assume the other choice is 'yes' push @choices, 'yes'; } if (@choices == 1 and $choices[0] eq 'yes') { push @choices, 'no'; } if ($desc =~ /(Specif\w+|Sets?) (a|the) (maximum )?(number|timeout)|size \(in bits\)/) { my $upstream_default; if ($desc =~ /The default(?: value)?(?: is|,) (\d+)/) { $upstream_default = $1; } # do not set integer type when upstream default value is not an integer if (not defined $upstream_default or $upstream_default =~ /^\d+$/) { $value_type = 'integer'; push @load_extra, qq!upstream_default="$upstream_default"! if defined $upstream_default; } } elsif (@choices == 1) { die "Parser error: Cannot create an enum with only once choice ($name): @choices\n", "Description is:\n $desc\n"; } elsif (@choices == 2 and any { /^yes|no$/ } @choices) { $value_type = 'boolean'; push @load_extra, 'write_as=no,yes'; } elsif (@choices) { $value_type = 'enum'; push @load_extra, 'choice='.join(',',sort @choices); } if ($desc =~ m!The default(?: is|,) [BI]<([\w/:]+)>! or $desc =~ m!The default(?: is|,) ((?:/\w+)+)\b! or $desc =~ /The default(?: is|,) ([A-Z]{3,}\d?)\b/ or $desc =~ /B<([\w]+)> \(the default\)/) { push @load_extra, "upstream_default=$1"; } $value_type //= 'uniline'; my @load ; if ($desc =~ /multiple (\w+ ){1,2}may be (specified|separated)|keyword can be followed by a list of/i) { @load = ('type=list', 'cargo'); } # TODO: # CanonicalDomains depends on CanonicalizeHostname -> order problem, use move on model push @load, 'type=leaf', "value_type=$value_type"; return join(' ',@load, @load_extra); } my ($ssh_version) = (`ssh -V 2>&1` =~ /OpenSSH_([\w\.]+)/); sub create_class_boilerplate ($meta_root, $ssh_system, $config_class) { my $desc_text="This configuration class was generated from $ssh_system documentation.\n" ."by L\n"; my $steps = "class:$config_class class_description"; $meta_root->grab(step => $steps, autoadd => 1)->store($desc_text); $meta_root->load( steps => [ qq!class:$config_class generated_by="parse-man.pl from $ssh_system $ssh_version doc"!, qq!license=LGPL2!, qq!accept:".*" type=leaf value_type=uniline!, qq!summary="boilerplate parameter that may hide a typo"!, qq!warn="Unknown parameter. Please make sure there\'s no typo and contact the author"!, ]); } 1; libconfig-model-openssh-perl-2.9.9.1/contrib/parse-man.pl000066400000000000000000000104671477474553300232540ustar00rootroot00000000000000#!/usr/bin/perl use strict; use warnings; use 5.22.0; use utf8; use open qw(:std :utf8); # undeclared streams in UTF-8 use lib 'contrib/lib'; use lib 'lib'; use IO::Pipe; use Path::Tiny; use Config::Model 2.134; # load_data __skip_order parameter use Config::Model::Itself 2.012; use Config::Model::Exception; use YAML::XS qw/LoadFile/; use experimental qw/postderef signatures/ ; use ParseMan; # make sure that Ssh models are created from scratch path('lib/Config/Model/models/')->remove_tree; sub parse_man_page ($man_page_name) { my $path = `man --path $man_page_name`; chomp $path; my $pipe = IO::Pipe->new(); $pipe->reader("zcat $path | man2html"); my @lines = $pipe->getlines; $pipe->close; return parse_html_man_page(join('',@lines)); } sub store_description ($obj, @desc) { $obj->fetch_element("description")->store(join("\n\n", @desc)); } sub create_ssh_model ($meta_root) { say "Processing ssh documentation..."; create_class_boilerplate ($meta_root, ssh_system => 'Ssh'); create_class_boilerplate ($meta_root, ssh_system => 'Ssh::HostElement'); # extract data from ssh man pages my $data = parse_man_page( 'ssh_config' ) ; foreach my $element ($data->{element_list}->@*) { my @desc = $data->{element_data}{$element}->@*; my $load_string = create_load_data(ssh => $element, @desc); my $target = $element =~ /^(Host|Match)$/ ? 'Ssh' : 'Ssh::HostElement'; my $obj = $meta_root->grab(qq!class:$target element:"$element"!); $obj->load($load_string); store_description($obj, @desc); } $meta_root->load(qq!class:Ssh include="Ssh::HostElement"!); } sub create_sshd_model ($meta_root) { say "Processing sshd documentation..."; create_class_boilerplate ($meta_root, sshd_system => 'Sshd'); create_class_boilerplate ($meta_root, sshd_system => 'Sshd::MatchElement'); my $data = parse_man_page( 'sshd_config' ) ; # retrieve list of keywords that can fit in Match block my $is_match = extract_list_from_desc($data->{element_data}{'Match'}); foreach my $element ($data->{element_list}->@*) { my @desc = $data->{element_data}{$element}->@*; my $load_string = create_load_data(sshd => $element, @desc); my $target = $is_match->{$element} ? 'Sshd::MatchElement' : 'Sshd'; my $obj = $meta_root->grab(qq!class:$target element:"$element"!); $obj->load($load_string); store_description($obj, @desc); } $meta_root->load(qq!class:Sshd include="Sshd::MatchElement"!); } sub extract_list_from_desc ($desc_ref) { my $str = $desc_ref->[$#$desc_ref]; my @keywords = ( $str =~ /B<(\w+)>/g ); my %is_match = map { $_ => 1 ; } grep { $_ ne 'Match' } @keywords; return \%is_match; } sub load_yaml_model ($meta_root,$class) { my $file = 'contrib/'.lc($class).'.yml'; $file =~ s/::/-/g; say "Creating $class from $file..."; $meta_root->load_data(LoadFile($file)); } # Itself constructor returns an object to read or write the data # structure containing the model to be edited my $rw_obj = Config::Model::Itself -> new () ; # now load the existing model to be edited $rw_obj -> read_all() ; my $meta_root = $rw_obj->meta_root; load_yaml_model($meta_root,"Ssh::PortForward"); say "Creating ssh model..."; create_ssh_model($meta_root); say "loading ssh model addendum from ssh-fixup.yaml"; $meta_root->load_data(LoadFile('contrib/ssh-fixup.yaml')); say "loading ssh model IPQoS element from fixup-element-ipqos.yml"; $meta_root ->grab("class:Ssh::HostElement element:IPQoS") ->load_data(LoadFile('contrib/fixup-element-ipqos.yml')); # This class include Ssh model and must be loaded after Ssh model is # created load_yaml_model($meta_root,"SystemSsh"); say "Ssh model is done..."; say "Generating Sshd model"; load_yaml_model($meta_root,"Sshd::MatchCondition"); create_sshd_model($meta_root); # requires Sshd::MatchElement load_yaml_model($meta_root,"Sshd::MatchBlock"); say "loading sshd model addendum from sshd-fixup.yaml"; $meta_root->load_data(LoadFile('contrib/sshd-fixup.yaml')); say "loading ssh model IPQoS element from fixup-element-ipqos.yml"; $meta_root ->grab("class:Sshd::MatchElement element:IPQoS") ->load_data(LoadFile('contrib/fixup-element-ipqos.yml')); say "Saving ssh and sshd models..."; $rw_obj->write_all; say "Done."; libconfig-model-openssh-perl-2.9.9.1/contrib/ssh-fixup.yaml000066400000000000000000000025571477474553300236470ustar00rootroot00000000000000--- class: __order: - Ssh::HostElement - Ssh Ssh: include: - Ssh::HostElement include_after: Host rw_config: auto_create: 1 backend: OpenSsh::Ssh config_dir: ~/.ssh file: config Ssh::HostElement: element: __skip_order: 1 IdentityFile: cargo: warn_if_match: \.pub$: fix: s/\.pub$//; msg: 'identity file must be the private key' UseRsh: &deprecated description: This parameter is now ignored by Ssh status: deprecated type: leaf value_type: uniline FallBackToRsh: *deprecated HostbasedKeyTypes: *deprecated HostbasedAcceptedAlgorithms: migrate_from: variables: old: "- HostbasedKeyTypes" formula: "$old" PreferredAuthentications: cargo: warn_unless_match: "^(gssapi-with-mic|hostbased|publickey|keyboard-interactive|password)$": msg: | Unexpected authentication method: 'C<$_>'. Expected one of C, C, C, C or C PubkeyAcceptedKeyTypes: *deprecated PubkeyAcceptedAlgorithms: migrate_from: variables: old: "- PubkeyAcceptedKeyTypes" formula: "$old" libconfig-model-openssh-perl-2.9.9.1/contrib/ssh-portforward.yml000066400000000000000000000035551477474553300247230ustar00rootroot00000000000000--- class: Ssh::PortForward: author: - Dominique Dumont class_description: |- Configuration class that represents the parameters required to specify port forwarding in a ssh configuration. copyright: - 2009-2018 Dominique Dumont element: __element_order: - ipv6 - bind_address - port - host - hostport bind_address: description: |- Specify the address that the port will listen to. By default, only connections coming from localhost (127.0.0.1) will be forwarded. By default, the local port is bound in accordance with the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The bind_address of 'localhost' indicates that the listening port be bound for local use only, while an empty address or '*' indicates that the port should be available from all interfaces. summary: bind address to listen to type: leaf value_type: uniline host: mandatory: '1' summary: host name or address type: leaf value_type: uniline hostport: description: Port number to connect the tunnel to. mandatory: '1' match: ^\w+$ summary: destination port type: leaf value_type: uniline ipv6: description: Specify if the forward is specified iwth IPv6 or IPv4 type: leaf value_type: boolean write_as: - 'no' - 'yes' port: description: Listening port. Connection made to this port will be forwarded to the other side of the tunnel. mandatory: '1' match: ^\w+$ type: leaf value_type: uniline license: LGPL2 __class_order: - Ssh::PortForward libconfig-model-openssh-perl-2.9.9.1/contrib/sshd-fixup.yaml000066400000000000000000000026311477474553300240040ustar00rootroot00000000000000--- class: __order: - Sshd - Sshd::MatchElement Sshd: include: - Sshd::MatchElement rw_config: backend: OpenSsh::Sshd config_dir: /etc/ssh file: sshd_config os_config_dir: darwin: /etc element: __skip_order: 1 Match: type: list cargo: type: node config_class_name: Sshd::MatchBlock PerSourceNetBlockSize: &uniline value_type: uniline PerSourceMaxStartups: *uniline Sshd::MatchElement: element: __skip_order: 1 AuthorizedKeysFile2: description: This parameter is now ignored by Ssh status: deprecated type: list cargo: type: leaf value_type: uniline AuthorizedKeysFile: migrate_values_from: "- AuthorizedKeysFile2" ChallengeResponseAuthentication: status: deprecated type: leaf value_type: boolean KbdInteractiveAuthentication: migrate_from: variables: old: "- ChallengeResponseAuthentication" formula: "$old" KeyRegenerationInterval: &deprecated status: deprecated type: leaf value_type: uniline # deprecated with Ssh protocol V1 Protocol: *deprecated RDomain: *deprecated RSAAuthentication: *deprecated RhostsRSAAuthentication: *deprecated UsePrivilegeSeparation: *deprecated libconfig-model-openssh-perl-2.9.9.1/contrib/sshd-matchblock.yml000066400000000000000000000015371477474553300246230ustar00rootroot00000000000000--- class: Sshd::MatchBlock: author: - Dominique Dumont class_description: "Class to represent a Match block inside a sshd_config file. \n\nIt's made of a list of conditions to match and a list of \nparameters to apply to the matched items." copyright: - 2009-2011 Dominique Dumont element: Condition: config_class_name: Sshd::MatchCondition description: Specify the condition (User, Group, Host, Address) necessary for this Match block to be applied type: node Settings: config_class_name: Sshd::MatchElement description: Defines the sshd_config parameters that will override general settings when all defined User, Group, Host and Address patterns match. type: node __element_order: - Condition - Settings license: LGPL2 libconfig-model-openssh-perl-2.9.9.1/contrib/sshd-matchcondition.yml000066400000000000000000000023671477474553300255210ustar00rootroot00000000000000--- class: Sshd::MatchCondition: author: - Dominique Dumont class_description: "Conidtion to apply to identify matched items inside \na sshd_config match block." copyright: - 2009-2011 Dominique Dumont element: Address: description: Define the Address criteria of a conditional block. The value of this field is a pattern that is tested against the address of the incoming connection. type: leaf value_type: uniline Group: description: Define the Group criteria of a conditional block. The value of this field is a pattern that is tested against group name. type: leaf value_type: uniline Host: description: Define the Host criteria of a conditional block. The value of this field is a pattern that is tested against host name. type: leaf value_type: uniline User: description: Define the User criteria of a conditional block. The value of this field is a pattern that is tested against user name. type: leaf value_type: uniline __element_order: - User - Group - Host - Address license: LGPL2 __class_order: - Sshd::MatchCondition libconfig-model-openssh-perl-2.9.9.1/contrib/systemssh.yml000066400000000000000000000006311477474553300236110ustar00rootroot00000000000000--- class: SystemSsh: author: - Dominique Dumont class_description: "Configuration class used by L to edit or \nvalidate /etc/ssh/ssh_config (as root)\n" copyright: - 2013 Dominique Dumont include: - Ssh license: LGPL2 rw_config: backend: OpenSsh::Ssh config_dir: /etc/ssh file: ssh_config os_config_dir: darwin: /etc libconfig-model-openssh-perl-2.9.9.1/dist.ini000066400000000000000000000043401477474553300210310ustar00rootroot00000000000000name = Config-Model-OpenSsh author = Dominique Dumont license = LGPL_2_1 copyright_holder = Dominique Dumont copyright_year = 2008-2025 [MetaResources] homepage = https://github.com/dod38fr/config-model/wiki bugtracker.mailto = ddumont at cpan.org bugtracker.web = https://github.com/dod38fr/config-model-openssh/issues repository.url = git://github.com/dod38fr/config-model-openssh.git repository.web = http://github.com/dod38fr/config-model-openssh.git repository.type = git [Prereqs] perl = 5.012 [NextRelease] format = %v%T %{yyyy-MM-dd}d ; use 'V=2.234 dzil release' to override version number [Git::NextVersion] [Git::Check] allow_dirty = dist.ini allow_dirty = Changes [Git::Commit] [Git::Tag] signed = 1 [Git::Push] [MetaJSON] [AutoPrereqs] skip = ^[a-z\d]+$ skip = ExtUtils::testlib skip = Exporter configure_finder = ScriptFile [Prereqs / RuntimeRequires] [Prereqs / RuntimeRecommends] App::Cme = 0 Config::Model::TkUI = 0 [Prereqs / BuildRequires] ; not detected by dzil authordep. ; See Dist::Zilla::App::Command::authordeps man page ; authordep Pod::Weaver::Section::Support ; authordep Pod::Elemental::Transformer::List ; authordep App::Cme Config::Model = 2.134 [@Filter] -bundle = @Basic -remove = Readme -remove = MakeMaker [ModuleBuild::Custom] mb_version = 0.34 ; avoid messing with generated pod files. Otherwise pod re-generated ; at packaging time (Debian) are different (because Dist::Zilla is not ; used at that time) See ; http://blogs.perl.org/users/polettix/2011/11/distzilla-podweaver-and-bin.html ; for details on this configuration magic [FileFinder::ByName / OnlyPmFiles] dir = lib match = \.pm$ [FileFinder::ByName / ScriptFile] dir = script match = \.pl$ [FileFinder::ByName / noModelFiles] dir = lib skip = /models/ match = \.p(m|od)$ [PkgVersion] finder = OnlyPmFiles [Test::Perl::Critic] [PodWeaver] finder = :ExecFiles finder = noModelFiles [Prepender] copyright=1 [Run::BeforeBuild] ;-- Generate pod doc from model, requires Config::Model 2.026 run = cme gen-class-pod [Run::BeforeRelease] ;-- Generate pod doc from model, requires Config::Model 2.026 run = cme gen-class-pod [Run::Clean] ; pod files are generated in Run::BeforeBuild run = find lib -name '*.pod' -delete [Signature] libconfig-model-openssh-perl-2.9.9.1/lib/000077500000000000000000000000001477474553300201325ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/000077500000000000000000000000001477474553300213375ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/000077500000000000000000000000001477474553300223775ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/000077500000000000000000000000001477474553300237265ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/000077500000000000000000000000001477474553300253055ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/Role/000077500000000000000000000000001477474553300262065ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/Role/MatchBlock.pm000066400000000000000000000050131477474553300305520ustar00rootroot00000000000000use strict; use warnings; package Config::Model::Backend::OpenSsh::Role::MatchBlock ; use Mouse::Role ; requires qw(current_node write_node_content write_line); use Carp ; use IO::File ; use Log::Log4perl; use File::Copy ; use File::Path ; my $logger = Log::Log4perl::get_logger("Backend::OpenSsh"); sub match { my ($self, $root, $key, $pairs, $comment, $check) = @_ ; $logger->debug("match: @$pairs # $comment"); my $list_obj = $root->fetch_element('Match'); # create new match block my $nb_of_elt = $list_obj->fetch_size; my $block_obj = $list_obj->fetch_with_id($nb_of_elt) ; $block_obj->annotation($comment) ; while (@$pairs) { my $criteria = shift @$pairs; my $pattern = shift @$pairs; $block_obj->load( steps => qq!Condition $criteria="$pattern"!, check => $check, ); } $self->current_node( $block_obj->fetch_element('Settings') ); } sub write_all_match_block { my $self = shift ; my $match_elt = shift ; my $mode = shift || ''; my $result = ''; foreach my $elt ($match_elt->fetch_all($mode) ) { $result .= $self->write_match_block($elt,$mode) ; } return $result ; } sub write_match_block { my $self = shift ; my $match_elt = shift ; my $mode = shift || ''; my $match_line ; my $match_body ; foreach my $name ($match_elt->get_element_name() ) { my $elt = $match_elt->fetch_element($name) ; if ($name eq 'Settings') { $match_body .= $self->write_node_content($elt,$mode)."\n" ; } elsif ($name eq 'Condition') { $match_line = $self->write_line( Match => $self->write_match_condition($elt,$mode) , $match_elt -> annotation ) ; } else { die "write_match_block: unexpected element: $name"; } } return $match_line.$match_body ; } sub write_match_condition { my $self = shift ; my $cond_elt = shift ; my $mode = shift || ''; my $result = '' ; foreach my $name ($cond_elt->get_element_name() ) { my $elt = $cond_elt->fetch_element($name) ; my $v = $elt->fetch($mode) ; $result .= " $name $v" if defined $v; } return $result ; } no Mouse; 1; # ABSTRACT: Backend role for Ssh Match blocks __END__ =head1 SYNOPSIS None =head1 DESCRIPTION This class provides a backend role to read and write C blocks in OpenSsh configuration files. =head1 SEE ALSO L, libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/Role/Reader.pm000066400000000000000000000077541477474553300277630ustar00rootroot00000000000000use strict; use warnings; package Config::Model::Backend::OpenSsh::Role::Reader ; use 5.10.1; use Config::Model 2.128; use Mouse::Role ; requires qw(read_global_comments associates_comments_with_data); # sub stub known as "forward" declaration # required for Role consistency checks # See Moose::Manual::Roles for details sub current_node; has 'current_node' => ( is => 'rw', isa => 'Config::Model::Node', weak_ref => 1 ) ; use Carp ; use Log::Log4perl 1.11; my $logger = Log::Log4perl::get_logger("Backend::OpenSsh"); my @dispatch = ( qr/match/i => 'match', qr/host\b/i => 'host', qr/(local|remote)forward/i => 'forward', qr/^PreferredAuthentications$/ => 'comma_list', qr/localcommand/i => 'assign', qr/\w/ => 'assign', ); sub read { my $self = shift ; my %args = @_ ; my $config_root = $args{object} || croak __PACKAGE__," read_ssh_file: undefined config root object"; return 0 unless $args{file_path}->is_file; $logger->info("loading config file ".$args{file_path}); my @lines = $args{file_path}->lines_utf8 ; # try to get global comments (comments before a blank line) $self->read_global_comments(\@lines,'#') ; # need to reset this when reading user ssh file after system ssh file $self->current_node($config_root) ; my @assoc = $self->associates_comments_with_data( \@lines, '#' ) ; foreach my $item (@assoc) { my ( $vdata, $comment ) = @$item; my ( $k, @v ) = split /\s+/, $vdata; my $i = 0; while ( $i < @dispatch ) { my ( $regexp, $sub ) = @dispatch[ $i++, $i++ ]; if ( $k =~ $regexp and $self->can($sub)) { $logger->trace("read_ssh_file: dispatch calls $sub"); $self->$sub( $config_root, $k, \@v, $comment, $args{check} ); last; } warn __PACKAGE__, " unknown keyword: $k" if $i >= @dispatch; } } return 1; } sub comma_list { my ($self,$root, $raw_key,$arg,$comment, $check) = @_ ; $logger->debug("assign: $raw_key @$arg # $comment"); my @list = map { split /\s*,\s*/ } @$arg; $self->assign($root, $raw_key,\@list,$comment, $check); } sub assign { my ($self,$root, $raw_key,$arg,$comment, $check) = @_ ; $logger->debug("assign: $raw_key @$arg # $comment"); # keys are case insensitive, try to find a match my $key = $self->current_node->find_element ($raw_key, case => 'any') ; if (not defined $key) { if ($check eq 'yes') { # drop if -force is not set die "Error: unknown parameter: '$raw_key'. Use -force option to drop this parameter\n"; } else { say "Dropping parameter '$raw_key'" ; } return; } my $elt = $self->current_node->fetch_element($key) ; my $type = $elt->get_type; #print "got $key type $type and ",join('+',@$arg),"\n"; $elt->annotation($comment) if $comment and $type ne 'hash'; if ($type eq 'leaf') { $elt->store( value => join(' ',@$arg), check => $check ) ; } elsif ($type eq 'list') { $elt->push_x ( values => $arg, check => $check ) ; } elsif ($type eq 'hash') { my $hv = $elt->fetch_with_id($arg->[0]); $hv->store( value => $arg->[1], check => $check ); $hv->annotation($comment) if $comment; } elsif ($type eq 'check_list') { my @check = split /\s*,\s*/,$arg->[0] ; $elt->set_checked_list (\@check, check => 'skip') ; } else { die "OpenSsh::assign did not expect $type for $key\n"; } } no Mouse; 1; # ABSTRACT: Role to read OpenSsh config files __END__ =head1 SYNOPSIS None. Consumed by L and L. =head1 DESCRIPTION Read methods used by both L and L. =head1 SEE ALSO L, L, L libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/Role/Writer.pm000066400000000000000000000072751477474553300300330ustar00rootroot00000000000000use strict; use warnings; package Config::Model::Backend::OpenSsh::Role::Writer ; use Mouse::Role ; with 'Config::Model::Backend::OpenSsh::Role::MatchBlock'; requires qw(write_global_comments write_data_and_comments); use 5.10.1; use Config::Model 2.128; use Carp ; use IO::File ; use Log::Log4perl 1.11; my $logger = Log::Log4perl::get_logger("Backend::OpenSsh"); sub ssh_write { my $self = shift ; my %args = @_ ; my $config_root = $args{object} || croak __PACKAGE__," ssh_write: undefined config root object"; $logger->info("writing config file $args{file_path}"); my $comment = $self->write_global_comment('#') ; my $result = $self->write_node_content($config_root,$args{ssh_mode}); if ($result) { $args{file_path}->spew_utf8($comment.$result); return 1; } return 0; } sub write_line { my ($self, $k, $v, $note) = @_ ; return '' unless length($v) ; return $self->write_data_and_comments('#',sprintf("%-20s %s",$k,$v),$note) ; } sub write_list { my ($self,$name,$mode,$elt) = @_; my @r = map { $self->write_line($name,$_->fetch($mode), $_->annotation) ;} $elt->fetch_all() ; return join('',@r) ; } sub write_list_in_one_line { my ($self,$name,$mode,$elt) = @_; my @v = $elt->fetch_all_values(mode => $mode) ; return $self->write_line($name,join(' ',@v)) ; } # list there list element that must be written on one line with items # separated by a white space my %list_as_one_line = ( 'AuthorizedKeysFile' => 1 , ) ; sub write_node_content { my $self= shift ; my $node = shift ; my $mode = shift || ''; my $result = '' ; my $match = '' ; foreach my $name ($node->get_element_name() ) { next unless $node->is_element_defined($name) ; my $elt = $node->fetch_element($name) ; my $type = $elt->get_type; my $note = $elt->annotation ; #print "got $key type $type and ",join('+',@arg),"\n"; if ($name eq 'Match') { $match .= $self->write_all_match_block($elt,$mode) ; } elsif ($name eq 'Host') { $match .= $self->write_all_host_block($elt,$mode) ; } elsif ($name =~ /^(Local|Remote)Forward$/) { foreach ($elt->fetch_all()) { $result .= $self->write_forward($_,$mode); } } elsif ($type eq 'leaf') { my $v = $elt->fetch($mode) ; $result .= $self->write_line($name,$v,$note); } elsif ($type eq 'check_list') { my $v = $elt->fetch($mode) ; $result .= $self->write_line($name,$v,$note); } elsif ($type eq 'list') { $result .= $self->write_data_and_comments('#', undef, $note) ; $result .= $list_as_one_line{$name} ? $self->write_list_in_one_line($name,$mode,$elt) : $self->write_list($name,$mode,$elt) ; } elsif ($type eq 'hash') { foreach my $k ( $elt->fetch_all_indexes ) { my $o = $elt->fetch_with_id($k); my $v = $o->fetch($mode) ; $result .= $self->write_line($name,"$k $v", $o->annotation) ; } } else { die "OpenSsh::write did not expect $type for $name\n"; } } return $result.$match ; } no Mouse; 1; # ABSTRACT: Role to write OpenSsh config files __END__ =head1 SYNOPSIS None. Consumed by L and L. =head1 DESCRIPTION Write methods used by both L and L. =head1 SEE ALSO L, L, L libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/Ssh.pm000066400000000000000000000114061477474553300264020ustar00rootroot00000000000000use strict; use warnings; package Config::Model::Backend::OpenSsh::Ssh ; use Mouse ; use 5.10.1; extends "Config::Model::Backend::Any" ; with ( 'Config::Model::Backend::OpenSsh::Role::Reader', 'Config::Model::Backend::OpenSsh::Role::Writer', ); use Carp ; use IO::File ; use Log::Log4perl; use File::Copy ; use File::Path ; use File::HomeDir ; my $logger = Log::Log4perl::get_logger("Backend::OpenSsh"); sub write { my $self = shift; $self->ssh_write(@_, ssh_mode => 'custom') ; } sub host { my ($self,$root,$key, $patterns,$comment) = @_; $logger->debug("host: pattern @$patterns # $comment"); my $hash_obj = $root->fetch_element('Host'); $logger->info("ssh: load host patterns '".join("','", @$patterns)."'"); my $hv = $hash_obj->fetch_with_id("@$patterns") ; $hv -> annotation($comment) if $comment ; $self->current_node($hv); } sub forward { my ($self, $root, $key, $args, $comment, $check) = @_; $logger->debug("forward: $key @$args # $comment"); $self->current_node = $root unless defined $self->current_node ; my $elt_name = $key =~ /local/i ? 'Localforward' : 'RemoteForward' ; my $v6 = ($args->[1] =~ m![/\[\]]!) ? 1 : 0; $logger->info("ssh: load $key '".join("','", @$args)."' ". ( $v6 ? 'IPv6' : 'IPv4')); # cleanup possible square brackets used for IPv6 foreach (@$args) { s/[\[\]]+//g; } # reverse enable to assign string to port even if no bind_adress # is specified my $re = $v6 ? qr!/! : qr!:! ; my ($port,$bind_adr ) = reverse split $re,$args->[0] ; my ($host,$host_port) = split $re,$args->[1] ; my $fw_list = $self->current_node->fetch_element($key); my $size = $fw_list->fetch_size; # this creates a new node in the list my $fw_obj = $fw_list->fetch_with_id($size); # $fw_obj->store_element_value( GatewayPorts => 1 ) if $bind_adr ; $fw_obj->annotation($comment) if $comment; $fw_obj->store_element_value( ipv6 => 1) if $v6 ; $fw_obj->store_element_value( check => $check, name => 'bind_address', value => $bind_adr) if defined $bind_adr ; $fw_obj->store_element_value( check => $check, name => 'port', value => $port ); $fw_obj->store_element_value( check => $check, name => 'host', value => $host ); $fw_obj->store_element_value( check => $check, name => 'hostport', value => $host_port ); } sub write_all_host_block { my $self = shift ; my $host_elt = shift ; my $mode = shift || ''; my $result = '' ; foreach my $pattern ( $host_elt->fetch_all_indexes) { my $block_elt = $host_elt->fetch_with_id($pattern) ; $logger->debug("write_all_host_block on ".$block_elt->location." mode $mode"); my $block_data = $self->write_node_content($block_elt,'custom') ; # write data only if custom pattern or custom data is found this # is necessary to avoid writing data from /etc/ssh/ssh_config that # were entered as 'preset' data if ($block_data) { $result .= $self->write_line(Host => $pattern, $block_elt->annotation); $result .= "$block_data\n" ; } } return $result ; } sub write_forward { my $self = shift ; my $forward_elt = shift ; my $mode = shift || ''; my $result = '' ; my $v6 = $forward_elt->grab_value('ipv6') ; my $sep = $v6 ? '/' : ':'; my $line = ''; foreach my $name ($forward_elt->get_element_name() ) { next if $name eq 'ipv6' ; my $elt = $forward_elt->fetch_element($name) ; my $v = $elt->fetch($mode) ; next unless length($v); $line .= $name =~ /bind|host$/ ? "$v$sep" : $name eq 'port' ? "$v " : $v ; } return $self->write_line($forward_elt->element_name,$line,$forward_elt->annotation) ; } no Mouse; 1; # ABSTRACT: Backend for ssh configuration files __END__ =head1 SYNOPSIS None =head1 DESCRIPTION This module provides a backend to read and write ssh client configuration files. =head1 STOP The documentation provides details on the module used to read and write OpenSsh configuration files. These details are not needed for the basic usages explained in L. =head1 Methods These read/write functions are part of C read/write backend. They are declared in Ssh configuration model and are called back when needed to read and write the configuration file. =head2 read (object => , config_dir => ...) Reads F in C and load the data in the C configuration tree. =head2 write (object => , config_dir => ...) Write F in C from the data stored in C configuration tree. =head1 SEE ALSO L, L, L libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/Backend/OpenSsh/Sshd.pm000066400000000000000000000015001477474553300265400ustar00rootroot00000000000000use strict; use warnings; package Config::Model::Backend::OpenSsh::Sshd ; use Mouse ; extends "Config::Model::Backend::Any" ; with ( 'Config::Model::Backend::OpenSsh::Role::Reader', 'Config::Model::Backend::OpenSsh::Role::Writer', ); use Carp ; use IO::File ; use Log::Log4perl; use File::Copy ; use File::Path ; my $logger = Log::Log4perl::get_logger("Backend::OpenSsh"); # now the write part sub write { my $self = shift; $self->ssh_write(@_) ; } sub _write_line { return sprintf("%-20s %s\n",@_) ; } no Mouse; 1; # ABSTRACT: Backend for sshd configuration files __END__ =head1 SYNOPSIS None =head1 DESCRIPTION This class provides a backend to read and write sshd client configuration files. This class is a plugin for L. =head1 SEE ALSO L, L, libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/OpenSsh.pm000066400000000000000000000031631477474553300243170ustar00rootroot00000000000000use strict; use warnings; package Config::Model::OpenSsh ; use Config::Model 2.111; 1; # ABSTRACT: OpenSSH config editor __END__ =head1 SYNOPSIS =head2 invoke editor The following launches a graphical editor (if L is installed): sudo cme edit sshd =head2 command line This command adds a C section in C<~/.ssh/config>: cme modify ssh Host:Foo ForwardX11=yes =head2 programmatic This code snippet removes the C section added above: use Config::Model ; my $model = Config::Model->new() ; my $inst = $model->instance (root_class_name => 'Ssh'); $inst -> config_root->load("Host~Foo") ; $inst->write_back() ; =head1 DESCRIPTION This module provides a configuration editor (and models) for the configuration files of OpenSSH. (C, C and C<~/.ssh/config>). This module can also be used to modify safely the content of these configuration files from a Perl program. Once this module is installed, you can edit C with (as root) : # cme edit sshd To edit F, run (as root): # cme edit ssh To edit F<~/.ssh/config>, run as a normal user: $ cme edit ssh =head1 user interfaces As mentioned in L, several user interfaces are available with C subcommand: =over =item * A graphical interface is proposed by default if L is installed. =item * A Curses interface with option C if L is installed. =item * A Shell like interface with option C. =back =head1 SEE ALSO L, L, libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/000077500000000000000000000000001477474553300236625ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Ssh.pl000066400000000000000000000114651477474553300247630ustar00rootroot00000000000000use strict; use warnings; return [ { 'accept' => [ '.*', { 'summary' => 'boilerplate parameter that may hide a typo', 'type' => 'leaf', 'value_type' => 'uniline', 'warn' => 'Unknown parameter. Please make sure there\'s no typo and contact the author' } ], 'class_description' => 'This configuration class was generated from ssh_system documentation. by L ', 'element' => [ 'Host', { 'cargo' => { 'config_class_name' => 'Ssh::HostElement', 'type' => 'node' }, 'description' => 'Restricts the following declarations (up to the next B or B keyword) to be only for those hosts that match one of the patterns given after the keyword. If more than one pattern is provided, they should be separated by whitespace. A single \'*\' as a pattern can be used to provide global defaults for all hosts. The host is usually the I argument given on the command line (see the B keyword for exceptions). A pattern entry may be negated by prefixing it with an exclamation mark (\'!\' ) If a negated entry is matched, then the B entry is ignored, regardless of whether any other patterns on the line match. Negated matches are therefore useful to provide exceptions for wildcard matches. See I for more information on patterns.', 'index_type' => 'string', 'ordered' => '1', 'type' => 'hash' }, 'Match', { 'cargo' => { 'config_class_name' => 'Ssh::HostElement', 'type' => 'node' }, 'description' => 'Restricts the following declarations (up to the next B or B keyword) to be used only when the conditions following the B keyword are satisfied. Match conditions are specified using one or more criteria or the single token B which always matches. The available criteria keywords are: B B B B B B B B and B The B criteria must appear alone or immediately after B or B Other criteria may be combined arbitrarily. All criteria but B B and B require an argument. Criteria may be negated by prepending an exclamation mark (\'!\' ) The B keyword matches only when the configuration file is being re-parsed after hostname canonicalization (see the B option). This may be useful to specify conditions that work with canonical host names only. The B keyword requests that the configuration be re-parsed (regardless of whether B is enabled), and matches only during this final pass. If B is enabled, then B and B match during the same pass. The B keyword executes the specified command under the user\'s shell. If the command returns a zero exit status then the condition is considered true. Commands containing whitespace characters must be quoted. Arguments to B accept the tokens described in the I section. The B keyword matches the addresses of active local network interfaces against the supplied list of networks in CIDR format. This may be convenient for varying the effective configuration on devices that roam between networks. Note that network address is not a trustworthy criteria in many situations (e.g. when the network is automatically configured using DHCP) and so caution should be applied if using it to control security-sensitive configuration. The other keywords\' criteria must be single entries or comma-separated lists and may use the wildcard and negation operators described in the I section. The criteria for the B keyword are matched against the target hostname, after any substitution by the B or B options. The B keyword matches against the hostname as it was specified on the command-line. The B keyword matches a tag name specified by a prior B directive or on the L command-line using the -B

flag. The B keyword matches against the target username on the remote host. The B keyword matches against the name of the local user running L (this keyword may be useful in system-wide B files).', 'index_type' => 'string', 'ordered' => '1', 'type' => 'hash' } ], 'generated_by' => 'parse-man.pl from ssh_system 9.9p2 doc', 'include' => [ 'Ssh::HostElement' ], 'include_after' => 'Host', 'license' => 'LGPL2', 'name' => 'Ssh', 'rw_config' => { 'auto_create' => '1', 'backend' => 'OpenSsh::Ssh', 'config_dir' => '~/.ssh', 'file' => 'config' } } ] ; libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Ssh/000077500000000000000000000000001477474553300244175ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Ssh/HostElement.pl000066400000000000000000002267171477474553300272220ustar00rootroot00000000000000use strict; use warnings; return [ { 'accept' => [ '.*', { 'summary' => 'boilerplate parameter that may hide a typo', 'type' => 'leaf', 'value_type' => 'uniline', 'warn' => 'Unknown parameter. Please make sure there\'s no typo and contact the author' } ], 'class_description' => 'This configuration class was generated from ssh_system documentation. by L ', 'element' => [ 'AddKeysToAgent', { 'choice' => [ 'ask', 'confirm', 'no', 'yes' ], 'description' => 'Specifies whether keys should be automatically added to a running ssh-agent1. If this option is set to B and a key is loaded from a file, the key and its passphrase are added to the agent with the default lifetime, as if by ssh-add1. If this option is set to B L will require confirmation using the B program before adding a key (see ssh-add1 for details). If this option is set to B each use of the key must be confirmed, as if the -B option was specified to ssh-add1. If this option is set to B no keys are added to the agent. Alternately, this option may be specified as a time interval using the format described in the I

The match patterns may consist of single entries or comma-separated lists and may use the wildcard and negation operators described in the I section of ssh_config5. The patterns in an B
criteria may additionally contain addresses to match in CIDR address/masklen format, such as 192.0.2.0/24 or 2001:db8::/32. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. Only a subset of keywords may be used on the lines following a B keyword. Available keywords are B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B and B', 'type' => 'list' }, 'MaxStartups', { 'description' => 'Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the B expires for a connection. The default is 10:30:100. Alternatively, random early drop can be enabled by specifying the three colon separated values start:rate:full (e.g. "10:30:60"). L will refuse connection attempts with a probability of rate/100 (30%) if there are currently start (10) unauthenticated connections. The probability increases linearly and all connection attempts are refused if the number of unauthenticated connections reaches full (60).', 'type' => 'leaf', 'upstream_default' => '10', 'value_type' => 'uniline' }, 'ModuliFile', { 'description' => 'Specifies the L file that contains the Diffie-Hellman groups used for the \'\'diffie-hellman-group-exchange-sha1\'\' and \'\'diffie-hellman-group-exchange-sha256\'\' key exchange methods. The default is /etc/ssh/moduli', 'type' => 'leaf', 'upstream_default' => '/etc/ssh/moduli', 'value_type' => 'uniline' }, 'PermitUserEnvironment', { 'description' => 'Specifies whether ~/.ssh/environment and B options in ~/.ssh/authorized_keys are processed by L. Valid options are B B or a pattern-list specifying which environment variable names to accept (for example Qq LANG, LC_* ) . The default is B Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as B', 'type' => 'leaf', 'upstream_default' => 'no', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'PerSourceMaxStartups', { 'description' => 'Specifies the number of unauthenticated connections allowed from a given source address, or \'\'none\'\' if there is no limit. This limit is applied in addition to B whichever is lower. The default is B', 'type' => 'leaf', 'upstream_default' => 'none', 'value_type' => 'uniline' }, 'PerSourceNetBlockSize', { 'description' => 'Specifies the number of bits of source address that are grouped together for the purposes of applying PerSourceMaxStartups limits. Values for IPv4 and optionally IPv6 may be specified, separated by a colon. The default is B<32:128> which means each address is considered individually.', 'type' => 'leaf', 'upstream_default' => '32:128', 'value_type' => 'uniline' }, 'PerSourcePenalties', { 'description' => 'Controls penalties for various conditions that may represent attacks on L. If a penalty is enforced against a client then its source address and any others in the same network, as defined by B will be refused connection for a period. A penalty doesn\'t affect concurrent connections in progress, but multiple penalties from the same source from concurrent connections will accumulate up to a maximum. Conversely, penalties are not applied until a minimum threshold time has been accumulated. Penalties are enabled by default with the default settings listed below but may disabled using the B keyword. The defaults may be overridden by specifying one or more of the keywords below, separated by whitespace. All keywords accept arguments, e.g. Qq crash:2m . B Specifies how long to refuse clients that cause a crash of L(default:90s). B Specifies how long to refuse clients that disconnect after making one or more unsuccessful authentication attempts (default: 5s). B Specifies how long to refuse clients that were administratively prohibited connection via the B option (default: 10s). B Specifies how long to refuse clients that disconnect without attempting authentication (default: 1s). This timeout should be used cautiously otherwise it may penalise legitimate scanning tools such as ssh-keyscan1. B Specifies how long to refuse clients that fail to authenticate after B (default: 10s). B Specifies the maximum time a particular source address range will be refused access for (default: 10m). Repeated penalties will accumulate up to this maximum. B Specifies the minimum penalty that must accrue before enforcement begins (default: 15s). B Specifies the maximum number of client IPv4 and IPv6 address ranges to track for penalties (default: 65536 for both). B Controls how the server behaves when B or B is exceeded. There are two operating modes: B which denies all incoming connections other than those exempted via B until a penalty expires, and B which allows new connections by removing existing penalties early (default: permissive). Note that client penalties below the B threshold count against the total number of tracked penalties. IPv4 and IPv6 addresses are tracked separately, so an overflow in one will not affect the other. B Allows specifying a different overflow mode for IPv6 addresses. The default it to use the same overflow mode as was specified for IPv4.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'PerSourcePenaltyExemptList', { 'description' => 'Specifies a comma-separated list of addresses to exempt from penalties. This list may contain wildcards and CIDR address/masklen ranges. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. The default is not to exempt any addresses.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'PidFile', { 'description' => 'Specifies the file that contains the process ID of the SSH daemon, or B to not write one. The default is /run/sshd.pid', 'type' => 'leaf', 'upstream_default' => '/run/sshd', 'value_type' => 'uniline' }, 'Port', { 'description' => 'Specifies the port number that L listens on. The default is 22. Multiple options of this type are permitted. See also B', 'type' => 'leaf', 'value_type' => 'uniline' }, 'PrintLastLog', { 'description' => 'Specifies whether L should print the date and time of the last user login when a user logs in interactively. The default is B', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'PrintMotd', { 'description' => 'Specifies whether L should print /etc/motd when a user logs in interactively. (On some systems it is also printed by the shell, /etc/profile or equivalent.) The default is B', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'RequiredRSASize', { 'description' => 'Specifies the minimum RSA key size (in bits) that L will accept. User and host-based authentication keys smaller than this limit will be refused. The default is B<1024> bits. Note that this limit may only be raised from the default.', 'type' => 'leaf', 'upstream_default' => '1024', 'value_type' => 'integer' }, 'SecurityKeyProvider', { 'description' => 'Specifies a path to a library that will be used when loading FIDO authenticator-hosted keys, overriding the default of using the built-in USB HID support.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'SshdSessionPath', { 'description' => 'Overrides the default path to the B binary that is invoked to handle each connection. The default is /usr/lib/openssh/sshd-session This option is intended for use by tests.', 'type' => 'leaf', 'upstream_default' => '/usr/lib/openssh/sshd', 'value_type' => 'uniline' }, 'StrictModes', { 'description' => 'Specifies whether L should check file modes and ownership of the user\'s files and home directory before accepting login. This is normally desirable because novices sometimes accidentally leave their directory or files world-writable. The default is B Note that this does not apply to B whose permissions and ownership are checked unconditionally.', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'Subsystem', { 'cargo' => { 'mandatory' => '1', 'type' => 'leaf', 'value_type' => 'uniline' }, 'description' => 'Configures an external subsystem (e.g. file transfer daemon). Arguments should be a subsystem name and a command (with optional arguments) to execute upon subsystem request. The command B implements the SFTP file transfer subsystem. Alternately the name B implements an in-process SFTP server. This may simplify configurations using B to force a different filesystem root on clients. It accepts the same command line arguments as B and even though it is in-process, settings such as B or B do not apply to it and must be set explicitly via command line arguments. By default no subsystems are defined.', 'index_type' => 'string', 'type' => 'hash' }, 'SyslogFacility', { 'choice' => [ 'AUTH', 'DAEMON', 'LOCAL0', 'LOCAL1', 'LOCAL2', 'LOCAL3', 'LOCAL4', 'LOCAL5', 'LOCAL6', 'LOCAL7', 'USER' ], 'description' => 'Gives the facility code that is used when logging messages from L. The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH.', 'type' => 'leaf', 'upstream_default' => 'AUTH', 'value_type' => 'enum' }, 'TCPKeepAlive', { 'description' => 'Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, this means that connections will die if the route is down temporarily, and some people find it annoying. On the other hand, if TCP keepalives are not sent, sessions may hang indefinitely on the server, leaving Qq ghost users and consuming server resources. The default is B (to send TCP keepalive messages), and the server will notice if the network goes down or the client host crashes. This avoids infinitely hanging sessions. To disable TCP keepalive messages, the value should be set to B This option was formerly called B', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'UseDNS', { 'description' => 'Specifies whether L should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address. If this option is set to B (the default) then only addresses and not host names may be used in ~/.ssh/authorized_keys B and B B B directives.', 'type' => 'leaf', 'upstream_default' => 'no', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'UsePAM', { 'description' => 'Enables the Pluggable Authentication Module interface. If set to B this will enable PAM authentication using B and B in addition to PAM account and session module processing for all authentication types. Because PAM keyboard-interactive authentication usually serves an equivalent role to password authentication, you should disable either B or B If B is enabled, you will not be able to run L as a non-root user. The default is B', 'type' => 'leaf', 'upstream_default' => 'no', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'VersionAddendum', { 'description' => 'Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection. The default is B', 'type' => 'leaf', 'value_type' => 'uniline' }, 'XAuthLocation', { 'description' => 'Specifies the full pathname of the L program, or B to not use one. The default is /usr/bin/xauth', 'type' => 'leaf', 'upstream_default' => '/usr/bin/xauth', 'value_type' => 'uniline' } ], 'generated_by' => 'parse-man.pl from sshd_system 9.9p2 doc', 'include' => [ 'Sshd::MatchElement' ], 'license' => 'LGPL2', 'name' => 'Sshd', 'rw_config' => { 'backend' => 'OpenSsh::Sshd', 'config_dir' => '/etc/ssh', 'file' => 'sshd_config', 'os_config_dir' => { 'darwin' => '/etc' } } } ] ; libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Sshd/000077500000000000000000000000001477474553300245635ustar00rootroot00000000000000libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Sshd/MatchBlock.pl000066400000000000000000000016721477474553300271350ustar00rootroot00000000000000use strict; use warnings; return [ { 'author' => [ 'Dominique Dumont' ], 'class_description' => 'Class to represent a Match block inside a sshd_config file. It\'s made of a list of conditions to match and a list of parameters to apply to the matched items.', 'copyright' => [ '2009-2011 Dominique Dumont' ], 'element' => [ 'Condition', { 'config_class_name' => 'Sshd::MatchCondition', 'description' => 'Specify the condition (User, Group, Host, Address) necessary for this Match block to be applied', 'type' => 'node' }, 'Settings', { 'config_class_name' => 'Sshd::MatchElement', 'description' => 'Defines the sshd_config parameters that will override general settings when all defined User, Group, Host and Address patterns match.', 'type' => 'node' } ], 'license' => 'LGPL2', 'name' => 'Sshd::MatchBlock' } ] ; libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Sshd/MatchCondition.pl000066400000000000000000000025121477474553300300230ustar00rootroot00000000000000use strict; use warnings; return [ { 'author' => [ 'Dominique Dumont' ], 'class_description' => 'Conidtion to apply to identify matched items inside a sshd_config match block.', 'copyright' => [ '2009-2011 Dominique Dumont' ], 'element' => [ 'User', { 'description' => 'Define the User criteria of a conditional block. The value of this field is a pattern that is tested against user name.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'Group', { 'description' => 'Define the Group criteria of a conditional block. The value of this field is a pattern that is tested against group name.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'Host', { 'description' => 'Define the Host criteria of a conditional block. The value of this field is a pattern that is tested against host name.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'Address', { 'description' => 'Define the Address criteria of a conditional block. The value of this field is a pattern that is tested against the address of the incoming connection.', 'type' => 'leaf', 'value_type' => 'uniline' } ], 'license' => 'LGPL2', 'name' => 'Sshd::MatchCondition' } ] ; libconfig-model-openssh-perl-2.9.9.1/lib/Config/Model/models/Sshd/MatchElement.pl000066400000000000000000001361671477474553300275040ustar00rootroot00000000000000use strict; use warnings; return [ { 'accept' => [ '.*', { 'summary' => 'boilerplate parameter that may hide a typo', 'type' => 'leaf', 'value_type' => 'uniline', 'warn' => 'Unknown parameter. Please make sure there\'s no typo and contact the author' } ], 'class_description' => 'This configuration class was generated from sshd_system documentation. by L ', 'element' => [ 'AcceptEnv', { 'cargo' => { 'type' => 'leaf', 'value_type' => 'uniline' }, 'description' => 'Specifies what environment variables sent by the client will be copied into the session\'s L. See B and B in ssh_config5 for how to configure the client. The B environment variable is always accepted whenever the client requests a pseudo-terminal as it is required by the protocol. Variables are specified by name, which may contain the wildcard characters \'*\' and \'?\' Multiple environment variables may be separated by whitespace or spread across multiple B directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be taken in the use of this directive. The default is not to accept any environment variables.', 'type' => 'list' }, 'AllowAgentForwarding', { 'description' => 'Specifies whether ssh-agent1 forwarding is permitted. The default is B Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'boolean', 'write_as' => [ 'no', 'yes' ] }, 'AllowGroups', { 'cargo' => { 'type' => 'leaf', 'value_type' => 'uniline' }, 'description' => 'This keyword can be followed by a list of group name patterns, separated by spaces. If specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: B B See PATTERNS in ssh_config5 for more information on patterns. This keyword may appear multiple times in B with each instance appending to the list.', 'type' => 'list' }, 'AllowStreamLocalForwarding', { 'choice' => [ 'all', 'local', 'no', 'remote', 'yes' ], 'description' => 'Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. The available options are B (the default) or B to allow StreamLocal forwarding, B to prevent all StreamLocal forwarding, B to allow local (from the perspective of L) forwarding only or B to allow remote forwarding only. Note that disabling StreamLocal forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'enum' }, 'AllowTcpForwarding', { 'choice' => [ 'all', 'local', 'no', 'remote', 'yes' ], 'description' => 'Specifies whether TCP forwarding is permitted. The available options are B (the default) or B to allow TCP forwarding, B to prevent all TCP forwarding, B to allow local (from the perspective of L) forwarding only or B to allow remote forwarding only. Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.', 'type' => 'leaf', 'upstream_default' => 'yes', 'value_type' => 'enum' }, 'AllowUsers', { 'cargo' => { 'type' => 'leaf', 'value_type' => 'uniline' }, 'description' => 'This keyword can be followed by a list of user name patterns, separated by spaces. If specified, login is allowed only for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: B B See PATTERNS in ssh_config5 for more information on patterns. This keyword may appear multiple times in B with each instance appending to the list.', 'type' => 'list' }, 'AuthenticationMethods', { 'description' => 'Specifies the authentication methods that must be successfully completed for a user to be granted access. This option must be followed by one or more lists of comma-separated authentication method names, or by the single string B to indicate the default behaviour of accepting any single authentication method. If the default is overridden, then successful authentication requires completion of every method in at least one of these lists. For example, Qq publickey, password publickey, keyboard-interactive would require the user to complete public key authentication, followed by either password or keyboard interactive authentication. Only methods that are next in one or more lists are offered at each stage, so for this example it would not be possible to attempt password or keyboard-interactive authentication before public key. For keyboard interactive authentication it is also possible to restrict authentication to a specific device by appending a colon followed by the device identifier B or B depending on the server configuration. For example, Qq keyboard-interactive:bsdauth would restrict keyboard interactive authentication to the B device. If the publickey method is listed more than once, L verifies that keys that have been used successfully are not reused for subsequent authentications. For example, Qq publickey, publickey requires successful authentication using two different public keys. Note that each authentication method listed should also be explicitly enabled in the configuration. The available authentication methods are: Qq gssapi-with-mic , Qq hostbased , Qq keyboard-interactive , Qq none (used for access to password-less accounts when B is enabled), Qq password and Qq publickey .', 'type' => 'leaf', 'value_type' => 'uniline' }, 'AuthorizedKeysCommand', { 'description' => 'Specifies a program to be used to look up the user\'s public keys. The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to B accept the tokens described in the I section. If no arguments are specified then the username of the target user is used. The program should produce on standard output zero or more lines of authorized_keys output (see I in L). B is tried after the usual B files and will not be executed if a matching key is found there. By default, no B is run.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'AuthorizedKeysCommandUser', { 'description' => 'Specifies the user under whose account the B is run. It is recommended to use a dedicated user that has no other role on the host than running authorized keys commands. If B is specified but B is not, then L will refuse to start.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'AuthorizedKeysFile', { 'cargo' => { 'type' => 'leaf', 'value_type' => 'uniline' }, 'description' => 'Specifies the file that contains the public keys used for user authentication. The format is described in the AUTHORIZED_KEYS FILE FORMAT section of L. Arguments to B accept the tokens described in the I section. After expansion, B is taken to be an absolute path or one relative to the user\'s home directory. Multiple files may be listed, separated by whitespace. Alternately this option may be set to B to skip checking for user keys in files. The default is Qq .ssh/authorized_keys .ssh/authorized_keys2 .', 'migrate_values_from' => '- AuthorizedKeysFile2', 'type' => 'list' }, 'AuthorizedPrincipalsCommand', { 'description' => 'Specifies a program to be used to generate the list of allowed certificate principals as per B The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to B accept the tokens described in the I section. If no arguments are specified then the username of the target user is used. The program should produce on standard output zero or more lines of B output. If either B or B is specified, then certificates offered by the client for authentication must contain a principal that is listed. By default, no B is run.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'AuthorizedPrincipalsCommandUser', { 'description' => 'Specifies the user under whose account the B is run. It is recommended to use a dedicated user that has no other role on the host than running authorized principals commands. If B is specified but B is not, then L will refuse to start.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'AuthorizedPrincipalsFile', { 'description' => 'Specifies a file that lists principal names that are accepted for certificate authentication. When using certificates signed by a key listed in B this file lists names, one of which must appear in the certificate for it to be accepted for authentication. Names are listed one per line preceded by key options (as described in I in L). Empty lines and comments starting with \'#\' are ignored. Arguments to B accept the tokens described in the I section. After expansion, B is taken to be an absolute path or one relative to the user\'s home directory. The default is B i.e. not to use a principals file - in this case, the username of the user must appear in a certificate\'s principals list for it to be accepted. Note that B is only used when authentication proceeds using a CA listed in B and is not consulted for certification authorities trusted via ~/.ssh/authorized_keys though the B key option offers a similar facility (see L for details).', 'type' => 'leaf', 'upstream_default' => 'none', 'value_type' => 'uniline' }, 'Banner', { 'description' => 'The contents of the specified file are sent to the remote user before authentication is allowed. If the argument is B then no banner is displayed. By default, no banner is displayed.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'CASignatureAlgorithms', { 'description' => 'Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, rsa-sha2-512, rsa-sha2-256 If the specified list begins with a \'+\' character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a \'-\' character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. Certificates signed using other algorithms will not be accepted for public key or host-based authentication.', 'type' => 'leaf', 'value_type' => 'uniline' }, 'ChannelTimeout', { 'description' => 'Specifies whether and how quickly L should close inactive channels. Timeouts are specified as one or more \'\'type=interval\'\' pairs separated by whitespace, where the \'\'type\'\' must be the special keyword \'\'global\'\' or a channel type name from the list below, optionally containing wildcard characters. The timeout value \'\'interval\'\' is specified in seconds or may use any of the units documented in the I