From c191af11616a3306b8e0a3650b6972eb61d2aba1 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 17 Jun 2016 11:49:22 -0400 Subject: rearrange the go packages a bit --- .gitignore | 1 - Makefile | 20 +-- src/cmd-nshd/.gitignore | 1 + src/cmd-nshd/main.go.in | 32 ++++ src/nshd/hackers_git/check_password.go | 23 --- src/nshd/hackers_git/db_config.go | 39 ----- src/nshd/hackers_git/db_group.go | 139 ----------------- src/nshd/hackers_git/db_pam.go | 100 ------------ src/nshd/hackers_git/db_passwd.go | 81 ---------- src/nshd/hackers_git/db_shadow.go | 77 --------- src/nshd/hackers_git/gid.go | 37 ----- src/nshd/hackers_git/hackers.go | 116 -------------- src/nshd/hackers_git/hackers_parse.go | 173 --------------------- src/nshd/hackers_git/set.go | 27 ---- src/nshd/main.go.in | 32 ---- .../nslcd_backend/check_password.go | 23 +++ src/parabola_hackers/nslcd_backend/db_config.go | 39 +++++ src/parabola_hackers/nslcd_backend/db_group.go | 139 +++++++++++++++++ src/parabola_hackers/nslcd_backend/db_pam.go | 100 ++++++++++++ src/parabola_hackers/nslcd_backend/db_passwd.go | 81 ++++++++++ src/parabola_hackers/nslcd_backend/db_shadow.go | 77 +++++++++ src/parabola_hackers/nslcd_backend/gid.go | 37 +++++ src/parabola_hackers/nslcd_backend/hackers.go | 116 ++++++++++++++ .../nslcd_backend/hackers_parse.go | 173 +++++++++++++++++++++ src/parabola_hackers/nslcd_backend/set.go | 27 ++++ 25 files changed, 855 insertions(+), 855 deletions(-) create mode 100644 src/cmd-nshd/.gitignore create mode 100644 src/cmd-nshd/main.go.in delete mode 100644 src/nshd/hackers_git/check_password.go delete mode 100644 src/nshd/hackers_git/db_config.go delete mode 100644 src/nshd/hackers_git/db_group.go delete mode 100644 src/nshd/hackers_git/db_pam.go delete mode 100644 src/nshd/hackers_git/db_passwd.go delete mode 100644 src/nshd/hackers_git/db_shadow.go delete mode 100644 src/nshd/hackers_git/gid.go delete mode 100644 src/nshd/hackers_git/hackers.go delete mode 100644 src/nshd/hackers_git/hackers_parse.go delete mode 100644 src/nshd/hackers_git/set.go delete mode 100644 src/nshd/main.go.in create mode 100644 src/parabola_hackers/nslcd_backend/check_password.go create mode 100644 src/parabola_hackers/nslcd_backend/db_config.go create mode 100644 src/parabola_hackers/nslcd_backend/db_group.go create mode 100644 src/parabola_hackers/nslcd_backend/db_pam.go create mode 100644 src/parabola_hackers/nslcd_backend/db_passwd.go create mode 100644 src/parabola_hackers/nslcd_backend/db_shadow.go create mode 100644 src/parabola_hackers/nslcd_backend/gid.go create mode 100644 src/parabola_hackers/nslcd_backend/hackers.go create mode 100644 src/parabola_hackers/nslcd_backend/hackers_parse.go create mode 100644 src/parabola_hackers/nslcd_backend/set.go diff --git a/.gitignore b/.gitignore index f5a711d..0446d88 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ *.o *~ -/src/nshd/main.go /nshd.service /nshd.sysusers /scripts/common.rb diff --git a/Makefile b/Makefile index d7cee40..e28e7f1 100644 --- a/Makefile +++ b/Makefile @@ -42,9 +42,9 @@ at.subdirs += src/lukeshu.com/git/go/libnslcd.git/proto scripts = $(filter-out common.rb common.rb.in,$(notdir $(wildcard $(srcdir)/scripts/*))) common.rb std.gen_files += LICENSE.lgpl-2.1.txt LICENSE.gpl-2.txt LICENSE.apache-2.0.txt -std.out_files += bin/nshd nshd.service nshd.sysusers scripts/common.rb test/runner +std.out_files += bin/cmd-nshd nshd.service nshd.sysusers scripts/common.rb test/runner std.sys_files += $(addprefix $(bindir)/,nshd $(scripts)) $(systemunitdir)/nshd.socket $(systemunitdir)/nshd.service $(sysusersdir)/nshd.conf $(conf_file) -std.clean_files += test/*.o pkg/ .tmp* .var* +std.clean_files += test/*.o pkg/ .tmp* .var* src/cmd-nshd/main.go $(srcdir)/LICENSE.lgpl-2.1.txt: $(NET) curl https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt > $@ @@ -55,12 +55,12 @@ $(srcdir)/LICENSE.apache-2.0.txt: $(NET) $(srcdir)/LICENSE.wtfpl-2.txt: $(NET) curl http://www.wtfpl.net/txt/copying/ > $@ -$(outdir)/bin/nshd: src/lukeshu.com/git/go/libnslcd.git/proto/server/interface_backend.go -$(outdir)/bin/nshd: src/lukeshu.com/git/go/libnslcd.git/proto/server/func_handlerequest.go -$(outdir)/bin/nshd: src/lukeshu.com/git/go/libnslcd.git/proto/server/type_nilbackend.go -$(outdir)/bin/nshd: src/nshd/main.go -$(outdir)/bin/nshd: $(call golang.src,$(srcdir)) $(var)conf_file $(var)bindir - $(call golang.install,$(topsrcdir),nshd) +$(outdir)/bin/cmd-nshd: src/lukeshu.com/git/go/libnslcd.git/proto/server/interface_backend.go +$(outdir)/bin/cmd-nshd: src/lukeshu.com/git/go/libnslcd.git/proto/server/func_handlerequest.go +$(outdir)/bin/cmd-nshd: src/lukeshu.com/git/go/libnslcd.git/proto/server/type_nilbackend.go +$(outdir)/bin/cmd-nshd: src/cmd-nshd/main.go +$(outdir)/bin/cmd-nshd: $(call golang.src,$(srcdir)) $(var)conf_file $(var)bindir + $(call golang.install,$(topsrcdir),cmd-nshd) $(outdir)/%.o: $(srcdir)/%.c $(var)CC $(var)CPPFLAGS $(var)CFLAGS $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(filter-out $(var)%,$^) @@ -72,9 +72,9 @@ $(outdir)/%: $(srcdir)/%.in $(outdir)/nshd.service: $(var)user $(var)bindir $(outdir)/nshd.sysusers: $(var)user $(outdir)/scripts/common.rb: $(var)conf_file -$(outdir)/src/nshd/main.go: $(var)conf_file $(var)bindir +$(outdir)/src/cmd-nshd/main.go: $(var)conf_file $(var)bindir -$(DESTDIR)$(bindir)/%: $(outdir)/bin/% +$(DESTDIR)$(bindir)/%: $(outdir)/bin/cmd-% install -TDm755 $< $@ $(DESTDIR)$(bindir)/%: $(srcdir)/scripts/% install -TDm755 $< $@ diff --git a/src/cmd-nshd/.gitignore b/src/cmd-nshd/.gitignore new file mode 100644 index 0000000..00870e2 --- /dev/null +++ b/src/cmd-nshd/.gitignore @@ -0,0 +1 @@ +/main.go diff --git a/src/cmd-nshd/main.go.in b/src/cmd-nshd/main.go.in new file mode 100644 index 0000000..d888f27 --- /dev/null +++ b/src/cmd-nshd/main.go.in @@ -0,0 +1,32 @@ +// Copyright 2015-2016 Luke Shumaker . +// +// 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. +// +// 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 +// . + +// Command nshd is an implementation of nslcd that talks to hackers.git instead of LDAP. +package main + +import ( + "lukeshu.com/git/go/libnslcd.git/systemd" + hackers_nslcd_backend "parabola_hackers/nslcd_backend" + "os" +) + +func main() { + backend := &hackers_nslcd_backend.Hackers{ + CfgFilename: "@conf_file@", + YamlCat: "@bindir@/meta-cat", + } + os.Exit(int(nslcd_systemd.Main(backend))) +} diff --git a/src/nshd/hackers_git/check_password.go b/src/nshd/hackers_git/check_password.go deleted file mode 100644 index 84a5a24..0000000 --- a/src/nshd/hackers_git/check_password.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015-2016 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import "lukeshu.com/git/go/libgnulinux.git/crypt" - -func check_password(password string, hash string) bool { - return crypt.Crypt(password, hash) == hash -} diff --git a/src/nshd/hackers_git/db_config.go b/src/nshd/hackers_git/db_config.go deleted file mode 100644 index cdbb7db..0000000 --- a/src/nshd/hackers_git/db_config.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015-2016 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import ( - p "lukeshu.com/git/go/libnslcd.git/proto" - s "syscall" -) - -func (o *Hackers) Config_Get(cred s.Ucred, req p.Request_Config_Get) <-chan p.Config { - o.lock.RLock() - ret := make(chan p.Config) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - switch req.Key { - case p.NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE: - if o.cfg.Pam_password_prohibit_message != "" { - ret <- p.Config{Value: o.cfg.Pam_password_prohibit_message} - } - } - }() - return ret -} diff --git a/src/nshd/hackers_git/db_group.go b/src/nshd/hackers_git/db_group.go deleted file mode 100644 index af1ac2c..0000000 --- a/src/nshd/hackers_git/db_group.go +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2015-2016 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import ( - p "lukeshu.com/git/go/libnslcd.git/proto" - s "syscall" -) - -func (o *Hackers) groupByName(name string, users bool) p.Group { - members_set, found := o.groups[name] - if !found { - return p.Group{ID: -1} - } - gid := name2gid(name) - if gid < 0 { - return p.Group{ID: -1} - } - var members_list []string - if users { - members_list = set2list(members_set) - } else { - members_list = make([]string, 0) - } - return p.Group{ - Name: name, - PwHash: "x", - ID: gid, - Members: members_list, - } -} - -func (o *Hackers) groupByGid(gid int32, users bool) p.Group { - name, found := gid2name(gid) - if !found { - return p.Group{ID: -1} - } - members_set, found := o.groups[name] - if !found { - return p.Group{ID: -1} - } - var members_list []string - if users { - members_list = set2list(members_set) - } else { - members_list = make([]string, 0) - } - return p.Group{ - Name: name, - PwHash: "x", - ID: gid, - Members: members_list, - } -} - -func (o *Hackers) Group_ByName(cred s.Ucred, req p.Request_Group_ByName) <-chan p.Group { - o.lock.RLock() - ret := make(chan p.Group) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - group := o.groupByName(req.Name, true) - if group.ID < 0 { - return - } - ret <- group - }() - return ret -} - -func (o *Hackers) Group_ByGid(cred s.Ucred, req p.Request_Group_ByGid) <-chan p.Group { - o.lock.RLock() - ret := make(chan p.Group) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - group := o.groupByGid(req.Gid, true) - if group.ID < 0 { - return - } - ret <- group - }() - return ret -} - -// note that the BYMEMBER call returns an empty members list -func (o *Hackers) Group_ByMember(cred s.Ucred, req p.Request_Group_ByMember) <-chan p.Group { - o.lock.RLock() - ret := make(chan p.Group) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - uid := o.name2uid(req.Member) - if uid < 0 { - return - } - for _, name := range o.users[uid].groups { - group := o.groupByName(name, false) - if group.ID >= 0 { - ret <- group - } - } - }() - return ret -} - -func (o *Hackers) Group_All(cred s.Ucred, req p.Request_Group_All) <-chan p.Group { - o.lock.RLock() - ret := make(chan p.Group) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - for name, _ := range o.groups { - group := o.groupByName(name, true) - if group.ID >= 0 { - ret <- group - } - } - }() - return ret -} diff --git a/src/nshd/hackers_git/db_pam.go b/src/nshd/hackers_git/db_pam.go deleted file mode 100644 index 977104e..0000000 --- a/src/nshd/hackers_git/db_pam.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2015 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import ( - "crypto/rand" - p "lukeshu.com/git/go/libnslcd.git/proto" - "math/big" - s "syscall" -) - -func (o *Hackers) PAM_Authentication(cred s.Ucred, req p.Request_PAM_Authentication) <-chan p.PAM_Authentication { - o.lock.RLock() - ret := make(chan p.PAM_Authentication) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - uid := o.name2uid(req.UserName) - if uid < 0 { - return - } - - user := o.users[uid] - obj := p.PAM_Authentication{ - AuthenticationResult: p.NSLCD_PAM_AUTH_ERR, - UserName: "", - AuthorizationResult: p.NSLCD_PAM_AUTH_ERR, - AuthorizationError: "", - } - if check_password(req.Password, user.passwd.PwHash) { - obj.AuthenticationResult = p.NSLCD_PAM_SUCCESS - obj.AuthorizationResult = obj.AuthenticationResult - obj.UserName = user.passwd.Name - } - ret <- obj - }() - return ret -} - -func (o *Hackers) PAM_Authorization(cred s.Ucred, req p.Request_PAM_Authorization) <-chan p.PAM_Authorization { - o.lock.RLock() - ret := make(chan p.PAM_Authorization) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - uid := o.name2uid(req.UserName) - if uid < 0 { - return - } - ret <- p.PAM_Authorization{ - Result: p.NSLCD_PAM_SUCCESS, - Error: "", - } - }() - return ret -} - -const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - -var alphabet_len = big.NewInt(int64(len(alphabet))) - -func (o *Hackers) PAM_SessionOpen(cred s.Ucred, req p.Request_PAM_SessionOpen) <-chan p.PAM_SessionOpen { - ret := make(chan p.PAM_SessionOpen) - go func() { - defer close(ret) - - var sessionid [24]byte - for i := 0; i < len(sessionid); i++ { - bigint, err := rand.Int(rand.Reader, alphabet_len) - if err != nil { - return - } - sessionid[i] = alphabet[bigint.Int64()] - } - ret <- p.PAM_SessionOpen{SessionID: string(sessionid[:])} - }() - return ret -} - -func (o *Hackers) PAM_SessionClose(cred s.Ucred, req p.Request_PAM_SessionClose) <-chan p.PAM_SessionClose { - ret := make(chan p.PAM_SessionClose) - go close(ret) - return ret -} diff --git a/src/nshd/hackers_git/db_passwd.go b/src/nshd/hackers_git/db_passwd.go deleted file mode 100644 index d6e4f16..0000000 --- a/src/nshd/hackers_git/db_passwd.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import ( - p "lukeshu.com/git/go/libnslcd.git/proto" - s "syscall" -) - -/* Note that the output password hash value should be one of: - - no password set, allow login without password - ! - used to prevent logins - x - "valid" encrypted password that does not match any valid password - often used to indicate that the password is defined elsewhere - other - encrypted password, in crypt(3) format */ - -func (o *Hackers) Passwd_ByName(cred s.Ucred, req p.Request_Passwd_ByName) <-chan p.Passwd { - o.lock.RLock() - ret := make(chan p.Passwd) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - uid := o.name2uid(req.Name) - if uid < 0 { - return - } - passwd := o.users[uid].passwd - passwd.PwHash = "x" // only put actual hashes in the Shadow DB - ret <- passwd - }() - return ret -} - -func (o *Hackers) Passwd_ByUID(cred s.Ucred, req p.Request_Passwd_ByUID) <-chan p.Passwd { - o.lock.RLock() - ret := make(chan p.Passwd) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - user, found := o.users[req.UID] - if !found { - return - } - passwd := user.passwd - passwd.PwHash = "x" // only put actual hashes in the Shadow DB - ret <- passwd - }() - return ret -} - -func (o *Hackers) Passwd_All(cred s.Ucred, req p.Request_Passwd_All) <-chan p.Passwd { - o.lock.RLock() - ret := make(chan p.Passwd) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - for _, user := range o.users { - passwd := user.passwd - passwd.PwHash = "x" // only put actual hashes in the Shadow DB - ret <- passwd - } - }() - return ret -} diff --git a/src/nshd/hackers_git/db_shadow.go b/src/nshd/hackers_git/db_shadow.go deleted file mode 100644 index 2df4026..0000000 --- a/src/nshd/hackers_git/db_shadow.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import ( - p "lukeshu.com/git/go/libnslcd.git/proto" - s "syscall" -) - -func (o *Hackers) Shadow_ByName(cred s.Ucred, req p.Request_Shadow_ByName) <-chan p.Shadow { - o.lock.RLock() - ret := make(chan p.Shadow) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - if cred.Uid != 0 { - return - } - uid := o.name2uid(req.Name) - user := o.users[uid] - ret <- p.Shadow{ - Name: user.passwd.Name, - PwHash: user.passwd.PwHash, - LastChangeDate: -1, - MinDays: -1, - MaxDays: -1, - WarnDays: -1, - InactDays: -1, - ExpireDate: -1, - Flag: -1, - } - }() - return ret -} - -func (o *Hackers) Shadow_All(cred s.Ucred, req p.Request_Shadow_All) <-chan p.Shadow { - o.lock.RLock() - ret := make(chan p.Shadow) - go func() { - defer o.lock.RUnlock() - defer close(ret) - - if cred.Uid != 0 { - return - } - - for _, user := range o.users { - ret <- p.Shadow{ - Name: user.passwd.Name, - PwHash: user.passwd.PwHash, - LastChangeDate: -1, - MinDays: -1, - MaxDays: -1, - WarnDays: -1, - InactDays: -1, - ExpireDate: -1, - Flag: -1, - } - } - }() - return ret -} diff --git a/src/nshd/hackers_git/gid.go b/src/nshd/hackers_git/gid.go deleted file mode 100644 index 852b9a3..0000000 --- a/src/nshd/hackers_git/gid.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import "lukeshu.com/git/go/libgnulinux.git/getgr" - -func name2gid(name string) int32 { - gr, err := getgr.ByName(name) - if gr == nil || err != nil { - return -1 - } else { - return int32(gr.Gid) - } -} - -func gid2name(gid int32) (string, bool) { - gr, err := getgr.ByGid(gid) - if gr == nil || err != nil { - return "", false - } else { - return gr.Name, true - } -} diff --git a/src/nshd/hackers_git/hackers.go b/src/nshd/hackers_git/hackers.go deleted file mode 100644 index b9a0b9a..0000000 --- a/src/nshd/hackers_git/hackers.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015-2016 Luke Shumaker . -// -// 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. -// -// 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 -// . - -// Package hackers_git is an nslcd_server Backend that speaks to -// hackers.git. -package hackers_git - -import ( - "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" - "sync" -) - -type user struct { - passwd nslcd_proto.Passwd - groups []string -} - -type config struct { - Pam_password_prohibit_message string -} - -type Hackers struct { - nslcd_server.NilBackend - lock sync.RWMutex - - CfgFilename string - YamlCat string - - cfg config - users map[int32]user - groups map[string]map[string]bool -} - -var _ nslcd_systemd.Backend = &Hackers{} -var _ nslcd_server.Backend = &Hackers{} - -func (o *Hackers) Init() error { - logger.Debug("hackers.git: CfgFilename = %v", o.CfgFilename) - logger.Debug("hackers.git: YamlCat = %v", o.YamlCat) - err := o.Reload() - if err != nil { - logger.Err("hackers.git: Could not initialize: %v", err) - return err - } - return nil -} - -func (o *Hackers) Close() { - logger.Info("hackers.git: Closing session") - o.lock.Lock() - defer o.lock.Unlock() - - o.users = make(map[int32]user, 0) - o.groups = make(map[string]map[string]bool) -} - -func (o *Hackers) Reload() error { - logger.Info("hackers.git: Loading session") - o.lock.Lock() - defer o.lock.Unlock() - - var err error - o.cfg, err = parse_config(o.CfgFilename) - if err != nil { - return err - } - logger.Info("hackers.git: pam_password_prohibit_message: %#v", o.cfg.Pam_password_prohibit_message) - - logger.Debug("hackers.git: Parsing user data") - o.users, err = parse_users(o.YamlCat) - if err != nil { - return err - } - - o.groups = make(map[string]map[string]bool) - for _, user := range o.users { - for _, groupname := range user.groups { - o.add_user_to_group(user.passwd.Name, groupname) - } - } - return nil -} - -func (o *Hackers) name2uid(name string) int32 { - for uid, data := range o.users { - if data.passwd.Name == name { - return uid - } - } - 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_parse.go b/src/nshd/hackers_git/hackers_parse.go deleted file mode 100644 index af8c913..0000000 --- a/src/nshd/hackers_git/hackers_parse.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2015-2016 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -import ( - "fmt" - yaml "gopkg.in/yaml.v2" - "io/ioutil" - "lukeshu.com/git/go/libsystemd.git/sd_daemon/logger" - "os" - "os/exec" - "strings" -) - -var usersGid = name2gid("users") - -func parse_config(filename string) (cfg config, err error) { - file, err := os.Open(filename) - if err != nil { - return - } - contents, err := ioutil.ReadAll(file) - if err != nil { - return - } - err = yaml.Unmarshal(contents, &cfg) - return -} - -func parse_users(yaml_cat string) (users map[int32]user, err error) { - contents, err := exec.Command(yaml_cat).Output() - if err != nil { - return - } - - var _data interface{} - err = yaml.Unmarshal(contents, &_data) - if err != nil { - return - } - - data, isMap := _data.(map[interface{}]interface{}) - errs := []string{} - if !isMap { - errs = append(errs, "root node is not a map") - } else { - users = make(map[int32]user, len(data)) - for _uid, _user := range data { - uid, isInt := _uid.(int) - if !isInt { - errs = append(errs, fmt.Sprintf("UID is not an int: %T ( %#v )", _uid, _uid)) - continue - } - user, _err := parse_user(_user) - if _err != nil { - errs = append(errs, fmt.Sprintf("Could not parse data for UID %d: %v", uid, _err)) - continue - } - user.passwd.UID = int32(uid) - logger.Debug("hackers.git: -> User %d(%s) parsed", user.passwd.UID, user.passwd.Name) - users[user.passwd.UID] = user - } - } - if len(errs) > 0 { - users = nil - err = &yaml.TypeError{Errors: errs} - } - return -} - -func parse_user(_data interface{}) (ret user, err error) { - data, isMap := _data.(map[interface{}]interface{}) - errs := []string{} - if !isMap { - errs = append(errs, "root node is not a map") - } else { - if iface, isSet := data["username"]; !isSet { - errs = append(errs, "\"username\" is not set") - } else if str, isTyp := iface.(string); !isTyp { - errs = append(errs, "\"username\" is not a string") - } else { - ret.passwd.Name = str - ret.passwd.HomeDir = "/home/" + str - } - - if iface, isSet := data["fullname"]; !isSet { - errs = append(errs, "\"fullname\" is not set") - } else if str, isTyp := iface.(string); !isTyp { - errs = append(errs, "\"fullname\" is not a string") - } else { - ret.passwd.GECOS = str - } - - if iface, isSet := data["shell"]; !isSet { - errs = append(errs, "\"shell\" is not set") - } else if str, isTyp := iface.(string); !isTyp { - errs = append(errs, "\"shell\" is not a string") - } else { - ret.passwd.Shell = str - } - - if iface, isSet := data["groups"]; !isSet { - ret.groups = make([]string, 0) - } else if ary, isTyp := iface.([]interface{}); !isTyp { - errs = append(errs, "\"groups\" is not an array") - } else { - groups := make(map[string]bool, len(ary)) - e := false - for _, iface := range ary { - if str, isTyp := iface.(string); !isTyp { - errs = append(errs, "\"group\" item is not an array") - e = true - break - } else { - groups[str] = true - } - } - if !e { - ret.groups = set2list(groups) - } - } - } - if len(errs) > 0 { - err = &yaml.TypeError{Errors: errs} - } - - ret.passwd.PwHash = parse_user_password(ret.passwd.HomeDir + "/.password") - ret.passwd.GID = usersGid - - return -} - -func parse_user_password(filename string) (hash string) { - hash = "!" - file, err := os.Open(filename) - if err != nil { - logger.Debug("hackers.git: %v", err) - return - } - contents, err := ioutil.ReadAll(file) - if err != nil { - logger.Debug("hackers.git: Error while reading: %q: %v", filename, err) - return - } - lines := strings.Split(string(contents), "\n") - switch len(lines) { - case 1: - hash = lines[0] - case 2: - if lines[1] == "" { - hash = lines[0] - } else { - logger.Debug("hackers.git: Invalid password format in file: %q", filename) - } - default: - logger.Debug("hackers.git: Invalid password format in file: %q", filename) - } - return -} diff --git a/src/nshd/hackers_git/set.go b/src/nshd/hackers_git/set.go deleted file mode 100644 index f0cf454..0000000 --- a/src/nshd/hackers_git/set.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 Luke Shumaker . -// -// 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. -// -// 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 -// . - -package hackers_git - -func set2list(set map[string]bool) []string { - list := make([]string, len(set)) - i := uint(0) - for item, _ := range set { - list[i] = item - i++ - } - return list -} diff --git a/src/nshd/main.go.in b/src/nshd/main.go.in deleted file mode 100644 index 7dd4cae..0000000 --- a/src/nshd/main.go.in +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015-2016 Luke Shumaker . -// -// 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. -// -// 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 -// . - -// Command nshd is an implementation of nslcd that talks to hackers.git instead of LDAP. -package main - -import ( - "lukeshu.com/git/go/libnslcd.git/systemd" - "nshd/hackers_git" - "os" -) - -func main() { - backend := &hackers_git.Hackers{ - CfgFilename: "@conf_file@", - YamlCat: "@bindir@/meta-cat", - } - os.Exit(int(nslcd_systemd.Main(backend))) -} diff --git a/src/parabola_hackers/nslcd_backend/check_password.go b/src/parabola_hackers/nslcd_backend/check_password.go new file mode 100644 index 0000000..1458b6f --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/check_password.go @@ -0,0 +1,23 @@ +// Copyright 2015-2016 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import "lukeshu.com/git/go/libgnulinux.git/crypt" + +func check_password(password string, hash string) bool { + return crypt.Crypt(password, hash) == hash +} diff --git a/src/parabola_hackers/nslcd_backend/db_config.go b/src/parabola_hackers/nslcd_backend/db_config.go new file mode 100644 index 0000000..934498d --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/db_config.go @@ -0,0 +1,39 @@ +// Copyright 2015-2016 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import ( + p "lukeshu.com/git/go/libnslcd.git/proto" + s "syscall" +) + +func (o *Hackers) Config_Get(cred s.Ucred, req p.Request_Config_Get) <-chan p.Config { + o.lock.RLock() + ret := make(chan p.Config) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + switch req.Key { + case p.NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE: + if o.cfg.Pam_password_prohibit_message != "" { + ret <- p.Config{Value: o.cfg.Pam_password_prohibit_message} + } + } + }() + return ret +} diff --git a/src/parabola_hackers/nslcd_backend/db_group.go b/src/parabola_hackers/nslcd_backend/db_group.go new file mode 100644 index 0000000..8990fad --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/db_group.go @@ -0,0 +1,139 @@ +// Copyright 2015-2016 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import ( + p "lukeshu.com/git/go/libnslcd.git/proto" + s "syscall" +) + +func (o *Hackers) groupByName(name string, users bool) p.Group { + members_set, found := o.groups[name] + if !found { + return p.Group{ID: -1} + } + gid := name2gid(name) + if gid < 0 { + return p.Group{ID: -1} + } + var members_list []string + if users { + members_list = set2list(members_set) + } else { + members_list = make([]string, 0) + } + return p.Group{ + Name: name, + PwHash: "x", + ID: gid, + Members: members_list, + } +} + +func (o *Hackers) groupByGid(gid int32, users bool) p.Group { + name, found := gid2name(gid) + if !found { + return p.Group{ID: -1} + } + members_set, found := o.groups[name] + if !found { + return p.Group{ID: -1} + } + var members_list []string + if users { + members_list = set2list(members_set) + } else { + members_list = make([]string, 0) + } + return p.Group{ + Name: name, + PwHash: "x", + ID: gid, + Members: members_list, + } +} + +func (o *Hackers) Group_ByName(cred s.Ucred, req p.Request_Group_ByName) <-chan p.Group { + o.lock.RLock() + ret := make(chan p.Group) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + group := o.groupByName(req.Name, true) + if group.ID < 0 { + return + } + ret <- group + }() + return ret +} + +func (o *Hackers) Group_ByGid(cred s.Ucred, req p.Request_Group_ByGid) <-chan p.Group { + o.lock.RLock() + ret := make(chan p.Group) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + group := o.groupByGid(req.Gid, true) + if group.ID < 0 { + return + } + ret <- group + }() + return ret +} + +// note that the BYMEMBER call returns an empty members list +func (o *Hackers) Group_ByMember(cred s.Ucred, req p.Request_Group_ByMember) <-chan p.Group { + o.lock.RLock() + ret := make(chan p.Group) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + uid := o.name2uid(req.Member) + if uid < 0 { + return + } + for _, name := range o.users[uid].groups { + group := o.groupByName(name, false) + if group.ID >= 0 { + ret <- group + } + } + }() + return ret +} + +func (o *Hackers) Group_All(cred s.Ucred, req p.Request_Group_All) <-chan p.Group { + o.lock.RLock() + ret := make(chan p.Group) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + for name, _ := range o.groups { + group := o.groupByName(name, true) + if group.ID >= 0 { + ret <- group + } + } + }() + return ret +} diff --git a/src/parabola_hackers/nslcd_backend/db_pam.go b/src/parabola_hackers/nslcd_backend/db_pam.go new file mode 100644 index 0000000..6b2a7c7 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/db_pam.go @@ -0,0 +1,100 @@ +// Copyright 2015 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import ( + "crypto/rand" + p "lukeshu.com/git/go/libnslcd.git/proto" + "math/big" + s "syscall" +) + +func (o *Hackers) PAM_Authentication(cred s.Ucred, req p.Request_PAM_Authentication) <-chan p.PAM_Authentication { + o.lock.RLock() + ret := make(chan p.PAM_Authentication) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + uid := o.name2uid(req.UserName) + if uid < 0 { + return + } + + user := o.users[uid] + obj := p.PAM_Authentication{ + AuthenticationResult: p.NSLCD_PAM_AUTH_ERR, + UserName: "", + AuthorizationResult: p.NSLCD_PAM_AUTH_ERR, + AuthorizationError: "", + } + if check_password(req.Password, user.passwd.PwHash) { + obj.AuthenticationResult = p.NSLCD_PAM_SUCCESS + obj.AuthorizationResult = obj.AuthenticationResult + obj.UserName = user.passwd.Name + } + ret <- obj + }() + return ret +} + +func (o *Hackers) PAM_Authorization(cred s.Ucred, req p.Request_PAM_Authorization) <-chan p.PAM_Authorization { + o.lock.RLock() + ret := make(chan p.PAM_Authorization) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + uid := o.name2uid(req.UserName) + if uid < 0 { + return + } + ret <- p.PAM_Authorization{ + Result: p.NSLCD_PAM_SUCCESS, + Error: "", + } + }() + return ret +} + +const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +var alphabet_len = big.NewInt(int64(len(alphabet))) + +func (o *Hackers) PAM_SessionOpen(cred s.Ucred, req p.Request_PAM_SessionOpen) <-chan p.PAM_SessionOpen { + ret := make(chan p.PAM_SessionOpen) + go func() { + defer close(ret) + + var sessionid [24]byte + for i := 0; i < len(sessionid); i++ { + bigint, err := rand.Int(rand.Reader, alphabet_len) + if err != nil { + return + } + sessionid[i] = alphabet[bigint.Int64()] + } + ret <- p.PAM_SessionOpen{SessionID: string(sessionid[:])} + }() + return ret +} + +func (o *Hackers) PAM_SessionClose(cred s.Ucred, req p.Request_PAM_SessionClose) <-chan p.PAM_SessionClose { + ret := make(chan p.PAM_SessionClose) + go close(ret) + return ret +} diff --git a/src/parabola_hackers/nslcd_backend/db_passwd.go b/src/parabola_hackers/nslcd_backend/db_passwd.go new file mode 100644 index 0000000..514a8b3 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/db_passwd.go @@ -0,0 +1,81 @@ +// Copyright 2015 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import ( + p "lukeshu.com/git/go/libnslcd.git/proto" + s "syscall" +) + +/* Note that the output password hash value should be one of: + - no password set, allow login without password + ! - used to prevent logins + x - "valid" encrypted password that does not match any valid password + often used to indicate that the password is defined elsewhere + other - encrypted password, in crypt(3) format */ + +func (o *Hackers) Passwd_ByName(cred s.Ucred, req p.Request_Passwd_ByName) <-chan p.Passwd { + o.lock.RLock() + ret := make(chan p.Passwd) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + uid := o.name2uid(req.Name) + if uid < 0 { + return + } + passwd := o.users[uid].passwd + passwd.PwHash = "x" // only put actual hashes in the Shadow DB + ret <- passwd + }() + return ret +} + +func (o *Hackers) Passwd_ByUID(cred s.Ucred, req p.Request_Passwd_ByUID) <-chan p.Passwd { + o.lock.RLock() + ret := make(chan p.Passwd) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + user, found := o.users[req.UID] + if !found { + return + } + passwd := user.passwd + passwd.PwHash = "x" // only put actual hashes in the Shadow DB + ret <- passwd + }() + return ret +} + +func (o *Hackers) Passwd_All(cred s.Ucred, req p.Request_Passwd_All) <-chan p.Passwd { + o.lock.RLock() + ret := make(chan p.Passwd) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + for _, user := range o.users { + passwd := user.passwd + passwd.PwHash = "x" // only put actual hashes in the Shadow DB + ret <- passwd + } + }() + return ret +} diff --git a/src/parabola_hackers/nslcd_backend/db_shadow.go b/src/parabola_hackers/nslcd_backend/db_shadow.go new file mode 100644 index 0000000..26b1b05 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/db_shadow.go @@ -0,0 +1,77 @@ +// Copyright 2015 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import ( + p "lukeshu.com/git/go/libnslcd.git/proto" + s "syscall" +) + +func (o *Hackers) Shadow_ByName(cred s.Ucred, req p.Request_Shadow_ByName) <-chan p.Shadow { + o.lock.RLock() + ret := make(chan p.Shadow) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + if cred.Uid != 0 { + return + } + uid := o.name2uid(req.Name) + user := o.users[uid] + ret <- p.Shadow{ + Name: user.passwd.Name, + PwHash: user.passwd.PwHash, + LastChangeDate: -1, + MinDays: -1, + MaxDays: -1, + WarnDays: -1, + InactDays: -1, + ExpireDate: -1, + Flag: -1, + } + }() + return ret +} + +func (o *Hackers) Shadow_All(cred s.Ucred, req p.Request_Shadow_All) <-chan p.Shadow { + o.lock.RLock() + ret := make(chan p.Shadow) + go func() { + defer o.lock.RUnlock() + defer close(ret) + + if cred.Uid != 0 { + return + } + + for _, user := range o.users { + ret <- p.Shadow{ + Name: user.passwd.Name, + PwHash: user.passwd.PwHash, + LastChangeDate: -1, + MinDays: -1, + MaxDays: -1, + WarnDays: -1, + InactDays: -1, + ExpireDate: -1, + Flag: -1, + } + } + }() + return ret +} diff --git a/src/parabola_hackers/nslcd_backend/gid.go b/src/parabola_hackers/nslcd_backend/gid.go new file mode 100644 index 0000000..eabdbd7 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/gid.go @@ -0,0 +1,37 @@ +// Copyright 2015 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import "lukeshu.com/git/go/libgnulinux.git/getgr" + +func name2gid(name string) int32 { + gr, err := getgr.ByName(name) + if gr == nil || err != nil { + return -1 + } else { + return int32(gr.Gid) + } +} + +func gid2name(gid int32) (string, bool) { + gr, err := getgr.ByGid(gid) + if gr == nil || err != nil { + return "", false + } else { + return gr.Name, true + } +} diff --git a/src/parabola_hackers/nslcd_backend/hackers.go b/src/parabola_hackers/nslcd_backend/hackers.go new file mode 100644 index 0000000..66312c6 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/hackers.go @@ -0,0 +1,116 @@ +// Copyright 2015-2016 Luke Shumaker . +// +// 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. +// +// 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 +// . + +// Package hackers_nslcd_backend is an nslcd_server Backend that +// speaks to hackers.git. +package hackers_nslcd_backend + +import ( + "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" + "sync" +) + +type user struct { + passwd nslcd_proto.Passwd + groups []string +} + +type config struct { + Pam_password_prohibit_message string +} + +type Hackers struct { + nslcd_server.NilBackend + lock sync.RWMutex + + CfgFilename string + YamlCat string + + cfg config + users map[int32]user + groups map[string]map[string]bool +} + +var _ nslcd_systemd.Backend = &Hackers{} +var _ nslcd_server.Backend = &Hackers{} + +func (o *Hackers) Init() error { + logger.Debug("hackers.git: CfgFilename = %v", o.CfgFilename) + logger.Debug("hackers.git: YamlCat = %v", o.YamlCat) + err := o.Reload() + if err != nil { + logger.Err("hackers.git: Could not initialize: %v", err) + return err + } + return nil +} + +func (o *Hackers) Close() { + logger.Info("hackers.git: Closing session") + o.lock.Lock() + defer o.lock.Unlock() + + o.users = make(map[int32]user, 0) + o.groups = make(map[string]map[string]bool) +} + +func (o *Hackers) Reload() error { + logger.Info("hackers.git: Loading session") + o.lock.Lock() + defer o.lock.Unlock() + + var err error + o.cfg, err = parse_config(o.CfgFilename) + if err != nil { + return err + } + logger.Info("hackers.git: pam_password_prohibit_message: %#v", o.cfg.Pam_password_prohibit_message) + + logger.Debug("hackers.git: Parsing user data") + o.users, err = parse_users(o.YamlCat) + if err != nil { + return err + } + + o.groups = make(map[string]map[string]bool) + for _, user := range o.users { + for _, groupname := range user.groups { + o.add_user_to_group(user.passwd.Name, groupname) + } + } + return nil +} + +func (o *Hackers) name2uid(name string) int32 { + for uid, data := range o.users { + if data.passwd.Name == name { + return uid + } + } + 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/parabola_hackers/nslcd_backend/hackers_parse.go b/src/parabola_hackers/nslcd_backend/hackers_parse.go new file mode 100644 index 0000000..b18fdf8 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/hackers_parse.go @@ -0,0 +1,173 @@ +// Copyright 2015-2016 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +import ( + "fmt" + yaml "gopkg.in/yaml.v2" + "io/ioutil" + "lukeshu.com/git/go/libsystemd.git/sd_daemon/logger" + "os" + "os/exec" + "strings" +) + +var usersGid = name2gid("users") + +func parse_config(filename string) (cfg config, err error) { + file, err := os.Open(filename) + if err != nil { + return + } + contents, err := ioutil.ReadAll(file) + if err != nil { + return + } + err = yaml.Unmarshal(contents, &cfg) + return +} + +func parse_users(yaml_cat string) (users map[int32]user, err error) { + contents, err := exec.Command(yaml_cat).Output() + if err != nil { + return + } + + var _data interface{} + err = yaml.Unmarshal(contents, &_data) + if err != nil { + return + } + + data, isMap := _data.(map[interface{}]interface{}) + errs := []string{} + if !isMap { + errs = append(errs, "root node is not a map") + } else { + users = make(map[int32]user, len(data)) + for _uid, _user := range data { + uid, isInt := _uid.(int) + if !isInt { + errs = append(errs, fmt.Sprintf("UID is not an int: %T ( %#v )", _uid, _uid)) + continue + } + user, _err := parse_user(_user) + if _err != nil { + errs = append(errs, fmt.Sprintf("Could not parse data for UID %d: %v", uid, _err)) + continue + } + user.passwd.UID = int32(uid) + logger.Debug("hackers.git: -> User %d(%s) parsed", user.passwd.UID, user.passwd.Name) + users[user.passwd.UID] = user + } + } + if len(errs) > 0 { + users = nil + err = &yaml.TypeError{Errors: errs} + } + return +} + +func parse_user(_data interface{}) (ret user, err error) { + data, isMap := _data.(map[interface{}]interface{}) + errs := []string{} + if !isMap { + errs = append(errs, "root node is not a map") + } else { + if iface, isSet := data["username"]; !isSet { + errs = append(errs, "\"username\" is not set") + } else if str, isTyp := iface.(string); !isTyp { + errs = append(errs, "\"username\" is not a string") + } else { + ret.passwd.Name = str + ret.passwd.HomeDir = "/home/" + str + } + + if iface, isSet := data["fullname"]; !isSet { + errs = append(errs, "\"fullname\" is not set") + } else if str, isTyp := iface.(string); !isTyp { + errs = append(errs, "\"fullname\" is not a string") + } else { + ret.passwd.GECOS = str + } + + if iface, isSet := data["shell"]; !isSet { + errs = append(errs, "\"shell\" is not set") + } else if str, isTyp := iface.(string); !isTyp { + errs = append(errs, "\"shell\" is not a string") + } else { + ret.passwd.Shell = str + } + + if iface, isSet := data["groups"]; !isSet { + ret.groups = make([]string, 0) + } else if ary, isTyp := iface.([]interface{}); !isTyp { + errs = append(errs, "\"groups\" is not an array") + } else { + groups := make(map[string]bool, len(ary)) + e := false + for _, iface := range ary { + if str, isTyp := iface.(string); !isTyp { + errs = append(errs, "\"group\" item is not an array") + e = true + break + } else { + groups[str] = true + } + } + if !e { + ret.groups = set2list(groups) + } + } + } + if len(errs) > 0 { + err = &yaml.TypeError{Errors: errs} + } + + ret.passwd.PwHash = parse_user_password(ret.passwd.HomeDir + "/.password") + ret.passwd.GID = usersGid + + return +} + +func parse_user_password(filename string) (hash string) { + hash = "!" + file, err := os.Open(filename) + if err != nil { + logger.Debug("hackers.git: %v", err) + return + } + contents, err := ioutil.ReadAll(file) + if err != nil { + logger.Debug("hackers.git: Error while reading: %q: %v", filename, err) + return + } + lines := strings.Split(string(contents), "\n") + switch len(lines) { + case 1: + hash = lines[0] + case 2: + if lines[1] == "" { + hash = lines[0] + } else { + logger.Debug("hackers.git: Invalid password format in file: %q", filename) + } + default: + logger.Debug("hackers.git: Invalid password format in file: %q", filename) + } + return +} diff --git a/src/parabola_hackers/nslcd_backend/set.go b/src/parabola_hackers/nslcd_backend/set.go new file mode 100644 index 0000000..7a01c01 --- /dev/null +++ b/src/parabola_hackers/nslcd_backend/set.go @@ -0,0 +1,27 @@ +// Copyright 2015 Luke Shumaker . +// +// 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. +// +// 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 +// . + +package hackers_nslcd_backend + +func set2list(set map[string]bool) []string { + list := make([]string, len(set)) + i := uint(0) + for item, _ := range set { + list[i] = item + i++ + } + return list +} -- cgit v1.2.2