summaryrefslogtreecommitdiff
path: root/nslcd_systemd
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-12-18 03:59:10 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-12-18 03:59:10 -0500
commit5aa2dc8085d65c8cfcc46a02ee74ddb9d9032e62 (patch)
tree7ffa48eea1cd99655413a18b83144c8ca2ddf5bb /nslcd_systemd
parent321e6c8958823f64fa2464497f9d217712f93530 (diff)
Rename packages to make goimports happy. BREAKING CHANGE.
Diffstat (limited to 'nslcd_systemd')
-rw-r--r--nslcd_systemd/disable_nss_module.go63
-rw-r--r--nslcd_systemd/nslcd_systemd.go164
2 files changed, 227 insertions, 0 deletions
diff --git a/nslcd_systemd/disable_nss_module.go b/nslcd_systemd/disable_nss_module.go
new file mode 100644
index 0000000..d13cb5f
--- /dev/null
+++ b/nslcd_systemd/disable_nss_module.go
@@ -0,0 +1,63 @@
+// Copyright (C) 2006 West Consulting
+// Copyright (C) 2006-2015 Arthur de Jong
+// Copyright (C) 2015-2016 Luke Shumaker <lukeshu@sbcglobal.net>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301 USA
+
+package nslcd_systemd
+
+import (
+ "fmt"
+
+ "lukeshu.com/git/go/libgnulinux.git/dl"
+ "lukeshu.com/git/go/libsystemd.git/sd_daemon"
+)
+
+//static char *strary(char **ary, unsigned int n) { return ary[n]; }
+import "C"
+
+const (
+ nss_module_soname = "libnss_ldap.so.2"
+ nss_module_sym_version = "_nss_ldap_version"
+ nss_module_sym_enablelookups = "_nss_ldap_enablelookups"
+)
+
+func disable_nss_module() {
+ handle, err := dl.Open(nss_module_soname, dl.RTLD_LAZY|dl.RTLD_NODELETE)
+ if err == nil {
+ defer handle.Close()
+ } else {
+ sd_daemon.Log.Warning(fmt.Sprintf("NSS module %s not loaded: %v", nss_module_soname, err))
+ return
+ }
+
+ c_version_info, err := handle.Sym(nss_module_sym_version)
+ if err == nil {
+ g_version_info := (**C.char)(c_version_info)
+ sd_daemon.Log.Debug(fmt.Sprintf("NSS module %s version %s %s", nss_module_soname,
+ C.GoString(C.strary(g_version_info, 0)),
+ C.GoString(C.strary(g_version_info, 1))))
+ } else {
+ sd_daemon.Log.Warning(fmt.Sprintf("NSS module %s version missing: %v", nss_module_soname, err))
+ }
+ c_enable_flag, err := handle.Sym(nss_module_sym_enablelookups)
+ if err != nil {
+ sd_daemon.Log.Warning(fmt.Sprintf("Unable to disable NSS ldap module for nslcd process: %v", err))
+ return
+ }
+ g_enable_flag := (*C.int)(c_enable_flag)
+ *g_enable_flag = 0
+}
diff --git a/nslcd_systemd/nslcd_systemd.go b/nslcd_systemd/nslcd_systemd.go
new file mode 100644
index 0000000..eb545c2
--- /dev/null
+++ b/nslcd_systemd/nslcd_systemd.go
@@ -0,0 +1,164 @@
+// Copyright (C) 2015-2016 Luke Shumaker <lukeshu@sbcglobal.net>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301 USA
+
+// Package nslcd_systemd does the legwork for implementing a systemd
+// socket-activated nslcd server.
+//
+// You just need to implement the Backend interface, then pass it to
+// Main, which will return the exit code for the process. Everything
+// but the backend is taken care of for you!
+//
+// package main
+//
+// import "nslcd/systemd"
+//
+// func main() {
+// backend := ...
+// os.Exit(int(nslcd_systemd.Main(backend)))
+// }
+package nslcd_systemd
+
+import (
+ "fmt"
+ "net"
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+
+ "lukeshu.com/git/go/libnslcd.git/nslcd_server"
+ "lukeshu.com/git/go/libsystemd.git/sd_daemon"
+ "lukeshu.com/git/go/libsystemd.git/sd_daemon/lsb"
+)
+
+type Backend interface {
+ nslcd_server.Backend
+ Init() error
+ Reload() error
+ Close()
+}
+
+func get_socket() (socket net.Listener, err error) {
+ socket = nil
+ err = nil
+ fds := sd_daemon.ListenFds(true)
+ if fds == nil {
+ err = fmt.Errorf("Failed to aquire sockets from systemd")
+ return
+ }
+ if len(fds) != 1 {
+ err = fmt.Errorf("Wrong number of sockets from systemd: expected %d but got %d", 1, len(fds))
+ return
+ }
+ socket, err = net.FileListener(fds[0])
+ fds[0].Close()
+ return
+}
+
+func getpeercred(conn *net.UnixConn) (cred syscall.Ucred, err error) {
+ file, err := conn.File()
+ if err != nil {
+ return
+ }
+ defer file.Close()
+ _cred, err := syscall.GetsockoptUcred(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_PEERCRED)
+ cred = *_cred
+ return
+}
+
+func handler(conn *net.UnixConn, backend nslcd_server.Backend) {
+ defer conn.Close()
+ cred, err := getpeercred(conn)
+ if err != nil {
+ sd_daemon.Log.Debug("Connection from unknown client")
+ } else {
+ sd_daemon.Log.Debug(fmt.Sprintf("Connection from pid=%v uid=%v gid=%v",
+ cred.Pid, cred.Uid, cred.Gid))
+ }
+ err = nslcd_server.HandleRequest(backend, conn, conn, cred)
+ if err != nil {
+ sd_daemon.Log.Notice(fmt.Sprintf("Error while handling request: %v", err))
+ }
+}
+
+func Main(backend Backend) uint8 {
+ var err error = nil
+
+ sigs := make(chan os.Signal)
+ signal.Notify(sigs, syscall.SIGTERM, syscall.SIGHUP)
+
+ disable_nss_module()
+
+ err = backend.Init()
+ if err != nil {
+ sd_daemon.Log.Err(fmt.Sprintf("Could not initialize backend: %v", err))
+ sd_daemon.Notify(0, false, "STOPPING=1", nil)
+ return lsb.EXIT_FAILURE
+ }
+ defer backend.Close()
+
+ socket, err := get_socket()
+ if err != nil {
+ sd_daemon.Log.Err(fmt.Sprintf("%v", err))
+ sd_daemon.Notify(0, false, "STOPPING=1", nil)
+ return lsb.EXIT_NOTRUNNING
+ }
+ defer socket.Close()
+ sock := make(chan *net.UnixConn)
+ go func() {
+ defer lsb.Recover()
+ for {
+ conn, err := socket.Accept()
+ if err != nil {
+ sd_daemon.Log.Notice(fmt.Sprintf("%v", err))
+ }
+ if conn != nil {
+ sock <- conn.(*net.UnixConn)
+ }
+ }
+ }()
+
+ var wg sync.WaitGroup
+ defer wg.Wait()
+ defer sd_daemon.Notify(0, false, "STOPPING=1", nil)
+ sd_daemon.Notify(0, false, "READY=1", nil)
+ for {
+ select {
+ case sig := <-sigs:
+ switch sig {
+ case syscall.SIGTERM:
+ sd_daemon.Log.Notice("Received SIGTERM, shutting down")
+ return lsb.EXIT_SUCCESS
+ case syscall.SIGHUP:
+ sd_daemon.Notify(0, false, "RELOADING=1", nil)
+ err := backend.Reload()
+ if err != nil {
+ sd_daemon.Log.Notice(fmt.Sprintf("Could not reload backend: %s", err.Error()))
+ return lsb.EXIT_NOTRUNNING
+ }
+ sd_daemon.Notify(0, false, "READY=1", nil)
+ }
+ case conn := <-sock:
+ wg.Add(1)
+ go func() {
+ defer lsb.Recover()
+ defer wg.Done()
+ handler(conn, backend)
+ }()
+ }
+ }
+}