.--~~~~~~~~~~~~~------.
/--===============------\
| |```````````````| |
| | | |
| | >_< | |
| | | |
| |_______________| |
| ::::|
'======================='
//-"-"-"-"-"-"-"-"-"-"-\\
//_"_"_"_"_"_"_"_"_"_"_"_\\
[-------------------------]
\_________________________/
Secure Shell Developer Guide
Secure Shell is a Chrome extension that combines hterm with a WASM build of OpenSSH to provide a PuTTY-like app for Chrome users.
See /HACK.md for general information about working with the source control setup.
The Secure Shell app depends on some library code from libapps/libdot/ and the hterm terminal emulator from in libapps/hterm/. To build these external dependencies, run...
nassh$ ./bin/mkdeps
This will create the various library dependencies that we use.
Secure Shell depends on compiled WASM programs to function, namely a port of OpenSSH. The latest version of the plugin is copied into nassh/plugin/ by nassh/bin/mkdeps. You can overwrite this with a different version if desired. Your options are (pick one):
# In the ssh_client/ directory. $ cp -a output/plugin/ ../nassh/
# In the nassh/ directory. $ ./bin/plugin
Loading directly from the checked out nassh directory is the normal way of testing. It will use the dev extension id to avoid conflicts with the stable extension id, although it will still conflict if you have the dev version installed from the Chrome Web Store (CWS).
The extension id is controlled by the key field in the manifest.json. See the manifest key docs for more details.
Now that your checkout is ready, you can load it into Chrome.
chrome://extensions page.nassh/ directory.If you‘re not running on ChromeOS device, and loading the app, you might see warnings right away about certain permissions (see the allowed sections below). You can ignore those. It’s unfortunate they show up with the same level/color as legitmate errors.
* 'file_system_provider_capabilities' is only allowed for extensions and packaged apps, but this is a legacy packaged app. * 'terminalPrivate' is not allowed for specified platform. * 'fileSystemProvider' is not allowed for specified platform.
Using the dev extension id is necessary in order to access some APIs that are allowed only for Secure Shell. If you don't need these features, you can get by with using a different id (and delete the settings from the manifest.json to avoid warnings at runtime).
terminalPrivate). (1) (2) (3)chrome.crashReportPrivate APIs. This allows users to opt-in to providing crash-reports. Not required to be able to use Secure Shell of course.chrome.metricsPrivate APIs. This allows users to opt-in to metrics/UMA collection about basic features. Not required to be able to use Secure Shell of course.fileSystemProvider and file_system_provider_capabilities). (1) To double check what & where things are allowed, search the Chromium code base for our extension ids:
The hashes are the SHA1's of the (lower case) extension id.
$ ext_id_hash() { printf "$1" | tr '[:upper:]' '[:lower:]' | sha1sum | tr '[:lower:]' '[:upper:]'; } $ ext_id_hash pnhechapfaindjhompbnflcldabbghjo 0EA6B717932AD64C469C1CCB6911457733295907
There are a few extensions we talk to for various services at runtime which need to allow our extension ids (for source verification). If you don't need any of these services, then you can ignore it.
If you try to load an unpacked extension using the stable extension id, you might run into problems if your administrator installs it via enterprise policy. If you see the error below, you won't be able to bypass it. Just use the dev extension id instead.
Secure Shell (extension ID "pnhechapfaindjhompbnflcldabbghjo") is blocked by the administrator.
While most of the UI code for crosh lives here (e.g. HTML/CSS/JS), the backend code and manifest lives in Chrome.
chrome.terminalPrivate JavaScript API.chrome.terminalPrivate JavaScript API.api/terminal/ code.See the libapps hacking document for details.
Keep in mind that the WASM ssh_client code does not live here.
The vast majority of the code here lives under js/.
*.concat.js: Compiled JS output of other projects we use.nassh object setup and glue code to Chrome runtime.CommandInstance launching code.nassh.relay.Corp code for proxying connections via Corp Relay protocol.nassh.Stream streams.*_tests.js: Each module has a corresponding set of unittests. The filename follows the convention of adding _tests. e.g. nassh_tests.js contains the tests for nassh.js.There are a few specialized modules that are not relevant to the core Secure Shell logic.
When the extension is launched (e.g. a new connection is opened), the background page is automatically created. This is used to monitor global state like extension updates and coordinate SFTP mounts. The logic lives in nassh_background_main.js and takes care of creating a new instance of nassh.App which it saves in the background page‘s app variable. If you aren’t looking at the SFTP logic, you can probably ignore this code.
When the extension is run, a new nassh.html window is shown. If no connection info is provided via the URL, then an iframe is created to show nassh_connect_dialog.html. Here the user manages their saved list of connections and picks the one they want to connect to. This logic is in nassh_connect_dialog.js. Once the user makes a selection (either connecting or mounting), a message is sent to nassh_command_instance.js. There the connection dialog is closed, the plugin is loaded, and the streams are connected to hterm.
Since the ssh program uses positive exit statuses, we tend to use -1 for internal exit states in the JS code. It doesn't matter too much as the exit values are purely for showing the user.
On ChromeOS, it is possible to mount remote paths via SFTP and the Files app. We currently support version 3 of the protocol. We don't support newer standards because the most popular implementation is OpenSSH's which only supports SFTPv3, and for the majority of Secure Shell users, they only interact with OpenSSH.
We could support newer versions, but they wouldn‘t be well tested, and not a lot of people would even use it, and it’s not like we'd see any performance improvements (as our operations tend to be basic open/read/write/close).
We support a few optional extensions to improve behavior or performance.
The SFTPv3 protocol says the argument order should be linkpath then the targetpath, but OpenSSH made a mistake and reversed the order. They can't change the order without breaking existing clients or servers, so they document it and leave it as-is.
We follow the OpenSSH SFTP Protocol here, as do many other clients.
SFTPv6 noted this desync between implementations and the specification and replaced the SSH_FXP_SYMLINK packet type with a new SSH_FXP_LINK.
The OpenSSH SFTP Protocol defines a fsync@openssh.com extension which takes an open handle and instructs the remote server to use the fsync() syscall.
We use this extension when the user has requested syncing after writes.
The OpenSSH SFTP Protocol defines a hardlink@openssh.com extension with the same API as SSH_FXP_SYMLINK.
We use this extension when the user has requested hardlinks explicitly.
The OpenSSH SFTP Protocol defines a posix-rename@openssh.com extension with the same API as SSH_FXP_RENAME, but uses the simple rename(2) semantics on the server. Otherwise, the default rename operation can be a bit buggy/racy.
We use this extension when available, or fallback to SSH_FXP_RENAME if not.
The OpenSSH SFTP Protocol defines a statvfs@openssh.com extension which returns the struct statvfs data from statvfs() syscall.
We use this extension when the user has requested filesystem statistics.
The copy-data extension is great for speeding up remote copies as it avoids having to download data from one file and uploading to a different one.
Here's a random list of documents which would be useful to people.