Compare commits

..

No commits in common. "master" and "v0.9.12-2" have entirely different histories.

17 changed files with 186 additions and 2599 deletions

50
LICENSE
View File

@ -1,37 +1,21 @@
MIT NON-AI License MIT License
Copyright (c) 2017 - 2026 Russell Magee (xs/xsd/xsnet/xspasswd) Copyright (c) 2017 - 2021 Russell Magee (xs/xsd/xsnet/xspasswd)
Permission is hereby granted, free of charge, to any person obtaining a copy of the software and associated documentation files (the "Software"), to deal in Permission is hereby granted, free of charge, to any person obtaining a copy
the Software without restriction, including without limitation the of this software and associated documentation files (the "Software"), to deal
rights to use, copy, modify, merge, publish, distribute, sublicense, in the Software without restriction, including without limitation the rights
and/or sell copies of the Software, and to permit persons to whom the to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Software is furnished to do so, subject to the following conditions. copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included The above copyright notice and this permission notice shall be included in all
in all copies or substantial portions of the Software. copies or substantial portions of the Software.
In addition, the following restrictions apply: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1. The Software and any modifications made to it may not be used for the FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
purpose of training or improving machine learning algorithms, including AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
but not limited to artificial intelligence, natural language processing, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
or data mining. This condition applies to any derivatives, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
modifications, or updates based on the Software code. Any usage of the SOFTWARE.
Software in an AI-training dataset is considered a breach of this License.
2. The Software may not be included in any dataset used for training or
improving machine learning algorithms, including but not limited to
artificial intelligence, natural language processing, or data mining.
3. Any person or organization found to be in violation of these
restrictions will be subject to legal action and may be held liable for
any damages resulting from such use.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,4 +1,4 @@
VERSION := 0.9.17 VERSION := 0.9.12
.PHONY: lint vis clean common client server passwd\ .PHONY: lint vis clean common client server passwd\
subpkgs install uninstall reinstall scc subpkgs install uninstall reinstall scc
@ -34,7 +34,7 @@ GIT_COMMIT := $(shell git rev-list -1 HEAD)
BUILDOPTS :=$(BUILDOPTS)"$(GOBUILDOPTS) -ldflags \"-X main.version=$(VERSION)$(MTAG)$(VTAG) -X main.gitCommit=$(GIT_COMMIT)\"" BUILDOPTS :=$(BUILDOPTS)"$(GOBUILDOPTS) -ldflags \"-X main.version=$(VERSION)$(MTAG)$(VTAG) -X main.gitCommit=$(GIT_COMMIT)\""
#endif #endif
SUBPKGS = logger xsnet SUBPKGS = logger spinsult xsnet
TOOLS = xs xsd TOOLS = xs xsd
SUBDIRS = $(LIBS) $(TOOLS) SUBDIRS = $(LIBS) $(TOOLS)

View File

