├── .gitignore ├── .python-version ├── LICENSE ├── README.md ├── demo.ipynb ├── pyproject.toml ├── src └── schemagen │ ├── __init__.py │ └── py.typed └── tests ├── __init__.py └── man └── ssh.1 /.gitignore: -------------------------------------------------------------------------------- 1 | # Python-generated files 2 | __pycache__/ 3 | *.py[oc] 4 | build/ 5 | dist/ 6 | wheels/ 7 | *.egg-info 8 | 9 | # Virtual environments 10 | .venv 11 | uv.lock 12 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.11 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # schemagen: Make tool-calling schemas for existing tools 2 | 3 | 4 | ## Installation 5 | 6 | The cli tool `groff` must be installed this package to work, 7 | e.g. on MacOS: 8 | 9 | `brew install groff` 10 | 11 | 12 | ## Usage 13 | 14 | ```python 15 | > json_function_schema, schema_arguments = man_schema() 16 | ``` 17 | 18 | `json_function_schema` can then be passed to tools which use JSON schemas 19 | to specify functions. 20 | 21 | 22 | `schema_arguments` can be used to take a tool call dictionary and return 23 | the CLI arguments to run (e.g. via `subprocess.run`): 24 | 25 | ```python 26 | > json_function_schema, schema_arguments = man_schema() 27 | > tool_call = { "destination": "user@example.org", "4": True, "E": "/tmp/log", "A": False, } 28 | > get_cli_args(tool_call, schema_arguments) 29 | ['-4', '-E', '/tmp/log', 'user@example.org'] 30 | ``` 31 | -------------------------------------------------------------------------------- /demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%pip install --quiet https://github.com/adamobeng/schemagen" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 6, 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "data": { 19 | "text/plain": [ 20 | "{'name': 'ssh',\n", 21 | " 'description': 'ssh (SSH client) is a\\nprogram for logging into a remote machine and for executing\\ncommands on a remote machine. It is intended to provide\\nsecure encrypted communications between two untrusted hosts\\nover an insecure network. X11 connections, arbitrary TCP\\nports and Unix-domain sockets can also be forwarded over the\\nsecure channel.\\nssh\\nconnects and logs into the specified destination,\\nwhich may be specified as either [\\nuser@ ]hostname or a URI of the form ssh://[ \\nuser@ ]hostname[:port]. The user must prove their identity\\nto the remote machine using one of several methods (see\\nbelow).\\nIf a\\ncommand is specified, it will be executed on the\\nremote host instead of a login shell. A complete command\\nline may be specified as command, or it may have\\nadditional arguments. If supplied, the arguments will be\\nappended to the command, separated by spaces, before it is\\nsent to the server to be executed.',\n", 22 | " 'parameters': {'type': 'object',\n", 23 | " 'properties': {'4': {'type': 'boolean',\n", 24 | " 'description': 'Forces ssh to use IPv4 addresses only.'},\n", 25 | " '6': {'type': 'boolean',\n", 26 | " 'description': 'Forces ssh to use IPv6 addresses only.'},\n", 27 | " 'A': {'type': 'boolean',\n", 28 | " 'description': 'Enables forwarding of connections from an authentication agent such as ssh-agent(1). This can also be specified on a per-host basis in a configuration file.Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent’s Unix-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. A safer alternative may be to use a jump host (see −J).'},\n", 29 | " 'a': {'type': 'boolean',\n", 30 | " 'description': 'Disables forwarding of the authentication agent connection.'},\n", 31 | " 'B': {'type': 'string',\n", 32 | " 'description': 'Bind to the address of bind_interface before attempting to connect to the destination host. This is only useful on systems with more than one address.'},\n", 33 | " 'b': {'type': 'string',\n", 34 | " 'description': 'Use bind_address on the local machine as the source address of the connection. Only useful on systems with more than one address.'},\n", 35 | " 'C': {'type': 'boolean',\n", 36 | " 'description': 'Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11, TCP and Unix-domain connections). The compression algorithm is the same used by gzip(1). Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks. The default value can be set on a host-by-host basis in the configuration files; see the Compression option in ssh_config(5).'},\n", 37 | " 'c': {'type': 'string',\n", 38 | " 'description': 'Selects the cipher specification for encrypting the session. cipher_spec is a comma-separated list of ciphers listed in order of preference. See the Ciphers keyword in ssh_config(5) for more information.'},\n", 39 | " 'D': {'type': 'string',\n", 40 | " 'description': 'Specifies a local “dynamic” application-level port forwarding. This works by allocating a socket to listen to port on the local side, optionally bound to the specified bind_address. Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will act as a SOCKS server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file.IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged ports. 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.'},\n", 41 | " 'E': {'type': 'string',\n", 42 | " 'description': 'Append debug logs to log_file instead of standard error.'},\n", 43 | " 'e': {'type': 'string',\n", 44 | " 'description': 'Sets the escape character for sessions with a pty (default: ‘˜’). The escape character is only recognized at the beginning of a line. The escape character followed by a dot (‘.’) closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once. Setting the character to “none” disables any escapes and makes the session fully transparent.'},\n", 45 | " 'F': {'type': 'string',\n", 46 | " 'description': 'Specifies an alternative per-user configuration file. If a configuration file is given on the command line, the system-wide configuration file (/etc/ssh/ssh_config) will be ignored. The default for the per-user configuration file is ˜/.ssh/config. If set to “none”, no configuration files will be read.'},\n", 47 | " 'f': {'type': 'boolean',\n", 48 | " 'description': 'Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or passphrases, but the user wants it in the background. This implies −n. The recommended way to start X11 programs at a remote site is with something like ssh -f host xterm.If the ExitOnForwardFailure configuration option is set to “yes”, then a client started with −f will wait for all remote port forwards to be successfully established before placing itself in the background. Refer to the description of ForkAfterAuthentication in ssh_config(5) for details.'},\n", 49 | " 'G': {'type': 'boolean',\n", 50 | " 'description': 'Causes ssh to print its configuration after evaluating Host and Match blocks and exit.'},\n", 51 | " 'g': {'type': 'boolean',\n", 52 | " 'description': 'Allows remote hosts to connect to local forwarded ports. If used on a multiplexed connection, then this option must be specified on the master process.'},\n", 53 | " 'I': {'type': 'string',\n", 54 | " 'description': 'Specify the PKCS#11 shared library ssh should use to communicate with a PKCS#11 token providing keys for user authentication. Use of this option will disable UseKeychain.'},\n", 55 | " 'i': {'type': 'string',\n", 56 | " 'description': 'Selects a file from which the identity (private key) for public key authentication is read. You can also specify a public key file to use the corresponding private key that is loaded in ssh-agent(1) when the private key file is not present locally. The default is ˜/.ssh/id_rsa, ˜/.ssh/id_ecdsa, ˜/.ssh/id_ecdsa_sk, ˜/.ssh/id_ed25519, ˜/.ssh/id_ed25519_sk and ˜/.ssh/id_dsa. Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple −i options (and multiple identities specified in configuration files). If no certificates have been explicitly specified by the CertificateFile directive, ssh will also try to load certificate information from the filename obtained by appending -cert.pub to identity filenames.'},\n", 57 | " 'J': {'type': 'string',\n", 58 | " 'description': 'Connect to the target host by first making an ssh connection to the jump host described by destination and then establishing a TCP forwarding to the ultimate destination from there. Multiple jump hops may be specified separated by comma characters. This is a shortcut to specify a ProxyJump configuration directive. Note that configuration directives supplied on the command-line generally apply to the destination host and not any specified jump hosts. Use ˜/.ssh/config to specify configuration for jump hosts.'},\n", 59 | " 'K': {'type': 'boolean',\n", 60 | " 'description': 'Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI credentials to the server.'},\n", 61 | " 'k': {'type': 'boolean',\n", 62 | " 'description': 'Disables forwarding (delegation) of GSSAPI credentials to the server.'},\n", 63 | " 'L': {'type': 'string',\n", 64 | " 'description': 'Specifies that connections to the given TCP port or Unix socket on the local (client) host are to be forwarded to the given host and port, or Unix socket, on the remote side. This works by allocating a socket to listen to either a TCP port on the local side, optionally bound to the specified bind_address, or to a Unix socket. Whenever a connection is made to the local port or socket, the connection is forwarded over the secure channel, and a connection is made to either host port hostport, or the Unix socket remote_socket, from the remote machine.Port forwardings can also be specified in the configuration file. Only the superuser can forward privileged ports. IPv6 addresses can be specified by enclosing the address in square brackets.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.'},\n", 65 | " 'l': {'type': 'string',\n", 66 | " 'description': 'Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file.'},\n", 67 | " 'M': {'type': 'boolean',\n", 68 | " 'description': 'Places the ssh client into “master” mode for connection sharing. Multiple −M options places ssh into “master” mode but with confirmation required using ssh-askpass(1) before each operation that changes the multiplexing state (e.g. opening a new session). Refer to the description of ControlMaster in ssh_config(5) for details.'},\n", 69 | " 'm': {'type': 'string',\n", 70 | " 'description': 'A comma-separated list of MAC (message authentication code) algorithms, specified in order of preference. See the MACs keyword in ssh_config(5) for more information.'},\n", 71 | " 'N': {'type': 'boolean',\n", 72 | " 'description': 'Do not execute a remote command. This is useful for just forwarding ports. Refer to the description of SessionType in ssh_config(5) for details.'},\n", 73 | " 'n': {'type': 'boolean',\n", 74 | " 'description': 'Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background. A common trick is to use this to run X11 programs on a remote machine. For example, ssh -n shadows.cs.hut.fi emacs & will start an emacs on shadows.cs.hut.fi, and the X11 connection will be automatically forwarded over an encrypted channel. The ssh program will be put in the background. (This does not work if ssh needs to ask for a password or passphrase; see also the −f option.) Refer to the description of StdinNull in ssh_config(5) for details.'},\n", 75 | " 'O': {'type': 'string',\n", 76 | " 'description': 'Control an active connection multiplexing master process. When the −O option is specified, the ctl_cmd argument is interpreted and passed to the master process. Valid commands are: “check” (check that the master process is running), “forward” (request forwardings without command execution), “cancel” (cancel forwardings), “exit” (request the master to exit), and “stop” (request the master to stop accepting further multiplexing requests).'},\n", 77 | " 'o': {'type': 'string',\n", 78 | " 'description': 'Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. For full details of the options listed below, and their possible values, see ssh_config(5).AddKeysToAgent AddressFamily BatchMode BindAddress CanonicalDomains CanonicalizeFallbackLocal CanonicalizeHostname CanonicalizeMaxDots CanonicalizePermittedCNAMEs CASignatureAlgorithms CertificateFile CheckHostIP Ciphers ClearAllForwardings Compression ConnectionAttempts ConnectTimeout ControlMaster ControlPath ControlPersist DynamicForward EnableEscapeCommandline EscapeChar ExitOnForwardFailure FingerprintHash ForkAfterAuthentication ForwardAgent ForwardX11 ForwardX11Timeout ForwardX11Trusted GatewayPorts GlobalKnownHostsFile GSSAPIAuthentication GSSAPIDelegateCredentials HashKnownHosts Host HostbasedAcceptedAlgorithms HostbasedAuthentication HostKeyAlgorithms HostKeyAlias Hostname IdentitiesOnly IdentityAgent IdentityFile IPQoS KbdInteractiveAuthentication KbdInteractiveDevices KexAlgorithms KnownHostsCommand LocalCommand LocalForward LogLevel MACs Match NoHostAuthenticationForLocalhost NumberOfPasswordPrompts PasswordAuthentication PermitLocalCommand PermitRemoteOpen PKCS11Provider Port PreferredAuthentications ProxyCommand ProxyJump ProxyUseFdpass PubkeyAcceptedAlgorithms PubkeyAuthentication RekeyLimit RemoteCommand RemoteForward RequestTTY RequiredRSASize SendEnv ServerAliveInterval ServerAliveCountMax SessionType SetEnv StdinNull StreamLocalBindMask StreamLocalBindUnlink StrictHostKeyChecking TCPKeepAlive Tunnel TunnelDevice UpdateHostKeys UseKeychain User UserKnownHostsFile VerifyHostKeyDNS VisualHostKey XAuthLocation'},\n", 79 | " 'P': {'type': 'string',\n", 80 | " 'description': 'Specify a tag name that may be used to select configuration in ssh_config(5). Refer to the Tag and Match keywords in ssh_config(5) for more information.'},\n", 81 | " 'p': {'type': 'string',\n", 82 | " 'description': 'Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file.'},\n", 83 | " 'Q': {'type': 'boolean',\n", 84 | " 'description': 'Queries for the algorithms supported by one of the following features: cipher (supported symmetric ciphers), cipher-auth (supported symmetric ciphers that support authenticated encryption), help (supported query terms for use with the −Q flag), mac (supported message integrity codes), kex (key exchange algorithms), key (key types), key-ca-sign (valid CA signature algorithms for certificates), key-cert (certificate key types), key-plain (non-certificate key types), key-sig (all key types and signature algorithms), protocol-version (supported SSH protocol versions), and sig (supported signature algorithms). Alternatively, any keyword from ssh_config(5) or sshd_config(5) that takes an algorithm list may be used as an alias for the corresponding query_option.'},\n", 85 | " 'q': {'type': 'boolean',\n", 86 | " 'description': 'Quiet mode. Causes most warning and diagnostic messages to be suppressed.'},\n", 87 | " 'R': {'type': 'string',\n", 88 | " 'description': 'Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.This works by allocating a socket to listen to either a TCP port or to a Unix socket on the remote side. Whenever a connection is made to this port or Unix socket, the connection is forwarded over the secure channel, and a connection is made from the local machine to either an explicit destination specified by host port hostport, or local_socket, or, if no explicit destination was specified, ssh will act as a SOCKS 4/5 proxy and forward connections to the destinations requested by the remote SOCKS client.Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 addresses can be specified by enclosing the address in square brackets.By default, TCP listening sockets on the server will be bound to the loopback interface only. This may be overridden by specifying a bind_address. An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on all interfaces. Specifying a remote bind_address will only succeed if the server’s GatewayPorts option is enabled (see sshd_config(5)).If the port argument is ‘0’, the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with -O forward, the allocated port will be printed to the standard output.'},\n", 89 | " 'S': {'type': 'string',\n", 90 | " 'description': 'Specifies the location of a control socket for connection sharing, or the string “none” to disable connection sharing. Refer to the description of ControlPath and ControlMaster in ssh_config(5) for details.'},\n", 91 | " 's': {'type': 'boolean',\n", 92 | " 'description': 'May be used to request invocation of a subsystem on the remote system. Subsystems facilitate the use of SSH as a secure transport for other applications (e.g. sftp(1)). The subsystem is specified as the remote command. Refer to the description of SessionType in ssh_config(5) for details.'},\n", 93 | " 'T': {'type': 'boolean',\n", 94 | " 'description': 'Disable pseudo-terminal allocation.'},\n", 95 | " 't': {'type': 'boolean',\n", 96 | " 'description': 'Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple −t options force tty allocation, even if ssh has no local tty.'},\n", 97 | " 'V': {'type': 'boolean',\n", 98 | " 'description': 'Display the version number and exit.'},\n", 99 | " 'v': {'type': 'boolean',\n", 100 | " 'description': 'Verbose mode. Causes ssh to print debugging messages about its progress. This is helpful in debugging connection, authentication, and configuration problems. Multiple −v options increase the verbosity. The maximum is 3.'},\n", 101 | " 'W': {'type': 'string',\n", 102 | " 'description': 'Requests that standard input and output on the client be forwarded to host on port over the secure channel. Implies −N, −T, ExitOnForwardFailure and ClearAllForwardings, though these can be overridden in the configuration file or using −o command line options.'},\n", 103 | " 'w': {'type': 'string',\n", 104 | " 'description': 'Requests tunnel device forwarding with the specified tun(4) devices between the client (local_tun) and the server (remote_tun).The devices may be specified by numerical ID or the keyword “any”, which uses the next available tunnel device. If remote_tun is not specified, it defaults to “any”. See also the Tunnel and TunnelDevice directives in ssh_config(5).If the Tunnel directive is unset, it will be set to the default tunnel mode, which is “point-to-point”. If a different Tunnel forwarding mode it desired, then it should be specified before −w.'},\n", 105 | " 'X': {'type': 'boolean',\n", 106 | " 'description': 'Enables X11 forwarding. This can also be specified on a per-host basis in a configuration file.X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the user’s X authorization database) can access the local X11 display through the forwarded connection. An attacker may then be able to perform activities such as keystroke monitoring.For this reason, X11 forwarding is subjected to X11 SECURITY extension restrictions by default. Refer to the ssh −Y option and the ForwardX11Trusted directive in ssh_config(5) for more information.'},\n", 107 | " 'x': {'type': 'boolean', 'description': 'Disables X11 forwarding.'},\n", 108 | " 'Y': {'type': 'boolean',\n", 109 | " 'description': 'Enables trusted X11 forwarding. Trusted X11 forwardings are not subjected to the X11 SECURITY extension controls.'},\n", 110 | " 'y': {'type': 'boolean', 'description': ''},\n", 111 | " 'destination': {'type': 'string', 'description': ''}},\n", 112 | " 'required': ['destination']}}" 113 | ] 114 | }, 115 | "execution_count": 6, 116 | "metadata": {}, 117 | "output_type": "execute_result" 118 | } 119 | ], 120 | "source": [ 121 | "import schemagen\n", 122 | "\n", 123 | "man_path = schemagen.get_man_file_path('ssh')\n", 124 | "json_function_schema, schema_arguments = schemagen.man_schema(man_path, groff_path='/opt/homebrew/bin/groff')\n", 125 | "json_function_schema" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 3, 131 | "metadata": {}, 132 | "outputs": [ 133 | { 134 | "data": { 135 | "text/plain": [ 136 | "['-4', '-E', '/tmp/log', 'user@example.org']" 137 | ] 138 | }, 139 | "execution_count": 3, 140 | "metadata": {}, 141 | "output_type": "execute_result" 142 | } 143 | ], 144 | "source": [ 145 | "tool_call = { \"destination\": \"user@example.org\", \"4\": True, \"E\": \"/tmp/log\", \"A\": False, }\n", 146 | "schemagen.get_cli_args(tool_call, schema_arguments)" 147 | ] 148 | } 149 | ], 150 | "metadata": { 151 | "kernelspec": { 152 | "display_name": ".venv", 153 | "language": "python", 154 | "name": "python3" 155 | }, 156 | "language_info": { 157 | "codemirror_mode": { 158 | "name": "ipython", 159 | "version": 3 160 | }, 161 | "file_extension": ".py", 162 | "mimetype": "text/x-python", 163 | "name": "python", 164 | "nbconvert_exporter": "python", 165 | "pygments_lexer": "ipython3", 166 | "version": "3.11.8" 167 | } 168 | }, 169 | "nbformat": 4, 170 | "nbformat_minor": 2 171 | } 172 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "schemagen" 3 | version = "0.1.0" 4 | description = "Make tool-calling schemas for existing tools" 5 | readme = "README.md" 6 | authors = [ 7 | { name = "Adam Obeng", email = "git@adamobeng.com" } 8 | ] 9 | requires-python = ">=3.11" 10 | dependencies = [ 11 | "roffio>=1.1.0", 12 | ] 13 | 14 | [build-system] 15 | requires = ["hatchling"] 16 | build-backend = "hatchling.build" 17 | -------------------------------------------------------------------------------- /src/schemagen/__init__.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import os 3 | import glob 4 | import os.path 5 | from bs4 import BeautifulSoup 6 | import re 7 | from typing import List, Tuple, Dict, Any, Optional 8 | import bs4 9 | 10 | # https://python.langchain.com/v0.1/docs/modules/model_io/chat/function_calling/ 11 | 12 | 13 | def get_man_file_path(cmd: str) -> str: 14 | """ 15 | Retreive the path to the man file for the given command 16 | 17 | Args: 18 | cmd (`str`): the command to get the man file for (e.g. "ssh) 19 | 20 | Returns: 21 | `str`: A path to a man file for the specified command 22 | """ 23 | man_paths = subprocess.getoutput(["manpath"]).split(":") 24 | man_files = [f for d in man_paths for f in glob.glob(d + "/**", recursive=True)] 25 | matching_files = [ 26 | f for f in man_files if os.path.splitext(os.path.basename(f))[0] == cmd 27 | ] 28 | if len(matching_files) == 0: 29 | raise Exception(f"No man file found for {cmd}") 30 | else: 31 | return matching_files[0] 32 | 33 | 34 | def get_man_file_html(filename: str, groff_path: Optional[str] = 'groff') -> str: 35 | """ 36 | Convert the man file to HTML using groff 37 | """ 38 | try: 39 | process = subprocess.Popen( 40 | [groff_path, "-mandoc", filename, "-Thtml"], 41 | stderr=subprocess.PIPE, 42 | stdout=subprocess.PIPE, 43 | ) 44 | html = process.stdout.read().decode("utf8") 45 | return html 46 | except FileNotFoundError: 47 | raise Exception("groff must be installed") 48 | 49 | 50 | def arguments_to_schema_format(collated_arguments: str): 51 | properties = {} 52 | required_args = [] 53 | for a in collated_arguments: 54 | # Choose the longest argument name 55 | if len(a["description_arguments"]) > 0: 56 | argument = sorted(a["description_arguments"], key=lambda x: len(x["name"]))[ 57 | -1 58 | ] 59 | else: 60 | # Arguments which are only in the synopsis, not in the description (typically operands) 61 | argument = a["synopsis_args"][0] 62 | # safe_argument_name = re.sub('\W', '_', argument['name']) 63 | # TODO: it would be nice to support repeated arguments as arrays 64 | properties[argument["name"]] = { 65 | # TODO: should the type 66 | "type": ( 67 | "string" 68 | if not all( 69 | i["type"] in ("flag", "long_flag") for i in a["synopsis_args"] 70 | ) 71 | else "boolean" 72 | ), 73 | "description": a["description"], 74 | "description_arg": argument, 75 | "synopsis_args": a["synopsis_args"], 76 | } 77 | if not all(s["optional"] for s in a["synopsis_args"]): 78 | required_args.append(argument["name"]) 79 | # TODO: handle require args 80 | return properties, required_args 81 | 82 | 83 | def parse_arg(arg: str) -> List[str]: 84 | """ 85 | Given an argument as specified in a man file (e.g. `[−−binary-files=value]`), 86 | determine what type of argument it is 87 | """ 88 | FLAG_CHARS = "[A-z0-9]" # Character range valid for a single-characer flag name. Does not include `_` 89 | OPTION_CHARS = "[\w-]" 90 | OPERAND_CHARS = "[A-z0-9]" 91 | # These two do not take arguments 92 | # single-letter flags e.g. `-aBc` 93 | # TODO: represent these types as an Enum 94 | if re.match(f"−{FLAG_CHARS}+$", arg): 95 | parsed_arg = [] 96 | for a in arg[1:]: 97 | parsed_arg.append({"name": a, "type": "flag"}) 98 | # long flags e.g. `--label` 99 | elif match := re.match(f"−−({OPTION_CHARS}+)$", arg): 100 | parsed_arg = {"name": match.group(1), "type": "long_flag"} 101 | # These have option arguments 102 | elif match := re.match(f"−({OPTION_CHARS})\s+(.*)$", arg): 103 | name = match.group(1) 104 | argument = match.group(2) 105 | if "[" not in argument: 106 | # e.g. `−E log_file` 107 | parsed_arg = { 108 | "name": match.group(1), 109 | "argument": match.group(2), 110 | "type": "option", 111 | } 112 | else: 113 | # e.g. , `−D [ bind_address :] port` 114 | arguments = re.findall("(?:\[.*\])|(?:\S+)", argument) 115 | parsed_arg = { 116 | "name": match.group(1), 117 | "argument": arguments, 118 | "type": "option", 119 | } 120 | elif match := re.match(f"−−({OPTION_CHARS}+)=(\S+)$", arg): 121 | # e.g. `−−binary-files=value` 122 | parsed_arg = { 123 | "name": match.group(1), 124 | "argument": match.group(2), 125 | "type": "long_option", 126 | } 127 | elif match := re.match(f"−−({OPTION_CHARS}+)\[=(\S+)\]$", arg): 128 | parsed_arg = { 129 | "name": match.group(1), 130 | "argument": match.group(2), 131 | "type": "long_option_optional_argument", 132 | } 133 | # These do not have names, they're operands 134 | elif match := re.match(f"({OPERAND_CHARS}+)$", arg): 135 | # e.g. `destination` 136 | parsed_arg = {"name": match.group(1), "type": "operand"} 137 | elif match := re.match(f"({OPERAND_CHARS}+) ...$", arg): 138 | # e.g. `file ...` 139 | parsed_arg = {"name": match.group(1), "type": "multiple_operand"} 140 | else: 141 | parsed_arg = [] 142 | if not isinstance(parsed_arg, list): 143 | parsed_arg = [parsed_arg] 144 | return parsed_arg 145 | 146 | 147 | def get_description_args(arg_ps: List[bs4.element.Tag]) -> List: 148 | """ 149 | Extract the args as listed in the description section. 150 | This is necessary because 151 | a) the description contains the description of each argument, and 152 | b)  If an argument can be specified in multiple forms (e.g. `−G, −−basic-regexp`) 153 | this will not be distinguishable from the synopsis, but it is from the 154 | description in which both forms will be listed on the same line 155 | """ 156 | description_arguments = [] 157 | current_argument = None 158 | for p in arg_ps: 159 | # Find all the p tags which contain argument names 160 | if p.select_one("b") and "margin-left" not in (p.attrs.get("style") or ""): 161 | if ( 162 | current_argument is not None 163 | ): # if we've already parsed the first argument 164 | # TODO: deal with off-by-one-error causing missing description for last argument 165 | da = [ 166 | i for a in current_argument.split(",") for i in parse_arg(a.strip()) 167 | ] 168 | description_arguments.append( 169 | { 170 | "arg_text": current_argument, 171 | "description_arguments": da, 172 | "description": current_argument_description, 173 | } 174 | ) 175 | current_argument = " ".join( 176 | [i.get_text().strip() for i in p.contents] 177 | ).replace("\n", " ") 178 | current_argument_description = "" 179 | else: 180 | current_argument_description += p.get_text().replace("\n", " ") 181 | return description_arguments 182 | 183 | 184 | def get_synopsis_args(command_text: str) -> List: 185 | """ 186 | Parse out the arguments as listed in the synopsis section 187 | """ 188 | args = re.findall("((?:\[.+?\])|(?:\w+))(?: |$)", command_text) 189 | synopsis_args = [] 190 | for pos, arg in enumerate(args): 191 | optional = arg.startswith("[") 192 | arg = re.sub("^\[", "", arg) 193 | arg = re.sub("\]$", "", arg) 194 | for a in parse_arg(arg): 195 | synopsis_args.append(a | {"optional": optional, "pos": pos}) 196 | return synopsis_args 197 | 198 | 199 | def collate_description_synopsis_args(synopsis_args, description_arguments) -> List: 200 | parsed_args = synopsis_args.copy() 201 | collated_arguments = [] 202 | for d_args in description_arguments: 203 | matching_arg_indexes = [ 204 | i 205 | for i, a in enumerate(parsed_args) 206 | if any(a["name"] == m["name"] for m in d_args["description_arguments"]) 207 | ] 208 | collated_arguments.append( 209 | d_args | {"synopsis_args": [parsed_args[i] for i in matching_arg_indexes]} 210 | ) 211 | # Remove from parsed_args the ones we just matched to the description 212 | parsed_args = [ 213 | e for i, e in enumerate(parsed_args) if i not in matching_arg_indexes 214 | ] 215 | # At this point, the only args in parsed_args are ones which didn't match the description 216 | # which should just be operands 217 | for a in parsed_args: 218 | collated_arguments.append( 219 | { 220 | "arg_text": a["name"], 221 | "description_arguments": [], 222 | "description": "", 223 | "synopsis_args": [a], 224 | } 225 | ) 226 | # TODO: Handle leftover parsed args and collated_arguments with no match 227 | # TODO: add enums for arguments with choices 228 | # collated_arguments = [a for a in collated_arguments if len(a['description_arguments']) != 0] 229 | return collated_arguments 230 | 231 | 232 | def get_cli_args(tool_call, arguments): 233 | """ 234 | Does check that only known arguments are passed 235 | Does not check whether required arguments are specified 236 | """ 237 | cli_args = [] 238 | for k, v in tool_call.items(): 239 | if k not in arguments: 240 | raise ValueError(f"Unknown argument {k}") 241 | p = arguments[k] 242 | arg_prefix = "" 243 | if p["description_arg"]["type"] in ("flag", "option"): 244 | arg_prefix = "-" 245 | elif p["description_arg"]["type"] in ( 246 | "long_flag", 247 | "long_option", 248 | "long_option_optional_argument", 249 | ): 250 | arg_prefix = "--" 251 | 252 | if p["description_arg"]["type"] in ( 253 | "operand", 254 | "multiple_operand", 255 | ): 256 | # No argument name 257 | args = [] 258 | else: 259 | args = [arg_prefix + k] 260 | 261 | if isinstance( 262 | v, bool 263 | ): # this is a flag or long flag, do not need to include the argument 264 | if v: # if not v, then it's a False flag so do nothing 265 | cli_args.append((args, p["synopsis_args"][0]["pos"])) 266 | else: 267 | args = args + [v] 268 | cli_args.append((args, p["synopsis_args"][0]["pos"])) 269 | return [ 270 | j for i in sorted(cli_args, key=lambda x: x[1]) for j in i[0] 271 | ] # sort by position 272 | 273 | 274 | def parse_man_file_html(html: str): 275 | """ 276 | Parse the command description and arguments out of the HTML representing the man page 277 | """ 278 | soup = BeautifulSoup(html, features="lxml") 279 | ps = soup.select("p") 280 | 281 | # Heuristic for finding section headers: b tags with all-upper text 282 | # longer than 4 characters (to distinguish from flags) 283 | section_indexes = { 284 | e.select_one("b").text: i - 1 285 | for i, e in enumerate(ps) 286 | if e.select_one("b") 287 | and (e.select_one("b").text == e.select_one("b").text.upper()) 288 | and len(e.select_one("b").text) > 4 289 | } 290 | 291 | synopsis_index = section_indexes["SYNOPSIS"] 292 | next_index = [v for v in section_indexes.values() if v > synopsis_index][0] 293 | command_ps = ps[synopsis_index + 2 : next_index + 1] 294 | 295 | command_forms = [] 296 | for p in command_ps: 297 | if "margin-left:14%" in (p.attrs.get("style") or ""): 298 | command_forms.append("") 299 | command_forms[-1] += p.get_text() 300 | 301 | # TODO: Maybe it's easier to parse command.contents using the and tags? 302 | # TODO: Account for multiple separate command lines as in ssh 303 | command_text = command_forms[0] 304 | command_text = re.sub("[\n\xa0]", " ", command_text) 305 | command_name, command_text = command_text.split(" ", 1) 306 | 307 | # Reference for arg formats: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html 308 | 309 | description_index = section_indexes["DESCRIPTION"] + 1 310 | next_index = [v for v in section_indexes.values() if v > description_index][0] 311 | description_ps = ps[description_index : next_index + 1] 312 | first_arg_index = [ 313 | i - 1 314 | for i, p in enumerate(description_ps) 315 | if i > 1 316 | and p.select_one("b") 317 | and "margin-left" not in (p.attrs.get("style") or "") 318 | ][0] 319 | arg_ps = description_ps[first_arg_index + 1 :] 320 | # TODO: replace mentions of arguments in b tags with the argument names 321 | 322 | synopsis_args = get_synopsis_args(command_text) 323 | description_arguments = get_description_args(arg_ps) 324 | 325 | collated_arguments = collate_description_synopsis_args( 326 | synopsis_args, description_arguments 327 | ) 328 | schema_arguments, required_args = arguments_to_schema_format(collated_arguments) 329 | 330 | json_function_schema = { 331 | "name": command_name, 332 | "description": "\n".join( 333 | [a.get_text() for a in description_ps[1:first_arg_index]] 334 | ), 335 | "parameters": { 336 | "type": "object", 337 | "properties": { 338 | n: {k: v for k, v in p.items() if k in ("type", "description", "enum")} 339 | for n, p in schema_arguments.items() 340 | }, 341 | "required": required_args, 342 | }, 343 | } 344 | return json_function_schema, schema_arguments 345 | 346 | 347 | def man_schema(man_file_path: str, groff_path: Optional[str] = 'groff') -> Tuple[Dict[str, str], Dict]: 348 | """ 349 | This is the main entrypoint to schemagen, it converts a man file 350 | to a JSON schema suitable for tool calling 351 | 352 | 353 | Args: 354 | man_file_path (`str`): path to the man file 355 | groff_path (`Optional[str]`): path to the groff executable, default 'groff' 356 | 357 | Returns: 358 | `Tuple[Dict[str, str], Dict]`: Two element tuple. The first 359 | element is the JSON schema for use in tool calling, the second 360 | is a more detailed representation of the schema which can 361 | be used by `get_cli_args` to turn the tool call into cli args 362 | which can be passed to e.g. `subprocess.args`. 363 | 364 | """ 365 | html = get_man_file_html(man_file_path,groff_path=groff_path ) 366 | json_function_schema, schema_arguments = parse_man_file_html(html) 367 | return json_function_schema, schema_arguments 368 | -------------------------------------------------------------------------------- /src/schemagen/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamobeng/schemagen/c96e4a5744b955804737c5f7a5145fdcc6bcc1e3/src/schemagen/py.typed -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import schemagen 4 | 5 | 6 | class TestSchemaGen(unittest.TestCase): 7 | def test_man_schema_ssh(self): 8 | man_file_path = "./tests/man/ssh.1" 9 | json_function_schema, schema_arguments = schemagen.man_schema(man_file_path) 10 | self.assertEqual( 11 | set(json_function_schema["parameters"]["properties"].keys()), 12 | { 13 | "4", 14 | "6", 15 | "A", 16 | "a", 17 | "C", 18 | "f", 19 | "G", 20 | "g", 21 | "K", 22 | "k", 23 | "M", 24 | "N", 25 | "n", 26 | "q", 27 | "s", 28 | "T", 29 | "t", 30 | "V", 31 | "v", 32 | "X", 33 | "x", 34 | "Y", 35 | "y", 36 | "B", 37 | "b", 38 | "c", 39 | "D", 40 | "E", 41 | "e", 42 | "F", 43 | "I", 44 | "i", 45 | "J", 46 | "L", 47 | "l", 48 | "m", 49 | "O", 50 | "o", 51 | "p", 52 | "Q", 53 | "R", 54 | "S", 55 | "W", 56 | "w", 57 | "destination", 58 | "command", 59 | }, 60 | ) 61 | 62 | def test_get_cli_args_ssh(self): 63 | man_file_path = "./tests/man/ssh.1" 64 | _, schema_arguments = schemagen.man_schema(man_file_path) 65 | 66 | # Test that 67 | # - args are in correct order despite being specified in wrong order 68 | # - the -4 flag does not have "True as the argument" 69 | # - `-A` is excluded because it's false 70 | # - -E does have its argument 71 | # - the operand "destination" does not have an argument name 72 | tool_call = { 73 | "destination": "user@example.org", 74 | "4": True, 75 | "E": "/tmp/log", 76 | "A": False, 77 | } 78 | self.assertEqual( 79 | schemagen.get_cli_args(tool_call, schema_arguments), 80 | ["-4", "-E", "/tmp/log", "user@example.org"], 81 | ) 82 | 83 | def test_get_cli_args_ssh_two_operands(self): 84 | man_file_path = "./tests/man/ssh.1" 85 | _, schema_arguments = schemagen.man_schema(man_file_path) 86 | 87 | # Two operands 88 | tool_call = { 89 | "4": True, 90 | "E": "/tmp/log", 91 | "destination": "user@example.org", 92 | "command": 'echo "test"', 93 | } 94 | self.assertEqual( 95 | schemagen.get_cli_args(tool_call, schema_arguments), 96 | [ 97 | "-4", 98 | "-E", 99 | "/tmp/log", 100 | "user@example.org", 101 | 'echo "test"', 102 | ], 103 | ) 104 | 105 | def test_get_cli_args_ssh_optional_args(self): 106 | man_file_path = "./tests/man/ssh.1" 107 | _, schema_arguments = schemagen.man_schema(man_file_path) 108 | # argument with an optional part `[−w local_tun[:remote_tun]]` 109 | tool_call = { 110 | "4": True, 111 | "E": "/tmp/log", 112 | "destination": "user@example.org", 113 | "w": "8888", 114 | } 115 | self.assertEqual( 116 | schemagen.get_cli_args(tool_call, schema_arguments), 117 | [ 118 | "-4", 119 | "-E", 120 | "/tmp/log", 121 | "-w", 122 | "8888", 123 | "user@example.org", 124 | ], 125 | ) 126 | 127 | tool_call = { 128 | "4": True, 129 | "E": "/tmp/log", 130 | "destination": "user@example.org", 131 | "w": "8888:8888", 132 | } 133 | self.assertEqual( 134 | schemagen.get_cli_args(tool_call, schema_arguments), 135 | [ 136 | "-4", 137 | "-E", 138 | "/tmp/log", 139 | "-w", 140 | "8888:8888", 141 | "user@example.org", 142 | ], 143 | ) 144 | 145 | 146 | if __name__ == "__main__": 147 | unittest.main() 148 | -------------------------------------------------------------------------------- /tests/man/ssh.1: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" Author: Tatu Ylonen 3 | .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland 4 | .\" All rights reserved 5 | .\" 6 | .\" As far as I am concerned, the code I have written for this software 7 | .\" can be used freely for any purpose. Any derived versions of this 8 | .\" software must be clearly marked as such, and if the derived work is 9 | .\" incompatible with the protocol description in the RFC file, it must be 10 | .\" called by a name other than "ssh" or "Secure Shell". 11 | .\" 12 | .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. 13 | .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. 14 | .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. 15 | .\" 16 | .\" Redistribution and use in source and binary forms, with or without 17 | .\" modification, are permitted provided that the following conditions 18 | .\" are met: 19 | .\" 1. Redistributions of source code must retain the above copyright 20 | .\" notice, this list of conditions and the following disclaimer. 21 | .\" 2. Redistributions in binary form must reproduce the above copyright 22 | .\" notice, this list of conditions and the following disclaimer in the 23 | .\" documentation and/or other materials provided with the distribution. 24 | .\" 25 | .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 | .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 | .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 | .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 | .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | .\" 36 | .\" $OpenBSD: ssh.1,v 1.410 2020/02/07 03:54:44 dtucker Exp $ 37 | .Dd $Mdocdate: February 7 2020 $ 38 | .Dt SSH 1 39 | .Os 40 | .Sh NAME 41 | .Nm ssh 42 | .Nd OpenSSH remote login client 43 | .Sh SYNOPSIS 44 | .Nm ssh 45 | .Op Fl 46AaCfGgKkMNnqsTtVvXxYy 46 | .Op Fl B Ar bind_interface 47 | .Op Fl b Ar bind_address 48 | .Op Fl c Ar cipher_spec 49 | .Op Fl D Oo Ar bind_address : Oc Ns Ar port 50 | .Op Fl E Ar log_file 51 | .Op Fl e Ar escape_char 52 | .Op Fl F Ar configfile 53 | .Op Fl I Ar pkcs11 54 | .Op Fl i Ar identity_file 55 | .Op Fl J Ar destination 56 | .Op Fl L Ar address 57 | .Op Fl l Ar login_name 58 | .Op Fl m Ar mac_spec 59 | .Op Fl O Ar ctl_cmd 60 | .Op Fl o Ar option 61 | .Op Fl p Ar port 62 | .Op Fl Q Ar query_option 63 | .Op Fl R Ar address 64 | .Op Fl S Ar ctl_path 65 | .Op Fl W Ar host : Ns Ar port 66 | .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun 67 | .Ar destination 68 | .Op Ar command 69 | .Sh DESCRIPTION 70 | .Nm 71 | (SSH client) is a program for logging into a remote machine and for 72 | executing commands on a remote machine. 73 | It is intended to provide secure encrypted communications between 74 | two untrusted hosts over an insecure network. 75 | X11 connections, arbitrary TCP ports and 76 | .Ux Ns -domain 77 | sockets can also be forwarded over the secure channel. 78 | .Pp 79 | .Nm 80 | connects and logs into the specified 81 | .Ar destination , 82 | which may be specified as either 83 | .Sm off 84 | .Oo user @ Oc hostname 85 | .Sm on 86 | or a URI of the form 87 | .Sm off 88 | .No ssh:// Oo user @ Oc hostname Op : port . 89 | .Sm on 90 | The user must prove 91 | his/her identity to the remote machine using one of several methods 92 | (see below). 93 | .Pp 94 | If a 95 | .Ar command 96 | is specified, 97 | it is executed on the remote host instead of a login shell. 98 | .Pp 99 | The options are as follows: 100 | .Pp 101 | .Bl -tag -width Ds -compact 102 | .It Fl 4 103 | Forces 104 | .Nm 105 | to use IPv4 addresses only. 106 | .Pp 107 | .It Fl 6 108 | Forces 109 | .Nm 110 | to use IPv6 addresses only. 111 | .Pp 112 | .It Fl A 113 | Enables forwarding of connections from an authentication agent such as 114 | .Xr ssh-agent 1 . 115 | This can also be specified on a per-host basis in a configuration file. 116 | .Pp 117 | Agent forwarding should be enabled with caution. 118 | Users with the ability to bypass file permissions on the remote host 119 | (for the agent's 120 | .Ux Ns -domain 121 | socket) can access the local agent through the forwarded connection. 122 | An attacker cannot obtain key material from the agent, 123 | however they can perform operations on the keys that enable them to 124 | authenticate using the identities loaded into the agent. 125 | A safer alternative may be to use a jump host 126 | (see 127 | .Fl J ) . 128 | .Pp 129 | .It Fl a 130 | Disables forwarding of the authentication agent connection. 131 | .Pp 132 | .It Fl B Ar bind_interface 133 | Bind to the address of 134 | .Ar bind_interface 135 | before attempting to connect to the destination host. 136 | This is only useful on systems with more than one address. 137 | .Pp 138 | .It Fl b Ar bind_address 139 | Use 140 | .Ar bind_address 141 | on the local machine as the source address 142 | of the connection. 143 | Only useful on systems with more than one address. 144 | .Pp 145 | .It Fl C 146 | Requests compression of all data (including stdin, stdout, stderr, and 147 | data for forwarded X11, TCP and 148 | .Ux Ns -domain 149 | connections). 150 | The compression algorithm is the same used by 151 | .Xr gzip 1 . 152 | Compression is desirable on modem lines and other 153 | slow connections, but will only slow down things on fast networks. 154 | The default value can be set on a host-by-host basis in the 155 | configuration files; see the 156 | .Cm Compression 157 | option. 158 | .Pp 159 | .It Fl c Ar cipher_spec 160 | Selects the cipher specification for encrypting the session. 161 | .Ar cipher_spec 162 | is a comma-separated list of ciphers 163 | listed in order of preference. 164 | See the 165 | .Cm Ciphers 166 | keyword in 167 | .Xr ssh_config 5 168 | for more information. 169 | .Pp 170 | .It Fl D Xo 171 | .Sm off 172 | .Oo Ar bind_address : Oc 173 | .Ar port 174 | .Sm on 175 | .Xc 176 | Specifies a local 177 | .Dq dynamic 178 | application-level port forwarding. 179 | This works by allocating a socket to listen to 180 | .Ar port 181 | on the local side, optionally bound to the specified 182 | .Ar bind_address . 183 | Whenever a connection is made to this port, the 184 | connection is forwarded over the secure channel, and the application 185 | protocol is then used to determine where to connect to from the 186 | remote machine. 187 | Currently the SOCKS4 and SOCKS5 protocols are supported, and 188 | .Nm 189 | will act as a SOCKS server. 190 | Only root can forward privileged ports. 191 | Dynamic port forwardings can also be specified in the configuration file. 192 | .Pp 193 | IPv6 addresses can be specified by enclosing the address in square brackets. 194 | Only the superuser can forward privileged ports. 195 | By default, the local port is bound in accordance with the 196 | .Cm GatewayPorts 197 | setting. 198 | However, an explicit 199 | .Ar bind_address 200 | may be used to bind the connection to a specific address. 201 | The 202 | .Ar bind_address 203 | of 204 | .Dq localhost 205 | indicates that the listening port be bound for local use only, while an 206 | empty address or 207 | .Sq * 208 | indicates that the port should be available from all interfaces. 209 | .Pp 210 | .It Fl E Ar log_file 211 | Append debug logs to 212 | .Ar log_file 213 | instead of standard error. 214 | .Pp 215 | .It Fl e Ar escape_char 216 | Sets the escape character for sessions with a pty (default: 217 | .Ql ~ ) . 218 | The escape character is only recognized at the beginning of a line. 219 | The escape character followed by a dot 220 | .Pq Ql \&. 221 | closes the connection; 222 | followed by control-Z suspends the connection; 223 | and followed by itself sends the escape character once. 224 | Setting the character to 225 | .Dq none 226 | disables any escapes and makes the session fully transparent. 227 | .Pp 228 | .It Fl F Ar configfile 229 | Specifies an alternative per-user configuration file. 230 | If a configuration file is given on the command line, 231 | the system-wide configuration file 232 | .Pq Pa /etc/ssh/ssh_config 233 | will be ignored. 234 | The default for the per-user configuration file is 235 | .Pa ~/.ssh/config . 236 | .Pp 237 | .It Fl f 238 | Requests 239 | .Nm 240 | to go to background just before command execution. 241 | This is useful if 242 | .Nm 243 | is going to ask for passwords or passphrases, but the user 244 | wants it in the background. 245 | This implies 246 | .Fl n . 247 | The recommended way to start X11 programs at a remote site is with 248 | something like 249 | .Ic ssh -f host xterm . 250 | .Pp 251 | If the 252 | .Cm ExitOnForwardFailure 253 | configuration option is set to 254 | .Dq yes , 255 | then a client started with 256 | .Fl f 257 | will wait for all remote port forwards to be successfully established 258 | before placing itself in the background. 259 | .Pp 260 | .It Fl G 261 | Causes 262 | .Nm 263 | to print its configuration after evaluating 264 | .Cm Host 265 | and 266 | .Cm Match 267 | blocks and exit. 268 | .Pp 269 | .It Fl g 270 | Allows remote hosts to connect to local forwarded ports. 271 | If used on a multiplexed connection, then this option must be specified 272 | on the master process. 273 | .Pp 274 | .It Fl I Ar pkcs11 275 | Specify the PKCS#11 shared library 276 | .Nm 277 | should use to communicate with a PKCS#11 token providing keys for user 278 | authentication. 279 | .Pp 280 | .It Fl i Ar identity_file 281 | Selects a file from which the identity (private key) for 282 | public key authentication is read. 283 | The default is 284 | .Pa ~/.ssh/id_dsa , 285 | .Pa ~/.ssh/id_ecdsa , 286 | .Pa ~/.ssh/id_ecdsa_sk , 287 | .Pa ~/.ssh/id_ed25519 , 288 | .Pa ~/.ssh/id_ed25519_sk 289 | and 290 | .Pa ~/.ssh/id_rsa . 291 | Identity files may also be specified on 292 | a per-host basis in the configuration file. 293 | It is possible to have multiple 294 | .Fl i 295 | options (and multiple identities specified in 296 | configuration files). 297 | If no certificates have been explicitly specified by the 298 | .Cm CertificateFile 299 | directive, 300 | .Nm 301 | will also try to load certificate information from the filename obtained 302 | by appending 303 | .Pa -cert.pub 304 | to identity filenames. 305 | .Pp 306 | .It Fl J Ar destination 307 | Connect to the target host by first making a 308 | .Nm 309 | connection to the jump host described by 310 | .Ar destination 311 | and then establishing a TCP forwarding to the ultimate destination from 312 | there. 313 | Multiple jump hops may be specified separated by comma characters. 314 | This is a shortcut to specify a 315 | .Cm ProxyJump 316 | configuration directive. 317 | Note that configuration directives supplied on the command-line generally 318 | apply to the destination host and not any specified jump hosts. 319 | Use 320 | .Pa ~/.ssh/config 321 | to specify configuration for jump hosts. 322 | .Pp 323 | .It Fl K 324 | Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI 325 | credentials to the server. 326 | .Pp 327 | .It Fl k 328 | Disables forwarding (delegation) of GSSAPI credentials to the server. 329 | .Pp 330 | .It Fl L Xo 331 | .Sm off 332 | .Oo Ar bind_address : Oc 333 | .Ar port : host : hostport 334 | .Sm on 335 | .Xc 336 | .It Fl L Xo 337 | .Sm off 338 | .Oo Ar bind_address : Oc 339 | .Ar port : remote_socket 340 | .Sm on 341 | .Xc 342 | .It Fl L Xo 343 | .Sm off 344 | .Ar local_socket : host : hostport 345 | .Sm on 346 | .Xc 347 | .It Fl L Xo 348 | .Sm off 349 | .Ar local_socket : remote_socket 350 | .Sm on 351 | .Xc 352 | Specifies that connections to the given TCP port or Unix socket on the local 353 | (client) host are to be forwarded to the given host and port, or Unix socket, 354 | on the remote side. 355 | This works by allocating a socket to listen to either a TCP 356 | .Ar port 357 | on the local side, optionally bound to the specified 358 | .Ar bind_address , 359 | or to a Unix socket. 360 | Whenever a connection is made to the local port or socket, the 361 | connection is forwarded over the secure channel, and a connection is 362 | made to either 363 | .Ar host 364 | port 365 | .Ar hostport , 366 | or the Unix socket 367 | .Ar remote_socket , 368 | from the remote machine. 369 | .Pp 370 | Port forwardings can also be specified in the configuration file. 371 | Only the superuser can forward privileged ports. 372 | IPv6 addresses can be specified by enclosing the address in square brackets. 373 | .Pp 374 | By default, the local port is bound in accordance with the 375 | .Cm GatewayPorts 376 | setting. 377 | However, an explicit 378 | .Ar bind_address 379 | may be used to bind the connection to a specific address. 380 | The 381 | .Ar bind_address 382 | of 383 | .Dq localhost 384 | indicates that the listening port be bound for local use only, while an 385 | empty address or 386 | .Sq * 387 | indicates that the port should be available from all interfaces. 388 | .Pp 389 | .It Fl l Ar login_name 390 | Specifies the user to log in as on the remote machine. 391 | This also may be specified on a per-host basis in the configuration file. 392 | .Pp 393 | .It Fl M 394 | Places the 395 | .Nm 396 | client into 397 | .Dq master 398 | mode for connection sharing. 399 | Multiple 400 | .Fl M 401 | options places 402 | .Nm 403 | into 404 | .Dq master 405 | mode but with confirmation required using 406 | .Xr ssh-askpass 1 407 | before each operation that changes the multiplexing state 408 | (e.g. opening a new session). 409 | Refer to the description of 410 | .Cm ControlMaster 411 | in 412 | .Xr ssh_config 5 413 | for details. 414 | .Pp 415 | .It Fl m Ar mac_spec 416 | A comma-separated list of MAC (message authentication code) algorithms, 417 | specified in order of preference. 418 | See the 419 | .Cm MACs 420 | keyword for more information. 421 | .Pp 422 | .It Fl N 423 | Do not execute a remote command. 424 | This is useful for just forwarding ports. 425 | .Pp 426 | .It Fl n 427 | Redirects stdin from 428 | .Pa /dev/null 429 | (actually, prevents reading from stdin). 430 | This must be used when 431 | .Nm 432 | is run in the background. 433 | A common trick is to use this to run X11 programs on a remote machine. 434 | For example, 435 | .Ic ssh -n shadows.cs.hut.fi emacs & 436 | will start an emacs on shadows.cs.hut.fi, and the X11 437 | connection will be automatically forwarded over an encrypted channel. 438 | The 439 | .Nm 440 | program will be put in the background. 441 | (This does not work if 442 | .Nm 443 | needs to ask for a password or passphrase; see also the 444 | .Fl f 445 | option.) 446 | .Pp 447 | .It Fl O Ar ctl_cmd 448 | Control an active connection multiplexing master process. 449 | When the 450 | .Fl O 451 | option is specified, the 452 | .Ar ctl_cmd 453 | argument is interpreted and passed to the master process. 454 | Valid commands are: 455 | .Dq check 456 | (check that the master process is running), 457 | .Dq forward 458 | (request forwardings without command execution), 459 | .Dq cancel 460 | (cancel forwardings), 461 | .Dq exit 462 | (request the master to exit), and 463 | .Dq stop 464 | (request the master to stop accepting further multiplexing requests). 465 | .Pp 466 | .It Fl o Ar option 467 | Can be used to give options in the format used in the configuration file. 468 | This is useful for specifying options for which there is no separate 469 | command-line flag. 470 | For full details of the options listed below, and their possible values, see 471 | .Xr ssh_config 5 . 472 | .Pp 473 | .Bl -tag -width Ds -offset indent -compact 474 | .It AddKeysToAgent 475 | .It AddressFamily 476 | .It BatchMode 477 | .It BindAddress 478 | .It CanonicalDomains 479 | .It CanonicalizeFallbackLocal 480 | .It CanonicalizeHostname 481 | .It CanonicalizeMaxDots 482 | .It CanonicalizePermittedCNAMEs 483 | .It CASignatureAlgorithms 484 | .It CertificateFile 485 | .It ChallengeResponseAuthentication 486 | .It CheckHostIP 487 | .It Ciphers 488 | .It ClearAllForwardings 489 | .It Compression 490 | .It ConnectionAttempts 491 | .It ConnectTimeout 492 | .It ControlMaster 493 | .It ControlPath 494 | .It ControlPersist 495 | .It DynamicForward 496 | .It EscapeChar 497 | .It ExitOnForwardFailure 498 | .It FingerprintHash 499 | .It ForwardAgent 500 | .It ForwardX11 501 | .It ForwardX11Timeout 502 | .It ForwardX11Trusted 503 | .It GatewayPorts 504 | .It GlobalKnownHostsFile 505 | .It GSSAPIAuthentication 506 | .It GSSAPIKeyExchange 507 | .It GSSAPIClientIdentity 508 | .It GSSAPIDelegateCredentials 509 | .It GSSAPIKexAlgorithms 510 | .It GSSAPIRenewalForcesRekey 511 | .It GSSAPIServerIdentity 512 | .It GSSAPITrustDns 513 | .It HashKnownHosts 514 | .It Host 515 | .It HostbasedAuthentication 516 | .It HostbasedKeyTypes 517 | .It HostKeyAlgorithms 518 | .It HostKeyAlias 519 | .It Hostname 520 | .It IdentitiesOnly 521 | .It IdentityAgent 522 | .It IdentityFile 523 | .It IPQoS 524 | .It KbdInteractiveAuthentication 525 | .It KbdInteractiveDevices 526 | .It KexAlgorithms 527 | .It LocalCommand 528 | .It LocalForward 529 | .It LogLevel 530 | .It MACs 531 | .It Match 532 | .It NoHostAuthenticationForLocalhost 533 | .It NumberOfPasswordPrompts 534 | .It PasswordAuthentication 535 | .It PermitLocalCommand 536 | .It PKCS11Provider 537 | .It Port 538 | .It PreferredAuthentications 539 | .It ProxyCommand 540 | .It ProxyJump 541 | .It ProxyUseFdpass 542 | .It PubkeyAcceptedKeyTypes 543 | .It PubkeyAuthentication 544 | .It RekeyLimit 545 | .It RemoteCommand 546 | .It RemoteForward 547 | .It RequestTTY 548 | .It SendEnv 549 | .It ServerAliveInterval 550 | .It ServerAliveCountMax 551 | .It SetEnv 552 | .It StreamLocalBindMask 553 | .It StreamLocalBindUnlink 554 | .It StrictHostKeyChecking 555 | .It TCPKeepAlive 556 | .It Tunnel 557 | .It TunnelDevice 558 | .It UpdateHostKeys 559 | .It User 560 | .It UserKnownHostsFile 561 | .It VerifyHostKeyDNS 562 | .It VisualHostKey 563 | .It XAuthLocation 564 | .El 565 | .Pp 566 | .It Fl p Ar port 567 | Port to connect to on the remote host. 568 | This can be specified on a 569 | per-host basis in the configuration file. 570 | .Pp 571 | .It Fl Q Ar query_option 572 | Queries 573 | .Nm 574 | for the algorithms supported for the specified version 2. 575 | The available features are: 576 | .Ar cipher 577 | (supported symmetric ciphers), 578 | .Ar cipher-auth 579 | (supported symmetric ciphers that support authenticated encryption), 580 | .Ar help 581 | (supported query terms for use with the 582 | .Fl Q 583 | flag), 584 | .Ar mac 585 | (supported message integrity codes), 586 | .Ar kex 587 | (key exchange algorithms), 588 | .Ar kex-gss 589 | (GSSAPI key exchange algorithms), 590 | .Ar key 591 | (key types), 592 | .Ar key-cert 593 | (certificate key types), 594 | .Ar key-plain 595 | (non-certificate key types), 596 | .Ar key-sig 597 | (all key types and signature algorithms), 598 | .Ar protocol-version 599 | (supported SSH protocol versions), and 600 | .Ar sig 601 | (supported signature algorithms). 602 | Alternatively, any keyword from 603 | .Xr ssh_config 5 604 | or 605 | .Xr sshd_config 5 606 | that takes an algorithm list may be used as an alias for the corresponding 607 | query_option. 608 | .Pp 609 | .It Fl q 610 | Quiet mode. 611 | Causes most warning and diagnostic messages to be suppressed. 612 | .Pp 613 | .It Fl R Xo 614 | .Sm off 615 | .Oo Ar bind_address : Oc 616 | .Ar port : host : hostport 617 | .Sm on 618 | .Xc 619 | .It Fl R Xo 620 | .Sm off 621 | .Oo Ar bind_address : Oc 622 | .Ar port : local_socket 623 | .Sm on 624 | .Xc 625 | .It Fl R Xo 626 | .Sm off 627 | .Ar remote_socket : host : hostport 628 | .Sm on 629 | .Xc 630 | .It Fl R Xo 631 | .Sm off 632 | .Ar remote_socket : local_socket 633 | .Sm on 634 | .Xc 635 | .It Fl R Xo 636 | .Sm off 637 | .Oo Ar bind_address : Oc 638 | .Ar port 639 | .Sm on 640 | .Xc 641 | Specifies that connections to the given TCP port or Unix socket on the remote 642 | (server) host are to be forwarded to the local side. 643 | .Pp 644 | This works by allocating a socket to listen to either a TCP 645 | .Ar port 646 | or to a Unix socket on the remote side. 647 | Whenever a connection is made to this port or Unix socket, the 648 | connection is forwarded over the secure channel, and a connection 649 | is made from the local machine to either an explicit destination specified by 650 | .Ar host 651 | port 652 | .Ar hostport , 653 | or 654 | .Ar local_socket , 655 | or, if no explicit destination was specified, 656 | .Nm 657 | will act as a SOCKS 4/5 proxy and forward connections to the destinations 658 | requested by the remote SOCKS client. 659 | .Pp 660 | Port forwardings can also be specified in the configuration file. 661 | Privileged ports can be forwarded only when 662 | logging in as root on the remote machine. 663 | IPv6 addresses can be specified by enclosing the address in square brackets. 664 | .Pp 665 | By default, TCP listening sockets on the server will be bound to the loopback 666 | interface only. 667 | This may be overridden by specifying a 668 | .Ar bind_address . 669 | An empty 670 | .Ar bind_address , 671 | or the address 672 | .Ql * , 673 | indicates that the remote socket should listen on all interfaces. 674 | Specifying a remote 675 | .Ar bind_address 676 | will only succeed if the server's 677 | .Cm GatewayPorts 678 | option is enabled (see 679 | .Xr sshd_config 5 ) . 680 | .Pp 681 | If the 682 | .Ar port 683 | argument is 684 | .Ql 0 , 685 | the listen port will be dynamically allocated on the server and reported 686 | to the client at run time. 687 | When used together with 688 | .Ic -O forward 689 | the allocated port will be printed to the standard output. 690 | .Pp 691 | .It Fl S Ar ctl_path 692 | Specifies the location of a control socket for connection sharing, 693 | or the string 694 | .Dq none 695 | to disable connection sharing. 696 | Refer to the description of 697 | .Cm ControlPath 698 | and 699 | .Cm ControlMaster 700 | in 701 | .Xr ssh_config 5 702 | for details. 703 | .Pp 704 | .It Fl s 705 | May be used to request invocation of a subsystem on the remote system. 706 | Subsystems facilitate the use of SSH 707 | as a secure transport for other applications (e.g.\& 708 | .Xr sftp 1 ) . 709 | The subsystem is specified as the remote command. 710 | .Pp 711 | .It Fl T 712 | Disable pseudo-terminal allocation. 713 | .Pp 714 | .It Fl t 715 | Force pseudo-terminal allocation. 716 | This can be used to execute arbitrary 717 | screen-based programs on a remote machine, which can be very useful, 718 | e.g. when implementing menu services. 719 | Multiple 720 | .Fl t 721 | options force tty allocation, even if 722 | .Nm 723 | has no local tty. 724 | .Pp 725 | .It Fl V 726 | Display the version number and exit. 727 | .Pp 728 | .It Fl v 729 | Verbose mode. 730 | Causes 731 | .Nm 732 | to print debugging messages about its progress. 733 | This is helpful in 734 | debugging connection, authentication, and configuration problems. 735 | Multiple 736 | .Fl v 737 | options increase the verbosity. 738 | The maximum is 3. 739 | .Pp 740 | .It Fl W Ar host : Ns Ar port 741 | Requests that standard input and output on the client be forwarded to 742 | .Ar host 743 | on 744 | .Ar port 745 | over the secure channel. 746 | Implies 747 | .Fl N , 748 | .Fl T , 749 | .Cm ExitOnForwardFailure 750 | and 751 | .Cm ClearAllForwardings , 752 | though these can be overridden in the configuration file or using 753 | .Fl o 754 | command line options. 755 | .Pp 756 | .It Fl w Xo 757 | .Ar local_tun Ns Op : Ns Ar remote_tun 758 | .Xc 759 | Requests 760 | tunnel 761 | device forwarding with the specified 762 | .Xr tun 4 763 | devices between the client 764 | .Pq Ar local_tun 765 | and the server 766 | .Pq Ar remote_tun . 767 | .Pp 768 | The devices may be specified by numerical ID or the keyword 769 | .Dq any , 770 | which uses the next available tunnel device. 771 | If 772 | .Ar remote_tun 773 | is not specified, it defaults to 774 | .Dq any . 775 | See also the 776 | .Cm Tunnel 777 | and 778 | .Cm TunnelDevice 779 | directives in 780 | .Xr ssh_config 5 . 781 | .Pp 782 | If the 783 | .Cm Tunnel 784 | directive is unset, it will be set to the default tunnel mode, which is 785 | .Dq point-to-point . 786 | If a different 787 | .Cm Tunnel 788 | forwarding mode it desired, then it should be specified before 789 | .Fl w . 790 | .Pp 791 | .It Fl X 792 | Enables X11 forwarding. 793 | This can also be specified on a per-host basis in a configuration file. 794 | .Pp 795 | X11 forwarding should be enabled with caution. 796 | Users with the ability to bypass file permissions on the remote host 797 | (for the user's X authorization database) 798 | can access the local X11 display through the forwarded connection. 799 | An attacker may then be able to perform activities such as keystroke monitoring. 800 | .Pp 801 | For this reason, X11 forwarding is subjected to X11 SECURITY extension 802 | restrictions by default. 803 | Please refer to the 804 | .Nm 805 | .Fl Y 806 | option and the 807 | .Cm ForwardX11Trusted 808 | directive in 809 | .Xr ssh_config 5 810 | for more information. 811 | .Pp 812 | (Debian-specific: X11 forwarding is not subjected to X11 SECURITY extension 813 | restrictions by default, because too many programs currently crash in this 814 | mode. 815 | Set the 816 | .Cm ForwardX11Trusted 817 | option to 818 | .Dq no 819 | to restore the upstream behaviour. 820 | This may change in future depending on client-side improvements.) 821 | .Pp 822 | .It Fl x 823 | Disables X11 forwarding. 824 | .Pp 825 | .It Fl Y 826 | Enables trusted X11 forwarding. 827 | Trusted X11 forwardings are not subjected to the X11 SECURITY extension 828 | controls. 829 | .Pp 830 | (Debian-specific: In the default configuration, this option is equivalent to 831 | .Fl X , 832 | since 833 | .Cm ForwardX11Trusted 834 | defaults to 835 | .Dq yes 836 | as described above. 837 | Set the 838 | .Cm ForwardX11Trusted 839 | option to 840 | .Dq no 841 | to restore the upstream behaviour. 842 | This may change in future depending on client-side improvements.) 843 | .Pp 844 | .It Fl y 845 | Send log information using the 846 | .Xr syslog 3 847 | system module. 848 | By default this information is sent to stderr. 849 | .El 850 | .Pp 851 | .Nm 852 | may additionally obtain configuration data from 853 | a per-user configuration file and a system-wide configuration file. 854 | The file format and configuration options are described in 855 | .Xr ssh_config 5 . 856 | .Sh AUTHENTICATION 857 | The OpenSSH SSH client supports SSH protocol 2. 858 | .Pp 859 | The methods available for authentication are: 860 | GSSAPI-based authentication, 861 | host-based authentication, 862 | public key authentication, 863 | challenge-response authentication, 864 | and password authentication. 865 | Authentication methods are tried in the order specified above, 866 | though 867 | .Cm PreferredAuthentications 868 | can be used to change the default order. 869 | .Pp 870 | Host-based authentication works as follows: 871 | If the machine the user logs in from is listed in 872 | .Pa /etc/hosts.equiv 873 | or 874 | .Pa /etc/ssh/shosts.equiv 875 | on the remote machine, and the user names are 876 | the same on both sides, or if the files 877 | .Pa ~/.rhosts 878 | or 879 | .Pa ~/.shosts 880 | exist in the user's home directory on the 881 | remote machine and contain a line containing the name of the client 882 | machine and the name of the user on that machine, the user is 883 | considered for login. 884 | Additionally, the server 885 | .Em must 886 | be able to verify the client's 887 | host key (see the description of 888 | .Pa /etc/ssh/ssh_known_hosts 889 | and 890 | .Pa ~/.ssh/known_hosts , 891 | below) 892 | for login to be permitted. 893 | This authentication method closes security holes due to IP 894 | spoofing, DNS spoofing, and routing spoofing. 895 | [Note to the administrator: 896 | .Pa /etc/hosts.equiv , 897 | .Pa ~/.rhosts , 898 | and the rlogin/rsh protocol in general, are inherently insecure and should be 899 | disabled if security is desired.] 900 | .Pp 901 | Public key authentication works as follows: 902 | The scheme is based on public-key cryptography, 903 | using cryptosystems 904 | where encryption and decryption are done using separate keys, 905 | and it is unfeasible to derive the decryption key from the encryption key. 906 | The idea is that each user creates a public/private 907 | key pair for authentication purposes. 908 | The server knows the public key, and only the user knows the private key. 909 | .Nm 910 | implements public key authentication protocol automatically, 911 | using one of the DSA, ECDSA, Ed25519 or RSA algorithms. 912 | The HISTORY section of 913 | .Xr ssl 8 914 | (on non-OpenBSD systems, see 915 | .nh 916 | http://www.openbsd.org/cgi\-bin/man.cgi?query=ssl&sektion=8#HISTORY) 917 | .hy 918 | contains a brief discussion of the DSA and RSA algorithms. 919 | .Pp 920 | The file 921 | .Pa ~/.ssh/authorized_keys 922 | lists the public keys that are permitted for logging in. 923 | When the user logs in, the 924 | .Nm 925 | program tells the server which key pair it would like to use for 926 | authentication. 927 | The client proves that it has access to the private key 928 | and the server checks that the corresponding public key 929 | is authorized to accept the account. 930 | .Pp 931 | The server may inform the client of errors that prevented public key 932 | authentication from succeeding after authentication completes using a 933 | different method. 934 | These may be viewed by increasing the 935 | .Cm LogLevel 936 | to 937 | .Cm DEBUG 938 | or higher (e.g. by using the 939 | .Fl v 940 | flag). 941 | .Pp 942 | The user creates his/her key pair by running 943 | .Xr ssh-keygen 1 . 944 | This stores the private key in 945 | .Pa ~/.ssh/id_dsa 946 | (DSA), 947 | .Pa ~/.ssh/id_ecdsa 948 | (ECDSA), 949 | .Pa ~/.ssh/id_ecdsa_sk 950 | (authenticator-hosted ECDSA), 951 | .Pa ~/.ssh/id_ed25519 952 | (Ed25519), 953 | .Pa ~/.ssh/id_ed25519_sk 954 | (authenticator-hosted Ed25519), 955 | or 956 | .Pa ~/.ssh/id_rsa 957 | (RSA) 958 | and stores the public key in 959 | .Pa ~/.ssh/id_dsa.pub 960 | (DSA), 961 | .Pa ~/.ssh/id_ecdsa.pub 962 | (ECDSA), 963 | .Pa ~/.ssh/id_ecdsa_sk.pub 964 | (authenticator-hosted ECDSA), 965 | .Pa ~/.ssh/id_ed25519.pub 966 | (Ed25519), 967 | .Pa ~/.ssh/id_ed25519_sk.pub 968 | (authenticator-hosted Ed25519), 969 | or 970 | .Pa ~/.ssh/id_rsa.pub 971 | (RSA) 972 | in the user's home directory. 973 | The user should then copy the public key 974 | to 975 | .Pa ~/.ssh/authorized_keys 976 | in his/her home directory on the remote machine. 977 | The 978 | .Pa authorized_keys 979 | file corresponds to the conventional 980 | .Pa ~/.rhosts 981 | file, and has one key 982 | per line, though the lines can be very long. 983 | After this, the user can log in without giving the password. 984 | .Pp 985 | A variation on public key authentication 986 | is available in the form of certificate authentication: 987 | instead of a set of public/private keys, 988 | signed certificates are used. 989 | This has the advantage that a single trusted certification authority 990 | can be used in place of many public/private keys. 991 | See the CERTIFICATES section of 992 | .Xr ssh-keygen 1 993 | for more information. 994 | .Pp 995 | The most convenient way to use public key or certificate authentication 996 | may be with an authentication agent. 997 | See 998 | .Xr ssh-agent 1 999 | and (optionally) the 1000 | .Cm AddKeysToAgent 1001 | directive in 1002 | .Xr ssh_config 5 1003 | for more information. 1004 | .Pp 1005 | Challenge-response authentication works as follows: 1006 | The server sends an arbitrary 1007 | .Qq challenge 1008 | text, and prompts for a response. 1009 | Examples of challenge-response authentication include 1010 | .Bx 1011 | Authentication (see 1012 | .Xr login.conf 5 ) 1013 | and PAM (some 1014 | .Pf non- Ox 1015 | systems). 1016 | .Pp 1017 | Finally, if other authentication methods fail, 1018 | .Nm 1019 | prompts the user for a password. 1020 | The password is sent to the remote 1021 | host for checking; however, since all communications are encrypted, 1022 | the password cannot be seen by someone listening on the network. 1023 | .Pp 1024 | .Nm 1025 | automatically maintains and checks a database containing 1026 | identification for all hosts it has ever been used with. 1027 | Host keys are stored in 1028 | .Pa ~/.ssh/known_hosts 1029 | in the user's home directory. 1030 | Additionally, the file 1031 | .Pa /etc/ssh/ssh_known_hosts 1032 | is automatically checked for known hosts. 1033 | Any new hosts are automatically added to the user's file. 1034 | If a host's identification ever changes, 1035 | .Nm 1036 | warns about this and disables password authentication to prevent 1037 | server spoofing or man-in-the-middle attacks, 1038 | which could otherwise be used to circumvent the encryption. 1039 | The 1040 | .Cm StrictHostKeyChecking 1041 | option can be used to control logins to machines whose 1042 | host key is not known or has changed. 1043 | .Pp 1044 | When the user's identity has been accepted by the server, the server 1045 | either executes the given command in a non-interactive session or, 1046 | if no command has been specified, logs into the machine and gives 1047 | the user a normal shell as an interactive session. 1048 | All communication with 1049 | the remote command or shell will be automatically encrypted. 1050 | .Pp 1051 | If an interactive session is requested 1052 | .Nm 1053 | by default will only request a pseudo-terminal (pty) for interactive 1054 | sessions when the client has one. 1055 | The flags 1056 | .Fl T 1057 | and 1058 | .Fl t 1059 | can be used to override this behaviour. 1060 | .Pp 1061 | If a pseudo-terminal has been allocated the 1062 | user may use the escape characters noted below. 1063 | .Pp 1064 | If no pseudo-terminal has been allocated, 1065 | the session is transparent and can be used to reliably transfer binary data. 1066 | On most systems, setting the escape character to 1067 | .Dq none 1068 | will also make the session transparent even if a tty is used. 1069 | .Pp 1070 | The session terminates when the command or shell on the remote 1071 | machine exits and all X11 and TCP connections have been closed. 1072 | .Sh ESCAPE CHARACTERS 1073 | When a pseudo-terminal has been requested, 1074 | .Nm 1075 | supports a number of functions through the use of an escape character. 1076 | .Pp 1077 | A single tilde character can be sent as 1078 | .Ic ~~ 1079 | or by following the tilde by a character other than those described below. 1080 | The escape character must always follow a newline to be interpreted as 1081 | special. 1082 | The escape character can be changed in configuration files using the 1083 | .Cm EscapeChar 1084 | configuration directive or on the command line by the 1085 | .Fl e 1086 | option. 1087 | .Pp 1088 | The supported escapes (assuming the default 1089 | .Ql ~ ) 1090 | are: 1091 | .Bl -tag -width Ds 1092 | .It Cm ~. 1093 | Disconnect. 1094 | .It Cm ~^Z 1095 | Background 1096 | .Nm . 1097 | .It Cm ~# 1098 | List forwarded connections. 1099 | .It Cm ~& 1100 | Background 1101 | .Nm 1102 | at logout when waiting for forwarded connection / X11 sessions to terminate. 1103 | .It Cm ~? 1104 | Display a list of escape characters. 1105 | .It Cm ~B 1106 | Send a BREAK to the remote system 1107 | (only useful if the peer supports it). 1108 | .It Cm ~C 1109 | Open command line. 1110 | Currently this allows the addition of port forwardings using the 1111 | .Fl L , 1112 | .Fl R 1113 | and 1114 | .Fl D 1115 | options (see above). 1116 | It also allows the cancellation of existing port-forwardings 1117 | with 1118 | .Sm off 1119 | .Fl KL Oo Ar bind_address : Oc Ar port 1120 | .Sm on 1121 | for local, 1122 | .Sm off 1123 | .Fl KR Oo Ar bind_address : Oc Ar port 1124 | .Sm on 1125 | for remote and 1126 | .Sm off 1127 | .Fl KD Oo Ar bind_address : Oc Ar port 1128 | .Sm on 1129 | for dynamic port-forwardings. 1130 | .Ic !\& Ns Ar command 1131 | allows the user to execute a local command if the 1132 | .Ic PermitLocalCommand 1133 | option is enabled in 1134 | .Xr ssh_config 5 . 1135 | Basic help is available, using the 1136 | .Fl h 1137 | option. 1138 | .It Cm ~R 1139 | Request rekeying of the connection 1140 | (only useful if the peer supports it). 1141 | .It Cm ~V 1142 | Decrease the verbosity 1143 | .Pq Ic LogLevel 1144 | when errors are being written to stderr. 1145 | .It Cm ~v 1146 | Increase the verbosity 1147 | .Pq Ic LogLevel 1148 | when errors are being written to stderr. 1149 | .El 1150 | .Sh TCP FORWARDING 1151 | Forwarding of arbitrary TCP connections over a secure channel 1152 | can be specified either on the command line or in a configuration file. 1153 | One possible application of TCP forwarding is a secure connection to a 1154 | mail server; another is going through firewalls. 1155 | .Pp 1156 | In the example below, we look at encrypting communication for an IRC client, 1157 | even though the IRC server it connects to does not directly 1158 | support encrypted communication. 1159 | This works as follows: 1160 | the user connects to the remote host using 1161 | .Nm , 1162 | specifying the ports to be used to forward the connection. 1163 | After that it is possible to start the program locally, 1164 | and 1165 | .Nm 1166 | will encrypt and forward the connection to the remote server. 1167 | .Pp 1168 | The following example tunnels an IRC session from the client 1169 | to an IRC server at 1170 | .Dq server.example.com , 1171 | joining channel 1172 | .Dq #users , 1173 | nickname 1174 | .Dq pinky , 1175 | using the standard IRC port, 6667: 1176 | .Bd -literal -offset 4n 1177 | $ ssh -f -L 6667:localhost:6667 server.example.com sleep 10 1178 | $ irc -c '#users' pinky IRC/127.0.0.1 1179 | .Ed 1180 | .Pp 1181 | The 1182 | .Fl f 1183 | option backgrounds 1184 | .Nm 1185 | and the remote command 1186 | .Dq sleep 10 1187 | is specified to allow an amount of time 1188 | (10 seconds, in the example) 1189 | to start the program which is going to use the tunnel. 1190 | If no connections are made within the time specified, 1191 | .Nm 1192 | will exit. 1193 | .Sh X11 FORWARDING 1194 | If the 1195 | .Cm ForwardX11 1196 | variable is set to 1197 | .Dq yes 1198 | (or see the description of the 1199 | .Fl X , 1200 | .Fl x , 1201 | and 1202 | .Fl Y 1203 | options above) 1204 | and the user is using X11 (the 1205 | .Ev DISPLAY 1206 | environment variable is set), the connection to the X11 display is 1207 | automatically forwarded to the remote side in such a way that any X11 1208 | programs started from the shell (or command) will go through the 1209 | encrypted channel, and the connection to the real X server will be made 1210 | from the local machine. 1211 | The user should not manually set 1212 | .Ev DISPLAY . 1213 | Forwarding of X11 connections can be 1214 | configured on the command line or in configuration files. 1215 | .Pp 1216 | The 1217 | .Ev DISPLAY 1218 | value set by 1219 | .Nm 1220 | will point to the server machine, but with a display number greater than zero. 1221 | This is normal, and happens because 1222 | .Nm 1223 | creates a 1224 | .Dq proxy 1225 | X server on the server machine for forwarding the 1226 | connections over the encrypted channel. 1227 | .Pp 1228 | .Nm 1229 | will also automatically set up Xauthority data on the server machine. 1230 | For this purpose, it will generate a random authorization cookie, 1231 | store it in Xauthority on the server, and verify that any forwarded 1232 | connections carry this cookie and replace it by the real cookie when 1233 | the connection is opened. 1234 | The real authentication cookie is never 1235 | sent to the server machine (and no cookies are sent in the plain). 1236 | .Pp 1237 | If the 1238 | .Cm ForwardAgent 1239 | variable is set to 1240 | .Dq yes 1241 | (or see the description of the 1242 | .Fl A 1243 | and 1244 | .Fl a 1245 | options above) and 1246 | the user is using an authentication agent, the connection to the agent 1247 | is automatically forwarded to the remote side. 1248 | .Sh VERIFYING HOST KEYS 1249 | When connecting to a server for the first time, 1250 | a fingerprint of the server's public key is presented to the user 1251 | (unless the option 1252 | .Cm StrictHostKeyChecking 1253 | has been disabled). 1254 | Fingerprints can be determined using 1255 | .Xr ssh-keygen 1 : 1256 | .Pp 1257 | .Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key 1258 | .Pp 1259 | If the fingerprint is already known, it can be matched 1260 | and the key can be accepted or rejected. 1261 | If only legacy (MD5) fingerprints for the server are available, the 1262 | .Xr ssh-keygen 1 1263 | .Fl E 1264 | option may be used to downgrade the fingerprint algorithm to match. 1265 | .Pp 1266 | Because of the difficulty of comparing host keys 1267 | just by looking at fingerprint strings, 1268 | there is also support to compare host keys visually, 1269 | using 1270 | .Em random art . 1271 | By setting the 1272 | .Cm VisualHostKey 1273 | option to 1274 | .Dq yes , 1275 | a small ASCII graphic gets displayed on every login to a server, no matter 1276 | if the session itself is interactive or not. 1277 | By learning the pattern a known server produces, a user can easily 1278 | find out that the host key has changed when a completely different pattern 1279 | is displayed. 1280 | Because these patterns are not unambiguous however, a pattern that looks 1281 | similar to the pattern remembered only gives a good probability that the 1282 | host key is the same, not guaranteed proof. 1283 | .Pp 1284 | To get a listing of the fingerprints along with their random art for 1285 | all known hosts, the following command line can be used: 1286 | .Pp 1287 | .Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts 1288 | .Pp 1289 | If the fingerprint is unknown, 1290 | an alternative method of verification is available: 1291 | SSH fingerprints verified by DNS. 1292 | An additional resource record (RR), 1293 | SSHFP, 1294 | is added to a zonefile 1295 | and the connecting client is able to match the fingerprint 1296 | with that of the key presented. 1297 | .Pp 1298 | In this example, we are connecting a client to a server, 1299 | .Dq host.example.com . 1300 | The SSHFP resource records should first be added to the zonefile for 1301 | host.example.com: 1302 | .Bd -literal -offset indent 1303 | $ ssh-keygen -r host.example.com. 1304 | .Ed 1305 | .Pp 1306 | The output lines will have to be added to the zonefile. 1307 | To check that the zone is answering fingerprint queries: 1308 | .Pp 1309 | .Dl $ dig -t SSHFP host.example.com 1310 | .Pp 1311 | Finally the client connects: 1312 | .Bd -literal -offset indent 1313 | $ ssh -o "VerifyHostKeyDNS ask" host.example.com 1314 | [...] 1315 | Matching host key fingerprint found in DNS. 1316 | Are you sure you want to continue connecting (yes/no)? 1317 | .Ed 1318 | .Pp 1319 | See the 1320 | .Cm VerifyHostKeyDNS 1321 | option in 1322 | .Xr ssh_config 5 1323 | for more information. 1324 | .Sh SSH-BASED VIRTUAL PRIVATE NETWORKS 1325 | .Nm 1326 | contains support for Virtual Private Network (VPN) tunnelling 1327 | using the 1328 | .Xr tun 4 1329 | network pseudo-device, 1330 | allowing two networks to be joined securely. 1331 | The 1332 | .Xr sshd_config 5 1333 | configuration option 1334 | .Cm PermitTunnel 1335 | controls whether the server supports this, 1336 | and at what level (layer 2 or 3 traffic). 1337 | .Pp 1338 | The following example would connect client network 10.0.50.0/24 1339 | with remote network 10.0.99.0/24 using a point-to-point connection 1340 | from 10.1.1.1 to 10.1.1.2, 1341 | provided that the SSH server running on the gateway to the remote network, 1342 | at 192.168.1.15, allows it. 1343 | .Pp 1344 | On the client: 1345 | .Bd -literal -offset indent 1346 | # ssh -f -w 0:1 192.168.1.15 true 1347 | # ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252 1348 | # route add 10.0.99.0/24 10.1.1.2 1349 | .Ed 1350 | .Pp 1351 | On the server: 1352 | .Bd -literal -offset indent 1353 | # ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252 1354 | # route add 10.0.50.0/24 10.1.1.1 1355 | .Ed 1356 | .Pp 1357 | Client access may be more finely tuned via the 1358 | .Pa /root/.ssh/authorized_keys 1359 | file (see below) and the 1360 | .Cm PermitRootLogin 1361 | server option. 1362 | The following entry would permit connections on 1363 | .Xr tun 4 1364 | device 1 from user 1365 | .Dq jane 1366 | and on tun device 2 from user 1367 | .Dq john , 1368 | if 1369 | .Cm PermitRootLogin 1370 | is set to 1371 | .Dq forced-commands-only : 1372 | .Bd -literal -offset 2n 1373 | tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane 1374 | tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john 1375 | .Ed 1376 | .Pp 1377 | Since an SSH-based setup entails a fair amount of overhead, 1378 | it may be more suited to temporary setups, 1379 | such as for wireless VPNs. 1380 | More permanent VPNs are better provided by tools such as 1381 | .Xr ipsecctl 8 1382 | and 1383 | .Xr isakmpd 8 . 1384 | .Sh ENVIRONMENT 1385 | .Nm 1386 | will normally set the following environment variables: 1387 | .Bl -tag -width "SSH_ORIGINAL_COMMAND" 1388 | .It Ev DISPLAY 1389 | The 1390 | .Ev DISPLAY 1391 | variable indicates the location of the X11 server. 1392 | It is automatically set by 1393 | .Nm 1394 | to point to a value of the form 1395 | .Dq hostname:n , 1396 | where 1397 | .Dq hostname 1398 | indicates the host where the shell runs, and 1399 | .Sq n 1400 | is an integer \*(Ge 1. 1401 | .Nm 1402 | uses this special value to forward X11 connections over the secure 1403 | channel. 1404 | The user should normally not set 1405 | .Ev DISPLAY 1406 | explicitly, as that 1407 | will render the X11 connection insecure (and will require the user to 1408 | manually copy any required authorization cookies). 1409 | .It Ev HOME 1410 | Set to the path of the user's home directory. 1411 | .It Ev LOGNAME 1412 | Synonym for 1413 | .Ev USER ; 1414 | set for compatibility with systems that use this variable. 1415 | .It Ev MAIL 1416 | Set to the path of the user's mailbox. 1417 | .It Ev PATH 1418 | Set to the default 1419 | .Ev PATH , 1420 | as specified when compiling 1421 | .Nm . 1422 | .It Ev SSH_ASKPASS 1423 | If 1424 | .Nm 1425 | needs a passphrase, it will read the passphrase from the current 1426 | terminal if it was run from a terminal. 1427 | If 1428 | .Nm 1429 | does not have a terminal associated with it but 1430 | .Ev DISPLAY 1431 | and 1432 | .Ev SSH_ASKPASS 1433 | are set, it will execute the program specified by 1434 | .Ev SSH_ASKPASS 1435 | and open an X11 window to read the passphrase. 1436 | This is particularly useful when calling 1437 | .Nm 1438 | from a 1439 | .Pa .xsession 1440 | or related script. 1441 | (Note that on some machines it 1442 | may be necessary to redirect the input from 1443 | .Pa /dev/null 1444 | to make this work.) 1445 | .It Ev SSH_AUTH_SOCK 1446 | Identifies the path of a 1447 | .Ux Ns -domain 1448 | socket used to communicate with the agent. 1449 | .It Ev SSH_CONNECTION 1450 | Identifies the client and server ends of the connection. 1451 | The variable contains 1452 | four space-separated values: client IP address, client port number, 1453 | server IP address, and server port number. 1454 | .It Ev SSH_ORIGINAL_COMMAND 1455 | This variable contains the original command line if a forced command 1456 | is executed. 1457 | It can be used to extract the original arguments. 1458 | .It Ev SSH_TTY 1459 | This is set to the name of the tty (path to the device) associated 1460 | with the current shell or command. 1461 | If the current session has no tty, 1462 | this variable is not set. 1463 | .It Ev SSH_TUNNEL 1464 | Optionally set by 1465 | .Xr sshd 8 1466 | to contain the interface names assigned if tunnel forwarding was 1467 | requested by the client. 1468 | .It Ev SSH_USER_AUTH 1469 | Optionally set by 1470 | .Xr sshd 8 , 1471 | this variable may contain a pathname to a file that lists the authentication 1472 | methods successfully used when the session was established, including any 1473 | public keys that were used. 1474 | .It Ev TZ 1475 | This variable is set to indicate the present time zone if it 1476 | was set when the daemon was started (i.e. the daemon passes the value 1477 | on to new connections). 1478 | .It Ev USER 1479 | Set to the name of the user logging in. 1480 | .El 1481 | .Pp 1482 | Additionally, 1483 | .Nm 1484 | reads 1485 | .Pa ~/.ssh/environment , 1486 | and adds lines of the format 1487 | .Dq VARNAME=value 1488 | to the environment if the file exists and users are allowed to 1489 | change their environment. 1490 | For more information, see the 1491 | .Cm PermitUserEnvironment 1492 | option in 1493 | .Xr sshd_config 5 . 1494 | .Sh FILES 1495 | .Bl -tag -width Ds -compact 1496 | .It Pa ~/.rhosts 1497 | This file is used for host-based authentication (see above). 1498 | On some machines this file may need to be 1499 | world-readable if the user's home directory is on an NFS partition, 1500 | because 1501 | .Xr sshd 8 1502 | reads it as root. 1503 | Additionally, this file must be owned by the user, 1504 | and must not have write permissions for anyone else. 1505 | The recommended 1506 | permission for most machines is read/write for the user, and not 1507 | accessible by others. 1508 | .Pp 1509 | .It Pa ~/.shosts 1510 | This file is used in exactly the same way as 1511 | .Pa .rhosts , 1512 | but allows host-based authentication without permitting login with 1513 | rlogin/rsh. 1514 | .Pp 1515 | .It Pa ~/.ssh/ 1516 | This directory is the default location for all user-specific configuration 1517 | and authentication information. 1518 | There is no general requirement to keep the entire contents of this directory 1519 | secret, but the recommended permissions are read/write/execute for the user, 1520 | and not accessible by others. 1521 | .Pp 1522 | .It Pa ~/.ssh/authorized_keys 1523 | Lists the public keys (DSA, ECDSA, Ed25519, RSA) 1524 | that can be used for logging in as this user. 1525 | The format of this file is described in the 1526 | .Xr sshd 8 1527 | manual page. 1528 | This file is not highly sensitive, but the recommended 1529 | permissions are read/write for the user, and not accessible by others. 1530 | .Pp 1531 | .It Pa ~/.ssh/config 1532 | This is the per-user configuration file. 1533 | The file format and configuration options are described in 1534 | .Xr ssh_config 5 . 1535 | Because of the potential for abuse, this file must have strict permissions: 1536 | read/write for the user, and not writable by others. 1537 | It may be group-writable provided that the group in question contains only 1538 | the user. 1539 | .Pp 1540 | .It Pa ~/.ssh/environment 1541 | Contains additional definitions for environment variables; see 1542 | .Sx ENVIRONMENT , 1543 | above. 1544 | .Pp 1545 | .It Pa ~/.ssh/id_dsa 1546 | .It Pa ~/.ssh/id_ecdsa 1547 | .It Pa ~/.ssh/id_ecdsa_sk 1548 | .It Pa ~/.ssh/id_ed25519 1549 | .It Pa ~/.ssh/id_ed25519_sk 1550 | .It Pa ~/.ssh/id_rsa 1551 | Contains the private key for authentication. 1552 | These files 1553 | contain sensitive data and should be readable by the user but not 1554 | accessible by others (read/write/execute). 1555 | .Nm 1556 | will simply ignore a private key file if it is accessible by others. 1557 | It is possible to specify a passphrase when 1558 | generating the key which will be used to encrypt the 1559 | sensitive part of this file using AES-128. 1560 | .Pp 1561 | .It Pa ~/.ssh/id_dsa.pub 1562 | .It Pa ~/.ssh/id_ecdsa.pub 1563 | .It Pa ~/.ssh/id_ecdsa_sk.pub 1564 | .It Pa ~/.ssh/id_ed25519.pub 1565 | .It Pa ~/.ssh/id_ed25519_sk.pub 1566 | .It Pa ~/.ssh/id_rsa.pub 1567 | Contains the public key for authentication. 1568 | These files are not 1569 | sensitive and can (but need not) be readable by anyone. 1570 | .Pp 1571 | .It Pa ~/.ssh/known_hosts 1572 | Contains a list of host keys for all hosts the user has logged into 1573 | that are not already in the systemwide list of known host keys. 1574 | See 1575 | .Xr sshd 8 1576 | for further details of the format of this file. 1577 | .Pp 1578 | .It Pa ~/.ssh/rc 1579 | Commands in this file are executed by 1580 | .Nm 1581 | when the user logs in, just before the user's shell (or command) is 1582 | started. 1583 | See the 1584 | .Xr sshd 8 1585 | manual page for more information. 1586 | .Pp 1587 | .It Pa /etc/hosts.equiv 1588 | This file is for host-based authentication (see above). 1589 | It should only be writable by root. 1590 | .Pp 1591 | .It Pa /etc/ssh/shosts.equiv 1592 | This file is used in exactly the same way as 1593 | .Pa hosts.equiv , 1594 | but allows host-based authentication without permitting login with 1595 | rlogin/rsh. 1596 | .Pp 1597 | .It Pa /etc/ssh/ssh_config 1598 | Systemwide configuration file. 1599 | The file format and configuration options are described in 1600 | .Xr ssh_config 5 . 1601 | .Pp 1602 | .It Pa /etc/ssh/ssh_host_key 1603 | .It Pa /etc/ssh/ssh_host_dsa_key 1604 | .It Pa /etc/ssh/ssh_host_ecdsa_key 1605 | .It Pa /etc/ssh/ssh_host_ed25519_key 1606 | .It Pa /etc/ssh/ssh_host_rsa_key 1607 | These files contain the private parts of the host keys 1608 | and are used for host-based authentication. 1609 | .Pp 1610 | .It Pa /etc/ssh/ssh_known_hosts 1611 | Systemwide list of known host keys. 1612 | This file should be prepared by the 1613 | system administrator to contain the public host keys of all machines in the 1614 | organization. 1615 | It should be world-readable. 1616 | See 1617 | .Xr sshd 8 1618 | for further details of the format of this file. 1619 | .Pp 1620 | .It Pa /etc/ssh/sshrc 1621 | Commands in this file are executed by 1622 | .Nm 1623 | when the user logs in, just before the user's shell (or command) is started. 1624 | See the 1625 | .Xr sshd 8 1626 | manual page for more information. 1627 | .El 1628 | .Sh EXIT STATUS 1629 | .Nm 1630 | exits with the exit status of the remote command or with 255 1631 | if an error occurred. 1632 | .Sh SEE ALSO 1633 | .Xr scp 1 , 1634 | .Xr sftp 1 , 1635 | .Xr ssh-add 1 , 1636 | .Xr ssh-agent 1 , 1637 | .Xr ssh-argv0 1 , 1638 | .Xr ssh-keygen 1 , 1639 | .Xr ssh-keyscan 1 , 1640 | .Xr tun 4 , 1641 | .Xr ssh_config 5 , 1642 | .Xr ssh-keysign 8 , 1643 | .Xr sshd 8 1644 | .Sh STANDARDS 1645 | .Rs 1646 | .%A S. Lehtinen 1647 | .%A C. Lonvick 1648 | .%D January 2006 1649 | .%R RFC 4250 1650 | .%T The Secure Shell (SSH) Protocol Assigned Numbers 1651 | .Re 1652 | .Pp 1653 | .Rs 1654 | .%A T. Ylonen 1655 | .%A C. Lonvick 1656 | .%D January 2006 1657 | .%R RFC 4251 1658 | .%T The Secure Shell (SSH) Protocol Architecture 1659 | .Re 1660 | .Pp 1661 | .Rs 1662 | .%A T. Ylonen 1663 | .%A C. Lonvick 1664 | .%D January 2006 1665 | .%R RFC 4252 1666 | .%T The Secure Shell (SSH) Authentication Protocol 1667 | .Re 1668 | .Pp 1669 | .Rs 1670 | .%A T. Ylonen 1671 | .%A C. Lonvick 1672 | .%D January 2006 1673 | .%R RFC 4253 1674 | .%T The Secure Shell (SSH) Transport Layer Protocol 1675 | .Re 1676 | .Pp 1677 | .Rs 1678 | .%A T. Ylonen 1679 | .%A C. Lonvick 1680 | .%D January 2006 1681 | .%R RFC 4254 1682 | .%T The Secure Shell (SSH) Connection Protocol 1683 | .Re 1684 | .Pp 1685 | .Rs 1686 | .%A J. Schlyter 1687 | .%A W. Griffin 1688 | .%D January 2006 1689 | .%R RFC 4255 1690 | .%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints 1691 | .Re 1692 | .Pp 1693 | .Rs 1694 | .%A F. Cusack 1695 | .%A M. Forssen 1696 | .%D January 2006 1697 | .%R RFC 4256 1698 | .%T Generic Message Exchange Authentication for the Secure Shell Protocol (SSH) 1699 | .Re 1700 | .Pp 1701 | .Rs 1702 | .%A J. Galbraith 1703 | .%A P. Remaker 1704 | .%D January 2006 1705 | .%R RFC 4335 1706 | .%T The Secure Shell (SSH) Session Channel Break Extension 1707 | .Re 1708 | .Pp 1709 | .Rs 1710 | .%A M. Bellare 1711 | .%A T. Kohno 1712 | .%A C. Namprempre 1713 | .%D January 2006 1714 | .%R RFC 4344 1715 | .%T The Secure Shell (SSH) Transport Layer Encryption Modes 1716 | .Re 1717 | .Pp 1718 | .Rs 1719 | .%A B. Harris 1720 | .%D January 2006 1721 | .%R RFC 4345 1722 | .%T Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol 1723 | .Re 1724 | .Pp 1725 | .Rs 1726 | .%A M. Friedl 1727 | .%A N. Provos 1728 | .%A W. Simpson 1729 | .%D March 2006 1730 | .%R RFC 4419 1731 | .%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol 1732 | .Re 1733 | .Pp 1734 | .Rs 1735 | .%A J. Galbraith 1736 | .%A R. Thayer 1737 | .%D November 2006 1738 | .%R RFC 4716 1739 | .%T The Secure Shell (SSH) Public Key File Format 1740 | .Re 1741 | .Pp 1742 | .Rs 1743 | .%A D. Stebila 1744 | .%A J. Green 1745 | .%D December 2009 1746 | .%R RFC 5656 1747 | .%T Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer 1748 | .Re 1749 | .Pp 1750 | .Rs 1751 | .%A A. Perrig 1752 | .%A D. Song 1753 | .%D 1999 1754 | .%O International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99) 1755 | .%T Hash Visualization: a New Technique to improve Real-World Security 1756 | .Re 1757 | .Sh AUTHORS 1758 | OpenSSH is a derivative of the original and free 1759 | ssh 1.2.12 release by Tatu Ylonen. 1760 | Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, 1761 | Theo de Raadt and Dug Song 1762 | removed many bugs, re-added newer features and 1763 | created OpenSSH. 1764 | Markus Friedl contributed the support for SSH 1765 | protocol versions 1.5 and 2.0. 1766 | --------------------------------------------------------------------------------