annotate file/file.go @ 0:c18bc7b9d1d9

Basic binaries. checkpassword doesn't yet work.
author Paul Fisher <paul@pfish.zone>
date Sat, 24 Oct 2015 21:32:03 -0400
parents
children e58bfc7fc207
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,
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
5 // then has entries in the format specified by auth.Entry.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
6
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
7 package file
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 "os/user"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
14 "syscall"
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 "path"
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 "golang.org/x/sys/unix"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
19 "pfish.zone/go/multipass/auth"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
20 )
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
21
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
22 const (
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
23 // the Banner acts as a version indicator
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
24 Banner = "# Multipass v0.1 password file"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
25 )
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
26
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
27 var (
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
28 // Raised when
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
29 ErrorBadFile = errors.New("multipass/file: Invalid file format")
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
30 )
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
31
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
32 type ShadowFile struct {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
33 name string
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
34 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
35
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
36 // ForUser gets the given user's ShadowFile.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
37 func ForUser(username string) (*ShadowFile, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
38 u, err := user.Lookup(username)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
39 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
40 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
41 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
42 return New(path.Join(u.HomeDir, MultipassFile)), nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
43 }
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 // ForMe gets the current user's ShadowFile.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
46 func ForMe() (*ShadowFile, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
47 u, err := user.Current()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
48 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
49 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
50 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
51 return New(path.Join(u.HomeDir, MultipassFile)), nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
52 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
53
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
54 // 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
55 // 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
56 func New(name string) *ShadowFile {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
57 f := new(ShadowFile)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
58 f.name = name
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
59 return f
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
60 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
61
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
62 func (f *ShadowFile) newFilename() string {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
63 return f.name + ".new"
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
64 }
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 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
67 file, err := os.Open(f.name)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
68 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
69 return nil, nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
70 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
71 scanner := bufio.NewScanner(file)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
72 if !scanner.Scan() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
73 file.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
74 return nil, nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
75 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
76 if scanner.Text() != Banner {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
77 file.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
78 return nil, nil, ErrorBadFile
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 return file, scanner, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
81 }
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 func (f *ShadowFile) Authenticate(password string) (bool, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
84 file, scanner, err := f.open()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
85 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
86 return false, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
87 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
88 defer file.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
89
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
90 for scanner.Scan() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
91 entry, err := auth.EntryFromShadow(scanner.Text())
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
92 // Skip invalid lines.
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 continue
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
95 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
96 if entry.Authenticate(password) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
97 return true, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
98 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
99 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
100 return false, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
101 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
102
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
103 func (f *ShadowFile) Add(entry *auth.Entry) error {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
104 handle, err := f.openWrite()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
105 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
106 return err
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 err = handle.write(entry)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
109 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
110 handle.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
111 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
112 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
113 for handle.next() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
114 if entry, err := handle.entry(); err == nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
115 // 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
116 if err := handle.write(entry); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
117 handle.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
118 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
119 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
120 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
121 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
122 return handle.finalize()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
123 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
124
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
125 func (f *ShadowFile) openWrite() (*writeHandle, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
126 return openWriteHandle(f.newFilename(), f.name)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
127 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
128
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
129 type writeHandle struct {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
130 // 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
131 tempName string
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
132 tempFile *os.File
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
133 writer *bufio.Writer
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
134
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
135 // 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
136 fileName string
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
137 // 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
138 inFile *os.File
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
139 scanner *bufio.Scanner
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
140 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
141
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
142 func openWriteHandle(tempName, fileName string) (*writeHandle, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
143 h := new(writeHandle)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
144 h.tempName = tempName
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
145 h.fileName = fileName
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
146 // Open the output file, readable only by the current user.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
147 oldUmask := unix.Umask(077)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
148 tempFile, err := os.Create(tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
149 unix.Umask(oldUmask)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
150 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
151 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
152 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
153 h.tempFile = tempFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
154 // Open the input file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
155 inFile, err := os.Open(fileName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
156 if err == nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
157 // 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
158 h.inFile = inFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
159 h.scanner = bufio.NewScanner(h.inFile)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
160 if !h.scanner.Scan() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
161 return nil, ErrorBadFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
162 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
163 if h.scanner.Text() != Banner {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
164 return nil, ErrorBadFile
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
165 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
166 // 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
167 inStat, err := h.inFile.Stat()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
168 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
169 h.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
170 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
171 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
172 inStatUnix := inStat.Sys().(*syscall.Stat_t)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
173 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
174 h.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
175 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
176 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
177 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
178 h.bail()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
179 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
180 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
181 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
182 // TODO(pfish): If there is no input file, set the right permissions + group on the output file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
183 h.writer = bufio.NewWriter(h.tempFile)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
184 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
185 return nil, err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
186 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
187 return h, nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
188 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
189
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
190 func (h *writeHandle) bail() {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
191 h.tempFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
192 h.inFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
193 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
194 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
195
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
196 func (h *writeHandle) next() bool {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
197 // 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
198 return h.scanner != nil && h.scanner.Scan()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
199 }
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 func (h *writeHandle) entry() (*auth.Entry, error) {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
202 return auth.EntryFromShadow(h.scanner.Text())
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
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
205 func (h *writeHandle) write(entry *auth.Entry) error {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
206 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
207 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
208 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
209 _, err := h.writer.WriteString("\n")
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
210 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
211 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
212
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
213 func (h *writeHandle) finalize() error {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
214 h.inFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
215 // Make absolutely completely sure we're synced.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
216 if err := h.writer.Flush(); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
217 h.tempFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
218 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
219 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
220 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
221 if err := h.tempFile.Sync(); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
222 h.tempFile.Close()
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
223 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
224 return err
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 // Close the file.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
227 if err := h.tempFile.Close(); err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
228 os.Remove(h.tempName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
229 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
230 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
231 // And atomically write it over the new one.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
232 err := os.Rename(h.tempName, h.fileName)
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
233 if err != nil {
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
234 return err
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
235 }
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
236 // 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
237 // will the multipass shadow file have been updated.
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
238 return nil
c18bc7b9d1d9 Basic binaries. checkpassword doesn't yet work.
Paul Fisher <paul@pfish.zone>
parents:
diff changeset
239 }