func createShadowFile(brigPath string, ID, password string) error { shadowPath := filepath.Join(brigPath, "shadow") fd, err := os.OpenFile(shadowPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0755) if err != nil { return err } defer util.Closer(fd) salt := make([]byte, 8) n, err := rand.Reader.Read(salt) if err != nil { return err } if n != len(salt) { return fmt.Errorf("Inadeqaute salt length from random generator.") } entry := fmt.Sprintf("%s %x %x\n", ID, salt, hashPassword(salt, password)) if _, err := fd.Write([]byte(entry)); err != nil { return err } return nil }
func parseShadowFile(brigPath string, who string) (*shadowEntry, error) { fd, err := os.Open(filepath.Join(brigPath, "shadow")) if err != nil { return nil, err } defer util.Closer(fd) var entry *shadowEntry bufd := bufio.NewScanner(fd) for bufd.Scan() { var ID string var salt, hash []byte _, err = fmt.Sscanf(bufd.Text(), "%s %x %x", &ID, &salt, &hash) if err != nil && err != io.EOF { return nil, err } if ID == who { entry = &shadowEntry{ID: ID, salt: salt, hash: hash} } } if err := bufd.Err(); err != nil { return nil, err } // Might be a broken shadow file: if entry == nil { return nil, fmt.Errorf("No shadow entry found for `%v`.", who) } return entry, nil }
// PromptNewPassword asks the user to input a password. // // While typing, the user gets feedback by the prompt color, // which changes with the security of the password to green. // Additionally the entrtopy of the password is shown. // If minEntropy was not reached after hitting enter, // this function will log a message and ask the user again. func PromptNewPassword(minEntropy float64) ([]byte, error) { rl, err := readline.New("") if err != nil { return nil, err } defer util.Closer(rl) passwordCfg := rl.GenPasswordConfig() passwordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) { rl.SetPrompt(createStrengthPrompt(line, " New ")) rl.Refresh() return nil, 0, false }) pwd := []byte{} for { pwd, err = rl.ReadPasswordWithConfig(passwordCfg) if err != nil { return nil, err } strength := zxcvbn.PasswordStrength(string(pwd), nil) if strength.Entropy >= minEntropy { break } fmt.Printf(colors.Colorize(msgLowEntropy, colors.Yellow)+"\n", minEntropy) } passwordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) { rl.SetPrompt(createStrengthPrompt(line, "Retype ")) rl.Refresh() return nil, 0, false }) fmt.Println(colors.Colorize(msgReEnter, colors.Green)) for { newPwd, err := rl.ReadPasswordWithConfig(passwordCfg) if err != nil { return nil, err } if bytes.Equal(pwd, newPwd) { break } fmt.Println(colors.Colorize(msgBadPassword, colors.Yellow)) } return pwd, nil }
func promptPasswordColored(color int) (string, error) { prompt := "Password: "******"", err } defer util.Closer(rl) return doPromptLine(rl, prompt, true) }
func createMasterKey(brigPath string, keySize int) error { keyPath := filepath.Join(brigPath, "master.key") fd, err := os.OpenFile(keyPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0755) if err != nil { return err } defer util.Closer(fd) if _, err := io.CopyN(fd, rand.Reader, int64(keySize/8)); err != nil { return err } return nil }
// StageDir traverses all files in a directory and calls StageFromReader on them. func (st *Store) StageDir(filePath, repoPath string) error { walkErr := filepath.Walk(filePath, func(path string, info os.FileInfo, err error) error { // Simply skip errorneous files: if err != nil { log.Warningf("Walk: %v", err) return err } // Map the file path relative to repoPath: repoPath = prefixSlash(repoPath) currPath := filepath.Join(repoPath, path[len(filePath):]) switch mode := info.Mode(); { case mode.IsRegular(): fd, openErr := os.Open(path) if openErr != nil { return openErr } defer util.Closer(fd) compressAlgo, chooseErr := compress.ChooseCompressAlgo(path, fd) if err != nil { return chooseErr } err = st.StageFromReader(currPath, fd, compressAlgo) case mode.IsDir(): _, err = st.Mkdir(currPath) default: log.Warningf("Recursive add: Ignoring weird file type: %v") return nil } if err != nil { log.WithFields(log.Fields{ "file_path": filePath, "repo_path": repoPath, "curr_path": currPath, }).Warningf("StageDir: %v", err) } return nil }) return walkErr }
func handleCat(ctx *cli.Context, client *daemon.Client) error { repoPath := prefixSlash(ctx.Args().First()) filePath := "" isStdoutMode := ctx.NArg() < 2 if isStdoutMode { tmpFile, err := ioutil.TempFile("", ".brig-tmp-") if err != nil { return ExitCode{ UnknownError, fmt.Sprintf("Unable to create temp file: %v", err), } } filePath = tmpFile.Name() defer util.Closer(tmpFile) defer func() { if err := os.Remove(filePath); err != nil { log.Warningf("Cannot remove temp-file: %v", err) } }() } else { absPath, err := filepath.Abs(ctx.Args()[1]) if err != nil { return ExitCode{ UnknownError, fmt.Sprintf("Unable to make abs path: %v: %v", filePath, err), } } filePath = absPath } if err := client.Cat(repoPath, filePath); err != nil { return ExitCode{ UnknownError, fmt.Sprintf("Could not cat file: %v: %v", repoPath, err), } } if isStdoutMode { fd, err := os.Open(filePath) if err != nil { return ExitCode{ UnknownError, "Could not open temp file", } } if _, err := io.Copy(os.Stdout, fd); err != nil { return ExitCode{ UnknownError, fmt.Sprintf("Cannot copy to stdout: %v", err), } } if err := fd.Close(); err != nil { log.Warningf("Unable to close tmpfile handle: %v", err) } } return nil }