Skip to content

feat(ssh_config): wire the parsed-but-unused ssh_config keywords #281

Description

@inureyes

Part of the OpenSSH drop-in compatibility epic.

Problem

bssh's ssh_config parser accepts roughly 70 keywords, but the resolved host config is barely consumed. Of 81 fields on the config struct, only about 10 are read anywhere outside src/ssh/ssh_config/: hostname, user, port, identity files, StrictHostKeyChecking, ProxyJump, Compression, AddressFamily, ServerAliveInterval and ServerAliveCountMax.

Everything else is parsed, validated, merged, and discarded. A user writes a directive, bssh accepts it without complaint, and the behavior does not change. Two instances were severe enough to get their own issues (UserKnownHostsFile and ProxyCommand), but the pattern is the general case, not the exception.

The following fields are assigned by the resolver and never read: add_keys_to_agent, batch_mode, bind_interface, ca_signature_algorithms, certificate_files, check_host_ip, clear_all_forwardings, connection_attempts, control_master, control_path, control_persist, dynamic_forward, enable_ssh_keysign, escape_char, exit_on_forward_failure, fingerprint_hash, fork_after_authentication, forward_agent, forward_x11, forward_x11_timeout, forward_x11_trusted, gateway_ports, global_known_hosts_file, gssapi_authentication, hash_known_hosts, host_key_algorithms, host_key_alias, hostbased_accepted_algorithms, hostbased_authentication, identities_only, identity_agent, ipqos, kex_algorithms, keyboard_interactive_authentication, known_hosts_command, local_command, local_forward, log_level, macs, no_host_authentication_for_localhost, number_of_password_prompts, password_authentication, permit_local_command, permit_remote_open, preferred_authentications, proxy_command, proxy_use_fdpass, pubkey_accepted_algorithms, pubkey_authentication, rekey_limit, remote_command, remote_forward, request_tty, required_rsa_size, send_env, session_type, stdin_null, syslog_facility, tcp_keep_alive, update_host_keys, user_known_hosts_file, verify_host_key_dns, visual_host_key.

Scope

This is a tracking issue. Wire the keywords in the order the regression suite exercises them, and split out any individual keyword that turns out to be large enough to deserve its own issue.

First wave, each directly blocking a named regress test:

  • SendEnv and SetEnv (envpass)
  • LocalCommand and PermitLocalCommand (localcommand)
  • RequestTTY and SessionType (ssh-tty, match-subsystem)
  • RemoteCommand (percent, host-expand)
  • LocalForward, RemoteForward, DynamicForward, ClearAllForwardings, ExitOnForwardFailure (forwarding, dynamic-forward, forward-control)
  • Ciphers, MACs, KexAlgorithms, HostKeyAlgorithms, PubkeyAcceptedAlgorithms (try-ciphers, kextype, keytype, limit-keytype, integrity)
  • IdentitiesOnly, CertificateFile, PreferredAuthentications, PubkeyAuthentication, PasswordAuthentication, NumberOfPasswordPrompts, BatchMode (multipubkey, cert-file, cert-userkey, key-options)
  • RekeyLimit (rekey)
  • CheckHostIP, UpdateHostKeys, HashKnownHosts, KnownHostsCommand, VerifyHostKeyDNS (knownhosts, knownhosts-command, hostkey-rotate)
  • ConnectionAttempts, TCPKeepAlive, IPQoS, BindAddress, BindInterface

Second wave, no regress coverage but user-facing: AddKeysToAgent, ForwardAgent, IdentityAgent, EscapeChar, FingerprintHash, VisualHostKey, LogLevel, SyslogFacility, StdinNull, ForkAfterAuthentication, RequiredRSASize, GatewayPorts, PermitRemoteOpen.

Out of scope for this epic and to be rejected as unimplemented rather than silently accepted: GSSAPIAuthentication, HostbasedAuthentication, HostbasedAcceptedAlgorithms, EnableSSHKeysign, ForwardX11, ForwardX11Trusted, ForwardX11Timeout.

Implementation decomposition

Keep this tracker open until all seven implementation issues are merged, every first-wave directive has a behavior test, the registry invariant passes, and the named regress set is rerun against the integrated main branch.

Structural requirement

Whatever the outcome per keyword, the silently-parsed state must stop existing. Every keyword the parser accepts must either change behavior at runtime or produce a warning that names it as unimplemented. Add a test that walks the accepted-keyword table and asserts each entry falls into one of those two buckets, so a future keyword cannot be added in the parse-and-discard shape.

Acceptance criteria

  • Each first-wave keyword is consumed at runtime and covered by a test asserting the behavior changes.
  • Unimplemented keywords warn once, naming the keyword and the line, instead of being discarded.
  • The accepted-keyword table has no entry that is neither consumed nor declared unimplemented, enforced by a test.
  • The regress tests named against the first wave pass in the harness.

Part of #275.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions