mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
all: strict unlock API by rpc
This commit is contained in:
parent
d79b8b5492
commit
848ab4682b
12 changed files with 63 additions and 49 deletions
|
|
@ -45,7 +45,7 @@ type Manager struct {
|
||||||
|
|
||||||
// NewManager creates a generic account manager to sign transaction via various
|
// NewManager creates a generic account manager to sign transaction via various
|
||||||
// supported backends.
|
// supported backends.
|
||||||
func NewManager(insecureUnlockAllowed bool, backends ...Backend) *Manager {
|
func NewManager(config *Config, backends ...Backend) *Manager {
|
||||||
// Retrieve the initial list of wallets from the backends and sort by URL
|
// Retrieve the initial list of wallets from the backends and sort by URL
|
||||||
var wallets []Wallet
|
var wallets []Wallet
|
||||||
for _, backend := range backends {
|
for _, backend := range backends {
|
||||||
|
|
@ -60,7 +60,7 @@ func NewManager(insecureUnlockAllowed bool, backends ...Backend) *Manager {
|
||||||
}
|
}
|
||||||
// Assemble the account manager and return
|
// Assemble the account manager and return
|
||||||
am := &Manager{
|
am := &Manager{
|
||||||
config: &Config{insecureUnlockAllowed},
|
config: config,
|
||||||
backends: make(map[reflect.Type][]Backend),
|
backends: make(map[reflect.Type][]Backend),
|
||||||
updaters: subs,
|
updaters: subs,
|
||||||
updates: updates,
|
updates: updates,
|
||||||
|
|
|
||||||
|
|
@ -397,18 +397,9 @@ func startNode(ctx *cli.Context, stack *node.Node) {
|
||||||
|
|
||||||
// unlockAccounts unlocks any account specifically requested.
|
// unlockAccounts unlocks any account specifically requested.
|
||||||
func unlockAccounts(ctx *cli.Context, stack *node.Node) {
|
func unlockAccounts(ctx *cli.Context, stack *node.Node) {
|
||||||
// personalExposed checks whether personal API is exposed by http.
|
// If insecure account unlocking is not allowed if node's APIs are exposed to external.
|
||||||
personalExposed := func() bool {
|
// Print warning log to user and skip unlocking.
|
||||||
for _, module := range stack.Config().HTTPModules {
|
if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() {
|
||||||
if module == "personal" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// If insecure account unlocking is not allowed and account-related APIs are exposed by http,
|
|
||||||
// print warning log to user and skip unlocking.
|
|
||||||
if !stack.Config().InsecureUnlockAllowed && personalExposed() {
|
|
||||||
log.Warn("Not safe to unlock account, please enable `allow-insecure-unlock` flag if necessary")
|
log.Warn("Not safe to unlock account, please enable `allow-insecure-unlock` flag if necessary")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ import (
|
||||||
|
|
||||||
// EthAPIBackend implements ethapi.Backend for full nodes
|
// EthAPIBackend implements ethapi.Backend for full nodes
|
||||||
type EthAPIBackend struct {
|
type EthAPIBackend struct {
|
||||||
|
extRPCEnabled bool
|
||||||
eth *Ethereum
|
eth *Ethereum
|
||||||
gpo *gasprice.Oracle
|
gpo *gasprice.Oracle
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +214,10 @@ func (b *EthAPIBackend) AccountManager() *accounts.Manager {
|
||||||
return b.eth.AccountManager()
|
return b.eth.AccountManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *EthAPIBackend) ExtRPCEnabled() bool {
|
||||||
|
return b.extRPCEnabled
|
||||||
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
|
func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
|
||||||
sections, _, _ := b.eth.bloomIndexer.Sections()
|
sections, _, _ := b.eth.bloomIndexer.Sections()
|
||||||
return params.BloomBitsBlocks, sections
|
return params.BloomBitsBlocks, sections
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
eth.miner = miner.New(eth, chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock)
|
eth.miner = miner.New(eth, chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, config.MinerGasCeil, eth.isLocalBlock)
|
||||||
eth.miner.SetExtra(makeExtraData(config.MinerExtraData))
|
eth.miner.SetExtra(makeExtraData(config.MinerExtraData))
|
||||||
|
|
||||||
eth.APIBackend = &EthAPIBackend{eth, nil}
|
eth.APIBackend = &EthAPIBackend{ctx.ExtRPCEnabled(), eth, nil}
|
||||||
gpoParams := config.GPO
|
gpoParams := config.GPO
|
||||||
if gpoParams.Default == nil {
|
if gpoParams.Default == nil {
|
||||||
gpoParams.Default = config.MinerGasPrice
|
gpoParams.Default = config.MinerGasPrice
|
||||||
|
|
|
||||||
|
|
@ -318,9 +318,10 @@ func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (commo
|
||||||
// the given password for duration seconds. If duration is nil it will use a
|
// the given password for duration seconds. If duration is nil it will use a
|
||||||
// default of 300 seconds. It returns an indication if the account was unlocked.
|
// default of 300 seconds. It returns an indication if the account was unlocked.
|
||||||
func (s *PrivateAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) {
|
func (s *PrivateAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) {
|
||||||
// When the API is exposed by HTTP, unless the user explicitly specifies to
|
// When the API is exposed by external RPC(http, ws etc), unless the user
|
||||||
// allow the insecure account unlocking, otherwise it is disabled.
|
// explicitly specifies to allow the insecure account unlocking, otherwise
|
||||||
if isHttp, ok := ctx.Value("http").(bool); ok && isHttp && !s.b.AccountManager().Config().InsecureUnlockAllowed {
|
// it is disabled.
|
||||||
|
if s.b.ExtRPCEnabled() && !s.b.AccountManager().Config().InsecureUnlockAllowed {
|
||||||
return false, errors.New("not safe to unlock account, please enable `allow-insecure-unlock` flag if necessary")
|
return false, errors.New("not safe to unlock account, please enable `allow-insecure-unlock` flag if necessary")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ type Backend interface {
|
||||||
ChainDb() ethdb.Database
|
ChainDb() ethdb.Database
|
||||||
EventMux() *event.TypeMux
|
EventMux() *event.TypeMux
|
||||||
AccountManager() *accounts.Manager
|
AccountManager() *accounts.Manager
|
||||||
|
ExtRPCEnabled() bool
|
||||||
|
|
||||||
// BlockChain API
|
// BlockChain API
|
||||||
SetHead(number uint64)
|
SetHead(number uint64)
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type LesApiBackend struct {
|
type LesApiBackend struct {
|
||||||
|
extRPCEnabled bool
|
||||||
eth *LightEthereum
|
eth *LightEthereum
|
||||||
gpo *gasprice.Oracle
|
gpo *gasprice.Oracle
|
||||||
}
|
}
|
||||||
|
|
@ -187,6 +188,10 @@ func (b *LesApiBackend) AccountManager() *accounts.Manager {
|
||||||
return b.eth.accountManager
|
return b.eth.accountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *LesApiBackend) ExtRPCEnabled() bool {
|
||||||
|
return b.extRPCEnabled
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
|
func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
|
||||||
if b.eth.bloomIndexer == nil {
|
if b.eth.bloomIndexer == nil {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction)
|
log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction)
|
||||||
leth.blockchain.DisableCheckFreq()
|
leth.blockchain.DisableCheckFreq()
|
||||||
}
|
}
|
||||||
leth.ApiBackend = &LesApiBackend{leth, nil}
|
leth.ApiBackend = &LesApiBackend{ctx.ExtRPCEnabled(), leth, nil}
|
||||||
|
|
||||||
gpoParams := config.GPO
|
gpoParams := config.GPO
|
||||||
if gpoParams.Default == nil {
|
if gpoParams.Default == nil {
|
||||||
|
|
|
||||||
|
|
@ -109,29 +109,6 @@ type Config struct {
|
||||||
// for ephemeral nodes).
|
// for ephemeral nodes).
|
||||||
HTTPPort int `toml:",omitempty"`
|
HTTPPort int `toml:",omitempty"`
|
||||||
|
|
||||||
// GraphQLHost is the host interface on which to start the GraphQL server. If this
|
|
||||||
// field is empty, no GraphQL API endpoint will be started.
|
|
||||||
GraphQLHost string `toml:",omitempty"`
|
|
||||||
|
|
||||||
// GraphQLPort is the TCP port number on which to start the GraphQL server. The
|
|
||||||
// default zero value is/ valid and will pick a port number randomly (useful
|
|
||||||
// for ephemeral nodes).
|
|
||||||
GraphQLPort int `toml:",omitempty"`
|
|
||||||
|
|
||||||
// GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting
|
|
||||||
// clients. Please be aware that CORS is a browser enforced security, it's fully
|
|
||||||
// useless for custom HTTP clients.
|
|
||||||
GraphQLCors []string `toml:",omitempty"`
|
|
||||||
|
|
||||||
// GraphQLVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
|
|
||||||
// This is by default {'localhost'}. Using this prevents attacks like
|
|
||||||
// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
|
|
||||||
// origin. These attacks do not utilize CORS, since they are not cross-domain.
|
|
||||||
// By explicitly checking the Host-header, the server will not allow requests
|
|
||||||
// made against the server with a malicious host domain.
|
|
||||||
// Requests using ip address directly are not affected
|
|
||||||
GraphQLVirtualHosts []string `toml:",omitempty"`
|
|
||||||
|
|
||||||
// HTTPCors is the Cross-Origin Resource Sharing header to send to requesting
|
// HTTPCors is the Cross-Origin Resource Sharing header to send to requesting
|
||||||
// clients. Please be aware that CORS is a browser enforced security, it's fully
|
// clients. Please be aware that CORS is a browser enforced security, it's fully
|
||||||
// useless for custom HTTP clients.
|
// useless for custom HTTP clients.
|
||||||
|
|
@ -181,6 +158,29 @@ type Config struct {
|
||||||
// private APIs to untrusted users is a major security risk.
|
// private APIs to untrusted users is a major security risk.
|
||||||
WSExposeAll bool `toml:",omitempty"`
|
WSExposeAll bool `toml:",omitempty"`
|
||||||
|
|
||||||
|
// GraphQLHost is the host interface on which to start the GraphQL server. If this
|
||||||
|
// field is empty, no GraphQL API endpoint will be started.
|
||||||
|
GraphQLHost string `toml:",omitempty"`
|
||||||
|
|
||||||
|
// GraphQLPort is the TCP port number on which to start the GraphQL server. The
|
||||||
|
// default zero value is/ valid and will pick a port number randomly (useful
|
||||||
|
// for ephemeral nodes).
|
||||||
|
GraphQLPort int `toml:",omitempty"`
|
||||||
|
|
||||||
|
// GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting
|
||||||
|
// clients. Please be aware that CORS is a browser enforced security, it's fully
|
||||||
|
// useless for custom HTTP clients.
|
||||||
|
GraphQLCors []string `toml:",omitempty"`
|
||||||
|
|
||||||
|
// GraphQLVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
|
||||||
|
// This is by default {'localhost'}. Using this prevents attacks like
|
||||||
|
// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
|
||||||
|
// origin. These attacks do not utilize CORS, since they are not cross-domain.
|
||||||
|
// By explicitly checking the Host-header, the server will not allow requests
|
||||||
|
// made against the server with a malicious host domain.
|
||||||
|
// Requests using ip address directly are not affected
|
||||||
|
GraphQLVirtualHosts []string `toml:",omitempty"`
|
||||||
|
|
||||||
// Logger is a custom logger to use with the p2p.Server.
|
// Logger is a custom logger to use with the p2p.Server.
|
||||||
Logger log.Logger `toml:",omitempty"`
|
Logger log.Logger `toml:",omitempty"`
|
||||||
|
|
||||||
|
|
@ -273,6 +273,12 @@ func DefaultWSEndpoint() string {
|
||||||
return config.WSEndpoint()
|
return config.WSEndpoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtRPCEnabled returns the indicator whether node enables the external
|
||||||
|
// RPC(http, ws or graphql).
|
||||||
|
func (c *Config) ExtRPCEnabled() bool {
|
||||||
|
return c.HTTPHost != "" || c.WSHost != "" || c.GraphQLHost != ""
|
||||||
|
}
|
||||||
|
|
||||||
// NodeName returns the devp2p node identifier.
|
// NodeName returns the devp2p node identifier.
|
||||||
func (c *Config) NodeName() string {
|
func (c *Config) NodeName() string {
|
||||||
name := c.name()
|
name := c.name()
|
||||||
|
|
@ -500,7 +506,7 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return accounts.NewManager(conf.InsecureUnlockAllowed, backends...), ephemeral, nil
|
return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: conf.InsecureUnlockAllowed}, backends...), ephemeral, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var warnLock sync.Mutex
|
var warnLock sync.Mutex
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,12 @@ func (ctx *ServiceContext) Service(service interface{}) error {
|
||||||
return ErrServiceUnknown
|
return ErrServiceUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExtRPCEnabled returns the indicator whether node enables the external
|
||||||
|
// RPC(http, ws or graphql).
|
||||||
|
func (ctx *ServiceContext) ExtRPCEnabled() bool {
|
||||||
|
return ctx.config.ExtRPCEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceConstructor is the function signature of the constructors needed to be
|
// ServiceConstructor is the function signature of the constructors needed to be
|
||||||
// registered for service instantiation.
|
// registered for service instantiation.
|
||||||
type ServiceConstructor func(ctx *ServiceContext) (Service, error)
|
type ServiceConstructor func(ctx *ServiceContext) (Service, error)
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx = context.WithValue(ctx, "remote", r.RemoteAddr)
|
ctx = context.WithValue(ctx, "remote", r.RemoteAddr)
|
||||||
ctx = context.WithValue(ctx, "scheme", r.Proto)
|
ctx = context.WithValue(ctx, "scheme", r.Proto)
|
||||||
ctx = context.WithValue(ctx, "local", r.Host)
|
ctx = context.WithValue(ctx, "local", r.Host)
|
||||||
ctx = context.WithValue(ctx, "http", true)
|
|
||||||
if ua := r.Header.Get("User-Agent"); ua != "" {
|
if ua := r.Header.Get("User-Agent"); ua != "" {
|
||||||
ctx = context.WithValue(ctx, "User-Agent", ua)
|
ctx = context.WithValue(ctx, "User-Agent", ua)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ func StartClefAccountManager(ksLocation string, nousb, lightKDF bool) *accounts.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Clef doesn't allow insecure http account unlock.
|
// Clef doesn't allow insecure http account unlock.
|
||||||
return accounts.NewManager(false, backends...)
|
return accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, backends...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MetadataFromContext extracts Metadata from a given context.Context
|
// MetadataFromContext extracts Metadata from a given context.Context
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue