github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/cmds/upspinsos/service.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "flag" 9 "fmt" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "regexp" 15 "strings" 16 ) 17 18 var ( 19 upspinConfigDir = flag.String("configdir", filepath.Join(os.Getenv("HOME"), "upspin"), "path for Upspin config file") 20 upspinKeyDir = flag.String("keydir", filepath.Join(os.Getenv("HOME"), ".ssh"), "path for username directory to hold key files") 21 ) 22 23 type UpspinService struct { 24 Configured bool 25 User string 26 Dir string 27 Store string 28 Seed string 29 } 30 31 func makeUserDirectories(dir string) error { 32 if _, err := os.Stat(dir); os.IsNotExist(err) { 33 if err := os.MkdirAll(dir, 0777); err != nil { 34 return err 35 } 36 return filepath.Walk(dir, func(name string, info os.FileInfo, err error) error { 37 if err == nil { 38 err = os.Chown(name, 1000, 1000) 39 } 40 return err 41 }) 42 } 43 return nil 44 } 45 46 func getFileData(path string) map[string]string { 47 userData := make(map[string]string) 48 b, err := ioutil.ReadFile(path) 49 if err != nil { 50 // start in unconfigured mode using empty map 51 return userData 52 } 53 // regex for finding key-val separator ": [remote,]" and port ":443" 54 splitpoint := regexp.MustCompile("(: )(.*,|)") 55 port := regexp.MustCompile("(:443)") 56 for _, s := range strings.Split(string(b), "\n") { 57 s := port.ReplaceAllString(s, "") 58 keyval := splitpoint.Split(s, -1) 59 if len(keyval) == 2 { 60 userData[keyval[0]] = keyval[1] 61 } 62 } 63 return userData 64 } 65 66 func (us UpspinService) setFileData(path string) error { 67 f, err := os.Create(path) 68 if err != nil { 69 return err 70 } 71 defer f.Close() 72 f.WriteString(fmt.Sprintf("username: %v\n", us.User)) 73 // hardcoded default server prefix and suffix 74 f.WriteString(fmt.Sprintf("dirserver: remote,%v:443\n", us.Dir)) 75 f.WriteString(fmt.Sprintf("storeserver: remote,%v:443\n", us.Store)) 76 f.WriteString("packing: ee\n") 77 return nil 78 } 79 80 func (us UpspinService) setKeys(path string) error { 81 // check if keys are set already 82 f, err := os.Open(path) 83 if err != nil { 84 return err 85 } 86 defer f.Close() 87 args := []string{"keygen", fmt.Sprintf("-secretseed=%v", us.Seed)} 88 // if the directory is populated, rotate the keys instead of generating new ones 89 // this method of appending args is ugly, but they have to be in this specific order: 90 // upspin keygen <-rotate> -secretseed=<seed> path 91 if _, err = f.Readdir(1); err == nil { 92 args = append(args, "-rotate") 93 } 94 95 return exec.Command("upspin", append(args, path)...).Run() 96 } 97 98 func (us *UpspinService) Update() { 99 data := getFileData(filepath.Join(*upspinConfigDir, "config")) 100 us.User = data["username"] 101 us.Dir = data["dirserver"] 102 us.Store = data["storeserver"] 103 } 104 105 func (us *UpspinService) ToggleFlag() { 106 us.Configured = !us.Configured 107 } 108 109 func (us *UpspinService) SetConfig(new UpspinAcctJsonMsg) error { 110 us.User = new.User 111 us.Dir = new.Dir 112 us.Store = new.Store 113 us.Seed = new.Seed 114 makeUserDirectories(*upspinConfigDir) 115 if err := us.setFileData(filepath.Join(*upspinConfigDir, "config")); err != nil { 116 return err 117 } 118 fullKeyPath := filepath.Join(*upspinKeyDir, us.User) 119 makeUserDirectories(fullKeyPath) 120 if err := us.setKeys(fullKeyPath); err != nil { 121 return err 122 } 123 return nil 124 } 125 126 func NewUpspinService() (*UpspinService, error) { 127 data := getFileData(filepath.Join(*upspinConfigDir, "config")) 128 config := false 129 if len(data) > 0 { 130 config = true 131 } 132 return &UpspinService{ 133 Configured: config, 134 User: data["username"], 135 Dir: data["dirserver"], 136 Store: data["storeserver"], 137 Seed: "", 138 }, nil 139 }