feat: Add IPAddressValue; improvments & bugfixes

This commit is contained in:
Myzel394 2024-07-31 19:10:53 +02:00
parent 8352e0df40
commit 76df6c5351
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
5 changed files with 260 additions and 70 deletions

View File

@ -0,0 +1,133 @@
package docvalues
import (
"config-lsp/utils"
net "net/netip"
protocol "github.com/tliron/glsp/protocol_3_16"
)
var NonRoutableNetworks = []net.Prefix{
net.MustParsePrefix("240.0.0.0/4"),
net.MustParsePrefix("2001:db8::/32"),
}
type InvalidIPAddress struct{}
func (e InvalidIPAddress) Error() string {
return "This is not a valid IP Address"
}
type IP4AddressNotAllowedError struct{}
func (e IP4AddressNotAllowedError) Error() string {
return "IPv4 Addresses are not allowed"
}
type IP6AddressNotAllowedError struct{}
func (e IP6AddressNotAllowedError) Error() string {
return "IPv6 Addresses are not allowed"
}
type IpRangeNotAllowedError struct{}
func (e IpRangeNotAllowedError) Error() string {
return "IP Ranges are not allowed; Use a single IP Address instead"
}
type IPAddressNotAllowedError struct{}
func (e IPAddressNotAllowedError) Error() string {
return "This IP Address is not allowed"
}
type IPAddressValue struct {
AllowIPv4 bool
AllowIPv6 bool
AllowRange bool
AllowedIPs *[]net.Prefix
DisallowedIPs *[]net.Prefix
}
func (v IPAddressValue) GetTypeDescription() []string {
if v.AllowedIPs != nil && len(*v.AllowedIPs) != 0 {
return append(
[]string{"One of the following IP Addresses (in range):"},
utils.Map(*v.AllowedIPs, func(ip net.Prefix) string {
return ip.String()
})...,
)
}
return []string{"An IP Address"}
}
func (v IPAddressValue) CheckIsValid(value string) error {
var ip net.Prefix
if v.AllowRange {
rawIP, err := net.ParsePrefix(value)
if err != nil {
return InvalidIPAddress{}
}
ip = rawIP
} else {
rawIP, err := net.ParseAddr(value)
if err != nil {
return InvalidIPAddress{}
}
ip = net.PrefixFrom(rawIP, 32)
}
if !ip.IsValid() {
return InvalidIPAddress{}
}
if v.AllowedIPs != nil {
for _, allowedIP := range *v.AllowedIPs {
if allowedIP.Contains(ip.Addr()) {
return nil
}
}
return IpRangeNotAllowedError{}
}
if v.DisallowedIPs != nil {
for _, disallowedIP := range *v.DisallowedIPs {
if disallowedIP.Contains(ip.Addr()) {
return IPAddressNotAllowedError{}
}
}
}
if v.AllowIPv4 && ip.Addr().Is4() {
return nil
}
if v.AllowIPv6 && ip.Addr().Is6() {
return nil
}
return InvalidIPAddress{}
}
func (v IPAddressValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
if v.AllowedIPs != nil && len(*v.AllowedIPs) != 0 {
kind := protocol.CompletionItemKindValue
return utils.Map(*v.AllowedIPs, func(ip net.Prefix) protocol.CompletionItem {
return protocol.CompletionItem{
Label: ip.Addr().String(),
Kind: &kind,
}
})
}
return []protocol.CompletionItem{}
}

View File

