In Chapter 5, we described the server configuration files in detail, including OpenSSH's sshd_config and Tectia's sshd2_config. Tectia provides several levels of configuration not found in OpenSSH, called metaconfiguration and subconfiguration, and also some unusual rules for quoted values. We now cover them in detail.
Tectia recognizes specially structured comments at the beginning of configuration files. These lines determine the syntax rules for the rest of the file, and are therefore called metaconfiguration information.
Configuration files distributed with Tectia all start with lines of the form:
## SSH CONFIGURATION FILE FORMAT VERSION 1.1 ## REGEX-SYNTAX egrep ## end of metaconfig ## (leave above lines intact!)
The first line specifies the syntax version number, and defines the start of the metaconfiguration information. Increasing syntax version numbers allow the syntax rules to be extended, possibly in incompatible ways. As long as older configuration files explicitly specify their syntax versions, they can still be correctly understood by newer versions of the Tectia server.
The default syntax version (used if there is no metaconfiguration information) is 1.0. This refers to the "traditional" syntax rules understood by Tectia versions before Version 3.0.0 (when the metaconfiguration information syntax was introduced). The latest syntax version at press time is 1.1.
Syntax rules are further refined by lines that immediately follow the syntax version. These lines contain pairs of metaconfiguration parameter names and values, and look similar to the keyword lines in the rest of the configuration file, with two important differences:
The pairs occur within comment lines.
The metaconfiguration parameter names must always be uppercase.
Syntax Version 1.1 adds support for the REGEX-SYNTAX
parameter, which determines how
regular expressions are interpreted. The three standards are:
These values are case-insensitive, unlike the parameter names. Full syntax rules are described in Appendix B.
Metaconfiguration information ends when an unrecognized comment
line (or a standard, uncommented keyword line) is encountered. It's a
good idea to mark the end with an ordinary comment line (like "end of
metaconfig" as shown earlier) that does not look like a
metaconfiguration parameter, to prevent possible misinterpretation of
adjacent comment lines and to enhance readability. Use of ##
instead of #
is just a stylistic convention to allow
the metaconfiguration information to be more easily distinguished from
unrelated comments.
It is sometimes useful to customize the SSH server configuration depending on the type of connection or session. For example, a system administrator might want to impose stronger authentication requirements if a connection originates from a client outside of a firewall, or to record more detailed logging information about the activities of special-purpose guest accounts.
Tectia servers support these kinds of conditional configuration modifications with host-and user-specific configuration files, which are known collectively as subconfiguration files . The subconfiguration files use the same syntax as the main configuration file, except as noted later. Each file starts with its own, independent metaconfiguration information.
The HostSpecificConfig
keyword is used to update the configuration based on the client
host:
# Tectia with zsh_fileglob or traditional regex syntax HostSpecificConfig *.example.com /etc/ssh2/subconfig/ourhosts # Tectia with egrep regex syntax HostSpecificConfig .*\.example\.com /etc/ssh2/subconfig/ourhosts
The first value is a pattern that matches hostnames or
addresses, as described for the AllowHosts
keyword. [5.5.3] For example, if all of
the machines inside a firewall are assigned to a range of addresses,
it might be convenient to use a netmask for the pattern:
# Tectia HostSpecificConfig \m10.1.1.0/24 /etc/ssh2/subconfig/insiders
The second value is the filename containing the host-specific configuration.
Similarly, the UserSpecificConfig
keyword specifies a
pattern describing user accounts, and the filename with user-specific
configuration settings that apply to those accounts. In the simplest
case, the pattern matches usernames or numerical user IDs, as for the
AllowUsers
keyword: [5.5.1]
# Tectia with zsh_fileglob or traditional regex syntax UserSpecificConfig guest[[:digit:]]## /etc/ssh2/subconfig/guests # Tectia with egrep regex syntax UserSpecificConfig guest[[:digit:]]+ /etc/ssh2/subconfig/guests # Tectia UserSpecificConfig 12[3-6][[:digit:]] /etc/ssh2/subconfig/guests
More generally, patterns have the form
user[%group][@host].
The optional group matches either group names or
numerical group IDs, as for the AllowGroup
keyword: [5.5.2]
# Tectia with zsh_fileglob or traditional regex syntax UserSpecificConfig *%[x-z]guests /etc/ssh2/subconfig/xyz-guests UserSpecificConfig *%800[[:digit:]] /etc/ssh2/subconfig/guests-8k # Tectia with egrep regex syntax UserSpecificConfig .*%[x-z]guests /etc/ssh2/subconfig/xyz-guests UserSpecificConfig .*%800[[:digit:]] /etc/ssh2/subconfig/guests-8k
Users can (and often do) belong to multiple groups: they are all checked.
The optional host matches the client
hostname or address, as for the AllowHosts
keyword [5.5.3] or HostSpecificConfig
:
# Tectia with zsh_fileglob or traditional regex syntax UserSpecificConfig guest@*.friendly.org /etc/ssh2/subconfig/friends UserSpecificConfig *%trusted@\m10.1.1.0/24 /etc/ssh2/subconfig/trusted-insiders # Tectia with egrep regex syntax UserSpecificConfig guest@.*\.friendly\.org /etc/ssh2/subconfig/friends UserSpecificConfig .*%trusted@\m10.1.1.0/24 /etc/ssh2/subconfig/trusted-insiders
The user cannot be omitted from the pattern. If the pattern has two or more components (user, group, or host), then all of them must match for the user-specific configuration to be read.
The Tectia server starts by reading the main configuration file, and sets up the default configuration, which can include references to the subconfiguration files, and an associated pattern for each. When a connection is accepted from a client host, the server forks, and the child process that handles the session inherits its own private copy of the configuration. This private configuration is discarded when the child process exits at the end of the session, so the private configuration can be modified without affecting the default configuration that is used as the starting point for other sessions.[153]
The metaconfiguration parameters are not considered part of the configuration and are not inherited by subconfiguration files. Metaconfiguration information is independently associated with each file, because it describes the syntax of that file's contents. Although it's possible to use different metaconfiguration parameters for subconfiguration files, this is confusing, and we strongly recommend starting each subconfiguration file with the same, explicit metaconfiguration information as the main configuration file.
Immediately after the server accepts a new connection, but
before any conversation ensues with the client, the server uses the
client hostname or address to check the patterns for all HostSpecificConfig
keywords, in the order
that they were specified in the main configuration file. The server
reads each host-specific configuration file for patterns that match,
and modifies its private configuration as it does so.
Later, when the username has been specified by the client (and
group memberships have been determined by the server for the user),
the server checks the patterns for all UserSpecificConfig
keywords, again in the
order indicated by the main configuration file, and reads
user-specific configuration files for matching patterns to further
customize the configuration.
The order for reading the configuration files is important because it determines how keywords apply to the final configuration that is used for each session. Keywords that are read later either override or append to the values for earlier keywords—this principle applies whether the keywords appear multiple times in a single file, or in separate files.
For example, suppose our main configuration file contains:[154]
# Tectia: /etc/ssh2/sshd2_config PasswordGuesses 1 UserSpecificConfig guest[[:digit:]]+ /etc/ssh2/subconfig/guests UserSpecificConfig .*%[x-z]guests /etc/ssh2/subconfig/xyz-guests HostSpecificConfig .*\.example\.com /etc/ssh2/subconfig/ourhosts HostSpecificConfig .*\.foo\.example\.com /etc/ssh2/subconfig/foohosts PasswordGuesses 2
When the server starts, it reads this main configuration file,
and sets the value for the PasswordGuesses
keyword first to 1
, and then to 2
. The server also records the filenames and
patterns for the subconfiguration files.
Later, the server checks the patterns for the host-specific configuration files, in order. If a connection is accepted from laptop.foo.example.com, then both host patterns match. So, if the files contain:
# Tectia: /etc/ssh2/subconfig/ourhosts PasswordGuesses 3 # Tectia: /etc/ssh2/subconfig/foohosts PasswordGuesses 4
then the value for the PasswordGuesses
keyword is overridden to
3
, and subsequently to 4
.
Finally, the server checks the patterns for the user-specific configuration files, again in order. If the client specifies the username as guest33, and the server determines that this user belongs to the group yguests, then both user patterns match. So, if the files contain:
# Tectia: /etc/ssh2/subconfig/guests PasswordGuesses 5 # Tectia: /etc/ssh2/subconfig/xyz-guests PasswordGuesses 6
then the value for the PasswordGuesses
keyword is overridden to
5
, and eventually to 6
, which is the value that is actually used
for authentication.
The order for reading keywords is determined primarily by the
order for reading files, and secondarily by the order of occurrence of
the individual keywords within each file. In our example, even though
the last PasswordGuesses
keyword in
the main configuration file appears after the subconfiguration
keywords, the settings in the subconfiguration files still override
the default configuration. Similarly, even though UserSpecificConfig
keywords appear before
HostSpecificConfig
keywords in the
main configuration file, the server always reads host-specific
configuration files before user-specific configuration files.
It's therefore a good idea to order the keywords in the main
configuration file to reflect the order imposed by reading
subconfiguration files, with default settings first, followed by
HostSpecificConfig
and UserSpecificConfig
keywords at the end. Our
example would be more clearly written as:[155]
# Tectia: /etc/ssh2/sshd2_config PasswordGuesses 2 HostSpecificConfig .*\.example\.com /etc/ssh2/subconfig/ourhosts HostSpecificConfig .*\.foo\.example\.com /etc/ssh2/subconfig/foohosts UserSpecificConfig guest[[:digit:]]+ /etc/ssh2/subconfig/guests UserSpecificConfig .*%[x-z]guests /etc/ssh2/subconfig/xyz-guests
Because host- and user-specific configuration files are read in the order specified in the main configuration file, the patterns should be listed starting with general patterns first, followed by increasingly specific patterns.[156] Patterns can be carefully constructed and ordered to encode arbitrarily complicated logic for customizing almost any aspect of the configuration based on the client host, users, or groups: a very powerful feature.
Subconfiguration files can be further divided into
sections , which are marked by even more specific patterns, each
followed by a colon, on separate lines.[157] The keywords in each section are used only if the
pattern for the section matches. Sections end when a new pattern line
is encountered, or at the end of the subconfiguration file. The
section patterns in host- and user-specific configuration files are
interpreted in the same way as the patterns for the HostSpecificConfig
and UserSpecificConfig
keywords, in the main
configuration file, respectively.
Sections are a useful alternative to separate subconfiguration files. We might choose to combine the host-specific configuration files from our original example as:
# Tectia: /etc/ssh2/subconfig/ourhosts PasswordGuesses 3 # ... other general keywords for all hosts in example.com .*\.foo\.example\.com: PasswordGuesses 4 # ... other more specific keywords for foo.example.com .*\.bar\.example\.com: PasswordGuesses 8 # ... other more specific keywords for bar.example.com .*\.baz\.example\.com: PasswordGuesses 9 # ... other more specific keywords for baz.example.com
This is especially convenient if there are many general keywords for the primary domain, but only a few, more specific keywords for each subdomain. It's also handy if there are lots of subdomains, because we can add or remove subdomains without modifying the main configuration file.
Sections cannot be used in the main configuration file. This makes sense: it isn't at all clear what would be used to match such patterns. The server warns if any section pattern lines are detected in configuration files where sections are inappropriate, like the main configuration file.
Sections for user-specific configuration files work similarly. We can override settings for specific users:
# Tectia: /etc/ssh2/subconfig/guests PasswordGuesses 5 # ... other general keywords for all guest usernames guest[0-4][[:digit:]]*: PasswordGuesses 10 # ... other more specific keywords for guest usernames with [0-4] digits guest[5-9][[:digit:]]*: PasswordGuesses 12 # ... other more specific keywords for guest usernames with [5-9] digits
or for specific groups:
# Tectia: /etc/ssh2/subconfig/xyz-guests PasswordGuesses 6 # ... other general keywords for all [x-z]guests groups .*%xguests: PasswordGuesses 15 # ... other more specific keywords for the xguests group .*%yguests: PasswordGuesses 16 # ... other more specific keywords for the yguests group .*%zguests: PasswordGuesses 17 # ... other more specific keywords for the zguests group
Several other important aspects of server behavior follow directly as consequences of the order and timing for reading the configuration files. The server normally reads its main configuration file only when it starts, and must be signaled to reread the configuration later, if changes are made. [5.2.4] In contrast, subconfiguration files are reread for each connection, so no signaling is necessary if the files are modified. In fact, a "match anything" pattern can be used to store frequently changed keywords in a subconfiguration file, to avoid the need for frequent signaling:
# Tectia with zsh_fileglob or traditional regex syntax HostSpecificConfig * /etc/ssh2/subconfig/volatile # Tectia with egrep regex syntax HostSpecificConfig .* /etc/ssh2/subconfig/volatile
If an error is detected while reading the main configuration file, then the server exits. Errors within host-specific configuration files cause the connection to be terminated. For user-specific configuration files, errors result in denial of access.
Some keywords cannot be specified in subconfiguration files. In
some cases, the keywords control server behavior that happens before
the subconfiguration files are read. For example, it doesn't make
sense to specify the Port
keyword
[5.3.3.1] in
subconfiguration files, because the port (or ports) must be chosen to
listen for incoming connections before any connections can be
accepted. Certain other keywords are forbidden in subconfiguration
files because they would be too confusing. For example, the HostSpecificConfig
and UserSpecificConfig
keywords are restricted
to main configuration files: imagine trying to understand the pretzel
logic resulting from nested subconfiguration files! Tables 11-1, 11-2, and 11-3 list the keywords
permitted in each kind of configuration file.
Table 11-1. Tectia keywords permitted only in the main configuration file
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
Table 11-2. Tectia keywords permitted in the main and host-specific configuration files, but not user-specific ones
| | |
| | |
| | |
| | |
| | |
| | |
| | |
|
Table 11-3. Tectia keywords permitted in all configuration files
a The | |
---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
Tectia removes double quotes from values. The following lines are all valid:[158]
# Tectia PermitEmptyPasswords "no" PermitEmptyPasswords "y"es
In most cases, there is no reason to use quotes, but they are
handy in a few, rare situations. If a value ends with a colon
(:
) character, it will be
misinterpreted as a section pattern: [5.2.1]
# Tectia: misinterpreted as a section pattern! AuthKbdInt.Plugin /usr/local/sbin/kiplugin --prompt color:
This is a particularly insidious error if it occurs in a configuration file that supports sections (e.g., subconfiguration files), because the section pattern will probably never match, so the rest of the configuration file is silently ignored![159]
To prevent this, enclose the value in quotes:
# Tectia AuthKbdInt.Plugin "/usr/local/sbin/kiplugin --prompt color:"
This works because the recognition of section pattern lines occurs before quotes are removed. Since the quoted line doesn't end in a colon, it isn't considered a section pattern line. Equivalently, you can also enclose only part of the value in quotes, as long as the quoted part includes the final colon:
# Tectia AuthKbdInt.Plugin /usr/local/sbin/kiplugin --prompt "color:" AuthKbdInt.Plugin /usr/local/sbin/kiplugin --prompt color":"
To include a literal quote character in a value, precede it with a backslash. For example, to construct a shell command that uses (shell) quotes to protect a command-line argument with embedded whitespace from being split:
# Tectia AuthKbdInt.Plugin /usr/local/sbin/kiplugin --prompt \"Enter your favorite color:\"
When configuration files are read, the whitespace between the keyword and value is discarded, and any trailing whitespace at the end of each line is removed from the value.[160] Quotes can be used to retain this whitespace as part of the value. As a devious example, you can hide user configurations in a temporary directory named as a single space character:
# Tectia UserConfigDirectory /tmp/" "
[153] If debugging options [5.9] prevent forking, then the single server process exits after handling a single session, so only a single copy of the configuration is needed.
[154] We'll use egrep regex syntax exclusively in this running example for simplicity, but of course other regex syntaxes could be used as well.
[155] We have removed the first PasswordGuesses
keyword, since it is
always overridden by the second occurrence anyway.
[156] The order for reading files can also be viewed as a consistent progression from general settings in the main configuration file to increasingly specific settings for hosts and users in the subconfiguration files.
[157] The Tectia documentation also refers to sections as configuration blocks, or stanzas. Subconfiguration sections have the same structure as those used in client configuration files [7.1.2], except for the interpretation of the patterns.
[158] Single quotes have no special significance.
[159] The server does warn about section patterns in configuration files that should not have them, like the main configuration file, which makes the error easier to detect.
[160] Keywords that use multiple values separated by whitespace also discard the whitespace between those values. Otherwise, whitespace that is embedded within a single value is left unchanged.