diff --git a/.golangci.yml b/.golangci.yml index 2ea8fb8..a4cad3d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,327 +1,160 @@ -# This file contains all available configuration options -# with their default values. - -# options for analysis running -run: - # default concurrency is a available CPU number - concurrency: 4 - - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 1m - - # exit code when at least one issue was found, default is 1 - issues-exit-code: 1 - - # include test files or not, default is true - tests: true - - # list of build tags, all linters use it. Default is empty list. - build-tags: - - mytag - - # which dirs to skip: issues from them won't be reported; - # can use regexp here: generated.*, regexp is applied on full path; - # default value is empty list, but default dirs are skipped independently - # from this option's value (see skip-dirs-use-default). - skip-dirs: - - src/external_libs - - autogenerated_by_my_lib - - # default is true. Enables skipping of directories: - # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ - skip-dirs-use-default: true - - # which files to skip: they will be analyzed, but issues from them - # won't be reported. Default value is empty list, but there is - # no need to include all autogenerated files, we confidently recognize - # autogenerated files. If it's not please let us know. - skip-files: - - ".*\\.my\\.go$" - - lib/bad.go - - # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules": - # If invoked with -mod=readonly, the go command is disallowed from the implicit - # automatic updating of go.mod described above. Instead, it fails when any changes - # to go.mod are needed. This setting is most useful to check that go.mod does - # not need updates, such as in a continuous integration and testing system. - # If invoked with -mod=vendor, the go command assumes that the vendor - # directory holds the correct copies of dependencies and ignores - # the dependency descriptions in go.mod. - #! modules-download-mode: readonly|release|vendor - - -# output configuration options -output: - # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - format: colored-line-number - - # print lines of code with issue, default is true - print-issued-lines: true - - # print linter name in the end of issue text, default is true - print-linter-name: true - - # make issues output unique by line, default is true - uniq-by-line: true - - -# all available settings of specific linters linters-settings: - dogsled: - # checks assignments with too many blank identifiers; default is 2 - max-blank-identifiers: 2 + depguard: + list-type: blacklist + packages: + # logging is allowed only by logutils.Log, logrus + # is allowed to use only in logutils package + - github.com/sirupsen/logrus + packages-with-error-message: + - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" dupl: - # tokens count to trigger issue, 150 by default - threshold: 100 - errcheck: - # report about not checking of errors in type assetions: `a := b.(MyStruct)`; - # default is false: such cases aren't reported by default. - check-type-assertions: false - - # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; - # default is false: such cases aren't reported by default. - check-blank: false - - # [deprecated] comma-separated list of pairs of the form pkg:regex - # the regex is used to ignore names within pkg. (default "fmt:.*"). - # see https://github.com/kisielk/errcheck#the-deprecated-method for details - ignore: fmt:.*,io/ioutil:^Read.* - - # path to a file containing a list of functions to exclude from checking - # see https://github.com/kisielk/errcheck#excluding-functions for details - #!exclude: /path/to/file.txt + threshold: 125 funlen: - lines: 60 - statements: 40 - gocognit: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 10 + lines: 125 + statements: 50 + gci: + local-prefixes: github.com/golangci/golangci-lint goconst: - # minimal length of string constant, 3 by default - min-len: 3 - # minimal occurrences count to trigger, 3 by default - min-occurrences: 3 + min-len: 2 + min-occurrences: 2 gocritic: - # Which checks should be enabled; can't be combined with 'disabled-checks'; - # See https://go-critic.github.io/overview#checks-overview - # To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run` - # By default list of stable checks is used. - enabled-checks: - #!- rangeValCopy - - # Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty - disabled-checks: - - regexpMust - - # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks. - # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". enabled-tags: + - diagnostic + - experimental - performance - - settings: # settings passed to gocritic - captLocal: # must be valid enabled check name - paramsOnly: true - rangeValCopy: - sizeThreshold: 32 + #- style + #- opinionated + disabled-checks: + - commentFormatting + - commentedOutCode + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - ifElseChain + - octalLiteral + - whyNoLint + - wrapperFunc gocyclo: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 10 - godox: - # report any comments starting with keywords, this is useful for TODO or FIXME comments that - # might be left in the code accidentally and should be resolved before merging - keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting - - NOTE - - OPTIMIZE # marks code that should be optimized before merging - - HACK # marks hack-arounds that should be removed before merging - gofmt: - # simplify code: gofmt with `-s` option, true by default - simplify: true + min-complexity: 15 goimports: - # put imports beginning with prefix after 3rd-party packages; - # it's a comma-separated list of prefixes - local-prefixes: github.com/org/project - golint: - # minimal confidence for issues, default is 0.8 - min-confidence: 0.8 + local-prefixes: github.com/golangci/golangci-lint gomnd: settings: mnd: - # the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. - checks: argument,case,condition,operation,return,assign + # don't include the "operation" and "assign" + checks: argument,case,condition,return govet: - # report about shadowed variables check-shadowing: true - - # settings per analyzer settings: - printf: # analyzer name, run `go tool vet help` to see all analyzers - funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer + printf: + funcs: - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf - - # enable or disable analyzers by name - enable: - - atomicalign - enable-all: false - disable: - - shadow - disable-all: false - depguard: - list-type: blacklist - include-go-root: false - packages: - - github.com/sirupsen/logrus - packages-with-error-message: - # specify an error message to output when a blacklisted package is used - - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" lll: - # max line length, lines longer will be reported. Default is 120. - # '\t' is counted as 1 character by default, and can be changed with the tab-width option - line-length: 120 - # tab width in spaces. Default to 1. - tab-width: 1 + line-length: 140 maligned: - # print struct with more effective memory layout or not, false by default suggest-new: true misspell: - # Correct spellings using locale preferences for US or UK. - # Default is to use a neutral variety of English. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. - locale: US - ignore-words: - - someword - nakedret: - # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 - max-func-lines: 30 - prealloc: - # XXX: we don't recommend using this linter before doing performance profiling. - # For most programs usage of prealloc will be a premature optimization. - - # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. - # True by default. - simple: true - range-loops: true # Report preallocation suggestions on range loops, true by default - for-loops: false # Report preallocation suggestions on for loops, false by default - rowserrcheck: - packages: - - github.com/jmoiron/sqlx - unparam: - # Inspect exported functions, default is false. Set to true if no external program/library imports your code. - # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: - # if it's called for subdir of a project it can't find external interfaces. All text editor integrations - # with golangci-lint call it on a directory with the changed file. - check-exported: false - unused: - # treat code as a program (not a library) and report unused exported identifiers; default is false. - # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: - # if it's called for subdir of a project it can't find funcs usages. All text editor integrations - # with golangci-lint call it on a directory with the changed file. - check-exported: false - whitespace: - multi-if: false # Enforces newlines (or comments) after every multi-line if statement - multi-func: false # Enforces newlines (or comments) after every multi-line function signature - wsl: - # If true append is only allowed to be cuddled if appending value is - # matching variables, fields or types on line above. Default is true. - strict-append: true - # Allow calls and assignments to be cuddled as long as the lines have any - # matching variables, fields or types. Default is true. - allow-assign-and-call: true - # Allow multiline assignments to be cuddled. Default is true. - allow-multiline-assign: true - # Allow declarations (var) to be cuddled. - allow-cuddle-declarations: false - # Allow trailing comments in ending of blocks - allow-trailing-comment: false - # Force newlines in end of case at this limit (0 = never). - force-case-trailing-whitespace: 0 - - # The custom section can be used to define linter plugins to be loaded at runtime. See README doc - # for more info. - custom: - # Each custom linter should have a unique name. - #! example: - #! # The path to the plugin *.so. Can be absolute or local. Required for each custom linter - #! path: /path/to/example.so - #! # The description of the linter. Optional, just for documentation purposes. - #! description: This is an example usage of a plugin linter. - #! # Intended to point to the repo location of the linter. Optional, just for documentation purposes. - #! original-url: github.com/golangci/example-linter + locale: en_CA + nolintlint: + allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) + allow-unused: false # report any unused nolint directives + require-explanation: false # don't require an explanation for nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped linters: + # please, do not use `enable-all`: it's deprecated and will be removed soon. + # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint + disable-all: true enable: - - megacheck + - bodyclose + - depguard + - dogsled + - dupl + - errcheck + - exhaustive + - exportloopref + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + #- golint + - gomnd + - goprintffuncname + - gosec + - gosimple - govet - disable: - - maligned - - prealloc - disable-all: false - presets: - - bugs + - ineffassign + #- interfacer + - lll + - misspell + #- nakedret + - noctx + - nolintlint + - rowserrcheck + #- scopelint + - staticcheck + #- structcheck + - stylecheck + - typecheck + - unconvert + - unparam - unused - fast: false + #- varcheck + - whitespace + # don't enable: + # - asciicheck + # - deadcode + # - gochecknoglobals + # - gocognit + # - godot + # - godox + # - goerr113 + # - golint + # - interfacer + # - maligned + # - nestif + # - prealloc + ## - rowserrcheck + # - scopelint + # - structcheck + # - testpackage + # - varcheck + # - wsl issues: - # List of regexps of issue texts to exclude, empty list by default. - # But independently from this option we use default exclude patterns, - # it can be disabled by `exclude-use-default: false`. To list all - # excluded by default patterns execute `golangci-lint run --help` - exclude: - - abcdef - # Excluding configuration per-path, per-linter, per-text and per-source exclude-rules: - # Exclude some linters from running on tests files. - path: _test\.go linters: - - gocyclo - - errcheck - - dupl - - gosec + - gomnd - # Exclude known linters from partially hard-vendored code, - # which is impossible to exclude via "nolint" comments. - - path: internal/hmac/ - text: "weak cryptographic primitive" - linters: - - gosec - - # Exclude some staticcheck messages + # https://github.com/go-critic/go-critic/issues/926 - linters: - - staticcheck - text: "SA9003:" + - gocritic + text: "unnecessaryDefer:" - # Exclude lll issues for long lines with go:generate - - linters: - - lll - source: "^//go:generate " + # TODO temporary rule, must be removed + # seems related to v0.34.1, but I was not able to reproduce locally, + # I was also not able to reproduce in the CI of a fork, + # only the golangci-lint CI seems to be affected by this invalid analysis. + - path: pkg/golinters/scopelint.go + text: 'directive `//nolint:interfacer` is unused for linter interfacer' - # Independently from option `exclude` we use default exclude patterns, - # it can be disabled by this option. To list all - # excluded by default patterns execute `golangci-lint run --help`. - # Default value for this option is true. - exclude-use-default: false +run: + skip-dirs: + - test/testdata_etc + - internal/cache + - internal/renameio + - internal/robustio - # Maximum issues count per one linter. Set to 0 to disable. Default is 50. - max-issues-per-linter: 0 - - # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. - max-same-issues: 0 - - # Show only new issues: if there are unstaged changes or untracked files, - # only those changes are analyzed, else only changes in HEAD~ are analyzed. - # It's a super-useful option for integration of golangci-lint into existing - # large codebase. It's not practical to fix all existing issues at the moment - # of integration: much better don't allow issues in new code. - # Default is false. - new: false - - # Show only new issues created after git revision `REV` - #!new-from-rev: REV - #new-from-rev: HEAD^ - - # Show only new issues created in git patch with set file path. - #!new-from-patch: path/to/patch/file +# golangci.com configuration +# https://github.com/golangci/golangci/wiki/Configuration +service: + golangci-lint-version: 1.23.x # use the fixed version to not introduce new linters unexpectedly + prepare: + - echo "here I can run custom commands, but no preparation needed for this repo" diff --git a/Makefile b/Makefile index 319723c..67eb22d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ -VERSION := 0.9.5.1 -.PHONY: lint vis clean common client server passwd subpkgs install uninstall reinstall - +VERSION := 0.9.11 +.PHONY: lint vis clean common client server passwd\ + subpkgs install uninstall reinstall scc + ## Tag version of binaries with build info wrt. ## GO111MODULE(=on) and vendor/ setup vs. $GOPATH pkg builds ############################################################ @@ -72,7 +73,7 @@ tools: common: $(GO) build . - go install . + go install -a . client: common @@ -86,6 +87,9 @@ else $(MAKE) BUILDOPTS=$(BUILDOPTS) -C xsd endif +scc: + @scc --exclude-dir=bacillus,vendor,garbled --cocomo-project-type=rlabs,3,1.12,1,1 + vis: @which go-callvis >/dev/null 2>&1; \ stat=$$?; if [ $$stat -ne "0" ]; then \ diff --git a/README.md b/README.md index ef6d2cc..c7278f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ [![GoDoc](https://godoc.org/blitter.com/go/xs?status.svg)](https://godoc.org/blitter.com/go/xs) # XS + +![last build status](https://bacillus.blitter.com/onPush-xs-build/lastStatusIcon) -- XS (**X**perimental **S**hell) is a simple alternative to ssh (<5% total SLOCC) written from scratch in Go. @@ -42,10 +44,12 @@ Currently supported session algorithms: * Blowfish-64 * CryptMTv1 (64bit) (https://eprint.iacr.org/2005/165.pdf) * ChaCha20 (https://github.com/aead/chacha20) +* HOPSCOTCH (https://gogs.blitter.com/Russtopia/hopscotch) [HMAC] * HMAC-SHA256 * HMAC-SHA512 +* WHIRLPOOL *** **A Note on 'cryptographic agility'** @@ -90,18 +94,6 @@ KYBER IND-CCA-2 KEM As of this time (Oct 2018) Kyber is one of the candidate algorithms submitted to the [NIST post-quantum cryptography project](https://csrc.nist.gov/Projects/Post-Quantum-Cryptography). The authors recommend using it in "... so-called hybrid mode in combination with established "pre-quantum" security; for example in combination with elliptic-curve Diffie-Hellman." THIS PROJECT DOES NOT DO THIS (in case you didn't notice yet, THIS PROJECT IS EXPERIMENTAL.) -### Dependencies: - -* Recent version of go (tested, at various times, with go-1.9 to go-1.12.4) -* [github.com/mattn/go-isatty](http://github.com/mattn/go-isatty) //terminal tty detection -* [github.com/kr/pty](http://github.com/kr/pty) //unix pty control (server pty connections) -* [github.com/jameskeane/bcrypt](http://github.com/jameskeane/bcrypt) //password storage/auth -* [blitter.com/go/goutmp](https://gogs.blitter.com/RLabs/goutmp) // wtmp/lastlog C bindings for user accounting -* [https://gitlab.com/yawning/kyber](https://gogs.blitter.com/RLabs/kyber) // golang Kyber KEM -* [https://gitlab.com/yawning/kyber](https://gogs.blitter.com/RLabs/newhope) // golang NEWHOPE,NEWHOPE-SIMPLE KEX -* [blitter.com/go/mtwist](https://gogs.blitter.com/RLabs/mtwist) // 64-bit Mersenne Twister PRNG -* [blitter.com/go/cryptmt](https://gogs.blitter.com/RLabs/cryptmt) // CryptMTv1 stream cipher - ### Installing @@ -195,10 +187,18 @@ or is interrupted. ### Setting up an 'authtoken' for scripted (password-free) logins Use the -g option of xs to request a token from the remote server, which will return a -hostname:token string. Place this string into $HOME/.xs_id to allow logins without -entering a password (obviously, $HOME/.xs_id on both server and client for the user +hostname:token string. Place this string into $HOME/.config/xs/.xs_id to allow logins without +entering a password (obviously, $HOME/.config/xs/.xs_id on both server and client for the user should *not* be world-readable.) +``` +$ xs -g user@host.net >>~/.config/xs/.xs_id +``` +[enter password blindly, authtoken entry will be stored in ~/.config/xs/.xs_id] + +NOTE you may need to remove older entries for the same host if this is not the first time you have added +it to your .xs_id file. + ### File Copying using xc xc is a symlink to xs, and the binary checks its own filename to determine whether diff --git a/auth.go b/auth.go index 5f4f2ed..cc3b042 100755 --- a/auth.go +++ b/auth.go @@ -23,6 +23,7 @@ import ( "runtime" "strings" + "blitter.com/go/xs/xsnet" "github.com/jameskeane/bcrypt" passlib "gopkg.in/hlandau/passlib.v1" ) @@ -52,7 +53,7 @@ func VerifyPass(ctx *AuthCtx, user, password string) (bool, error) { } else if runtime.GOOS == "freebsd" { pwFileName = "/etc/master.passwd" } else { - pwFileName = "unsupported" + return false, errors.New("Unsupported platform") } pwFileData, e := ctx.reader(pwFileName) if e != nil { @@ -154,7 +155,7 @@ func AuthUserByPasswd(ctx *AuthCtx, username string, auth string, fname string) // ------------- End xs-local passwd auth routine(s) ----------- // AuthUserByToken checks user login information against an auth token. -// Auth tokens are stored in each user's $HOME/.xs_id and are requested +// Auth tokens are stored in each user's $HOME/.config/xs/.xs_id and are requested // via the -g option. // The function also check system /etc/passwd to cross-check the user // actually exists. @@ -172,9 +173,9 @@ func AuthUserByToken(ctx *AuthCtx, username string, connhostname string, auth st return false } - b, e := ctx.reader(fmt.Sprintf("%s/.xs_id", u.HomeDir)) + b, e := ctx.reader(fmt.Sprintf("%s/%s", u.HomeDir, xsnet.XS_ID_AUTHTOKFILE)) if e != nil { - log.Printf("INFO: Cannot read %s/.xs_id\n", u.HomeDir) + log.Printf("INFO: Cannot read %s/%s\n", u.HomeDir, xsnet.XS_ID_AUTHTOKFILE) return false } diff --git a/bacillus/ci_pushbuild.sh b/bacillus/ci_pushbuild.sh index f69ee21..8cfe45f 100755 --- a/bacillus/ci_pushbuild.sh +++ b/bacillus/ci_pushbuild.sh @@ -5,7 +5,7 @@ export GOPATH="${HOME}/go" export PATH=/usr/local/bin:/usr/bin:/usr/lib/ccache/bin:/bin:$GOPATH/bin unset GO111MODULE -export GOPROXY="direct" +#export GOPROXY="direct" #!# GOCACHE will be phased out in v1.12. [github.com/golang/go/issues/26809] #!export GOCACHE="${HOME}/.cache/go-build" @@ -25,19 +25,14 @@ echo "Building most recent push on branch $branch" git checkout "$branch" ls -############ -stage "Build" -############ -echo "Recreating go.mod from scratch ..." -mv go.mod go.mod.git || true -mv go.sum go.sum.git || true go mod init go mod tidy -echo "Cleaning go mod cache ..." -go clean -modcache -echo "Cleaning go cache ..." -go clean -cache +############ +stage "Build" +############ +echo "Invoking 'make clean' ..." +make clean echo "Invoking 'make all' ..." make all @@ -54,12 +49,12 @@ go test -v . ############ stage "Test(Authtoken)" ############ -if [ -f ~/.xs_id ]; then - echo "Clearing test user $USER ~/.xs_id file ..." - mv ~/.xs_id ~/.xs_id.bak +if [ -f ~/.config/xs/.xs_id ]; then + echo "Clearing test user $USER .xs_id file ..." + mv ~/.config/xs/.xs_id ~/.config/xs/.xs_id.bak fi -echo "Setting dummy authtoken in ~/.xs_id ..." -echo "localhost:${USER}:asdfasdfasdf" >~/.xs_id +echo "Setting dummy authtoken in .xs_id ..." +echo "localhost:${USER}:asdfasdfasdf" >~/.config/xs/.xs_id echo "Performing remote command on @localhost via authtoken login ..." tokentest=$(timeout 10 xs -x "echo -n FOO" @localhost) if [ "${tokentest}" != "FOO" ]; then @@ -99,9 +94,9 @@ stage "Test(xc C->S)" ############ echo "TODO ..." -if [ -f ~/.xs_id.bak ]; then - echo "Restoring test user $USER ~/.xs_id file ..." - mv ~/.xs_id.bak ~/.xs_id +if [ -f ~/.config/xs/.xs_id.bak ]; then + echo "Restoring test user $USER .xs_id file ..." + mv ~/.config/xs/.xs_id.bak ~/.config/xs/.xs_id fi ############ diff --git a/go.mod b/go.mod deleted file mode 100644 index f711150..0000000 --- a/go.mod +++ /dev/null @@ -1,36 +0,0 @@ -module blitter.com/go/xs - -go 1.17 - -require ( - blitter.com/go/cryptmt v1.0.2 - blitter.com/go/goutmp v1.0.6 - blitter.com/go/herradurakex v1.0.0 - blitter.com/go/hopscotch v0.0.0-20211113042251-b8a306eea4dc - blitter.com/go/kyber v0.0.0-20200130200857-6f2021cb88d9 - blitter.com/go/newhope v0.0.0-20200130200750-192fc08a8aae - github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da - github.com/creack/pty v1.1.18 - github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f - github.com/kuking/go-frodokem v1.0.2 - github.com/mattn/go-isatty v0.0.14 - github.com/xtaci/kcp-go v5.4.20+incompatible - golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 - golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f - gopkg.in/hlandau/passlib.v1 v1.0.11 -) - -require ( - blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c // indirect - blitter.com/go/mtwist v1.0.1 // indirect - github.com/klauspost/cpuid/v2 v2.0.6 // indirect - github.com/klauspost/reedsolomon v1.9.16 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect - github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect - github.com/tjfoc/gmsm v1.4.1 // indirect - github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 // indirect - golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect - gopkg.in/hlandau/easymetric.v1 v1.0.0 // indirect - gopkg.in/hlandau/measurable.v1 v1.0.1 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 4217963..0000000 --- a/go.sum +++ /dev/null @@ -1,145 +0,0 @@ -blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c h1:LcnFFg6MCIJHf26P7eOUST45fNLHJI5erq0gWZaDLCo= -blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c/go.mod h1:EMJtRcf22WCtHGiXCw+NB/Sb/PYcXtUgUql6LDEwyXo= -blitter.com/go/cryptmt v1.0.2 h1:ZcLhQk7onUssXyQwG3GdXDXctCVnNL+b7aFuvwOdKXc= -blitter.com/go/cryptmt v1.0.2/go.mod h1:tdME2J3O4agaDAYIYNQzzuB28yVGnPSMmV3a/ucSU84= -blitter.com/go/goutmp v1.0.6 h1:jRKRw2WalVBza4T50etAfbvT2xp9G5uykIHTvyB5r0k= -blitter.com/go/goutmp v1.0.6/go.mod h1:DnK/uLBu1/1yLFiuVlmwvWErzAWVp+pDv7t6ZaQRLNc= -blitter.com/go/herradurakex v1.0.0 h1:6XaxY+JLT1HUWPF0gYJnjX3pVjrw4YhYZEzZ1U0wkyc= -blitter.com/go/herradurakex v1.0.0/go.mod h1:m3+vYZX+2dDjdo+n/HDnXEYJX9pwmNeQLgAfJM8mtxw= -blitter.com/go/hopscotch v0.0.0-20211113042251-b8a306eea4dc h1:IS+jxdKSdlqp6TWG3yMoBde/cctBEMwMDg588JHxgTE= -blitter.com/go/hopscotch v0.0.0-20211113042251-b8a306eea4dc/go.mod h1:9Da1oy0t9aUw3wviba+2mP1inbLGbDuCKAO3mmGQha4= -blitter.com/go/kyber v0.0.0-20200130200857-6f2021cb88d9 h1:D45AnrNphtvczBXRp5JQicZRTgaK/Is5bgPDDvRKhTc= -blitter.com/go/kyber v0.0.0-20200130200857-6f2021cb88d9/go.mod h1:SK6QfGG72lIfKW1Td0wH7f0wwN5nSIhV3K+wvzGNjrw= -blitter.com/go/mtwist v1.0.1 h1:PxmoWexfMpLmc8neHP/PcRc3s17ct7iz4d5W/qJVt04= -blitter.com/go/mtwist v1.0.1/go.mod h1:aU82Nx8+b1v8oZRNqImfEDzDTPim81rY0ACKAIclV18= -blitter.com/go/newhope v0.0.0-20200130200750-192fc08a8aae h1:YBBaCcdYRrI1btsmcMTv1VMPmaSXXz0RwKOTgMJYSRU= -blitter.com/go/newhope v0.0.0-20200130200750-192fc08a8aae/go.mod h1:ywoxfDBqInPsqtnxYsmS4SYMJ5D/kNcrFgpvI+Xcun0= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f h1:UWGE8Vi+1Agt0lrvnd7UsmvwqWKRzb9byK9iQmsbY0Y= -github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f/go.mod h1:u+9Snq0w+ZdYKi8BBoaxnEwWu0fY4Kvu9ByFpM51t1s= -github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI= -github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/reedsolomon v1.9.16 h1:mR0AwphBwqFv/I3B9AHtNKvzuowI1vrj8/3UX4XRmHA= -github.com/klauspost/reedsolomon v1.9.16/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= -github.com/kuking/go-frodokem v1.0.2 h1:sxdguENCyr6WnLbJ/cjz0AYCW75H1b+E6zXY2ldZnUU= -github.com/kuking/go-frodokem v1.0.2/go.mod h1:83ZX1kHOd72ouCsvbffCqJIj7Ih83MQTAjH2QbqzLZk= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= -github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= -github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= -github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= -github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= -github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= -github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= -github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg= -github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= -github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= -github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= -golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/hlandau/easymetric.v1 v1.0.0 h1:ZbfbH7W3giuVDjWUoFhDOjjv20hiPr5HZ2yMV5f9IeE= -gopkg.in/hlandau/easymetric.v1 v1.0.0/go.mod h1:yh75hypuFzAxmvECh3ZKGCvFnIfapYJh2wv7ASaX2RE= -gopkg.in/hlandau/measurable.v1 v1.0.1 h1:wH5UZKCRUnRr1iD+xIZfwhtxhmr+bprRJttqA1Rklf4= -gopkg.in/hlandau/measurable.v1 v1.0.1/go.mod h1:6N+SYJGMTmetsx7wskULP+juuO+++tsHJkAgzvzsbuM= -gopkg.in/hlandau/passlib.v1 v1.0.11 h1:vKeHwGRdWBD9mm4bJ56GAAdBXpFUYvg/BYYkmphjnmA= -gopkg.in/hlandau/passlib.v1 v1.0.11/go.mod h1:wxGAv2CtQHlzWY8NJp+p045yl4WHyX7v2T6XbOcmqjM= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/xs/mintty_wrapper.sh b/xs/mintty_wrapper.sh index 9cba8ff..dbc678a 100755 --- a/xs/mintty_wrapper.sh +++ b/xs/mintty_wrapper.sh @@ -1,7 +1,7 @@ #!/bin/bash # ## This wrapper may be used within the MSYS/mintty Windows -## shell environment to have a functioning hkexsh client with +## shell environment to have a functioning xs client with ## working 'raw' mode and hidden password entry. ## ## mintty uses named pipes and ptys to get a more POSIX-like diff --git a/xs/termsize_unix.go b/xs/termsize_unix.go index 410a243..112947a 100644 --- a/xs/termsize_unix.go +++ b/xs/termsize_unix.go @@ -1,3 +1,4 @@ +//go:build linux || freebsd // +build linux freebsd package main @@ -30,7 +31,7 @@ func handleTermResizes(conn *xsnet.Conn) { log.Println(err) } termSzPacket := fmt.Sprintf("%d %d", rows, cols) - conn.WritePacket([]byte(termSzPacket), xsnet.CSOTermSize) // nolint: errcheck,gosec + conn.WritePacket([]byte(termSzPacket), xsnet.CSOTermSize) //nolint:errcheck } }() ch <- syscall.SIGWINCH // Initial resize. diff --git a/xs/xs-vis-fixedup.png b/xs/xs-vis-fixedup.png index 3307bdd..1526a41 100644 Binary files a/xs/xs-vis-fixedup.png and b/xs/xs-vis-fixedup.png differ diff --git a/xs/xs-vis.gv b/xs/xs-vis.gv index 02e3c8d..c470a0e 100755 --- a/xs/xs-vis.gv +++ b/xs/xs-vis.gv @@ -10,207 +10,207 @@ digraph gocallvis { pad="0.0"; nodesep="0.35"; - node [shape="ellipse" style="filled" fillcolor="honeydew" fontname="Verdana" penwidth="1.0" margin="0.05,0.0"]; + node [shape="box" style="filled,rounded" fillcolor="honeydew" fontname="Verdana" penwidth="1.0" margin="0.05,0.0"]; edge [minlen="2"] subgraph "cluster_focus" { - label="main"; + bgcolor="#e6ecfa"; +label="main"; labelloc="t"; labeljust="c"; fontsize="18"; -bgcolor="#e6ecfa"; - "blitter.com/go/xs/xs.restoreTermState" [ fillcolor="lightblue" label="restoreTermState" penwidth="0.5" tooltip="blitter.com/go/xs/xs.restoreTermState | defined in xs.go:1095\nat xs.go:1096: calling [blitter.com/go/xs.Restore]" ] - "blitter.com/go/xs/xs.main$2" [ fillcolor="lightblue" label="deferCloseChaff" style="dotted,filled" tooltip="blitter.com/go/xs/xs.main$2 | defined in xs.go:974\nat xs.go:977: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:975: calling [blitter.com/go/xs/xs.restoreTermState]" ] - "blitter.com/go/xs/xs.exitWithStatus" [ fillcolor="lightblue" label="exitWithStatus" penwidth="0.5" tooltip="blitter.com/go/xs/xs.exitWithStatus | defined in xs.go:1100" ] - "blitter.com/go/xs/xs.handleTermResizes$1" [ label="handleTermResizes$1" style="dotted,filled" tooltip="blitter.com/go/xs/xs.handleTermResizes$1 | defined in termsize_unix.go:21\nat termsize_unix.go:27: calling [blitter.com/go/xs/xs.GetSize]\nat termsize_unix.go:33: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" fillcolor="lightblue" ] - "blitter.com/go/xs/xs.GetSize" [ tooltip="blitter.com/go/xs/xs.GetSize | defined in xs.go:221" fillcolor="lightblue" label="GetSize" penwidth="1.5" ] - "blitter.com/go/xs/xs.sendSessionParams" [ fillcolor="lightblue" label="sendSessionParams" penwidth="0.5" tooltip="blitter.com/go/xs/xs.sendSessionParams | defined in xs.go:649\nat xs.go:651: calling [(blitter.com/go/xs.Session).Who]\nat xs.go:659: calling [(blitter.com/go/xs.Session).Who]\nat xs.go:651: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xs.go:675: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xs.go:651: calling [(blitter.com/go/xs.Session).ConnHost]\nat xs.go:663: calling [(blitter.com/go/xs.Session).ConnHost]\nat xs.go:651: calling [(blitter.com/go/xs.Session).Op]\nat xs.go:655: calling [(blitter.com/go/xs.Session).Op]\nat xs.go:675: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:671: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:667: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:663: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:659: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:655: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:651: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:671: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:651: calling [(blitter.com/go/xs.Session).TermType]\nat xs.go:667: calling [(blitter.com/go/xs.Session).TermType]" ] - "blitter.com/go/xs/xs.main$3" [ label="main$3" style="dotted,filled" tooltip="blitter.com/go/xs/xs.main$3 | defined in xs.go:1043\nat xs.go:1046: calling [math/rand.Intn]\nat xs.go:1050: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" fillcolor="lightblue" ] - "blitter.com/go/xs/xs.handleTermResizes" [ fillcolor="lightblue" label="handleTermResizes" penwidth="0.5" tooltip="blitter.com/go/xs/xs.handleTermResizes | defined in termsize_unix.go:16\nat termsize_unix.go:21: calling [blitter.com/go/xs/xs.handleTermResizes$1]" ] - "blitter.com/go/xs/xs.main" [ penwidth="0.5" tooltip="blitter.com/go/xs/xs.main | defined in xs.go:680\nat xs.go:769: calling [blitter.com/go/xs/xs.main$1]\nat xs.go:782: calling [blitter.com/go/xs/xs.localUserName]\nat xs.go:1024: calling [blitter.com/go/xs/xs.rejectUserMsg]\nat xs.go:843: calling [blitter.com/go/xs/logger.New]\nat xs.go:938: calling [blitter.com/go/xs/xsnet.Dial]\nat xs.go:1003: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1021: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1025: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1064: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1005: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1067: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1069: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1079: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1053: calling [blitter.com/go/xs/xs.main$3]\nat xs.go:831: calling [blitter.com/go/xs/xs.usageShell]\nat xs.go:956: calling [blitter.com/go/xs.MakeRaw]\nat xs.go:1017: calling [(blitter.com/go/xs/xsnet.Conn).Read]\nat xs.go:1059: calling [blitter.com/go/xs/xs.launchTuns]\nat xs.go:1063: calling [blitter.com/go/xs/xs.doCopyMode]\nat xs.go:950: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xs.go:775: calling [blitter.com/go/xs/xs.parseNonSwitchArgs]\nat xs.go:962: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1032: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xs.go:1002: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1068: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1074: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:831: calling [blitter.com/go/xs/xs.usageCp]\nat xs.go:955: calling [github.com/mattn/go-isatty.IsTerminal]\nat xs.go:1000: calling [blitter.com/go/xs/xs.sendSessionParams]\nat xs.go:751: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:832: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:941: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1005: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1079: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:844: calling [blitter.com/go/xs/xsnet.Init]\nat xs.go:1028: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]\nat xs.go:983: calling [blitter.com/go/xs.ReadPassword]\nat xs.go:999: calling [blitter.com/go/xs.NewSession]\nat xs.go:1033: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]\nat xs.go:1034: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]\nat xs.go:1060: calling [blitter.com/go/xs/xs.doShellMode]" fillcolor="lightblue" label="main" ] - "blitter.com/go/xs/xs.parseNonSwitchArgs" [ tooltip="blitter.com/go/xs/xs.parseNonSwitchArgs | defined in xs.go:599" fillcolor="lightblue" label="parseNonSwitchArgs" penwidth="0.5" ] - "blitter.com/go/xs/xs.main$1" [ fillcolor="lightblue" label="deferRestore" style="dotted,filled" tooltip="blitter.com/go/xs/xs.main$1 | defined in xs.go:769" ] - "blitter.com/go/xs/xs.localUserName" [ fillcolor="lightblue" label="localUserName" penwidth="0.5" tooltip="blitter.com/go/xs/xs.localUserName | defined in xs.go:1084" ] - "blitter.com/go/xs/xs.rejectUserMsg" [ fillcolor="lightblue" label="rejectUserMsg" penwidth="0.5" tooltip="blitter.com/go/xs/xs.rejectUserMsg | defined in xs.go:576\nat xs.go:577: calling [blitter.com/go/xs/spinsult.GetSentence]" ] - "blitter.com/go/xs/xs.reqTunnel" [ penwidth="0.5" tooltip="blitter.com/go/xs/xs.reqTunnel | defined in xs.go:584\nat xs.go:594: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat xs.go:593: calling [blitter.com/go/xs/logger.LogDebug]" fillcolor="lightblue" label="reqTunnel" ] - "blitter.com/go/xs/xs.launchTuns" [ penwidth="0.5" tooltip="blitter.com/go/xs/xs.launchTuns | defined in xs.go:634\nat xs.go:645: calling [blitter.com/go/xs/xs.reqTunnel]" fillcolor="lightblue" label="launchTuns" ] - "blitter.com/go/xs/xs.doShellMode$1" [ tooltip="blitter.com/go/xs/xs.doShellMode$1 | defined in xs.go:490\nat xs.go:507: calling [(crypto/tls.alert).Error]\nat xs.go:503: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:518: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:509: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:519: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:507: calling [(compress/flate.InternalError).Error]\nat xs.go:507: calling [(crypto/aes.KeySizeError).Error]\nat xs.go:507: calling [(context.deadlineExceededError).Error]\nat xs.go:507: calling [(crypto/x509.UnhandledCriticalExtension).Error]\nat xs.go:514: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:519: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:507: calling [(crypto/x509.CertificateInvalidError).Error]\nat xs.go:507: calling [(crypto/tls.RecordHeaderError).Error]\nat xs.go:507: calling [(crypto/x509.HostnameError).Error]\nat xs.go:507: calling [(*github.com/pkg/errors.fundamental).Error]\nat xs.go:491: calling [blitter.com/go/xs/xs.doShellMode$1$1]\nat xs.go:507: calling [(*crypto/tls.permamentError).Error]\nat xs.go:507: calling [(crypto/x509.SystemRootsError).Error]\nat xs.go:507: calling [(compress/flate.CorruptInputError).Error]\nat xs.go:513: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:513: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:507: calling [(crypto/x509.UnknownAuthorityError).Error]" fillcolor="lightblue" label="shellRemoteToStdin" style="dotted,filled" ] - "blitter.com/go/xs/xs.doShellMode$1$1" [ fillcolor="lightblue" label="doShellMode$1$1" style="dotted,filled" tooltip="blitter.com/go/xs/xs.doShellMode$1$1 | defined in xs.go:491" ] - "blitter.com/go/xs/xs.doShellMode" [ fillcolor="lightblue" label="doShellMode" penwidth="0.5" tooltip="blitter.com/go/xs/xs.doShellMode | defined in xs.go:483\nat xs.go:527: calling [blitter.com/go/xs/xs.handleTermResizes]\nat xs.go:551: calling [blitter.com/go/xs/xs.doShellMode$2]\nat xs.go:522: calling [blitter.com/go/xs/xs.doShellMode$1]" ] - "blitter.com/go/xs/xs.copyBuffer" [ tooltip="blitter.com/go/xs/xs.copyBuffer | defined in xs.go:128\nat xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$2]\nat xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$3]\nat xs.go:193: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$1]" fillcolor="lightblue" label="copyBuffer" penwidth="0.5" ] - "blitter.com/go/xs/xs.copyBuffer$1" [ style="dotted,filled" tooltip="blitter.com/go/xs/xs.copyBuffer$1 | defined in xs.go:144" fillcolor="lightblue" label="copyBuffer$1" ] - "blitter.com/go/xs/xs.copyBuffer$2" [ tooltip="blitter.com/go/xs/xs.copyBuffer$2 | defined in xs.go:145" fillcolor="lightblue" label="copyBuffer$2" style="dotted,filled" ] - "blitter.com/go/xs/xs.copyBuffer$3" [ fillcolor="lightblue" label="copyBuffer$3" style="dotted,filled" tooltip="blitter.com/go/xs/xs.copyBuffer$3 | defined in xs.go:146" ] - "blitter.com/go/xs/xs.Copy" [ fillcolor="lightblue" label="Copy" penwidth="1.5" tooltip="blitter.com/go/xs/xs.Copy | defined in xs.go:115\nat xs.go:116: calling [blitter.com/go/xs/xs.copyBuffer]" ] - "blitter.com/go/xs/xs.doShellMode$2$1" [ tooltip="blitter.com/go/xs/xs.doShellMode$2$1 | defined in xs.go:536\nat xs.go:539: calling [blitter.com/go/xs/xs.Copy]" fillcolor="lightblue" label="doShellMode$2$1" style="dotted,filled" ] - "blitter.com/go/xs/xs.doShellMode$2" [ fillcolor="lightblue" label="shellStdinToRemote" style="dotted,filled" tooltip="blitter.com/go/xs/xs.doShellMode$2 | defined in xs.go:534\nat xs.go:546: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:548: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:541: calling [blitter.com/go/xs/xs.doShellMode$2$1]" ] - "blitter.com/go/xs/xs.doCopyMode" [ penwidth="0.5" tooltip="blitter.com/go/xs/xs.doCopyMode | defined in xs.go:354\nat xs.go:417: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat xs.go:356: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:441: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:430: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xs.go:424: calling [(blitter.com/go/xs/xsnet.Conn).Read]\nat xs.go:364: calling [blitter.com/go/xs/xs.buildCmdLocalToRemote]\nat xs.go:435: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:438: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:473: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:475: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:444: calling [blitter.com/go/xs/xs.buildCmdRemoteToLocal]" fillcolor="lightblue" label="doCopyMode" ] - "blitter.com/go/xs/xs.buildCmdLocalToRemote" [ fillcolor="lightblue" label="buildCmdLocalToRemote" penwidth="0.5" tooltip="blitter.com/go/xs/xs.buildCmdLocalToRemote | defined in xs.go:270\nat xs.go:335: calling [blitter.com/go/xs/xs.getTreeSizeSubCmd]\nat xs.go:283: calling [blitter.com/go/xs.GetTool]\nat xs.go:311: calling [blitter.com/go/xs.GetTool]\nat xs.go:312: calling [blitter.com/go/xs.GetTool]" ] + "blitter.com/go/xs/xs.restoreTermState" [ fillcolor="lightblue" label="restoreTermState" penwidth="0.5" tooltip="blitter.com/go/xs/xs.restoreTermState | defined in xs.go:1117\nat xs.go:1118: calling [blitter.com/go/xs.Restore]" ] + "blitter.com/go/xs/xs.main$2" [ fillcolor="lightblue" label="deferCloseChaff" style="dotted,filled" tooltip="blitter.com/go/xs/xs.main$2 | defined in xs.go:996\nat xs.go:999: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:997: calling [blitter.com/go/xs/xs.restoreTermState]" ] + "blitter.com/go/xs/xs.exitWithStatus" [ penwidth="0.5" tooltip="blitter.com/go/xs/xs.exitWithStatus | defined in xs.go:1122" fillcolor="lightblue" label="exitWithStatus" ] + "blitter.com/go/xs/xs.doCopyMode" [ fillcolor="lightblue" label="doCopyMode" penwidth="0.5" tooltip="blitter.com/go/xs/xs.doCopyMode | defined in xs.go:354\nat xs.go:435: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:438: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:473: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:475: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:430: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xs.go:444: calling [blitter.com/go/xs/xs.buildCmdRemoteToLocal]\nat xs.go:424: calling [(blitter.com/go/xs/xsnet.Conn).Read]\nat xs.go:356: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:441: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:417: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat xs.go:364: calling [blitter.com/go/xs/xs.buildCmdLocalToRemote]" ] + "blitter.com/go/xs/xs.buildCmdLocalToRemote" [ tooltip="blitter.com/go/xs/xs.buildCmdLocalToRemote | defined in xs.go:270\nat xs.go:283: calling [blitter.com/go/xs.GetTool]\nat xs.go:311: calling [blitter.com/go/xs.GetTool]\nat xs.go:312: calling [blitter.com/go/xs.GetTool]\nat xs.go:335: calling [blitter.com/go/xs/xs.getTreeSizeSubCmd]" fillcolor="lightblue" label="buildCmdLocalToRemote" penwidth="0.5" ] "blitter.com/go/xs/xs.getTreeSizeSubCmd" [ fillcolor="lightblue" label="getTreeSizeSubCmd" penwidth="0.5" tooltip="blitter.com/go/xs/xs.getTreeSizeSubCmd | defined in xs.go:342" ] "blitter.com/go/xs/xs.buildCmdRemoteToLocal" [ fillcolor="lightblue" label="buildCmdRemoteToLocal" penwidth="0.5" tooltip="blitter.com/go/xs/xs.buildCmdRemoteToLocal | defined in xs.go:244\nat xs.go:256: calling [blitter.com/go/xs.GetTool]\nat xs.go:263: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xs.usageShell" [ label="usageShell" penwidth="0.5" tooltip="blitter.com/go/xs/xs.usageShell | defined in xs.go:559" fillcolor="lightblue" ] - "blitter.com/go/xs/xs.usageCp" [ fillcolor="lightblue" label="usageCp" penwidth="0.5" tooltip="blitter.com/go/xs/xs.usageCp | defined in xs.go:565" ] + "blitter.com/go/xs/xs.copyBuffer" [ fillcolor="lightblue" label="copyBuffer" penwidth="0.5" tooltip="blitter.com/go/xs/xs.copyBuffer | defined in xs.go:128\nat xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$2]\nat xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$3]\nat xs.go:193: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$1]" ] + "blitter.com/go/xs/xs.copyBuffer$1" [ fillcolor="lightblue" label="copyBuffer$1" style="dotted,filled" tooltip="blitter.com/go/xs/xs.copyBuffer$1 | defined in xs.go:144" ] + "blitter.com/go/xs/xs.copyBuffer$2" [ fillcolor="lightblue" label="copyBuffer$2" style="dotted,filled" tooltip="blitter.com/go/xs/xs.copyBuffer$2 | defined in xs.go:145" ] + "blitter.com/go/xs/xs.copyBuffer$3" [ fillcolor="lightblue" label="copyBuffer$3" style="dotted,filled" tooltip="blitter.com/go/xs/xs.copyBuffer$3 | defined in xs.go:146" ] + "blitter.com/go/xs/xs.reqTunnel" [ tooltip="blitter.com/go/xs/xs.reqTunnel | defined in xs.go:584\nat xs.go:594: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat xs.go:593: calling [blitter.com/go/xs/logger.LogDebug]" fillcolor="lightblue" label="reqTunnel" penwidth="0.5" ] + "blitter.com/go/xs/xs.main" [ fillcolor="lightblue" label="main" penwidth="0.5" tooltip="blitter.com/go/xs/xs.main | defined in xs.go:680\nat xs.go:1056: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]\nat xs.go:1027: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1089: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1091: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1101: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:864: calling [blitter.com/go/xs/logger.New]\nat xs.go:978: calling [blitter.com/go/xs.MakeRaw]\nat xs.go:1075: calling [blitter.com/go/xs/xs.main$3]\nat xs.go:1039: calling [(blitter.com/go/xs/xsnet.Conn).Read]\nat xs.go:960: calling [blitter.com/go/xs/xsnet.Dial]\nat xs.go:1081: calling [blitter.com/go/xs/xs.launchTuns]\nat xs.go:977: calling [github.com/mattn/go-isatty.IsTerminal]\nat xs.go:772: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:853: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:963: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1027: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1101: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1082: calling [blitter.com/go/xs/xs.doShellMode]\nat xs.go:1050: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]\nat xs.go:1022: calling [blitter.com/go/xs/xs.sendSessionParams]\nat xs.go:796: calling [blitter.com/go/xs/xs.parseNonSwitchArgs]\nat xs.go:1024: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1090: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1096: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1055: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]\nat xs.go:1025: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1043: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1047: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1086: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:852: calling [blitter.com/go/xs/xs.usageShell]\nat xs.go:984: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1005: calling [blitter.com/go/xs.ReadPassword]\nat xs.go:1054: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xs.go:1085: calling [blitter.com/go/xs/xs.doCopyMode]\nat xs.go:972: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xs.go:1046: calling [blitter.com/go/xs/xs.rejectUserMsg]\nat xs.go:852: calling [blitter.com/go/xs/xs.usageCp]\nat xs.go:790: calling [blitter.com/go/xs/xs.main$1]\nat xs.go:803: calling [blitter.com/go/xs/xs.localUserName]\nat xs.go:865: calling [blitter.com/go/xs/xsnet.Init]\nat xs.go:1021: calling [blitter.com/go/xs.NewSession]" ] + "blitter.com/go/xs/xs.parseNonSwitchArgs" [ label="parseNonSwitchArgs" penwidth="0.5" tooltip="blitter.com/go/xs/xs.parseNonSwitchArgs | defined in xs.go:599" fillcolor="lightblue" ] + "blitter.com/go/xs/xs.main$1" [ fillcolor="lightblue" label="deferRestore" style="dotted,filled" tooltip="blitter.com/go/xs/xs.main$1 | defined in xs.go:790" ] + "blitter.com/go/xs/xs.localUserName" [ fillcolor="lightblue" label="localUserName" penwidth="0.5" tooltip="blitter.com/go/xs/xs.localUserName | defined in xs.go:1106" ] + "blitter.com/go/xs/xs.sendSessionParams" [ fillcolor="lightblue" label="sendSessionParams" penwidth="0.5" tooltip="blitter.com/go/xs/xs.sendSessionParams | defined in xs.go:649\nat xs.go:651: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:671: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:651: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xs.go:675: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xs.go:651: calling [(blitter.com/go/xs.Session).Who]\nat xs.go:659: calling [(blitter.com/go/xs.Session).Who]\nat xs.go:651: calling [(blitter.com/go/xs.Session).Op]\nat xs.go:655: calling [(blitter.com/go/xs.Session).Op]\nat xs.go:651: calling [(blitter.com/go/xs.Session).TermType]\nat xs.go:667: calling [(blitter.com/go/xs.Session).TermType]\nat xs.go:651: calling [(blitter.com/go/xs.Session).ConnHost]\nat xs.go:663: calling [(blitter.com/go/xs.Session).ConnHost]\nat xs.go:675: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:671: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:667: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:663: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:659: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:655: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] + "blitter.com/go/xs/xs.rejectUserMsg" [ fillcolor="lightblue" label="rejectUserMsg" penwidth="0.5" tooltip="blitter.com/go/xs/xs.rejectUserMsg | defined in xs.go:576\nat xs.go:577: calling [blitter.com/go/xs/spinsult.GetSentence]" ] + "blitter.com/go/xs/xs.main$3" [ fillcolor="lightblue" label="main$3" style="dotted,filled" tooltip="blitter.com/go/xs/xs.main$3 | defined in xs.go:1065\nat xs.go:1068: calling [math/rand.Intn]\nat xs.go:1072: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] + "blitter.com/go/xs/xs.launchTuns" [ fillcolor="lightblue" label="launchTuns" penwidth="0.5" tooltip="blitter.com/go/xs/xs.launchTuns | defined in xs.go:634\nat xs.go:645: calling [blitter.com/go/xs/xs.reqTunnel]" ] + "blitter.com/go/xs/xs.doShellMode$1" [ tooltip="blitter.com/go/xs/xs.doShellMode$1 | defined in xs.go:490\nat xs.go:509: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:519: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:507: calling [(crypto/x509.SystemRootsError).Error]\nat xs.go:513: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:507: calling [(crypto/x509.CertificateInvalidError).Error]\nat xs.go:507: calling [(vendor/golang.org/x/net/idna.labelError).Error]\nat xs.go:507: calling [(crypto/tls.RecordHeaderError).Error]\nat xs.go:507: calling [(crypto/x509.UnknownAuthorityError).Error]\nat xs.go:513: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:507: calling [(crypto/tls.alert).Error]\nat xs.go:507: calling [(context.deadlineExceededError).Error]\nat xs.go:507: calling [(crypto/aes.KeySizeError).Error]\nat xs.go:507: calling [(crypto/x509.UnhandledCriticalExtension).Error]\nat xs.go:507: calling [(compress/flate.CorruptInputError).Error]\nat xs.go:507: calling [(*github.com/pkg/errors.fundamental).Error]\nat xs.go:491: calling [blitter.com/go/xs/xs.doShellMode$1$1]\nat xs.go:507: calling [(crypto/x509.HostnameError).Error]\nat xs.go:507: calling [(*crypto/tls.permanentError).Error]\nat xs.go:507: calling [(vendor/golang.org/x/net/idna.runeError).Error]\nat xs.go:514: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:519: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:503: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:518: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:507: calling [(compress/flate.InternalError).Error]" fillcolor="lightblue" label="shellRemoteToStdin" style="dotted,filled" ] + "blitter.com/go/xs/xs.doShellMode$1$1" [ fillcolor="lightblue" label="doShellMode$1$1" style="dotted,filled" tooltip="blitter.com/go/xs/xs.doShellMode$1$1 | defined in xs.go:491" ] + "blitter.com/go/xs/xs.doShellMode" [ fillcolor="lightblue" label="doShellMode" penwidth="0.5" tooltip="blitter.com/go/xs/xs.doShellMode | defined in xs.go:483\nat xs.go:522: calling [blitter.com/go/xs/xs.doShellMode$1]\nat xs.go:551: calling [blitter.com/go/xs/xs.doShellMode$2]\nat xs.go:527: calling [blitter.com/go/xs/xs.handleTermResizes]" ] + "blitter.com/go/xs/xs.handleTermResizes$1" [ tooltip="blitter.com/go/xs/xs.handleTermResizes$1 | defined in termsize_unix.go:21\nat termsize_unix.go:33: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat termsize_unix.go:27: calling [blitter.com/go/xs/xs.GetSize]" fillcolor="lightblue" label="handleTermResizes$1" style="dotted,filled" ] + "blitter.com/go/xs/xs.GetSize" [ penwidth="1.5" tooltip="blitter.com/go/xs/xs.GetSize | defined in xs.go:221" fillcolor="lightblue" label="GetSize" ] + "blitter.com/go/xs/xs.handleTermResizes" [ fillcolor="lightblue" label="handleTermResizes" penwidth="0.5" tooltip="blitter.com/go/xs/xs.handleTermResizes | defined in termsize_unix.go:16\nat termsize_unix.go:21: calling [blitter.com/go/xs/xs.handleTermResizes$1]" ] + "blitter.com/go/xs/xs.Copy" [ tooltip="blitter.com/go/xs/xs.Copy | defined in xs.go:115\nat xs.go:116: calling [blitter.com/go/xs/xs.copyBuffer]" fillcolor="lightblue" label="Copy" penwidth="1.5" ] + "blitter.com/go/xs/xs.doShellMode$2$1" [ fillcolor="lightblue" label="doShellMode$2$1" style="dotted,filled" tooltip="blitter.com/go/xs/xs.doShellMode$2$1 | defined in xs.go:536\nat xs.go:539: calling [blitter.com/go/xs/xs.Copy]" ] + "blitter.com/go/xs/xs.doShellMode$2" [ style="dotted,filled" tooltip="blitter.com/go/xs/xs.doShellMode$2 | defined in xs.go:534\nat xs.go:546: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:548: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:541: calling [blitter.com/go/xs/xs.doShellMode$2$1]" fillcolor="lightblue" label="shellStdinToRemote" ] + "blitter.com/go/xs/xs.usageShell" [ fillcolor="lightblue" label="usageShell" penwidth="0.5" tooltip="blitter.com/go/xs/xs.usageShell | defined in xs.go:559" ] + "blitter.com/go/xs/xs.usageCp" [ label="usageCp" penwidth="0.5" tooltip="blitter.com/go/xs/xs.usageCp | defined in xs.go:565" fillcolor="lightblue" ] subgraph "cluster_blitter.com/go/xs" { - tooltip="package: blitter.com/go/xs"; -penwidth="0.8"; -style="filled"; -fillcolor="lightyellow"; + style="filled"; +rank="sink"; +tooltip="package: blitter.com/go/xs"; label="xs"; URL="/?f=blitter.com/go/xs"; +penwidth="0.8"; fontsize="16"; +fillcolor="lightyellow"; fontname="Tahoma bold"; -rank="sink"; - "blitter.com/go/xs.Restore" [ fillcolor="moccasin" label="Restore" penwidth="1.5" tooltip="blitter.com/go/xs.Restore | defined in termmode_linux.go:70" ] - "blitter.com/go/xs.MakeRaw" [ tooltip="blitter.com/go/xs.MakeRaw | defined in termmode_linux.go:33" fillcolor="moccasin" label="MakeRaw" penwidth="1.5" ] - "blitter.com/go/xs.ReadPassword" [ fillcolor="moccasin" label="ReadPassword" penwidth="1.5" tooltip="blitter.com/go/xs.ReadPassword | defined in termmode_linux.go:81" ] - "blitter.com/go/xs.NewSession" [ tooltip="blitter.com/go/xs.NewSession | defined in session.go:130" fillcolor="moccasin" label="NewSession" penwidth="1.5" ] - "blitter.com/go/xs.GetTool" [ fillcolor="moccasin" label="GetTool" penwidth="1.5" tooltip="blitter.com/go/xs.GetTool | defined in auth.go:211" ] + "blitter.com/go/xs.Restore" [ tooltip="blitter.com/go/xs.Restore | defined in termmode_linux.go:70" fillcolor="moccasin" label="Restore" penwidth="1.5" ] + "blitter.com/go/xs.GetTool" [ fillcolor="moccasin" label="GetTool" penwidth="1.5" tooltip="blitter.com/go/xs.GetTool | defined in auth.go:217" ] + "blitter.com/go/xs.MakeRaw" [ fillcolor="moccasin" label="MakeRaw" penwidth="1.5" tooltip="blitter.com/go/xs.MakeRaw | defined in termmode_linux.go:33" ] + "blitter.com/go/xs.ReadPassword" [ tooltip="blitter.com/go/xs.ReadPassword | defined in termmode_linux.go:81" fillcolor="moccasin" label="ReadPassword" penwidth="1.5" ] + "blitter.com/go/xs.NewSession" [ fillcolor="moccasin" label="NewSession" penwidth="1.5" tooltip="blitter.com/go/xs.NewSession | defined in session.go:130" ] subgraph "cluster_*blitter.com/go/xs.Session" { - labelloc="b"; -style="rounded,filled"; -fillcolor="wheat2"; + fillcolor="wheat2"; label="(*Session)"; tooltip="type: *blitter.com/go/xs.Session"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; "(*blitter.com/go/xs.Session).SetStatus" [ fillcolor="moccasin" label="SetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetStatus | defined in session.go:125" ] } subgraph "cluster_blitter.com/go/xs.Session" { - fontcolor="#222222"; + penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; label="(Session)"; tooltip="type: blitter.com/go/xs.Session"; -penwidth="0.5"; -fontsize="15"; + "(blitter.com/go/xs.Session).Cmd" [ fillcolor="moccasin" label="Cmd" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Cmd | defined in session.go:79" ] "(blitter.com/go/xs.Session).Op" [ fillcolor="moccasin" label="Op" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Op | defined in session.go:36" ] "(blitter.com/go/xs.Session).Who" [ fillcolor="moccasin" label="Who" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Who | defined in session.go:46" ] - "(blitter.com/go/xs.Session).ConnHost" [ fillcolor="moccasin" label="ConnHost" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).ConnHost | defined in session.go:56" ] - "(blitter.com/go/xs.Session).TermType" [ label="TermType" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).TermType | defined in session.go:67" fillcolor="moccasin" ] - "(blitter.com/go/xs.Session).Cmd" [ fillcolor="moccasin" label="Cmd" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Cmd | defined in session.go:79" ] - "(blitter.com/go/xs.Session).AuthCookie" [ penwidth="1.5" tooltip="(blitter.com/go/xs.Session).AuthCookie | defined in session.go:92" fillcolor="moccasin" label="AuthCookie" ] - "(blitter.com/go/xs.Session).Status" [ fillcolor="moccasin" label="Status" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Status | defined in session.go:120" ] + "(blitter.com/go/xs.Session).ConnHost" [ label="ConnHost" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).ConnHost | defined in session.go:56" fillcolor="moccasin" ] + "(blitter.com/go/xs.Session).TermType" [ fillcolor="moccasin" label="TermType" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).TermType | defined in session.go:67" ] + "(blitter.com/go/xs.Session).AuthCookie" [ fillcolor="moccasin" label="AuthCookie" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).AuthCookie | defined in session.go:92" ] + "(blitter.com/go/xs.Session).Status" [ penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Status | defined in session.go:120" fillcolor="moccasin" label="Status" ] } } subgraph "cluster_blitter.com/go/xs/logger" { - fillcolor="lightyellow"; -URL="/?f=blitter.com/go/xs/logger"; -penwidth="0.8"; -style="filled"; + penwidth="0.8"; +fontsize="16"; fontname="Tahoma bold"; +URL="/?f=blitter.com/go/xs/logger"; +tooltip="package: blitter.com/go/xs/logger"; +style="filled"; +fillcolor="lightyellow"; rank="sink"; label="logger"; -tooltip="package: blitter.com/go/xs/logger"; -fontsize="16"; + "blitter.com/go/xs/logger.LogDebug" [ fillcolor="moccasin" label="LogDebug" penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogDebug | defined in logger_linux.go:103" ] "blitter.com/go/xs/logger.New" [ fillcolor="moccasin" label="New" penwidth="1.5" tooltip="blitter.com/go/xs/logger.New | defined in logger_linux.go:71" ] - "blitter.com/go/xs/logger.LogDebug" [ penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogDebug | defined in logger_linux.go:103" fillcolor="moccasin" label="LogDebug" ] } subgraph "cluster_blitter.com/go/xs/spinsult" { - style="filled"; + penwidth="0.8"; +style="filled"; +fontname="Tahoma bold"; rank="sink"; -URL="/?f=blitter.com/go/xs/spinsult"; -tooltip="package: blitter.com/go/xs/spinsult"; -penwidth="0.8"; fontsize="16"; fillcolor="lightyellow"; -fontname="Tahoma bold"; label="spinsult"; +URL="/?f=blitter.com/go/xs/spinsult"; +tooltip="package: blitter.com/go/xs/spinsult"; - "blitter.com/go/xs/spinsult.GetSentence" [ fillcolor="moccasin" label="GetSentence" penwidth="1.5" tooltip="blitter.com/go/xs/spinsult.GetSentence | defined in spinsult.go:43" ] + "blitter.com/go/xs/spinsult.GetSentence" [ label="GetSentence" penwidth="1.5" tooltip="blitter.com/go/xs/spinsult.GetSentence | defined in spinsult.go:43" fillcolor="moccasin" ] } subgraph "cluster_blitter.com/go/xs/xsnet" { - fillcolor="lightyellow"; -fontname="Tahoma bold"; -penwidth="0.8"; -style="filled"; -label="xsnet"; -URL="/?f=blitter.com/go/xs/xsnet"; -tooltip="package: blitter.com/go/xs/xsnet"; -fontsize="16"; + fontname="Tahoma bold"; rank="sink"; +label="xsnet"; +tooltip="package: blitter.com/go/xs/xsnet"; +penwidth="0.8"; +fontsize="16"; +style="filled"; +fillcolor="lightyellow"; +URL="/?f=blitter.com/go/xs/xsnet"; - "blitter.com/go/xs/xsnet.Init" [ fillcolor="moccasin" label="Init" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Init | defined in net.go:192" ] - "blitter.com/go/xs/xsnet.Dial" [ fillcolor="moccasin" label="Dial" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Dial | defined in net.go:890" ] + "blitter.com/go/xs/xsnet.Init" [ fillcolor="moccasin" label="Init" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Init | defined in net.go:198" ] + "blitter.com/go/xs/xsnet.Dial" [ fillcolor="moccasin" label="Dial" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Dial | defined in net.go:899" ] subgraph "cluster_*blitter.com/go/xs/xsnet.Conn" { - labelloc="b"; + fontcolor="#222222"; +labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; label="(*Conn)"; tooltip="type: *blitter.com/go/xs/xsnet.Conn"; penwidth="0.5"; fontsize="15"; -fontcolor="#222222"; - "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ fillcolor="moccasin" label="WritePacket" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).WritePacket | defined in net.go:1430" ] - "(*blitter.com/go/xs/xsnet.Conn).Close" [ label="Close" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).Close | defined in net.go:970" fillcolor="moccasin" ] - "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetupChaff | defined in net.go:1556" fillcolor="moccasin" label="SetupChaff" ] - "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ label="EnableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).EnableChaff | defined in net.go:1539" fillcolor="moccasin" ] - "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ label="DisableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).DisableChaff | defined in net.go:1546" fillcolor="moccasin" ] - "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ fillcolor="moccasin" label="ShutdownChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff | defined in net.go:1551" ] - "(*blitter.com/go/xs/xsnet.Conn).GetStatus" [ fillcolor="moccasin" label="GetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).GetStatus | defined in net.go:208" ] - "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ fillcolor="moccasin" label="SetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetStatus | defined in net.go:212" ] + "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ fillcolor="moccasin" label="WritePacket" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).WritePacket | defined in net.go:1437" ] + "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ label="SetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetStatus | defined in net.go:218" fillcolor="moccasin" ] + "(*blitter.com/go/xs/xsnet.Conn).GetStatus" [ fillcolor="moccasin" label="GetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).GetStatus | defined in net.go:214" ] + "(*blitter.com/go/xs/xsnet.Conn).Close" [ fillcolor="moccasin" label="Close" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).Close | defined in net.go:979" ] + "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetupChaff | defined in net.go:1563" fillcolor="moccasin" label="SetupChaff" ] + "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ fillcolor="moccasin" label="EnableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).EnableChaff | defined in net.go:1546" ] + "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ fillcolor="moccasin" label="DisableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).DisableChaff | defined in net.go:1553" ] + "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ tooltip="(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff | defined in net.go:1558" fillcolor="moccasin" label="ShutdownChaff" penwidth="1.5" ] } subgraph "cluster_blitter.com/go/xs/xsnet.Conn" { - labelloc="b"; -style="rounded,filled"; -fillcolor="wheat2"; -label="(Conn)"; + label="(Conn)"; tooltip="type: blitter.com/go/xs/xsnet.Conn"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; - "(blitter.com/go/xs/xsnet.Conn).Write" [ tooltip="(blitter.com/go/xs/xsnet.Conn).Write | defined in net.go:1424" fillcolor="moccasin" label="Write" penwidth="1.5" ] - "(blitter.com/go/xs/xsnet.Conn).Read" [ fillcolor="moccasin" label="Read" penwidth="1.5" tooltip="(blitter.com/go/xs/xsnet.Conn).Read | defined in net.go:1185" ] + "(blitter.com/go/xs/xsnet.Conn).Read" [ penwidth="1.5" tooltip="(blitter.com/go/xs/xsnet.Conn).Read | defined in net.go:1192" fillcolor="moccasin" label="Read" ] + "(blitter.com/go/xs/xsnet.Conn).Write" [ fillcolor="moccasin" label="Write" penwidth="1.5" tooltip="(blitter.com/go/xs/xsnet.Conn).Write | defined in net.go:1431" ] } } subgraph "cluster_compress/flate" { - URL="/?f=compress/flate"; + fontsize="16"; +style="filled"; +fillcolor="lightyellow"; +label="flate"; +URL="/?f=compress/flate"; penwidth="0.8"; -label="compress/flate"; -fillcolor="#E0FFE1"; fontname="Tahoma bold"; rank="sink"; tooltip="package: compress/flate"; -fontsize="16"; -style="filled"; subgraph "cluster_compress/flate.CorruptInputError" { - tooltip="type: compress/flate.CorruptInputError"; -penwidth="0.5"; -fontsize="15"; -fontcolor="#222222"; + fontcolor="#222222"; labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; +fillcolor="wheat2"; label="(CorruptInputError)"; +tooltip="type: compress/flate.CorruptInputError"; +penwidth="0.5"; +fontsize="15"; - "(compress/flate.CorruptInputError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(compress/flate.CorruptInputError).Error | defined in inflate.go:35" ] + "(compress/flate.CorruptInputError).Error" [ penwidth="1.5" tooltip="(compress/flate.CorruptInputError).Error | defined in inflate.go:35" fillcolor="moccasin" label="Error" ] } @@ -221,10 +221,10 @@ fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; +fillcolor="wheat2"; label="(InternalError)"; - "(compress/flate.InternalError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(compress/flate.InternalError).Error | defined in inflate.go:42" ] + "(compress/flate.InternalError).Error" [ tooltip="(compress/flate.InternalError).Error | defined in inflate.go:42" fillcolor="moccasin" label="Error" penwidth="1.5" ] } @@ -233,46 +233,46 @@ label="(InternalError)"; subgraph "cluster_context" { fontsize="16"; style="filled"; -fontname="Tahoma bold"; -penwidth="0.8"; -rank="sink"; label="context"; +penwidth="0.8"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +rank="sink"; URL="/?f=context"; tooltip="package: context"; -fillcolor="#E0FFE1"; subgraph "cluster_context.deadlineExceededError" { - tooltip="type: context.deadlineExceededError"; + style="rounded,filled"; +fillcolor="wheat2"; +label="(deadlineExceededError)"; +tooltip="type: context.deadlineExceededError"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; -style="rounded,filled"; -fillcolor="#c2e3c2"; -label="(deadlineExceededError)"; - "(context.deadlineExceededError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(context.deadlineExceededError).Error | defined in context.go:165" ] + "(context.deadlineExceededError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(context.deadlineExceededError).Error | defined in context.go:165" ] } } subgraph "cluster_crypto/aes" { - label="crypto/aes"; -tooltip="package: crypto/aes"; -penwidth="0.8"; + penwidth="0.8"; style="filled"; -fillcolor="#E0FFE1"; fontname="Tahoma bold"; rank="sink"; -fontsize="16"; +label="aes"; URL="/?f=crypto/aes"; +tooltip="package: crypto/aes"; +fontsize="16"; +fillcolor="lightyellow"; subgraph "cluster_crypto/aes.KeySizeError" { style="rounded,filled"; -fillcolor="#c2e3c2"; +fillcolor="wheat2"; label="(KeySizeError)"; tooltip="type: crypto/aes.KeySizeError"; penwidth="0.5"; @@ -280,7 +280,7 @@ fontsize="15"; fontcolor="#222222"; labelloc="b"; - "(crypto/aes.KeySizeError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(crypto/aes.KeySizeError).Error | defined in cipher.go:24" ] + "(crypto/aes.KeySizeError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(crypto/aes.KeySizeError).Error | defined in cipher.go:24" ] } @@ -288,111 +288,111 @@ labelloc="b"; subgraph "cluster_crypto/tls" { penwidth="0.8"; -style="filled"; +fontsize="16"; fontname="Tahoma bold"; -rank="sink"; URL="/?f=crypto/tls"; tooltip="package: crypto/tls"; -fontsize="16"; -fillcolor="#E0FFE1"; -label="crypto/tls"; +style="filled"; +fillcolor="lightyellow"; +rank="sink"; +label="tls"; - subgraph "cluster_*crypto/tls.permamentError" { - tooltip="type: *crypto/tls.permamentError"; + subgraph "cluster_*crypto/tls.permanentError" { + label="(*permanentError)"; +tooltip="type: *crypto/tls.permanentError"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; -label="(*permamentError)"; +fillcolor="wheat2"; - "(*crypto/tls.permamentError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(*crypto/tls.permamentError).Error | defined in conn.go:175" ] + "(*crypto/tls.permanentError).Error" [ tooltip="(*crypto/tls.permanentError).Error | defined in conn.go:184" fillcolor="moccasin" label="Error" penwidth="1.5" ] } subgraph "cluster_crypto/tls.RecordHeaderError" { - label="(RecordHeaderError)"; + fillcolor="wheat2"; +label="(RecordHeaderError)"; tooltip="type: crypto/tls.RecordHeaderError"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; - "(crypto/tls.RecordHeaderError).Error" [ tooltip="(crypto/tls.RecordHeaderError).Error | defined in conn.go:566" fillcolor="#adedad" label="Error" penwidth="1.5" ] + "(crypto/tls.RecordHeaderError).Error" [ tooltip="(crypto/tls.RecordHeaderError).Error | defined in conn.go:571" fillcolor="moccasin" label="Error" penwidth="1.5" ] } subgraph "cluster_crypto/tls.alert" { - style="rounded,filled"; -fillcolor="#c2e3c2"; + fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; label="(alert)"; tooltip="type: crypto/tls.alert"; penwidth="0.5"; fontsize="15"; -fontcolor="#222222"; -labelloc="b"; - "(crypto/tls.alert).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(crypto/tls.alert).Error | defined in alert.go:97" ] + "(crypto/tls.alert).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(crypto/tls.alert).Error | defined in alert.go:97" ] } } subgraph "cluster_crypto/x509" { - style="filled"; -URL="/?f=crypto/x509"; + URL="/?f=crypto/x509"; +style="filled"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +rank="sink"; +label="x509"; tooltip="package: crypto/x509"; penwidth="0.8"; fontsize="16"; -fillcolor="#E0FFE1"; -fontname="Tahoma bold"; -rank="sink"; -label="crypto/x509"; subgraph "cluster_crypto/x509.CertificateInvalidError" { - tooltip="type: crypto/x509.CertificateInvalidError"; + label="(CertificateInvalidError)"; +tooltip="type: crypto/x509.CertificateInvalidError"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; -label="(CertificateInvalidError)"; +fillcolor="wheat2"; - "(crypto/x509.CertificateInvalidError).Error" [ label="Error" penwidth="1.5" tooltip="(crypto/x509.CertificateInvalidError).Error | defined in verify.go:78" fillcolor="#adedad" ] + "(crypto/x509.CertificateInvalidError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(crypto/x509.CertificateInvalidError).Error | defined in verify.go:67" ] } subgraph "cluster_crypto/x509.HostnameError" { - labelloc="b"; -style="rounded,filled"; -fillcolor="#c2e3c2"; -label="(HostnameError)"; -tooltip="type: crypto/x509.HostnameError"; -penwidth="0.5"; -fontsize="15"; -fontcolor="#222222"; - - "(crypto/x509.HostnameError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(crypto/x509.HostnameError).Error | defined in verify.go:109" ] - - } - - subgraph "cluster_crypto/x509.SystemRootsError" { - fillcolor="#c2e3c2"; -label="(SystemRootsError)"; -tooltip="type: crypto/x509.SystemRootsError"; + tooltip="type: crypto/x509.HostnameError"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; +fillcolor="wheat2"; +label="(HostnameError)"; - "(crypto/x509.SystemRootsError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(crypto/x509.SystemRootsError).Error | defined in verify.go:182" ] + "(crypto/x509.HostnameError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(crypto/x509.HostnameError).Error | defined in verify.go:98" ] + + } + + subgraph "cluster_crypto/x509.SystemRootsError" { + tooltip="type: crypto/x509.SystemRootsError"; +penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; +label="(SystemRootsError)"; + + "(crypto/x509.SystemRootsError).Error" [ label="Error" penwidth="1.5" tooltip="(crypto/x509.SystemRootsError).Error | defined in verify.go:159" fillcolor="moccasin" ] } @@ -404,23 +404,23 @@ fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; +fillcolor="wheat2"; - "(crypto/x509.UnhandledCriticalExtension).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(crypto/x509.UnhandledCriticalExtension).Error | defined in x509.go:931" ] + "(crypto/x509.UnhandledCriticalExtension).Error" [ label="Error" penwidth="1.5" tooltip="(crypto/x509.UnhandledCriticalExtension).Error | defined in x509.go:893" fillcolor="moccasin" ] } subgraph "cluster_crypto/x509.UnknownAuthorityError" { - fillcolor="#c2e3c2"; -label="(UnknownAuthorityError)"; -tooltip="type: crypto/x509.UnknownAuthorityError"; -penwidth="0.5"; -fontsize="15"; + fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; +fillcolor="wheat2"; +label="(UnknownAuthorityError)"; +tooltip="type: crypto/x509.UnknownAuthorityError"; +penwidth="0.5"; - "(crypto/x509.UnknownAuthorityError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(crypto/x509.UnknownAuthorityError).Error | defined in verify.go:161" ] + "(crypto/x509.UnknownAuthorityError).Error" [ tooltip="(crypto/x509.UnknownAuthorityError).Error | defined in verify.go:138" fillcolor="moccasin" label="Error" penwidth="1.5" ] } @@ -428,151 +428,195 @@ style="rounded,filled"; subgraph "cluster_github.com/mattn/go-isatty" { penwidth="0.8"; -style="filled"; -fillcolor="lightyellow"; +fontsize="16"; fontname="Tahoma bold"; rank="sink"; +style="filled"; +fillcolor="lightyellow"; label="isatty"; URL="/?f=github.com/mattn/go-isatty"; -fontsize="16"; tooltip="package: github.com/mattn/go-isatty"; - "github.com/mattn/go-isatty.IsTerminal" [ fillcolor="moccasin" label="IsTerminal" penwidth="1.5" tooltip="github.com/mattn/go-isatty.IsTerminal | defined in isatty_tcgets.go:9" ] + "github.com/mattn/go-isatty.IsTerminal" [ penwidth="1.5" tooltip="github.com/mattn/go-isatty.IsTerminal | defined in isatty_tcgets.go:10" fillcolor="moccasin" label="IsTerminal" ] } subgraph "cluster_github.com/pkg/errors" { - penwidth="0.8"; -fontsize="16"; -fillcolor="lightyellow"; -rank="sink"; + fontname="Tahoma bold"; label="errors"; -style="filled"; -fontname="Tahoma bold"; URL="/?f=github.com/pkg/errors"; tooltip="package: github.com/pkg/errors"; +rank="sink"; +penwidth="0.8"; +fontsize="16"; +style="filled"; +fillcolor="lightyellow"; subgraph "cluster_*github.com/pkg/errors.fundamental" { - fontsize="15"; + label="(*fundamental)"; +tooltip="type: *github.com/pkg/errors.fundamental"; +penwidth="0.5"; +fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; -label="(*fundamental)"; -tooltip="type: *github.com/pkg/errors.fundamental"; -penwidth="0.5"; - "(*github.com/pkg/errors.fundamental).Error" [ tooltip="(*github.com/pkg/errors.fundamental).Error | defined in errors.go:125" fillcolor="moccasin" label="Error" penwidth="1.5" ] + "(*github.com/pkg/errors.fundamental).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(*github.com/pkg/errors.fundamental).Error | defined in errors.go:125" ] } } subgraph "cluster_math/rand" { - fontname="Tahoma bold"; -URL="/?f=math/rand"; -penwidth="0.8"; -style="filled"; -fillcolor="#E0FFE1"; -tooltip="package: math/rand"; -fontsize="16"; + style="filled"; +fillcolor="lightyellow"; rank="sink"; -label="math/rand"; +URL="/?f=math/rand"; +tooltip="package: math/rand"; +penwidth="0.8"; +fontsize="16"; +fontname="Tahoma bold"; +label="rand"; - "math/rand.Intn" [ fillcolor="#adedad" label="Intn" penwidth="1.5" tooltip="math/rand.Intn | defined in rand.go:337" ] + "math/rand.Intn" [ fillcolor="moccasin" label="Intn" penwidth="1.5" tooltip="math/rand.Intn | defined in rand.go:337" ] + + } + + subgraph "cluster_vendor/golang.org/x/net/idna" { + URL="/?f=vendor/golang.org/x/net/idna"; +penwidth="0.8"; +fontname="Tahoma bold"; +fillcolor="lightyellow"; +rank="sink"; +label="idna"; +tooltip="package: vendor/golang.org/x/net/idna"; +fontsize="16"; +style="filled"; + + + subgraph "cluster_vendor/golang.org/x/net/idna.labelError" { + style="rounded,filled"; +fillcolor="wheat2"; +label="(labelError)"; +tooltip="type: vendor/golang.org/x/net/idna.labelError"; +penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; +labelloc="b"; + + "(vendor/golang.org/x/net/idna.labelError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(vendor/golang.org/x/net/idna.labelError).Error | defined in idna10.0.0.go:324" ] + + } + + subgraph "cluster_vendor/golang.org/x/net/idna.runeError" { + style="rounded,filled"; +fillcolor="wheat2"; +label="(runeError)"; +tooltip="type: vendor/golang.org/x/net/idna.runeError"; +penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; +labelloc="b"; + + "(vendor/golang.org/x/net/idna.runeError).Error" [ tooltip="(vendor/golang.org/x/net/idna.runeError).Error | defined in idna10.0.0.go:331" fillcolor="moccasin" label="Error" penwidth="1.5" ] } } - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.main$1" [ arrowhead="normalnoneodot" tooltip="at xs.go:769: calling [blitter.com/go/xs/xs.main$1]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.localUserName" [ tooltip="at xs.go:782: calling [blitter.com/go/xs/xs.localUserName]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.rejectUserMsg" [ tooltip="at xs.go:1024: calling [blitter.com/go/xs/xs.rejectUserMsg]" ] + } + + "blitter.com/go/xs/xs.doShellMode$1" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:509: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:519: calling [blitter.com/go/xs/xs.exitWithStatus]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.SystemRootsError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.SystemRootsError).Error]" ] + "blitter.com/go/xs/xs.main$2" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:999: calling [blitter.com/go/xs/xs.exitWithStatus]" ] + "blitter.com/go/xs/xs.doCopyMode" -> "(*blitter.com/go/xs/xsnet.Conn).GetStatus" [ color="saddlebrown" tooltip="at xs.go:435: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:438: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:473: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:475: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]" ] + "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xs.go:1056: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(*blitter.com/go/xs.Session).SetStatus" [ color="saddlebrown" tooltip="at xs.go:513: calling [(*blitter.com/go/xs.Session).SetStatus]" ] + "blitter.com/go/xs/xs.doShellMode" -> "blitter.com/go/xs/xs.doShellMode$1" [ arrowhead="normalnoneodot" tooltip="at xs.go:522: calling [blitter.com/go/xs/xs.doShellMode$1]" ] + "blitter.com/go/xs/xs.main$2" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:997: calling [blitter.com/go/xs/xs.restoreTermState]" ] + "blitter.com/go/xs/xs.doCopyMode" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xs.go:430: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).Cmd" [ tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:671: calling [(blitter.com/go/xs.Session).Cmd]" color="saddlebrown" ] + "blitter.com/go/xs/xs.main" -> "(blitter.com/go/xs.Session).Status" [ color="saddlebrown" tooltip="at xs.go:1027: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1089: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1091: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1101: calling [(blitter.com/go/xs.Session).Status]" ] + "blitter.com/go/xs/xs.main$3" -> "math/rand.Intn" [ tooltip="at xs.go:1068: calling [math/rand.Intn]" color="saddlebrown" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.CertificateInvalidError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.CertificateInvalidError).Error]" ] + "blitter.com/go/xs/xs.doShellMode$2" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:546: calling [blitter.com/go/xs/xs.restoreTermState]" ] + "blitter.com/go/xs/xs.doShellMode$2" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:548: calling [blitter.com/go/xs/xs.exitWithStatus]" ] + "blitter.com/go/xs/xs.restoreTermState" -> "blitter.com/go/xs.Restore" [ color="saddlebrown" tooltip="at xs.go:1118: calling [blitter.com/go/xs.Restore]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/logger.New" [ color="saddlebrown" tooltip="at xs.go:864: calling [blitter.com/go/xs/logger.New]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs.MakeRaw" [ color="saddlebrown" tooltip="at xs.go:978: calling [blitter.com/go/xs.MakeRaw]" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).AuthCookie" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xs.go:675: calling [(blitter.com/go/xs.Session).AuthCookie]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.main$3" [ arrowhead="normalnoneodot" tooltip="at xs.go:1075: calling [blitter.com/go/xs/xs.main$3]" ] + "blitter.com/go/xs/xs.doCopyMode" -> "blitter.com/go/xs/xs.buildCmdRemoteToLocal" [ tooltip="at xs.go:444: calling [blitter.com/go/xs/xs.buildCmdRemoteToLocal]" ] + "blitter.com/go/xs/xs.doCopyMode" -> "(blitter.com/go/xs/xsnet.Conn).Read" [ color="saddlebrown" tooltip="at xs.go:424: calling [(blitter.com/go/xs/xsnet.Conn).Read]" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).Who" [ tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).Who]\nat xs.go:659: calling [(blitter.com/go/xs.Session).Who]" color="saddlebrown" ] + "blitter.com/go/xs/xs.main" -> "(blitter.com/go/xs/xsnet.Conn).Read" [ color="saddlebrown" tooltip="at xs.go:1039: calling [(blitter.com/go/xs/xsnet.Conn).Read]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xsnet.Dial" [ color="saddlebrown" tooltip="at xs.go:960: calling [blitter.com/go/xs/xsnet.Dial]" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).Op" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).Op]\nat xs.go:655: calling [(blitter.com/go/xs.Session).Op]" ] + "blitter.com/go/xs/xs.rejectUserMsg" -> "blitter.com/go/xs/spinsult.GetSentence" [ color="saddlebrown" tooltip="at xs.go:577: calling [blitter.com/go/xs/spinsult.GetSentence]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.launchTuns" [ tooltip="at xs.go:1081: calling [blitter.com/go/xs/xs.launchTuns]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(vendor/golang.org/x/net/idna.labelError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(vendor/golang.org/x/net/idna.labelError).Error]" ] + "blitter.com/go/xs/xs.Copy" -> "blitter.com/go/xs/xs.copyBuffer" [ tooltip="at xs.go:116: calling [blitter.com/go/xs/xs.copyBuffer]" ] + "blitter.com/go/xs/xs.main" -> "github.com/mattn/go-isatty.IsTerminal" [ color="saddlebrown" tooltip="at xs.go:977: calling [github.com/mattn/go-isatty.IsTerminal]" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).TermType" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).TermType]\nat xs.go:667: calling [(blitter.com/go/xs.Session).TermType]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/tls.RecordHeaderError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/tls.RecordHeaderError).Error]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.UnknownAuthorityError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.UnknownAuthorityError).Error]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:772: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:853: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:963: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1027: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1101: calling [blitter.com/go/xs/xs.exitWithStatus]" ] + "blitter.com/go/xs/xs.doShellMode$2" -> "blitter.com/go/xs/xs.doShellMode$2$1" [ tooltip="at xs.go:541: calling [blitter.com/go/xs/xs.doShellMode$2$1]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.doShellMode" [ tooltip="at xs.go:1082: calling [blitter.com/go/xs/xs.doShellMode]" ] + "blitter.com/go/xs/xs.doShellMode" -> "blitter.com/go/xs/xs.doShellMode$2" [ arrowhead="normalnoneodot" tooltip="at xs.go:551: calling [blitter.com/go/xs/xs.doShellMode$2]" ] + "blitter.com/go/xs/xs.buildCmdLocalToRemote" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xs.go:283: calling [blitter.com/go/xs.GetTool]\nat xs.go:311: calling [blitter.com/go/xs.GetTool]\nat xs.go:312: calling [blitter.com/go/xs.GetTool]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(*blitter.com/go/xs/xsnet.Conn).GetStatus" [ color="saddlebrown" tooltip="at xs.go:513: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]" ] "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/tls.alert).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/tls.alert).Error]" ] "blitter.com/go/xs/xs.doShellMode" -> "blitter.com/go/xs/xs.handleTermResizes" [ tooltip="at xs.go:527: calling [blitter.com/go/xs/xs.handleTermResizes]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/logger.New" [ color="saddlebrown" tooltip="at xs.go:843: calling [blitter.com/go/xs/logger.New]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:503: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:518: calling [blitter.com/go/xs/xs.restoreTermState]" ] - "blitter.com/go/xs/xs.buildCmdLocalToRemote" -> "blitter.com/go/xs/xs.getTreeSizeSubCmd" [ tooltip="at xs.go:335: calling [blitter.com/go/xs/xs.getTreeSizeSubCmd]" ] - "blitter.com/go/xs/xs.handleTermResizes" -> "blitter.com/go/xs/xs.handleTermResizes$1" [ tooltip="at termsize_unix.go:21: calling [blitter.com/go/xs/xs.handleTermResizes$1]" arrowhead="normalnoneodot" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:509: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:519: calling [blitter.com/go/xs/xs.exitWithStatus]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(compress/flate.InternalError).Error" [ tooltip="at xs.go:507: calling [(compress/flate.InternalError).Error]" style="dashed" color="saddlebrown" ] - "blitter.com/go/xs/xs.buildCmdRemoteToLocal" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xs.go:256: calling [blitter.com/go/xs.GetTool]\nat xs.go:263: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xs.doCopyMode" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at xs.go:417: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] - "blitter.com/go/xs/xs.buildCmdLocalToRemote" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xs.go:283: calling [blitter.com/go/xs.GetTool]\nat xs.go:311: calling [blitter.com/go/xs.GetTool]\nat xs.go:312: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xsnet.Dial" [ color="saddlebrown" tooltip="at xs.go:938: calling [blitter.com/go/xs/xsnet.Dial]" ] - "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs.Session).SetStatus" [ color="saddlebrown" tooltip="at xs.go:1003: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1021: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1025: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1064: calling [(*blitter.com/go/xs.Session).SetStatus]" ] - "blitter.com/go/xs/xs.main" -> "(blitter.com/go/xs.Session).Status" [ color="saddlebrown" tooltip="at xs.go:1005: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1067: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1069: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:1079: calling [(blitter.com/go/xs.Session).Status]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.main$3" [ arrowhead="normalnoneodot" tooltip="at xs.go:1053: calling [blitter.com/go/xs/xs.main$3]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/aes.KeySizeError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/aes.KeySizeError).Error]" ] - "blitter.com/go/xs/xs.doCopyMode" -> "(blitter.com/go/xs.Session).Cmd" [ color="saddlebrown" tooltip="at xs.go:356: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:441: calling [(blitter.com/go/xs.Session).Cmd]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).Who" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).Who]\nat xs.go:659: calling [(blitter.com/go/xs.Session).Who]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).AuthCookie" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xs.go:675: calling [(blitter.com/go/xs.Session).AuthCookie]" ] + "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ color="saddlebrown" tooltip="at xs.go:1050: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]" ] "blitter.com/go/xs/xs.doShellMode$1" -> "(context.deadlineExceededError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(context.deadlineExceededError).Error]" ] - "blitter.com/go/xs/xs.doShellMode" -> "blitter.com/go/xs/xs.doShellMode$2" [ arrowhead="normalnoneodot" tooltip="at xs.go:551: calling [blitter.com/go/xs/xs.doShellMode$2]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.usageShell" [ style="dashed" tooltip="at xs.go:831: calling [blitter.com/go/xs/xs.usageShell]" ] - "blitter.com/go/xs/xs.main$3" -> "math/rand.Intn" [ tooltip="at xs.go:1046: calling [math/rand.Intn]" color="saddlebrown" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs.MakeRaw" [ color="saddlebrown" tooltip="at xs.go:956: calling [blitter.com/go/xs.MakeRaw]" ] - "blitter.com/go/xs/xs.main" -> "(blitter.com/go/xs/xsnet.Conn).Read" [ color="saddlebrown" tooltip="at xs.go:1017: calling [(blitter.com/go/xs/xsnet.Conn).Read]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.UnhandledCriticalExtension).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.UnhandledCriticalExtension).Error]" ] - "blitter.com/go/xs/xs.doShellMode$2" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:546: calling [blitter.com/go/xs/xs.restoreTermState]" ] - "blitter.com/go/xs/xs.doCopyMode" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xs.go:430: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] - "blitter.com/go/xs/xs.reqTunnel" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at xs.go:594: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.launchTuns" [ tooltip="at xs.go:1059: calling [blitter.com/go/xs/xs.launchTuns]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(blitter.com/go/xs.Session).Status" [ tooltip="at xs.go:514: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:519: calling [(blitter.com/go/xs.Session).Status]" color="saddlebrown" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.CertificateInvalidError).Error" [ tooltip="at xs.go:507: calling [(crypto/x509.CertificateInvalidError).Error]" style="dashed" color="saddlebrown" ] - "blitter.com/go/xs/xs.doShellMode" -> "blitter.com/go/xs/xs.doShellMode$1" [ arrowhead="normalnoneodot" tooltip="at xs.go:522: calling [blitter.com/go/xs/xs.doShellMode$1]" ] - "blitter.com/go/xs/xs.copyBuffer" -> "blitter.com/go/xs/xs.copyBuffer$2" [ tooltip="at xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$2]" style="dashed" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.doCopyMode" [ tooltip="at xs.go:1063: calling [blitter.com/go/xs/xs.doCopyMode]" ] - "blitter.com/go/xs/xs.copyBuffer" -> "blitter.com/go/xs/xs.copyBuffer$3" [ style="dashed" tooltip="at xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$3]" ] - "blitter.com/go/xs/xs.doCopyMode" -> "(blitter.com/go/xs/xsnet.Conn).Read" [ tooltip="at xs.go:424: calling [(blitter.com/go/xs/xsnet.Conn).Read]" color="saddlebrown" ] - "blitter.com/go/xs/xs.handleTermResizes$1" -> "blitter.com/go/xs/xs.GetSize" [ tooltip="at termsize_unix.go:27: calling [blitter.com/go/xs/xs.GetSize]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).ConnHost" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).ConnHost]\nat xs.go:663: calling [(blitter.com/go/xs.Session).ConnHost]" ] - "blitter.com/go/xs/xs.main$3" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ tooltip="at xs.go:1050: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" color="saddlebrown" ] - "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xs.go:950: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] - "blitter.com/go/xs/xs.rejectUserMsg" -> "blitter.com/go/xs/spinsult.GetSentence" [ color="saddlebrown" tooltip="at xs.go:577: calling [blitter.com/go/xs/spinsult.GetSentence]" ] - "blitter.com/go/xs/xs.copyBuffer" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ style="dashed" color="saddlebrown" tooltip="at xs.go:193: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).Op" [ tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).Op]\nat xs.go:655: calling [(blitter.com/go/xs.Session).Op]" color="saddlebrown" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.parseNonSwitchArgs" [ tooltip="at xs.go:775: calling [blitter.com/go/xs/xs.parseNonSwitchArgs]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:962: calling [blitter.com/go/xs/xs.restoreTermState]" arrowhead="normalnoneodiamond" ] - "blitter.com/go/xs/xs.doCopyMode" -> "blitter.com/go/xs/xs.buildCmdLocalToRemote" [ tooltip="at xs.go:364: calling [blitter.com/go/xs/xs.buildCmdLocalToRemote]" ] - "blitter.com/go/xs/xs.main$2" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:977: calling [blitter.com/go/xs/xs.exitWithStatus]" ] - "blitter.com/go/xs/xs.handleTermResizes$1" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at termsize_unix.go:33: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ style="dashed" color="saddlebrown" tooltip="at xs.go:675: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:671: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:667: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:663: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:659: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:655: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] - "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xs.go:1032: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] - "blitter.com/go/xs/xs.doShellMode$2" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:548: calling [blitter.com/go/xs/xs.exitWithStatus]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:1002: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1068: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1074: calling [blitter.com/go/xs/xs.restoreTermState]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/tls.RecordHeaderError).Error" [ tooltip="at xs.go:507: calling [(crypto/tls.RecordHeaderError).Error]" style="dashed" color="saddlebrown" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.HostnameError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.HostnameError).Error]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.usageCp" [ style="dashed" tooltip="at xs.go:831: calling [blitter.com/go/xs/xs.usageCp]" ] - "blitter.com/go/xs/xs.main" -> "github.com/mattn/go-isatty.IsTerminal" [ color="saddlebrown" tooltip="at xs.go:955: calling [github.com/mattn/go-isatty.IsTerminal]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(*github.com/pkg/errors.fundamental).Error" [ color="saddlebrown" tooltip="at xs.go:507: calling [(*github.com/pkg/errors.fundamental).Error]" style="dashed" ] - "blitter.com/go/xs/xs.Copy" -> "blitter.com/go/xs/xs.copyBuffer" [ tooltip="at xs.go:116: calling [blitter.com/go/xs/xs.copyBuffer]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/aes.KeySizeError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/aes.KeySizeError).Error]" ] "blitter.com/go/xs/xs.doShellMode$2$1" -> "blitter.com/go/xs/xs.Copy" [ tooltip="at xs.go:539: calling [blitter.com/go/xs/xs.Copy]" ] - "blitter.com/go/xs/xs.doShellMode$2" -> "blitter.com/go/xs/xs.doShellMode$2$1" [ tooltip="at xs.go:541: calling [blitter.com/go/xs/xs.doShellMode$2$1]" ] - "blitter.com/go/xs/xs.restoreTermState" -> "blitter.com/go/xs.Restore" [ color="saddlebrown" tooltip="at xs.go:1096: calling [blitter.com/go/xs.Restore]" ] - "blitter.com/go/xs/xs.main$2" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:975: calling [blitter.com/go/xs/xs.restoreTermState]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).Cmd" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:671: calling [(blitter.com/go/xs.Session).Cmd]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.sendSessionParams" [ tooltip="at xs.go:1000: calling [blitter.com/go/xs/xs.sendSessionParams]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "blitter.com/go/xs/xs.doShellMode$1$1" [ arrowhead="normalnoneodiamond" tooltip="at xs.go:491: calling [blitter.com/go/xs/xs.doShellMode$1$1]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(*crypto/tls.permamentError).Error" [ tooltip="at xs.go:507: calling [(*crypto/tls.permamentError).Error]" style="dashed" color="saddlebrown" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.SystemRootsError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.SystemRootsError).Error]" ] - "blitter.com/go/xs/xs.doCopyMode" -> "(*blitter.com/go/xs/xsnet.Conn).GetStatus" [ color="saddlebrown" tooltip="at xs.go:435: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:438: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:473: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]\nat xs.go:475: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.exitWithStatus" [ tooltip="at xs.go:751: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:832: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:941: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1005: calling [blitter.com/go/xs/xs.exitWithStatus]\nat xs.go:1079: calling [blitter.com/go/xs/xs.exitWithStatus]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xsnet.Init" [ color="saddlebrown" tooltip="at xs.go:844: calling [blitter.com/go/xs/xsnet.Init]" ] - "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ color="saddlebrown" tooltip="at xs.go:1028: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(compress/flate.CorruptInputError).Error" [ color="saddlebrown" tooltip="at xs.go:507: calling [(compress/flate.CorruptInputError).Error]" style="dashed" ] + "blitter.com/go/xs/xs.doCopyMode" -> "(blitter.com/go/xs.Session).Cmd" [ color="saddlebrown" tooltip="at xs.go:356: calling [(blitter.com/go/xs.Session).Cmd]\nat xs.go:441: calling [(blitter.com/go/xs.Session).Cmd]" ] + "blitter.com/go/xs/xs.doCopyMode" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ tooltip="at xs.go:417: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" color="saddlebrown" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).ConnHost" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).ConnHost]\nat xs.go:663: calling [(blitter.com/go/xs.Session).ConnHost]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.sendSessionParams" [ tooltip="at xs.go:1022: calling [blitter.com/go/xs/xs.sendSessionParams]" ] + "blitter.com/go/xs/xs.doCopyMode" -> "blitter.com/go/xs/xs.buildCmdLocalToRemote" [ tooltip="at xs.go:364: calling [blitter.com/go/xs/xs.buildCmdLocalToRemote]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.parseNonSwitchArgs" [ tooltip="at xs.go:796: calling [blitter.com/go/xs/xs.parseNonSwitchArgs]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:1024: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1090: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:1096: calling [blitter.com/go/xs/xs.restoreTermState]" ] + "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ color="saddlebrown" tooltip="at xs.go:1055: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" arrowhead="normalnoneodiamond" ] "blitter.com/go/xs/xs.launchTuns" -> "blitter.com/go/xs/xs.reqTunnel" [ tooltip="at xs.go:645: calling [blitter.com/go/xs/xs.reqTunnel]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(*blitter.com/go/xs/xsnet.Conn).GetStatus" [ color="saddlebrown" tooltip="at xs.go:513: calling [(*blitter.com/go/xs/xsnet.Conn).GetStatus]" ] - "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs.Session).TermType" [ color="saddlebrown" tooltip="at xs.go:651: calling [(blitter.com/go/xs.Session).TermType]\nat xs.go:667: calling [(blitter.com/go/xs.Session).TermType]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs.ReadPassword" [ color="saddlebrown" tooltip="at xs.go:983: calling [blitter.com/go/xs.ReadPassword]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs.NewSession" [ color="saddlebrown" tooltip="at xs.go:999: calling [blitter.com/go/xs.NewSession]" ] - "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xs.go:1033: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" ] - "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ color="saddlebrown" tooltip="at xs.go:1034: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" arrowhead="normalnoneodiamond" ] - "blitter.com/go/xs/xs.reqTunnel" -> "blitter.com/go/xs/logger.LogDebug" [ color="saddlebrown" tooltip="at xs.go:593: calling [blitter.com/go/xs/logger.LogDebug]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(*blitter.com/go/xs.Session).SetStatus" [ color="saddlebrown" tooltip="at xs.go:513: calling [(*blitter.com/go/xs.Session).SetStatus]" ] - "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.UnknownAuthorityError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.UnknownAuthorityError).Error]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.UnhandledCriticalExtension).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.UnhandledCriticalExtension).Error]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(compress/flate.CorruptInputError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(compress/flate.CorruptInputError).Error]" ] + "blitter.com/go/xs/xs.buildCmdLocalToRemote" -> "blitter.com/go/xs/xs.getTreeSizeSubCmd" [ tooltip="at xs.go:335: calling [blitter.com/go/xs/xs.getTreeSizeSubCmd]" ] + "blitter.com/go/xs/xs.buildCmdRemoteToLocal" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xs.go:256: calling [blitter.com/go/xs.GetTool]\nat xs.go:263: calling [blitter.com/go/xs.GetTool]" ] + "blitter.com/go/xs/xs.sendSessionParams" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ style="dashed" color="saddlebrown" tooltip="at xs.go:675: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:671: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:667: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:663: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:659: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xs.go:655: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] + "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs.Session).SetStatus" [ color="saddlebrown" tooltip="at xs.go:1025: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1043: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1047: calling [(*blitter.com/go/xs.Session).SetStatus]\nat xs.go:1086: calling [(*blitter.com/go/xs.Session).SetStatus]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(*github.com/pkg/errors.fundamental).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(*github.com/pkg/errors.fundamental).Error]" ] + "blitter.com/go/xs/xs.handleTermResizes" -> "blitter.com/go/xs/xs.handleTermResizes$1" [ arrowhead="normalnoneodot" tooltip="at termsize_unix.go:21: calling [blitter.com/go/xs/xs.handleTermResizes$1]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.usageShell" [ style="dashed" tooltip="at xs.go:852: calling [blitter.com/go/xs/xs.usageShell]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.restoreTermState" [ arrowhead="normalnoneodiamond" tooltip="at xs.go:984: calling [blitter.com/go/xs/xs.restoreTermState]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs.ReadPassword" [ color="saddlebrown" tooltip="at xs.go:1005: calling [blitter.com/go/xs.ReadPassword]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "blitter.com/go/xs/xs.doShellMode$1$1" [ arrowhead="normalnoneodiamond" tooltip="at xs.go:491: calling [blitter.com/go/xs/xs.doShellMode$1$1]" ] + "blitter.com/go/xs/xs.handleTermResizes$1" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at termsize_unix.go:33: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] + "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xs.go:1054: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(crypto/x509.HostnameError).Error" [ style="dashed" color="saddlebrown" tooltip="at xs.go:507: calling [(crypto/x509.HostnameError).Error]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(*crypto/tls.permanentError).Error" [ color="saddlebrown" tooltip="at xs.go:507: calling [(*crypto/tls.permanentError).Error]" style="dashed" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.doCopyMode" [ tooltip="at xs.go:1085: calling [blitter.com/go/xs/xs.doCopyMode]" ] + "blitter.com/go/xs/xs.copyBuffer" -> "blitter.com/go/xs/xs.copyBuffer$2" [ style="dashed" tooltip="at xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$2]" ] + "blitter.com/go/xs/xs.copyBuffer" -> "blitter.com/go/xs/xs.copyBuffer$3" [ style="dashed" tooltip="at xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$3]" ] + "blitter.com/go/xs/xs.main" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xs.go:972: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.rejectUserMsg" [ tooltip="at xs.go:1046: calling [blitter.com/go/xs/xs.rejectUserMsg]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.usageCp" [ tooltip="at xs.go:852: calling [blitter.com/go/xs/xs.usageCp]" style="dashed" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(vendor/golang.org/x/net/idna.runeError).Error" [ color="saddlebrown" tooltip="at xs.go:507: calling [(vendor/golang.org/x/net/idna.runeError).Error]" style="dashed" ] + "blitter.com/go/xs/xs.copyBuffer" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ tooltip="at xs.go:193: calling [(blitter.com/go/xs/xsnet.Conn).Write]" style="dashed" color="saddlebrown" ] "blitter.com/go/xs/xs.copyBuffer" -> "blitter.com/go/xs/xs.copyBuffer$1" [ style="dashed" tooltip="at xs.go:186: calling [blitter.com/go/xs/xs.copyBuffer$1]" ] - "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.doShellMode" [ tooltip="at xs.go:1060: calling [blitter.com/go/xs/xs.doShellMode]" ] - "blitter.com/go/xs/xs.doCopyMode" -> "blitter.com/go/xs/xs.buildCmdRemoteToLocal" [ tooltip="at xs.go:444: calling [blitter.com/go/xs/xs.buildCmdRemoteToLocal]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.main$1" [ tooltip="at xs.go:790: calling [blitter.com/go/xs/xs.main$1]" arrowhead="normalnoneodot" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xs.localUserName" [ tooltip="at xs.go:803: calling [blitter.com/go/xs/xs.localUserName]" ] + "blitter.com/go/xs/xs.reqTunnel" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at xs.go:594: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs/xsnet.Init" [ color="saddlebrown" tooltip="at xs.go:865: calling [blitter.com/go/xs/xsnet.Init]" ] + "blitter.com/go/xs/xs.main" -> "blitter.com/go/xs.NewSession" [ tooltip="at xs.go:1021: calling [blitter.com/go/xs.NewSession]" color="saddlebrown" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(blitter.com/go/xs.Session).Status" [ tooltip="at xs.go:514: calling [(blitter.com/go/xs.Session).Status]\nat xs.go:519: calling [(blitter.com/go/xs.Session).Status]" color="saddlebrown" ] + "blitter.com/go/xs/xs.handleTermResizes$1" -> "blitter.com/go/xs/xs.GetSize" [ tooltip="at termsize_unix.go:27: calling [blitter.com/go/xs/xs.GetSize]" ] + "blitter.com/go/xs/xs.reqTunnel" -> "blitter.com/go/xs/logger.LogDebug" [ color="saddlebrown" tooltip="at xs.go:593: calling [blitter.com/go/xs/logger.LogDebug]" ] + "blitter.com/go/xs/xs.main$3" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ tooltip="at xs.go:1072: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" color="saddlebrown" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "blitter.com/go/xs/xs.restoreTermState" [ tooltip="at xs.go:503: calling [blitter.com/go/xs/xs.restoreTermState]\nat xs.go:518: calling [blitter.com/go/xs/xs.restoreTermState]" ] + "blitter.com/go/xs/xs.doShellMode$1" -> "(compress/flate.InternalError).Error" [ tooltip="at xs.go:507: calling [(compress/flate.InternalError).Error]" style="dashed" color="saddlebrown" ] } diff --git a/xs/xs.go b/xs/xs.go index 1c8314d..018c542 100755 --- a/xs/xs.go +++ b/xs/xs.go @@ -1,5 +1,4 @@ // xs client - // // Copyright (c) 2017-2020 Russell Magee // Licensed under the terms of the MIT license (see LICENSE.mit in this @@ -15,10 +14,8 @@ import ( "flag" "fmt" "io" - "io/ioutil" "log" "math/rand" - "net" "os" "os/exec" "os/user" @@ -32,7 +29,7 @@ import ( "time" "net/http" - _ "net/http/pprof" + _ "net/http/pprof" //nolint:gosec xs "blitter.com/go/xs" "blitter.com/go/xs/logger" @@ -59,6 +56,18 @@ var ( //////////////////////////////////////////////////// +const ( + CmdExitedEarly = 2 + XSNetDialFailed = 3 + ErrReadingAuthReply = 253 + ServerRejectedSecureProposal = 254 + GeneralProtocolErr = 255 +) + +const ( + DeadCharPrefix = 0x1d +) + // Praise Bob. Do not remove, lest ye lose Slack. const bob = string("\r\n\r\n" + "@@@@@@@^^~~~~~~~~~~~~~~~~~~~~^@@@@@@@@@\r\n" + @@ -93,6 +102,14 @@ type ( escSeqs map[byte]escHandler ) +var ( + escs = escSeqs{ + 'i': func(io.Writer) { os.Stdout.Write([]byte("\x1b[s\x1b[2;1H\x1b[1;31m[HKEXSH]\x1b[39;49m\x1b[u")) }, + 't': func(io.Writer) { os.Stdout.Write([]byte("\x1b[1;32m[HKEXSH]\x1b[39;49m")) }, + 'B': func(io.Writer) { os.Stdout.Write([]byte("\x1b[1;32m" + bob + "\x1b[39;49m")) }, + } +) + // Copy copies from src to dst until either EOF is reached // on src or an error occurs. It returns the number of bytes // copied and the first error encountered while copying, if any. @@ -140,11 +157,6 @@ func copyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err er // or tunnel traffic indicator - note we cannot just spawn a goroutine // here, as copyBuffer() returns after each burst of data. Scope must // outlive individual copyBuffer calls). - escs := escSeqs{ - 'i': func(io.Writer) { os.Stdout.Write([]byte("\x1b[s\x1b[2;1H\x1b[1;31m[HKEXSH]\x1b[39;49m\x1b[u")) }, - 't': func(io.Writer) { os.Stdout.Write([]byte("\x1b[1;32m[HKEXSH]\x1b[39;49m")) }, - 'B': func(io.Writer) { os.Stdout.Write([]byte("\x1b[1;32m" + bob + "\x1b[39;49m")) }, - } /* // If the reader has a WriteTo method, use it to do the copy. @@ -156,7 +168,7 @@ func copyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err er if rt, ok := dst.(io.ReaderFrom); ok { return rt.ReadFrom(src) } - */ + */ //nolint:gocritic,nolintlint if buf == nil { size := 32 * 1024 if l, ok := src.(*io.LimitedReader); ok && int64(size) > l.N { @@ -177,8 +189,8 @@ func copyBuffer(dst io.Writer, src io.Reader, buf []byte) (written int64, err er // A repeat of 4 keys (conveniently 'dead' chars for most // interactive shells; here CTRL-]) shall introduce // some special responses or actions on the client side. - if seqPos < 4 { - if buf[0] == 0x1d { + if seqPos < 4 { //nolint:gomnd + if buf[0] == DeadCharPrefix { seqPos++ } } else { @@ -225,7 +237,7 @@ func GetSize() (cols, rows int, err error) { if err != nil { log.Println(err) - cols, rows = 80, 24 //failsafe + cols, rows = 80, 24 // failsafe } else { n, err := fmt.Sscanf(string(out), "%d %d\n", &rows, &cols) if n < 2 || @@ -241,7 +253,7 @@ func GetSize() (cols, rows int, err error) { return } -func buildCmdRemoteToLocal(copyQuiet bool, copyLimitBPS uint, destPath, files string) (captureStderr bool, cmd string, args []string) { +func buildCmdRemoteToLocal(copyQuiet bool, copyLimitBPS uint, destPath string) (captureStderr bool, cmd string, args []string) { // Detect if we have 'pv' // pipeview http://www.ivarch.com/programs/pv.shtml // and use it for nice client progress display. @@ -259,7 +271,7 @@ func buildCmdRemoteToLocal(copyQuiet bool, copyLimitBPS uint, destPath, files st } else { // TODO: Query remote side for total file/dir size bandwidthInBytesPerSec := " -L " + fmt.Sprintf("%d ", copyLimitBPS) - displayOpts := " -pre " + displayOpts := " -pre " //nolint:goconst cmd = xs.GetTool("bash") args = []string{"-c", "pv " + displayOpts + bandwidthInBytesPerSec + "| tar -xz -C " + destPath} } @@ -307,7 +319,7 @@ func buildCmdLocalToRemote(copyQuiet bool, copyLimitBPS uint, files string) (cap } else { captureStderr = copyQuiet bandwidthInBytesPerSec := " -L " + fmt.Sprintf("%d", copyLimitBPS) - displayOpts := " -pre " + displayOpts := " -pre " //nolint:goconst,nolintlint cmd = xs.GetTool("bash") args = []string{"-c", xs.GetTool("tar") + " -cz -f /dev/stdout "} files = strings.TrimSpace(files) @@ -357,9 +369,9 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, var c *exec.Cmd - //os.Clearenv() - //os.Setenv("HOME", u.HomeDir) - //os.Setenv("TERM", "vt102") // TODO: server or client option? + // os.Clearenv() + // os.Setenv("HOME", u.HomeDir) + // os.Setenv("TERM", "vt102") // TODO: server or client option? captureStderr, cmdName, cmdArgs := buildCmdLocalToRemote(copyQuiet, copyLimitBPS, strings.TrimSpace(files)) c = exec.Command(cmdName, cmdArgs...) // #nosec @@ -392,7 +404,7 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, if err != nil { fmt.Println("cmd exited immediately. Cannot get cmd.Wait().ExitStatus()") err = errors.New("cmd exited prematurely") - exitStatus = uint32(2) + exitStatus = uint32(CmdExitedEarly) } else { if err = c.Wait(); err != nil { if exiterr, ok := err.(*exec.ExitError); ok { @@ -412,7 +424,7 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, } // send CSOExitStatus to inform remote (server) end cp is done log.Println("Sending local exitStatus:", exitStatus) - r := make([]byte, 4) + r := make([]byte, 4) //nolint:gomnd binary.BigEndian.PutUint32(r, exitStatus) _, we := conn.WritePacket(r, xsnet.CSOExitStatus) if we != nil { @@ -420,7 +432,7 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, } // Do a final read for remote's exit status - s := make([]byte, 4) + s := make([]byte, 4) //nolint:gomnd _, remErr := conn.Read(s) if remErr != io.EOF && !strings.Contains(remErr.Error(), "use of closed network") && @@ -441,10 +453,9 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, log.Println("remote filepath:", string(rec.Cmd()), "local files:", files) destPath := files - _, cmdName, cmdArgs := buildCmdRemoteToLocal(copyQuiet, copyLimitBPS, destPath, strings.TrimSpace(files)) + _, cmdName, cmdArgs := buildCmdRemoteToLocal(copyQuiet, copyLimitBPS, destPath) - var c *exec.Cmd - c = exec.Command(cmdName, cmdArgs...) // #nosec + c := exec.Command(cmdName, cmdArgs...) // #nosec c.Stdin = conn c.Stdout = os.Stdout c.Stderr = os.Stderr @@ -481,8 +492,8 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool, // doShellMode begins an xs shell session (one-shot command or // interactive). func doShellMode(isInteractive bool, conn *xsnet.Conn, oldState *xs.State, rec *xs.Session) { - //client reader (from server) goroutine - //Read remote end's stdout + // Client reader (from server) goroutine + // Read remote end's stdout wg.Add(1) // #gv:s/label=\"doShellMode\$1\"/label=\"shellRemoteToStdin\"/ @@ -536,6 +547,8 @@ func doShellMode(isInteractive bool, conn *xsnet.Conn, oldState *xs.State, rec * _, outerr := func(conn *xsnet.Conn, r io.Reader) (w int64, e error) { // Copy() expects EOF so this will // exit with outerr == nil + // NOTE we use a local implementation of Copy() to allow + // for custom key sequences to trigger local actions w, e = Copy(conn, r) return w, e }(conn, os.Stdin) @@ -557,15 +570,15 @@ func doShellMode(isInteractive bool, conn *xsnet.Conn, oldState *xs.State, rec * } func usageShell() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) // nolint: errcheck - fmt.Fprintf(os.Stderr, "%s [opts] [user]@server\n", os.Args[0]) // nolint: errcheck + fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "%s [opts] [user]@server\n", os.Args[0]) flag.PrintDefaults() } func usageCp() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) // nolint: errcheck - fmt.Fprintf(os.Stderr, "%s [opts] srcFileOrDir [...] [user]@server[:dstpath]\n", os.Args[0]) // nolint: errcheck - fmt.Fprintf(os.Stderr, "%s [opts] [user]@server[:srcFileOrDir] dstPath\n", os.Args[0]) // nolint: errcheck + fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "%s [opts] srcFileOrDir [...] [user]@server[:dstpath]\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "%s [opts] [user]@server[:srcFileOrDir] dstPath\n", os.Args[0]) flag.PrintDefaults() } @@ -581,18 +594,18 @@ func rejectUserMsg() string { // // Server responds with [CSOTunAck:rport] or [CSOTunRefused:rport] // (handled in xsnet.Read()) -func reqTunnel(hc *xsnet.Conn, lp uint16, p string /*net.Addr*/, rp uint16) { +func reqTunnel(hc *xsnet.Conn, lp uint16 /*, p string*/ /*net.Addr*/, rp uint16) { // Write request to server so it can attempt to set up its end var bTmp bytes.Buffer if e := binary.Write(&bTmp, binary.BigEndian, lp); e != nil { - fmt.Fprintln(os.Stderr, "reqTunnel:", e) // nolint: errcheck + fmt.Fprintln(os.Stderr, "reqTunnel:", e) } if e := binary.Write(&bTmp, binary.BigEndian, rp); e != nil { - fmt.Fprintln(os.Stderr, "reqTunnel:", e) // nolint: errcheck + fmt.Fprintln(os.Stderr, "reqTunnel:", e) } - _ = logger.LogDebug(fmt.Sprintln("[Client sending CSOTunSetup]")) // nolint: gosec + _ = logger.LogDebug(fmt.Sprintln("[Client sending CSOTunSetup]")) if n, e := hc.WritePacket(bTmp.Bytes(), xsnet.CSOTunSetup); e != nil || n != len(bTmp.Bytes()) { - fmt.Fprintln(os.Stderr, "reqTunnel:", e) // nolint: errcheck + fmt.Fprintln(os.Stderr, "reqTunnel:", e) } } @@ -605,7 +618,7 @@ func parseNonSwitchArgs(a []string) (user, host, path string, isDest bool, other if strings.Contains(arg, ":") || strings.Contains(arg, "@") { fancyArg := strings.Split(flag.Arg(i), "@") var fancyHostPath []string - if len(fancyArg) < 2 { + if len(fancyArg) < 2 { //nolint:gomnd //TODO: no user specified, use current fancyUser = "[default:getUser]" fancyHostPath = strings.Split(fancyArg[0], ":") @@ -631,8 +644,8 @@ func parseNonSwitchArgs(a []string) (user, host, path string, isDest bool, other return fancyUser, fancyHost, fancyPath, isDest, otherArgs } -func launchTuns(conn *xsnet.Conn, remoteHost string, tuns string) { - remAddrs, _ := net.LookupHost(remoteHost) // nolint: gosec +func launchTuns(conn *xsnet.Conn /*remoteHost string,*/, tuns string) { + /*remAddrs, _ := net.LookupHost(remoteHost)*/ //nolint:gocritic,nolintlint if tuns == "" { return @@ -641,8 +654,8 @@ func launchTuns(conn *xsnet.Conn, remoteHost string, tuns string) { tunSpecs := strings.Split(tuns, ",") for _, tunItem := range tunSpecs { var lPort, rPort uint16 - _, _ = fmt.Sscanf(tunItem, "%d:%d", &lPort, &rPort) // nolint: gosec - reqTunnel(conn, lPort, remAddrs[0], rPort) + _, _ = fmt.Sscanf(tunItem, "%d:%d", &lPort, &rPort) + reqTunnel(conn, lPort /*remAddrs[0],*/, rPort) } } @@ -677,25 +690,26 @@ func sendSessionParams(conn io.Writer /* *xsnet.Conn*/, rec *xs.Session) (e erro } // TODO: reduce gocyclo -func main() { +func main() { //nolint: funlen, gocyclo var ( - isInteractive bool - vopt bool - gopt bool //login via password, asking server to generate authToken - dbg bool - shellMode bool // if true act as shell, else file copier - cipherAlg string //cipher alg - hmacAlg string //hmac alg - kexAlg string //KEX/KEM alg - server string - port uint - cmdStr string - tunSpecStr string // lport1:rport1[,lport2:rport2,...] - - copySrc []byte - copyDst string - copyQuiet bool - copyLimitBPS uint + isInteractive bool + vopt bool + gopt bool // true: login via password, asking server to generate authToken + dbg bool + shellMode bool // true: act as shell, false: file copier + cipherAlg string + hmacAlg string + kexAlg string + server string + port uint + cmdStr string + tunSpecStr string // lport1:rport1[,lport2:rport2,...] + rekeySecs uint + remodRequested bool // true: when rekeying, switch to random cipher/hmac alg + copySrc []byte + copyDst string + copyQuiet bool + copyLimitBPS uint authCookie string chaffEnabled bool @@ -706,7 +720,7 @@ func main() { op []byte ) - //=== Common (xs and xc) option parsing + // === Common (xs and xc) option parsing flag.BoolVar(&vopt, "v", false, "show version") flag.BoolVar(&dbg, "d", false, "debug logging") @@ -719,7 +733,8 @@ func main() { C_CHACHA20_12`) flag.StringVar(&hmacAlg, "m", "H_SHA256", "session `HMAC`"+` H_SHA256 - H_SHA512`) + H_SHA512 + H_WHIRLPOOL`) flag.StringVar(&kexAlg, "k", "KEX_HERRADURA512", "KEx `alg`"+` KEX_HERRADURA256 KEX_HERRADURA512 @@ -734,18 +749,20 @@ func main() { KEX_FRODOKEM_1344SHAKE KEX_FRODOKEM_976AES KEX_FRODOKEM_976SHAKE`) - flag.StringVar(&kcpMode, "K", "unused", "KCP `alg`, one of [KCP_NONE | KCP_AES | KCP_BLOWFISH | KCP_CAST5 | KCP_SM4 | KCP_SALSA20 | KCP_SIMPLEXOR | KCP_TEA | KCP_3DES | KCP_TWOFISH | KCP_XTEA] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP") - flag.UintVar(&port, "p", 2000, "``port") - //flag.StringVar(&authCookie, "a", "", "auth cookie") + flag.StringVar(&kcpMode, "K", "unused", "KCP `alg`, one of [KCP_NONE | KCP_AES | KCP_BLOWFISH | KCP_CAST5 | KCP_SM4 | KCP_SALSA20 | KCP_SIMPLEXOR | KCP_TEA | KCP_3DES | KCP_TWOFISH | KCP_XTEA] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP") //nolint:lll + flag.UintVar(&port, "p", 2000, "``port") //nolint:gomnd,lll + flag.UintVar(&rekeySecs, "r", 300, "rekey interval in `secs`") + flag.BoolVar(&remodRequested, "R", false, "Borg Countermeasures (remodulate cipher/hmac alg on each rekey)") + //nolint:gocritic,nolintlint // flag.StringVar(&authCookie, "a", "", "auth cookie") flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts") - flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min `msecs`") - flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max `msecs`") - flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max `bytes`") + flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min `msecs`") //nolint:gomnd + flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max `msecs`") //nolint:gomnd + flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max `bytes`") //nolint:gomnd flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to <`file`>") flag.StringVar(&memprofile, "memprofile", "", "write memory profile to <`file`>") - //=== xc vs. xs option parsing + // === xc vs. xs option parsing // Find out what program we are (shell or copier) myPath := strings.Split(os.Args[0], string(os.PathSeparator)) @@ -762,7 +779,7 @@ func main() { flag.Usage = usageShell } else { flag.BoolVar(©Quiet, "q", false, "do not output progress bar during copy") - flag.UintVar(©LimitBPS, "L", 8589934592, "copy max rate in bytes per sec") + flag.UintVar(©LimitBPS, "L", 8589934592, "copy max rate in bytes per sec") //nolint:gomnd flag.Usage = usageCp } flag.Parse() @@ -772,7 +789,7 @@ func main() { exitWithStatus(0) } - //=== Profiling instrumentation + // === Profiling instrumentation if cpuprofile != "" { f, err := os.Create(cpuprofile) @@ -782,24 +799,24 @@ func main() { defer f.Close() fmt.Println("StartCPUProfile()") if err := pprof.StartCPUProfile(f); err != nil { - log.Fatal("could not start CPU profile: ", err) + log.Fatal("could not start CPU profile: ", err) //nolint:gocritic } else { defer pprof.StopCPUProfile() } - go func() { http.ListenAndServe("localhost:6060", nil) }() + go func() { http.ListenAndServe("localhost:6060", nil) }() //nolint:errcheck,gosec } - //=== User, host, port and path args for file operations, if applicable + // === User, host, port and path args for file operations, if applicable remoteUser, remoteHost, tmpPath, pathIsDest, otherArgs := parseNonSwitchArgs(flag.Args()) - //fmt.Println("otherArgs:", otherArgs) + //nolint:gocritic,nolintlint // fmt.Println("otherArgs:", otherArgs) // Set defaults if user doesn't specify user, path or port var uname string if remoteUser == "" { - u, _ := user.Current() // nolint: gosec + u, _ := user.Current() uname = localUserName(u) } else { uname = remoteUser @@ -812,7 +829,7 @@ func main() { tmpPath = "." } - //=== Copy mode arg and copy src/dest setup + // === Copy mode arg and copy src/dest setup var fileArgs string if !shellMode /*&& tmpPath != ""*/ { @@ -845,15 +862,15 @@ func main() { } } - //=== Do some final option consistency checks + // === Do some final option consistency checks - //fmt.Println("server finally is:", server) + //nolint:gocritic,nolintlint // fmt.Println("server finally is:", server) if flag.NFlag() == 0 && server == "" { flag.Usage() exitWithStatus(0) } - if len(cmdStr) != 0 && (len(copySrc) != 0 || len(copyDst) != 0) { + if cmdStr != "" && (len(copySrc) != 0 || copyDst != "") { log.Fatal("incompatible options -- either cmd (-x) or copy ops but not both") } @@ -861,27 +878,27 @@ func main() { // either the shell session or copy operation. _ = shellMode - Log, _ = logger.New(logger.LOG_USER|logger.LOG_DEBUG|logger.LOG_NOTICE|logger.LOG_ERR, "xs") // nolint: errcheck,gosec + Log, _ = logger.New(logger.LOG_USER|logger.LOG_DEBUG|logger.LOG_NOTICE|logger.LOG_ERR, "xs") xsnet.Init(dbg, "xs", logger.LOG_USER|logger.LOG_DEBUG|logger.LOG_NOTICE|logger.LOG_ERR) if dbg { log.SetOutput(Log) } else { - log.SetOutput(ioutil.Discard) + log.SetOutput(io.Discard) } - //=== Auth token fetch for login + // === Auth token fetch for login if !gopt { // See if we can log in via an auth token - u, _ := user.Current() // nolint: gosec - ab, aerr := ioutil.ReadFile(fmt.Sprintf("%s/.xs_id", u.HomeDir)) + u, _ := user.Current() + ab, aerr := os.ReadFile(fmt.Sprintf("%s/%s", u.HomeDir, xsnet.XS_ID_AUTHTOKFILE)) if aerr == nil { for _, line := range strings.Split(string(ab), "\n") { - line = line + "\n" - idx := strings.Index(string(line), remoteHost+":"+uname) + line += "\n" + idx := strings.Index(line, remoteHost+":"+uname) if idx >= 0 { line = line[idx:] - entries := strings.SplitN(string(line), "\n", -1) + entries := strings.SplitN(line, "\n", -1) authCookie = strings.TrimSpace(entries[0]) // Security scrub line = "" @@ -891,15 +908,14 @@ func main() { if authCookie == "" { _, _ = fmt.Fprintln(os.Stderr, "[no authtoken, use -g to request one from server]") } - } else { - log.Printf("[cannot read %s/.xs_id]\n", u.HomeDir) + log.Printf("[cannot read %s/%s]\n", u.HomeDir, xsnet.XS_ID_AUTHTOKFILE) } } runtime.GC() - //=== Enforce some sane min/max vals on chaff flags - if chaffFreqMin < 2 { + // === Enforce some sane min/max vals on chaff flags + if chaffFreqMin < 2 { //nolint:gomnd chaffFreqMin = 2 } if chaffFreqMax == 0 { @@ -909,17 +925,17 @@ func main() { chaffBytesMax = 64 } - //=== Shell vs. Copy mode chaff and cmd setup + // === Shell vs. Copy mode chaff and cmd setup if shellMode { // We must make the decision about interactivity before Dial() // as it affects chaffing behaviour. 20180805 if gopt { - fmt.Fprintln(os.Stderr, "[requesting authtoken from server]") // nolint: errcheck + fmt.Fprintln(os.Stderr, "[requesting authtoken from server]") op = []byte{'A'} chaffFreqMin = 2 chaffFreqMax = 10 - } else if len(cmdStr) == 0 { + } else if cmdStr == "" { op = []byte{'s'} isInteractive = true } else { @@ -940,38 +956,47 @@ func main() { // client->server file copy // src file list is in copySrc op = []byte{'D'} - //fmt.Println("client->server copy:", string(copySrc), "->", copyDst) + //nolint:gocritic,nolintlint // fmt.Println("client->server copy:", string(copySrc), "->", copyDst) cmdStr = copyDst } else { // server->client file copy // remote src file(s) in copyDsr op = []byte{'S'} - //fmt.Println("server->client copy:", string(copySrc), "->", copyDst) + //nolint:gocritic,nolintlint // fmt.Println("server->client copy:", string(copySrc), "->", copyDst) cmdStr = string(copySrc) } } - //=== TCP / KCP Dial setup + // === TCP / KCP Dial setup proto := "tcp" if kcpMode != "unused" { proto = "kcp" } - conn, err := xsnet.Dial(proto, server, cipherAlg, hmacAlg, kexAlg, kcpMode) + + remodExtArg := "" + if remodRequested { + remodExtArg = "OPT_REMOD" + } + // Pass opt to Dial() via extensions arg + conn, err := xsnet.Dial(proto, server, cipherAlg, hmacAlg, kexAlg, kcpMode, remodExtArg) if err != nil { fmt.Println(err) - exitWithStatus(3) + exitWithStatus(XSNetDialFailed) } - //=== Shell terminal mode (Shell vs. Copy) setup + conn.RekeyHelper(rekeySecs) + defer conn.ShutdownRekey() + + // === Shell terminal mode (Shell vs. Copy) setup // Set stdin in raw mode if it's an interactive session // TODO: send flag to server side indicating this // affects shell command used var oldState *xs.State - defer conn.Close() // nolint: errcheck + defer conn.Close() - //=== From this point on, conn is a secure encrypted channel + // === From this point on, conn is a secure encrypted channel if shellMode { if isatty.IsTerminal(os.Stdin.Fd()) { @@ -987,108 +1012,115 @@ func main() { } } - //=== Login phase + // === Login phase // Start login timeout here and disconnect if user/pass phase stalls - //iloginImpatience := time.AfterFunc(20*time.Second, func() { - //i fmt.Printf(" .. [you still there? Waiting for a password.]") - //i}) - loginTimeout := time.AfterFunc(30*time.Second, func() { + // iloginImpatience := time.AfterFunc(20*time.Second, func() { + // i fmt.Printf(" .. [you still there? Waiting for a password.]") + // i}) + loginTimeout := time.AfterFunc(30*time.Second, func() { //nolint:gomnd restoreTermState(oldState) fmt.Printf(" .. [login timeout]\n") - exitWithStatus(xsnet.CSOLoginTimeout) + exitWithStatus(xsnet.CSELoginTimeout) }) - if len(authCookie) == 0 { - //No auth token, prompt for password - fmt.Printf("Gimme cookie:") + if authCookie == "" { + if !gopt { + // No auth token, prompt for password + fmt.Printf("Gimme cookie:") + } ab, e := xs.ReadPassword(os.Stdin.Fd()) - fmt.Printf("\r\n") + if !gopt { + fmt.Printf("\r\n") + } if e != nil { panic(e) } authCookie = string(ab) } - //i_ = loginImpatience.Stop() + //nolint:gocritic,nolintlint // i_ = loginImpatience.Stop() _ = loginTimeout.Stop() // Security scrub runtime.GC() - //=== Session param and TERM setup + // === Session param and TERM setup // Set up session params and send over to server rec := xs.NewSession(op, []byte(uname), []byte(remoteHost), []byte(os.Getenv("TERM")), []byte(cmdStr), []byte(authCookie), 0) sendErr := sendSessionParams(&conn, rec) if sendErr != nil { restoreTermState(oldState) - rec.SetStatus(254) - fmt.Fprintln(os.Stderr, "Error: server rejected secure proposal params or login timed out") // nolint: errcheck + rec.SetStatus(ServerRejectedSecureProposal) + fmt.Fprintln(os.Stderr, "Error: server rejected secure proposal params or login timed out") exitWithStatus(int(rec.Status())) - //log.Fatal(sendErr) + //nolint:gocritic,nolintlint // log.Fatal(sendErr) } - //Security scrub - authCookie = "" // nolint: ineffassign + // Security scrub + authCookie = "" //nolint: ineffassign runtime.GC() - //=== Login Auth + // === Login Auth - //=== Read auth reply from server + // === Read auth reply from server authReply := make([]byte, 1) // bool: 0 = fail, 1 = pass _, err = conn.Read(authReply) if err != nil { - //=== Exit if auth reply not received - fmt.Fprintln(os.Stderr, "Error reading auth reply") // nolint: errcheck - rec.SetStatus(255) + // === Exit if auth reply not received + fmt.Fprintln(os.Stderr, "Error reading auth reply") + rec.SetStatus(ErrReadingAuthReply) } else if authReply[0] == 0 { - //=== .. or if auth failed - fmt.Fprintln(os.Stderr, rejectUserMsg()) // nolint: errcheck - rec.SetStatus(255) + // === .. or if auth failed + fmt.Fprintln(os.Stderr, rejectUserMsg()) + rec.SetStatus(GeneralProtocolErr) } else { - //=== Set up chaffing to server + // === Set up connection keepalive to server + conn.StartupKeepAlive() // goroutine, returns immediately + defer conn.ShutdownKeepAlive() + + // === Set up chaffing to server conn.SetupChaff(chaffFreqMin, chaffFreqMax, chaffBytesMax) // enable client->server chaffing if chaffEnabled { // #gv:s/label=\"main\$2\"/label=\"deferCloseChaff\"/ // TODO:.gv:main:2:deferCloseChaff - conn.EnableChaff() // goroutine, returns immediately - defer conn.DisableChaff() + conn.StartupChaff() // goroutine, returns immediately defer conn.ShutdownChaff() } - //=== (goroutine) Start keepAliveWorker for tunnels + // === (goroutine) Start keepAliveWorker for tunnels // #gv:s/label=\"main\$1\"/label=\"tunKeepAlive\"/ // TODO:.gv:main:1:tunKeepAlive - //[1]: better to always send tunnel keepAlives even if client didn't specify - // any, to prevent listeners from knowing this. - //[1] if tunSpecStr != "" { + // [1]: better to always send tunnel keepAlives even if client didn't specify + // any, to prevent listeners from knowing this. + // [1] if tunSpecStr != "" { keepAliveWorker := func() { for { // Add a bit of jitter to keepAlive so it doesn't stand out quite as much - time.Sleep(time.Duration(2000-rand.Intn(200)) * time.Millisecond) + time.Sleep(time.Duration(2000-rand.Intn(200)) * time.Millisecond) //nolint:gosec,gomnd // FIXME: keepAlives should probably have small random packet len/data as well // to further obscure them vs. interactive or tunnel data // keepAlives must be >=2 bytes, due to processing elsewhere - conn.WritePacket([]byte{0, 0}, xsnet.CSOTunKeepAlive) // nolint: errcheck,gosec + conn.WritePacket([]byte{0, 0}, xsnet.CSOTunKeepAlive) //nolint: errcheck } } go keepAliveWorker() - //[1]} + // [1]} - //=== Session entry (shellMode or copyMode) + // === Session entry (shellMode or copyMode) if shellMode { - //=== (shell) launch tunnels - launchTuns(&conn, remoteHost, tunSpecStr) + // === (shell) launch tunnels + launchTuns(&conn /*remoteHost,*/, tunSpecStr) doShellMode(isInteractive, &conn, oldState, rec) } else { - //=== (.. or file copy) - s, _ := doCopyMode(&conn, pathIsDest, fileArgs, copyQuiet, copyLimitBPS, rec) // nolint: errcheck,gosec + // === (.. or file copy) + s, _ := doCopyMode(&conn, pathIsDest, fileArgs, copyQuiet, copyLimitBPS, rec) rec.SetStatus(s) } if rec.Status() != 0 { restoreTermState(oldState) - fmt.Fprintln(os.Stderr, "Session exited with status:", rec.Status()) // nolint: errcheck + fmt.Fprintln(os.Stderr, "Session exited with status:", rec.Status()) } } @@ -1097,7 +1129,7 @@ func main() { oldState = nil } - //=== Exit + // === Exit exitWithStatus(int(rec.Status())) } @@ -1115,7 +1147,7 @@ func localUserName(u *user.User) string { } func restoreTermState(oldState *xs.State) { - _ = xs.Restore(os.Stdin.Fd(), oldState) // nolint: errcheck,gosec + _ = xs.Restore(os.Stdin.Fd(), oldState) } // exitWithStatus wraps os.Exit() plus does any required pprof housekeeping @@ -1132,9 +1164,8 @@ func exitWithStatus(status int) { defer f.Close() runtime.GC() // get up-to-date statistics if err := pprof.WriteHeapProfile(f); err != nil { - log.Fatal("could not write memory profile: ", err) + log.Fatal("could not write memory profile: ", err) //nolint:gocritic } } - os.Exit(status) } diff --git a/xsd.sysvrc b/xsd.sysvrc index 8e617c5..415c591 100755 --- a/xsd.sysvrc +++ b/xsd.sysvrc @@ -11,6 +11,10 @@ set -e +echo "SET XSD_OPTS in this script to define allow KEX, cipher and hmac algs" +#XSD_OPTS="-L -aK KEX_all -aC C_all -aH H_all" +exit 1 + # /etc/init.d/xsd: start and stop the eXperimental "secure" Shell Daemon test -x /usr/local/sbin/xsd || exit 0 diff --git a/xsd/xsd-vis-fixedup.png b/xsd/xsd-vis-fixedup.png index ffa007d..4a16553 100644 Binary files a/xsd/xsd-vis-fixedup.png and b/xsd/xsd-vis-fixedup.png differ diff --git a/xsd/xsd-vis.gv b/xsd/xsd-vis.gv index 91e71a4..d584224 100755 --- a/xsd/xsd-vis.gv +++ b/xsd/xsd-vis.gv @@ -10,102 +10,102 @@ digraph gocallvis { pad="0.0"; nodesep="0.35"; - node [shape="ellipse" style="filled" fillcolor="honeydew" fontname="Verdana" penwidth="1.0" margin="0.05,0.0"]; + node [shape="box" style="filled,rounded" fillcolor="honeydew" fontname="Verdana" penwidth="1.0" margin="0.05,0.0"]; edge [minlen="2"] subgraph "cluster_focus" { - label="main"; + bgcolor="#e6ecfa"; +label="main"; labelloc="t"; labeljust="c"; fontsize="18"; -bgcolor="#e6ecfa"; - "blitter.com/go/xs/xsd.main$2$1" [ fillcolor="lightblue" label="main$2$1" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.main$2$1 | defined in xsd.go:650\nat xsd.go:653: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:652: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:651: calling [blitter.com/go/xs/logger.LogNotice]" ] - "blitter.com/go/xs/xsd.runShellAs$6" [ fillcolor="lightblue" label="runShellAs$6" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$6 | defined in xsd.go:381\nat xsd.go:385: calling [(context.deadlineExceededError).Error]\nat xsd.go:385: calling [(compress/flate.CorruptInputError).Error]\nat xsd.go:385: calling [(compress/flate.InternalError).Error]\nat xsd.go:385: calling [(*github.com/pkg/errors.fundamental).Error]" ] + "blitter.com/go/xs/xsd.main$2$1" [ fillcolor="lightblue" label="main$2$1" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.main$2$1 | defined in xsd.go:675\nat xsd.go:677: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:676: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:678: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] + "blitter.com/go/xs/xsd.main$1" [ fillcolor="lightblue" label="main$1" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.main$1 | defined in xsd.go:610\nat xsd.go:615: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:619: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:623: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:625: calling [blitter.com/go/xs/logger.LogNotice]" ] + "blitter.com/go/xs/xsd.runShellAs$3" [ tooltip="blitter.com/go/xs/xsd.runShellAs$3 | defined in xsd.go:345\nat xsd.go:348: calling [github.com/creack/pty.Setsize]" fillcolor="lightblue" label="stdinToPtyWorker" style="dotted,filled" ] "blitter.com/go/xs/xsd.runShellAs$2" [ fillcolor="lightblue" label="termResizeWatcher" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$2 | defined in xsd.go:336\nat xsd.go:336: calling [blitter.com/go/goutmp.Unput_utmp]" ] - "blitter.com/go/xs/xsd.runServerToClientCopyAs" [ fillcolor="lightblue" label="runServerToClientCopyAs" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.runServerToClientCopyAs | defined in xsd.go:169\nat xsd.go:220: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xsd.go:223: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]\nat xsd.go:224: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]\nat xsd.go:193: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xsd.runClientToServerCopyAs" [ fillcolor="lightblue" label="runClientToServerCopyAs" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.runClientToServerCopyAs | defined in xsd.go:68\nat xsd.go:122: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]\nat xsd.go:119: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xsd.go:88: calling [blitter.com/go/xs.GetTool]\nat xsd.go:121: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" ] - "blitter.com/go/xs/xsd.runShellAs$4" [ label="deferChaffShutdown" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$4 | defined in xsd.go:355\nat xsd.go:358: calling [(*github.com/pkg/errors.fundamental).Error]\nat xsd.go:358: calling [(context.deadlineExceededError).Error]\nat xsd.go:358: calling [(compress/flate.CorruptInputError).Error]\nat xsd.go:358: calling [(compress/flate.InternalError).Error]" fillcolor="lightblue" ] - "blitter.com/go/xs/xsd.main$1" [ fillcolor="lightblue" label="main$1" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.main$1 | defined in xsd.go:586\nat xsd.go:591: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:595: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:599: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:601: calling [blitter.com/go/xs/logger.LogNotice]" ] - "blitter.com/go/xs/xsd.main$2" [ fillcolor="lightblue" label="main$2" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.main$2 | defined in xsd.go:646\nat xsd.go:828: calling [blitter.com/go/xs/xsd.runServerToClientCopyAs]\nat xsd.go:701: calling [(*blitter.com/go/xs.Session).SetTermType]\nat xsd.go:720: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:724: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:729: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:731: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:743: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:754: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:755: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:757: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:762: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:764: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:771: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:772: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:777: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:779: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:786: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:788: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:793: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:795: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:803: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:809: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:811: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:827: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:830: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:833: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:729: calling [blitter.com/go/xs.VerifyPass]\nat xsd.go:737: calling [(*blitter.com/go/xs.Session).ClearAuthCookie]\nat xsd.go:743: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:754: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:771: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:779: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:786: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:795: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:803: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:811: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:827: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:833: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:717: calling [(*blitter.com/go/xs.Session).SetAuthCookie]\nat xsd.go:757: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:772: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:788: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:765: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:780: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:796: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:815: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:841: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:693: calling [(*blitter.com/go/xs.Session).SetConnHost]\nat xsd.go:804: calling [blitter.com/go/xs/xsd.runClientToServerCopyAs]\nat xsd.go:752: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:769: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:784: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:801: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:825: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:762: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:777: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:809: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:846: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:830: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:709: calling [(*blitter.com/go/xs.Session).SetCmd]\nat xsd.go:720: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:724: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:755: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:821: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat xsd.go:685: calling [(*blitter.com/go/xs.Session).SetWho]\nat xsd.go:753: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:770: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:785: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:802: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:826: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:755: calling [blitter.com/go/xs/xsd.GenAuthToken]\nat xsd.go:757: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:772: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:788: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:647: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:677: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:760: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:775: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:791: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:807: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:840: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:724: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:729: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:731: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:724: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:729: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:731: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:731: calling [blitter.com/go/xs.AuthUserByPasswd]\nat xsd.go:741: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:744: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:720: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:750: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:767: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:782: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:798: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:822: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:720: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:772: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:788: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:724: calling [blitter.com/go/xs.AuthUserByToken]" ] - "blitter.com/go/xs/xsd.GenAuthToken" [ fillcolor="lightblue" label="GenAuthToken" penwidth="1.5" tooltip="blitter.com/go/xs/xsd.GenAuthToken | defined in xsd.go:424" ] - "blitter.com/go/xs/xsd.runShellAs" [ penwidth="0.5" tooltip="blitter.com/go/xs/xsd.runShellAs | defined in xsd.go:259\nat xsd.go:381: calling [blitter.com/go/xs/xsd.runShellAs$6]\nat xsd.go:336: calling [blitter.com/go/xs/xsd.runShellAs$2]\nat xsd.go:318: calling [github.com/creack/pty.Start]\nat xsd.go:337: calling [blitter.com/go/goutmp.Put_lastlog_entry]\nat xsd.go:409: calling [blitter.com/go/xs/logger.LogDebug]\nat xsd.go:308: calling [blitter.com/go/xs.GetTool]\nat xsd.go:297: calling [blitter.com/go/xs.GetTool]\nat xsd.go:303: calling [blitter.com/go/xs.GetTool]\nat xsd.go:331: calling [blitter.com/go/xs/xsd.ptsName]\nat xsd.go:335: calling [blitter.com/go/goutmp.Put_utmp]\nat xsd.go:368: calling [blitter.com/go/xs/xsd.runShellAs$5]\nat xsd.go:365: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xsd.go:407: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:345: calling [blitter.com/go/xs/xsd.runShellAs$3]\nat xsd.go:325: calling [blitter.com/go/xs/xsd.runShellAs$1]\nat xsd.go:355: calling [blitter.com/go/xs/xsd.runShellAs$4]" fillcolor="lightblue" label="runShellAs" ] - "blitter.com/go/xs/xsd.runShellAs$1" [ label="deferPtmxClose" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$1 | defined in xsd.go:325" fillcolor="lightblue" ] - "blitter.com/go/xs/xsd.ptsName" [ tooltip="blitter.com/go/xs/xsd.ptsName | defined in xsd.go:57\nat xsd.go:59: calling [blitter.com/go/xs/xsd.ioctl]" fillcolor="lightblue" label="ptsName" penwidth="0.5" ] + "blitter.com/go/xs/xsd.main" [ penwidth="0.5" tooltip="blitter.com/go/xs/xsd.main | defined in xsd.go:508\nat xsd.go:583: calling [blitter.com/go/xs/logger.New]\nat xsd.go:650: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:654: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:658: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:648: calling [(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed]\nat xsd.go:671: calling [blitter.com/go/xs/xsd.main$2]\nat xsd.go:644: calling [(*blitter.com/go/xs/xsnet.HKExListener).Accept]\nat xsd.go:648: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]\nat xsd.go:649: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]\nat xsd.go:656: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]\nat xsd.go:657: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]\nat xsd.go:595: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:600: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:605: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:651: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:655: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:659: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:652: calling [(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed]\nat xsd.go:638: calling [(blitter.com/go/xs/xsnet.HKExListener).Close]\nat xsd.go:666: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]\nat xsd.go:610: calling [blitter.com/go/xs/xsd.main$1]\nat xsd.go:656: calling [(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed]\nat xsd.go:652: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]\nat xsd.go:653: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]\nat xsd.go:584: calling [blitter.com/go/xs/xsnet.Init]\nat xsd.go:634: calling [blitter.com/go/xs/xsnet.Listen]" fillcolor="lightblue" label="main" ] + "blitter.com/go/xs/xsd.main$2" [ style="dotted,filled" tooltip="blitter.com/go/xs/xsd.main$2 | defined in xsd.go:671\nat xsd.go:853: calling [blitter.com/go/xs/xsd.runServerToClientCopyAs]\nat xsd.go:672: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:710: calling [(*blitter.com/go/xs.Session).SetWho]\nat xsd.go:790: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:805: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:821: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:840: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:866: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:726: calling [(*blitter.com/go/xs.Session).SetTermType]\nat xsd.go:766: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:769: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:782: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:797: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:813: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:829: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:853: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:734: calling [(*blitter.com/go/xs.Session).SetCmd]\nat xsd.go:754: calling [blitter.com/go/xs.VerifyPass]\nat xsd.go:762: calling [(*blitter.com/go/xs.Session).ClearAuthCookie]\nat xsd.go:718: calling [(*blitter.com/go/xs.Session).SetConnHost]\nat xsd.go:745: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:797: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:813: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:829: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:853: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:829: calling [blitter.com/go/xs/xsd.runClientToServerCopyAs]\nat xsd.go:749: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:754: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:756: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:745: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:749: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:754: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:756: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:768: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:779: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:780: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:782: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:787: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:789: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:796: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:797: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:802: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:811: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:813: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:818: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:820: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:829: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:834: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:836: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:852: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:853: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:855: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:858: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:749: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:754: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:756: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:778: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:795: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:810: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:827: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:851: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:782: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:797: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:813: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:768: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:779: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:796: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:804: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:811: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:820: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:828: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:836: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:852: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:858: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:787: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:802: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:834: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:871: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:855: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:756: calling [blitter.com/go/xs.AuthUserByPasswd]\nat xsd.go:742: calling [(*blitter.com/go/xs.Session).SetAuthCookie]\nat xsd.go:745: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:749: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:780: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:780: calling [blitter.com/go/xs/xsd.GenAuthToken]\nat xsd.go:777: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:794: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:809: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:826: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:850: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:846: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]\nat xsd.go:749: calling [blitter.com/go/xs.AuthUserByToken]\nat xsd.go:745: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:775: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:792: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:807: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:823: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:847: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:702: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:785: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:800: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:816: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:832: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:865: calling [(*blitter.com/go/xs.Session).SetOp]" fillcolor="lightblue" label="main$2" ] + "blitter.com/go/xs/xsd.GenAuthToken" [ label="GenAuthToken" penwidth="1.5" tooltip="blitter.com/go/xs/xsd.GenAuthToken | defined in xsd.go:424" fillcolor="lightblue" ] + "blitter.com/go/xs/xsd.runShellAs" [ fillcolor="lightblue" label="runShellAs" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.runShellAs | defined in xsd.go:259\nat xsd.go:355: calling [blitter.com/go/xs/xsd.runShellAs$4]\nat xsd.go:381: calling [blitter.com/go/xs/xsd.runShellAs$6]\nat xsd.go:308: calling [blitter.com/go/xs.GetTool]\nat xsd.go:297: calling [blitter.com/go/xs.GetTool]\nat xsd.go:303: calling [blitter.com/go/xs.GetTool]\nat xsd.go:331: calling [blitter.com/go/xs/xsd.ptsName]\nat xsd.go:365: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xsd.go:407: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:318: calling [github.com/creack/pty.Start]\nat xsd.go:335: calling [blitter.com/go/goutmp.Put_utmp]\nat xsd.go:368: calling [blitter.com/go/xs/xsd.runShellAs$5]\nat xsd.go:409: calling [blitter.com/go/xs/logger.LogDebug]\nat xsd.go:325: calling [blitter.com/go/xs/xsd.runShellAs$1]\nat xsd.go:336: calling [blitter.com/go/xs/xsd.runShellAs$2]\nat xsd.go:337: calling [blitter.com/go/goutmp.Put_lastlog_entry]\nat xsd.go:345: calling [blitter.com/go/xs/xsd.runShellAs$3]" ] + "blitter.com/go/xs/xsd.runShellAs$1" [ fillcolor="lightblue" label="deferPtmxClose" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$1 | defined in xsd.go:325" ] + "blitter.com/go/xs/xsd.ptsName" [ fillcolor="lightblue" label="ptsName" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.ptsName | defined in xsd.go:57\nat xsd.go:59: calling [blitter.com/go/xs/xsd.ioctl]" ] "blitter.com/go/xs/xsd.ioctl" [ fillcolor="lightblue" label="ioctl" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.ioctl | defined in xsd.go:50" ] - "blitter.com/go/xs/xsd.runShellAs$3" [ label="stdinToPtyWorker" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$3 | defined in xsd.go:345\nat xsd.go:348: calling [github.com/creack/pty.Setsize]" fillcolor="lightblue" ] + "blitter.com/go/xs/xsd.runShellAs$4" [ label="deferChaffShutdown" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$4 | defined in xsd.go:355\nat xsd.go:358: calling [(context.deadlineExceededError).Error]\nat xsd.go:358: calling [(vendor/golang.org/x/net/idna.runeError).Error]\nat xsd.go:358: calling [(compress/flate.InternalError).Error]\nat xsd.go:358: calling [(compress/flate.CorruptInputError).Error]\nat xsd.go:358: calling [(vendor/golang.org/x/net/idna.labelError).Error]\nat xsd.go:358: calling [(*github.com/pkg/errors.fundamental).Error]" fillcolor="lightblue" ] "blitter.com/go/xs/xsd.runShellAs$5" [ fillcolor="lightblue" label="ptyToStdoutWorker" style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$5 | defined in xsd.go:368\nat xsd.go:369: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]\nat xsd.go:370: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" ] - "blitter.com/go/xs/xsd.main" [ fillcolor="lightblue" label="main" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.main | defined in xsd.go:508\nat xsd.go:627: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]\nat xsd.go:628: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]\nat xsd.go:641: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]\nat xsd.go:610: calling [blitter.com/go/xs/xsnet.Listen]\nat xsd.go:623: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]\nat xsd.go:624: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]\nat xsd.go:614: calling [(blitter.com/go/xs/xsnet.HKExListener).Close]\nat xsd.go:620: calling [(*blitter.com/go/xs/xsnet.HKExListener).Accept]\nat xsd.go:627: calling [(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed]\nat xsd.go:623: calling [(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed]\nat xsd.go:631: calling [(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed]\nat xsd.go:626: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:630: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:634: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:571: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:576: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:581: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:586: calling [blitter.com/go/xs/xsd.main$1]\nat xsd.go:625: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:629: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:633: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:559: calling [blitter.com/go/xs/logger.New]\nat xsd.go:631: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]\nat xsd.go:632: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]\nat xsd.go:560: calling [blitter.com/go/xs/xsnet.Init]\nat xsd.go:646: calling [blitter.com/go/xs/xsd.main$2]" ] + "blitter.com/go/xs/xsd.runShellAs$6" [ style="dotted,filled" tooltip="blitter.com/go/xs/xsd.runShellAs$6 | defined in xsd.go:381\nat xsd.go:385: calling [(vendor/golang.org/x/net/idna.labelError).Error]\nat xsd.go:385: calling [(*github.com/pkg/errors.fundamental).Error]\nat xsd.go:385: calling [(compress/flate.CorruptInputError).Error]\nat xsd.go:385: calling [(vendor/golang.org/x/net/idna.runeError).Error]\nat xsd.go:385: calling [(context.deadlineExceededError).Error]\nat xsd.go:385: calling [(compress/flate.InternalError).Error]" fillcolor="lightblue" label="runShellAs$6" ] + "blitter.com/go/xs/xsd.runClientToServerCopyAs" [ fillcolor="lightblue" label="runClientToServerCopyAs" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.runClientToServerCopyAs | defined in xsd.go:68\nat xsd.go:119: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xsd.go:121: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]\nat xsd.go:122: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]\nat xsd.go:88: calling [blitter.com/go/xs.GetTool]" ] + "blitter.com/go/xs/xsd.runServerToClientCopyAs" [ fillcolor="lightblue" label="runServerToClientCopyAs" penwidth="0.5" tooltip="blitter.com/go/xs/xsd.runServerToClientCopyAs | defined in xsd.go:169\nat xsd.go:220: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]\nat xsd.go:224: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]\nat xsd.go:193: calling [blitter.com/go/xs.GetTool]\nat xsd.go:223: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" ] subgraph "cluster_blitter.com/go/goutmp" { - fontname="Tahoma bold"; + penwidth="0.8"; rank="sink"; -label="goutmp"; -penwidth="0.8"; -style="filled"; URL="/?f=blitter.com/go/goutmp"; -tooltip="package: blitter.com/go/goutmp"; fontsize="16"; +style="filled"; fillcolor="lightyellow"; +fontname="Tahoma bold"; +label="goutmp"; +tooltip="package: blitter.com/go/goutmp"; "blitter.com/go/goutmp.Unput_utmp" [ fillcolor="moccasin" label="Unput_utmp" penwidth="1.5" tooltip="blitter.com/go/goutmp.Unput_utmp | defined in goutmp_linux.go:115" ] "blitter.com/go/goutmp.GetHost" [ fillcolor="moccasin" label="GetHost" penwidth="1.5" tooltip="blitter.com/go/goutmp.GetHost | defined in goutmp_linux.go:91" ] "blitter.com/go/goutmp.Put_utmp" [ fillcolor="moccasin" label="Put_utmp" penwidth="1.5" tooltip="blitter.com/go/goutmp.Put_utmp | defined in goutmp_linux.go:106" ] - "blitter.com/go/goutmp.Put_lastlog_entry" [ fillcolor="moccasin" label="Put_lastlog_entry" penwidth="1.5" tooltip="blitter.com/go/goutmp.Put_lastlog_entry | defined in goutmp_linux.go:120" ] + "blitter.com/go/goutmp.Put_lastlog_entry" [ tooltip="blitter.com/go/goutmp.Put_lastlog_entry | defined in goutmp_linux.go:120" fillcolor="moccasin" label="Put_lastlog_entry" penwidth="1.5" ] } subgraph "cluster_blitter.com/go/xs" { - fontsize="16"; + penwidth="0.8"; style="filled"; +fontname="Tahoma bold"; +tooltip="package: blitter.com/go/xs"; +fontsize="16"; fillcolor="lightyellow"; rank="sink"; -penwidth="0.8"; -fontname="Tahoma bold"; label="xs"; URL="/?f=blitter.com/go/xs"; -tooltip="package: blitter.com/go/xs"; - "blitter.com/go/xs.GetTool" [ tooltip="blitter.com/go/xs.GetTool | defined in auth.go:211" fillcolor="moccasin" label="GetTool" penwidth="1.5" ] - "blitter.com/go/xs.NewAuthCtx" [ penwidth="1.5" tooltip="blitter.com/go/xs.NewAuthCtx | defined in auth.go:35" fillcolor="moccasin" label="NewAuthCtx" ] - "blitter.com/go/xs.AuthUserByToken" [ tooltip="blitter.com/go/xs.AuthUserByToken | defined in auth.go:161" fillcolor="moccasin" label="AuthUserByToken" penwidth="1.5" ] + "blitter.com/go/xs.NewAuthCtx" [ fillcolor="moccasin" label="NewAuthCtx" penwidth="1.5" tooltip="blitter.com/go/xs.NewAuthCtx | defined in auth.go:35" ] + "blitter.com/go/xs.AuthUserByToken" [ fillcolor="moccasin" label="AuthUserByToken" penwidth="1.5" tooltip="blitter.com/go/xs.AuthUserByToken | defined in auth.go:161" ] "blitter.com/go/xs.VerifyPass" [ fillcolor="moccasin" label="VerifyPass" penwidth="1.5" tooltip="blitter.com/go/xs.VerifyPass | defined in auth.go:44" ] "blitter.com/go/xs.AuthUserByPasswd" [ fillcolor="moccasin" label="AuthUserByPasswd" penwidth="1.5" tooltip="blitter.com/go/xs.AuthUserByPasswd | defined in auth.go:96" ] + "blitter.com/go/xs.GetTool" [ fillcolor="moccasin" label="GetTool" penwidth="1.5" tooltip="blitter.com/go/xs.GetTool | defined in auth.go:217" ] subgraph "cluster_*blitter.com/go/xs.Session" { - style="rounded,filled"; + fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; fillcolor="wheat2"; label="(*Session)"; tooltip="type: *blitter.com/go/xs.Session"; penwidth="0.5"; fontsize="15"; -fontcolor="#222222"; -labelloc="b"; "(*blitter.com/go/xs.Session).SetOp" [ fillcolor="moccasin" label="SetOp" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetOp | defined in session.go:41" ] "(*blitter.com/go/xs.Session).SetWho" [ fillcolor="moccasin" label="SetWho" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetWho | defined in session.go:51" ] - "(*blitter.com/go/xs.Session).SetConnHost" [ penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetConnHost | defined in session.go:61" fillcolor="moccasin" label="SetConnHost" ] - "(*blitter.com/go/xs.Session).SetTermType" [ tooltip="(*blitter.com/go/xs.Session).SetTermType | defined in session.go:73" fillcolor="moccasin" label="SetTermType" penwidth="1.5" ] - "(*blitter.com/go/xs.Session).SetCmd" [ fillcolor="moccasin" label="SetCmd" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetCmd | defined in session.go:85" ] - "(*blitter.com/go/xs.Session).SetAuthCookie" [ label="SetAuthCookie" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetAuthCookie | defined in session.go:101" fillcolor="moccasin" ] + "(*blitter.com/go/xs.Session).SetConnHost" [ fillcolor="moccasin" label="SetConnHost" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetConnHost | defined in session.go:61" ] + "(*blitter.com/go/xs.Session).SetTermType" [ label="SetTermType" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetTermType | defined in session.go:73" fillcolor="moccasin" ] + "(*blitter.com/go/xs.Session).SetCmd" [ tooltip="(*blitter.com/go/xs.Session).SetCmd | defined in session.go:85" fillcolor="moccasin" label="SetCmd" penwidth="1.5" ] + "(*blitter.com/go/xs.Session).SetAuthCookie" [ fillcolor="moccasin" label="SetAuthCookie" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).SetAuthCookie | defined in session.go:101" ] "(*blitter.com/go/xs.Session).ClearAuthCookie" [ fillcolor="moccasin" label="ClearAuthCookie" penwidth="1.5" tooltip="(*blitter.com/go/xs.Session).ClearAuthCookie | defined in session.go:109" ] } subgraph "cluster_blitter.com/go/xs.Session" { - fontcolor="#222222"; -labelloc="b"; -style="rounded,filled"; -fillcolor="wheat2"; -label="(Session)"; + label="(Session)"; tooltip="type: blitter.com/go/xs.Session"; penwidth="0.5"; fontsize="15"; +fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; "(blitter.com/go/xs.Session).Op" [ fillcolor="moccasin" label="Op" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Op | defined in session.go:36" ] "(blitter.com/go/xs.Session).Who" [ tooltip="(blitter.com/go/xs.Session).Who | defined in session.go:46" fillcolor="moccasin" label="Who" penwidth="1.5" ] - "(blitter.com/go/xs.Session).ConnHost" [ fillcolor="moccasin" label="ConnHost" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).ConnHost | defined in session.go:56" ] - "(blitter.com/go/xs.Session).Cmd" [ label="Cmd" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Cmd | defined in session.go:79" fillcolor="moccasin" ] + "(blitter.com/go/xs.Session).ConnHost" [ label="ConnHost" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).ConnHost | defined in session.go:56" fillcolor="moccasin" ] + "(blitter.com/go/xs.Session).Cmd" [ penwidth="1.5" tooltip="(blitter.com/go/xs.Session).Cmd | defined in session.go:79" fillcolor="moccasin" label="Cmd" ] "(blitter.com/go/xs.Session).AuthCookie" [ fillcolor="moccasin" label="AuthCookie" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).AuthCookie | defined in session.go:92" ] "(blitter.com/go/xs.Session).TermType" [ fillcolor="moccasin" label="TermType" penwidth="1.5" tooltip="(blitter.com/go/xs.Session).TermType | defined in session.go:67" ] @@ -114,156 +114,156 @@ fontsize="15"; } subgraph "cluster_blitter.com/go/xs/logger" { - fontsize="16"; -style="filled"; -label="logger"; -tooltip="package: blitter.com/go/xs/logger"; -penwidth="0.8"; -fillcolor="lightyellow"; -fontname="Tahoma bold"; + fillcolor="lightyellow"; rank="sink"; URL="/?f=blitter.com/go/xs/logger"; +penwidth="0.8"; +fontsize="16"; +label="logger"; +tooltip="package: blitter.com/go/xs/logger"; +style="filled"; +fontname="Tahoma bold"; - "blitter.com/go/xs/logger.LogNotice" [ fillcolor="moccasin" label="LogNotice" penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogNotice | defined in logger_linux.go:135" ] - "blitter.com/go/xs/logger.LogDebug" [ penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogDebug | defined in logger_linux.go:103" fillcolor="moccasin" label="LogDebug" ] + "blitter.com/go/xs/logger.LogNotice" [ label="LogNotice" penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogNotice | defined in logger_linux.go:135" fillcolor="moccasin" ] + "blitter.com/go/xs/logger.New" [ tooltip="blitter.com/go/xs/logger.New | defined in logger_linux.go:71" fillcolor="moccasin" label="New" penwidth="1.5" ] + "blitter.com/go/xs/logger.LogDebug" [ fillcolor="moccasin" label="LogDebug" penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogDebug | defined in logger_linux.go:103" ] "blitter.com/go/xs/logger.LogErr" [ fillcolor="moccasin" label="LogErr" penwidth="1.5" tooltip="blitter.com/go/xs/logger.LogErr | defined in logger_linux.go:119" ] - "blitter.com/go/xs/logger.New" [ fillcolor="moccasin" label="New" penwidth="1.5" tooltip="blitter.com/go/xs/logger.New | defined in logger_linux.go:71" ] } subgraph "cluster_blitter.com/go/xs/xsd.allowedCipherAlgs" { - style="rounded,filled"; + fontsize="15"; +fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; fillcolor="lightsteelblue"; label="(allowedCipherAlgs)"; tooltip="type: blitter.com/go/xs/xsd.allowedCipherAlgs"; penwidth="0.5"; -fontsize="15"; -fontcolor="#222222"; -labelloc="b"; "(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed" [ fillcolor="lightblue" label="allowed" penwidth="0.5" tooltip="(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed | defined in xsd.go:464\nat xsd.go:466: calling [(*blitter.com/go/xs/xsnet.CSCipherAlg).String]" ] } subgraph "cluster_blitter.com/go/xs/xsd.allowedHMACAlgs" { - fillcolor="lightsteelblue"; -label="(allowedHMACAlgs)"; + label="(allowedHMACAlgs)"; tooltip="type: blitter.com/go/xs/xsd.allowedHMACAlgs"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; +fillcolor="lightsteelblue"; - "(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed" [ tooltip="(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed | defined in xsd.go:482\nat xsd.go:484: calling [(*blitter.com/go/xs/xsnet.CSHmacAlg).String]" fillcolor="lightblue" label="allowed" penwidth="0.5" ] + "(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed" [ label="allowed" penwidth="0.5" tooltip="(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed | defined in xsd.go:482\nat xsd.go:484: calling [(*blitter.com/go/xs/xsnet.CSHmacAlg).String]" fillcolor="lightblue" ] } subgraph "cluster_blitter.com/go/xs/xsd.allowedKEXAlgs" { - fontsize="15"; -fontcolor="#222222"; -labelloc="b"; -style="rounded,filled"; + style="rounded,filled"; fillcolor="lightsteelblue"; label="(allowedKEXAlgs)"; tooltip="type: blitter.com/go/xs/xsd.allowedKEXAlgs"; penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; +labelloc="b"; - "(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed" [ fillcolor="lightblue" label="allowed" penwidth="0.5" tooltip="(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed | defined in xsd.go:446\nat xsd.go:448: calling [(*blitter.com/go/xs/xsnet.KEXAlg).String]" ] + "(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed" [ tooltip="(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed | defined in xsd.go:446\nat xsd.go:448: calling [(*blitter.com/go/xs/xsnet.KEXAlg).String]" fillcolor="lightblue" label="allowed" penwidth="0.5" ] } subgraph "cluster_blitter.com/go/xs/xsnet" { - label="xsnet"; -penwidth="0.8"; -fontsize="16"; -style="filled"; + URL="/?f=blitter.com/go/xs/xsnet"; fillcolor="lightyellow"; fontname="Tahoma bold"; rank="sink"; -URL="/?f=blitter.com/go/xs/xsnet"; +label="xsnet"; tooltip="package: blitter.com/go/xs/xsnet"; +penwidth="0.8"; +fontsize="16"; +style="filled"; - "blitter.com/go/xs/xsnet.Init" [ fillcolor="moccasin" label="Init" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Init | defined in net.go:192" ] - "blitter.com/go/xs/xsnet.Listen" [ fillcolor="moccasin" label="Listen" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Listen | defined in net.go:1040" ] + "blitter.com/go/xs/xsnet.Init" [ fillcolor="moccasin" label="Init" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Init | defined in net.go:198" ] + "blitter.com/go/xs/xsnet.Listen" [ fillcolor="moccasin" label="Listen" penwidth="1.5" tooltip="blitter.com/go/xs/xsnet.Listen | defined in net.go:1049" ] subgraph "cluster_*blitter.com/go/xs/xsnet.CSCipherAlg" { - fillcolor="wheat2"; -label="(*CSCipherAlg)"; -tooltip="type: *blitter.com/go/xs/xsnet.CSCipherAlg"; -penwidth="0.5"; -fontsize="15"; -fontcolor="#222222"; -labelloc="b"; -style="rounded,filled"; - - "(*blitter.com/go/xs/xsnet.CSCipherAlg).String" [ fillcolor="moccasin" label="String" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.CSCipherAlg).String | defined in net.go:148" ] - - } - - subgraph "cluster_*blitter.com/go/xs/xsnet.CSHmacAlg" { fontcolor="#222222"; labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; -label="(*CSHmacAlg)"; -tooltip="type: *blitter.com/go/xs/xsnet.CSHmacAlg"; +label="(*CSCipherAlg)"; +tooltip="type: *blitter.com/go/xs/xsnet.CSCipherAlg"; penwidth="0.5"; fontsize="15"; - "(*blitter.com/go/xs/xsnet.CSHmacAlg).String" [ penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.CSHmacAlg).String | defined in net.go:169" fillcolor="moccasin" label="String" ] + "(*blitter.com/go/xs/xsnet.CSCipherAlg).String" [ fillcolor="moccasin" label="String" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.CSCipherAlg).String | defined in net.go:152" ] } - subgraph "cluster_*blitter.com/go/xs/xsnet.Conn" { - fillcolor="wheat2"; -label="(*Conn)"; -tooltip="type: *blitter.com/go/xs/xsnet.Conn"; + subgraph "cluster_*blitter.com/go/xs/xsnet.CSHmacAlg" { + label="(*CSHmacAlg)"; +tooltip="type: *blitter.com/go/xs/xsnet.CSHmacAlg"; penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; +fillcolor="wheat2"; - "(*blitter.com/go/xs/xsnet.Conn).Close" [ fillcolor="moccasin" label="Close" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).Close | defined in net.go:970" ] - "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ tooltip="(*blitter.com/go/xs/xsnet.Conn).EnableChaff | defined in net.go:1539" fillcolor="moccasin" label="EnableChaff" penwidth="1.5" ] - "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ fillcolor="moccasin" label="DisableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).DisableChaff | defined in net.go:1546" ] - "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff | defined in net.go:1551" fillcolor="moccasin" label="ShutdownChaff" ] - "(*blitter.com/go/xs/xsnet.Conn).RemoteAddr" [ fillcolor="moccasin" label="RemoteAddr" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).RemoteAddr | defined in net.go:988" ] - "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ fillcolor="moccasin" label="SetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetStatus | defined in net.go:212" ] - "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ fillcolor="moccasin" label="WritePacket" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).WritePacket | defined in net.go:1430" ] - "(*blitter.com/go/xs/xsnet.Conn).KEX" [ fillcolor="moccasin" label="KEX" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).KEX | defined in net.go:204" ] - "(*blitter.com/go/xs/xsnet.Conn).CAlg" [ tooltip="(*blitter.com/go/xs/xsnet.Conn).CAlg | defined in net.go:144" fillcolor="moccasin" label="CAlg" penwidth="1.5" ] - "(*blitter.com/go/xs/xsnet.Conn).HAlg" [ fillcolor="moccasin" label="HAlg" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).HAlg | defined in net.go:165" ] - "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ label="SetupChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetupChaff | defined in net.go:1556" fillcolor="moccasin" ] + "(*blitter.com/go/xs/xsnet.CSHmacAlg).String" [ fillcolor="moccasin" label="String" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.CSHmacAlg).String | defined in net.go:175" ] + + } + + subgraph "cluster_*blitter.com/go/xs/xsnet.Conn" { + fontsize="15"; +fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; +label="(*Conn)"; +tooltip="type: *blitter.com/go/xs/xsnet.Conn"; +penwidth="0.5"; + + "(*blitter.com/go/xs/xsnet.Conn).Close" [ label="Close" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).Close | defined in net.go:979" fillcolor="moccasin" ] + "(*blitter.com/go/xs/xsnet.Conn).KEX" [ penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).KEX | defined in net.go:210" fillcolor="moccasin" label="KEX" ] + "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ fillcolor="moccasin" label="SetStatus" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).SetStatus | defined in net.go:218" ] + "(*blitter.com/go/xs/xsnet.Conn).CAlg" [ fillcolor="moccasin" label="CAlg" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).CAlg | defined in net.go:148" ] + "(*blitter.com/go/xs/xsnet.Conn).HAlg" [ fillcolor="moccasin" label="HAlg" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).HAlg | defined in net.go:171" ] + "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ tooltip="(*blitter.com/go/xs/xsnet.Conn).SetupChaff | defined in net.go:1563" fillcolor="moccasin" label="SetupChaff" penwidth="1.5" ] + "(*blitter.com/go/xs/xsnet.Conn).RemoteAddr" [ fillcolor="moccasin" label="RemoteAddr" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).RemoteAddr | defined in net.go:997" ] + "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ fillcolor="moccasin" label="EnableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).EnableChaff | defined in net.go:1546" ] + "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ fillcolor="moccasin" label="DisableChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).DisableChaff | defined in net.go:1553" ] + "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ fillcolor="moccasin" label="ShutdownChaff" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff | defined in net.go:1558" ] + "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ fillcolor="moccasin" label="WritePacket" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.Conn).WritePacket | defined in net.go:1437" ] } subgraph "cluster_*blitter.com/go/xs/xsnet.HKExListener" { - penwidth="0.5"; -fontsize="15"; + fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; label="(*HKExListener)"; tooltip="type: *blitter.com/go/xs/xsnet.HKExListener"; +penwidth="0.5"; - "(*blitter.com/go/xs/xsnet.HKExListener).Accept" [ tooltip="(*blitter.com/go/xs/xsnet.HKExListener).Accept | defined in net.go:1081" fillcolor="moccasin" label="Accept" penwidth="1.5" ] + "(*blitter.com/go/xs/xsnet.HKExListener).Accept" [ fillcolor="moccasin" label="Accept" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.HKExListener).Accept | defined in net.go:1090" ] } subgraph "cluster_*blitter.com/go/xs/xsnet.KEXAlg" { - fillcolor="wheat2"; -label="(*KEXAlg)"; -tooltip="type: *blitter.com/go/xs/xsnet.KEXAlg"; -penwidth="0.5"; -fontsize="15"; + fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; +fillcolor="wheat2"; +label="(*KEXAlg)"; +tooltip="type: *blitter.com/go/xs/xsnet.KEXAlg"; +penwidth="0.5"; - "(*blitter.com/go/xs/xsnet.KEXAlg).String" [ label="String" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.KEXAlg).String | defined in net.go:111" fillcolor="moccasin" ] + "(*blitter.com/go/xs/xsnet.KEXAlg).String" [ fillcolor="moccasin" label="String" penwidth="1.5" tooltip="(*blitter.com/go/xs/xsnet.KEXAlg).String | defined in net.go:115" ] } @@ -277,228 +277,274 @@ tooltip="type: blitter.com/go/xs/xsnet.Conn"; penwidth="0.5"; fontsize="15"; - "(blitter.com/go/xs/xsnet.Conn).Write" [ tooltip="(blitter.com/go/xs/xsnet.Conn).Write | defined in net.go:1424" fillcolor="moccasin" label="Write" penwidth="1.5" ] + "(blitter.com/go/xs/xsnet.Conn).Write" [ penwidth="1.5" tooltip="(blitter.com/go/xs/xsnet.Conn).Write | defined in net.go:1431" fillcolor="moccasin" label="Write" ] } subgraph "cluster_blitter.com/go/xs/xsnet.HKExListener" { - fontsize="15"; -fontcolor="#222222"; -labelloc="b"; + labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; label="(HKExListener)"; tooltip="type: blitter.com/go/xs/xsnet.HKExListener"; penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; - "(blitter.com/go/xs/xsnet.HKExListener).Close" [ fillcolor="moccasin" label="Close" penwidth="1.5" tooltip="(blitter.com/go/xs/xsnet.HKExListener).Close | defined in net.go:1066" ] + "(blitter.com/go/xs/xsnet.HKExListener).Close" [ fillcolor="moccasin" label="Close" penwidth="1.5" tooltip="(blitter.com/go/xs/xsnet.HKExListener).Close | defined in net.go:1075" ] } } subgraph "cluster_compress/flate" { - URL="/?f=compress/flate"; + fontsize="16"; style="filled"; -fillcolor="#E0FFE1"; -label="compress/flate"; -rank="sink"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +label="flate"; +URL="/?f=compress/flate"; tooltip="package: compress/flate"; penwidth="0.8"; -fontsize="16"; -fontname="Tahoma bold"; +rank="sink"; subgraph "cluster_compress/flate.CorruptInputError" { - labelloc="b"; + fontcolor="#222222"; +labelloc="b"; style="rounded,filled"; -fillcolor="#c2e3c2"; +fillcolor="wheat2"; label="(CorruptInputError)"; tooltip="type: compress/flate.CorruptInputError"; penwidth="0.5"; fontsize="15"; -fontcolor="#222222"; - "(compress/flate.CorruptInputError).Error" [ penwidth="1.5" tooltip="(compress/flate.CorruptInputError).Error | defined in inflate.go:35" fillcolor="#adedad" label="Error" ] + "(compress/flate.CorruptInputError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(compress/flate.CorruptInputError).Error | defined in inflate.go:35" ] } subgraph "cluster_compress/flate.InternalError" { - label="(InternalError)"; -tooltip="type: compress/flate.InternalError"; -penwidth="0.5"; -fontsize="15"; -fontcolor="#222222"; -labelloc="b"; -style="rounded,filled"; -fillcolor="#c2e3c2"; - - "(compress/flate.InternalError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(compress/flate.InternalError).Error | defined in inflate.go:42" ] - - } - - } - - subgraph "cluster_context" { - penwidth="0.8"; -fillcolor="#E0FFE1"; -fontname="Tahoma bold"; -rank="sink"; -tooltip="package: context"; -fontsize="16"; -style="filled"; -label="context"; -URL="/?f=context"; - - - subgraph "cluster_context.deadlineExceededError" { - label="(deadlineExceededError)"; -tooltip="type: context.deadlineExceededError"; -penwidth="0.5"; -fontsize="15"; -fontcolor="#222222"; -labelloc="b"; -style="rounded,filled"; -fillcolor="#c2e3c2"; - - "(context.deadlineExceededError).Error" [ fillcolor="#adedad" label="Error" penwidth="1.5" tooltip="(context.deadlineExceededError).Error | defined in context.go:165" ] - - } - - } - - subgraph "cluster_github.com/creack/pty" { - URL="/?f=github.com/creack/pty"; -tooltip="package: github.com/creack/pty"; -fontsize="16"; -fillcolor="lightyellow"; -fontname="Tahoma bold"; -rank="sink"; -label="pty"; -penwidth="0.8"; -style="filled"; - - "github.com/creack/pty.Start" [ label="Start" penwidth="1.5" tooltip="github.com/creack/pty.Start | defined in run.go:16" fillcolor="moccasin" ] - "github.com/creack/pty.Setsize" [ fillcolor="moccasin" label="Setsize" penwidth="1.5" tooltip="github.com/creack/pty.Setsize | defined in util.go:27" ] - - } - - subgraph "cluster_github.com/pkg/errors" { - rank="sink"; -label="errors"; -tooltip="package: github.com/pkg/errors"; -penwidth="0.8"; -style="filled"; -fillcolor="lightyellow"; -fontname="Tahoma bold"; -fontsize="16"; -URL="/?f=github.com/pkg/errors"; - - - subgraph "cluster_*github.com/pkg/errors.fundamental" { penwidth="0.5"; fontsize="15"; fontcolor="#222222"; labelloc="b"; style="rounded,filled"; fillcolor="wheat2"; +label="(InternalError)"; +tooltip="type: compress/flate.InternalError"; + + "(compress/flate.InternalError).Error" [ penwidth="1.5" tooltip="(compress/flate.InternalError).Error | defined in inflate.go:42" fillcolor="moccasin" label="Error" ] + + } + + } + + subgraph "cluster_context" { + tooltip="package: context"; +fontsize="16"; +style="filled"; +fillcolor="lightyellow"; +label="context"; +URL="/?f=context"; +penwidth="0.8"; +fontname="Tahoma bold"; +rank="sink"; + + + subgraph "cluster_context.deadlineExceededError" { + penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; +label="(deadlineExceededError)"; +tooltip="type: context.deadlineExceededError"; + + "(context.deadlineExceededError).Error" [ penwidth="1.5" tooltip="(context.deadlineExceededError).Error | defined in context.go:165" fillcolor="moccasin" label="Error" ] + + } + + } + + subgraph "cluster_github.com/creack/pty" { + penwidth="0.8"; +style="filled"; +URL="/?f=github.com/creack/pty"; +tooltip="package: github.com/creack/pty"; +fontsize="16"; +fillcolor="lightyellow"; +fontname="Tahoma bold"; +rank="sink"; +label="pty"; + + "github.com/creack/pty.Setsize" [ fillcolor="moccasin" label="Setsize" penwidth="1.5" tooltip="github.com/creack/pty.Setsize | defined in winsize_unix.go:21" ] + "github.com/creack/pty.Start" [ fillcolor="moccasin" label="Start" penwidth="1.5" tooltip="github.com/creack/pty.Start | defined in run.go:14" ] + + } + + subgraph "cluster_github.com/pkg/errors" { + penwidth="0.8"; +fontname="Tahoma bold"; +rank="sink"; +label="errors"; +tooltip="package: github.com/pkg/errors"; +fontsize="16"; +style="filled"; +fillcolor="lightyellow"; +URL="/?f=github.com/pkg/errors"; + + + subgraph "cluster_*github.com/pkg/errors.fundamental" { + fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; label="(*fundamental)"; tooltip="type: *github.com/pkg/errors.fundamental"; +penwidth="0.5"; +fontsize="15"; "(*github.com/pkg/errors.fundamental).Error" [ label="Error" penwidth="1.5" tooltip="(*github.com/pkg/errors.fundamental).Error | defined in errors.go:125" fillcolor="moccasin" ] } + } + + subgraph "cluster_vendor/golang.org/x/net/idna" { + rank="sink"; +fillcolor="lightyellow"; +fontsize="16"; +style="filled"; +fontname="Tahoma bold"; +label="idna"; +URL="/?f=vendor/golang.org/x/net/idna"; +tooltip="package: vendor/golang.org/x/net/idna"; +penwidth="0.8"; + + + subgraph "cluster_vendor/golang.org/x/net/idna.labelError" { + label="(labelError)"; +tooltip="type: vendor/golang.org/x/net/idna.labelError"; +penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; +labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; + + "(vendor/golang.org/x/net/idna.labelError).Error" [ label="Error" penwidth="1.5" tooltip="(vendor/golang.org/x/net/idna.labelError).Error | defined in idna10.0.0.go:324" fillcolor="moccasin" ] + + } + + subgraph "cluster_vendor/golang.org/x/net/idna.runeError" { + labelloc="b"; +style="rounded,filled"; +fillcolor="wheat2"; +label="(runeError)"; +tooltip="type: vendor/golang.org/x/net/idna.runeError"; +penwidth="0.5"; +fontsize="15"; +fontcolor="#222222"; + + "(vendor/golang.org/x/net/idna.runeError).Error" [ fillcolor="moccasin" label="Error" penwidth="1.5" tooltip="(vendor/golang.org/x/net/idna.runeError).Error | defined in idna10.0.0.go:331" ] + + } + } } - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.runServerToClientCopyAs" [ tooltip="at xsd.go:828: calling [blitter.com/go/xs/xsd.runServerToClientCopyAs]" ] - "blitter.com/go/xs/xsd.main$2$1" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ color="saddlebrown" tooltip="at xsd.go:653: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] - "blitter.com/go/xs/xsd.runShellAs$2" -> "blitter.com/go/goutmp.Unput_utmp" [ color="saddlebrown" tooltip="at xsd.go:336: calling [blitter.com/go/goutmp.Unput_utmp]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetTermType" [ color="saddlebrown" tooltip="at xsd.go:701: calling [(*blitter.com/go/xs.Session).SetTermType]" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).Who" [ color="saddlebrown" tooltip="at xsd.go:720: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:724: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:729: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:731: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:743: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:754: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:755: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:757: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:762: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:764: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:771: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:772: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:777: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:779: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:786: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:788: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:793: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:795: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:803: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:809: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:811: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:827: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:830: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:833: calling [(blitter.com/go/xs.Session).Who]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.VerifyPass" [ color="saddlebrown" tooltip="at xsd.go:729: calling [blitter.com/go/xs.VerifyPass]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$6" [ arrowhead="normalnoneodot" tooltip="at xsd.go:381: calling [blitter.com/go/xs/xsd.runShellAs$6]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).ClearAuthCookie" [ color="saddlebrown" tooltip="at xsd.go:737: calling [(*blitter.com/go/xs.Session).ClearAuthCookie]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).CAlg" [ color="saddlebrown" tooltip="at xsd.go:627: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]\nat xsd.go:628: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]" ] - "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:122: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$2" [ arrowhead="normalnoneodiamond" tooltip="at xsd.go:336: calling [blitter.com/go/xs/xsd.runShellAs$2]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ color="saddlebrown" tooltip="at xsd.go:641: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]" ] - "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsnet.Listen" [ color="saddlebrown" tooltip="at xsd.go:610: calling [blitter.com/go/xs/xsnet.Listen]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).KEX" [ tooltip="at xsd.go:623: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]\nat xsd.go:624: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.runShellAs$6" -> "(context.deadlineExceededError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(context.deadlineExceededError).Error]" ] - "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xsd.go:220: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:743: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:754: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:771: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:779: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:786: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:795: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:803: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:811: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:827: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:833: calling [blitter.com/go/xs/logger.LogNotice]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "github.com/creack/pty.Start" [ color="saddlebrown" tooltip="at xsd.go:318: calling [github.com/creack/pty.Start]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/goutmp.Put_lastlog_entry" [ color="saddlebrown" tooltip="at xsd.go:337: calling [blitter.com/go/goutmp.Put_lastlog_entry]" ] - "blitter.com/go/xs/xsd.runShellAs$5" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ tooltip="at xsd.go:369: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsnet.HKExListener).Close" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:614: calling [(blitter.com/go/xs/xsnet.HKExListener).Close]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.HKExListener).Accept" [ color="saddlebrown" tooltip="at xsd.go:620: calling [(*blitter.com/go/xs/xsnet.HKExListener).Accept]" ] - "blitter.com/go/xs/xsd.main$1" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:591: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:595: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:599: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:601: calling [blitter.com/go/xs/logger.LogNotice]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetAuthCookie" [ color="saddlebrown" tooltip="at xsd.go:717: calling [(*blitter.com/go/xs.Session).SetAuthCookie]" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).TermType" [ color="saddlebrown" tooltip="at xsd.go:757: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:772: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:788: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).TermType]" ] - "blitter.com/go/xs/xsd.runShellAs$3" -> "github.com/creack/pty.Setsize" [ color="saddlebrown" tooltip="at xsd.go:348: calling [github.com/creack/pty.Setsize]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/logger.LogDebug" [ color="saddlebrown" tooltip="at xsd.go:409: calling [blitter.com/go/xs/logger.LogDebug]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xsd.go:765: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:780: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:796: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:815: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:841: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] - "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed" [ tooltip="at xsd.go:627: calling [(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed]" ] - "blitter.com/go/xs/xsd.runShellAs$6" -> "(compress/flate.CorruptInputError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(compress/flate.CorruptInputError).Error]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetConnHost" [ color="saddlebrown" tooltip="at xsd.go:693: calling [(*blitter.com/go/xs.Session).SetConnHost]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xsd.go:308: calling [blitter.com/go/xs.GetTool]\nat xsd.go:297: calling [blitter.com/go/xs.GetTool]\nat xsd.go:303: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.runClientToServerCopyAs" [ tooltip="at xsd.go:804: calling [blitter.com/go/xs/xsd.runClientToServerCopyAs]" ] - "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed" [ tooltip="at xsd.go:623: calling [(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed]" ] - "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed" [ tooltip="at xsd.go:631: calling [(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed]" ] "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xsd.go:119: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).RemoteAddr" [ tooltip="at xsd.go:752: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:769: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:784: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:801: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:825: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/logger.LogErr" [ color="saddlebrown" tooltip="at xsd.go:762: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:777: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:809: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:846: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:830: calling [blitter.com/go/xs/logger.LogErr]" ] - "(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed" -> "(*blitter.com/go/xs/xsnet.CSCipherAlg).String" [ color="saddlebrown" tooltip="at xsd.go:466: calling [(*blitter.com/go/xs/xsnet.CSCipherAlg).String]" ] - "(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed" -> "(*blitter.com/go/xs/xsnet.CSHmacAlg).String" [ color="saddlebrown" tooltip="at xsd.go:484: calling [(*blitter.com/go/xs/xsnet.CSHmacAlg).String]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ color="saddlebrown" tooltip="at xsd.go:626: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:630: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:634: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] - "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xsd.go:88: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetCmd" [ color="saddlebrown" tooltip="at xsd.go:709: calling [(*blitter.com/go/xs.Session).SetCmd]" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).ConnHost" [ color="saddlebrown" tooltip="at xsd.go:720: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:724: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:755: calling [(blitter.com/go/xs.Session).ConnHost]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.ptsName" [ tooltip="at xsd.go:331: calling [blitter.com/go/xs/xsd.ptsName]" ] - "blitter.com/go/xs/xsd.runShellAs$5" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ color="saddlebrown" tooltip="at xsd.go:370: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at xsd.go:821: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/goutmp.Put_utmp" [ tooltip="at xsd.go:335: calling [blitter.com/go/goutmp.Put_utmp]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$5" [ arrowhead="normalnoneodiamond" tooltip="at xsd.go:368: calling [blitter.com/go/xs/xsd.runShellAs$5]" ] - "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ tooltip="at xsd.go:223: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" arrowhead="normalnoneodiamond" color="saddlebrown" ] - "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ color="saddlebrown" tooltip="at xsd.go:224: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" arrowhead="normalnoneodiamond" ] - "blitter.com/go/xs/xsd.runShellAs$4" -> "(*github.com/pkg/errors.fundamental).Error" [ tooltip="at xsd.go:358: calling [(*github.com/pkg/errors.fundamental).Error]" style="dashed" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetWho" [ tooltip="at xsd.go:685: calling [(*blitter.com/go/xs.Session).SetWho]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/goutmp.GetHost" [ color="saddlebrown" tooltip="at xsd.go:753: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:770: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:785: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:802: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:826: calling [blitter.com/go/goutmp.GetHost]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.GenAuthToken" [ tooltip="at xsd.go:755: calling [blitter.com/go/xs/xsd.GenAuthToken]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.runShellAs" [ tooltip="at xsd.go:757: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:772: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:788: calling [blitter.com/go/xs/xsd.runShellAs]" ] - "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:571: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:576: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:581: calling [blitter.com/go/xs/logger.LogNotice]" ] - "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsd.main$1" [ arrowhead="normalnoneodot" tooltip="at xsd.go:586: calling [blitter.com/go/xs/xsd.main$1]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xsd.go:625: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:629: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:633: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ color="saddlebrown" tooltip="at xsd.go:647: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" arrowhead="normalnoneodiamond" ] - "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetOp" [ color="saddlebrown" tooltip="at xsd.go:677: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:760: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:775: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:791: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:807: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:840: calling [(*blitter.com/go/xs.Session).SetOp]" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).AuthCookie" [ tooltip="at xsd.go:724: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:729: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:731: calling [(blitter.com/go/xs.Session).AuthCookie]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/logger.New" [ tooltip="at xsd.go:559: calling [blitter.com/go/xs/logger.New]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:121: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xsd.go:365: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xsd.go:407: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] - "blitter.com/go/xs/xsd.main$2$1" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ color="saddlebrown" tooltip="at xsd.go:652: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] - "blitter.com/go/xs/xsd.runShellAs$6" -> "(compress/flate.InternalError).Error" [ tooltip="at xsd.go:385: calling [(compress/flate.InternalError).Error]" style="dashed" color="saddlebrown" ] - "blitter.com/go/xs/xsd.runShellAs$4" -> "(context.deadlineExceededError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(context.deadlineExceededError).Error]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.NewAuthCtx" [ tooltip="at xsd.go:724: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:729: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:731: calling [blitter.com/go/xs.NewAuthCtx]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.AuthUserByPasswd" [ color="saddlebrown" tooltip="at xsd.go:731: calling [blitter.com/go/xs.AuthUserByPasswd]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$3" [ arrowhead="normalnoneodot" tooltip="at xsd.go:345: calling [blitter.com/go/xs/xsd.runShellAs$3]" ] - "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).HAlg" [ color="saddlebrown" tooltip="at xsd.go:631: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]\nat xsd.go:632: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]" ] - "blitter.com/go/xs/xsd.runShellAs$6" -> "(*github.com/pkg/errors.fundamental).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(*github.com/pkg/errors.fundamental).Error]" ] - "(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed" -> "(*blitter.com/go/xs/xsnet.KEXAlg).String" [ tooltip="at xsd.go:448: calling [(*blitter.com/go/xs/xsnet.KEXAlg).String]" color="saddlebrown" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ color="saddlebrown" tooltip="at xsd.go:741: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:744: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] - "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$1" [ arrowhead="normalnoneodiamond" tooltip="at xsd.go:325: calling [blitter.com/go/xs/xsd.runShellAs$1]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.runServerToClientCopyAs" [ tooltip="at xsd.go:853: calling [blitter.com/go/xs/xsd.runServerToClientCopyAs]" ] + "blitter.com/go/xs/xsd.main$2$1" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ color="saddlebrown" tooltip="at xsd.go:677: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] + "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/logger.New" [ color="saddlebrown" tooltip="at xsd.go:583: calling [blitter.com/go/xs/logger.New]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xsd.go:650: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:654: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:658: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:672: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetWho" [ color="saddlebrown" tooltip="at xsd.go:710: calling [(*blitter.com/go/xs.Session).SetWho]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xsd.go:790: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:805: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:821: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:840: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]\nat xsd.go:866: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] + "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ tooltip="at xsd.go:121: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" arrowhead="normalnoneodiamond" color="saddlebrown" ] + "(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed" -> "(*blitter.com/go/xs/xsnet.KEXAlg).String" [ color="saddlebrown" tooltip="at xsd.go:448: calling [(*blitter.com/go/xs/xsnet.KEXAlg).String]" ] + "blitter.com/go/xs/xsd.runShellAs$3" -> "github.com/creack/pty.Setsize" [ color="saddlebrown" tooltip="at xsd.go:348: calling [github.com/creack/pty.Setsize]" ] + "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed" [ tooltip="at xsd.go:648: calling [(blitter.com/go/xs/xsd.allowedKEXAlgs).allowed]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetTermType" [ tooltip="at xsd.go:726: calling [(*blitter.com/go/xs.Session).SetTermType]" color="saddlebrown" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs/xsnet.Conn).Write" [ color="saddlebrown" tooltip="at xsd.go:766: calling [(blitter.com/go/xs/xsnet.Conn).Write]\nat xsd.go:769: calling [(blitter.com/go/xs/xsnet.Conn).Write]" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).TermType" [ color="saddlebrown" tooltip="at xsd.go:782: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:797: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:813: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:829: calling [(blitter.com/go/xs.Session).TermType]\nat xsd.go:853: calling [(blitter.com/go/xs.Session).TermType]" ] + "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xsd.go:220: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] + "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsd.main$2" [ arrowhead="normalnoneodot" tooltip="at xsd.go:671: calling [blitter.com/go/xs/xsd.main$2]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.HKExListener).Accept" [ color="saddlebrown" tooltip="at xsd.go:644: calling [(*blitter.com/go/xs/xsnet.HKExListener).Accept]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).KEX" [ color="saddlebrown" tooltip="at xsd.go:648: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]\nat xsd.go:649: calling [(*blitter.com/go/xs/xsnet.Conn).KEX]" ] "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$4" [ arrowhead="normalnoneodot" tooltip="at xsd.go:355: calling [blitter.com/go/xs/xsd.runShellAs$4]" ] - "blitter.com/go/xs/xsd.main$2$1" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:651: calling [blitter.com/go/xs/logger.LogNotice]" ] + "blitter.com/go/xs/xsd.main$2$1" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:676: calling [blitter.com/go/xs/logger.LogNotice]" ] + "blitter.com/go/xs/xsd.main$2$1" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ color="saddlebrown" tooltip="at xsd.go:678: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).HAlg" [ color="saddlebrown" tooltip="at xsd.go:656: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]\nat xsd.go:657: calling [(*blitter.com/go/xs/xsnet.Conn).HAlg]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetCmd" [ color="saddlebrown" tooltip="at xsd.go:734: calling [(*blitter.com/go/xs.Session).SetCmd]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$6" [ arrowhead="normalnoneodot" tooltip="at xsd.go:381: calling [blitter.com/go/xs/xsd.runShellAs$6]" ] + "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:224: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" ] + "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:595: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:600: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:605: calling [blitter.com/go/xs/logger.LogNotice]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).Close" [ color="saddlebrown" tooltip="at xsd.go:651: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:655: calling [(*blitter.com/go/xs/xsnet.Conn).Close]\nat xsd.go:659: calling [(*blitter.com/go/xs/xsnet.Conn).Close]" ] + "blitter.com/go/xs/xsd.runShellAs$6" -> "(vendor/golang.org/x/net/idna.labelError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(vendor/golang.org/x/net/idna.labelError).Error]" ] + "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed" [ tooltip="at xsd.go:652: calling [(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xsd.go:308: calling [blitter.com/go/xs.GetTool]\nat xsd.go:297: calling [blitter.com/go/xs.GetTool]\nat xsd.go:303: calling [blitter.com/go/xs.GetTool]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.VerifyPass" [ color="saddlebrown" tooltip="at xsd.go:754: calling [blitter.com/go/xs.VerifyPass]" ] + "blitter.com/go/xs/xsd.runShellAs$4" -> "(context.deadlineExceededError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(context.deadlineExceededError).Error]" ] + "blitter.com/go/xs/xsd.runShellAs$6" -> "(*github.com/pkg/errors.fundamental).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(*github.com/pkg/errors.fundamental).Error]" ] "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xsd.go:193: calling [blitter.com/go/xs.GetTool]" ] - "blitter.com/go/xs/xsd.runShellAs$4" -> "(compress/flate.CorruptInputError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(compress/flate.CorruptInputError).Error]" ] + "blitter.com/go/xs/xsd.runShellAs$2" -> "blitter.com/go/goutmp.Unput_utmp" [ color="saddlebrown" tooltip="at xsd.go:336: calling [blitter.com/go/goutmp.Unput_utmp]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).ClearAuthCookie" [ color="saddlebrown" tooltip="at xsd.go:762: calling [(*blitter.com/go/xs.Session).ClearAuthCookie]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.ptsName" [ tooltip="at xsd.go:331: calling [blitter.com/go/xs/xsd.ptsName]" ] + "blitter.com/go/xs/xsd.runShellAs$4" -> "(vendor/golang.org/x/net/idna.runeError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(vendor/golang.org/x/net/idna.runeError).Error]" ] + "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ tooltip="at xsd.go:122: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" arrowhead="normalnoneodiamond" color="saddlebrown" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetConnHost" [ color="saddlebrown" tooltip="at xsd.go:718: calling [(*blitter.com/go/xs.Session).SetConnHost]" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).Cmd" [ color="saddlebrown" tooltip="at xsd.go:745: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:797: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:813: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:829: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:853: calling [(blitter.com/go/xs.Session).Cmd]" ] "blitter.com/go/xs/xsd.runShellAs$4" -> "(compress/flate.InternalError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(compress/flate.InternalError).Error]" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).Op" [ color="saddlebrown" tooltip="at xsd.go:720: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:750: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:767: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:782: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:798: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:822: calling [(blitter.com/go/xs.Session).Op]" ] - "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).Cmd" [ color="saddlebrown" tooltip="at xsd.go:720: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:772: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:788: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).Cmd]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).Cmd]" ] - "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.AuthUserByToken" [ tooltip="at xsd.go:724: calling [blitter.com/go/xs.AuthUserByToken]" color="saddlebrown" ] + "blitter.com/go/xs/xsd.runShellAs" -> "(*blitter.com/go/xs/xsnet.Conn).EnableChaff" [ color="saddlebrown" tooltip="at xsd.go:365: calling [(*blitter.com/go/xs/xsnet.Conn).EnableChaff]" ] + "blitter.com/go/xs/xsd.runShellAs$5" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ tooltip="at xsd.go:369: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" color="saddlebrown" ] + "blitter.com/go/xs/xsd.runShellAs$6" -> "(compress/flate.CorruptInputError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(compress/flate.CorruptInputError).Error]" ] + "blitter.com/go/xs/xsd.runShellAs$6" -> "(vendor/golang.org/x/net/idna.runeError).Error" [ color="saddlebrown" tooltip="at xsd.go:385: calling [(vendor/golang.org/x/net/idna.runeError).Error]" style="dashed" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.runClientToServerCopyAs" [ tooltip="at xsd.go:829: calling [blitter.com/go/xs/xsd.runClientToServerCopyAs]" ] + "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsnet.HKExListener).Close" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:638: calling [(blitter.com/go/xs/xsnet.HKExListener).Close]" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).AuthCookie" [ color="saddlebrown" tooltip="at xsd.go:749: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:754: calling [(blitter.com/go/xs.Session).AuthCookie]\nat xsd.go:756: calling [(blitter.com/go/xs.Session).AuthCookie]" ] + "blitter.com/go/xs/xsd.runServerToClientCopyAs" -> "(*blitter.com/go/xs/xsnet.Conn).DisableChaff" [ arrowhead="normalnoneodiamond" color="saddlebrown" tooltip="at xsd.go:223: calling [(*blitter.com/go/xs/xsnet.Conn).DisableChaff]" ] + "blitter.com/go/xs/xsd.runShellAs$6" -> "(context.deadlineExceededError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(context.deadlineExceededError).Error]" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).Who" [ tooltip="at xsd.go:745: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:749: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:754: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:756: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:768: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:779: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:780: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:782: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:787: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:789: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:796: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:797: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:802: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:804: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:811: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:813: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:818: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:820: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:828: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:829: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:834: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:836: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:852: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:853: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:855: calling [(blitter.com/go/xs.Session).Who]\nat xsd.go:858: calling [(blitter.com/go/xs.Session).Who]" color="saddlebrown" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.NewAuthCtx" [ color="saddlebrown" tooltip="at xsd.go:749: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:754: calling [blitter.com/go/xs.NewAuthCtx]\nat xsd.go:756: calling [blitter.com/go/xs.NewAuthCtx]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).SetupChaff" [ color="saddlebrown" tooltip="at xsd.go:666: calling [(*blitter.com/go/xs/xsnet.Conn).SetupChaff]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/goutmp.GetHost" [ color="saddlebrown" tooltip="at xsd.go:778: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:795: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:810: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:827: calling [blitter.com/go/goutmp.GetHost]\nat xsd.go:851: calling [blitter.com/go/goutmp.GetHost]" ] + "blitter.com/go/xs/xsd.runShellAs$6" -> "(compress/flate.InternalError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:385: calling [(compress/flate.InternalError).Error]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "(*blitter.com/go/xs/xsnet.Conn).SetStatus" [ color="saddlebrown" tooltip="at xsd.go:407: calling [(*blitter.com/go/xs/xsnet.Conn).SetStatus]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.runShellAs" [ tooltip="at xsd.go:782: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:797: calling [blitter.com/go/xs/xsd.runShellAs]\nat xsd.go:813: calling [blitter.com/go/xs/xsd.runShellAs]" ] + "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsd.main$1" [ tooltip="at xsd.go:610: calling [blitter.com/go/xs/xsd.main$1]" arrowhead="normalnoneodot" ] + "blitter.com/go/xs/xsd.main" -> "(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed" [ tooltip="at xsd.go:656: calling [(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:768: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:779: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:796: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:804: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:811: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:820: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:828: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:836: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:852: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:858: calling [blitter.com/go/xs/logger.LogNotice]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "github.com/creack/pty.Start" [ color="saddlebrown" tooltip="at xsd.go:318: calling [github.com/creack/pty.Start]" ] "blitter.com/go/xs/xsd.ptsName" -> "blitter.com/go/xs/xsd.ioctl" [ tooltip="at xsd.go:59: calling [blitter.com/go/xs/xsd.ioctl]" ] - "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsnet.Init" [ color="saddlebrown" tooltip="at xsd.go:560: calling [blitter.com/go/xs/xsnet.Init]" ] - "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsd.main$2" [ arrowhead="normalnoneodot" tooltip="at xsd.go:646: calling [blitter.com/go/xs/xsd.main$2]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/goutmp.Put_utmp" [ color="saddlebrown" tooltip="at xsd.go:335: calling [blitter.com/go/goutmp.Put_utmp]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$5" [ arrowhead="normalnoneodiamond" tooltip="at xsd.go:368: calling [blitter.com/go/xs/xsd.runShellAs$5]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/logger.LogErr" [ color="saddlebrown" tooltip="at xsd.go:787: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:802: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:834: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:871: calling [blitter.com/go/xs/logger.LogErr]\nat xsd.go:855: calling [blitter.com/go/xs/logger.LogErr]" ] + "blitter.com/go/xs/xsd.main" -> "(*blitter.com/go/xs/xsnet.Conn).CAlg" [ color="saddlebrown" tooltip="at xsd.go:652: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]\nat xsd.go:653: calling [(*blitter.com/go/xs/xsnet.Conn).CAlg]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.AuthUserByPasswd" [ color="saddlebrown" tooltip="at xsd.go:756: calling [blitter.com/go/xs.AuthUserByPasswd]" ] + "blitter.com/go/xs/xsd.runClientToServerCopyAs" -> "blitter.com/go/xs.GetTool" [ color="saddlebrown" tooltip="at xsd.go:88: calling [blitter.com/go/xs.GetTool]" ] + "blitter.com/go/xs/xsd.runShellAs$4" -> "(compress/flate.CorruptInputError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(compress/flate.CorruptInputError).Error]" ] + "blitter.com/go/xs/xsd.runShellAs$4" -> "(vendor/golang.org/x/net/idna.labelError).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(vendor/golang.org/x/net/idna.labelError).Error]" ] + "blitter.com/go/xs/xsd.runShellAs$5" -> "(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff" [ color="saddlebrown" tooltip="at xsd.go:370: calling [(*blitter.com/go/xs/xsnet.Conn).ShutdownChaff]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/logger.LogDebug" [ tooltip="at xsd.go:409: calling [blitter.com/go/xs/logger.LogDebug]" color="saddlebrown" ] + "(blitter.com/go/xs/xsd.allowedCipherAlgs).allowed" -> "(*blitter.com/go/xs/xsnet.CSCipherAlg).String" [ color="saddlebrown" tooltip="at xsd.go:466: calling [(*blitter.com/go/xs/xsnet.CSCipherAlg).String]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$1" [ arrowhead="normalnoneodiamond" tooltip="at xsd.go:325: calling [blitter.com/go/xs/xsd.runShellAs$1]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetAuthCookie" [ color="saddlebrown" tooltip="at xsd.go:742: calling [(*blitter.com/go/xs.Session).SetAuthCookie]" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).ConnHost" [ color="saddlebrown" tooltip="at xsd.go:745: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:749: calling [(blitter.com/go/xs.Session).ConnHost]\nat xsd.go:780: calling [(blitter.com/go/xs.Session).ConnHost]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs/xsd.GenAuthToken" [ tooltip="at xsd.go:780: calling [blitter.com/go/xs/xsd.GenAuthToken]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$2" [ tooltip="at xsd.go:336: calling [blitter.com/go/xs/xsd.runShellAs$2]" arrowhead="normalnoneodiamond" ] + "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsnet.Init" [ color="saddlebrown" tooltip="at xsd.go:584: calling [blitter.com/go/xs/xsnet.Init]" ] + "blitter.com/go/xs/xsd.main" -> "blitter.com/go/xs/xsnet.Listen" [ color="saddlebrown" tooltip="at xsd.go:634: calling [blitter.com/go/xs/xsnet.Listen]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).RemoteAddr" [ color="saddlebrown" tooltip="at xsd.go:777: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:794: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:809: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:826: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]\nat xsd.go:850: calling [(*blitter.com/go/xs/xsnet.Conn).RemoteAddr]" ] + "blitter.com/go/xs/xsd.runShellAs$4" -> "(*github.com/pkg/errors.fundamental).Error" [ style="dashed" color="saddlebrown" tooltip="at xsd.go:358: calling [(*github.com/pkg/errors.fundamental).Error]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs/xsnet.Conn).WritePacket" [ color="saddlebrown" tooltip="at xsd.go:846: calling [(*blitter.com/go/xs/xsnet.Conn).WritePacket]" ] + "(blitter.com/go/xs/xsd.allowedHMACAlgs).allowed" -> "(*blitter.com/go/xs/xsnet.CSHmacAlg).String" [ color="saddlebrown" tooltip="at xsd.go:484: calling [(*blitter.com/go/xs/xsnet.CSHmacAlg).String]" ] + "blitter.com/go/xs/xsd.main$2" -> "blitter.com/go/xs.AuthUserByToken" [ color="saddlebrown" tooltip="at xsd.go:749: calling [blitter.com/go/xs.AuthUserByToken]" ] + "blitter.com/go/xs/xsd.main$2" -> "(blitter.com/go/xs.Session).Op" [ color="saddlebrown" tooltip="at xsd.go:745: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:775: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:792: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:807: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:823: calling [(blitter.com/go/xs.Session).Op]\nat xsd.go:847: calling [(blitter.com/go/xs.Session).Op]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/goutmp.Put_lastlog_entry" [ color="saddlebrown" tooltip="at xsd.go:337: calling [blitter.com/go/goutmp.Put_lastlog_entry]" ] + "blitter.com/go/xs/xsd.runShellAs" -> "blitter.com/go/xs/xsd.runShellAs$3" [ arrowhead="normalnoneodot" tooltip="at xsd.go:345: calling [blitter.com/go/xs/xsd.runShellAs$3]" ] + "blitter.com/go/xs/xsd.main$1" -> "blitter.com/go/xs/logger.LogNotice" [ color="saddlebrown" tooltip="at xsd.go:615: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:619: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:623: calling [blitter.com/go/xs/logger.LogNotice]\nat xsd.go:625: calling [blitter.com/go/xs/logger.LogNotice]" ] + "blitter.com/go/xs/xsd.main$2" -> "(*blitter.com/go/xs.Session).SetOp" [ color="saddlebrown" tooltip="at xsd.go:702: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:785: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:800: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:816: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:832: calling [(*blitter.com/go/xs.Session).SetOp]\nat xsd.go:865: calling [(*blitter.com/go/xs.Session).SetOp]" ] } diff --git a/xsd/xsd.go b/xsd/xsd.go index 98e83eb..62f9a39 100755 --- a/xsd/xsd.go +++ b/xsd/xsd.go @@ -16,13 +16,15 @@ import ( "flag" "fmt" "io" - "io/ioutil" "log" + "net/http" "os" "os/exec" "os/signal" "os/user" "path" + "runtime" + "runtime/pprof" "strings" "sync" "syscall" @@ -45,6 +47,14 @@ var ( // Log - syslog output (with no -d) Log *logger.Writer + + cpuprofile string + memprofile string +) + +const ( + AuthTokenLen = 64 + LoginTimeoutSecs = 30 ) func ioctl(fd, request, argp uintptr) error { @@ -66,23 +76,18 @@ func ptsName(fd uintptr) (string, error) { /* -------------------------------------------------------------- */ // Perform a client->server copy func runClientToServerCopyAs(who, ttype string, conn *xsnet.Conn, fpath string, chaffing bool) (exitStatus uint32, err error) { - u, _ := user.Lookup(who) // nolint: gosec + u, _ := user.Lookup(who) var uid, gid uint32 - fmt.Sscanf(u.Uid, "%d", &uid) // nolint: gosec,errcheck - fmt.Sscanf(u.Gid, "%d", &gid) // nolint: gosec,errcheck + fmt.Sscanf(u.Uid, "%d", &uid) + fmt.Sscanf(u.Gid, "%d", &gid) log.Println("uid:", uid, "gid:", gid) // Need to clear server's env and set key vars of the - // target user. This isn't perfect (TERM doesn't seem to - // work 100%; ANSI/xterm colour isn't working even - // if we set "xterm" or "ansi" here; and line count - // reported by 'stty -a' defaults to 24 regardless - // of client shell window used to run client. - // Investigate -- rlm 2018-01-26) + // target user. os.Clearenv() - os.Setenv("HOME", u.HomeDir) // nolint: gosec,errcheck - os.Setenv("TERM", ttype) // nolint: gosec,errcheck - os.Setenv("XS_SESSION", "1") // nolint: gosec,errcheck + os.Setenv("HOME", u.HomeDir) + os.Setenv("TERM", ttype) + os.Setenv("XS_SESSION", "1") var c *exec.Cmd cmdName := xs.GetTool("tar") @@ -101,13 +106,14 @@ func runClientToServerCopyAs(who, ttype string, conn *xsnet.Conn, fpath string, // (as this isn't input from a shell) (right? -rlm 20180823) //cmdArgs := []string{"-x", "-C", destDir, `--xform=s#.*/\(.*\)#\1#`} fmt.Println(cmdName, cmdArgs) - c = exec.Command(cmdName, cmdArgs...) // nolint: gosec + c = exec.Command(cmdName, cmdArgs...) c.Dir = destDir - //If os.Clearenv() isn't called by server above these will be seen in the - //client's session env. - //c.Env = []string{"HOME=" + u.HomeDir, "SUDO_GID=", "SUDO_UID=", "SUDO_USER=", "SUDO_COMMAND=", "MAIL=", "LOGNAME="+who} + //If os.Clearenv() isn't called by server above these will be seen + //in the client's session env. + //c.Env = []string{"HOME=" + u.HomeDir, "SUDO_GID=", "SUDO_UID=", + // "SUDO_USER=", "SUDO_COMMAND=", "MAIL=", "LOGNAME="+who} //c.Dir = u.HomeDir c.SysProcAttr = &syscall.SysProcAttr{} c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid} @@ -115,10 +121,13 @@ func runClientToServerCopyAs(who, ttype string, conn *xsnet.Conn, fpath string, c.Stdout = os.Stdout c.Stderr = os.Stderr + // === Set up connection keepalive to client + conn.StartupKeepAlive() // goroutine, returns immediately + defer conn.ShutdownKeepAlive() + if chaffing { - conn.EnableChaff() + conn.StartupChaff() } - defer conn.DisableChaff() defer conn.ShutdownChaff() // Start the command (no pty) @@ -173,21 +182,16 @@ func runServerToClientCopyAs(who, ttype string, conn *xsnet.Conn, srcPath string return } var uid, gid uint32 - _, _ = fmt.Sscanf(u.Uid, "%d", &uid) // nolint: gosec - _, _ = fmt.Sscanf(u.Gid, "%d", &gid) // nolint: gosec + _, _ = fmt.Sscanf(u.Uid, "%d", &uid) + _, _ = fmt.Sscanf(u.Gid, "%d", &gid) log.Println("uid:", uid, "gid:", gid) // Need to clear server's env and set key vars of the - // target user. This isn't perfect (TERM doesn't seem to - // work 100%; ANSI/xterm colour isn't working even - // if we set "xterm" or "ansi" here; and line count - // reported by 'stty -a' defaults to 24 regardless - // of client shell window used to run client. - // Investigate -- rlm 2018-01-26) + // target user. os.Clearenv() - _ = os.Setenv("HOME", u.HomeDir) // nolint: gosec - _ = os.Setenv("TERM", ttype) // nolint: gosec - _ = os.Setenv("XS_SESSION", "1") // nolint: gosec + _ = os.Setenv("HOME", u.HomeDir) + _ = os.Setenv("TERM", ttype) + _ = os.Setenv("XS_SESSION", "1") var c *exec.Cmd cmdName := xs.GetTool("tar") @@ -198,11 +202,12 @@ func runServerToClientCopyAs(who, ttype string, conn *xsnet.Conn, srcPath string srcDir, srcBase := path.Split(srcPath) cmdArgs := []string{"-cz", "-C", srcDir, "-f", "-", srcBase} - c = exec.Command(cmdName, cmdArgs...) // nolint: gosec + c = exec.Command(cmdName, cmdArgs...) - //If os.Clearenv() isn't called by server above these will be seen in the - //client's session env. - //c.Env = []string{"HOME=" + u.HomeDir, "SUDO_GID=", "SUDO_UID=", "SUDO_USER=", "SUDO_COMMAND=", "MAIL=", "LOGNAME="+who} + //If os.Clearenv() isn't called by server above these will be seen + //in the client's session env. + //c.Env = []string{"HOME=" + u.HomeDir, "SUDO_GID=", "SUDO_UID=", "SUDO_USER=", + // "SUDO_COMMAND=", "MAIL=", "LOGNAME="+who} c.Dir = u.HomeDir c.SysProcAttr = &syscall.SysProcAttr{} c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid} @@ -216,11 +221,14 @@ func runServerToClientCopyAs(who, ttype string, conn *xsnet.Conn, srcPath string c.Stderr = stdErrBuffer //c.Stderr = nil + // === Set up connection keepalive to client + conn.StartupKeepAlive() // goroutine, returns immediately + defer conn.ShutdownKeepAlive() + if chaffing { - conn.EnableChaff() + conn.StartupChaff() } //defer conn.Close() - defer conn.DisableChaff() defer conn.ShutdownChaff() // Start the command (no pty) @@ -252,11 +260,10 @@ func runServerToClientCopyAs(who, ttype string, conn *xsnet.Conn, srcPath string return } -// Run a command (via default shell) as a specific user -// -// Uses ptys to support commands which expect a terminal. -// nolint: gocyclo -func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Conn, chaffing bool) (exitStatus uint32, err error) { +// Run a command (via default shell) as a specific user. Uses +// ptys to support commands which expect a terminal. //nolint:gofmt +func runShellAs(who, hname, ttype, cmd string, interactive bool, //nolint:funlen + conn *xsnet.Conn, chaffing bool) (exitStatus uint32, err error) { var wg sync.WaitGroup u, err := user.Lookup(who) if err != nil { @@ -264,54 +271,57 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Con return } var uid, gid uint32 - _, _ = fmt.Sscanf(u.Uid, "%d", &uid) // nolint: gosec - _, _ = fmt.Sscanf(u.Gid, "%d", &gid) // nolint: gosec + _, _ = fmt.Sscanf(u.Uid, "%d", &uid) + _, _ = fmt.Sscanf(u.Gid, "%d", &gid) log.Println("uid:", uid, "gid:", gid) // Need to clear server's env and set key vars of the - // target user. This isn't perfect (TERM doesn't seem to - // work 100%; ANSI/xterm colour isn't working even - // if we set "xterm" or "ansi" here; and line count - // reported by 'stty -a' defaults to 24 regardless - // of client shell window used to run client. - // Investigate -- rlm 2018-01-26) + // target user. os.Clearenv() - _ = os.Setenv("HOME", u.HomeDir) // nolint: gosec - _ = os.Setenv("TERM", ttype) // nolint: gosec - _ = os.Setenv("XS_SESSION", "1") // nolint: gosec + _ = os.Setenv("HOME", u.HomeDir) + _ = os.Setenv("TERM", ttype) + _ = os.Setenv("XS_SESSION", "1") var c *exec.Cmd if interactive { if useSysLogin { - // Use the server's login binary (post-auth, which - // is still done via our own bcrypt file) - // - // Note login will drop privs to the intended user for us + // Use the server's login binary (post-auth) // // Things UNIX login does, like print the 'motd', // and use the shell specified by /etc/passwd, will be done // automagically, at the cost of another external tool // dependency. // - c = exec.Command(xs.GetTool("login"), "-f", "-p", who) // nolint: gosec + // One drawback of using 'login' is that the remote side + // cannot give us back the shell's exit code, since it + // exits back to 'login', which usually returns its own + // 0 status back to us. + // + // Note login will drop privs to the intended user for us. + // + c = exec.Command(xs.GetTool("login"), "-f", "-p", who) //nolint:gosec } else { - // Using our separate login via local passwd file + // Run shell directly (which allows nonzero exit codes back to + // the local system upon shell exit, whereas 'login' does not.) // - // Note we must drop privs ourselves for the user shell + // Note we must drop privs ourselves for the user shell since + // we aren't using 'login' on the remote end which would do it + // for us. // - c = exec.Command(xs.GetTool("bash"), "-i", "-l") // nolint: gosec + c = exec.Command(xs.GetTool("bash"), "-i", "-l") //nolint:gosec c.SysProcAttr = &syscall.SysProcAttr{} c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid} } } else { - c = exec.Command(xs.GetTool("bash"), "-c", cmd) // nolint: gosec + c = exec.Command(xs.GetTool("bash"), "-c", cmd) //nolint:gosec c.SysProcAttr = &syscall.SysProcAttr{} c.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid} } - //If os.Clearenv() isn't called by server above these will be seen in the - //client's session env. - //c.Env = []string{"HOME=" + u.HomeDir, "SUDO_GID=", "SUDO_UID=", "SUDO_USER=", "SUDO_COMMAND=", "MAIL=", "LOGNAME="+who} + //If os.Clearenv() isn't called by server above these will be seen + //in the client's session env. + //c.Env = []string{"HOME=" + u.HomeDir, "SUDO_GID=", "SUDO_UID=", + // "SUDO_USER=", "SUDO_COMMAND=", "MAIL=", "LOGNAME="+who} c.Dir = u.HomeDir // Start the command with a pty. @@ -325,7 +335,7 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Con defer func() { //logger.LogDebug(fmt.Sprintf("[Exited process was %d]", c.Process.Pid)) _ = ptmx.Close() - }() // nolint: gosec + }() // get pty info for system accounting (who, lastlog) pts, pe := ptsName(ptmx.Fd()) @@ -336,6 +346,9 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Con defer func() { goutmp.Unput_utmp(utmpx) }() goutmp.Put_lastlog_entry("xs", who, pts, hname) + conn.Pproc = c.Process.Pid + //fmt.Printf("[process %d started]\n", c.Process.Pid) + log.Printf("[%s]\n", cmd) if err != nil { log.Printf("Command finished with error: %v", err) @@ -345,7 +358,7 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Con go func() { for sz := range conn.WinCh { log.Printf("[Setting term size to: %v %v]\n", sz.Rows, sz.Cols) - pty.Setsize(ptmx, &pty.Winsize{Rows: sz.Rows, Cols: sz.Cols}) // nolint: gosec,errcheck + pty.Setsize(ptmx, &pty.Winsize{Rows: sz.Rows, Cols: sz.Cols}) //nolint:errcheck } log.Println("*** WinCh goroutine done ***") }() @@ -361,12 +374,15 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Con } }() + // === Set up connection keepalive to client + conn.StartupKeepAlive() // goroutine, returns immediately + defer conn.ShutdownKeepAlive() + if chaffing { - conn.EnableChaff() + conn.StartupChaff() } // #gv:s/label=\"runShellAs\$4\"/label=\"deferChaffShutdown\"/ defer func() { - conn.DisableChaff() conn.ShutdownChaff() }() @@ -406,7 +422,7 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, conn *xsnet.Con } conn.SetStatus(xsnet.CSOType(exitStatus)) } else { - logger.LogDebug("*** Main proc has exited. ***") + logger.LogDebug(fmt.Sprintf("*** Main proc has exited (%d) ***", c.ProcessState.ExitCode())) //nolint:errcheck // Background jobs still may be running; close the // pty anyway, so the client can return before // wg.Wait() below completes (Issue #18) @@ -428,8 +444,8 @@ func GenAuthToken(who string, connhost string) string { //} hname := connhost - token := make([]byte, 64) - _, _ = rand.Read(token) // nolint: gosec + token := make([]byte, AuthTokenLen) + _, _ = rand.Read(token) return fmt.Sprintf("%s:%s:%s", hname, who, hex.EncodeToString(token)) } @@ -505,7 +521,7 @@ func (a *allowedHMACAlgs) Set(value string) error { // daemon dies, all clients will be rudely disconnected. // Consider this when planning to restart or upgrade in-place an installation. // TODO: reduce gocyclo -func main() { +func main() { //nolint:funlen,gocyclo var vopt bool var chaffEnabled bool var chaffFreqMin uint @@ -513,21 +529,24 @@ func main() { var chaffBytesMax uint var dbg bool var laddr string + var rekeySecs uint + var remodSupported bool // true: when rekeying, switch to random cipher/hmac alg var useSystemPasswd bool flag.BoolVar(&vopt, "v", false, "show version") - flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen") - flag.StringVar(&kcpMode, "K", "unused", `set to one of ["KCP_NONE","KCP_AES", "KCP_BLOWFISH", "KCP_CAST5", "KCP_SM4", "KCP_SALSA20", "KCP_SIMPLEXOR", "KCP_TEA", "KCP_3DES", "KCP_TWOFISH", "KCP_XTEA"] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP`) + flag.UintVar(&rekeySecs, "r", 300, "rekey interval in `secs`") + flag.BoolVar(&remodSupported, "R", false, "Borg Countermeasures (remodulate cipher/hmac alg on each rekey)") + flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen") //nolint:gomnd,lll + flag.StringVar(&kcpMode, "K", "unused", `set to one of ["KCP_NONE","KCP_AES", "KCP_BLOWFISH", "KCP_CAST5", "KCP_SM4", "KCP_SALSA20", "KCP_SIMPLEXOR", "KCP_TEA", "KCP_3DES", "KCP_TWOFISH", "KCP_XTEA"] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP`) //nolint:lll flag.BoolVar(&useSysLogin, "L", false, "use system login") flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts") - flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)") - flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max (msecs)") - flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)") + flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)") //nolint:gomnd + flag.UintVar(&chaffFreqMax, "F", 5000, "chaff pkt freq max (msecs)") //nolint:gomnd + flag.UintVar(&chaffBytesMax, "B", 64, "chaff pkt size max (bytes)") //nolint:gomnd flag.BoolVar(&useSystemPasswd, "s", true, "use system shadow passwds") flag.BoolVar(&dbg, "d", false, "debug logging") - - flag.Var(&aKEXAlgs, "aK", "Allowed KEX `alg`s (eg. '-aK KEXAlgA -aK KEXAlgB ...')" + ` + flag.Var(&aKEXAlgs, "aK", "Allowed KEX `alg`s (eg. '-aK KEXAlgA -aK KEXAlgB ...')"+` KEX_all KEX_HERRADURA256 KEX_HERRADURA512 @@ -542,7 +561,7 @@ func main() { KEX_FRODOKEM_1344SHAKE KEX_FRODOKEM_976AES KEX_FRODOKEM_976SHAKE`) - flag.Var(&aCipherAlgs, "aC", "Allowed `cipher`s (eg. '-aC CAlgA -aC CAlgB ...')" + ` + flag.Var(&aCipherAlgs, "aC", "Allowed `cipher`s (eg. '-aC CAlgA -aC CAlgB ...')"+` C_all C_AES_256 C_TWOFISH_128 @@ -550,10 +569,14 @@ func main() { C_CRYPTMT1 C_HOPSCOTCH C_CHACHA20_12`) - flag.Var(&aHMACAlgs, "aH", "Allowed `HMAC`s (eg. '-aH HMACAlgA -aH HMACAlgB ...')" + ` + flag.Var(&aHMACAlgs, "aH", "Allowed `HMAC`s (eg. '-aH HMACAlgA -aH HMACAlgB ...')"+` H_all H_SHA256 - H_SHA512`) + H_SHA512 + H_WHIRLPOOL`) + + flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to <`file`>") + flag.StringVar(&memprofile, "memprofile", "", "write memory profile to <`file`>") flag.Parse() @@ -569,8 +592,26 @@ func main() { } } + // === Profiling instrumentation + + if cpuprofile != "" { + f, err := os.Create(cpuprofile) + if err != nil { + log.Fatal("could not create CPU profile: ", err) + } + defer f.Close() + fmt.Println("StartCPUProfile()") + if err := pprof.StartCPUProfile(f); err != nil { + log.Fatal("could not start CPU profile: ", err) //nolint:gocritic + } else { + defer pprof.StopCPUProfile() + } + + go func() { http.ListenAndServe("localhost:6060", nil) }() //nolint:errcheck,gosec + } + // Enforce some sane min/max vals on chaff flags - if chaffFreqMin < 2 { + if chaffFreqMin < 2 { //nolint:gomnd chaffFreqMin = 2 } if chaffFreqMax == 0 { @@ -580,49 +621,52 @@ func main() { chaffBytesMax = 64 } - Log, _ = logger.New(logger.LOG_DAEMON|logger.LOG_DEBUG|logger.LOG_NOTICE|logger.LOG_ERR, "xsd") // nolint: gosec + Log, _ = logger.New(logger.LOG_DAEMON|logger.LOG_DEBUG|logger.LOG_NOTICE|logger.LOG_ERR, "xsd") xsnet.Init(dbg, "xsd", logger.LOG_DAEMON|logger.LOG_DEBUG|logger.LOG_NOTICE|logger.LOG_ERR) if dbg { log.SetOutput(Log) } else { - log.SetOutput(ioutil.Discard) + log.SetOutput(io.Discard) } // Set up allowed algs, if specified (default allow all) if len(aKEXAlgs) == 0 { aKEXAlgs = []string{"none"} } - logger.LogNotice(fmt.Sprintf("Allowed KEXAlgs: %v\n", aKEXAlgs)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("Allowed KEXAlgs: %v\n", aKEXAlgs)) //nolint:errcheck if len(aCipherAlgs) == 0 { aCipherAlgs = []string{"none"} } - logger.LogNotice(fmt.Sprintf("Allowed CipherAlgs: %v\n", aCipherAlgs)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("Allowed CipherAlgs: %v\n", aCipherAlgs)) //nolint:errcheck if len(aHMACAlgs) == 0 { aHMACAlgs = []string{"none"} } - logger.LogNotice(fmt.Sprintf("Allowed HMACAlgs: %v\n", aHMACAlgs)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("Allowed HMACAlgs: %v\n", aHMACAlgs)) //nolint:errcheck // Set up handler for daemon signalling exitCh := make(chan os.Signal, 1) - signal.Notify(exitCh, os.Signal(syscall.SIGTERM), os.Signal(syscall.SIGINT), os.Signal(syscall.SIGHUP), os.Signal(syscall.SIGUSR1), os.Signal(syscall.SIGUSR2)) + signal.Notify(exitCh, os.Signal(syscall.SIGTERM), os.Signal(syscall.SIGINT), os.Signal(syscall.SIGHUP), os.Signal(syscall.SIGUSR1), os.Signal(syscall.SIGUSR2)) //nolint:lll go func() { for { sig := <-exitCh - switch sig.String() { - case "terminated": - logger.LogNotice(fmt.Sprintf("[Got signal: %s]", sig)) // nolint: gosec,errcheck + switch sig { + case syscall.SIGTERM: //"terminated": + logger.LogNotice(fmt.Sprintf("[Got signal: %s]", sig.String())) //nolint:errcheck signal.Reset() - syscall.Kill(0, syscall.SIGTERM) // nolint: gosec,errcheck - case "interrupt": - logger.LogNotice(fmt.Sprintf("[Got signal: %s]", sig)) // nolint: gosec,errcheck + syscall.Kill(0, syscall.SIGTERM) //nolint:errcheck + case syscall.SIGINT: //"interrupt": + logger.LogNotice(fmt.Sprintf("[Got signal: %s]", sig.String())) //nolint:errcheck signal.Reset() - syscall.Kill(0, syscall.SIGINT) // nolint: gosec,errcheck - case "hangup": - logger.LogNotice(fmt.Sprintf("[Got signal: %s - nop]", sig)) // nolint:gosec,errcheck + syscall.Kill(0, syscall.SIGINT) //nolint:errcheck + case syscall.SIGHUP: //"hangup": + logger.LogNotice(fmt.Sprintf("[Got signal: %s - nop]", sig.String())) //nolint:errcheck + if cpuprofile != "" || memprofile != "" { + dumpProf() + } default: - logger.LogNotice(fmt.Sprintf("[Got signal: %s - ignored]", sig)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[Got signal: %s - ignored]", sig.String())) //nolint:errcheck } } }() @@ -635,13 +679,14 @@ func main() { if err != nil { log.Fatal(err) } - defer l.Close() // nolint: errcheck + defer l.Close() log.Println("Serving on", laddr) for { // Wait for a connection. // Then check if client-proposed algs are allowed conn, err := l.Accept() + //logger.LogDebug(fmt.Sprintf("l.Accept()\n")) if err != nil { log.Printf("Accept() got error(%v), hanging up.\n", err) } else { @@ -660,6 +705,24 @@ func main() { } else { log.Println("Accepted client") + // Only enable cipher alg changes on re-key if we were told + // to support it (launching xsd with -R), *and* the client + // proposes to use it. + if !remodSupported { + if (conn.Opts() & xsnet.CORemodulateShields) != 0 { + logger.LogDebug("[client proposed cipher/hmac remod, but we don't support it.]") + conn.Close() + continue + } + } else { + if conn.Opts()&xsnet.CORemodulateShields != 0 { + logger.LogDebug("[cipher/hmac remodulation active]") + } else { + logger.LogDebug("[cipher/hmac remodulation inactive]") + } + } + conn.RekeyHelper(rekeySecs) + // Set up chaffing to client // Will only start when runShellAs() is called // after stdin/stdout are hooked up @@ -669,12 +732,13 @@ func main() { // The loop then returns to accepting, so that // multiple connections may be served concurrently. go func(hc *xsnet.Conn) (e error) { - defer hc.Close() // nolint: errcheck + defer hc.ShutdownRekey() + defer hc.Close() // Start login timeout here and disconnect if user/pass phase stalls - loginTimeout := time.AfterFunc(30*time.Second, func() { - logger.LogNotice(fmt.Sprintln("Login timed out")) // nolint: errcheck,gosec - hc.Write([]byte{0}) // nolint: gosec,errcheck + loginTimeout := time.AfterFunc(LoginTimeoutSecs*time.Second, func() { + logger.LogNotice(fmt.Sprintln("Login timed out")) //nolint:errcheck + hc.Write([]byte{0}) //nolint:errcheck hc.Close() }) @@ -763,10 +827,10 @@ func main() { // Tell client if auth was valid if valid { - hc.Write([]byte{1}) // nolint: gosec,errcheck + hc.Write([]byte{1}) //nolint:errcheck } else { - logger.LogNotice(fmt.Sprintln("Invalid user", string(rec.Who()))) // nolint: errcheck,gosec - hc.Write([]byte{0}) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintln("Invalid user", string(rec.Who()))) //nolint:errcheck + hc.Write([]byte{0}) //nolint:errcheck return } @@ -776,15 +840,15 @@ func main() { // Generate automated login token addr := hc.RemoteAddr() hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[Generating autologin token for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[Generating autologin token for [%s@%s]]\n", rec.Who(), hname)) //nolint:errcheck token := GenAuthToken(string(rec.Who()), string(rec.ConnHost())) - tokenCmd := fmt.Sprintf("echo \"%s\" | tee -a ~/.xs_id", token) + tokenCmd := fmt.Sprintf("echo %q | tee -a ~/%s", token, xsnet.XS_ID_AUTHTOKFILE) cmdStatus, runErr := runShellAs(string(rec.Who()), hname, string(rec.TermType()), tokenCmd, false, hc, chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) if runErr != nil { - logger.LogErr(fmt.Sprintf("[Error generating autologin token for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogErr(fmt.Sprintf("[Error generating autologin token for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck } else { log.Printf("[Autologin token generation completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus) hc.SetStatus(xsnet.CSOType(cmdStatus)) @@ -793,31 +857,31 @@ func main() { // Non-interactive command addr := hc.RemoteAddr() hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[Running command for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[Running command for [%s@%s]]\n", rec.Who(), hname)) //nolint:errcheck cmdStatus, runErr := runShellAs(string(rec.Who()), hname, string(rec.TermType()), string(rec.Cmd()), false, hc, chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) if runErr != nil { - logger.LogErr(fmt.Sprintf("[Error spawning cmd for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogErr(fmt.Sprintf("[Error spawning cmd for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck } else { - logger.LogNotice(fmt.Sprintf("[Command completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[Command completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) //nolint:errcheck hc.SetStatus(xsnet.CSOType(cmdStatus)) } } else if rec.Op()[0] == 's' { // Interactive session addr := hc.RemoteAddr() hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[Running shell for [%s@%s]]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[Running shell for [%s@%s]]\n", rec.Who(), hname)) //nolint:errcheck cmdStatus, runErr := runShellAs(string(rec.Who()), hname, string(rec.TermType()), string(rec.Cmd()), true, hc, chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) if runErr != nil { - Log.Err(fmt.Sprintf("[Error spawning shell for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + Log.Err(fmt.Sprintf("[Error spawning shell for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck } else { - logger.LogNotice(fmt.Sprintf("[Shell completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[Shell completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) //nolint:errcheck hc.SetStatus(xsnet.CSOType(cmdStatus)) } } else if rec.Op()[0] == 'D' { @@ -825,41 +889,38 @@ func main() { log.Printf("[Client->Server copy]\n") addr := hc.RemoteAddr() hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[c->s copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[c->s copy for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck cmdStatus, runErr := runClientToServerCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) if runErr != nil { - logger.LogErr(fmt.Sprintf("[c->s copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogErr(fmt.Sprintf("[c->s copy error for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck } else { - logger.LogNotice(fmt.Sprintf("[c->s copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[c->s copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) //nolint:errcheck } // TODO: Test this with huge files.. see Bug #22 - do we need to // sync w/sender (client) that we've gotten all data? hc.SetStatus(xsnet.CSOType(cmdStatus)) // Send CSOExitStatus *before* client closes channel - s := make([]byte, 4) + s := make([]byte, 4) //nolint:gomnd binary.BigEndian.PutUint32(s, cmdStatus) log.Printf("** cp writing closeStat %d at Close()\n", cmdStatus) - hc.WritePacket(s, xsnet.CSOExitStatus) // nolint: gosec,errcheck + hc.WritePacket(s, xsnet.CSOExitStatus) //nolint:errcheck } else if rec.Op()[0] == 'S' { // File copy (src) operation - server copy to client log.Printf("[Server->Client copy]\n") addr := hc.RemoteAddr() hname := goutmp.GetHost(addr.String()) - logger.LogNotice(fmt.Sprintf("[s->c copy for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[s->c copy for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck cmdStatus, runErr := runServerToClientCopyAs(string(rec.Who()), string(rec.TermType()), hc, string(rec.Cmd()), chaffEnabled) if runErr != nil { - logger.LogErr(fmt.Sprintf("[s->c copy error for %s@%s]\n", rec.Who(), hname)) // nolint: gosec,errcheck + logger.LogErr(fmt.Sprintf("[s->c copy error for %s@%s]\n", rec.Who(), hname)) //nolint:errcheck } else { // Returned hopefully via an EOF or exit/logout; - logger.LogNotice(fmt.Sprintf("[s->c copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) // nolint: gosec,errcheck + logger.LogNotice(fmt.Sprintf("[s->c copy completed for %s@%s, status %d]\n", rec.Who(), hname, cmdStatus)) //nolint:errcheck } - // HACK: Bug #22: (xc) Need to wait for rcvr to get final data - // TODO: Await specific msg from client to inform they have gotten all data from the tarpipe - time.Sleep(time.Duration(900 * time.Millisecond)) // Let rcvr set this on setup? // Clear current op so user can enter next, or EOF rec.SetOp([]byte{0}) @@ -868,12 +929,32 @@ func main() { //_, _ = hc.Read(nil /*ackByte*/) //fmt.Println("Got remote end ack.") } else { - logger.LogErr(fmt.Sprintln("[Bad xs.Session]")) // nolint: gosec,errcheck + logger.LogErr(fmt.Sprintln("[Bad xs.Session]")) //nolint:errcheck } return - }(&conn) // nolint: errcheck + }(&conn) //nolint:errcheck } // algs valid and not blacklisted } // Accept() success } //endfor - //logger.LogNotice(fmt.Sprintln("[Exiting]")) // nolint: gosec,errcheck + //logger.LogNotice(fmt.Sprintln("[Exiting]")) //nolint:errcheck +} + +func dumpProf() { + if cpuprofile != "" { + pprof.StopCPUProfile() + } + + if memprofile != "" { + f, err := os.Create(memprofile) + if err != nil { + log.Fatal("could not create memory profile: ", err) + } + defer f.Close() + runtime.GC() // get up-to-date statistics + if err := pprof.WriteHeapProfile(f); err != nil { + log.Fatal("could not write memory profile: ", err) //nolint:gocritic + } + } + + //os.Exit(status) } diff --git a/xsnet/chan.go b/xsnet/chan.go index 6e5a0f3..5847372 100644 --- a/xsnet/chan.go +++ b/xsnet/chan.go @@ -22,10 +22,11 @@ import ( "blitter.com/go/cryptmt" "blitter.com/go/hopscotch" + "blitter.com/go/xs/logger" "github.com/aead/chacha20/chacha" "golang.org/x/crypto/blowfish" "golang.org/x/crypto/twofish" - + whirlpool "github.com/jzelinskie/whirlpool" // hash algos must be manually imported thusly: // (Would be nice if the golang pkg docs were more clear // on this...) @@ -57,9 +58,19 @@ func expandKeyMat(keymat []byte, blocksize int) []byte { return keymat } -/* Support functionality to set up encryption after a channel has -been negotiated via xsnet.go -*/ +// Choose a cipher and hmac alg from supported sets, given two uint8 values +func getNewStreamAlgs(cb uint8, hb uint8) (config uint32) { + // Get new cipher and hash algs (clamped to valid values) based on + // the input rekeying data + c := (cb % CAlgNoneDisallowed) + h := (hb % HmacNoneDisallowed) + config = uint32(h<<8) | uint32(c) + logger.LogDebug(fmt.Sprintf("[Chose new algs [%d:%d]", h, c)) + return +} + +// (Re-)initialize the keystream and hmac state for an xsnet.Conn, returning +// a cipherStream and hash func (hc *Conn) getStream(keymat []byte) (rc cipher.Stream, mc hash.Hash, err error) { var key []byte var block cipher.Block @@ -146,6 +157,9 @@ func (hc *Conn) getStream(keymat []byte) (rc cipher.Stream, mc hash.Hash, err er if !halg.Available() { log.Fatal("hash not available!") } + case HmacWHIRLPOOL: + log.Printf("[hash HmacWHIRLPOOL (%d)]\n", hopts) + mc = whirlpool.New() default: log.Printf("[invalid hmac (%d)]\n", hopts) fmt.Printf("DOOFUS SET A VALID HMAC ALG (%d)\n", hopts) diff --git a/xsnet/consts.go b/xsnet/consts.go index 30833a2..9c58d6e 100644 --- a/xsnet/consts.go +++ b/xsnet/consts.go @@ -52,6 +52,8 @@ const ( CSEKEXAlgDenied // server rejected proposed KEX alg CSECipherAlgDenied // server rejected proposed Cipher alg CSEHMACAlgDenied // server rejected proposed HMAC alg + CSEConnDead // connection keepalives expired + CSELoginTimeout ) // Extended (>255 UNIX exit status) codes @@ -67,9 +69,6 @@ const ( CSOExitStatus // Remote cmd exit status CSOChaff // Dummy packet, do not pass beyond decryption - // Client side errors - CSOLoginTimeout - // Tunnel setup/control/status CSOTunSetup // client -> server tunnel setup request (dstport) CSOTunSetupAck // server -> client tunnel setup ack @@ -78,6 +77,8 @@ const ( CSOTunKeepAlive // client tunnel heartbeat CSOTunDisconn // server -> client: tunnel rport disconnected CSOTunHangup // client -> server: tunnel lport hung up + CSOKeepAlive // bidir keepalive packet to monitor main connection + CSORekey // TODO: rekey/re-select session cipher/hash algs ) // TunEndpoint.tunCtl control values - used to control workers for client @@ -97,7 +98,7 @@ const ( // Channel status Op byte type (see CSONone, ... and CSENone, ...) type CSOType uint32 -//TODO: this should be small (max unfragmented packet size?) +// TODO: this should be small (max unfragmented packet size?) const MAX_PAYLOAD_LEN = 2*1024*1024*1024 - 1 // Session symmetric crypto algs @@ -118,8 +119,27 @@ type CSCipherAlg uint32 const ( HmacSHA256 = iota HmacSHA512 + HmacWHIRLPOOL HmacNoneDisallowed ) +// Conn opts outside of basic kex/cipher/hmac connect config +const ( + CONone = iota + CORemodulateShields // if set, rekeying also reselects random cipher/hmac alg +) + +type COValue uint32 + // Available HMACs for hkex.Conn type CSHmacAlg uint32 + +// Some bounds-checking consts +const ( + REKEY_SECS_MIN = 1 + REKEY_SECS_MAX = 28800 // 8 hours + CHAFF_FREQ_MSECS_MIN = 1 + CHAFF_FREQ_MSECS_MAX = 300000 // 5 minutes +) + +const XS_ID_AUTHTOKFILE = ".config/xs/.xs_id" diff --git a/xsnet/net.go b/xsnet/net.go index bfb002f..8727437 100644 --- a/xsnet/net.go +++ b/xsnet/net.go @@ -9,7 +9,7 @@ package xsnet -// Implementation of HKEx-wrapped versions of the golang standard +// Implementation of key-exchange-wrapped versions of the golang standard // net package interfaces, allowing clients and servers to simply replace // 'net.Dial' and 'net.Listen' with 'hkex.Dial' and 'hkex.Listen' // (though some extra methods are implemented and must be used @@ -39,6 +39,7 @@ import ( "net" "strings" "sync" + "syscall" "time" hkex "blitter.com/go/herradurakex" @@ -64,7 +65,6 @@ type ( // see: https://en.wikipedia.org/wiki/chaff_(countermeasure) ChaffConfig struct { shutdown bool //set to inform chaffHelper to shut down - enabled bool msecsMin uint //msecs min interval msecsMax uint //msecs max interval szMax uint // max size in bytes @@ -87,8 +87,11 @@ type ( Rows uint16 Cols uint16 - chaff ChaffConfig - tuns *map[uint16](*TunEndpoint) + keepalive uint // if this reaches zero, conn is considered dead + rekey uint // if nonzero, rekeying interval in seconds + Pproc int // proc ID of command run on this conn + chaff ChaffConfig + tuns *map[uint16](*TunEndpoint) closeStat *CSOType // close status (CSOExitStatus) r cipher.Stream //read cipherStream @@ -174,6 +177,8 @@ func (h *CSHmacAlg) String() string { return "H_SHA256" case HmacSHA512: return "H_SHA512" + case HmacWHIRLPOOL: + return "H_WHIRLPOOL" default: return "H_ERR_UNK" } @@ -238,7 +243,7 @@ func (hc *Conn) SetConnOpts(copts uint32) { // // Consumers of this lib may use this for protocol-level options not part // of the KEx or encryption info used by the connection. -func (hc Conn) Opts() uint32 { +func (hc *Conn) Opts() uint32 { return hc.opts } @@ -267,8 +272,6 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) { tempMap := make(map[uint16]*TunEndpoint) hc.tuns = &tempMap - *hc.closeStat = CSEStillOpen // open or prematurely-closed status - // Set up KEx/KEM-specifics switch kexAlg { case KEX_HERRADURA256: @@ -310,9 +313,9 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) { // applyConnExtensions processes optional Dial() negotiation // parameters. See also getkexalgnum(). // -// Currently defined extension values +// # Currently defined extension values // -// KEx algs +// # KEx algs // // KEX_HERRADURA256 KEX_HERRADURA512 KEX_HERRADURA1024 KEX_HERRADURA2048 // @@ -320,11 +323,11 @@ func _new(kexAlg KEXAlg, conn *net.Conn) (hc *Conn, e error) { // // KEX_NEWHOPE KEX_NEWHOPE_SIMPLE // -// Session (symmetric) crypto +// # Session (symmetric) crypto // // C_AES_256 C_TWOFISH_128 C_BLOWFISH_128 C_CRYPTMT1 C_CHACHA20_12 C_HOPSCOTCH // -// Session HMACs +// # Session HMACs // // H_SHA256 H_SHA512 func (hc *Conn) applyConnExtensions(extensions ...string) { @@ -362,6 +365,13 @@ func (hc *Conn) applyConnExtensions(extensions ...string) { log.Println("[extension arg = H_SHA512]") hc.cipheropts &= (0xFFFF00FF) hc.cipheropts |= (HmacSHA512 << 8) + case "H_WHIRLPOOL": + log.Println("[extension arg = H_WHIRLPOOL]") + hc.cipheropts &= (0xFFFF00FF) + hc.cipheropts |= (HmacWHIRLPOOL << 8) + case "OPT_REMOD": + log.Println("[extension arg = OPT_REMOD]") + hc.opts |= CORemodulateShields //default: // log.Printf("[Dial ext \"%s\" ignored]\n", s) } @@ -884,12 +894,12 @@ func HKExAcceptSetup(c *net.Conn, hc *Conn) (err error) { // Dial as net.Dial(), but with implicit key exchange to set up secure // channel on connect // -// Can be called like net.Dial(), defaulting to C_AES_256/H_SHA256, -// or additional extensions can be passed amongst the following: +// Can be called like net.Dial(), defaulting to C_AES_256/H_SHA256, +// or additional extensions can be passed amongst the following: // -// "C_AES_256" | "C_TWOFISH_128" | ... +// "C_AES_256" | "C_TWOFISH_128" | ... // -// "H_SHA256" | "H_SHA512" | ... +// "H_SHA256" | "H_SHA512" | ... // // See go doc -u xsnet.applyConnExtensions func Dial(protocol string, ipport string, extensions ...string) (hc Conn, err error) { @@ -973,12 +983,25 @@ func Dial(protocol string, ipport string, extensions ...string) (hc Conn, err er // Close a hkex.Conn func (hc *Conn) Close() (err error) { - hc.DisableChaff() + hc.ShutdownChaff() s := make([]byte, 4) binary.BigEndian.PutUint32(s, uint32(*hc.closeStat)) log.Printf("** Writing closeStat %d at Close()\n", *hc.closeStat) //(*hc.c).SetWriteDeadline(time.Now().Add(500 * time.Millisecond)) hc.WritePacket(s, CSOExitStatus) + + // HACK: Bug #22,#33: Need to wait for rcvr to get final data + // TODO: Find a way to explicitly check if any outgoing data is pending + + //Ensure socket has sent all data to client prior to closing + //NOTE: This is not ideal, as it would be better to somehow + //determine if there is any pending outgoing (write) data to the + //underlying socket (TCP/KCP) prior to closing; however Go's net pkg + //completely hides lower-level stuff. net.Conn.Close() according to + //docs sends written data in the background, so how best to determine + //all data has been sent? -rlm 2022-10-04 + time.Sleep(10 * time.Millisecond) //nolint:gomnd + err = (*hc.c).Close() logger.LogDebug(fmt.Sprintln("[Conn Closing]")) return @@ -1073,7 +1096,7 @@ func (hl HKExListener) Close() error { return hl.l.Close() } -// Addr returns a the listener's network address. +// Addr returns the listener's network address. // // See go doc net.Listener.Addr func (hl HKExListener) Addr() net.Addr { @@ -1098,7 +1121,7 @@ func (hl *HKExListener) Accept() (hc Conn, err error) { return Conn{}, err } - logger.LogDebug(fmt.Sprintln("[net.Listener Accepted]")) + logger.LogDebug(fmt.Sprintf("[net.Listener Accepted %v]\n", c.RemoteAddr())) } // Read KEx alg proposed by client var kexAlg KEXAlg @@ -1185,7 +1208,7 @@ func (hl *HKExListener) Accept() (hc Conn, err error) { // packet processing. // // See go doc io.Reader -func (hc Conn) Read(b []byte) (n int, err error) { +func (hc *Conn) Read(b []byte) (n int, err error) { for { if hc.dBuf.Len() > 0 { break @@ -1195,6 +1218,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { var hmacIn [HMAC_CHK_SZ]uint8 var payloadLen uint32 + //------------- Read ctrl/status opcode -------------------- // Read ctrl/status opcode (CSOHmacInvalid on hmac mismatch) err = binary.Read(*hc.c, binary.BigEndian, &ctrlStatOp) if err != nil { @@ -1202,7 +1226,8 @@ func (hc Conn) Read(b []byte) (n int, err error) { return 0, io.EOF } if strings.HasSuffix(err.Error(), "use of closed network connection") { - logger.LogDebug(fmt.Sprintln("[Client hung up]")) + logger.LogDebug(fmt.Sprintln("[Client hung up(1)]")) + //!rlm hc.SetStatus(CSENone) //FIXME: re-examine this (exit 9 w/o it - 2023-11-05) return 0, io.EOF } etxt := fmt.Sprintf("** Failed read:%s (%s) **", "ctrlStatOp", err) @@ -1215,7 +1240,9 @@ func (hc Conn) Read(b []byte) (n int, err error) { hc.Close() return 0, errors.New("** ALERT - remote end detected HMAC mismatch - possible channel tampering **") } + //---------------------------------------------------------- + //------------------ Read HMAC len ------------------------ // Read the hmac and payload len first err = binary.Read(*hc.c, binary.BigEndian, &hmacIn) if err != nil { @@ -1223,27 +1250,30 @@ func (hc Conn) Read(b []byte) (n int, err error) { return 0, io.EOF } if strings.HasSuffix(err.Error(), "use of closed network connection") { - logger.LogDebug(fmt.Sprintln("[Client hung up]")) + logger.LogDebug(fmt.Sprintln("[Client hung up(2)]")) return 0, io.EOF } etxt := fmt.Sprintf("** Failed read:%s (%s) **", "HMAC", err) logger.LogDebug(etxt) return 0, errors.New(etxt) } + //---------------------------------------------------------- + //------------------ Read Payload len --------------------- err = binary.Read(*hc.c, binary.BigEndian, &payloadLen) if err != nil { if err.Error() == "EOF" { return 0, io.EOF } if strings.HasSuffix(err.Error(), "use of closed network connection") { - logger.LogDebug(fmt.Sprintln("[Client hung up]")) + logger.LogDebug(fmt.Sprintln("[Client hung up(3)]")) return 0, io.EOF } etxt := fmt.Sprintf("** Failed read:%s (%s) **", "payloadLen", err) logger.LogDebug(etxt) return 0, errors.New(etxt) } + //---------------------------------------------------------- if payloadLen > MAX_PAYLOAD_LEN { logger.LogDebug(fmt.Sprintf("[Insane payloadLen:%v]\n", payloadLen)) @@ -1251,6 +1281,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { return 1, errors.New("Insane payloadLen") } + //-------------------- Read Payload ------------------------ var payloadBytes = make([]byte, payloadLen) n, err = io.ReadFull(*hc.c, payloadBytes) if err != nil { @@ -1258,19 +1289,21 @@ func (hc Conn) Read(b []byte) (n int, err error) { return 0, io.EOF } if strings.HasSuffix(err.Error(), "use of closed network connection") { - logger.LogDebug(fmt.Sprintln("[Client hung up]")) + logger.LogDebug(fmt.Sprintln("[Client hung up(4)]")) return 0, io.EOF } etxt := fmt.Sprintf("** Failed read:%s (%s) **", "payloadBytes", err) logger.LogDebug(etxt) return 0, errors.New(etxt) } + //---------------------------------------------------------- if hc.logCipherText { log.Printf(" <:ctext:\r\n%s\r\n", hex.Dump(payloadBytes[:n])) } //fmt.Printf(" <:ctext:\r\n%s\r\n", hex.Dump(payloadBytes[:n])) + //---------------- Verify Payload via HMAC ----------------- hc.rm.Write(payloadBytes) // Calc hmac on received data hTmp := hc.rm.Sum(nil)[0:HMAC_CHK_SZ] //log.Printf("<%04x) HMAC:(i)%s (c)%02x\r\n", decryptN, hex.EncodeToString([]byte(hmacIn[0:])), hTmp) @@ -1280,7 +1313,9 @@ func (hc Conn) Read(b []byte) (n int, err error) { logger.LogDebug(fmt.Sprintln("** ALERT - detected HMAC mismatch, possible channel tampering **")) _, _ = (*hc.c).Write([]byte{CSOHmacInvalid}) } + //---------------------------------------------------------- + //------------------- Decrypt Payload ---------------------- db := bytes.NewBuffer(payloadBytes[:n]) //copying payloadBytes to db // The StreamReader acts like a pipe, decrypting // whatever is available and forwarding the result @@ -1289,6 +1324,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { // The caller isn't necessarily reading the full payload so we need // to decrypt to an intermediate buffer, draining it on demand of caller decryptN, err := rs.Read(payloadBytes) + //---------------------------------------------------------- if hc.logPlainText { log.Printf(" <:ptext:\r\n%s\r\n", hex.Dump(payloadBytes[:n])) @@ -1297,6 +1333,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { log.Println("xsnet.Read():", err) //panic(err) } else { + //------------ Discard Padding --------------------- // Padding: Read padSide, padLen, (padding | d) or (d | padding) padSide := payloadBytes[0] padLen := payloadBytes[1] @@ -1307,15 +1344,33 @@ func (hc Conn) Read(b []byte) (n int, err error) { } else { payloadBytes = payloadBytes[0 : len(payloadBytes)-int(padLen)] } + //-------------------------------------------------- - // Throw away pkt if it's chaff (ie., caller to Read() won't see this data) - if ctrlStatOp == CSOChaff { + switch ctrlStatOp { + case CSOChaff: + // Throw away pkt if it's chaff (ie., caller to Read() won't see this data) log.Printf("[Chaff pkt, discarded (len %d)]\n", decryptN) - } else if ctrlStatOp == CSOTermSize { + case CSOKeepAlive: + //logger.LogDebug(fmt.Sprintf("[got keepAlive pkt, discarded (len %d)]\n", decryptN)) + // payload of keepalive (2 bytes) is not currently used (0x55aa fixed) + _ = binary.BigEndian.Uint16(payloadBytes[0:2]) + hc.ResetKeepAlive() + case CSORekey: + // rekey + //logger.LogDebug(fmt.Sprintf("[Got rekey [%02x %02x %02x ...]\n", + // payloadBytes[0], payloadBytes[1], payloadBytes[2])) + rekeyData := payloadBytes + if (hc.opts & CORemodulateShields) != 0 { + hc.Lock() + hc.cipheropts = getNewStreamAlgs(rekeyData[0], rekeyData[1]) + hc.Unlock() + } + hc.r, hc.rm, err = hc.getStream(rekeyData) + case CSOTermSize: fmt.Sscanf(string(payloadBytes), "%d %d", &hc.Rows, &hc.Cols) log.Printf("[TermSize pkt: rows %v cols %v]\n", hc.Rows, hc.Cols) hc.WinCh <- WinSize{hc.Rows, hc.Cols} - } else if ctrlStatOp == CSOExitStatus { + case CSOExitStatus: if len(payloadBytes) > 0 { hc.SetStatus(CSOType(binary.BigEndian.Uint32(payloadBytes))) } else { @@ -1323,7 +1378,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { hc.SetStatus(CSETruncCSO) } hc.Close() - } else if ctrlStatOp == CSOTunSetup { + case CSOTunSetup: // server side tunnel setup in response to client lport := binary.BigEndian.Uint16(payloadBytes[0:2]) rport := binary.BigEndian.Uint16(payloadBytes[2:4]) @@ -1335,7 +1390,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { logger.LogDebug(fmt.Sprintf("[Server] Got CSOTunSetup [%d:%d]", lport, rport)) } (*hc.tuns)[rport].Ctl <- 'd' // Dial() rport - } else if ctrlStatOp == CSOTunSetupAck { + case CSOTunSetupAck: lport := binary.BigEndian.Uint16(payloadBytes[0:2]) rport := binary.BigEndian.Uint16(payloadBytes[2:4]) if _, ok := (*hc.tuns)[rport]; !ok { @@ -1346,7 +1401,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { logger.LogDebug(fmt.Sprintf("[Client] Got CSOTunSetupAck [%d:%d]", lport, rport)) } (*hc.tuns)[rport].Ctl <- 'a' // Listen() for lport connection - } else if ctrlStatOp == CSOTunRefused { + case CSOTunRefused: // client side receiving CSOTunRefused means the remote side // could not dial() rport. So we cannot yet listen() // for client-side on lport. @@ -1358,7 +1413,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { } else { logger.LogDebug(fmt.Sprintf("[Client] CSOTunRefused on already-closed tun [%d:%d]", lport, rport)) } - } else if ctrlStatOp == CSOTunDisconn { + case CSOTunDisconn: // server side's rport has disconnected (server lost) lport := binary.BigEndian.Uint16(payloadBytes[0:2]) rport := binary.BigEndian.Uint16(payloadBytes[2:4]) @@ -1368,7 +1423,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { } else { logger.LogDebug(fmt.Sprintf("[Client] CSOTunDisconn on already-closed tun [%d:%d]", lport, rport)) } - } else if ctrlStatOp == CSOTunHangup { + case CSOTunHangup: // client side's lport has hung up lport := binary.BigEndian.Uint16(payloadBytes[0:2]) rport := binary.BigEndian.Uint16(payloadBytes[2:4]) @@ -1378,7 +1433,7 @@ func (hc Conn) Read(b []byte) (n int, err error) { } else { logger.LogDebug(fmt.Sprintf("[Server] CSOTunHangup to already-closed tun [%d:%d]", lport, rport)) } - } else if ctrlStatOp == CSOTunData { + case CSOTunData: lport := binary.BigEndian.Uint16(payloadBytes[0:2]) rport := binary.BigEndian.Uint16(payloadBytes[2:4]) //fmt.Printf("[Got CSOTunData: [lport %d:rport %d] data:%v\n", lport, rport, payloadBytes[4:]) @@ -1391,20 +1446,23 @@ func (hc Conn) Read(b []byte) (n int, err error) { } else { logger.LogDebug(fmt.Sprintf("[Attempt to write data to closed tun [%d:%d]", lport, rport)) } - } else if ctrlStatOp == CSOTunKeepAlive { + case CSOTunKeepAlive: // client side has sent keepalive for tunnels -- if client // dies or exits unexpectedly the absence of this will // let the server know to hang up on Dial()ed server rports. _ = binary.BigEndian.Uint16(payloadBytes[0:2]) //logger.LogDebug(fmt.Sprintf("[Server] Got CSOTunKeepAlive")) + // though CSOTunKeepAlive sends an endp (uint16), we don't use it, + // preferring to refresh *all* tunnels on the message. + // (?rlm 2023-11-04 -- TODO: verify this, it's been a while.) for _, t := range *hc.tuns { hc.Lock() t.KeepAlive = 0 hc.Unlock() } - } else if ctrlStatOp == CSONone { + case CSONone: hc.dBuf.Write(payloadBytes) - } else { + default: logger.LogDebug(fmt.Sprintf("[Unknown CSOType:%d]", ctrlStatOp)) } } @@ -1424,13 +1482,18 @@ func (hc Conn) Read(b []byte) (n int, err error) { // Write a byte slice // // See go doc io.Writer -func (hc Conn) Write(b []byte) (n int, err error) { +func (hc *Conn) Write(b []byte) (n int, err error) { + //logger.LogDebug("[+Write]") n, err = hc.WritePacket(b, CSONone) + //logger.LogDebug("[-Write]") return n, err } // Write a byte slice with specified ctrlStatOp byte func (hc *Conn) WritePacket(b []byte, ctrlStatOp byte) (n int, err error) { + hc.Lock() + defer hc.Unlock() + //log.Printf("[Encrypting...]\r\n") var hmacOut []uint8 var payloadLen uint32 @@ -1458,15 +1521,6 @@ func (hc *Conn) WritePacket(b []byte, ctrlStatOp byte) (n int, err error) { b = append([]byte{byte(padSide)}, append([]byte{byte(padLen)}, append(b, padBytes...)...)...) } - // N.B. Originally this Lock() surrounded only the - // calls to binary.Write(hc.c ..) however there appears - // to be some other unshareable state in the Conn - // struct that must be protected to serialize main and - // chaff data written to it. - // - // Would be nice to determine if the mutex scope - // could be tightened. - hc.Lock() payloadLen = uint32(len(b)) if hc.logPlainText { log.Printf(" >:ptext:\r\n%s\r\n", hex.Dump(b[0:payloadLen])) @@ -1524,7 +1578,6 @@ func (hc *Conn) WritePacket(b []byte, ctrlStatOp byte) (n int, err error) { } else { //fmt.Println("[a]WriteError!") } - hc.Unlock() if err != nil { log.Println(err) @@ -1539,53 +1592,180 @@ func (hc *Conn) WritePacket(b []byte, ctrlStatOp byte) (n int, err error) { return retN, err } -func (hc *Conn) EnableChaff() { +func (hc *Conn) StartupChaff() { hc.chaff.shutdown = false - hc.chaff.enabled = true log.Println("Chaffing ENABLED") hc.chaffHelper() } -func (hc *Conn) DisableChaff() { - hc.chaff.enabled = false - log.Println("Chaffing DISABLED") -} - func (hc *Conn) ShutdownChaff() { + hc.Lock() hc.chaff.shutdown = true + hc.Unlock() log.Println("Chaffing SHUTDOWN") } func (hc *Conn) SetupChaff(msecsMin uint, msecsMax uint, szMax uint) { + // Enforce bounds on chaff frequency and pkt size + hc.Lock() + if hc.chaff.msecsMin < CHAFF_FREQ_MSECS_MIN { + hc.chaff.msecsMin = CHAFF_FREQ_MSECS_MIN + } + if hc.chaff.msecsMax > CHAFF_FREQ_MSECS_MAX { + hc.chaff.msecsMax = CHAFF_FREQ_MSECS_MAX + } + hc.Unlock() + hc.chaff.msecsMin = msecsMin //move these to params of chaffHelper() ? hc.chaff.msecsMax = msecsMax hc.chaff.szMax = szMax } +func (hc *Conn) ShutdownRekey() { + hc.Lock() + hc.rekey = 0 + hc.Unlock() +} + +func (hc *Conn) RekeyHelper(intervalSecs uint) { + if intervalSecs < REKEY_SECS_MIN { + intervalSecs = REKEY_SECS_MIN + } + if intervalSecs > REKEY_SECS_MAX { + intervalSecs = REKEY_SECS_MAX + } + + go func() { + hc.Lock() + hc.rekey = intervalSecs + hc.Unlock() + + for { + hc.Lock() + rekey := hc.rekey + hc.Unlock() + + if rekey != 0 { + jitter := rand.Intn(int(rekey)) / 4 + rekey = rekey - uint(jitter) + if rekey < 1 { + rekey = 1 + } + + //logger.LogDebug(fmt.Sprintf("[rekeyHelper Loop]\n")) + time.Sleep(time.Duration(rekey) * time.Second) + + // Send rekey to other end + rekeyData := make([]byte, 64) + _, err := crand.Read(rekeyData) + //logger.LogDebug(fmt.Sprintf("[rekey [%02x %02x %02x ...]\n", + // rekeyData[0], rekeyData[1], rekeyData[2])) + //logger.LogDebug("[+rekeyHelper]") + _, err = hc.WritePacket(rekeyData, CSORekey) + hc.Lock() + if (hc.opts & CORemodulateShields) != 0 { + hc.cipheropts = getNewStreamAlgs(rekeyData[0], rekeyData[1]) + } + hc.w, hc.wm, err = hc.getStream(rekeyData) + //logger.LogDebug("[-rekeyHelper]") + hc.Unlock() + if err != nil { + log.Printf("[rekey WritePacket err! (%v) rekey dying ...]\n", err) + return + } + } else { + return + } + } + }() +} + // Helper routine to spawn a chaffing goroutine for each Conn func (hc *Conn) chaffHelper() { go func() { + var nextDuration int for { - var nextDuration int - if hc.chaff.enabled { + //logger.LogDebug(fmt.Sprintf("[chaffHelper Loop]\n")) + hc.Lock() + shutdown := hc.chaff.shutdown + hc.Unlock() + if !shutdown { var bufTmp []byte bufTmp = make([]byte, rand.Intn(int(hc.chaff.szMax))) min := int(hc.chaff.msecsMin) nextDuration = rand.Intn(int(hc.chaff.msecsMax)-min) + min _, _ = rand.Read(bufTmp) + //logger.LogDebug("[+chaffHelper]") _, err := hc.WritePacket(bufTmp, CSOChaff) + //logger.LogDebug("[-chaffHelper]") if err != nil { - log.Println("[ *** error - chaffHelper quitting *** ]") - hc.chaff.enabled = false + log.Println("[ *** error - chaffHelper shutting down *** ]") + hc.Lock() + hc.chaff.shutdown = true + hc.Unlock() break } - } - time.Sleep(time.Duration(nextDuration) * time.Millisecond) - if hc.chaff.shutdown { - log.Println("*** chaffHelper shutting down") + } else { + log.Println("[ *** chaffHelper shutting down *** ]") + break + } + time.Sleep(time.Duration(nextDuration) * time.Millisecond) + } + }() +} + +func (hc *Conn) StartupKeepAlive() { + hc.ResetKeepAlive() + log.Println("KeepAlive ENABLED") + hc.keepaliveHelper() +} + +func (hc *Conn) ShutdownKeepAlive() { + log.Println("Conn SHUTDOWN") + hc.Close() +} + +func (hc *Conn) ResetKeepAlive() { + hc.Lock() + hc.keepalive = 3 + hc.Unlock() + log.Println("KeepAlive RESET") +} + +// Helper routine to spawn a keepalive goroutine for each Conn +func (hc *Conn) keepaliveHelper() { + go func() { + for { + nextDuration := 10000 + bufTmp := []byte{0x55, 0xaa} + //logger.LogDebug("[+keepaliveHelper]") + _, err := hc.WritePacket(bufTmp, CSOKeepAlive) + //logger.LogDebug("[-keepaliveHelper]") + //logger.LogDebug(fmt.Sprintf("[keepalive]\n")) + if err != nil { + logger.LogDebug(fmt.Sprintf("[ *** error - keepaliveHelper quitting *** ]\n")) + break + } + time.Sleep(time.Duration(nextDuration) * time.Millisecond) + hc.Lock() + hc.keepalive -= 1 + hc.Unlock() + //logger.LogDebug(fmt.Sprintf("[keepAlive is now %d]\n", hc.keepalive)) + + //if rand.Intn(8) == 0 { + // hc.keepalive = 0 + //} + + if hc.keepalive == 0 { + logger.LogDebug(fmt.Sprintf("*** keepaliveHelper shutting down\n")) + hc.SetStatus(CSEConnDead) + hc.ShutdownKeepAlive() + if hc.Pproc != 0 { + //fmt.Printf("[pid %d needs to be killed]\n", hc.Pproc) + syscall.Kill(hc.Pproc, syscall.SIGABRT) //nolint:errcheck + } break } - } }() } diff --git a/xsnet/tun.go b/xsnet/tun.go index ac63047..ebddcae 100644 --- a/xsnet/tun.go +++ b/xsnet/tun.go @@ -37,6 +37,8 @@ type ( // client starts worker to receive/send data using lport // ... client disconnects: sends remhost [CSOTunClose:rport] // ... or server disconnects: sends client [CSOTunClose:lport] + // ... or server disconnects: due to client failing to send TunKeepAlive + // events for too long // server at any time sends [CSOTunRefused:rport] if daemon died // -- diff --git a/xspasswd/xspasswd.go b/xspasswd/xspasswd.go index 8cb41a9..ff18083 100644 --- a/xspasswd/xspasswd.go +++ b/xspasswd/xspasswd.go @@ -1,5 +1,5 @@ // Util to generate/store passwords for users in a file akin to /etc/passwd -// suitable for the demo hkexsh server, using bcrypt. +// suitable for the xs server, using bcrypt. // // Copyright (c) 2017-2020 Russell Magee // Licensed under the terms of the MIT license (see LICENSE.mit in this