зеркало из https://github.com/github/smimesign.git
better error messages
This commit is contained in:
Родитель
5abdd89a0b
Коммит
f50a4eebe8
|
@ -10,24 +10,16 @@ import (
|
|||
|
||||
"github.com/mastahyeti/certstore"
|
||||
"github.com/mastahyeti/cms"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func commandSign() int {
|
||||
idents, err := store.Identities()
|
||||
func commandSign() {
|
||||
userIdent, err := findUserIdentity()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, ident := range idents {
|
||||
defer ident.Close()
|
||||
}
|
||||
|
||||
userIdent, err := findUserIdentity(idents)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to get identity matching specified user-id")
|
||||
}
|
||||
if userIdent == nil {
|
||||
fmt.Printf("Could not find identity matching specified user-id: %s\n", *localUserOpt)
|
||||
return 1
|
||||
failf("Could not find identity matching specified user-id: %s\n", *localUserOpt)
|
||||
}
|
||||
|
||||
// Git is looking for "\n[GNUPG:] SIG_CREATED ", meaning we need to print a
|
||||
|
@ -37,17 +29,17 @@ func commandSign() int {
|
|||
|
||||
chain, err := userIdent.CertificateChain()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to get idenity certificate chain")
|
||||
}
|
||||
|
||||
signer, err := userIdent.Signer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to get idenity signer")
|
||||
}
|
||||
|
||||
dataBuf := new(bytes.Buffer)
|
||||
if _, err = io.Copy(dataBuf, os.Stdin); err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to read message from stdin")
|
||||
}
|
||||
|
||||
var der []byte
|
||||
|
@ -57,7 +49,7 @@ func commandSign() int {
|
|||
der, err = cms.Sign(dataBuf.Bytes(), chain, signer)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to sign message")
|
||||
}
|
||||
|
||||
emitSigCreated(chain[0], *detachSignFlag)
|
||||
|
@ -71,15 +63,13 @@ func commandSign() int {
|
|||
_, err = os.Stdout.Write(der)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
fail("failed to write signature")
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// findUserIdentity attempts to find an identity to sign with in the certstore
|
||||
// by checking available identities against the --local-user argument.
|
||||
func findUserIdentity(idents []certstore.Identity) (certstore.Identity, error) {
|
||||
func findUserIdentity() (certstore.Identity, error) {
|
||||
var (
|
||||
email string
|
||||
fpr []byte
|
||||
|
@ -98,7 +88,7 @@ func findUserIdentity(idents []certstore.Identity) (certstore.Identity, error) {
|
|||
for _, ident := range idents {
|
||||
cert, err := ident.Certificate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "failed to get identity certificate")
|
||||
}
|
||||
|
||||
if certHasEmail(cert, email) || certHasFingerprint(cert, fpr) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
|
@ -12,17 +11,17 @@ import (
|
|||
"github.com/mastahyeti/cms"
|
||||
)
|
||||
|
||||
func commandVerify() int {
|
||||
func commandVerify() {
|
||||
sNewSig.emit()
|
||||
|
||||
if len(fileArgs) < 2 {
|
||||
return verifyAttached()
|
||||
verifyAttached()
|
||||
} else {
|
||||
verifyDetached()
|
||||
}
|
||||
|
||||
return verifyDetached()
|
||||
}
|
||||
|
||||
func verifyAttached() int {
|
||||
func verifyAttached() {
|
||||
var (
|
||||
f *os.File
|
||||
err error
|
||||
|
@ -31,7 +30,7 @@ func verifyAttached() int {
|
|||
// Read in signature
|
||||
if len(fileArgs) == 1 {
|
||||
if f, err = os.Open(fileArgs[0]); err != nil {
|
||||
panic(err)
|
||||
failef(err, "failed to open signature file (%s)", fileArgs[0])
|
||||
}
|
||||
defer f.Close()
|
||||
} else {
|
||||
|
@ -40,7 +39,7 @@ func verifyAttached() int {
|
|||
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err = io.Copy(buf, f); err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to read signature")
|
||||
}
|
||||
|
||||
// Try decoding as PEM
|
||||
|
@ -54,7 +53,7 @@ func verifyAttached() int {
|
|||
// Parse signature
|
||||
sd, err := cms.ParseSignedData(der)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to parse signature")
|
||||
}
|
||||
|
||||
// Verify signature
|
||||
|
@ -67,8 +66,7 @@ func verifyAttached() int {
|
|||
sErrSig.emit()
|
||||
}
|
||||
|
||||
fmt.Printf("Sinature verification failed: %s\n", err.Error())
|
||||
return 1
|
||||
faile(err, "failed to verify signature")
|
||||
}
|
||||
|
||||
emitGoodSig(certs)
|
||||
|
@ -76,21 +74,19 @@ func verifyAttached() int {
|
|||
// TODO: Maybe split up signature checking and certificate checking so we can
|
||||
// output something more meaningful.
|
||||
emitTrustFully()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func verifyDetached() int {
|
||||
func verifyDetached() {
|
||||
// Read in signature
|
||||
f, err := os.Open(fileArgs[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
failef(err, "failed to open signature file (%s)", fileArgs[0])
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err = io.Copy(buf, f); err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to read signature file")
|
||||
}
|
||||
|
||||
// Try decoding as PEM
|
||||
|
@ -104,7 +100,7 @@ func verifyDetached() int {
|
|||
// Parse signature
|
||||
sd, err := cms.ParseSignedData(der)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to parse signature")
|
||||
}
|
||||
|
||||
// Read in signed data
|
||||
|
@ -112,7 +108,7 @@ func verifyDetached() int {
|
|||
f = os.Stdin
|
||||
} else {
|
||||
if f, err = os.Open(fileArgs[1]); err != nil {
|
||||
panic(err)
|
||||
failef(err, "failed to open message file (%s)", fileArgs[1])
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
|
@ -120,7 +116,7 @@ func verifyDetached() int {
|
|||
// Verify signature
|
||||
buf.Reset()
|
||||
if _, err = io.Copy(buf, f); err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to read message file")
|
||||
}
|
||||
|
||||
certs, err := sd.VerifyDetached(buf.Bytes(), rootsPool())
|
||||
|
@ -132,8 +128,7 @@ func verifyDetached() int {
|
|||
sErrSig.emit()
|
||||
}
|
||||
|
||||
fmt.Printf("Sinature verification failed: %s\n", err.Error())
|
||||
return 1
|
||||
faile(err, "failed to verify signature")
|
||||
}
|
||||
|
||||
emitGoodSig(certs)
|
||||
|
@ -141,8 +136,6 @@ func verifyDetached() int {
|
|||
// TODO: Maybe split up signature checking and certificate checking so we can
|
||||
// output something more meaningful.
|
||||
emitTrustFully()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func rootsPool() *x509.CertPool {
|
||||
|
@ -157,10 +150,6 @@ func rootsPool() *x509.CertPool {
|
|||
}
|
||||
}
|
||||
|
||||
idents, err := store.Identities()
|
||||
if err != nil {
|
||||
return roots
|
||||
}
|
||||
for _, ident := range idents {
|
||||
if cert, err := ident.Certificate(); err == nil {
|
||||
roots.AddCert(cert)
|
||||
|
|
|
@ -5,19 +5,11 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func commandListKeys() int {
|
||||
idents, err := store.Identities()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, ident := range idents {
|
||||
defer ident.Close()
|
||||
}
|
||||
|
||||
func commandListKeys() {
|
||||
for j, ident := range idents {
|
||||
cert, err := ident.Certificate()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
faile(err, "failed to get identity certificate")
|
||||
}
|
||||
|
||||
if j > 0 {
|
||||
|
@ -32,6 +24,4 @@ func commandListKeys() int {
|
|||
fmt.Println(" Subject:", rdnSequenceString(cert.Subject.ToRDNSequence()))
|
||||
fmt.Println(" Emails:", strings.Join(certEmails(cert), ", "))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
138
main.go
138
main.go
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/mastahyeti/certstore"
|
||||
"github.com/pborman/getopt/v2"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -23,16 +24,11 @@ var (
|
|||
keyFormatOpt = getopt.EnumLong("keyid-format", 0, []string{"long"}, "long", "Select how to display key IDs.", "{long}")
|
||||
fileArgs []string
|
||||
|
||||
store certstore.Store
|
||||
idents []certstore.Identity
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Open certificate store
|
||||
var err error
|
||||
if store, err = certstore.Open(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer store.Close()
|
||||
defer handleExit()
|
||||
|
||||
// Parse CLI args
|
||||
getopt.HelpColumn = 30
|
||||
|
@ -40,49 +36,101 @@ func main() {
|
|||
getopt.Parse()
|
||||
fileArgs = getopt.Args()
|
||||
|
||||
status := 1
|
||||
if *helpFlag {
|
||||
if *signFlag || *verifyFlag || *listKeysFlag {
|
||||
fmt.Println("specify --help, --sign, --verify, or --list-keys")
|
||||
fail("specify --help, --sign, --verify, or --list-keys")
|
||||
} else {
|
||||
getopt.Usage()
|
||||
status = 0
|
||||
return
|
||||
}
|
||||
} else if *signFlag {
|
||||
if *helpFlag || *verifyFlag || *listKeysFlag {
|
||||
fmt.Println("specify --help, --sign, --verify, or --list-keys")
|
||||
} else if len(*localUserOpt) == 0 {
|
||||
fmt.Println("specify a USER-ID to sign with")
|
||||
} else {
|
||||
status = commandSign()
|
||||
}
|
||||
} else if *verifyFlag {
|
||||
if *helpFlag || *signFlag || *listKeysFlag {
|
||||
fmt.Println("specify --help, --sign, --verify, or --list-keys")
|
||||
} else if len(*localUserOpt) > 0 {
|
||||
fmt.Println("local-user cannot be specified for verification")
|
||||
} else if *detachSignFlag {
|
||||
fmt.Println("detach-sign cannot be specified for verification")
|
||||
} else if *armorFlag {
|
||||
fmt.Println("armor cannot be specified for verification")
|
||||
} else {
|
||||
status = commandVerify()
|
||||
}
|
||||
} else if *listKeysFlag {
|
||||
if *helpFlag || *signFlag || *verifyFlag {
|
||||
fmt.Println("specify --help, --sign, --verify, or --list-keys")
|
||||
} else if len(*localUserOpt) > 0 {
|
||||
fmt.Println("local-user cannot be specified for list-keys")
|
||||
} else if *detachSignFlag {
|
||||
fmt.Println("detach-sign cannot be specified for list-keys")
|
||||
} else if *armorFlag {
|
||||
fmt.Println("armor cannot be specified for list-keys")
|
||||
} else {
|
||||
status = commandListKeys()
|
||||
}
|
||||
} else {
|
||||
fmt.Println("specify --help, --sign, --verify, or --list-keys")
|
||||
}
|
||||
|
||||
os.Exit(status)
|
||||
// Open certificate store
|
||||
store, err := certstore.Open()
|
||||
if err != nil {
|
||||
faile(err, "failed to open certificate store")
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
// Get list of identities
|
||||
idents, err = store.Identities()
|
||||
if err != nil {
|
||||
faile(err, "failed to get identities from certificate store")
|
||||
}
|
||||
for _, ident := range idents {
|
||||
defer ident.Close()
|
||||
}
|
||||
|
||||
if *signFlag {
|
||||
if *helpFlag || *verifyFlag || *listKeysFlag {
|
||||
fail("specify --help, --sign, --verify, or --list-keys")
|
||||
} else if len(*localUserOpt) == 0 {
|
||||
fail("specify a USER-ID to sign with")
|
||||
} else {
|
||||
commandSign()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if *verifyFlag {
|
||||
if *helpFlag || *signFlag || *listKeysFlag {
|
||||
fail("specify --help, --sign, --verify, or --list-keys")
|
||||
} else if len(*localUserOpt) > 0 {
|
||||
fail("local-user cannot be specified for verification")
|
||||
} else if *detachSignFlag {
|
||||
fail("detach-sign cannot be specified for verification")
|
||||
} else if *armorFlag {
|
||||
fail("armor cannot be specified for verification")
|
||||
} else {
|
||||
commandVerify()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if *listKeysFlag {
|
||||
if *helpFlag || *signFlag || *verifyFlag {
|
||||
fail("specify --help, --sign, --verify, or --list-keys")
|
||||
} else if len(*localUserOpt) > 0 {
|
||||
fail("local-user cannot be specified for list-keys")
|
||||
} else if *detachSignFlag {
|
||||
fail("detach-sign cannot be specified for list-keys")
|
||||
} else if *armorFlag {
|
||||
fail("armor cannot be specified for list-keys")
|
||||
} else {
|
||||
commandListKeys()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fail("specify --help, --sign, --verify, or --list-keys")
|
||||
}
|
||||
|
||||
type statusCode int
|
||||
|
||||
func handleExit() {
|
||||
if e := recover(); e != nil {
|
||||
if sc, isStatusCode := e.(statusCode); isStatusCode {
|
||||
os.Exit(int(sc))
|
||||
}
|
||||
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func faile(err error, message string) {
|
||||
fail(errors.Wrap(err, message))
|
||||
}
|
||||
|
||||
func failef(err error, format string, a ...interface{}) {
|
||||
fail(errors.Wrapf(err, format, a...))
|
||||
}
|
||||
|
||||
func fail(a ...interface{}) {
|
||||
fmt.Fprintln(os.Stderr, a...)
|
||||
panic(statusCode(1))
|
||||
}
|
||||
|
||||
func failf(format string, a ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, format, a...)
|
||||
panic(statusCode(1))
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче