Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding Shared access to multiple processes #100

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
13 changes: 11 additions & 2 deletions piv/pcsc_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import (
const rcSuccess = C.SCARD_S_SUCCESS

type scContext struct {
ctx C.SCARDCONTEXT
ctx C.SCARDCONTEXT
shared bool
}

func newSCContext() (*scContext, error) {
Expand All @@ -54,6 +55,10 @@ func (c *scContext) Close() error {
return scCheck(C.SCardReleaseContext(c.ctx))
}

func (c *scContext) SetShared() {
rajnikant12345 marked this conversation as resolved.
Show resolved Hide resolved
c.shared = true
}

func (c *scContext) ListReaders() ([]string, error) {
var n C.DWORD
rc := C.SCardListReaders(c.ctx, nil, nil, &n)
Expand Down Expand Up @@ -93,8 +98,12 @@ func (c *scContext) Connect(reader string) (*scHandle, error) {
handle C.SCARDHANDLE
activeProtocol C.DWORD
)
opt := C.SCARD_SHARE_EXCLUSIVE
if c.shared {
opt = C.SCARD_SHARE_SHARED
}
rc := C.SCardConnect(c.ctx, C.CString(reader),
C.SCARD_SHARE_EXCLUSIVE, C.SCARD_PROTOCOL_T1,
C.uint(opt), C.SCARD_PROTOCOL_T1,
&handle, &activeProtocol)
if err := scCheck(rc); err != nil {
return nil, err
Expand Down
14 changes: 12 additions & 2 deletions piv/pcsc_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ var (
const (
scardScopeSystem = 2
scardShareExclusive = 1
scardShareShared = 2
scardLeaveCard = 0
scardProtocolT1 = 2
scardPCIT1 = 0
Expand All @@ -54,7 +55,8 @@ func isRCNoReaders(rc uintptr) bool {
}

type scContext struct {
ctx syscall.Handle
ctx syscall.Handle
shared bool
}

func newSCContext() (*scContext, error) {
Expand All @@ -72,6 +74,10 @@ func newSCContext() (*scContext, error) {
return &scContext{ctx: ctx}, nil
}

func (c *scContext) SetShared() {
rajnikant12345 marked this conversation as resolved.
Show resolved Hide resolved
c.shared = true
}

func (c *scContext) Close() error {
r0, _, _ := procSCardReleaseContext.Call(uintptr(c.ctx))
return scCheck(r0)
Expand Down Expand Up @@ -127,10 +133,14 @@ func (c *scContext) Connect(reader string) (*scHandle, error) {
handle syscall.Handle
activeProtocol uint16
)
opt := scardShareExclusive
if c.shared {
opt = scardShareShared
}
r0, _, _ := procSCardConnectW.Call(
uintptr(c.ctx),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(reader))),
scardShareExclusive,
C.DWORD(opt),
scardProtocolT1,
uintptr(unsafe.Pointer(&handle)),
uintptr(activeProtocol),
Expand Down
32 changes: 30 additions & 2 deletions piv/piv.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,26 @@ func (yk *YubiKey) Close() error {
return err1
}

// clientConfigOpts holds options for creating a new ClientConfigOpt.
type clientConfigOpts struct {
// configure shared access to PIV hardware
shared bool
}

// ClientConfigOpt configures a specific option
type ClientConfigOpt func(*clientConfigOpts)

// WithSharedAccess configures PIV card to be shared by multiple processes
func WithSharedAccess() ClientConfigOpt {
return func(o *clientConfigOpts) {
o.shared = true
}
}

// Open connects to a YubiKey smart card.
func Open(card string) (*YubiKey, error) {
func Open(card string, opts ...ClientConfigOpt) (*YubiKey, error) {
rajnikant12345 marked this conversation as resolved.
Show resolved Hide resolved
var c client
c.setConfigOpts(opts...)
return c.Open(card)
}

Expand All @@ -137,6 +154,13 @@ type client struct {
//
// If nil, defaults to crypto.Rand.
Rand io.Reader
opts clientConfigOpts
}

func (c *client) setConfigOpts(opts ...ClientConfigOpt) {
for _, v := range opts {
v(&c.opts)
}
}

func (c *client) Cards() ([]string, error) {
rajnikant12345 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -148,12 +172,16 @@ func (c *client) Cards() ([]string, error) {
return ctx.ListReaders()
}

func (c *client) Open(card string) (*YubiKey, error) {
func (c *client) Open(card string, opts ...ClientConfigOpt) (*YubiKey, error) {
ctx, err := newSCContext()
if err != nil {
return nil, fmt.Errorf("connecting to smart card daemon: %w", err)
}

if c.opts.shared {
ctx.SetShared()
}

h, err := ctx.Connect(card)
if err != nil {
ctx.Close()
Expand Down
2 changes: 1 addition & 1 deletion piv/piv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func newTestYubiKey(t *testing.T) (*YubiKey, func()) {
if !canModifyYubiKey {
t.Skip("not running test that accesses yubikey, provide --wipe-yubikey flag")
}
yk, err := Open(card)
yk, err := Open(card, WithSharedAccess())
if err != nil {
t.Fatalf("getting new yubikey: %v", err)
}
Expand Down