1// Copyright 2019 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package engine
5
6import (
7	"errors"
8
9	"github.com/keybase/client/go/libkb"
10	keybase1 "github.com/keybase/client/go/protocol/keybase1"
11)
12
13// PassphraseCheck is an engine that checks if given passphrase matches current
14// user's passphrase.
15type PassphraseCheck struct {
16	arg    *keybase1.PassphraseCheckArg
17	result bool
18	libkb.Contextified
19}
20
21func NewPassphraseCheck(g *libkb.GlobalContext, a *keybase1.PassphraseCheckArg) *PassphraseCheck {
22	return &PassphraseCheck{
23		arg:          a,
24		Contextified: libkb.NewContextified(g),
25	}
26}
27
28// Name provides the name of the engine for the engine interface
29func (c *PassphraseCheck) Name() string {
30	return "PassphraseCheck"
31}
32
33// Prereqs returns engine prereqs
34func (c *PassphraseCheck) Prereqs() Prereqs {
35	return Prereqs{Device: true}
36}
37
38// RequiredUIs returns the required UIs.
39func (c *PassphraseCheck) RequiredUIs() []libkb.UIKind {
40	return []libkb.UIKind{}
41}
42
43// SubConsumers requires the other UI consumers of this engine
44func (c *PassphraseCheck) SubConsumers() []libkb.UIConsumer {
45	return []libkb.UIConsumer{}
46}
47
48// Run the engine
49func (c *PassphraseCheck) Run(mctx libkb.MetaContext) (err error) {
50	defer mctx.Trace("PassphraseCheck#Run", &err)()
51
52	passphrase := c.arg.Passphrase
53	if passphrase == "" {
54		username := c.G().GetEnv().GetUsername().String()
55		promptArg := libkb.DefaultPassphrasePromptArg(mctx, username)
56		if !mctx.UIs().HasUI(libkb.SecretUIKind) {
57			return errors.New("Passphrase was not passed in arguments and SecretUI is not available")
58		}
59		res, err := mctx.UIs().SecretUI.GetPassphrase(promptArg, nil)
60		if err != nil {
61			return err
62		}
63		passphrase = res.Passphrase
64	}
65
66	_, err = libkb.VerifyPassphraseForLoggedInUser(mctx, passphrase)
67	if err != nil {
68		if _, ok := err.(libkb.PassphraseError); ok {
69			// Swallow passphrase errors, return `false` that the passphrase
70			// provided was incorrect.
71			c.result = false
72			return nil
73		}
74		// There was some other error.
75		return err
76	}
77	// No error, passphrase was correct.
78	c.result = true
79	return nil
80}
81
82// GetResult returns result of passphrase check, if Run() ran without errors.
83// False means passphrase was incorrect, true means it was correct.
84func (c *PassphraseCheck) GetResult() bool {
85	return c.result
86}
87