Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# make debug PKG=./pkg/util
PKG ?= ./...
DLV_PORT ?= 38697
COMMAND ?=

test:
go test $(PKG)

test-debug:
dlv test $(PKG) --headless --listen=:$(DLV_PORT) --api-version=2

build:
go build

dev:
go run main.go app.go $(COMMAND)

.PHONY: test debug build dev
46 changes: 19 additions & 27 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ package main

import (
"context"
"fmt"
"os"
"sort"

ap "passline/pkg/action"
"passline/pkg/config"
"passline/pkg/ctxutil"
"passline/pkg/util"

"github.com/blang/semver"
ucli "github.com/urfave/cli/v2"
ucli "github.com/urfave/cli/v3"
"golang.org/x/term"
)

func setupApp(ctx context.Context, sv semver.Version) (context.Context, *ucli.App) {
func setupApp(ctx context.Context, sv semver.Version) (context.Context, *ucli.Command) {
// try to load config
cfg, err := config.Get()
cfg, err := config.Get(util.OSFileSystem{})
if err != nil {
os.Exit(ap.ExitConfig)
}
Expand All @@ -30,27 +30,15 @@ func setupApp(ctx context.Context, sv semver.Version) (context.Context, *ucli.Ap
os.Exit(ap.ExitUnknown)
}

app := ucli.NewApp()
app.Name = "Passline"
app.Usage = "Password manager"
app.HelpName = "passline"
app.Version = sv.String()
app.Description = "Password manager for the command line"
app.EnableBashCompletion = true

// Append website information to default helper print
app.CustomAppHelpTemplate = fmt.Sprintf(`%s
WEBSITE:
https://github.com/perryrh0dan/passline

`, ucli.AppHelpTemplate)
var app = ucli.Command{
Name: "Passline",
Usage: "Password manager",
Version: sv.String(),
Description: "Password manager for the command line",
EnableShellCompletion: true,
}

app.Flags = []ucli.Flag{
&ucli.BoolFlag{
Name: "print",
Aliases: []string{"p"},
Usage: "Prints the password to the terminal",
},
&ucli.BoolFlag{
Name: "yes",
Usage: "Assume yes on all yes/no questions or use the default on all others",
Expand All @@ -64,19 +52,23 @@ WEBSITE:
Name: "noclip",
Usage: "Disable copy to clipboard",
},
&ucli.BoolFlag{
Name: "print",
Aliases: []string{"p"},
Usage: "Prints the password to the terminal",
},
}

// default command to get password
app.Action = func(c *ucli.Context) error {
return action.Default(c)
app.Action = func(c context.Context, command *ucli.Command) error {
return action.Default(c, command)
}

app.Commands = action.GetCommands()

sort.Sort(ucli.FlagsByName(app.Flags))
sort.Sort(ucli.CommandsByName(app.Commands))

return ctx, app
return ctx, &app
}

func initContext(ctx context.Context, cfg *config.Config) context.Context {
Expand Down
11 changes: 8 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Changelog for passline

## Version 1.15.0

### Feature

- Add experimental full encryption mode

## Version 1.12.0

### Feature
Expand Down Expand Up @@ -52,15 +58,15 @@ Changelog for passline

### Fix

- Set default category to "*"
- Set default category to "\*"
- Display Bug in edit crdential

## Version 1.7.0

### Feature

- Add filterable categories to credentials
- Set Default category in the config.json
- Set Default category in the config.json

## Version 1.5.4

Expand Down Expand Up @@ -106,7 +112,6 @@ Changelog for passline

- Increment version indicator


## Version 0.3.0

- Generate Password method generates now password with at least one special character, small character, capital character and number.
Expand Down
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module passline

go 1.22
go 1.23.4

require (
atomicgo.dev/keyboard v0.2.9
Expand All @@ -14,7 +14,8 @@ require (
github.com/mitchellh/go-ps v1.0.0
github.com/pkg/errors v0.9.1
github.com/rhysd/go-github-selfupdate v1.2.3
github.com/urfave/cli/v2 v2.25.3
github.com/stretchr/testify v1.10.0
github.com/urfave/cli/v3 v3.3.8
golang.org/x/crypto v0.21.0
golang.org/x/net v0.23.0
golang.org/x/sys v0.18.0
Expand All @@ -32,7 +33,7 @@ require (
cloud.google.com/go/longrunning v0.4.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
Expand All @@ -45,10 +46,10 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/tcnksm/go-gitconfig v0.1.2 // indirect
github.com/ulikunitz/xz v0.5.9 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sync v0.1.0 // indirect
Expand All @@ -58,4 +59,5 @@ require (
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
19 changes: 11 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -102,8 +100,10 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
Expand All @@ -121,6 +121,7 @@ github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
Expand All @@ -135,29 +136,29 @@ github.com/rhysd/go-github-selfupdate v1.2.3 h1:iaa+J202f+Nc+A8zi75uccC8Wg3omaM7
github.com/rhysd/go-github-selfupdate v1.2.3/go.mod h1:mp/N8zj6jFfBQy/XMYoWsmfzxazpPAODuqarmPDe2Rg=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY=
github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down Expand Up @@ -259,6 +260,7 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 h1:MZF6J7CV6s/h0HBkfqebrYfKCVEo5iN+wzE4QhV3Evo=
Expand All @@ -270,6 +272,7 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
6 changes: 3 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (

var (
// Version is the released version of passline
version string = "1.14.2"
version string = "1.15.0"
// BuildTime is the time the binary was built
date string
)
Expand All @@ -34,7 +34,7 @@ func main() {
// Get the initial state of the terminal.
initialTermState, _ := term.GetState(int(syscall.Stdin))

//trap Ctrl+C and call cancel on the context
// Trap Ctrl+C and call cancel on the context
ctx, cancel := context.WithCancel(ctx)
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM, os.Kill)
Expand Down Expand Up @@ -63,7 +63,7 @@ func main() {
}

ctx, app := setupApp(ctx, sv)
if err := app.RunContext(ctx, os.Args); err != nil {
if err := app.Run(ctx, os.Args); err != nil {
log.Fatal(err)
}
}
Expand Down
74 changes: 1 addition & 73 deletions pkg/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ package action

import (
"context"
"fmt"
"os"
"path/filepath"

"passline/pkg/cli/input"
"passline/pkg/cli/selection"
"passline/pkg/config"
"passline/pkg/crypt"
"passline/pkg/ctxutil"
"passline/pkg/out"
"passline/pkg/storage"

"github.com/blang/semver"
ucli "github.com/urfave/cli/v2"
ucli "github.com/urfave/cli/v3"
)

// Action knows everything to run passline CLI actions
Expand Down Expand Up @@ -69,75 +66,6 @@ func (s *Action) selectCredential(ctx context.Context, args ucli.Args, item stor
return credential, nil
}

func (s *Action) getMasterKey(ctx context.Context) ([]byte, error) {
// Get encrypted content encryption key from store
encryptedEncryptionKey, err := s.Store.GetKey(ctx)
if err != nil {
return []byte{}, ExitError(ExitUnknown, err, "Unable to load key: %s", err)
}

if encryptedEncryptionKey != "" {
// If encrypted encryption key exists decrypt it
envKey := []byte(os.Getenv("PASSLINE_MASTER_KEY"))
if len(envKey) > 0 {
encryptionKey, err := crypt.DecryptKey(envKey, encryptedEncryptionKey)
if err == nil {
return []byte(encryptionKey), nil
}
}

// try password three times
counter := 0
for counter < 3 {
password := input.Password("Enter master password: ")
fmt.Println()

encryptionKey, err := crypt.DecryptKey(password, encryptedEncryptionKey)
if err == nil {
return []byte(encryptionKey), nil
} else if counter != 2 {
fmt.Println("Wrong password! Please try again")
}

counter++
}

return []byte{}, ExitError(ExitPassword, err, "Wrong Password")
}

// initiate new encryption key
encryptionKey, err := s.initMasterKey(ctx)
if err != nil {
return nil, err
}

return encryptionKey, nil
}

func (s *Action) initMasterKey(ctx context.Context) ([]byte, error) {
decryptedEncryptionKey, err := crypt.GenerateKey()
if err != nil {
return []byte{}, ExitError(ExitUnknown, err, "Unable to generate key: %s", err)
}

password := input.Password("Enter master password: ")
fmt.Println()
passwordTwo := input.Password("Enter master password again: ")
fmt.Println()

if string(password) != string(passwordTwo) {
return []byte{}, ExitError(ExitPassword, err, "Password do not match")
}

encryptedEncryptionKey, err := crypt.EncryptKey(password, decryptedEncryptionKey)
if err != nil {
return []byte{}, ExitError(ExitUnknown, err, "Unable to store key: %s", err)
}
s.Store.SetKey(ctx, encryptedEncryptionKey)

return []byte(decryptedEncryptionKey), nil
}

func (s *Action) getSites(ctx context.Context) ([]storage.Item, error) {
items, err := s.Store.GetAllItems(ctx)
if err != nil {
Expand Down
Loading