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  }