Minor cleanups and one bugfix:
* bugfix: use os.IsNotExist() instead of comparing errors for equality; this fixes incorrect handling of missing authorized_keys file. * move die() and warn() into die.go - and make them public functions. * teach die.go to also provide atexit() like functionality * teach all callers of sign.SafeFile{} to use AtExit() to delete temporary artifacts * symbol renaming: die->Die, warn->Warn.
This commit is contained in:
parent
42bbe5ddeb
commit
0ddf48c92f
5 changed files with 126 additions and 75 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -24,12 +24,11 @@ _testmain.go
|
|||
*.prof
|
||||
vendor/*
|
||||
|
||||
# vendor management
|
||||
vendor/src/*
|
||||
vendor/pkg/*
|
||||
bin/*
|
||||
sigtool
|
||||
|
||||
.??*.sw?
|
||||
*.pub
|
||||
*.key
|
||||
*.sig
|
||||
|
||||
|
|
81
crypt.go
81
crypt.go
|
@ -48,7 +48,7 @@ func encrypt(args []string) {
|
|||
|
||||
err := fs.Parse(args)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
var pws, infile string
|
||||
|
@ -64,19 +64,19 @@ func encrypt(args []string) {
|
|||
} else {
|
||||
pws, err = utils.Askpass("Enter passphrase for private key", false)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
return []byte(pws), nil
|
||||
})
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
args = fs.Args()
|
||||
if len(args) < 2 {
|
||||
die("Insufficient args. Try '%s --help'", os.Args[0])
|
||||
Die("Insufficient args. Try '%s --help'", os.Args[0])
|
||||
}
|
||||
|
||||
var infd io.Reader = os.Stdin
|
||||
|
@ -96,14 +96,14 @@ func encrypt(args []string) {
|
|||
// Lets try to read the authorized files
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
die("can't find homedir for this user")
|
||||
Die("can't find homedir for this user")
|
||||
}
|
||||
|
||||
authkeys := fmt.Sprintf("%s/.ssh/authorized_keys", home)
|
||||
authdata, err := ioutil.ReadFile(authkeys)
|
||||
if err != nil {
|
||||
if err != os.ErrNotExist {
|
||||
die("can't open %s: %s", authkeys, err)
|
||||
if !os.IsNotExist(err) {
|
||||
Die("can't open %s: %s", authkeys, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,30 +122,32 @@ func encrypt(args []string) {
|
|||
var ist, ost os.FileInfo
|
||||
|
||||
if ost, err = os.Stat(outfile); err != nil {
|
||||
die("can't stat %s: %s", outfile, err)
|
||||
Die("can't stat %s: %s", outfile, err)
|
||||
}
|
||||
|
||||
if ist, err = inf.Stat(); err != nil {
|
||||
die("can't stat %s: %s", infile, err)
|
||||
Die("can't stat %s: %s", infile, err)
|
||||
}
|
||||
|
||||
if os.SameFile(ist, ost) {
|
||||
die("won't create output file: same as input file!")
|
||||
Die("won't create output file: same as input file!")
|
||||
}
|
||||
mode = ist.Mode()
|
||||
}
|
||||
|
||||
sf, err := sign.NewSafeFile(outfile, force, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
AtExit(sf.Abort)
|
||||
defer sf.Abort()
|
||||
outfd = sf
|
||||
}
|
||||
|
||||
en, err := sign.NewEncryptor(sk, blksize)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
errs := 0
|
||||
|
@ -158,14 +160,14 @@ func encrypt(args []string) {
|
|||
var ok bool
|
||||
pk, ok = keymap[fn]
|
||||
if !ok {
|
||||
warn("can't find user %s in %s", fn, authkeys)
|
||||
Warn("can't find user %s in %s", fn, authkeys)
|
||||
errs += 1
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
pk, err = sign.ReadPublicKey(fn)
|
||||
if err != nil {
|
||||
warn("%s", err)
|
||||
Warn("%s", err)
|
||||
errs += 1
|
||||
continue
|
||||
}
|
||||
|
@ -173,17 +175,17 @@ func encrypt(args []string) {
|
|||
|
||||
err = en.AddRecipient(pk)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if errs > 0 {
|
||||
die("Too many errors!")
|
||||
Die("Too many errors!")
|
||||
}
|
||||
|
||||
err = en.Encrypt(infd, outfd)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
outfd.Close()
|
||||
}
|
||||
|
@ -221,12 +223,12 @@ func decrypt(args []string) {
|
|||
|
||||
err := fs.Parse(args)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
args = fs.Args()
|
||||
if len(args) < 1 {
|
||||
die("Insufficient args. Try '%s --help'", os.Args[0])
|
||||
Die("Insufficient args. Try '%s --help'", os.Args[0])
|
||||
}
|
||||
|
||||
var infd io.Reader = os.Stdin
|
||||
|
@ -246,13 +248,13 @@ func decrypt(args []string) {
|
|||
} else {
|
||||
pws, err = utils.Askpass("Enter passphrase for private key", false)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
return []byte(pws), nil
|
||||
})
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
var pk *sign.PublicKey
|
||||
|
@ -260,7 +262,7 @@ func decrypt(args []string) {
|
|||
if len(pubkey) > 0 {
|
||||
pk, err = sign.ReadPublicKey(pubkey)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,33 +286,35 @@ func decrypt(args []string) {
|
|||
var err error
|
||||
|
||||
if ost, err = os.Stat(outfile); err != nil {
|
||||
die("can't stat %s: %s", outfile, err)
|
||||
Die("can't stat %s: %s", outfile, err)
|
||||
}
|
||||
if ist, err = inf.Stat(); err != nil {
|
||||
die("can't stat %s: %s", infile, err)
|
||||
Die("can't stat %s: %s", infile, err)
|
||||
}
|
||||
if os.SameFile(ist, ost) {
|
||||
die("won't create output file: same as input file!")
|
||||
Die("won't create output file: same as input file!")
|
||||
}
|
||||
mode = ist.Mode()
|
||||
}
|
||||
|
||||
sf, err := sign.NewSafeFile(outfile, force, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
AtExit(sf.Abort)
|
||||
defer sf.Abort()
|
||||
outfd = sf
|
||||
}
|
||||
|
||||
d, err := sign.NewDecryptor(infd)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
err = d.SetPrivateKey(sk, pk)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
if pk == nil && d.AuthenticatedSender() {
|
||||
|
@ -318,17 +322,17 @@ func decrypt(args []string) {
|
|||
if len(fn) == 0 || fn == "-" {
|
||||
fn = "<stdin>"
|
||||
}
|
||||
warn("%s: Missing sender Public Key; can't authenticate sender ..", fn)
|
||||
Warn("%s: Missing sender Public Key; can't authenticate sender ..", fn)
|
||||
}
|
||||
|
||||
if err = d.Decrypt(outfd); err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
outfd.Close()
|
||||
|
||||
if test {
|
||||
warn("Enc file OK")
|
||||
Warn("Enc file OK")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -338,9 +342,16 @@ func encryptUsage(fs *flag.FlagSet) {
|
|||
|
||||
Usage: %s encrypt [options] to [to ...] infile|-
|
||||
|
||||
Where TO is the public key of the recipient and INFILE is an input file.
|
||||
If the input file is '-' then %s reads from STDIN. Unless '-o' is used,
|
||||
%s writes the encrypted output to STDOUT.
|
||||
Where TO is the public key of the recipient; it can be one of:
|
||||
|
||||
- a file referring to an SSH or sigtool public key.
|
||||
- string of the form 'a@b' - in which case the user's default
|
||||
ssh/authorized_keys is consulted to find the comment matching
|
||||
'a@b' - in which case the user's ssh authorized_keys file is consulted to
|
||||
find the comment matching the string.
|
||||
|
||||
INFILE is an input file to be encrypted. If the input file is '-' then %s
|
||||
reads from STDIN. Unless '-o' is used, %s writes the encrypted output to STDOUT.
|
||||
|
||||
Options:
|
||||
`, Z, Z, Z, Z)
|
||||
|
@ -368,7 +379,7 @@ Options:
|
|||
func mustOpen(fn string, flag int) *os.File {
|
||||
fdk, err := os.OpenFile(fn, flag, 0600)
|
||||
if err != nil {
|
||||
die("can't open file %s: %s", fn, err)
|
||||
Die("can't open file %s: %s", fn, err)
|
||||
}
|
||||
return fdk
|
||||
}
|
||||
|
|
55
die.go
Normal file
55
die.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
// die.go -- die() and warn()
|
||||
//
|
||||
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
||||
//
|
||||
// Licensing Terms: GPLv2
|
||||
//
|
||||
// If you need a commercial license for this work, please contact
|
||||
// the author.
|
||||
//
|
||||
// This software does not come with any express or implied
|
||||
// warranty; it is provided "as is". No claim is made to its
|
||||
// suitability for any purpose.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var atExit []func()
|
||||
|
||||
// Die prints an error message to stderr
|
||||
// and exits the program after calling all the registered
|
||||
// at-exit functions.
|
||||
func Die(f string, v ...interface{}) {
|
||||
Warn(f, v...)
|
||||
Exit(1)
|
||||
}
|
||||
|
||||
// Warn prints an error message to stderr
|
||||
func Warn(f string, v ...interface{}) {
|
||||
z := fmt.Sprintf("%s: %s", os.Args[0], f)
|
||||
s := fmt.Sprintf(z, v...)
|
||||
if n := len(s); s[n-1] != '\n' {
|
||||
s += "\n"
|
||||
}
|
||||
|
||||
os.Stderr.WriteString(s)
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
|
||||
// AtExit registers a function to be called before the program exits.
|
||||
func AtExit(f func()) {
|
||||
atExit = append(atExit, f)
|
||||
}
|
||||
|
||||
// Exit invokes the registered atexit handlers and exits with the
|
||||
// given code.
|
||||
func Exit(v int) {
|
||||
for _, f := range atExit {
|
||||
f()
|
||||
}
|
||||
os.Exit(v)
|
||||
}
|
60
sigtool.go
60
sigtool.go
|
@ -49,8 +49,7 @@ func main() {
|
|||
|
||||
args := mf.Args()
|
||||
if len(args) < 1 {
|
||||
warn("Insufficient arguments. Try '%s -h'", Z)
|
||||
os.Exit(1)
|
||||
Die("Insufficient arguments. Try '%s -h'", Z)
|
||||
}
|
||||
|
||||
cmds := map[string]func(args []string){
|
||||
|
@ -73,15 +72,18 @@ func main() {
|
|||
ab := utils.Abbrev(words)
|
||||
canon, ok := ab[strings.ToLower(args[0])]
|
||||
if !ok {
|
||||
die("Unknown command %s", args[0])
|
||||
Die("Unknown command %s", args[0])
|
||||
}
|
||||
|
||||
cmd := cmds[canon]
|
||||
if cmd == nil {
|
||||
die("can't map command %s", canon)
|
||||
Die("can't map command %s", canon)
|
||||
}
|
||||
|
||||
cmd(args[1:])
|
||||
|
||||
// always call Exit so that at-exit handlers are called.
|
||||
Exit(0)
|
||||
}
|
||||
|
||||
// Run the generate command
|
||||
|
@ -115,7 +117,7 @@ Options:
|
|||
|
||||
args = fs.Args()
|
||||
if len(args) < 1 {
|
||||
die("Insufficient arguments to 'generate'. Try '%s generate -h' ..", Z)
|
||||
Die("Insufficient arguments to 'generate'. Try '%s generate -h' ..", Z)
|
||||
}
|
||||
|
||||
bn := args[0]
|
||||
|
@ -125,7 +127,7 @@ Options:
|
|||
|
||||
if !force {
|
||||
if exists(pkn) || exists(skn) {
|
||||
die("Public/Private key files (%s, %s) exist. won't overwrite!", skn, pkn)
|
||||
Die("Public/Private key files (%s, %s) exist. won't overwrite!", skn, pkn)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +141,7 @@ Options:
|
|||
} else {
|
||||
pws, err = utils.Askpass("Enter passphrase for private key", true)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,16 +150,16 @@ Options:
|
|||
|
||||
sk, err := sign.NewPrivateKey()
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
if err = sk.Serialize(skn, comment, force, pw); err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
pk := sk.PublicKey()
|
||||
if err = pk.Serialize(pkn, comment, force); err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +192,7 @@ Options:
|
|||
|
||||
args = fs.Args()
|
||||
if len(args) < 2 {
|
||||
die("Insufficient arguments to 'sign'. Try '%s sign -h' ..", Z)
|
||||
Die("Insufficient arguments to 'sign'. Try '%s sign -h' ..", Z)
|
||||
}
|
||||
|
||||
kn := args[0]
|
||||
|
@ -208,10 +210,11 @@ Options:
|
|||
if outf != "-" {
|
||||
sf, err := sign.NewSafeFile(outf, force, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
die("can't create sig file: %s", err)
|
||||
Die("can't create sig file: %s", err)
|
||||
}
|
||||
|
||||
// we unlink and remove temp on any error
|
||||
AtExit(sf.Abort)
|
||||
defer sf.Abort()
|
||||
fd = sf
|
||||
}
|
||||
|
@ -227,19 +230,19 @@ Options:
|
|||
} else {
|
||||
pws, err = utils.Askpass("Enter passphrase for private key", false)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return []byte(pws), nil
|
||||
})
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
sig, err := sk.SignFile(fn)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
sigbytes, err := sig.MarshalBinary(fmt.Sprintf("input=%s", fn))
|
||||
|
@ -271,7 +274,7 @@ Options:
|
|||
|
||||
args = fs.Args()
|
||||
if len(args) < 3 {
|
||||
die("Insufficient arguments to 'verify'. Try '%s verify -h' ..", Z)
|
||||
Die("Insufficient arguments to 'verify'. Try '%s verify -h' ..", Z)
|
||||
}
|
||||
|
||||
pn := args[0]
|
||||
|
@ -280,21 +283,21 @@ Options:
|
|||
|
||||
sig, err := sign.ReadSignature(sn)
|
||||
if err != nil {
|
||||
die("Can't read signature '%s': %s", sn, err)
|
||||
Die("Can't read signature '%s': %s", sn, err)
|
||||
}
|
||||
|
||||
pk, err := sign.ReadPublicKey(pn)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
if !sig.IsPKMatch(pk) {
|
||||
die("Wrong public key '%s' for verifying '%s'", pn, sn)
|
||||
Die("Wrong public key '%s' for verifying '%s'", pn, sn)
|
||||
}
|
||||
|
||||
ok, err := pk.VerifyFile(fn, sig)
|
||||
if err != nil {
|
||||
die("%s", err)
|
||||
Die("%s", err)
|
||||
}
|
||||
|
||||
exit := 0
|
||||
|
@ -343,23 +346,6 @@ func exists(nm string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// die with error
|
||||
func die(f string, v ...interface{}) {
|
||||
warn(f, v...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func warn(f string, v ...interface{}) {
|
||||
z := fmt.Sprintf("%s: %s", os.Args[0], f)
|
||||
s := fmt.Sprintf(z, v...)
|
||||
if n := len(s); s[n-1] != '\n' {
|
||||
s += "\n"
|
||||
}
|
||||
|
||||
os.Stderr.WriteString(s)
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
|
||||
// This will be filled in by "build"
|
||||
var RepoVersion string = "UNDEFINED"
|
||||
var Buildtime string = "UNDEFINED"
|
||||
|
|
0
tests.sh
Normal file → Executable file
0
tests.sh
Normal file → Executable file
Loading…
Add table
Reference in a new issue