aboutsummaryrefslogtreecommitdiff
path: root/flags.go
diff options
context:
space:
mode:
Diffstat (limited to 'flags.go')
-rw-r--r--flags.go168
1 files changed, 168 insertions, 0 deletions
diff --git a/flags.go b/flags.go
new file mode 100644
index 0000000..d7dc2ef
--- /dev/null
+++ b/flags.go
@@ -0,0 +1,168 @@
+package main
+
+// This file handles the complete parameter assignment, as some parameters are
+// often used by multiple functions.
+
+import (
+ "crypto/elliptic"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/gibheer/pkilib"
+)
+
+const (
+ RsaLowerLength = 2048
+ RsaUpperLength = 16384
+)
+
+var (
+ EcdsaCurves = []int{224, 256, 384, 521}
+)
+
+type (
+ // holds all certificate related flags, which need parsing afterwards
+ certFlagsContainer struct {
+ serialNumber int // the serial number for the cert
+ commonName string // the common name used in the cert
+ dnsNames string // all alternative names in the certificate (comma separated list)
+ ipAddresses string // all IP addresses in the certificate (comma separated list)
+ country string // the country names which should end up in the cert (comma separated list)
+ organization string // the organization names (comma separated list)
+ organizationalUnit string // the organizational units (comma separated list)
+ locality string // the city or locality (comma separated list)
+ province string // the province name (comma separated list)
+ streetAddress string // the street addresses of the organization (comma separated list)
+ postalCode string // the postal codes of the locality
+ }
+
+ // a container go gather all incoming flags for further processing
+ paramContainer struct {
+ outputPath string // path to output whatever is generated
+ cryptType string // type of something (private key)
+ length int // the length of something (private key)
+ privateKeyPath string // path to the private key
+ publicKeyPath string // path to the public key
+ signRequestPath string // path to the certificate sign request
+ certificateFlags *certFlagsContainer // container for certificate related flags
+ }
+
+ // a container for the refined flags
+ flagSet struct {
+ PrivateKey pkilib.PrivateKey
+ Output io.WriteCloser
+
+ // private key specific stuff
+ PrivateKeyGenerationFlags privateKeyGenerationFlags
+ }
+
+ privateKeyGenerationFlags struct {
+ Type string // type of the private key (rsa, ecdsa)
+ Curve elliptic.Curve // curve for ecdsa
+ Size int // bitsize for rsa
+ }
+
+ Flags struct {
+ flagset *flag.FlagSet // the flagset reference for printing the help
+ flag_container *paramContainer
+ Flags *flagSet // the end result of the flag setting
+
+ check_list []flagCheck // list of all checks
+ }
+
+ flagCheck func()(error)
+)
+
+// create a new flag handler with the name of the subfunction
+func NewFlags(method_name string) *Flags {
+ return &Flags{
+ Flags: &flagSet{},
+ flagset: flag.NewFlagSet(method_name, flag.ExitOnError),
+ check_list: make([]flagCheck, 0),
+ flag_container: &paramContainer{},
+ }
+}
+
+// check all parameters for validity
+func (f *Flags) Parse(options []string) error {
+ f.flagset.Parse(options)
+ for _, check := range f.check_list {
+ // TODO handle error in a betetr way (output specific help, not command help)
+ if err := check(); err != nil { return err }
+ }
+ return nil
+}
+
+// add the private key option to the requested flags
+func (f *Flags) AddPrivateKey() {
+ f.check_list = append(f.check_list, f.parsePrivateKey)
+ f.flagset.StringVar(&f.flag_container.privateKeyPath, "private-key", "", "path to the private key")
+}
+
+// check the private key flag and load the private key
+func (f *Flags) parsePrivateKey() error {
+ // check permissions of private key file
+ info, err := os.Stat(f.flag_container.privateKeyPath)
+ if err != nil { return fmt.Errorf("Error reading private key: %s", err) }
+ if info.Mode().Perm().String()[4:] != "------" {
+ return fmt.Errorf("private key file modifyable by others!")
+ }
+
+ pk, err := ReadPrivateKeyFile(f.flag_container.privateKeyPath)
+ if err != nil { return fmt.Errorf("Error reading private key: %s", err) }
+ f.Flags.PrivateKey = pk
+ return nil
+}
+
+// add the output parameter to the checklist
+func (f *Flags) AddOutput() {
+ f.check_list = append(f.check_list, f.parseOutput)
+ f.flagset.StringVar(&f.flag_container.outputPath, "output", "STDOUT", "path to the output or STDOUT")
+}
+
+// parse the output parameter and open the file handle
+func (f *Flags) parseOutput() error {
+ if f.flag_container.outputPath == "STDOUT" {
+ f.Flags.Output = os.Stdout
+ return nil
+ }
+ var err error
+ f.Flags.Output, err = os.OpenFile(
+ f.flag_container.outputPath,
+ os.O_WRONLY | os.O_APPEND | os.O_CREATE, // do not kill users files!
+ 0600,
+ )
+ if err != nil { return err }
+ return nil
+}
+
+// This function adds the private key generation flags.
+func (f *Flags) AddPrivateKeyGenerationFlags() {
+ f.check_list = append(f.check_list, f.parsePrivateKeyGenerationFlags)
+ f.flagset.StringVar(&f.flag_container.cryptType, "type", "ecdsa", "the type of the private key (ecdsa, rsa)")
+ f.flagset.IntVar(
+ &f.flag_container.length,
+ "length", 521,
+ fmt.Sprintf("%d - %d for rsa; %v for ecdsa", RsaLowerLength, RsaUpperLength, EcdsaCurves),
+ )
+}
+
+func (f *Flags) parsePrivateKeyGenerationFlags() error {
+ pk_type := f.flag_container.cryptType
+ f.Flags.PrivateKeyGenerationFlags.Type = pk_type
+ switch pk_type {
+ case "ecdsa":
+ switch f.flag_container.length {
+ case 224: f.Flags.PrivateKeyGenerationFlags.Curve = elliptic.P224()
+ case 256: f.Flags.PrivateKeyGenerationFlags.Curve = elliptic.P256()
+ case 384: f.Flags.PrivateKeyGenerationFlags.Curve = elliptic.P384()
+ case 521: f.Flags.PrivateKeyGenerationFlags.Curve = elliptic.P521()
+ default: return fmt.Errorf("Curve %d unknown!", f.flag_container.length)
+ }
+ case "rsa": f.Flags.PrivateKeyGenerationFlags.Size = f.flag_container.length
+ default: return fmt.Errorf("Type %s is unknown!", pk_type)
+ }
+ return nil
+}