Cleaned up some debug, moved insulter for failed login into project

This commit is contained in:
Russ Magee 2018-01-24 18:14:21 -08:00
parent d484ec7fd1
commit 52423b7144
7 changed files with 172 additions and 44 deletions

View file

@ -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 <https://www.gnu.org/licenses/>.
golang implementation by Russ Magee (rmagee_at_gmail.com) */
--
Package herradurakex is a drop-in replacement for golang/pkg/net facilities 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 (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]. (Omar Elejandro Herrera Reyna's github page)[github.com/Caume/HerraduraKEx].
One can simply replace calls to net.Dial() with hkex.Dial(), and likewise 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 keying material) and session algorithms to be used are exchanged allowing an
encrypted channel between client and server. encrypted channel between client and server.
NOTE: the terms 'secure' and 'securely' where used above are purposely NOTE: Due to the experimental nature of the HerraduraKEx algorithm used to
enclosed in singled quotes due to the experimental nature of the HerraduraKEx derive crypto keying material on each end, this algorithm and the
algorithm used to derive crypto keying material on each end. demonstration remote shell client/server programs should be used with caution.
As of this time no verdict by acknowledged 'crypto experts' as to the true As of this time (Jan 2018) no verdict by acknowledged 'crypto experts' as to
security of the HerraduraKEx algorithm for purposes of session key exchange the true security of the HerraduraKEx algorithm for purposes of session key
over an insecure channel has been rendered. exchange over an insecure channel has been rendered.
It is hoped that such experts in the field will analyze the algorithm and 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 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 To run
-- --
$ go get <tbd>/herradurakex.git $ go get <tbd>/herradurakex.git
$ cd $GOPATH/src/<tbd>/herradurakex $ cd $GOPATH/src/<tbd>/herradurakex
$ go install . $ go install .
$ cd demo/ $ go build demo/client/client.go && go build demo/server/server.go
$ go build client.go && go build 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 ] [ in separate shells ]
[A]$ ./server [A]$ ./server &
[B]$ ./client [B]$ ./client -u joebloggs

View file

@ -93,7 +93,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
for i, _ := range records { for i, _ := range records {
fmt.Println(records[i]) //fmt.Println(records[i])
if records[i][0] == uname { if records[i][0] == uname {
records[i][1] = salt records[i][1] = salt
records[i][2] = hash records[i][2] = hash

View file

@ -12,8 +12,9 @@ import (
"strings" "strings"
"syscall" "syscall"
"../spinsult"
hkex "blitter.com/herradurakex" hkex "blitter.com/herradurakex"
"blitter.com/spinsult"
"github.com/kr/pty" "github.com/kr/pty"
) )
@ -167,7 +168,7 @@ func main() {
fmt.Println("[Bad cmdSpec fmt]") fmt.Println("[Bad cmdSpec fmt]")
return err 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) rec.op = make([]byte, len1, len1)
_, err = io.ReadFull(c, rec.op) _, err = io.ReadFull(c, rec.op)
@ -196,8 +197,8 @@ func main() {
return err return err
} }
fmt.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:%s]\n", log.Printf("[cmdSpec: op:%c who:%s cmd:%s auth:****]\n",
rec.op[0], string(rec.who), string(rec.cmd), string(rec.authCookie)) rec.op[0], string(rec.who), string(rec.cmd))
valid, allowedCmds := hkex.AuthUser(string(rec.who), string(rec.authCookie), "/etc/hkexsh.passwd") valid, allowedCmds := hkex.AuthUser(string(rec.who), string(rec.authCookie), "/etc/hkexsh.passwd")
if !valid { if !valid {
@ -209,21 +210,21 @@ func main() {
if rec.op[0] == 'c' { if rec.op[0] == 'c' {
// Non-interactive command // Non-interactive command
fmt.Println("[Running command]") log.Println("[Running command]")
runShellAs(string(rec.who), string(rec.cmd), false, conn) runShellAs(string(rec.who), string(rec.cmd), false, conn)
// Returned hopefully via an EOF or exit/logout; // Returned hopefully via an EOF or exit/logout;
// Clear current op so user can enter next, or EOF // Clear current op so user can enter next, or EOF
rec.op[0] = 0 rec.op[0] = 0
fmt.Println("[Command complete]") log.Println("[Command complete]")
} else if rec.op[0] == 's' { } else if rec.op[0] == 's' {
fmt.Println("[Running shell]") log.Println("[Running shell]")
runShellAs(string(rec.who), string(rec.cmd), true, conn) runShellAs(string(rec.who), string(rec.cmd), true, conn)
// Returned hopefully via an EOF or exit/logout; // Returned hopefully via an EOF or exit/logout;
// Clear current op so user can enter next, or EOF // Clear current op so user can enter next, or EOF
rec.op[0] = 0 rec.op[0] = 0
fmt.Println("[Exiting shell]") log.Println("[Exiting shell]")
} else { } else {
fmt.Println("[Bad cmdSpec]") log.Println("[Bad cmdSpec]")
} }
return return
}(conn) }(conn)

55
demo/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
}

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

@ -7,6 +7,25 @@
// See README.md for full license info. // See README.md for full license info.
package herradurakex 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 <https://www.gnu.org/licenses/>.
golang implementation by Russ Magee (rmagee_at_gmail.com) */
/* This is the core KEx algorithm. For client/server net support code, /* 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 See hkexnet.go for a golang/pkg/net for the compatible Conn interface
using this to transparently negotiate keys and secure a network channel. */ using this to transparently negotiate keys and secure a network channel. */

View file

@ -16,7 +16,12 @@ import (
) )
func AuthUser(username string, auth string, fname string) (valid bool, allowedCmds string) { 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)) r := csv.NewReader(bytes.NewReader(b))
b = nil b = nil
@ -42,7 +47,7 @@ func AuthUser(username string, auth string, fname string) (valid bool, allowedCm
break break
} }
fmt.Println(record) //fmt.Println(record)
} }
return return
} }