annotate file/file.go @ 20:ef2ef22ca4b1 default tip

Add pfish.zone/go/multipass/file import directive to 'file' package.
author Paul Fisher <paul@pfish.zone>
date Sun, 01 Nov 2015 13:00:54 -0500
parents 00d30c67b56d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
1 // Package file handles I/O for single password files.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
2 //
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
3 // A password file contains multiple passwords for a single user.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
4 // It starts with a banner that indicates the version of the file,
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
5 // then has entries in the format specified by Entry.
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
6
20
ef2ef22ca4b1 Add pfish.zone/go/multipass/file import directive to 'file' package.
Paul Fisher <paul@pfish.zone>
parents: 18
diff changeset
7 package file // import "pfish.zone/go/multipass/file"
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
8
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
9 import (
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
10 "bufio"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
11 "errors"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
12 "os"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
13 "syscall"
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
14 "time"
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
15
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
16 "golang.org/x/sys/unix"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
17 )
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
18
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
19 const (
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
20 // the Banner acts as a version indicator
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
21 Banner = "# Multipass v0.1 password file"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
22 )
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
23
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
24 var (
15
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
25 // Raised when there's an error in the file format.
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
26 ErrorBadFile = errors.New("multipass/file: Invalid file format")
15
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
27
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
28 // we spin waiting for the file to become available, doubling our wait time
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
29 // every time it's unavailable. If the wait time is longer than this,
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
30 // give up. Variable so it can be set in tests.
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
31 maxDelay = time.Minute
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
32 )
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
33
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
34 type ShadowFile struct {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
35 name string
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
36 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
37
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
38 // New creates a ShadowFile for reading at the given path.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
39 // If a file needs to be created, uses the given GID to create it.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
40 func New(name string) *ShadowFile {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
41 f := new(ShadowFile)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
42 f.name = name
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
43 return f
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
44 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
45
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
46 func (f *ShadowFile) newFilename() string {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
47 return f.name + ".new"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
48 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
49
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
50 func (f *ShadowFile) open() (*os.File, *bufio.Scanner, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
51 file, err := os.Open(f.name)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
52 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
53 return nil, nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
54 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
55 scanner := bufio.NewScanner(file)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
56 if !scanner.Scan() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
57 file.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
58 return nil, nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
59 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
60 if scanner.Text() != Banner {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
61 file.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
62 return nil, nil, ErrorBadFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
63 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
64 return file, scanner, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
65 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
66
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
67 func (f *ShadowFile) Authenticate(password string) (bool, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
68 file, scanner, err := f.open()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
69 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
70 return false, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
71 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
72 defer file.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
73
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
74 for scanner.Scan() {
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
75 entry, err := EntryFromShadow(scanner.Text())
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
76 // Skip invalid lines.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
77 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
78 continue
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
79 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
80 if entry.Authenticate(password) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
81 return true, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
82 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
83 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
84 return false, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
85 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
86
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
87 func (f *ShadowFile) Add(entry *Entry) error {
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
88 handle, err := f.openWrite()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
89 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
90 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
91 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
92 err = handle.write(entry)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
93 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
94 handle.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
95 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
96 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
97 for handle.next() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
98 if entry, err := handle.entry(); err == nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
99 // If we get an invalid entry, just skip it.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
100 if err := handle.write(entry); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
101 handle.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
102 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
103 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
104 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
105 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
106 return handle.finalize()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
107 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
108
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
109 func (f *ShadowFile) AllEntries() ([]*Entry, error) {
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
110 file, scanner, err := f.open()
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
111 if err != nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
112 return nil, err
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
113 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
114 defer file.Close()
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
115
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
116 var entries []*Entry
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
117
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
118 for scanner.Scan() {
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
119 entry, err := EntryFromShadow(scanner.Text())
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
120 // Skip invalid lines.
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
121 if err != nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
122 continue
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
123 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
124 entries = append(entries, entry)
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
125 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
126 return entries, nil
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
127 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
128
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
129 func (f *ShadowFile) Remove(id uint64) error {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
130 handle, err := f.openWrite()
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
131 if err != nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
132 return err
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
133 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
134 for handle.next() {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
135 if entry, err := handle.entry(); err == nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
136 // If we get an invalid entry, just skip it.
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
137 if entry.ID() != id {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
138 if err := handle.write(entry); err != nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
139 handle.bail()
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
140 return err
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
141 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
142 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
143 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
144 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
145 return handle.finalize()
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
146 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
147
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
148 func (f *ShadowFile) openWrite() (*writeHandle, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
149 return openWriteHandle(f.newFilename(), f.name)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
150 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
151
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
152 type writeHandle struct {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
153 // We write to a file handle pointing to tempName.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
154 tempName string
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
155 tempFile *os.File
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
156 writer *bufio.Writer
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
157
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
158 // It will eventually move to fileName, which is our source file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
159 fileName string
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
160 // If inFile is nil, we're creating a new multipass file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
161 inFile *os.File
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
162 scanner *bufio.Scanner
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
163 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
164
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
165 func openWriteHandle(tempName, fileName string) (*writeHandle, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
166 h := new(writeHandle)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
167 h.tempName = tempName
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
168 h.fileName = fileName
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
169 // Open the output file, but only if it doesn't exist.
9
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
170 // This prevents race conditions.
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
171 oldUmask := unix.Umask(077)
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
172 var tempFile *os.File
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
173 delay := time.Nanosecond
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
174 for tempFile == nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
175 tempTempFile, err := os.OpenFile(tempName, os.O_CREATE|os.O_EXCL|os.O_WRONLY|os.O_SYNC, 0600)
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
176 tempFile = tempTempFile
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
177 if err != nil {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
178 perr := err.(*os.PathError)
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
179 errno, ok := perr.Err.(syscall.Errno)
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
180 if !ok {
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
181 return nil, err
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
182 }
15
9b4ec6b5c23e Add tests for multipass files.
Paul Fisher <paul@pfish.zone>
parents: 13
diff changeset
183 if errno != syscall.EEXIST || delay > maxDelay {
10
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
184 return nil, err
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
185 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
186 time.Sleep(delay)
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
187 delay *= 2
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
188 }
1246b4b9028b Add tool to remove passwords.
Paul Fisher <paul@pfish.zone>
parents: 9
diff changeset
189 }
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
190 unix.Umask(oldUmask)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
191 h.tempFile = tempFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
192 // Open the input file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
193 inFile, err := os.Open(fileName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
194 if err == nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
195 // Prepare to read in the input file, if it exists.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
196 h.inFile = inFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
197 h.scanner = bufio.NewScanner(h.inFile)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
198 if !h.scanner.Scan() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
199 return nil, ErrorBadFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
200 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
201 if h.scanner.Text() != Banner {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
202 return nil, ErrorBadFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
203 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
204 // Change the owner and group of the new file to that of the old.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
205 inStat, err := h.inFile.Stat()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
206 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
207 h.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
208 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
209 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
210 inStatUnix := inStat.Sys().(*syscall.Stat_t)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
211 if err := h.tempFile.Chown(int(inStatUnix.Uid), int(inStatUnix.Gid)); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
212 h.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
213 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
214 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
215 if err := h.tempFile.Chmod(inStat.Mode()); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
216 h.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
217 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
218 }
9
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
219 } else {
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
220 // TODO(pfish): Restrict ACL to only multipass authenticators.
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
221 if err := h.tempFile.Chmod(0644); err != nil {
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
222 h.bail()
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
223 return nil, err
e58bfc7fc207 Make multipass files default all-readable.
Paul Fisher <paul@pfish.zone>
parents: 0
diff changeset
224 }
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
225 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
226 h.writer = bufio.NewWriter(h.tempFile)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
227 if _, err := h.writer.WriteString(Banner + "\n"); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
228 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
229 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
230 return h, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
231 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
232
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
233 func (h *writeHandle) bail() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
234 h.tempFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
235 h.inFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
236 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
237 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
238
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
239 func (h *writeHandle) next() bool {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
240 // If the scanner is nil, then we have no input file and therefore no next.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
241 return h.scanner != nil && h.scanner.Scan()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
242 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
243
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
244 func (h *writeHandle) entry() (*Entry, error) {
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
245 return EntryFromShadow(h.scanner.Text())
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
246 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
247
18
00d30c67b56d Put all the library stuff into multipass/file.
Paul Fisher <paul@pfish.zone>
parents: 15
diff changeset
248 func (h *writeHandle) write(entry *Entry) error {
0
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
249 if _, err := h.writer.WriteString(entry.Encode()); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
250 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
251 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
252 _, err := h.writer.WriteString("\n")
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
253 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
254 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
255
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
256 func (h *writeHandle) finalize() error {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
257 h.inFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
258 // Make absolutely completely sure we're synced.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
259 if err := h.writer.Flush(); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
260 h.tempFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
261 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
262 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
263 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
264 if err := h.tempFile.Sync(); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
265 h.tempFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
266 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
267 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
268 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
269 // Close the file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
270 if err := h.tempFile.Close(); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
271 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
272 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
273 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
274 // And atomically write it over the new one.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
275 err := os.Rename(h.tempName, h.fileName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
276 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
277 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
278 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
279 // If we get here, everything succeeded, and only in this case
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
280 // will the multipass shadow file have been updated.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
281 return nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
282 }