# HG changeset patch # User Paul Fisher # Date 1445788040 14400 # Node ID 1246b4b9028bccabc76dc1add4dd3e2760c850d4 # Parent e58bfc7fc20749b290494e1b5dee376abdd1ee82 Add tool to remove passwords. diff -r e58bfc7fc207 -r 1246b4b9028b file/file.go --- a/file/file.go Sun Oct 25 10:45:32 2015 -0400 +++ b/file/file.go Sun Oct 25 11:47:20 2015 -0400 @@ -11,9 +11,9 @@ "errors" "os" "os/user" + "path" "syscall" - - "path" + "time" "golang.org/x/sys/unix" "pfish.zone/go/multipass/auth" @@ -122,6 +122,45 @@ return handle.finalize() } +func (f *ShadowFile) AllEntries() ([]*auth.Entry, error) { + file, scanner, err := f.open() + if err != nil { + return nil, err + } + defer file.Close() + + var entries []*auth.Entry + + for scanner.Scan() { + entry, err := auth.EntryFromShadow(scanner.Text()) + // Skip invalid lines. + if err != nil { + continue + } + entries = append(entries, entry) + } + return entries, nil +} + +func (f *ShadowFile) Remove(id uint64) error { + handle, err := f.openWrite() + if err != nil { + return err + } + for handle.next() { + if entry, err := handle.entry(); err == nil { + // If we get an invalid entry, just skip it. + if entry.ID() != id { + if err := handle.write(entry); err != nil { + handle.bail() + return err + } + } + } + } + return handle.finalize() +} + func (f *ShadowFile) openWrite() (*writeHandle, error) { return openWriteHandle(f.newFilename(), f.name) } @@ -143,14 +182,28 @@ h := new(writeHandle) h.tempName = tempName h.fileName = fileName - // Open the output file, readable by everybody, but only if it doesn't exist. + // Open the output file, but only if it doesn't exist. // This prevents race conditions. oldUmask := unix.Umask(077) - tempFile, err := os.OpenFile(tempName, os.O_CREATE | os.O_EXCL | os.O_WRONLY | os.O_SYNC, 0600) + var tempFile *os.File + delay := time.Nanosecond + for tempFile == nil { + tempTempFile, err := os.OpenFile(tempName, os.O_CREATE|os.O_EXCL|os.O_WRONLY|os.O_SYNC, 0600) + tempFile = tempTempFile + if err != nil { + perr := err.(*os.PathError) + errno, ok := perr.Err.(syscall.Errno) + if !ok { + return nil, err + } + if errno != syscall.EEXIST || delay > time.Minute { + return nil, err + } + time.Sleep(delay) + delay *= 2 + } + } unix.Umask(oldUmask) - if err != nil { - return nil, err - } h.tempFile = tempFile // Open the input file. inFile, err := os.Open(fileName) diff -r e58bfc7fc207 -r 1246b4b9028b multipass-add.go --- a/multipass-add.go Sun Oct 25 10:45:32 2015 -0400 +++ b/multipass-add.go Sun Oct 25 11:47:20 2015 -0400 @@ -13,6 +13,10 @@ func main() { passfile, err := file.ForMe() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } reader := bufio.NewReader(os.Stdin) fmt.Print("Describe password: ") text, err := reader.ReadString('\n')