// acquireLock locks the lock file for the given user's authorized_keys.d. // A lock file is created if it doesn't already exist. // The locking is currently a simple coarse-grained mutex held for the // Open()-Close() duration, implemented using a lock file in the user's ~/. func acquireLock(u *user.User) (*os.File, error) { f, err := as_user.OpenFile(u, lockFilePath(u), syscall.O_CREAT|syscall.O_RDONLY, 0600) if err != nil { return nil, err } if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil { f.Close() return nil, err } return f, nil }
// Replace replaces the opened key with the supplied data. func (ak *SSHAuthorizedKey) Replace(keys []byte) error { sp := stageFilePath(ak.origin.user) sf, err := as_user.OpenFile(ak.origin.user, sp, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0600) if err != nil { return err } defer os.Remove(sp) if _, err = sf.Write(keys); err != nil { return err } if err := sf.Close(); err != nil { return err } return as_user.Rename(ak.origin.user, sp, ak.Path) }
// Sync synchronizes the user's ~/.ssh/authorized_keys file with the // current authorized_keys.d directory state. func (akd *SSHAuthorizedKeysDir) Sync() error { sp := stageFilePath(akd.user) sf, err := as_user.OpenFile(akd.user, sp, syscall.O_CREAT|syscall.O_TRUNC|syscall.O_WRONLY, 0600) if err != nil { return err } defer func() { if err != nil { sf.Close() os.Remove(sp) } }() if err := akd.WalkKeys(func(k *SSHAuthorizedKey) error { if !k.Disabled { kb, err := ioutil.ReadFile(k.Path) if err != nil { return err } kb = append(kb, '\n') if _, err := sf.Write(kb); err != nil { return err } } return nil }); err != nil { return err } if err := sf.Close(); err != nil { return err } err = as_user.Rename(akd.user, sp, authKeysFilePath(akd.user)) if err != nil { return err } return nil }