@ -3,7 +3,6 @@
# XS # XS
![last build status](https://bacillus.blitter.com/onPush-xs-build/lastStatusIcon) ![last build status](https://bacillus.blitter.com/onPush-xs-build/lastStatusIcon)
![terminal screenshot on MSYS64](https://blitter.com/~russtopia/files/xs-msys64.png)
-- --
XS (**X**perimental **S**hell) is a simple alternative to ssh (<5% total SLOCC) written from scratch in Go. XS (**X**perimental **S**hell) is a simple alternative to ssh (<5% total SLOCC) written from scratch in Go.
@ -211,12 +210,6 @@ If no leading / is specified in src-or-dest-path, it is assumed to be relative t
remote user. File operations are all performed as the remote user, so account permissions apply remote user. File operations are all performed as the remote user, so account permissions apply
as expected. as expected.
When running under MSYS2, one must set the MINGW_ROOT environment variable to assist in
determining how to convert Windows paths to UNIX-style paths. This should be the installation path
of one's MSYS2 environment (eg., _C:/msys2_). Go's stdlib, under the hood, still uses Windows
style paths (drive letters and all) to locate other executables and _xc_ uses _tar_ as part of the copy
functionality.
Local (client) to remote (server) copy: Local (client) to remote (server) copy:
``` ```
$ xc fileA /some/where/fileB /some/where/else/dirC joebloggs@host-or-ip:remoteDir $ xc fileA /some/where/fileB /some/where/else/dirC joebloggs@host-or-ip:remoteDir

29
auth.go
View File

@ -2,7 +2,7 @@ package xs
// Package xs - a secure terminal client/server written from scratch in Go // Package xs - a secure terminal client/server written from scratch in Go
// //
// Copyright (c) 2017-2025 Russell Magee // Copyright (c) 2017-2020 Russell Magee
// Licensed under the terms of the MIT license (see LICENSE.mit in this // Licensed under the terms of the MIT license (see LICENSE.mit in this
// distribution) // distribution)
// //
@ -215,39 +215,18 @@ func AuthUserByToken(ctx *AuthCtx, username string, connhostname string, auth st
return return
} }
func GroomFsPath(path string) (ret string) {
pathRoot := os.Getenv("MINGW_ROOT")
if pathRoot != "" {
ret = path[len(pathRoot):]
ret = strings.ReplaceAll(ret, "\\", "/")
} else {
ret = path
}
//fmt.Printf("groomed fspath:%v\n", ret)
return
}
func GetTool(tool string) (ret string) { func GetTool(tool string) (ret string) {
cmdSuffix := "" ret = "/bin/" + tool
pathRoot := os.Getenv("MINGW_ROOT")
if pathRoot != "" {
cmdSuffix = ".exe"
}
//fmt.Printf("pathRoot:%v cmdSuffix:%v\n", pathRoot, cmdSuffix)
ret = pathRoot + "/bin/" + tool + cmdSuffix
_, err := os.Stat(ret) _, err := os.Stat(ret)
if err == nil { if err == nil {
return ret return ret
} }
ret = pathRoot + "/usr/bin/" + tool + cmdSuffix ret = "/usr/bin/" + tool
_, err = os.Stat(ret) _, err = os.Stat(ret)
if err == nil { if err == nil {
return ret return ret
} }
ret = pathRoot + "/usr/local/bin/" + tool + cmdSuffix ret = "/usr/local/bin/" + tool
_, err = os.Stat(ret) _, err = os.Stat(ret)
if err == nil { if err == nil {
return ret return ret

View File

@ -25,15 +25,8 @@ echo "Building most recent push on branch $branch"
git checkout "$branch" git checkout "$branch"
ls ls
#!############ go mod init
#!stage "GoMod" go mod tidy
#!############
#!go clean -modcache
#!
#!rm -f go.{mod,sum}
#!go mod init blitter.com/go/xs
#!go mod tidy
#!echo "---"
############ ############
stage "Build" stage "Build"
@ -42,19 +35,16 @@ echo "Invoking 'make clean' ..."
make clean make clean
echo "Invoking 'make all' ..." echo "Invoking 'make all' ..."
make all make all
echo "---"
############ ############
stage "Lint" stage "Lint"
############ ############
make lint make lint
echo "---"
############ ############
stage "UnitTests" stage "UnitTests"
############ ############
go test -v . go test -v .
echo "---"
############ ############
stage "Test(Authtoken)" stage "Test(Authtoken)"
@ -74,7 +64,6 @@ else
echo "client cmd performed OK." echo "client cmd performed OK."
unset tokentest unset tokentest
fi fi
echo "---"
############ ############
stage "Test(xc S->C)" stage "Test(xc S->C)"
@ -99,7 +88,6 @@ else
echo "FAILED!" echo "FAILED!"
exit $stat exit $stat
fi fi
echo "---"
############ ############
stage "Test(xc C->S)" stage "Test(xc C->S)"
@ -110,14 +98,12 @@ if [ -f ~/.config/xs/.xs_id.bak ]; then
echo "Restoring test user $USER .xs_id file ..." echo "Restoring test user $USER .xs_id file ..."
mv ~/.config/xs/.xs_id.bak ~/.config/xs/.xs_id mv ~/.config/xs/.xs_id.bak ~/.config/xs/.xs_id
fi fi
echo "---"
############ ############
stage "Artifacts" stage "Artifacts"
############ ############
echo -n "Creating tarfile ..." echo -n "Creating tarfile ..."
tar -cz --exclude=.git --exclude=cptest -f ${BACILLUS_ARTFDIR}/xs.tgz . tar -cz --exclude=.git --exclude=cptest -f ${BACILLUS_ARTFDIR}/xs.tgz .
echo "---"
############ ############
stage "Cleanup" stage "Cleanup"

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// Package xs - a secure terminal client/server written from scratch in Go // Package xs - a secure terminal client/server written from scratch in Go
// //
// Copyright (c) 2017-2025 Russell Magee // Copyright (c) 2017-2020 Russell Magee
// Licensed under the terms of the MIT license (see LICENSE.mit in this // Licensed under the terms of the MIT license (see LICENSE.mit in this
// distribution) // distribution)
// //

37
go.mod
View File

@ -1,37 +0,0 @@
module blitter.com/go/xs
go 1.24.0
require (
blitter.com/go/cryptmt v1.0.3
blitter.com/go/goutmp v1.0.6
blitter.com/go/herradurakex v1.0.1
blitter.com/go/hopscotch v0.3.0
blitter.com/go/kyber v1.0.0
blitter.com/go/newhope v1.0.0
blitter.com/go/spinsult v0.0.0-20260224023031-2afae6bbe758
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da
github.com/creack/pty v1.1.24
github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004
github.com/kuking/go-frodokem v1.0.2
github.com/mattn/go-isatty v0.0.20
github.com/xtaci/kcp-go v4.3.4+incompatible
golang.org/x/crypto v0.48.0
golang.org/x/sys v0.41.0
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.2 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/klauspost/reedsolomon v1.13.2 // 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
golang.org/x/net v0.49.0 // indirect
gopkg.in/hlandau/easymetric.v1 v1.0.0 // indirect
gopkg.in/hlandau/measurable.v1 v1.0.1 // indirect
)

144
go.sum
View File

@ -1,144 +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.3 h1:C1j55/TV8301jROxn83Zlm+qNH3/XUSzBoTrbBGD8gw=
blitter.com/go/cryptmt v1.0.3/go.mod h1:otZPP0Vps15DRZNo2zD4RLym+IT6XnbtI1HS412BxHM=
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.1 h1:7smv+RiG6PQ2hHebT/uSjIKcisp/lx5PSCBn8fISHWA=
blitter.com/go/herradurakex v1.0.1/go.mod h1:m3+vYZX+2dDjdo+n/HDnXEYJX9pwmNeQLgAfJM8mtxw=
blitter.com/go/hopscotch v0.3.0 h1:IaPdMXyZ1mjU6UHzMiWgu1PF8/5r7ElVTeTLliWqxbw=
blitter.com/go/hopscotch v0.3.0/go.mod h1:hCz7oE31KjaO9M6+s2DcyVNlAA8saE/AaVYKFs7hl1I=
blitter.com/go/kyber v1.0.0 h1:xniqw15FUrmR1bTqwH57cIZ0Ko2kYcINnSRE3ESzA9M=
blitter.com/go/kyber v1.0.0/go.mod h1:xE277hhExsmBIaVT7oFgNfkXC3ioHaZCTreNJHSCwqw=
blitter.com/go/mtwist v1.0.2 h1:4zmpKNynrRuFF8JAPdhBN8TaJB+quU5d2i7KBgFtVng=
blitter.com/go/mtwist v1.0.2/go.mod h1:Y/0x0EsFMUKK1+tdkoCW7H88eF7CTOycUMsTHcfCoZE=
blitter.com/go/newhope v1.0.0 h1:oUn35Ei30AGmLeqjNIG6DA7YNaK7fncBx4ptTnNrzmo=
blitter.com/go/newhope v1.0.0/go.mod h1:ywoxfDBqInPsqtnxYsmS4SYMJ5D/kNcrFgpvI+Xcun0=
blitter.com/go/spinsult v0.0.0-20260224023031-2afae6bbe758 h1:6CYxkKMXehsanwg0/G4q1K/+M+pYhfcv49ngfsmLtyk=
blitter.com/go/spinsult v0.0.0-20260224023031-2afae6bbe758/go.mod h1:/EchWRYRoJvzxpR6Pt6tSpQ9X4bjhF4BOppXYsZa16I=
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.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/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/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004 h1:G+9t9cEtnC9jFiTxyptEKuNIAbiN5ZCQzX2a74lj3xg=
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004/go.mod h1:KmHnJWQrgEvbuy0vcvj00gtMqbvNn1L+3YUZLK/B92c=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/reedsolomon v1.13.2 h1:9qtQy2tKEVpVB8Pfq87ZljHZb60/LbeTQ1OxV8EGzdE=
github.com/klauspost/reedsolomon v1.13.2/go.mod h1:ggJT9lc71Vu+cSOPBlxGvBN6TfAS77qB4fp8vJ05NSA=
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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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 v4.3.4+incompatible h1:T56s9GLhx+KZUn5T8aO2Didfa4uTYvjeVIRLt6uYdhE=
github.com/xtaci/kcp-go v4.3.4+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
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-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.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
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.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
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/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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=

View File

@ -2,7 +2,7 @@ package xs
// Package xs - a secure terminal client/server written from scratch in Go // Package xs - a secure terminal client/server written from scratch in Go
// //
// Copyright (c) 2017-2025 Russell Magee // Copyright (c) 2017-2020 Russell Magee
// Licensed under the terms of the MIT license (see LICENSE.mit in this // Licensed under the terms of the MIT license (see LICENSE.mit in this
// distribution) // distribution)
// //

24
spinsult/Makefile Normal file
View File

@ -0,0 +1,24 @@
.PHONY: info clean lib
ifeq ($(GARBLE),y)
GO = garble -literals -tiny -debugdir=garbled
else
GO = go
endif
all: lib
clean:
go clean .
lib: info
$(GO) build .
go install .
ifneq ($(MSYSTEM),)
info:
@echo "Building for Windows (MSYS)"
else
info:
@echo "Building for Linux"
endif

55
spinsult/spinsult.go Normal file
View File

@ -0,0 +1,55 @@
// A golang translation of a 'Shakespeare insult generator'
// Originally from http://www.mainstrike.com/mstservices/handy/insult.html
package spinsult
import (
"math/rand"
"time"
)
var (
r *rand.Rand
phrase1 = [...]string{
"artless", "bawdy", "beslubbering", "bootless", "churlish", "clouted",
"cockered", "craven", "currish", "dankish", "dissembling", "droning", "errant", "fawning",
"fobbing", "frothy", "froward", "gleeking", "goatish", "gorbellied", "impertinent",
"infectious", "jarring", "loggerheaded", "lumpish", "mammering", "mangled", "mewling",
"paunchy", "pribbling", "puking", "puny", "qualling", "rank", "reeky", "roguish", "ruttish",
"saucy", "spleeny", "spongy", "surly", "tottering", "unmuzzled", "vain", "venomed",
"villainous", "warped", "wayward", "weedy", "yeasty"}
phrase2 = [...]string{"base-court", "bat-fowling", "beef-witted", "beetle-headed",
"boil-brained", "clapper-clawed", "clay-brained", "common-kissing", "crook-pated",
"dismal-dreaming", "dizzy-eyed", "doghearted", "dread-bolted", "earth-vexing",
"elf-skinned", "fat-kidneyed", "fen-sucked", "flap-mouthed", "fly-bitten",
"folly-fallen", "fool-born", "full-gorged", "guts-griping", "half-faced", "hasty-witted",
"hedge-born", "hell-hated", "idle-headed", "ill-breeding", "ill-nurtured", "knotty-pated",
"milk-livered", "motley-minded", "onion-eyed", "plume-plucked", "pottle-deep",
"pox-marked", "reeling-ripe", "rough-hewn", "rude-growing", "rump-fed", "shard-borne",
"sheep-biting", "spur-galled", "swag-bellied", "tardy-gaited", "tickle-brained",
"toad-spotted", "urchin-snouted", "weather-bitten"}
phrase3 = [...]string{"apple-john", "baggage", "barnacle", "bladder", "boar-pig", "bugbear",
"bum-bailey", "canker-blossom", "clack-dish", "clotpole", "codpiece", "coxcomb", "death-token",
"dewberry", "flap-dragon", "flax-wench", "flirt-gill", "foot-licker", "fustilarian",
"giglet", "gudgeon", "haggard", "harpy", "hedge-pig", "horn-beast", "hugger-mugger",
"joithead", "lewdster", "lout", "maggot-pie", "malt-worm", "mammet", "measle", "minnow",
"miscreant", "moldwarp", "mumble-news", "nut-hook", "pigeon-egg", "pignut", "pumpion",
"puttock", "ratsbane", "scut", "skainsmate", "strumpet", "varlet", "vassal", "wagtail",
"whey-face"}
)
func GetSentence() (ret string) {
return "Thou " + Get()
}
func Get() (ret string) {
if r == nil {
r = rand.New(rand.NewSource(time.Now().UnixNano()))
}
ret = phrase1[r.Int()%len(phrase1)] + " " +
phrase2[r.Int()%len(phrase2)] + " " +
phrase3[r.Int()%len(phrase3)] + "!"
return
}

52
spinsult/spinsult_test.go Normal file
View File

@ -0,0 +1,52 @@
//To show coverage for tests:
//
//1. go test -coverprofile=cov.out
//2. go tool cover -func=cov.out
//3. go tool cover -html=cov.out
//4. Profit!!
//
// For heatmap coverage, change step 1 to:
//2. go test -covermode=count -coverprofile=cov.out
//
// ref: https://blog.golang.org/cover
package spinsult
import (
"fmt"
"math/rand"
"testing"
)
func Test1Get(t *testing.T) {
//if testing.Short() {
// t.Skip("skipping test in short mode.")
//}
r = rand.New(rand.NewSource(42))
out := Get()
if out != "mammering doghearted codpiece!" {
t.Fail()
}
}
func Test2Get(t *testing.T) {
//if testing.Short() {
// t.Skip("skipping test in short mode.")
//}
out := Get()
if out != "dankish common-kissing coxcomb!" {
t.Fail()
}
out = GetSentence()
if out != "Thou wayward crook-pated fustilarian!" {
t.Fail()
}
}
// Example of calling Get() for a random insult.
func ExampleGet() {
r = rand.New(rand.NewSource(42))
out := GetSentence()
fmt.Println(out)
//Output: Thou mammering doghearted codpiece!
}

View File

@ -1,6 +1,6 @@
// xs client // xs client
// //
// Copyright (c) 2017-2025 Russell Magee // Copyright (c) 2017-2020 Russell Magee
// Licensed under the terms of the MIT license (see LICENSE.mit in this // Licensed under the terms of the MIT license (see LICENSE.mit in this
// distribution) // distribution)
// //
@ -33,7 +33,7 @@ import (
xs "blitter.com/go/xs" xs "blitter.com/go/xs"
"blitter.com/go/xs/logger" "blitter.com/go/xs/logger"
"blitter.com/go/spinsult" "blitter.com/go/xs/spinsult"
"blitter.com/go/xs/xsnet" "blitter.com/go/xs/xsnet"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
//isatty "github.com/mattn/go-isatty" //isatty "github.com/mattn/go-isatty"
@ -294,14 +294,7 @@ func buildCmdLocalToRemote(copyQuiet bool, copyLimitBPS uint, files string) (cap
captureStderr = true captureStderr = true
cmd = xs.GetTool("tar") cmd = xs.GetTool("tar")
//fmt.Printf("GetTool found cmd:%v\n", cmd) args = []string{"-cz", "-f", "/dev/stdout"}
/* Explicit -f /dev/stdout doesn't work in MINGW/MSYS64
* as '/dev/stdout' doesn't actually appear in the /dev/ filesystem...?
* And it appears not to actually be required as without -f stdout is
* implied. -rlm 2025-12-07
*/
//args = []string{"-cz", "-f", "/dev/stdout"}
args = []string{"-cz"}
files = strings.TrimSpace(files) files = strings.TrimSpace(files)
// Awesome fact: tar actually can take multiple -C args, and // Awesome fact: tar actually can take multiple -C args, and
// changes to the dest dir *as it sees each one*. This enables // changes to the dest dir *as it sees each one*. This enables
@ -317,7 +310,6 @@ func buildCmdLocalToRemote(copyQuiet bool, copyLimitBPS uint, files string) (cap
// remote destDir. // remote destDir.
for _, v := range strings.Split(files, " ") { for _, v := range strings.Split(files, " ") {
v, _ = filepath.Abs(v) // #nosec v, _ = filepath.Abs(v) // #nosec
v = xs.GroomFsPath(v)
dirTmp, fileTmp := path.Split(v) dirTmp, fileTmp := path.Split(v)
if dirTmp == "" { if dirTmp == "" {
args = append(args, fileTmp) args = append(args, fileTmp)
@ -330,8 +322,7 @@ func buildCmdLocalToRemote(copyQuiet bool, copyLimitBPS uint, files string) (cap
bandwidthInBytesPerSec := " -L " + fmt.Sprintf("%d", copyLimitBPS) bandwidthInBytesPerSec := " -L " + fmt.Sprintf("%d", copyLimitBPS)
displayOpts := " -pre " //nolint:goconst,nolintlint displayOpts := " -pre " //nolint:goconst,nolintlint
cmd = xs.GetTool("bash") cmd = xs.GetTool("bash")
//args = []string{"-c", xs.GetTool("tar") + " -cz -f /dev/stdout "} args = []string{"-c", xs.GetTool("tar") + " -cz -f /dev/stdout "}
args = []string{"-c", xs.GetTool("tar") + " -cz "}
files = strings.TrimSpace(files) files = strings.TrimSpace(files)
// Awesome fact: tar actually can take multiple -C args, and // Awesome fact: tar actually can take multiple -C args, and
// changes to the dest dir *as it sees each one*. This enables // changes to the dest dir *as it sees each one*. This enables
@ -347,7 +338,6 @@ func buildCmdLocalToRemote(copyQuiet bool, copyLimitBPS uint, files string) (cap
// remote destDir. // remote destDir.
for _, v := range strings.Split(files, " ") { for _, v := range strings.Split(files, " ") {
v, _ = filepath.Abs(v) // #nosec v, _ = filepath.Abs(v) // #nosec
v = xs.GroomFsPath(v)
dirTmp, fileTmp := path.Split(v) dirTmp, fileTmp := path.Split(v)
if dirTmp == "" { if dirTmp == "" {
args[1] = args[1] + fileTmp + " " args[1] = args[1] + fileTmp + " "
@ -396,8 +386,6 @@ func doCopyMode(conn *xsnet.Conn, remoteDest bool, files string, copyQuiet bool,
c.Stderr = os.Stderr c.Stderr = os.Stderr
} }
//fmt.Printf("cmd:%v args:%v\n", cmdName, cmdArgs)
// Start the command (no pty) // Start the command (no pty)
err = c.Start() // returns immediately err = c.Start() // returns immediately
///////////// /////////////
@ -600,7 +588,7 @@ func usageCp() {
// //
// TODO: do this from the server side and have client just emit that // TODO: do this from the server side and have client just emit that
func rejectUserMsg() string { func rejectUserMsg() string {
return "Begone, thou " + spinsult.Get() + "!\r\n" return "Begone, " + spinsult.GetSentence() + "\r\n"
} }
// Transmit request to server for it to set up the remote end of a tunnel // Transmit request to server for it to set up the remote end of a tunnel
@ -626,12 +614,6 @@ func parseNonSwitchArgs(a []string) (user, host, path string, isDest bool, other
// Whether fancyArg is src or dst file depends on flag.Args() index; // Whether fancyArg is src or dst file depends on flag.Args() index;
// fancyArg as last flag.Args() element denotes dstFile // fancyArg as last flag.Args() element denotes dstFile
// fancyArg as not-last flag.Args() element denotes srcFile // fancyArg as not-last flag.Args() element denotes srcFile
/* rlm:2025-12-10 This breaks if srcPath is outside of MSYS2 tree, as srcPath
appears to silently be converted to an absolute winpath eg.,
/c/users/RM/... -> C:/users/RM/...
and the colon (:) in this breaks the logic below.
*/
var fancyUser, fancyHost, fancyPath string var fancyUser, fancyHost, fancyPath string
for i, arg := range a { for i, arg := range a {
if strings.Contains(arg, ":") || strings.Contains(arg, "@") { if strings.Contains(arg, ":") || strings.Contains(arg, "@") {
@ -1052,8 +1034,7 @@ func main() { //nolint: funlen, gocyclo
// === Terminal mode adjustment for session // === Terminal mode adjustment for session
if shellMode { if shellMode {
if isatty.IsTerminal(os.Stdin.Fd()) || if isatty.IsTerminal(os.Stdin.Fd()) {
isatty.IsCygwinTerminal(os.Stdin.Fd()) {
oldState, err = xs.MakeRaw(os.Stdin) oldState, err = xs.MakeRaw(os.Stdin)
if err != nil { if err != nil {
panic(err) panic(err)
@ -1097,6 +1078,10 @@ func main() { //nolint: funlen, gocyclo
fmt.Fprintln(os.Stderr, rejectUserMsg()) fmt.Fprintln(os.Stderr, rejectUserMsg())
rec.SetStatus(GeneralProtocolErr) rec.SetStatus(GeneralProtocolErr)
} else { } else {
// === Set up connection keepalive to server
conn.StartupKeepAlive() // goroutine, returns immediately
defer conn.ShutdownKeepAlive()
// === Set up chaffing to server // === Set up chaffing to server
conn.SetupChaff(chaffFreqMin, chaffFreqMax, chaffBytesMax) // enable client->server chaffing conn.SetupChaff(chaffFreqMin, chaffFreqMax, chaffBytesMax) // enable client->server chaffing
if chaffEnabled { if chaffEnabled {
@ -1127,10 +1112,6 @@ func main() { //nolint: funlen, gocyclo
// === Session entry (shellMode or copyMode) // === Session entry (shellMode or copyMode)
if shellMode { if shellMode {
// === Set up connection keepalive to server
conn.StartupKeepAlive() // goroutine, returns immediately
defer conn.ShutdownKeepAlive()
// === (shell) launch tunnels // === (shell) launch tunnels
launchTuns(&conn /*remoteHost,*/, tunSpecStr) launchTuns(&conn /*remoteHost,*/, tunSpecStr)
doShellMode(isInteractive, &conn, oldState, rec) doShellMode(isInteractive, &conn, oldState, rec)

View File

@ -1,6 +1,6 @@
// xsd server // xsd server
// //
// Copyright (c) 2017-2025 Russell Magee // Copyright (c) 2017-2020 Russell Magee
// Licensed under the terms of the MIT license (see LICENSE.mit in this // Licensed under the terms of the MIT license (see LICENSE.mit in this
// distribution) // distribution)
// //
@ -121,6 +121,10 @@ func runClientToServerCopyAs(who, ttype string, conn *xsnet.Conn, fpath string,
c.Stdout = os.Stdout c.Stdout = os.Stdout
c.Stderr = os.Stderr c.Stderr = os.Stderr
// === Set up connection keepalive to client
conn.StartupKeepAlive() // goroutine, returns immediately
defer conn.ShutdownKeepAlive()
if chaffing { if chaffing {
conn.StartupChaff() conn.StartupChaff()
} }
@ -217,6 +221,10 @@ func runServerToClientCopyAs(who, ttype string, conn *xsnet.Conn, srcPath string
c.Stderr = stdErrBuffer c.Stderr = stdErrBuffer
//c.Stderr = nil //c.Stderr = nil
// === Set up connection keepalive to client
conn.StartupKeepAlive() // goroutine, returns immediately
defer conn.ShutdownKeepAlive()
if chaffing { if chaffing {
conn.StartupChaff() conn.StartupChaff()
} }
@ -372,11 +380,11 @@ func runShellAs(who, hname, ttype, cmd string, interactive bool, //nolint:funlen
if chaffing { if chaffing {
conn.StartupChaff() conn.StartupChaff()
// #gv:s/label=\"runShellAs\$4\"/label=\"deferChaffShutdown\"/
defer func() {
conn.ShutdownChaff()
}()
} }
// #gv:s/label=\"runShellAs\$4\"/label=\"deferChaffShutdown\"/
defer func() {
conn.ShutdownChaff()
}()
// ..and the pty to stdout. // ..and the pty to stdout.
// This may take some time exceeding that of the // This may take some time exceeding that of the

View File

@ -22,11 +22,11 @@ import (
"blitter.com/go/cryptmt" "blitter.com/go/cryptmt"
"blitter.com/go/hopscotch" "blitter.com/go/hopscotch"
"blitter.com/go/xs/logger"
"github.com/aead/chacha20/chacha" "github.com/aead/chacha20/chacha"
whirlpool "github.com/jzelinskie/whirlpool"
"golang.org/x/crypto/blowfish" "golang.org/x/crypto/blowfish"
"golang.org/x/crypto/twofish" "golang.org/x/crypto/twofish"
whirlpool "github.com/jzelinskie/whirlpool"
// hash algos must be manually imported thusly: // hash algos must be manually imported thusly:
// (Would be nice if the golang pkg docs were more clear // (Would be nice if the golang pkg docs were more clear
// on this...) // on this...)
@ -64,7 +64,8 @@ func getNewStreamAlgs(cb uint8, hb uint8) (config uint32) {
// the input rekeying data // the input rekeying data
c := (cb % CAlgNoneDisallowed) c := (cb % CAlgNoneDisallowed)
h := (hb % HmacNoneDisallowed) h := (hb % HmacNoneDisallowed)
config = uint32(h)<<8 | uint32(c) config = uint32(h<<8) | uint32(c)
logger.LogDebug(fmt.Sprintf("[Chose new algs [%d:%d]", h, c))
return return
} }

View File

@ -1,7 +1,7 @@
// Util to generate/store passwords for users in a file akin to /etc/passwd // Util to generate/store passwords for users in a file akin to /etc/passwd
// suitable for the xs server, using bcrypt. // suitable for the xs server, using bcrypt.
// //
// Copyright (c) 2017-2025 Russell Magee // Copyright (c) 2017-2020 Russell Magee
// Licensed under the terms of the MIT license (see LICENSE.mit in this // Licensed under the terms of the MIT license (see LICENSE.mit in this
// distribution) // distribution)
// //