summaryrefslogtreecommitdiff
path: root/src/nshd/hackers_git
diff options
context:
space:
mode:
Diffstat (limited to 'src/nshd/hackers_git')
-rw-r--r--src/nshd/hackers_git/hackers.go50
-rw-r--r--src/nshd/hackers_git/hackers_watch.go254
2 files changed, 38 insertions, 266 deletions
diff --git a/src/nshd/hackers_git/hackers.go b/src/nshd/hackers_git/hackers.go
index 2e9edc1..b72698f 100644
--- a/src/nshd/hackers_git/hackers.go
+++ b/src/nshd/hackers_git/hackers.go
@@ -24,11 +24,11 @@
package hackers_git
import (
- "lukeshu.com/git/go/libgnulinux.git/inotify"
"lukeshu.com/git/go/libnslcd.git/proto"
"lukeshu.com/git/go/libnslcd.git/proto/server"
"lukeshu.com/git/go/libnslcd.git/systemd"
"lukeshu.com/git/go/libsystemd.git/sd_daemon/logger"
+ "path/filepath"
"sync"
)
@@ -44,18 +44,11 @@ type Config struct {
type Hackers struct {
nslcd_server.NilBackend
- Cfg Config
- lock sync.RWMutex
- workers sync.WaitGroup
+ Cfg Config
+ lock sync.RWMutex
users map[int32]user
groups map[string]map[string]bool
-
- in_fd *inotify.Watcher
- in_wd_home inotify.Wd
- in_wd_yaml inotify.Wd
- in_uid2wd map[int32]inotify.Wd
- in_wd2uid map[inotify.Wd]int32
}
var _ nslcd_systemd.Backend = &Hackers{}
@@ -74,7 +67,9 @@ func (o *Hackers) Close() {
logger.Info("hackers.git: Closing session")
o.lock.Lock()
defer o.lock.Unlock()
- o.close()
+
+ o.users = make(map[int32]user, 0)
+ o.groups = make(map[string]map[string]bool)
}
func (o *Hackers) Reload() error {
@@ -82,7 +77,29 @@ func (o *Hackers) Reload() error {
o.lock.Lock()
defer o.lock.Unlock()
- return o.reload()
+ filenames, err := filepath.Glob(o.Cfg.Yamldir + "/*.yml")
+ if err != nil {
+ return err
+ }
+ o.users = make(map[int32]user, len(filenames))
+ o.groups = make(map[string]map[string]bool)
+ for _, filename := range filenames {
+ logger.Debug("hackers.git: Loading YAML file: %s", filename)
+
+ user, err := parse_user_yaml(filename)
+ if err != nil {
+ logger.Warning("hackers.git: -> File ignored: %v", err)
+ continue
+ }
+ for _, groupname := range user.groups {
+ o.add_user_to_group(user.passwd.Name, groupname)
+ }
+ user.passwd.PwHash = parse_user_password(user.passwd.HomeDir + "/.password")
+ o.users[user.passwd.UID] = user
+ logger.Debug("hackers.git: -> User %d(%s) added", user.passwd.UID, user.passwd.Name)
+ }
+
+ return nil
}
func (o *Hackers) name2uid(name string) int32 {
@@ -93,3 +110,12 @@ func (o *Hackers) name2uid(name string) int32 {
}
return -1
}
+
+func (o *Hackers) add_user_to_group(username string, groupname string) {
+ group, found := o.groups[groupname]
+ if !found {
+ group = make(map[string]bool)
+ o.groups[groupname] = group
+ }
+ group[username] = true
+}
diff --git a/src/nshd/hackers_git/hackers_watch.go b/src/nshd/hackers_git/hackers_watch.go
deleted file mode 100644
index dc5ecf4..0000000
--- a/src/nshd/hackers_git/hackers_watch.go
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2015 Luke Shumaker <lukeshu@sbcglobal.net>.
-//
-// This is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of
-// the License, or (at your option) any later version.
-//
-// The GNU General Public License's references to "object code" and
-// "executables" are to be interpreted to also include the output of
-// any document formatting or typesetting system, including
-// intermediate and printed output.
-//
-// This software is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public
-// License along with this manual; if not, see
-// <http://www.gnu.org/licenses/>.
-
-package hackers_git
-
-import (
- "lukeshu.com/git/go/libgnulinux.git/inotify"
- "lukeshu.com/git/go/libsystemd.git/sd_daemon/logger"
- "lukeshu.com/git/go/libsystemd.git/sd_daemon/lsb"
- "os"
- "path/filepath"
-)
-
-const (
- in_CHILD_ADD = inotify.IN_CREATE | inotify.IN_MOVED_TO
- in_CHILD_DEL = inotify.IN_DELETE | inotify.IN_MOVED_FROM
- in_CHILD_MOD = inotify.IN_CLOSE_WRITE | inotify.IN_MOVED_TO
- in_CHILD_ANY = in_CHILD_ADD | in_CHILD_DEL | in_CHILD_MOD
-
- in_DIR_INVALID = inotify.IN_MOVE_SELF | inotify.IN_DELETE_SELF
- in_DIR = inotify.IN_ONLYDIR | in_DIR_INVALID
-)
-
-func (o *Hackers) watchHomedir(uid int32) {
- wd, err := o.in_fd.AddWatch(o.users[uid].passwd.HomeDir, in_DIR|in_CHILD_ANY)
- if err == nil {
- oldwd, found := o.in_uid2wd[uid]
- if found && oldwd != wd {
- o.unwatchHomedir(oldwd)
- }
- o.in_uid2wd[uid] = wd
- o.in_wd2uid[wd] = uid
- } else {
- delete(o.in_uid2wd, uid)
- logger.Debug("hackers.git: %v", err)
- }
- o.load_user_password(uid)
-}
-
-func (o *Hackers) unwatchHomedir(wd inotify.Wd) {
- err := o.in_fd.RmWatch(wd)
- if err != nil {
- logger.Warning("hackers.git: %v", err)
- return
- }
- uid := o.in_wd2uid[wd]
- delete(o.in_wd2uid, wd)
- delete(o.in_uid2wd, uid)
- o.load_user_password(uid)
-}
-
-func (o *Hackers) close() {
- if o.in_fd != nil {
- o.in_fd.Close()
- defer o.workers.Wait()
- }
- o.in_wd_home = -1
- o.in_wd_yaml = -1
- o.users = make(map[int32]user, 0)
- o.groups = make(map[string]map[string]bool)
- o.in_uid2wd = make(map[int32]inotify.Wd, 0)
- o.in_wd2uid = make(map[inotify.Wd]int32, 0)
-}
-
-func (o *Hackers) reload() (err error) {
- o.close()
- o.in_fd, err = inotify.WatcherInit() ; if err != nil { return }
- o.in_wd_home, err = o.in_fd.AddWatch("/home" , in_DIR|in_CHILD_ADD); if err != nil { return }
- o.in_wd_yaml, err = o.in_fd.AddWatch(o.Cfg.Yamldir, in_DIR|in_CHILD_ANY); if err != nil { return }
-
- filenames, err := filepath.Glob(o.Cfg.Yamldir + "/*.yml")
- o.users = make(map[int32]user, len(filenames))
- o.groups = make(map[string]map[string]bool)
- o.in_uid2wd = make(map[int32]inotify.Wd, len(filenames))
- o.in_wd2uid = make(map[inotify.Wd]int32, len(filenames))
- for _, filename := range filenames {
- o.load_yaml_file(filename, false)
- }
-
- go func() {
- defer lsb.Recover()
- defer o.workers.Done()
- o.worker()
- }()
-
- err = nil
- return
-}
-
-func (o *Hackers) add_user_to_group(username string, groupname string) {
- group, found := o.groups[groupname]
- if !found {
- group = make(map[string]bool)
- o.groups[groupname] = group
- }
- group[username] = true
-}
-
-func (o *Hackers) del_user_from_group(username string, groupname string) {
- group, found := o.groups[groupname]
- if !found {
- return
- }
- delete(group, username)
- if len(group) < 1 {
- delete(o.groups, groupname)
- }
-}
-
-func (o *Hackers) load_yaml_file(filename string, uselock bool) {
- logger.Debug("hackers.git: Loading YAML file: %s", filename)
- user, err := parse_user_yaml(filename)
- uid := user.passwd.UID
- if err == nil {
- logger.Debug("hackers.git: -> User %d added/updated", uid)
- if uselock {
- o.lock.Lock()
- defer o.lock.Unlock()
- }
- if olduser, found := o.users[uid]; found {
- for _, groupname := range olduser.groups {
- o.del_user_from_group(olduser.passwd.Name, groupname)
- }
- }
- for _, groupname := range user.groups {
- o.add_user_to_group(user.passwd.Name, groupname)
- }
- o.users[uid] = user
- o.watchHomedir(uid)
- } else if uid >= 0 {
- // User became invalid
- logger.Debug("hackers.git: -> User %d invalidated: %v", uid, err)
- if uselock {
- o.lock.Lock()
- defer o.lock.Unlock()
- }
- if wd, found := o.in_uid2wd[uid]; found {
- o.unwatchHomedir(wd)
- }
- if olduser, found := o.users[uid]; found {
- for _, groupname := range olduser.groups {
- o.del_user_from_group(olduser.passwd.Name, groupname)
- }
- delete(o.users, uid)
- }
- } else {
- logger.Debug("hackers.git: -> File ignored: %v", err)
- }
-}
-
-func (o *Hackers) load_user_password(uid int32) {
- user := o.users[uid]
- user.passwd.PwHash = parse_user_password(user.passwd.HomeDir + "/.password")
- o.users[uid] = user
-}
-
-func (o *Hackers) worker_watch_homedirs() {
- for uid, _ := range o.users {
- o.watchHomedir(uid)
- }
-}
-
-func worker_error(format string, a ...interface{}) {
- logger.Err("hackers.git: "+format, a)
- os.Exit(int(lsb.EXIT_FAILURE))
-}
-
-func (o *Hackers) worker() {
- err := os.Chdir(o.Cfg.Yamldir)
- if err != nil {
- worker_error("failed to load %q: %v", o.Cfg.Yamldir, err)
- }
-Loop:
- for {
- select {
- case event, ok := <-o.in_fd.Events:
- if !ok {
- break Loop
- }
- switch event.Wd {
- case o.in_wd_yaml:
- // handle updates to yaml files
- if event.Mask&in_DIR_INVALID != 0 {
- err := o.Reload()
- if err != nil {
- worker_error("failed to reload hackers.git yaml directory: %v", err)
-
- }
- err = os.Chdir(o.Cfg.Yamldir)
- if err != nil {
- worker_error("failed to load %q: %v", o.Cfg.Yamldir, err)
- }
- } else if event.Mask&in_CHILD_ANY != 0 {
- if event.Name == nil {
- panic("recieved child event from inotify, but no child name")
- }
- o.load_yaml_file(o.Cfg.Yamldir+"/"+*event.Name, true)
- } else {
- panic("recieved non-subscribed inotify event from kernel")
- }
- case o.in_wd_home:
- if event.Mask&in_DIR_INVALID != 0 {
- err := o.Reload()
- if err != nil {
- panic(err)
- }
- } else if event.Mask&inotify.IN_ISDIR != 0 {
- // handle added home directory
- o.worker_watch_homedirs()
- }
- default:
- // handle a change to someone's password
- if event.Mask&in_DIR_INVALID != 0 {
- o.unwatchHomedir(event.Wd)
- o.worker_watch_homedirs()
- } else if event.Name != nil {
- if *event.Name == ".password" {
- func() {
- o.lock.Lock()
- defer o.lock.Unlock()
- o.load_user_password(o.in_wd2uid[event.Wd])
- }()
- }
- } else {
- logger.Debug("hackers.git: Event didn't match: %#v", event)
- }
- }
- case err, ok := <-o.in_fd.Errors:
- if !ok {
- break Loop
- }
- logger.Warning("hackers.git: Inotify error: %v", err)
- }
- }
- logger.Info("hackers.git: Stopped inotify watcher")
-}