From 52423b7144217a46d25eee542f9d4935bb6ccf97 Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Wed, 24 Jan 2018 18:14:21 -0800 Subject: [PATCH] Cleaned up some debug, moved insulter for failed login into project --- README.md | 60 ++++++++++++++++------------------ demo/hkexpasswd/hkexpasswd.go~ | 2 +- demo/server/server.go | 19 ++++++----- demo/spinsult/spinsult.go | 55 +++++++++++++++++++++++++++++++ demo/spinsult/spinsult_test.go | 52 +++++++++++++++++++++++++++++ herradurakex.go | 19 +++++++++++ hkexauth.go | 9 +++-- 7 files changed, 172 insertions(+), 44 deletions(-) create mode 100644 demo/spinsult/spinsult.go create mode 100644 demo/spinsult/spinsult_test.go diff --git a/README.md b/README.md index 29d6a45..ddf782c 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,6 @@ -/* Herradura - a Key exchange scheme in the style of Diffie-Hellman Key Exchange. - Copyright (C) 2017 Omar Alejandro Herrera Reyna - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - golang implementation by Russ Magee (rmagee_at_gmail.com) */ - --- - Package herradurakex is a drop-in replacement for golang/pkg/net facilities (net.Dial(), net.Listen(), net.Accept() and the net.Conn type) using the -experimental HerraduraKEx 'secure' key exchange algorithm, first released at +experimental HerraduraKEx key exchange algorithm, first released at (Omar Elejandro Herrera Reyna's github page)[github.com/Caume/HerraduraKEx]. One can simply replace calls to net.Dial() with hkex.Dial(), and likewise @@ -30,24 +10,40 @@ is initiated (whereby client and server independently derive the same keying material) and session algorithms to be used are exchanged allowing an encrypted channel between client and server. -NOTE: the terms 'secure' and 'securely' where used above are purposely -enclosed in singled quotes due to the experimental nature of the HerraduraKEx -algorithm used to derive crypto keying material on each end. -As of this time no verdict by acknowledged 'crypto experts' as to the true -security of the HerraduraKEx algorithm for purposes of session key exchange -over an insecure channel has been rendered. +NOTE: Due to the experimental nature of the HerraduraKEx algorithm used to +derive crypto keying material on each end, this algorithm and the +demonstration remote shell client/server programs should be used with caution. +As of this time (Jan 2018) no verdict by acknowledged 'crypto experts' as to +the true security of the HerraduraKEx algorithm for purposes of session key +exchange over an insecure channel has been rendered. It is hoped that such experts in the field will analyze the algorithm and determine if it is indeed a suitable one for use in situations where -Diffie-Hellman key exchange is currently utilized. +Diffie-Hellman and other key exchange algorithms are currently utilized. + +Within the demo/ tree are client and servers implementing a simplified, +ssh-like secure shell facility and a password-setting utility using its +own user/password file separate from the system /etc/passwd, which is +used by the server to authenticate clients. + +Dependencies: +github.com/mattn/go-isatty //terminal tty detection +github.com/kr/pty //unix pty control (server pty connections) +github.com/jameskeane/bcrypt //password storage/auth + To run -- $ go get /herradurakex.git $ cd $GOPATH/src//herradurakex $ go install . -$ cd demo/ -$ go build client.go && go build server.go +$ go build demo/client/client.go && go build demo/server/server.go +$ go build demo/hkexpasswd/hkexpasswd.go + +[To set accounts & passwords] +$ sudo echo "joebloggs:*:*:*" >/etc/hkex.passwd +$ sudo ./hkexpasswd -u joebloggs [ in separate shells ] -[A]$ ./server -[B]$ ./client +[A]$ ./server & +[B]$ ./client -u joebloggs + diff --git a/demo/hkexpasswd/hkexpasswd.go~ b/demo/hkexpasswd/hkexpasswd.go~ index 236ae64..60adb97 100644 --- a/demo/hkexpasswd/hkexpasswd.go~ +++ b/demo/hkexpasswd/hkexpasswd.go~ @@ -93,7 +93,7 @@ func main() { log.Fatal(err) } for i, _ := range records { - fmt.Println(records[i]) + //fmt.Println(records[i]) if records[i][0] == uname { records[i][1] = salt records[i][2] = hash diff --git a/demo/server/server.go b/demo/server/server.go index 3795a90..b8f05da 100644 --- a/demo/server/server.go +++ b/demo/server/server.go @@ -12,8 +12,9 @@ import ( "strings" "syscall" + "../spinsult" + hkex "blitter.com/herradurakex" - "blitter.com/spinsult" "github.com/kr/pty" ) @@ -167,7 +168,7 @@ func main() { fmt.Println("[Bad cmdSpec fmt]") return err } - fmt.Printf(" lens:%d %d %d %d\n", len1, len2, len3, len4) + //fmt.Printf(" lens:%d %d %d %d\n", len1, len2, len3, len4) rec.op = make([]byte, len1, len1) _, err = io.ReadFull(c, rec.op) @@ -196,8 +197,8 @@ func main() { return err } - fmt.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:%s]\n", - rec.op[0], string(rec.who), string(rec.cmd), string(rec.authCookie)) + log.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:****]\n", + rec.op[0], string(rec.who), string(rec.cmd)) valid, allowedCmds := hkex.AuthUser(string(rec.who), string(rec.authCookie), "/etc/hkexsh.passwd") if !valid { @@ -209,21 +210,21 @@ func main() { if rec.op[0] == 'c' { // Non-interactive command - fmt.Println("[Running command]") + log.Println("[Running command]") runShellAs(string(rec.who), string(rec.cmd), false, conn) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.op[0] = 0 - fmt.Println("[Command complete]") + log.Println("[Command complete]") } else if rec.op[0] == 's' { - fmt.Println("[Running shell]") + log.Println("[Running shell]") runShellAs(string(rec.who), string(rec.cmd), true, conn) // Returned hopefully via an EOF or exit/logout; // Clear current op so user can enter next, or EOF rec.op[0] = 0 - fmt.Println("[Exiting shell]") + log.Println("[Exiting shell]") } else { - fmt.Println("[Bad cmdSpec]") + log.Println("[Bad cmdSpec]") } return }(conn) diff --git a/demo/spinsult/spinsult.go b/demo/spinsult/spinsult.go new file mode 100644 index 0000000..8f9aafb --- /dev/null +++ b/demo/spinsult/spinsult.go @@ -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 +} diff --git a/demo/spinsult/spinsult_test.go b/demo/spinsult/spinsult_test.go new file mode 100644 index 0000000..8e75caf --- /dev/null +++ b/demo/spinsult/spinsult_test.go @@ -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! +} diff --git a/herradurakex.go b/herradurakex.go index 00c9db5..4961b02 100644 --- a/herradurakex.go +++ b/herradurakex.go @@ -7,6 +7,25 @@ // See README.md for full license info. package herradurakex +/* Herradura - a Key exchange scheme in the style of Diffie-Hellman Key Exchange. + Copyright (C) 2017 Omar Alejandro Herrera Reyna + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + golang implementation by Russ Magee (rmagee_at_gmail.com) */ + + /* This is the core KEx algorithm. For client/server net support code, See hkexnet.go for a golang/pkg/net for the compatible Conn interface using this to transparently negotiate keys and secure a network channel. */ diff --git a/hkexauth.go b/hkexauth.go index be431aa..2f6b4ef 100644 --- a/hkexauth.go +++ b/hkexauth.go @@ -16,7 +16,12 @@ import ( ) func AuthUser(username string, auth string, fname string) (valid bool, allowedCmds string) { - b, _ := ioutil.ReadFile(fname) + b, e := ioutil.ReadFile(fname) + if e != nil { + valid = false + fmt.Println("ERROR: Cannot read hkexsh.passwd file!") + log.Fatal(e) + } r := csv.NewReader(bytes.NewReader(b)) b = nil @@ -42,7 +47,7 @@ func AuthUser(username string, auth string, fname string) (valid bool, allowedCm break } - fmt.Println(record) + //fmt.Println(record) } return }