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