diff options
Diffstat (limited to 'files.go')
| -rw-r--r-- | files.go | 141 |
1 files changed, 141 insertions, 0 deletions
@@ -2,6 +2,8 @@ package main import ( "bufio" + "crypto/tls" + "encoding/pem" "errors" "fmt" "net/url" @@ -264,3 +266,142 @@ func ensurePath(fpath string) error { } return nil } + +func getIdentities() (Identities, error) { + idents := Identities{ + ByName: map[string]*tls.Config{}, + ByDomain: map[string]*tls.Config{}, + ByFolder: map[string]*tls.Config{}, + ByPage: map[string]*tls.Config{}, + } + + manifest, err := dataFilePath("identities") + if err != nil { + return idents, err + } + + f, err := os.Open(manifest) + if err != nil { + return idents, err + } + defer func() { _ = f.Close() }() + + var curident *tls.Config + rdr := bufio.NewScanner(f) + for rdr.Scan() { + line := rdr.Text() + if strings.HasPrefix(line, ":") { + kind, location, _ := strings.Cut(line[1:], " ") + switch kind { + case "domain": + idents.ByDomain[location] = curident + case "folder": + idents.ByFolder[location] = curident + case "page": + idents.ByPage[location] = curident + } + } else { + name := strings.TrimSuffix(line, ":") + curident, err = getIdentity(name) + if err != nil { + return idents, err + } + idents.ByName[name] = curident + } + } + if err := rdr.Err(); err != nil { + return idents, err + } + + return idents, nil +} + +func saveIdentities(idents Identities) error { + manifest, err := dataFilePath("identities") + if err != nil { + return err + } + + f, err := os.OpenFile(manifest, os.O_WRONLY|os.O_TRUNC, 0o600) + if err != nil { + return err + } + defer func() { _ = f.Close() }() + + for name, ident := range idents.ByName { + if _, err := fmt.Fprintf(f, "%s:\n", name); err != nil { + return err + } + + for domain, id := range idents.ByDomain { + if id != ident { + continue + } + if _, err := fmt.Fprintf(f, ":domain %s\n", domain); err != nil { + return err + } + } + for folder, id := range idents.ByFolder { + if id != ident { + continue + } + if _, err := fmt.Fprintf(f, ":folder %s\n", folder); err != nil { + return err + } + } + for page, id := range idents.ByPage { + if id != ident { + continue + } + if _, err := fmt.Fprintf(f, ":page %s\n", page); err != nil { + return err + } + } + } + + return nil +} + +func getIdentity(name string) (*tls.Config, error) { + fpath, err := dataFilePath("ident/" + name) + if err != nil { + return nil, err + } + + cert, err := tls.LoadX509KeyPair(fpath, fpath) + if err != nil { + return nil, err + } + + return identityForCert(cert), nil +} + +func saveIdentity(name string, privkeyDER, certDER []byte) (string, error) { + fpath, err := dataFilePath("ident/" + name) + if err != nil { + return "", err + } + + f, err := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0o600) + if err != nil { + return "", err + } + defer func() { _ = f.Close() }() + + if err := pem.Encode(f, &pem.Block{Type: "PRIVATE KEY", Bytes: privkeyDER}); err != nil { + return "", err + } + if err := pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: certDER}); err != nil { + return "", err + } + + return fpath, nil +} + +func removeIdentity(name string) error { + fpath, err := dataFilePath("ident/" + name) + if err != nil { + return err + } + return os.Remove(fpath) +} |
