mirror of https://github.com/status-im/op-geth.git
accounts/scwallet: flag to specify path to smartcard daemon (#19439)
* accounts/scwallet: Add a switch to enable smartcard support * accounts: change the meaning of the switch * disable card support in windows until tested * only activate account if pcscd socket file is present * the switch is now the path to the socket file * accounts/scwallet: holiman's review feedback * accounts/scwallet: send the path to go-pcsclite * accounts/scwallet: add default, per platform path * accounts/scwallet: fix error log warning * accounts/scwallet: update pcsc lib to latest * accounts/scwallet: use default path from pcsclite * scwallet: forgot to change switch name * cmd: minor style cleanups (error handling first, then happy path)
This commit is contained in:
parent
30263ad37d
commit
7a22da98b9
|
@ -152,8 +152,8 @@ func (hub *Hub) setPairing(wallet *Wallet, pairing *smartcardPairing) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHub creates a new hardware wallet manager for smartcards.
|
// NewHub creates a new hardware wallet manager for smartcards.
|
||||||
func NewHub(scheme string, datadir string) (*Hub, error) {
|
func NewHub(daemonPath string, scheme string, datadir string) (*Hub, error) {
|
||||||
context, err := pcsc.EstablishContext(pcsc.ScopeSystem)
|
context, err := pcsc.EstablishContext(daemonPath, pcsc.ScopeSystem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ var (
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
utils.ExternalSignerFlag,
|
utils.ExternalSignerFlag,
|
||||||
utils.NoUSBFlag,
|
utils.NoUSBFlag,
|
||||||
|
utils.SmartCardDaemonPathFlag,
|
||||||
utils.DashboardEnabledFlag,
|
utils.DashboardEnabledFlag,
|
||||||
utils.DashboardAddrFlag,
|
utils.DashboardAddrFlag,
|
||||||
utils.DashboardPortFlag,
|
utils.DashboardPortFlag,
|
||||||
|
|
|
@ -72,6 +72,7 @@ var AppHelpFlagGroups = []flagGroup{
|
||||||
utils.AncientFlag,
|
utils.AncientFlag,
|
||||||
utils.KeyStoreDirFlag,
|
utils.KeyStoreDirFlag,
|
||||||
utils.NoUSBFlag,
|
utils.NoUSBFlag,
|
||||||
|
utils.SmartCardDaemonPathFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
utils.TestnetFlag,
|
utils.TestnetFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
|
|
|
@ -58,6 +58,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p/netutil"
|
"github.com/ethereum/go-ethereum/p2p/netutil"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
||||||
|
pcsclite "github.com/gballet/go-libpcsclite"
|
||||||
cli "gopkg.in/urfave/cli.v1"
|
cli "gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -129,6 +130,11 @@ var (
|
||||||
Name: "nousb",
|
Name: "nousb",
|
||||||
Usage: "Disables monitoring for and managing USB hardware wallets",
|
Usage: "Disables monitoring for and managing USB hardware wallets",
|
||||||
}
|
}
|
||||||
|
SmartCardDaemonPathFlag = cli.StringFlag{
|
||||||
|
Name: "pcscdpath",
|
||||||
|
Usage: "Path to the smartcard daemon (pcscd) socket file",
|
||||||
|
Value: pcsclite.PCSCDSockName,
|
||||||
|
}
|
||||||
NetworkIdFlag = cli.Uint64Flag{
|
NetworkIdFlag = cli.Uint64Flag{
|
||||||
Name: "networkid",
|
Name: "networkid",
|
||||||
Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
|
Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
|
||||||
|
@ -1126,6 +1132,7 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
||||||
setWS(ctx, cfg)
|
setWS(ctx, cfg)
|
||||||
setNodeUserIdent(ctx, cfg)
|
setNodeUserIdent(ctx, cfg)
|
||||||
setDataDir(ctx, cfg)
|
setDataDir(ctx, cfg)
|
||||||
|
setSmartCard(ctx, cfg)
|
||||||
|
|
||||||
if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
|
if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
|
||||||
cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
|
cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
|
||||||
|
@ -1145,6 +1152,26 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setSmartCard(ctx *cli.Context, cfg *node.Config) {
|
||||||
|
// Skip enabling smartcards if no path is set
|
||||||
|
path := ctx.GlobalString(SmartCardDaemonPathFlag.Name)
|
||||||
|
if path == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Sanity check that the smartcard path is valid
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to verify smartcard daemon path", "path", path, "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fi.Mode()&os.ModeType != os.ModeSocket {
|
||||||
|
log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Smartcard daemon path exists and is a socket, enable it
|
||||||
|
cfg.SmartCardDaemonPath = path
|
||||||
|
}
|
||||||
|
|
||||||
func setDataDir(ctx *cli.Context, cfg *node.Config) {
|
func setDataDir(ctx *cli.Context, cfg *node.Config) {
|
||||||
switch {
|
switch {
|
||||||
case ctx.GlobalIsSet(DataDirFlag.Name):
|
case ctx.GlobalIsSet(DataDirFlag.Name):
|
||||||
|
|
|
@ -95,6 +95,9 @@ type Config struct {
|
||||||
// NoUSB disables hardware wallet monitoring and connectivity.
|
// NoUSB disables hardware wallet monitoring and connectivity.
|
||||||
NoUSB bool `toml:",omitempty"`
|
NoUSB bool `toml:",omitempty"`
|
||||||
|
|
||||||
|
// SmartCardDaemonPath is the path to the smartcard daemon's socket
|
||||||
|
SmartCardDaemonPath string `toml:",omitempty"`
|
||||||
|
|
||||||
// IPCPath is the requested location to place the IPC endpoint. If the path is
|
// IPCPath is the requested location to place the IPC endpoint. If the path is
|
||||||
// a simple file name, it is placed inside the data directory (or on the root
|
// a simple file name, it is placed inside the data directory (or on the root
|
||||||
// pipe path on Windows), whereas if it's a resolvable path name (absolute or
|
// pipe path on Windows), whereas if it's a resolvable path name (absolute or
|
||||||
|
@ -505,11 +508,13 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) {
|
||||||
backends = append(backends, trezorhub)
|
backends = append(backends, trezorhub)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Start a smart card hub
|
if len(conf.SmartCardDaemonPath) > 0 {
|
||||||
if schub, err := scwallet.NewHub(scwallet.Scheme, keydir); err != nil {
|
// Start a smart card hub
|
||||||
log.Warn(fmt.Sprintf("Failed to start smart card hub, disabling: %v", err))
|
if schub, err := scwallet.NewHub(conf.SmartCardDaemonPath, scwallet.Scheme, keydir); err != nil {
|
||||||
} else {
|
log.Warn(fmt.Sprintf("Failed to start smart card hub, disabling: %v", err))
|
||||||
backends = append(backends, schub)
|
} else {
|
||||||
|
backends = append(backends, schub)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,6 @@ const (
|
||||||
SCardPowever = 0x0010 /* Card is powered */
|
SCardPowever = 0x0010 /* Card is powered */
|
||||||
SCardNegotiable = 0x0020 /* Ready for PTS */
|
SCardNegotiable = 0x0020 /* Ready for PTS */
|
||||||
SCardSpecific = 0x0040 /* PTS has been set */
|
SCardSpecific = 0x0040 /* PTS has been set */
|
||||||
|
|
||||||
PCSCDSockName = "/run/pcscd/pcscd.comm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// List of commands to send to the daemon
|
// List of commands to send to the daemon
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// BSD 3-Clause License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019, Guillaume Ballet
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the copyright holder nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// +build dragonfly darwin freebsd netbsd openbsd solaris
|
||||||
|
|
||||||
|
package pcsc
|
||||||
|
|
||||||
|
const PCSCDSockName string = "/var/run/pcscd/pcscd.comm"
|
|
@ -0,0 +1,35 @@
|
||||||
|
// BSD 3-Clause License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019, Guillaume Ballet
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the copyright holder nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package pcsc
|
||||||
|
|
||||||
|
const PCSCDSockName string = "/run/pcscd/pcscd.comm"
|
|
@ -0,0 +1,35 @@
|
||||||
|
// BSD 3-Clause License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019, Guillaume Ballet
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
// list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the copyright holder nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package pcsc
|
||||||
|
|
||||||
|
const PCSCDSockName string = ""
|
|
@ -62,7 +62,7 @@ func messageSendWithHeader(command uint32, conn net.Conn, data []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientSetupSession prepares a communication channel for the client to talk to the server.
|
// clientSetupSession prepares a communication channel for the client to talk to the server.
|
||||||
// This is called by the application to create a socket for local IPC with the
|
// This is called by the application to create a socket for local IPC with the
|
||||||
// server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME.
|
// server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME.
|
||||||
/*
|
/*
|
||||||
|
@ -73,6 +73,10 @@ func messageSendWithHeader(command uint32, conn net.Conn, data []byte) error {
|
||||||
* @retval -1 The socket can not open a connection.
|
* @retval -1 The socket can not open a connection.
|
||||||
* @retval -1 Can not set the socket to non-blocking.
|
* @retval -1 Can not set the socket to non-blocking.
|
||||||
*/
|
*/
|
||||||
func clientSetupSession() (net.Conn, error) {
|
func clientSetupSession(daemonPath string) (net.Conn, error) {
|
||||||
return net.Dial("unix", PCSCDSockName)
|
path := PCSCDSockName
|
||||||
|
if len(daemonPath) > 0 {
|
||||||
|
path = daemonPath
|
||||||
|
}
|
||||||
|
return net.Dial("unix", path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,10 +56,10 @@ type Client struct {
|
||||||
// EstablishContext asks the PCSC daemon to create a context
|
// EstablishContext asks the PCSC daemon to create a context
|
||||||
// handle for further communication with connected cards and
|
// handle for further communication with connected cards and
|
||||||
// readers.
|
// readers.
|
||||||
func EstablishContext(scope uint32) (*Client, error) {
|
func EstablishContext(path string, scope uint32) (*Client, error) {
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
|
|
||||||
conn, err := clientSetupSession()
|
conn, err := clientSetupSession(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,10 +135,10 @@
|
||||||
"revisionTime": "2018-04-18T12:24:29Z"
|
"revisionTime": "2018-04-18T12:24:29Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "GXqHzd0XkPLX/iulpOncaxbxzZo=",
|
"checksumSHA1": "+fiJGimxPPRSfi9sED4Lp6ytBeo=",
|
||||||
"path": "github.com/gballet/go-libpcsclite",
|
"path": "github.com/gballet/go-libpcsclite",
|
||||||
"revision": "312b5175032f98274685a4dd81935a92ad2412a5",
|
"revision": "2fd9b619dd3c5d74acbd975f997a6441984d74a7",
|
||||||
"revisionTime": "2019-04-03T18:15:18Z"
|
"revisionTime": "2019-05-28T10:50:17Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "gxV/cPPLkByTdY8y172t7v4qcZA=",
|
"checksumSHA1": "gxV/cPPLkByTdY8y172t7v4qcZA=",
|
||||||
|
|
Loading…
Reference in New Issue