Merge branch 'master' into include-certs

This commit is contained in:
Ben Toews 2018-09-05 12:43:23 -06:00
Родитель 0cacf715af 859c208a3b
Коммит 9f7f15e84e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
8 изменённых файлов: 84 добавлений и 127 удалений

2
Gopkg.lock сгенерированный
Просмотреть файл

@ -17,7 +17,7 @@
branch = "master"
name = "github.com/mastahyeti/certstore"
packages = ["."]
revision = "ab8919c9ca63b30a6f44cc573ee236ba24317979"
revision = "b5c7743eef9630309aec884accc77963ea8b1199"
[[projects]]
name = "github.com/mastahyeti/cms"

Просмотреть файл

@ -13,13 +13,13 @@ import (
"github.com/pkg/errors"
)
func commandSign() {
func commandSign() error {
userIdent, err := findUserIdentity()
if err != nil {
faile(err, "failed to get identity matching specified user-id")
return errors.Wrap(err, "failed to get identity matching specified user-id")
}
if userIdent == nil {
fail("Could not find identity matching specified user-id:", *localUserOpt)
return fmt.Errorf("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
@ -29,25 +29,25 @@ func commandSign() {
cert, err := userIdent.Certificate()
if err != nil {
faile(err, "failed to get idenity certificate")
return errors.Wrap(err, "failed to get idenity certificate")
}
signer, err := userIdent.Signer()
if err != nil {
faile(err, "failed to get idenity signer")
return errors.Wrap(err, "failed to get idenity signer")
}
dataBuf := new(bytes.Buffer)
if _, err = io.Copy(dataBuf, stdin); err != nil {
faile(err, "failed to read message from stdin")
return errors.Wrap(err, "failed to read message from stdin")
}
sd, err := cms.NewSignedData(dataBuf.Bytes())
if err != nil {
faile(err, "failed to create signed data")
return errors.Wrap(err, "failed to create signed data")
}
if err = sd.Sign([]*x509.Certificate{cert}, signer); err != nil {
faile(err, "failed to sign message")
return errors.Wrap(err, "failed to sign message")
}
if *detachSignFlag {
sd.Detached()
@ -55,21 +55,21 @@ func commandSign() {
if len(*tsaOpt) > 0 {
if err = sd.AddTimestamps(*tsaOpt); err != nil {
faile(err, "failed to add timestamp")
return errors.Wrap(err, "failed to add timestamp")
}
}
chain, err := userIdent.CertificateChain()
if err != nil {
faile(err, "failed to get idenity certificate chain")
return errors.Wrap(err, "failed to get idenity certificate chain")
}
if err = sd.SetCertificates(certsForSignature(chain)); err != nil {
faile(err, "failed to set certificates")
return errors.Wrap(err, "failed to set certificates")
}
der, err := sd.ToDER()
if err != nil {
faile(err, "failed to serialize signature")
return errors.Wrap(err, "failed to serialize signature")
}
emitSigCreated(cert, *detachSignFlag)
@ -83,8 +83,10 @@ func commandSign() {
_, err = stdout.Write(der)
}
if err != nil {
fail("failed to write signature")
return errors.New("failed to write signature")
}
return nil
}
// findUserIdentity attempts to find an identity to sign with in the certstore

Просмотреть файл

@ -13,7 +13,7 @@ func TestSign(t *testing.T) {
defer testSetup(t, "--sign", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
sd, err := cms.ParseSignedData(stdoutBuf.Bytes())
require.NoError(t, err)
@ -25,7 +25,7 @@ func TestSignIncludeCertsAIA(t *testing.T) {
defer testSetup(t, "--sign", "-u", certHexFingerprint(aiaLeaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -44,7 +44,7 @@ func TestSignIncludeCertsDefault(t *testing.T) {
defer testSetup(t, "--sign", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -64,7 +64,7 @@ func TestSignIncludeCertsMinus3(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=-3", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -84,7 +84,7 @@ func TestSignIncludeCertsMinus2(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=-2", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -104,7 +104,7 @@ func TestSignIncludeCertsMinus1(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=-1", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -125,7 +125,7 @@ func TestSignIncludeCerts0(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=0", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -143,7 +143,7 @@ func TestSignIncludeCerts1(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=1", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -162,7 +162,7 @@ func TestSignIncludeCerts2(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=2", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -182,7 +182,7 @@ func TestSignIncludeCerts3(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=3", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)
@ -203,7 +203,7 @@ func TestSignIncludeCerts4(t *testing.T) {
defer testSetup(t, "--sign", "--include-certs=4", "-u", certHexFingerprint(leaf.Certificate))()
stdinBuf.WriteString("hello, world!")
commandSign()
require.NoError(t, commandSign())
ci, err := protocol.ParseContentInfo(stdoutBuf.Bytes())
require.NoError(t, err)

Просмотреть файл

@ -8,20 +8,21 @@ import (
"os"
"github.com/certifi/gocertifi"
"github.com/github/go/errors"
"github.com/mastahyeti/cms"
)
func commandVerify() {
func commandVerify() error {
sNewSig.emit()
if len(fileArgs) < 2 {
verifyAttached()
} else {
verifyDetached()
return verifyAttached()
}
return verifyDetached()
}
func verifyAttached() {
func verifyAttached() error {
var (
f io.ReadCloser
err error
@ -30,7 +31,7 @@ func verifyAttached() {
// Read in signature
if len(fileArgs) == 1 {
if f, err = os.Open(fileArgs[0]); err != nil {
failef(err, "failed to open signature file (%s)", fileArgs[0])
return errors.Wrapf(err, "failed to open signature file (%s)", fileArgs[0])
}
defer f.Close()
} else {
@ -39,7 +40,7 @@ func verifyAttached() {
buf := new(bytes.Buffer)
if _, err = io.Copy(buf, f); err != nil {
faile(err, "failed to read signature")
return errors.Wrap(err, "failed to read signature")
}
// Try decoding as PEM
@ -53,7 +54,7 @@ func verifyAttached() {
// Parse signature
sd, err := cms.ParseSignedData(der)
if err != nil {
faile(err, "failed to parse signature")
return errors.Wrap(err, "failed to parse signature")
}
// Verify signature
@ -66,7 +67,7 @@ func verifyAttached() {
sErrSig.emit()
}
faile(err, "failed to verify signature")
return errors.Wrap(err, "failed to verify signature")
}
emitGoodSig(chains)
@ -74,9 +75,11 @@ func verifyAttached() {
// TODO: Maybe split up signature checking and certificate checking so we can
// output something more meaningful.
emitTrustFully()
return nil
}
func verifyDetached() {
func verifyDetached() error {
var (
f io.ReadCloser
err error
@ -84,13 +87,13 @@ func verifyDetached() {
// Read in signature
if f, err = os.Open(fileArgs[0]); err != nil {
failef(err, "failed to open signature file (%s)", fileArgs[0])
return errors.Wrapf(err, "failed to open signature file (%s)", fileArgs[0])
}
defer f.Close()
buf := new(bytes.Buffer)
if _, err = io.Copy(buf, f); err != nil {
faile(err, "failed to read signature file")
return errors.Wrap(err, "failed to read signature file")
}
// Try decoding as PEM
@ -104,7 +107,7 @@ func verifyDetached() {
// Parse signature
sd, err := cms.ParseSignedData(der)
if err != nil {
faile(err, "failed to parse signature")
return errors.Wrap(err, "failed to parse signature")
}
// Read in signed data
@ -112,7 +115,7 @@ func verifyDetached() {
f = stdin
} else {
if f, err = os.Open(fileArgs[1]); err != nil {
failef(err, "failed to open message file (%s)", fileArgs[1])
errors.Wrapf(err, "failed to open message file (%s)", fileArgs[1])
}
defer f.Close()
}
@ -120,7 +123,7 @@ func verifyDetached() {
// Verify signature
buf.Reset()
if _, err = io.Copy(buf, f); err != nil {
faile(err, "failed to read message file")
return errors.Wrap(err, "failed to read message file")
}
chains, err := sd.VerifyDetached(buf.Bytes(), verifyOpts())
@ -132,7 +135,7 @@ func verifyDetached() {
sErrSig.emit()
}
faile(err, "failed to verify signature")
return errors.Wrap(err, "failed to verify signature")
}
emitGoodSig(chains)
@ -140,6 +143,8 @@ func verifyDetached() {
// TODO: Maybe split up signature checking and certificate checking so we can
// output something more meaningful.
emitTrustFully()
return nil
}
func verifyOpts() x509.VerifyOptions {

Просмотреть файл

@ -3,13 +3,15 @@ package main
import (
"fmt"
"strings"
"github.com/pkg/errors"
)
func commandListKeys() {
func commandListKeys() error {
for j, ident := range idents {
cert, err := ident.Certificate()
if err != nil {
faile(err, "failed to get identity certificate")
return errors.Wrap(err, "failed to get identity certificate")
}
if j > 0 {
@ -24,4 +26,6 @@ func commandListKeys() {
fmt.Println(" Subject:", cert.Subject.ToRDNSequence().String())
fmt.Println(" Emails:", strings.Join(certEmails(cert), ", "))
}
return nil
}

84
main.go
Просмотреть файл

@ -42,8 +42,13 @@ var (
)
func main() {
defer handleExit()
if err := runCommand(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func runCommand() error {
// Parse CLI args
getopt.HelpColumn = 40
getopt.SetParameters("[files]")
@ -51,25 +56,21 @@ func main() {
fileArgs = getopt.Args()
if *helpFlag {
if *signFlag || *verifyFlag || *listKeysFlag {
fail("specify --help, --sign, --verify, or --list-keys")
} else {
getopt.Usage()
return
}
getopt.Usage()
return nil
}
// Open certificate store
store, err := certstore.Open()
if err != nil {
faile(err, "failed to open certificate store")
return errors.Wrap(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")
return errors.Wrap(err, "failed to get identities from certificate store")
}
for _, ident := range idents {
defer ident.Close()
@ -77,78 +78,41 @@ func main() {
if *signFlag {
if *helpFlag || *verifyFlag || *listKeysFlag {
fail("specify --help, --sign, --verify, or --list-keys")
return errors.New("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) == 0 {
fail("specify a USER-ID to sign with")
return errors.New("specify a USER-ID to sign with")
} else {
commandSign()
return
return commandSign()
}
}
if *verifyFlag {
if *helpFlag || *signFlag || *listKeysFlag {
fail("specify --help, --sign, --verify, or --list-keys")
return errors.New("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
fail("local-user cannot be specified for verification")
return errors.New("local-user cannot be specified for verification")
} else if *detachSignFlag {
fail("detach-sign cannot be specified for verification")
return errors.New("detach-sign cannot be specified for verification")
} else if *armorFlag {
fail("armor cannot be specified for verification")
return errors.New("armor cannot be specified for verification")
} else {
commandVerify()
return
return commandVerify()
}
}
if *listKeysFlag {
if *helpFlag || *signFlag || *verifyFlag {
fail("specify --help, --sign, --verify, or --list-keys")
return errors.New("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
fail("local-user cannot be specified for list-keys")
return errors.New("local-user cannot be specified for list-keys")
} else if *detachSignFlag {
fail("detach-sign cannot be specified for list-keys")
return errors.New("detach-sign cannot be specified for list-keys")
} else if *armorFlag {
fail("armor cannot be specified for list-keys")
return errors.New("armor cannot be specified for list-keys")
} else {
commandListKeys()
return
return commandListKeys()
}
}
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)
}
}
// actual fail implementation. overridden in tests.
func doFail(a ...interface{}) {
fmt.Fprintln(stderr, a...)
panic(statusCode(1))
}
type failerFunc func(...interface{})
var failer failerFunc = doFail
func fail(a ...interface{}) {
failer(a...)
}
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...))
return errors.New("specify --help, --sign, --verify, or --list-keys")
}

Просмотреть файл

@ -89,18 +89,11 @@ func resetIO() {
func testSetup(t *testing.T, args ...string) func() {
t.Helper()
failerWas := failer
resetFunc := func() {
failer = failerWas
resetIO()
getopt.Reset()
}
failer = func(a ...interface{}) {
t.Helper()
t.Fatal(a...)
}
getopt.CommandLine.Parse(append([]string{"smimesign"}, args...))
idents = []certstore.Identity{

23
vendor/github.com/mastahyeti/certstore/certstore_darwin.go сгенерированный поставляемый
Просмотреть файл

@ -18,12 +18,6 @@ import (
"unsafe"
)
// work around https://github.com/golang/go/issues/24161
var (
_ C.CFBooleanRef
_ C.SecPolicyRef
)
// work around https://golang.org/doc/go1.10#cgo
// in go>=1.10 CFTypeRefs are translated to uintptrs instead of pointers.
var (
@ -35,6 +29,7 @@ var (
nilCFStringRef C.CFStringRef
nilSecIdentityRef C.SecIdentityRef
nilSecKeyRef C.SecKeyRef
nilCFAllocatorRef C.CFAllocatorRef
)
// macStore is a bogus type. We have to explicitly open/close the store on
@ -210,7 +205,7 @@ func (i *macIdentity) Signer() (crypto.Signer, error) {
func (i *macIdentity) Delete() error {
itemList := []C.SecIdentityRef{i.ref}
itemListPtr := (*unsafe.Pointer)(unsafe.Pointer(&itemList[0]))
citemList := C.CFArrayCreate(nil, itemListPtr, 1, nil)
citemList := C.CFArrayCreate(nilCFAllocatorRef, itemListPtr, 1, nil)
if citemList == nilCFArrayRef {
return errors.New("error creating CFArray")
}
@ -284,15 +279,9 @@ func (i *macIdentity) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts
return nil, err
}
// Hack — algos is a SecKeyAlgorithm and SecKeyCreateSignature takes a
// SecKeyAlgorithm as its second argument. The compiler insists though that
// algos is a CFStringRef and that SecKeyCreateSignature wants a
// *C.struct___CFString as its second argument.
algoHack := (*C.struct___CFString)(unsafe.Pointer(algo))
// sign the digest
var cerr C.CFErrorRef
csig := C.SecKeyCreateSignature(kref, algoHack, cdigest, &cerr)
csig := C.SecKeyCreateSignature(kref, algo, cdigest, &cerr)
if err := cfErrorError(cerr); err != nil {
defer C.CFRelease(C.CFTypeRef(cerr))
@ -406,7 +395,7 @@ func stringToCFString(gostr string) C.CFStringRef {
cstr := C.CString(gostr)
defer C.free(unsafe.Pointer(cstr))
return C.CFStringCreateWithCString(nil, cstr, C.kCFStringEncodingUTF8)
return C.CFStringCreateWithCString(nilCFAllocatorRef, cstr, C.kCFStringEncodingUTF8)
}
// mapToCFDictionary converts a Go map[C.CFTypeRef]C.CFTypeRef to a
@ -423,7 +412,7 @@ func mapToCFDictionary(gomap map[C.CFTypeRef]C.CFTypeRef) C.CFDictionaryRef {
values = append(values, unsafe.Pointer(v))
}
return C.CFDictionaryCreate(nil, &keys[0], &values[0], C.CFIndex(n), nil, nil)
return C.CFDictionaryCreate(nilCFAllocatorRef, &keys[0], &values[0], C.CFIndex(n), nil, nil)
}
// cfDataToBytes converts a CFDataRef to a Go byte slice.
@ -444,7 +433,7 @@ func bytesToCFData(gobytes []byte) (C.CFDataRef, error) {
cptr = (*C.UInt8)(&gobytes[0])
}
cdata := C.CFDataCreate(nil, cptr, clen)
cdata := C.CFDataCreate(nilCFAllocatorRef, cptr, clen)
if cdata == nilCFDataRef {
return nilCFDataRef, errors.New("error creatin cfdata")
}