@ -17,6 +17,7 @@ func (e KeyValueAssignmentError) Error() string {
type KeyValueAssignmentValue struct { type KeyValueAssignmentValue struct {
Key Value Key Value
Value Value Value Value
ValueIsOptional bool
Separator string Separator string
} }
@ -31,20 +32,25 @@ func (v KeyValueAssignmentValue) GetTypeDescription() []string {
func (v KeyValueAssignmentValue) CheckIsValid(value string) error { func (v KeyValueAssignmentValue) CheckIsValid(value string) error {
parts := strings.Split(value, v.Separator) parts := strings.Split(value, v.Separator)
if len(parts) == 1 && parts[0] == "" { if len(parts) == 0 || parts[0] == "" {
// Nothing to check for
return nil return nil
} }
if len(parts) != 2 {
return KeyValueAssignmentError{}
}
err := v.Key.CheckIsValid(parts[0]) err := v.Key.CheckIsValid(parts[0])
if err != nil { if err != nil {
return err return err
} }
if len(parts) != 2 {
if v.ValueIsOptional {
return nil
}
return KeyValueAssignmentError{}
}
err = v.Value.CheckIsValid(parts[1]) err = v.Value.CheckIsValid(parts[1])
if err != nil { if err != nil {

View File

@ -0,0 +1,66 @@
package docvalues
import (
"fmt"
"strconv"
protocol "github.com/tliron/glsp/protocol_3_16"
)
type NotANumberError struct{}
func (e NotANumberError) Error() string {
return "This must be number"
}
type NumberNotInRangeError struct {
Min *int
Max *int
}
func (e NumberNotInRangeError) Error() string {
if e.Min == nil {
return fmt.Sprintf("This must be at most or less than %d", *e.Max)
}
if e.Max == nil {
return fmt.Sprintf("This must be equal or more than %d", *e.Min)
}
return fmt.Sprintf("This must be between %d and %d (inclusive)", *e.Min, *e.Max)
}
type NumberValue struct {
Min *int
Max *int
}
func (v NumberValue) GetTypeDescription() []string {
if v.Min != nil {
if v.Max != nil {
return []string{fmt.Sprintf("A number between %d and %d (inclusive)", *v.Min, *v.Max)}
} else {
return []string{fmt.Sprintf("A number of at least %d", *v.Min)}
}
} else if v.Max != nil {
return []string{fmt.Sprintf("A number of at most %d", *v.Max)}
}
return []string{"A number"}
}
func (v NumberValue) CheckIsValid(value string) error {
number, err := strconv.Atoi(value)
if err != nil {
return NotANumberError{}
}
if (v.Min != nil && number < *v.Min) || (v.Max != nil && number > *v.Max) {
return NumberNotInRangeError{v.Min, v.Max}
}
return nil
}
func (v NumberValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
return []protocol.CompletionItem{}
}

View File

@ -1,40 +0,0 @@
package docvalues
import (
protocol "github.com/tliron/glsp/protocol_3_16"
"strconv"
)
type NotANumberError struct{}
func (e NotANumberError) Error() string {
return "This must be number"
}
type NumberIsNotPositiveError struct{}
func (e NumberIsNotPositiveError) Error() string {
return "This number must be positive"
}
type PositiveNumberValue struct{}
func (v PositiveNumberValue) GetTypeDescription() []string {
return []string{"A positive number"}
}
func (v PositiveNumberValue) CheckIsValid(value string) error {
number, err := strconv.Atoi(value)
if err != nil {
return NotANumberError{}
}
if number < 0 {
return NumberIsNotPositiveError{}
}
return nil
}
func (v PositiveNumberValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
return []protocol.CompletionItem{}
}

View File

@ -5,6 +5,10 @@ import (
docvalues "config-lsp/doc-values" docvalues "config-lsp/doc-values"
) )
var ZERO = 0
var MAX_PORT = 65535
var MAX_FILE_MODE = 0777
var Options = map[string]common.Option{ var Options = map[string]common.Option{
"AcceptEnv": common.NewOption( "AcceptEnv": common.NewOption(
`Specifies what environment variables sent by the client will be copied into the session's environ(7). See SendEnv and SetEnv in ssh_config(5) for how to configure the client. The TERM 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 AcceptEnv 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.`, `Specifies what environment variables sent by the client will be copied into the session's environ(7). See SendEnv and SetEnv in ssh_config(5) for how to configure the client. The TERM 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 AcceptEnv 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.`,
@ -171,6 +175,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
Separator: " ", Separator: " ",
DuplicatesExtractor: &ChannelTimeoutExtractor, DuplicatesExtractor: &ChannelTimeoutExtractor,
SubValue: docvalues.KeyValueAssignmentValue{ SubValue: docvalues.KeyValueAssignmentValue{
ValueIsOptional: false,
Separator: "=", Separator: "=",
Key: docvalues.EnumValue{ Key: docvalues.EnumValue{
Values: []string{ Values: []string{
@ -213,12 +218,12 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
}), }),
), ),
"ClientAliveCountMax": common.NewOption(`Sets the number of client alive messages which may be sent without sshd(8) receiving any messages back from the client. If this threshold is reached while client alive messages are being sent, sshd will disconnect the client, terminating the session. It is important to note that the use of client alive messages is very different from TCPKeepAlive. The client alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by TCPKeepAlive is spoofable. The client alive mechanism is valuable when the client or server depend on knowing when a connection has become unresponsive. "ClientAliveCountMax": common.NewOption(`Sets the number of client alive messages which may be sent without sshd(8) receiving any messages back from the client. If this threshold is reached while client alive messages are being sent, sshd will disconnect the client, terminating the session. It is important to note that the use of client alive messages is very different from TCPKeepAlive. The client alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by TCPKeepAlive is spoofable. The client alive mechanism is valuable when the client or server depend on knowing when a connection has become unresponsive.
// The default value is 3. If ClientAliveInterval is set to 15, and ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. Setting a zero ClientAliveCountMax disables connection termination.`, The default value is 3. If ClientAliveInterval is set to 15, and ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. Setting a zero ClientAliveCountMax disables connection termination.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
), ),
"ClientAliveInterval": common.NewOption( "ClientAliveInterval": common.NewOption(
`Sets a timeout interval in seconds after which if no data has been received from the client, sshd(8) will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client.`, `Sets a timeout interval in seconds after which if no data has been received from the client, sshd(8) will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
), ),
"Compression": common.NewOption( "Compression": common.NewOption(
`Specifies whether compression is enabled after the user has authenticated successfully. The argument must be yes, delayed (a legacy synonym for yes) or no. The default is yes.`, `Specifies whether compression is enabled after the user has authenticated successfully. The argument must be yes, delayed (a legacy synonym for yes) or no. The default is yes.`,
@ -303,12 +308,12 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
), ),
"HostCertificate": common.NewOption( "HostCertificate": common.NewOption(
`Specifies a file containing a public host certificate. The certificate's public key must match a private host key already specified by HostKey. The default behaviour of sshd(8) is not to load any certificates.`, `Specifies a file containing a public host certificate. The certificate's public key must match a private host key already specified by HostKey. The default behaviour of sshd(8) is not to load any certificates.`,
docvalues.StringValue{}, docvalues.PathValue{},
), ),
"HostKey": common.NewOption(`Specifies a file containing a private host key used by SSH. The defaults are /etc/ssh/ssh_host_ecdsa_key, /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key. "HostKey": common.NewOption(`Specifies a file containing a private host key used by SSH. The defaults are /etc/ssh/ssh_host_ecdsa_key, /etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key.
Note that sshd(8) will refuse to use a file if it is group/world-accessible and that the HostKeyAlgorithms option restricts which of the keys are actually used by sshd(8). Note that sshd(8) will refuse to use a file if it is group/world-accessible and that the HostKeyAlgorithms option restricts which of the keys are actually used by sshd(8).
It is possible to have multiple host key files. It is also possible to specify public host key files instead. In this case operations on the private key will be delegated to an ssh-agent(1).`, It is possible to have multiple host key files. It is also possible to specify public host key files instead. In this case operations on the private key will be delegated to an ssh-agent(1).`,
docvalues.StringValue{}, docvalues.PathValue{},
), ),
"HostKeyAgent": common.NewOption( "HostKeyAgent": common.NewOption(
`Identifies the UNIX-domain socket used to communicate with an agent that has access to the private host keys. If the string "SSH_AUTH_SOCK" is specified, the location of the socket will be read from the SSH_AUTH_SOCK environment variable.`, `Identifies the UNIX-domain socket used to communicate with an agent that has access to the private host keys. If the string "SSH_AUTH_SOCK" is specified, the location of the socket will be read from the SSH_AUTH_SOCK environment variable.`,
@ -345,13 +350,20 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
BooleanEnumValue, BooleanEnumValue,
), ),
"Include": common.NewOption(`Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(7) wildcards that will be expanded and processed in lexical order. Files without absolute paths are assumed to be in /etc/ssh. An Include directive may appear inside a Match block to perform conditional inclusion.`, "Include": common.NewOption(`Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(7) wildcards that will be expanded and processed in lexical order. Files without absolute paths are assumed to be in /etc/ssh. An Include directive may appear inside a Match block to perform conditional inclusion.`,
docvalues.StringValue{}, docvalues.ArrayValue{
Separator: " ",
DuplicatesExtractor: &docvalues.SimpleDuplicatesExtractor,
SubValue: docvalues.PathValue{
RequiredType: docvalues.PathTypeFile,
},
},
// TODO: Add extra check
), ),
"IPQoS": common.NewOption(`Specifies the IPv4 type-of-service or DSCP class for the connection. Accepted values are af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a numeric value, or none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is af21 (Low-Latency Data) for interactive sessions and cs1 (Lower Effort) for non-interactive sessions.`, "IPQoS": common.NewOption(`Specifies the IPv4 type-of-service or DSCP class for the connection. Accepted values are af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a numeric value, or none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is af21 (Low-Latency Data) for interactive sessions and cs1 (Lower Effort) for non-interactive sessions.`,
docvalues.OrValue{ docvalues.OrValue{
Values: []docvalues.Value{ Values: []docvalues.Value{
docvalues.PositiveNumberValue{}, docvalues.NumberValue{},
docvalues.EnumValue{ docvalues.EnumValue{
Values: []string{"none"}, Values: []string{"none"},
}, },
@ -409,11 +421,23 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
"sntrup761x25519-sha512@openssh.com", "sntrup761x25519-sha512@openssh.com",
}), }),
), ),
// "ListenAddress": `Specifies the local addresses sshd(8) should listen on. The following forms may be used: "ListenAddress": common.NewOption(`Specifies the local addresses sshd(8) should listen on. The following forms may be used:
// ListenAddress hostname|address [rdomain domain] ListenAddress hostname:port [rdomain domain] ListenAddress IPv4_address:port [rdomain domain] ListenAddress [hostname|address]:port [rdomain domain] ListenAddress hostname|address [rdomain domain] ListenAddress hostname:port [rdomain domain] ListenAddress IPv4_address:port [rdomain domain] ListenAddress [hostname|address]:port [rdomain domain]
// The optional rdomain qualifier requests sshd(8) listen in an explicit routing domain. If port is not specified, sshd will listen on the address and all Port options specified. The default is to listen on all local addresses on the current default routing domain. Multiple ListenAddress options are permitted. For more information on routing domains, see rdomain(4).`, The optional rdomain qualifier requests sshd(8) listen in an explicit routing domain. If port is not specified, sshd will listen on the address and all Port options specified. The default is to listen on all local addresses on the current default routing domain. Multiple ListenAddress options are permitted. For more information on routing domains, see rdomain(4).`,
docvalues.KeyValueAssignmentValue{
ValueIsOptional: true,
Key: docvalues.IPAddressValue{
AllowIPv4: true,
AllowIPv6: true,
AllowRange: false,
DisallowedIPs: &docvalues.NonRoutableNetworks,
},
Separator: ":",
Value: docvalues.NumberValue{Min: &ZERO, Max: &MAX_PORT},
},
),
"LoginGraceTime": common.NewOption(`The server disconnects after this time if the user has not successfully logged in. If the value is 0, there is no time limit. The default is 120 seconds.`, "LoginGraceTime": common.NewOption(`The server disconnects after this time if the user has not successfully logged in. If the value is 0, there is no time limit. The default is 120 seconds.`,
docvalues.PositiveNumberValue{}, TimeFormatValue{},
), ),
"LogLevel": common.NewOption(`Gives the verbosity level that is used when logging messages from sshd(8). The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. Logging with a DEBUG level violates the privacy of users and is not recommended.`, "LogLevel": common.NewOption(`Gives the verbosity level that is used when logging messages from sshd(8). The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. Logging with a DEBUG level violates the privacy of users and is not recommended.`,
docvalues.EnumValue{ docvalues.EnumValue{
@ -470,10 +494,10 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
// The patterns in an Address 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. // The patterns in an Address 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 Match keyword. Available keywords are AcceptEnv, AllowAgentForwarding, AllowGroups, AllowStreamLocalForwarding, AllowTcpForwarding, AllowUsers, AuthenticationMethods, AuthorizedKeysCommand, AuthorizedKeysCommandUser, AuthorizedKeysFile, AuthorizedPrincipalsCommand, AuthorizedPrincipalsCommandUser, AuthorizedPrincipalsFile, Banner, CASignatureAlgorithms, ChannelTimeout, ChrootDirectory, ClientAliveCountMax, ClientAliveInterval, DenyGroups, DenyUsers, DisableForwarding, ExposeAuthInfo, ForceCommand, GatewayPorts, GSSAPIAuthentication, HostbasedAcceptedAlgorithms, HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IgnoreRhosts, Include, IPQoS, KbdInteractiveAuthentication, KerberosAuthentication, LogLevel, MaxAuthTries, MaxSessions, PasswordAuthentication, PermitEmptyPasswords, PermitListen, PermitOpen, PermitRootLogin, PermitTTY, PermitTunnel, PermitUserRC, PubkeyAcceptedAlgorithms, PubkeyAuthentication, PubkeyAuthOptions, RekeyLimit, RevokedKeys, RDomain, SetEnv, StreamLocalBindMask, StreamLocalBindUnlink, TrustedUserCAKeys, UnusedConnectionTimeout, X11DisplayOffset, X11Forwarding and X11UseLocalhost.`, // Only a subset of keywords may be used on the lines following a Match keyword. Available keywords are AcceptEnv, AllowAgentForwarding, AllowGroups, AllowStreamLocalForwarding, AllowTcpForwarding, AllowUsers, AuthenticationMethods, AuthorizedKeysCommand, AuthorizedKeysCommandUser, AuthorizedKeysFile, AuthorizedPrincipalsCommand, AuthorizedPrincipalsCommandUser, AuthorizedPrincipalsFile, Banner, CASignatureAlgorithms, ChannelTimeout, ChrootDirectory, ClientAliveCountMax, ClientAliveInterval, DenyGroups, DenyUsers, DisableForwarding, ExposeAuthInfo, ForceCommand, GatewayPorts, GSSAPIAuthentication, HostbasedAcceptedAlgorithms, HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IgnoreRhosts, Include, IPQoS, KbdInteractiveAuthentication, KerberosAuthentication, LogLevel, MaxAuthTries, MaxSessions, PasswordAuthentication, PermitEmptyPasswords, PermitListen, PermitOpen, PermitRootLogin, PermitTTY, PermitTunnel, PermitUserRC, PubkeyAcceptedAlgorithms, PubkeyAuthentication, PubkeyAuthOptions, RekeyLimit, RevokedKeys, RDomain, SetEnv, StreamLocalBindMask, StreamLocalBindUnlink, TrustedUserCAKeys, UnusedConnectionTimeout, X11DisplayOffset, X11Forwarding and X11UseLocalhost.`,
"MaxAuthTries": common.NewOption(`Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6.`, "MaxAuthTries": common.NewOption(`Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
), ),
"MaxSessions": common.NewOption(`Specifies the maximum number of open shell, login or subsystem (e.g. sftp) sessions permitted per network connection. Multiple sessions may be established by clients that support connection multiplexing. Setting MaxSessions to 1 will effectively disable session multiplexing, whereas setting it to 0 will prevent all shell, login and subsystem sessions while still permitting forwarding. The default is 10.`, "MaxSessions": common.NewOption(`Specifies the maximum number of open shell, login or subsystem (e.g. sftp) sessions permitted per network connection. Multiple sessions may be established by clients that support connection multiplexing. Setting MaxSessions to 1 will effectively disable session multiplexing, whereas setting it to 0 will prevent all shell, login and subsystem sessions while still permitting forwarding. The default is 10.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
), ),
// "MaxStartups": `Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. The default is 10:30:100. // "MaxStartups": `Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime 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"). sshd(8) 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).`, // Alternatively, random early drop can be enabled by specifying the three colon separated values start:rate:full (e.g. "10:30:60"). sshd(8) 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).`,
@ -547,7 +571,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
EnforceValues: true, EnforceValues: true,
Values: []string{"none"}, Values: []string{"none"},
}, },
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
}, },
}, },
), ),
@ -557,7 +581,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
), ),
"Port": common.NewOption(`Specifies the port number that sshd(8) listens on. The default is 22. Multiple options of this type are permitted. See also ListenAddress.`, "Port": common.NewOption(`Specifies the port number that sshd(8) listens on. The default is 22. Multiple options of this type are permitted. See also ListenAddress.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO, Max: &MAX_PORT},
), ),
"PrintLastLog": common.NewOption(`Specifies whether sshd(8) should print the date and time of the last user login when a user logs in interactively. The default is yes.`, "PrintLastLog": common.NewOption(`Specifies whether sshd(8) should print the date and time of the last user login when a user logs in interactively. The default is yes.`,
BooleanEnumValue, BooleanEnumValue,
@ -593,7 +617,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
), ),
// "RekeyLimit": `Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of K, M, or G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between 1G and 4G, depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the “TIME FORMATS” section. The default value for RekeyLimit is default none, which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done.`, // "RekeyLimit": `Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum amount of time that may pass before the session key is renegotiated. The first argument is specified in bytes and may have a suffix of K, M, or G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between 1G and 4G, depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the “TIME FORMATS” section. The default value for RekeyLimit is default none, which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done.`,
"RequiredRSASize": common.NewOption(`Specifies the minimum RSA key size (in bits) that sshd(8) will accept. User and host-based authentication keys smaller than this limit will be refused. The default is 1024 bits. Note that this limit may only be raised from the default.`, "RequiredRSASize": common.NewOption(`Specifies the minimum RSA key size (in bits) that sshd(8) will accept. User and host-based authentication keys smaller than this limit will be refused. The default is 1024 bits. Note that this limit may only be raised from the default.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
), ),
"RevokedKeys": common.NewOption(`Specifies revoked public keys file, or none to not use one. Keys listed in this file will be refused for public key authentication. Note that if this file is not readable, then public key authentication will be refused for all users. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by ssh-keygen(1). For more information on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1).`, "RevokedKeys": common.NewOption(`Specifies revoked public keys file, or none to not use one. Keys listed in this file will be refused for public key authentication. Note that if this file is not readable, then public key authentication will be refused for all users. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by ssh-keygen(1). For more information on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1).`,
docvalues.StringValue{}, docvalues.StringValue{},
@ -610,6 +634,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
Separator: " ", Separator: " ",
DuplicatesExtractor: &SetEnvExtractor, DuplicatesExtractor: &SetEnvExtractor,
SubValue: docvalues.KeyValueAssignmentValue{ SubValue: docvalues.KeyValueAssignmentValue{
ValueIsOptional: false,
Separator: "=", Separator: "=",
Key: docvalues.StringValue{}, Key: docvalues.StringValue{},
Value: docvalues.StringValue{}, Value: docvalues.StringValue{},
@ -618,7 +643,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
), ),
"StreamLocalBindMask": common.NewOption(`Sets the octal file creation mode mask (umask) used when creating a Unix-domain socket file for local or remote port forwarding. This option is only used for port forwarding to a Unix-domain socket file. "StreamLocalBindMask": common.NewOption(`Sets the octal file creation mode mask (umask) used when creating a Unix-domain socket file for local or remote port forwarding. This option is only used for port forwarding to a Unix-domain socket file.
The default value is 0177, which creates a Unix-domain socket file that is readable and writable only by the owner. Note that not all operating systems honor the file mode on Unix-domain socket files.`, The default value is 0177, which creates a Unix-domain socket file that is readable and writable only by the owner. Note that not all operating systems honor the file mode on Unix-domain socket files.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO, Max: &MAX_FILE_MODE},
), ),
"StreamLocalBindUnlink": common.NewOption(`Specifies whether to remove an existing Unix-domain socket file for local or remote port forwarding before creating a new one. If the socket file already exists and StreamLocalBindUnlink is not enabled, sshd will be unable to forward the port to the Unix-domain socket file. This option is only used for port forwarding to a Unix-domain socket file. "StreamLocalBindUnlink": common.NewOption(`Specifies whether to remove an existing Unix-domain socket file for local or remote port forwarding before creating a new one. If the socket file already exists and StreamLocalBindUnlink is not enabled, sshd will be unable to forward the port to the Unix-domain socket file. This option is only used for port forwarding to a Unix-domain socket file.
The argument must be yes or no. The default is no.`, The argument must be yes or no. The default is no.`,
@ -683,7 +708,7 @@ See PATTERNS in ssh_config(5) for more information on patterns. This keyword may
}, },
), ),
"X11DisplayOffset": common.NewOption(`Specifies the first display number available for sshd(8)'s X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10.`, "X11DisplayOffset": common.NewOption(`Specifies the first display number available for sshd(8)'s X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10.`,
docvalues.PositiveNumberValue{}, docvalues.NumberValue{Min: &ZERO},
), ),
"X11Forwarding": common.NewOption(`Specifies whether X11 forwarding is permitted. The argument must be yes or no. The default is no. "X11Forwarding": common.NewOption(`Specifies whether X11 forwarding is permitted. The argument must be yes or no. The default is no.
When X11 forwarding is enabled, there may be additional exposure to the server and to client displays if the sshd(8) proxy display is configured to listen on the wildcard address (see X11UseLocalhost), though this is not the default. Additionally, the authentication spoofing and authentication data verification and substitution occur on the client side. The security risk of using X11 forwarding is that the client's X11 display server may be exposed to attack when the SSH client requests forwarding (see the warnings for ForwardX11 in ssh_config(5)). A system administrator may have a stance in which they want to protect clients that may expose themselves to attack by unwittingly requesting X11 forwarding, which can warrant a no setting. When X11 forwarding is enabled, there may be additional exposure to the server and to client displays if the sshd(8) proxy display is configured to listen on the wildcard address (see X11UseLocalhost), though this is not the default. Additionally, the authentication spoofing and authentication data verification and substitution occur on the client side. The security risk of using X11 forwarding is that the client's X11 display server may be exposed to attack when the SSH client requests forwarding (see the warnings for ForwardX11 in ssh_config(5)). A system administrator may have a stance in which they want to protect clients that may expose themselves to attack by unwittingly requesting X11 forwarding, which can warrant a no setting.