github.com/codingfuture/orig-energi3@v0.8.4/cmd/swarm/access.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2018 The go-ethereum Authors 3 // This file is part of Energi Core. 4 // 5 // Energi Core is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Energi Core is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Energi Core. If not, see <http://www.gnu.org/licenses/>. 17 18 package main 19 20 import ( 21 "crypto/rand" 22 "encoding/json" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "strings" 27 28 "github.com/ethereum/go-ethereum/cmd/utils" 29 "github.com/ethereum/go-ethereum/swarm/api" 30 "github.com/ethereum/go-ethereum/swarm/api/client" 31 "gopkg.in/urfave/cli.v1" 32 ) 33 34 var ( 35 salt = make([]byte, 32) 36 accessCommand = cli.Command{ 37 CustomHelpTemplate: helpTemplate, 38 Name: "access", 39 Usage: "encrypts a reference and embeds it into a root manifest", 40 ArgsUsage: "<ref>", 41 Description: "encrypts a reference and embeds it into a root manifest", 42 Subcommands: []cli.Command{ 43 { 44 CustomHelpTemplate: helpTemplate, 45 Name: "new", 46 Usage: "encrypts a reference and embeds it into a root manifest", 47 ArgsUsage: "<ref>", 48 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 49 Subcommands: []cli.Command{ 50 { 51 Action: accessNewPass, 52 CustomHelpTemplate: helpTemplate, 53 Flags: []cli.Flag{ 54 utils.PasswordFileFlag, 55 SwarmDryRunFlag, 56 }, 57 Name: "pass", 58 Usage: "encrypts a reference with a password and embeds it into a root manifest", 59 ArgsUsage: "<ref>", 60 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 61 }, 62 { 63 Action: accessNewPK, 64 CustomHelpTemplate: helpTemplate, 65 Flags: []cli.Flag{ 66 utils.PasswordFileFlag, 67 SwarmDryRunFlag, 68 SwarmAccessGrantKeyFlag, 69 }, 70 Name: "pk", 71 Usage: "encrypts a reference with the node's private key and a given grantee's public key and embeds it into a root manifest", 72 ArgsUsage: "<ref>", 73 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 74 }, 75 { 76 Action: accessNewACT, 77 CustomHelpTemplate: helpTemplate, 78 Flags: []cli.Flag{ 79 SwarmAccessGrantKeysFlag, 80 SwarmDryRunFlag, 81 utils.PasswordFileFlag, 82 }, 83 Name: "act", 84 Usage: "encrypts a reference with the node's private key and a given grantee's public key and embeds it into a root manifest", 85 ArgsUsage: "<ref>", 86 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 87 }, 88 }, 89 }, 90 }, 91 } 92 ) 93 94 func init() { 95 if _, err := io.ReadFull(rand.Reader, salt); err != nil { 96 panic("reading from crypto/rand failed: " + err.Error()) 97 } 98 } 99 100 func accessNewPass(ctx *cli.Context) { 101 args := ctx.Args() 102 if len(args) != 1 { 103 utils.Fatalf("Expected 1 argument - the ref") 104 } 105 106 var ( 107 ae *api.AccessEntry 108 accessKey []byte 109 err error 110 ref = args[0] 111 password = getPassPhrase("", 0, makePasswordList(ctx)) 112 dryRun = ctx.Bool(SwarmDryRunFlag.Name) 113 ) 114 accessKey, ae, err = api.DoPassword(ctx, password, salt) 115 if err != nil { 116 utils.Fatalf("error getting session key: %v", err) 117 } 118 m, err := api.GenerateAccessControlManifest(ctx, ref, accessKey, ae) 119 if err != nil { 120 utils.Fatalf("had an error generating the manifest: %v", err) 121 } 122 if dryRun { 123 err = printManifests(m, nil) 124 if err != nil { 125 utils.Fatalf("had an error printing the manifests: %v", err) 126 } 127 } else { 128 err = uploadManifests(ctx, m, nil) 129 if err != nil { 130 utils.Fatalf("had an error uploading the manifests: %v", err) 131 } 132 } 133 } 134 135 func accessNewPK(ctx *cli.Context) { 136 args := ctx.Args() 137 if len(args) != 1 { 138 utils.Fatalf("Expected 1 argument - the ref") 139 } 140 141 var ( 142 ae *api.AccessEntry 143 sessionKey []byte 144 err error 145 ref = args[0] 146 privateKey = getPrivKey(ctx) 147 granteePublicKey = ctx.String(SwarmAccessGrantKeyFlag.Name) 148 dryRun = ctx.Bool(SwarmDryRunFlag.Name) 149 ) 150 sessionKey, ae, err = api.DoPK(ctx, privateKey, granteePublicKey, salt) 151 if err != nil { 152 utils.Fatalf("error getting session key: %v", err) 153 } 154 m, err := api.GenerateAccessControlManifest(ctx, ref, sessionKey, ae) 155 if err != nil { 156 utils.Fatalf("had an error generating the manifest: %v", err) 157 } 158 if dryRun { 159 err = printManifests(m, nil) 160 if err != nil { 161 utils.Fatalf("had an error printing the manifests: %v", err) 162 } 163 } else { 164 err = uploadManifests(ctx, m, nil) 165 if err != nil { 166 utils.Fatalf("had an error uploading the manifests: %v", err) 167 } 168 } 169 } 170 171 func accessNewACT(ctx *cli.Context) { 172 args := ctx.Args() 173 if len(args) != 1 { 174 utils.Fatalf("Expected 1 argument - the ref") 175 } 176 177 var ( 178 ae *api.AccessEntry 179 actManifest *api.Manifest 180 accessKey []byte 181 err error 182 ref = args[0] 183 pkGrantees = []string{} 184 passGrantees = []string{} 185 pkGranteesFilename = ctx.String(SwarmAccessGrantKeysFlag.Name) 186 passGranteesFilename = ctx.String(utils.PasswordFileFlag.Name) 187 privateKey = getPrivKey(ctx) 188 dryRun = ctx.Bool(SwarmDryRunFlag.Name) 189 ) 190 if pkGranteesFilename == "" && passGranteesFilename == "" { 191 utils.Fatalf("you have to provide either a grantee public-keys file or an encryption passwords file (or both)") 192 } 193 194 if pkGranteesFilename != "" { 195 bytes, err := ioutil.ReadFile(pkGranteesFilename) 196 if err != nil { 197 utils.Fatalf("had an error reading the grantee public key list") 198 } 199 pkGrantees = strings.Split(strings.Trim(string(bytes), "\n"), "\n") 200 } 201 202 if passGranteesFilename != "" { 203 bytes, err := ioutil.ReadFile(passGranteesFilename) 204 if err != nil { 205 utils.Fatalf("could not read password filename: %v", err) 206 } 207 passGrantees = strings.Split(strings.Trim(string(bytes), "\n"), "\n") 208 } 209 accessKey, ae, actManifest, err = api.DoACT(ctx, privateKey, salt, pkGrantees, passGrantees) 210 if err != nil { 211 utils.Fatalf("error generating ACT manifest: %v", err) 212 } 213 214 if err != nil { 215 utils.Fatalf("error getting session key: %v", err) 216 } 217 m, err := api.GenerateAccessControlManifest(ctx, ref, accessKey, ae) 218 if err != nil { 219 utils.Fatalf("error generating root access manifest: %v", err) 220 } 221 222 if dryRun { 223 err = printManifests(m, actManifest) 224 if err != nil { 225 utils.Fatalf("had an error printing the manifests: %v", err) 226 } 227 } else { 228 err = uploadManifests(ctx, m, actManifest) 229 if err != nil { 230 utils.Fatalf("had an error uploading the manifests: %v", err) 231 } 232 } 233 } 234 235 func printManifests(rootAccessManifest, actManifest *api.Manifest) error { 236 js, err := json.Marshal(rootAccessManifest) 237 if err != nil { 238 return err 239 } 240 fmt.Println(string(js)) 241 242 if actManifest != nil { 243 js, err := json.Marshal(actManifest) 244 if err != nil { 245 return err 246 } 247 fmt.Println(string(js)) 248 } 249 return nil 250 } 251 252 func uploadManifests(ctx *cli.Context, rootAccessManifest, actManifest *api.Manifest) error { 253 bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 254 client := client.NewClient(bzzapi) 255 256 var ( 257 key string 258 err error 259 ) 260 if actManifest != nil { 261 key, err = client.UploadManifest(actManifest, false) 262 if err != nil { 263 return err 264 } 265 266 rootAccessManifest.Entries[0].Access.Act = key 267 } 268 key, err = client.UploadManifest(rootAccessManifest, false) 269 if err != nil { 270 return err 271 } 272 fmt.Println(key) 273 return nil 274 } 275 276 // makePasswordList reads password lines from the file specified by the global --password flag 277 // and also by the same subcommand --password flag. 278 // This function ia a fork of utils.MakePasswordList to lookup cli context for subcommand. 279 // Function ctx.SetGlobal is not setting the global flag value that can be accessed 280 // by ctx.GlobalString using the current version of cli package. 281 func makePasswordList(ctx *cli.Context) []string { 282 path := ctx.GlobalString(utils.PasswordFileFlag.Name) 283 if path == "" { 284 path = ctx.String(utils.PasswordFileFlag.Name) 285 if path == "" { 286 return nil 287 } 288 } 289 text, err := ioutil.ReadFile(path) 290 if err != nil { 291 utils.Fatalf("Failed to read password file: %v", err) 292 } 293 lines := strings.Split(string(text), "\n") 294 // Sanitise DOS line endings. 295 for i := range lines { 296 lines[i] = strings.TrimRight(lines[i], "\r") 297 } 298 return lines 299 }