1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
//go:generate goversioninfo -file-version=$GIT_VERSION -ver-major=$VERSION_MAJOR -ver-minor=$VERSION_MINOR -ver-patch=$VERSION_PATCH -platform-specific=true windows-installer/versioninfo.json
package main
import (
"fmt"
"io"
"os"
"github.com/github/smimesign/certstore"
"github.com/pborman/getopt/v2"
"github.com/pkg/errors"
)
var (
// This can be set at build time by running
// go build -ldflags "-X main.versionString=$(git describe --tags)"
versionString = "undefined"
// default timestamp authority URL. This can be set at build time by running
// go build -ldflags "-X main.defaultTSA=${https://whatever}"
defaultTSA = ""
// Action flags
helpFlag = getopt.BoolLong("help", 'h', "print this help message")
versionFlag = getopt.BoolLong("version", 'v', "print the version number")
signFlag = getopt.BoolLong("sign", 's', "make a signature")
verifyFlag = getopt.BoolLong("verify", 0, "verify a signature")
listKeysFlag = getopt.BoolLong("list-keys", 0, "show keys")
// Option flags
localUserOpt = getopt.StringLong("local-user", 'u', "", "use USER-ID to sign", "USER-ID")
detachSignFlag = getopt.BoolLong("detach-sign", 'b', "make a detached signature")
armorFlag = getopt.BoolLong("armor", 'a', "create ascii armored output")
statusFdOpt = getopt.IntLong("status-fd", 0, -1, "write special status strings to the file descriptor n.", "n")
keyFormatOpt = getopt.EnumLong("keyid-format", 0, []string{"long"}, "long", "select how to display key IDs.", "{long}")
tsaOpt = getopt.StringLong("timestamp-authority", 't', defaultTSA, "URL of RFC3161 timestamp authority to use for timestamping", "url")
includeCertsOpt = getopt.IntLong("include-certs", 0, -2, "-3 is the same as -2, but ommits issuer when cert has Authority Information Access extension. -2 includes all certs except root. -1 includes all certs. 0 includes no certs. 1 includes leaf cert. >1 includes n from the leaf. Default -2.", "n")
// Remaining arguments
fileArgs []string
idents []certstore.Identity
// these are changed in tests
stdin io.ReadCloser = os.Stdin
stdout io.WriteCloser = os.Stdout
stderr io.WriteCloser = os.Stderr
)
func main() {
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]")
getopt.Parse()
fileArgs = getopt.Args()
if *helpFlag {
getopt.Usage()
return nil
}
if *versionFlag {
fmt.Println(versionString)
return nil
}
// Open certificate store
store, err := certstore.Open()
if err != nil {
return errors.Wrap(err, "failed to open certificate store")
}
defer store.Close()
// Get list of identities
idents, err = store.Identities()
if err != nil {
return errors.Wrap(err, "failed to get identities from certificate store")
}
for _, ident := range idents {
defer ident.Close()
}
if *signFlag {
if *verifyFlag || *listKeysFlag {
return errors.New("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) == 0 {
return errors.New("specify a USER-ID to sign with")
} else {
return commandSign()
}
}
if *verifyFlag {
if *signFlag || *listKeysFlag {
return errors.New("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
return errors.New("local-user cannot be specified for verification")
} else if *detachSignFlag {
return errors.New("detach-sign cannot be specified for verification")
} else if *armorFlag {
return errors.New("armor cannot be specified for verification")
} else {
return commandVerify()
}
}
if *listKeysFlag {
if *signFlag || *verifyFlag {
return errors.New("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
return errors.New("local-user cannot be specified for list-keys")
} else if *detachSignFlag {
return errors.New("detach-sign cannot be specified for list-keys")
} else if *armorFlag {
return errors.New("armor cannot be specified for list-keys")
} else {
return commandListKeys()
}
}
return errors.New("specify --help, --sign, --verify, or --list-keys")
}
|