From 5aa2dc8085d65c8cfcc46a02ee74ddb9d9032e62 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 18 Dec 2016 03:59:10 -0500 Subject: Rename packages to make goimports happy. BREAKING CHANGE. --- nslcd_proto/.gitignore | 1 + nslcd_proto/Makefile | 28 ++ nslcd_proto/common.mk | 33 +++ nslcd_proto/doc.go | 22 ++ nslcd_proto/io.go | 176 +++++++++++++ nslcd_proto/nslcd_h.go | 454 +++++++++++++++++++++++++++++++++ nslcd_server/.gitignore | 3 + nslcd_server/Makefile | 37 +++ nslcd_server/doc.go | 25 ++ nslcd_server/func_handlerequest.go.gen | 120 +++++++++ nslcd_server/interface_backend.go.gen | 40 +++ nslcd_server/type_nilbackend.go.gen | 41 +++ nslcd_systemd/disable_nss_module.go | 63 +++++ nslcd_systemd/nslcd_systemd.go | 164 ++++++++++++ proto/.gitignore | 1 - proto/Makefile | 26 -- proto/common.mk | 33 --- proto/doc.go | 22 -- proto/io.go | 176 ------------- proto/nslcd_h.go | 454 --------------------------------- proto/server/.gitignore | 3 - proto/server/Makefile | 36 --- proto/server/doc.go | 25 -- proto/server/func_handlerequest.go.sh | 120 --------- proto/server/interface_backend.go.sh | 40 --- proto/server/type_nilbackend.go.sh | 41 --- systemd/disable_nss_module.go | 63 ----- systemd/nslcd_systemd.go | 164 ------------ 28 files changed, 1207 insertions(+), 1204 deletions(-) create mode 100644 nslcd_proto/.gitignore create mode 100644 nslcd_proto/Makefile create mode 100644 nslcd_proto/common.mk create mode 100644 nslcd_proto/doc.go create mode 100644 nslcd_proto/io.go create mode 100644 nslcd_proto/nslcd_h.go create mode 100644 nslcd_server/.gitignore create mode 100644 nslcd_server/Makefile create mode 100644 nslcd_server/doc.go create mode 100755 nslcd_server/func_handlerequest.go.gen create mode 100755 nslcd_server/interface_backend.go.gen create mode 100755 nslcd_server/type_nilbackend.go.gen create mode 100644 nslcd_systemd/disable_nss_module.go create mode 100644 nslcd_systemd/nslcd_systemd.go delete mode 100644 proto/.gitignore delete mode 100644 proto/Makefile delete mode 100644 proto/common.mk delete mode 100644 proto/doc.go delete mode 100644 proto/io.go delete mode 100644 proto/nslcd_h.go delete mode 100644 proto/server/.gitignore delete mode 100644 proto/server/Makefile delete mode 100644 proto/server/doc.go delete mode 100755 proto/server/func_handlerequest.go.sh delete mode 100755 proto/server/interface_backend.go.sh delete mode 100755 proto/server/type_nilbackend.go.sh delete mode 100644 systemd/disable_nss_module.go delete mode 100644 systemd/nslcd_systemd.go diff --git a/nslcd_proto/.gitignore b/nslcd_proto/.gitignore new file mode 100644 index 0000000..9330212 --- /dev/null +++ b/nslcd_proto/.gitignore @@ -0,0 +1 @@ +/requests.txt diff --git a/nslcd_proto/Makefile b/nslcd_proto/Makefile new file mode 100644 index 0000000..c031de4 --- /dev/null +++ b/nslcd_proto/Makefile @@ -0,0 +1,28 @@ +# Copyright (C) 2015-2016 Luke Shumaker +# +# 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 + +files.src.gen += requests.txt + +files.generate: $(files.src.gen) +maintainer-clean: + rm -f -- $(files.src.gen) +.PHONY: files.generate maintainer-clean + +requests.txt: nslcd_h.go Makefile + < $< grep -Eo '\btype Request_([^_ ]+)(_\S+)?' | sed 's/^type Request_//' > $@ + +.DELETE_ON_ERROR: diff --git a/nslcd_proto/common.mk b/nslcd_proto/common.mk new file mode 100644 index 0000000..1496356 --- /dev/null +++ b/nslcd_proto/common.mk @@ -0,0 +1,33 @@ +# Copyright © 2015-2016 Luke Shumaker +# This work is free. You can redistribute it and/or modify it under the +# terms of the Do What The Fuck You Want To Public License, Version 2, +# as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. + +all: build +.PHONY: all + +generate: $(addprefix $(srcdir)/,$(std.gen_files)) +.PHONY: generate + +configure: generate $(addprefix $(outdir)/,$(std.cfg_files)) +.PHONY: configure + +build: configure $(addprefix $(outdir)/,$(std.out_files)) +.PHONY: build + +install: build $(addprefix $(DESTDIR),$(std.sys_files)) +.PHONY: install + +maintainer-clean: private files=$(addprefix $(srcdir)/,$(std.gen_files) $(std.secondary_gen_files)) # un-generate +distclean : private files=$(addprefix $(outdir)/,$(std.cfg_files) $(std.secondary_cfg_files)) # un-configure +clean : private files=$(addprefix $(outdir)/,$(std.out_files) $(std.secondary_out_files)) # un-build +uninstall : private files=$(addprefix $(DESTDIR),$(std.sys_files) ) # un-install + +distclean: clean +maintainer-clean: distclean + +clean distclean maintainer-clean uninstall: + rm -f -- $(sort $(filter-out %/,$(files))) + rm -f -r -- $(sort $(filter %/,$(files))) + rmdir -p -- $(sort $(dir $(files))) 2>/dev/null || true +.PHONY: clean distclean maintainer-clean uninstall diff --git a/nslcd_proto/doc.go b/nslcd_proto/doc.go new file mode 100644 index 0000000..70929f3 --- /dev/null +++ b/nslcd_proto/doc.go @@ -0,0 +1,22 @@ +// Copyright (C) 2015 Luke Shumaker +// +// 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_proto implements the nslcd protocol of nss-pam-ldapd. +// +// The godoc documentation for this packages isn't very good; you +// should look at the source file nslcd_h.go. +package nslcd_proto diff --git a/nslcd_proto/io.go b/nslcd_proto/io.go new file mode 100644 index 0000000..fa40be3 --- /dev/null +++ b/nslcd_proto/io.go @@ -0,0 +1,176 @@ +// Copyright (C) 2015 Luke Shumaker +// +// 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_proto + +import ( + "encoding/binary" + "fmt" + "io" + "net" + "reflect" + "syscall" +) + +type NslcdError string + +func (o NslcdError) Error() string { + return string(o) +} + +type nslcdObject interface { + nslcdWrite(fd io.Writer) +} + +type nslcdObjectPtr interface { + nslcdRead(fd io.Reader) +} + +// Write an object to a stream. In the event of an error, this +// function may panic! Handle it! +func Write(fd io.Writer, data interface{}) { + switch data := data.(type) { + // basic data types + case nslcdObject: + data.nslcdWrite(fd) + case []byte: + if len(data) > 0 { + _, err := fd.Write(data) + if err != nil { + panic(err) + } + } + case int32: + err := binary.Write(fd, binary.BigEndian, data) + if err != nil { + panic(err) + } + // composite datatypes + case string: + Write(fd, int32(len(data))) + Write(fd, []byte(data)) + case []string: + Write(fd, int32(len(data))) + for _, item := range data { + Write(fd, item) + } + case net.IP: + var af int32 = -1 + switch len(data) { + case net.IPv4len: + af = syscall.AF_INET + case net.IPv6len: + af = syscall.AF_INET6 + } + var bytes []byte + if af < 0 { + bytes = make([]byte, 0) + } else { + bytes = data + } + Write(fd, af) + Write(fd, int32(len(bytes))) + Write(fd, bytes) + case []net.IP: + Write(fd, int32(len(data))) + for _, item := range data { + Write(fd, item) + } + default: + v := reflect.ValueOf(data) + switch v.Kind() { + case reflect.Struct: + for i, n := 0, v.NumField(); i < n; i++ { + Write(fd, v.Field(i).Interface()) + } + default: + panic(fmt.Sprintf("Invalid structure to write NSLCD protocol data from: %T ( %#v )", data, data)) + } + } +} + +// Read an object from a stream. In the event of an error, this +// function may panic! Handle it! +func Read(fd io.Reader, data interface{}) { + switch data := data.(type) { + // basic data types + case nslcdObjectPtr: + data.nslcdRead(fd) + case *[]byte: + if len(*data) > 0 { + _, err := io.ReadFull(fd, *data) + if err != nil { + panic(err) + } + } + case *int32: + err := binary.Read(fd, binary.BigEndian, data) + if err != nil { + panic(err) + } + // composite datatypes + case *string: + var len int32 + Read(fd, &len) + buf := make([]byte, len) // BUG(lukeshu): Read: `string` length needs sanity checked + Read(fd, &buf) + *data = string(buf) + case *[]string: + var num int32 + Read(fd, &num) + *data = make([]string, num) // BUG(lukeshu): Read: `[]string` length needs sanity checked + for i := 0; i < int(num); i++ { + Read(fd, &((*data)[i])) + } + case *net.IP: + var af int32 + Read(fd, &af) + var _len int32 + switch af { + case syscall.AF_INET: + _len = net.IPv4len + case syscall.AF_INET6: + _len = net.IPv6len + default: + panic(NslcdError(fmt.Sprintf("incorrect address family specified: %d", af))) + } + var len int32 + Read(fd, &len) + if len != _len { + panic(NslcdError(fmt.Sprintf("address length incorrect: %d", len))) + } + buf := make([]byte, len) + Read(fd, &buf) + *data = buf + case *[]net.IP: + var num int32 + Read(fd, &num) + *data = make([]net.IP, num) // BUG(lukeshu): Read: `[]net.IP` length needs sanity checked + for i := 0; i < int(num); i++ { + Read(fd, &((*data)[i])) + } + default: + p := reflect.ValueOf(data) + v := reflect.Indirect(p) + if p == v || v.Kind() != reflect.Struct { + panic(fmt.Sprintf("The argument to nslcd_proto.Read() must be a pointer: %T ( %#v )", data, data)) + } + for i, n := 0, v.NumField(); i < n; i++ { + Read(fd, v.Field(i).Addr().Interface()) + } + } +} diff --git a/nslcd_proto/nslcd_h.go b/nslcd_proto/nslcd_h.go new file mode 100644 index 0000000..cb210cd --- /dev/null +++ b/nslcd_proto/nslcd_h.go @@ -0,0 +1,454 @@ +// This file is based heavily on nslcd.h from nss-pam-ldapd +// Copyright (C) 2015 Luke Shumaker +/* + nslcd.h - file describing client/server protocol + + Copyright (C) 2006 West Consulting + Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012, 2013 Arthur de Jong + + 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_proto + +import ( + "fmt" + "io" + "net" +) + +/* + The protocol used between the nslcd client and server is a simple binary + protocol. It is request/response based where the client initiates a + connection, does a single request and closes the connection again. Any + mangled or not understood messages will be silently ignored by the server. + + A request looks like: + INT32 NSLCD_VERSION + INT32 NSLCD_ACTION_* + [request parameters if any] + A response looks like: + INT32 NSLCD_VERSION + INT32 NSLCD_ACTION_* (the original request type) + [result(s)] + INT32 NSLCD_RESULT_END + A single result entry looks like: + NSLCD_RESULT_BEGIN int32 + [result value(s)] + If a response would return multiple values (e.g. for NSLCD_ACTION_*_ALL + functions) each return value will be preceded by a NSLCD_RESULT_BEGIN + value. After the last returned result the server sends + NSLCD_RESULT_END. If some error occurs (e.g. LDAP server unavailable, + error in the request, etc) the server terminates the connection to signal + an error condition (breaking the protocol). + + These are the available basic data types: + INT32 - 32-bit integer value + TYPE - a typed field that is transferred using sizeof() + STRING - a string length (32bit) followed by the string value (not + null-terminted) the string itself is assumed to be UTF-8 + STRINGLIST - a 32-bit number noting the number of strings followed by + the strings one at a time + + Furthermore the ADDRESS compound data type is defined as: + INT32 type of address: e.g. AF_INET or AF_INET6 + INT32 lenght of address + RAW the address itself + With the ADDRESSLIST using the same construct as with STRINGLIST. + + The protocol uses network byte order for all types. +*/ +// These basic data types are implemented in `io.go` + +/* The current version of the protocol. This protocol should only be + updated with major backwards-incompatible changes. */ +const NSLCD_VERSION int32 = 0x00000002 + +/* Get a NSLCD configuration option. There is one request parameter: */ +type Request_Config_Get struct { + Key int32 /* NSLCD_CONFIG_* */ +} +/* the result value is: */ +type Config struct { + Value string /* interpretation depending on request */ +} +const NSLCD_ACTION_CONFIG_GET int32 = 0x00010001 + +const ( + /* return the message, if any, that is presented to the user when password + modification through PAM is prohibited */ + NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE int32 = 1 +) + +/* Email alias (/etc/aliases) NSS requests. The result values for a + single entry are: */ +type Alias struct { + Name string + Recipients []string +} +const NSLCD_ACTION_ALIAS_BYNAME int32 = 0x00020001; type Request_Alias_ByName struct { Name string } +const NSLCD_ACTION_ALIAS_ALL int32 = 0x00020008; type Request_Alias_All struct {} + +/* Ethernet address/name mapping NSS requests. The result values for a + single entry are: */ +type Ether struct { + Name string + Address [6]byte +} +const NSLCD_ACTION_ETHER_BYNAME int32 = 0x00030001; type Request_Ether_ByName struct { Name string } +const NSLCD_ACTION_ETHER_BYETHER int32 = 0x00030002; type Request_Ether_ByEther struct { Ether [6]byte } +const NSLCD_ACTION_ETHER_ALL int32 = 0x00030008; type Request_Ether_All struct {} + +/* Group and group membership related NSS requests. The result values + for a single entry are: */ +type Group struct { + Name string + PwHash string + ID int32 + Members []string +} +/* (note that the BYMEMER call returns an emtpy members list) */ +const NSLCD_ACTION_GROUP_BYNAME int32 = 0x00040001; type Request_Group_ByName struct { Name string } +const NSLCD_ACTION_GROUP_BYGID int32 = 0x00040002; type Request_Group_ByGid struct { Gid int32 } +const NSLCD_ACTION_GROUP_BYMEMBER int32 = 0x00040006; type Request_Group_ByMember struct { Member string } +const NSLCD_ACTION_GROUP_ALL int32 = 0x00040008; type Request_Group_All struct {} + +/* Hostname (/etc/hosts) lookup NSS requests. The result values + for an entry are: */ +type Host struct { + Name string + Aliases []string + Addresses []net.IP +} +const NSLCD_ACTION_HOST_BYNAME int32 = 0x00050001; type Request_Host_ByName struct { Name string } +const NSLCD_ACTION_HOST_BYADDR int32 = 0x00050002; type Request_Host_ByAddr struct { Addr net.IP } +const NSLCD_ACTION_HOST_ALL int32 = 0x00050008; type Request_Host_All struct {} + +/* Netgroup NSS result entries contain a number of parts. A result entry + starts with: + STRING netgroup name + followed by zero or more references to other netgroups or netgroup + triples. A reference to another netgroup looks like: + INT32 NSLCD_NETGROUP_TYPE_NETGROUP + STRING other netgroup name + A a netgroup triple looks like: + INT32 NSLCD_NETGROUP_TYPE_TRIPLE + STRING host + STRING user + STRING domain + A netgroup result entry is terminated by: + INT32 NSLCD_NETGROUP_TYPE_END + */ +type Netgroup_Netgroup struct { + Name string +} +type Netgroup_Triple struct { + Host string + User string + Domain string +} +type Netgroup_PartList []interface{} +func (data Netgroup_PartList) nslcdWrite(fd io.Writer) { + for _, part := range data { + var t int32 = -1 + switch part.(type) { + case Netgroup_Netgroup: + t = NSLCD_NETGROUP_TYPE_NETGROUP + case Netgroup_Triple: + t = NSLCD_NETGROUP_TYPE_TRIPLE + } + if t < 0 { + panic("unrecognized netgroup type") + } + Write(fd, t) + Write(fd, part) + } + Write(fd, NSLCD_NETGROUP_TYPE_END) +} +func (data *Netgroup_PartList) nslcdRead(fd io.Reader) { + *data = make([]interface{}, 0) + for { + var t int32 + var v interface{} + Read(fd, &t) + switch t { + case NSLCD_NETGROUP_TYPE_NETGROUP: + v = Netgroup_Netgroup{} + case NSLCD_NETGROUP_TYPE_TRIPLE: + v = Netgroup_Triple{} + case NSLCD_NETGROUP_TYPE_END: + return + default: + panic(NslcdError(fmt.Sprintf("unrecognized netgroup type: %#08x", t))) + } + Read(fd, &v) + *data = append(*data, v) + } +} +var _ nslcdObject = Netgroup_PartList{} +var _ nslcdObjectPtr = &Netgroup_PartList{} +type Netgroup struct { + Name string + Parts Netgroup_PartList +} +const NSLCD_ACTION_NETGROUP_BYNAME int32 = 0x00060001; type Request_Netgroup_ByName struct { Name string } +const NSLCD_ACTION_NETGROUP_ALL int32 = 0x00060008; type Request_Netgroup_All struct {} +const ( + NSLCD_NETGROUP_TYPE_NETGROUP int32 = 1 + NSLCD_NETGROUP_TYPE_TRIPLE int32 = 2 + NSLCD_NETGROUP_TYPE_END int32 = 3 +) + +/* Network name (/etc/networks) NSS requests. Result values for a single + entry are: */ +type Network struct { + Name string + Aliases []string + Addresses []net.IP +} +const NSLCD_ACTION_NETWORK_BYNAME int32 = 0x00070001; type Request_Network_ByName struct { Name string } +const NSLCD_ACTION_NETWORK_BYADDR int32 = 0x00070002; type Request_Network_ByAddr struct { Addr net.IP } +const NSLCD_ACTION_NETWORK_ALL int32 = 0x00070008; type Request_Network_All struct {} + +/* User account (/etc/passwd) NSS requests. Result values are: */ +type Passwd struct { + Name string + PwHash string + UID int32 + GID int32 + GECOS string + HomeDir string + Shell string +} +const NSLCD_ACTION_PASSWD_BYNAME int32 = 0x00080001; type Request_Passwd_ByName struct { Name string } +const NSLCD_ACTION_PASSWD_BYUID int32 = 0x00080002; type Request_Passwd_ByUID struct { UID int32 } +const NSLCD_ACTION_PASSWD_ALL int32 = 0x00080008; type Request_Passwd_All struct {} + +/* Protocol information requests. Result values are: */ +type Protocol struct { + Name string + Aliases []string + Number int32 +} +const NSLCD_ACTION_PROTOCOL_BYNAME int32 = 0x00090001; type Request_Protocol_ByName struct { Name string } +const NSLCD_ACTION_PROTOCOL_BYNUMBER int32 = 0x00090002; type Request_Protocol_ByNumber struct { Number int32 } +const NSLCD_ACTION_PROTOCOL_ALL int32 = 0x00090008; type Request_Protocol_All struct {} + +/* RPC information requests. Result values are: */ +type RPC struct { + Name string + Aliases []string + Number int32 +} +const NSLCD_ACTION_RPC_BYNAME int32 = 0x000a0001; type Request_RPC_ByName struct { Name string } +const NSLCD_ACTION_RPC_BYNUMBER int32 = 0x000a0002; type Request_RPC_ByNumber struct { Number int32 } +const NSLCD_ACTION_RPC_ALL int32 = 0x000a0008; type Request_RPC_All struct {} + +/* Service (/etc/services) information requests. The BYNAME and BYNUMBER + requests contain an extra protocol string in the request which, if not + blank, will filter the services by this protocol. Result values are: */ +type Service struct { + Name string + Aliases []string + PortNumber int32 + Protocol string +} +const NSLCD_ACTION_SERVICE_BYNAME int32 = 0x000b0001; type Request_Service_ByName struct { Name string } +const NSLCD_ACTION_SERVICE_BYNUMBER int32 = 0x000b0002; type Request_Service_ByNumber struct { Number int32 } +const NSLCD_ACTION_SERVICE_ALL int32 = 0x000b0008; type Request_Service_All struct {} + +/* Extended user account (/etc/shadow) information requests. Result + values for a single entry are: */ +type Shadow struct { + // It is my understanding that an empty value for an INT32 + // field is expressed with a negative number. -- lukeshu + Name string + PwHash string + LastChangeDate int32 + MinDays int32 + MaxDays int32 + WarnDays int32 + InactDays int32 + ExpireDate int32 + Flag int32 +} +const NSLCD_ACTION_SHADOW_BYNAME int32 = 0x000c0001; type Request_Shadow_ByName struct { Name string } +const NSLCD_ACTION_SHADOW_ALL int32 = 0x000c0008; type Request_Shadow_All struct {} + +/* PAM-related requests. The request parameters for all these requests + begin with: */ +type PAM_Base struct { + UserName string + ServiceName string + RUser string + RHost string + TTY string +} +/* If the user is not known in LDAP no result may be returned (immediately + return NSLCD_RESULT_END instead of a PAM error code). */ + +/* PAM authentication check request. The extra request values are: */ +type Request_PAM_Authentication struct { + PAM_Base + Password string +} +/* and the result value consists of: */ +type PAM_Authentication struct { + AuthenticationResult int32 + UserName string + AuthorizationResult int32 + AuthorizationError string +} +/* If the username is empty in this request an attempt is made to + authenticate as the administrator (set using rootpwmoddn). + Some authorisation checks are already done during authentication so the + response also includes authorisation information. */ +const NSLCD_ACTION_PAM_AUTHENTICATION int32 = 0x000d0001 + +/* PAM authorisation check request. The result value consists of: */ +type PAM_Authorization struct { + Result int32 + Error string +} +/* The authentication check may have already returned some authorisation + information. The authorisation error message, if supplied, will be used + by the PAM module instead of a message that is generated by the PAM + module itself. */ +const NSLCD_ACTION_PAM_AUTHORIZATION int32 = 0x000d0002; type Request_PAM_Authorization PAM_Base + +/* PAM session open request. The result value consists of: */ +type PAM_SessionOpen struct { + SessionID string +} +/* This session id may be used to close this session with. */ +const NSLCD_ACTION_PAM_SESSIONOPEN int32 = 0x000d0003; type Request_PAM_SessionOpen PAM_Base + +/* PAM session close request. This request has the following + extra request value: */ +type Request_PAM_SessionClose struct { + PAM_Base + SessionID string +} +/* and this calls only returns an empty response value. */ +type PAM_SessionClose struct {} +const NSLCD_ACTION_PAM_SESSIONCLOSE int32 = 0x000d0004 + +/* PAM password modification request. This requests has the following extra + request values: */ +type Request_PAM_PwMod struct { + PAM_Base + AsRoot int32 /* 0=oldpasswd is user passwd, 1=oldpasswd is root passwd */ + OldPassword string + NewPassword string +} +/* and returns the result values: */ +type PAM_PwMod struct { + Result int32 + Error string +} +const NSLCD_ACTION_PAM_PWMOD int32 = 0x000d0005 + +/* User information change request. This request allows one to change + their full name and other information. The request parameters for this + request are: + STRING user name + INT32 asroot: 0=passwd is user passwd, 1=passwd is root passwd + STRING password + followed by one or more of the below, terminated by NSLCD_USERMOD_END + INT32 NSLCD_USERMOD_* + STRING new value + the response consists of one or more of the entries below, terminated + by NSLCD_USERMOD_END: + INT32 NSLCD_USERMOD_* + STRING response + (if the response is blank, the change went OK, otherwise the string + contains an error message) + */ +type UserMod_Item struct { + Key int32 + Value string +} +type UserMod_ItemList []UserMod_Item +func (data UserMod_ItemList) nslcdWrite(fd io.Writer) { + for _, item := range data { + Write(fd, item) + } + Write(fd, NSLCD_USERMOD_END) +} +func (data *UserMod_ItemList) nslcdRead(fd io.Reader) { + *data = make([]UserMod_Item, 0) + for { + var t int32 + Read(fd, &t) + if t == NSLCD_USERMOD_END { + return + } + var v UserMod_Item + Read(fd, &v) + *data = append(*data, v) + } +} +var _ nslcdObject = UserMod_ItemList{} +var _ nslcdObjectPtr = &UserMod_ItemList{} +type Request_UserMod struct { + UserName string + AsRoot int32 + Password string + Items UserMod_ItemList +} +type UserMod struct { + Items []UserMod_Item +} +const NSLCD_ACTION_USERMOD int32 = 0x000e0001 + +/* These are the possible values for the NSLCD_ACTION_USERMOD operation + above. */ +const ( + NSLCD_USERMOD_END int32 = 0 /* end of change values */ + NSLCD_USERMOD_RESULT int32 = 1 /* global result value */ + NSLCD_USERMOD_FULLNAME int32 = 2 /* full name */ + NSLCD_USERMOD_ROOMNUMBER int32 = 3 /* room number */ + NSLCD_USERMOD_WORKPHONE int32 = 4 /* office phone number */ + NSLCD_USERMOD_HOMEPHONE int32 = 5 /* home phone number */ + NSLCD_USERMOD_OTHER int32 = 6 /* other info */ + NSLCD_USERMOD_HOMEDIR int32 = 7 /* home directory */ + NSLCD_USERMOD_SHELL int32 = 8 /* login shell */ +) + +/* Request result codes. */ +const ( + NSLCD_RESULT_BEGIN int32 = 1 + NSLCD_RESULT_END int32 = 2 +) + +/* Partial list of PAM result codes. */ +const ( + NSLCD_PAM_SUCCESS int32 = 0 /* everything ok */ + NSLCD_PAM_PERM_DENIED int32 = 6 /* Permission denied */ + NSLCD_PAM_AUTH_ERR int32 = 7 /* Authc failure */ + NSLCD_PAM_CRED_INSUFFICIENT int32 = 8 /* Cannot access authc data */ + NSLCD_PAM_AUTHINFO_UNAVAIL int32 = 9 /* Cannot retrieve authc info */ + NSLCD_PAM_USER_UNKNOWN int32 = 10 /* User not known */ + NSLCD_PAM_MAXTRIES int32 = 11 /* Retry limit reached */ + NSLCD_PAM_NEW_AUTHTOK_REQD int32 = 12 /* Password expired */ + NSLCD_PAM_ACCT_EXPIRED int32 = 13 /* Account expired */ + NSLCD_PAM_SESSION_ERR int32 = 14 /* Cannot make/remove session record */ + NSLCD_PAM_AUTHTOK_ERR int32 = 20 /* Authentication token manipulation error */ + NSLCD_PAM_AUTHTOK_DISABLE_AGING int32 = 23 /* Password aging disabled */ + NSLCD_PAM_IGNORE int32 = 25 /* Ignore module */ + NSLCD_PAM_ABORT int32 = 26 /* Fatal error */ + NSLCD_PAM_AUTHTOK_EXPIRED int32 = 27 /* authentication token has expired */ +) diff --git a/nslcd_server/.gitignore b/nslcd_server/.gitignore new file mode 100644 index 0000000..ff46733 --- /dev/null +++ b/nslcd_server/.gitignore @@ -0,0 +1,3 @@ +/func_handlerequest.go +/interface_backend.go +/type_nilbackend.go diff --git a/nslcd_server/Makefile b/nslcd_server/Makefile new file mode 100644 index 0000000..f1ff20f --- /dev/null +++ b/nslcd_server/Makefile @@ -0,0 +1,37 @@ +# Copyright (C) 2015-2016 Luke Shumaker +# +# 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 + +files.src.gen += interface_backend.go +files.src.gen += func_handlerequest.go +files.src.gen += type_nilbackend.go + +files.generate: $(files.src.gen) +maintainer-clean: + rm -f -- $(files.src.gen) +.PHONY: files.generate maintainer-clean + +%.go: %.go.gen + ./$^ > $@ + +interface_backend.go: ../nslcd_proto/requests.txt +func_handlerequest.go: ../nslcd_proto/requests.txt +type_nilbackend.go: interface_backend.go + +../nslcd_proto/requests.txt: + $(MAKE) -C $(@D) $(@F) + +.DELETE_ON_ERROR: diff --git a/nslcd_server/doc.go b/nslcd_server/doc.go new file mode 100644 index 0000000..1cf7552 --- /dev/null +++ b/nslcd_server/doc.go @@ -0,0 +1,25 @@ +// Copyright (C) 2015-2016 Luke Shumaker +// +// 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 + +//go:generate make + +// Package nslcd_server is a framework for implementing an nslcd +// server. +// +// You write an implementation of the Backend interface, then pass +// that to the HandleRequest function for each connection. +package nslcd_server diff --git a/nslcd_server/func_handlerequest.go.gen b/nslcd_server/func_handlerequest.go.gen new file mode 100755 index 0000000..4c58ae0 --- /dev/null +++ b/nslcd_server/func_handlerequest.go.gen @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# -*- Mode: Go -*- +# Copyright (C) 2015 Luke Shumaker +# +# 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 + +requests=$1 +printf '//' +printf ' %q' "$0" "$@" +printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' +cat < 0 {' + echo ' _req.OldPassword = sensitive' + echo '}' + echo '_req.NewPassword = sensitive' + echo 'fmt.Fprintf(os.Stderr, "Request: %#v\n", _req)' + ;; + PAM_UserMod) + echo '_req := req' + echo '_req.Password = sensitive' + echo 'fmt.Fprintf(os.Stderr, "Request: %#v\n", _req)' + ;; + *) + echo 'fmt.Fprintf(os.Stderr, "Request: %#v\n", req)' + ;; + esac + ) + _ch := backend.${request}(cred, req) + go func() { + defer close(ch) + for obj := range _ch { + ch <- obj + } + }() +EOT +done < "$requests" +) + default: + close(ch) + panic(p.NslcdError(fmt.Sprintf("Unknown request action: %#08x", action))) + } + p.Write(out, p.NSLCD_VERSION) + p.Write(out, action) + + for result := range ch { + p.Write(out, p.NSLCD_RESULT_BEGIN) + p.Write(out, result) + } + p.Write(out, p.NSLCD_RESULT_END) +} +EOF diff --git a/nslcd_server/interface_backend.go.gen b/nslcd_server/interface_backend.go.gen new file mode 100755 index 0000000..94a0433 --- /dev/null +++ b/nslcd_server/interface_backend.go.gen @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Copyright (C) 2015 Luke Shumaker +# +# 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 + +requests=$1 +printf '//' +printf ' %q' "$0" "$@" +printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' +cat < +# +# 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 + +interface=$1 +printf '//' +printf ' %q' "$0" "$@" +printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' +cat < +// +// 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 +// +// 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) + }() + } + } +} diff --git a/proto/.gitignore b/proto/.gitignore deleted file mode 100644 index 9330212..0000000 --- a/proto/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/requests.txt diff --git a/proto/Makefile b/proto/Makefile deleted file mode 100644 index 2716cbc..0000000 --- a/proto/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) 2015-2016 Luke Shumaker -# -# 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 - -files.src.gen += requests.txt - -files.generate: $(files.src.gen) -maintainer-clean: - rm -f -- $(files.src.gen) -.PHONY: files.generate maintainer-clean - -requests.txt: nslcd_h.go Makefile - < $< grep -Eo '\btype Request_([^_ ]+)(_\S+)?' | sed 's/^type Request_//' > $@ diff --git a/proto/common.mk b/proto/common.mk deleted file mode 100644 index 1496356..0000000 --- a/proto/common.mk +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright © 2015-2016 Luke Shumaker -# This work is free. You can redistribute it and/or modify it under the -# terms of the Do What The Fuck You Want To Public License, Version 2, -# as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. - -all: build -.PHONY: all - -generate: $(addprefix $(srcdir)/,$(std.gen_files)) -.PHONY: generate - -configure: generate $(addprefix $(outdir)/,$(std.cfg_files)) -.PHONY: configure - -build: configure $(addprefix $(outdir)/,$(std.out_files)) -.PHONY: build - -install: build $(addprefix $(DESTDIR),$(std.sys_files)) -.PHONY: install - -maintainer-clean: private files=$(addprefix $(srcdir)/,$(std.gen_files) $(std.secondary_gen_files)) # un-generate -distclean : private files=$(addprefix $(outdir)/,$(std.cfg_files) $(std.secondary_cfg_files)) # un-configure -clean : private files=$(addprefix $(outdir)/,$(std.out_files) $(std.secondary_out_files)) # un-build -uninstall : private files=$(addprefix $(DESTDIR),$(std.sys_files) ) # un-install - -distclean: clean -maintainer-clean: distclean - -clean distclean maintainer-clean uninstall: - rm -f -- $(sort $(filter-out %/,$(files))) - rm -f -r -- $(sort $(filter %/,$(files))) - rmdir -p -- $(sort $(dir $(files))) 2>/dev/null || true -.PHONY: clean distclean maintainer-clean uninstall diff --git a/proto/doc.go b/proto/doc.go deleted file mode 100644 index 70929f3..0000000 --- a/proto/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2015 Luke Shumaker -// -// 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_proto implements the nslcd protocol of nss-pam-ldapd. -// -// The godoc documentation for this packages isn't very good; you -// should look at the source file nslcd_h.go. -package nslcd_proto diff --git a/proto/io.go b/proto/io.go deleted file mode 100644 index fa40be3..0000000 --- a/proto/io.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2015 Luke Shumaker -// -// 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_proto - -import ( - "encoding/binary" - "fmt" - "io" - "net" - "reflect" - "syscall" -) - -type NslcdError string - -func (o NslcdError) Error() string { - return string(o) -} - -type nslcdObject interface { - nslcdWrite(fd io.Writer) -} - -type nslcdObjectPtr interface { - nslcdRead(fd io.Reader) -} - -// Write an object to a stream. In the event of an error, this -// function may panic! Handle it! -func Write(fd io.Writer, data interface{}) { - switch data := data.(type) { - // basic data types - case nslcdObject: - data.nslcdWrite(fd) - case []byte: - if len(data) > 0 { - _, err := fd.Write(data) - if err != nil { - panic(err) - } - } - case int32: - err := binary.Write(fd, binary.BigEndian, data) - if err != nil { - panic(err) - } - // composite datatypes - case string: - Write(fd, int32(len(data))) - Write(fd, []byte(data)) - case []string: - Write(fd, int32(len(data))) - for _, item := range data { - Write(fd, item) - } - case net.IP: - var af int32 = -1 - switch len(data) { - case net.IPv4len: - af = syscall.AF_INET - case net.IPv6len: - af = syscall.AF_INET6 - } - var bytes []byte - if af < 0 { - bytes = make([]byte, 0) - } else { - bytes = data - } - Write(fd, af) - Write(fd, int32(len(bytes))) - Write(fd, bytes) - case []net.IP: - Write(fd, int32(len(data))) - for _, item := range data { - Write(fd, item) - } - default: - v := reflect.ValueOf(data) - switch v.Kind() { - case reflect.Struct: - for i, n := 0, v.NumField(); i < n; i++ { - Write(fd, v.Field(i).Interface()) - } - default: - panic(fmt.Sprintf("Invalid structure to write NSLCD protocol data from: %T ( %#v )", data, data)) - } - } -} - -// Read an object from a stream. In the event of an error, this -// function may panic! Handle it! -func Read(fd io.Reader, data interface{}) { - switch data := data.(type) { - // basic data types - case nslcdObjectPtr: - data.nslcdRead(fd) - case *[]byte: - if len(*data) > 0 { - _, err := io.ReadFull(fd, *data) - if err != nil { - panic(err) - } - } - case *int32: - err := binary.Read(fd, binary.BigEndian, data) - if err != nil { - panic(err) - } - // composite datatypes - case *string: - var len int32 - Read(fd, &len) - buf := make([]byte, len) // BUG(lukeshu): Read: `string` length needs sanity checked - Read(fd, &buf) - *data = string(buf) - case *[]string: - var num int32 - Read(fd, &num) - *data = make([]string, num) // BUG(lukeshu): Read: `[]string` length needs sanity checked - for i := 0; i < int(num); i++ { - Read(fd, &((*data)[i])) - } - case *net.IP: - var af int32 - Read(fd, &af) - var _len int32 - switch af { - case syscall.AF_INET: - _len = net.IPv4len - case syscall.AF_INET6: - _len = net.IPv6len - default: - panic(NslcdError(fmt.Sprintf("incorrect address family specified: %d", af))) - } - var len int32 - Read(fd, &len) - if len != _len { - panic(NslcdError(fmt.Sprintf("address length incorrect: %d", len))) - } - buf := make([]byte, len) - Read(fd, &buf) - *data = buf - case *[]net.IP: - var num int32 - Read(fd, &num) - *data = make([]net.IP, num) // BUG(lukeshu): Read: `[]net.IP` length needs sanity checked - for i := 0; i < int(num); i++ { - Read(fd, &((*data)[i])) - } - default: - p := reflect.ValueOf(data) - v := reflect.Indirect(p) - if p == v || v.Kind() != reflect.Struct { - panic(fmt.Sprintf("The argument to nslcd_proto.Read() must be a pointer: %T ( %#v )", data, data)) - } - for i, n := 0, v.NumField(); i < n; i++ { - Read(fd, v.Field(i).Addr().Interface()) - } - } -} diff --git a/proto/nslcd_h.go b/proto/nslcd_h.go deleted file mode 100644 index cb210cd..0000000 --- a/proto/nslcd_h.go +++ /dev/null @@ -1,454 +0,0 @@ -// This file is based heavily on nslcd.h from nss-pam-ldapd -// Copyright (C) 2015 Luke Shumaker -/* - nslcd.h - file describing client/server protocol - - Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012, 2013 Arthur de Jong - - 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_proto - -import ( - "fmt" - "io" - "net" -) - -/* - The protocol used between the nslcd client and server is a simple binary - protocol. It is request/response based where the client initiates a - connection, does a single request and closes the connection again. Any - mangled or not understood messages will be silently ignored by the server. - - A request looks like: - INT32 NSLCD_VERSION - INT32 NSLCD_ACTION_* - [request parameters if any] - A response looks like: - INT32 NSLCD_VERSION - INT32 NSLCD_ACTION_* (the original request type) - [result(s)] - INT32 NSLCD_RESULT_END - A single result entry looks like: - NSLCD_RESULT_BEGIN int32 - [result value(s)] - If a response would return multiple values (e.g. for NSLCD_ACTION_*_ALL - functions) each return value will be preceded by a NSLCD_RESULT_BEGIN - value. After the last returned result the server sends - NSLCD_RESULT_END. If some error occurs (e.g. LDAP server unavailable, - error in the request, etc) the server terminates the connection to signal - an error condition (breaking the protocol). - - These are the available basic data types: - INT32 - 32-bit integer value - TYPE - a typed field that is transferred using sizeof() - STRING - a string length (32bit) followed by the string value (not - null-terminted) the string itself is assumed to be UTF-8 - STRINGLIST - a 32-bit number noting the number of strings followed by - the strings one at a time - - Furthermore the ADDRESS compound data type is defined as: - INT32 type of address: e.g. AF_INET or AF_INET6 - INT32 lenght of address - RAW the address itself - With the ADDRESSLIST using the same construct as with STRINGLIST. - - The protocol uses network byte order for all types. -*/ -// These basic data types are implemented in `io.go` - -/* The current version of the protocol. This protocol should only be - updated with major backwards-incompatible changes. */ -const NSLCD_VERSION int32 = 0x00000002 - -/* Get a NSLCD configuration option. There is one request parameter: */ -type Request_Config_Get struct { - Key int32 /* NSLCD_CONFIG_* */ -} -/* the result value is: */ -type Config struct { - Value string /* interpretation depending on request */ -} -const NSLCD_ACTION_CONFIG_GET int32 = 0x00010001 - -const ( - /* return the message, if any, that is presented to the user when password - modification through PAM is prohibited */ - NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE int32 = 1 -) - -/* Email alias (/etc/aliases) NSS requests. The result values for a - single entry are: */ -type Alias struct { - Name string - Recipients []string -} -const NSLCD_ACTION_ALIAS_BYNAME int32 = 0x00020001; type Request_Alias_ByName struct { Name string } -const NSLCD_ACTION_ALIAS_ALL int32 = 0x00020008; type Request_Alias_All struct {} - -/* Ethernet address/name mapping NSS requests. The result values for a - single entry are: */ -type Ether struct { - Name string - Address [6]byte -} -const NSLCD_ACTION_ETHER_BYNAME int32 = 0x00030001; type Request_Ether_ByName struct { Name string } -const NSLCD_ACTION_ETHER_BYETHER int32 = 0x00030002; type Request_Ether_ByEther struct { Ether [6]byte } -const NSLCD_ACTION_ETHER_ALL int32 = 0x00030008; type Request_Ether_All struct {} - -/* Group and group membership related NSS requests. The result values - for a single entry are: */ -type Group struct { - Name string - PwHash string - ID int32 - Members []string -} -/* (note that the BYMEMER call returns an emtpy members list) */ -const NSLCD_ACTION_GROUP_BYNAME int32 = 0x00040001; type Request_Group_ByName struct { Name string } -const NSLCD_ACTION_GROUP_BYGID int32 = 0x00040002; type Request_Group_ByGid struct { Gid int32 } -const NSLCD_ACTION_GROUP_BYMEMBER int32 = 0x00040006; type Request_Group_ByMember struct { Member string } -const NSLCD_ACTION_GROUP_ALL int32 = 0x00040008; type Request_Group_All struct {} - -/* Hostname (/etc/hosts) lookup NSS requests. The result values - for an entry are: */ -type Host struct { - Name string - Aliases []string - Addresses []net.IP -} -const NSLCD_ACTION_HOST_BYNAME int32 = 0x00050001; type Request_Host_ByName struct { Name string } -const NSLCD_ACTION_HOST_BYADDR int32 = 0x00050002; type Request_Host_ByAddr struct { Addr net.IP } -const NSLCD_ACTION_HOST_ALL int32 = 0x00050008; type Request_Host_All struct {} - -/* Netgroup NSS result entries contain a number of parts. A result entry - starts with: - STRING netgroup name - followed by zero or more references to other netgroups or netgroup - triples. A reference to another netgroup looks like: - INT32 NSLCD_NETGROUP_TYPE_NETGROUP - STRING other netgroup name - A a netgroup triple looks like: - INT32 NSLCD_NETGROUP_TYPE_TRIPLE - STRING host - STRING user - STRING domain - A netgroup result entry is terminated by: - INT32 NSLCD_NETGROUP_TYPE_END - */ -type Netgroup_Netgroup struct { - Name string -} -type Netgroup_Triple struct { - Host string - User string - Domain string -} -type Netgroup_PartList []interface{} -func (data Netgroup_PartList) nslcdWrite(fd io.Writer) { - for _, part := range data { - var t int32 = -1 - switch part.(type) { - case Netgroup_Netgroup: - t = NSLCD_NETGROUP_TYPE_NETGROUP - case Netgroup_Triple: - t = NSLCD_NETGROUP_TYPE_TRIPLE - } - if t < 0 { - panic("unrecognized netgroup type") - } - Write(fd, t) - Write(fd, part) - } - Write(fd, NSLCD_NETGROUP_TYPE_END) -} -func (data *Netgroup_PartList) nslcdRead(fd io.Reader) { - *data = make([]interface{}, 0) - for { - var t int32 - var v interface{} - Read(fd, &t) - switch t { - case NSLCD_NETGROUP_TYPE_NETGROUP: - v = Netgroup_Netgroup{} - case NSLCD_NETGROUP_TYPE_TRIPLE: - v = Netgroup_Triple{} - case NSLCD_NETGROUP_TYPE_END: - return - default: - panic(NslcdError(fmt.Sprintf("unrecognized netgroup type: %#08x", t))) - } - Read(fd, &v) - *data = append(*data, v) - } -} -var _ nslcdObject = Netgroup_PartList{} -var _ nslcdObjectPtr = &Netgroup_PartList{} -type Netgroup struct { - Name string - Parts Netgroup_PartList -} -const NSLCD_ACTION_NETGROUP_BYNAME int32 = 0x00060001; type Request_Netgroup_ByName struct { Name string } -const NSLCD_ACTION_NETGROUP_ALL int32 = 0x00060008; type Request_Netgroup_All struct {} -const ( - NSLCD_NETGROUP_TYPE_NETGROUP int32 = 1 - NSLCD_NETGROUP_TYPE_TRIPLE int32 = 2 - NSLCD_NETGROUP_TYPE_END int32 = 3 -) - -/* Network name (/etc/networks) NSS requests. Result values for a single - entry are: */ -type Network struct { - Name string - Aliases []string - Addresses []net.IP -} -const NSLCD_ACTION_NETWORK_BYNAME int32 = 0x00070001; type Request_Network_ByName struct { Name string } -const NSLCD_ACTION_NETWORK_BYADDR int32 = 0x00070002; type Request_Network_ByAddr struct { Addr net.IP } -const NSLCD_ACTION_NETWORK_ALL int32 = 0x00070008; type Request_Network_All struct {} - -/* User account (/etc/passwd) NSS requests. Result values are: */ -type Passwd struct { - Name string - PwHash string - UID int32 - GID int32 - GECOS string - HomeDir string - Shell string -} -const NSLCD_ACTION_PASSWD_BYNAME int32 = 0x00080001; type Request_Passwd_ByName struct { Name string } -const NSLCD_ACTION_PASSWD_BYUID int32 = 0x00080002; type Request_Passwd_ByUID struct { UID int32 } -const NSLCD_ACTION_PASSWD_ALL int32 = 0x00080008; type Request_Passwd_All struct {} - -/* Protocol information requests. Result values are: */ -type Protocol struct { - Name string - Aliases []string - Number int32 -} -const NSLCD_ACTION_PROTOCOL_BYNAME int32 = 0x00090001; type Request_Protocol_ByName struct { Name string } -const NSLCD_ACTION_PROTOCOL_BYNUMBER int32 = 0x00090002; type Request_Protocol_ByNumber struct { Number int32 } -const NSLCD_ACTION_PROTOCOL_ALL int32 = 0x00090008; type Request_Protocol_All struct {} - -/* RPC information requests. Result values are: */ -type RPC struct { - Name string - Aliases []string - Number int32 -} -const NSLCD_ACTION_RPC_BYNAME int32 = 0x000a0001; type Request_RPC_ByName struct { Name string } -const NSLCD_ACTION_RPC_BYNUMBER int32 = 0x000a0002; type Request_RPC_ByNumber struct { Number int32 } -const NSLCD_ACTION_RPC_ALL int32 = 0x000a0008; type Request_RPC_All struct {} - -/* Service (/etc/services) information requests. The BYNAME and BYNUMBER - requests contain an extra protocol string in the request which, if not - blank, will filter the services by this protocol. Result values are: */ -type Service struct { - Name string - Aliases []string - PortNumber int32 - Protocol string -} -const NSLCD_ACTION_SERVICE_BYNAME int32 = 0x000b0001; type Request_Service_ByName struct { Name string } -const NSLCD_ACTION_SERVICE_BYNUMBER int32 = 0x000b0002; type Request_Service_ByNumber struct { Number int32 } -const NSLCD_ACTION_SERVICE_ALL int32 = 0x000b0008; type Request_Service_All struct {} - -/* Extended user account (/etc/shadow) information requests. Result - values for a single entry are: */ -type Shadow struct { - // It is my understanding that an empty value for an INT32 - // field is expressed with a negative number. -- lukeshu - Name string - PwHash string - LastChangeDate int32 - MinDays int32 - MaxDays int32 - WarnDays int32 - InactDays int32 - ExpireDate int32 - Flag int32 -} -const NSLCD_ACTION_SHADOW_BYNAME int32 = 0x000c0001; type Request_Shadow_ByName struct { Name string } -const NSLCD_ACTION_SHADOW_ALL int32 = 0x000c0008; type Request_Shadow_All struct {} - -/* PAM-related requests. The request parameters for all these requests - begin with: */ -type PAM_Base struct { - UserName string - ServiceName string - RUser string - RHost string - TTY string -} -/* If the user is not known in LDAP no result may be returned (immediately - return NSLCD_RESULT_END instead of a PAM error code). */ - -/* PAM authentication check request. The extra request values are: */ -type Request_PAM_Authentication struct { - PAM_Base - Password string -} -/* and the result value consists of: */ -type PAM_Authentication struct { - AuthenticationResult int32 - UserName string - AuthorizationResult int32 - AuthorizationError string -} -/* If the username is empty in this request an attempt is made to - authenticate as the administrator (set using rootpwmoddn). - Some authorisation checks are already done during authentication so the - response also includes authorisation information. */ -const NSLCD_ACTION_PAM_AUTHENTICATION int32 = 0x000d0001 - -/* PAM authorisation check request. The result value consists of: */ -type PAM_Authorization struct { - Result int32 - Error string -} -/* The authentication check may have already returned some authorisation - information. The authorisation error message, if supplied, will be used - by the PAM module instead of a message that is generated by the PAM - module itself. */ -const NSLCD_ACTION_PAM_AUTHORIZATION int32 = 0x000d0002; type Request_PAM_Authorization PAM_Base - -/* PAM session open request. The result value consists of: */ -type PAM_SessionOpen struct { - SessionID string -} -/* This session id may be used to close this session with. */ -const NSLCD_ACTION_PAM_SESSIONOPEN int32 = 0x000d0003; type Request_PAM_SessionOpen PAM_Base - -/* PAM session close request. This request has the following - extra request value: */ -type Request_PAM_SessionClose struct { - PAM_Base - SessionID string -} -/* and this calls only returns an empty response value. */ -type PAM_SessionClose struct {} -const NSLCD_ACTION_PAM_SESSIONCLOSE int32 = 0x000d0004 - -/* PAM password modification request. This requests has the following extra - request values: */ -type Request_PAM_PwMod struct { - PAM_Base - AsRoot int32 /* 0=oldpasswd is user passwd, 1=oldpasswd is root passwd */ - OldPassword string - NewPassword string -} -/* and returns the result values: */ -type PAM_PwMod struct { - Result int32 - Error string -} -const NSLCD_ACTION_PAM_PWMOD int32 = 0x000d0005 - -/* User information change request. This request allows one to change - their full name and other information. The request parameters for this - request are: - STRING user name - INT32 asroot: 0=passwd is user passwd, 1=passwd is root passwd - STRING password - followed by one or more of the below, terminated by NSLCD_USERMOD_END - INT32 NSLCD_USERMOD_* - STRING new value - the response consists of one or more of the entries below, terminated - by NSLCD_USERMOD_END: - INT32 NSLCD_USERMOD_* - STRING response - (if the response is blank, the change went OK, otherwise the string - contains an error message) - */ -type UserMod_Item struct { - Key int32 - Value string -} -type UserMod_ItemList []UserMod_Item -func (data UserMod_ItemList) nslcdWrite(fd io.Writer) { - for _, item := range data { - Write(fd, item) - } - Write(fd, NSLCD_USERMOD_END) -} -func (data *UserMod_ItemList) nslcdRead(fd io.Reader) { - *data = make([]UserMod_Item, 0) - for { - var t int32 - Read(fd, &t) - if t == NSLCD_USERMOD_END { - return - } - var v UserMod_Item - Read(fd, &v) - *data = append(*data, v) - } -} -var _ nslcdObject = UserMod_ItemList{} -var _ nslcdObjectPtr = &UserMod_ItemList{} -type Request_UserMod struct { - UserName string - AsRoot int32 - Password string - Items UserMod_ItemList -} -type UserMod struct { - Items []UserMod_Item -} -const NSLCD_ACTION_USERMOD int32 = 0x000e0001 - -/* These are the possible values for the NSLCD_ACTION_USERMOD operation - above. */ -const ( - NSLCD_USERMOD_END int32 = 0 /* end of change values */ - NSLCD_USERMOD_RESULT int32 = 1 /* global result value */ - NSLCD_USERMOD_FULLNAME int32 = 2 /* full name */ - NSLCD_USERMOD_ROOMNUMBER int32 = 3 /* room number */ - NSLCD_USERMOD_WORKPHONE int32 = 4 /* office phone number */ - NSLCD_USERMOD_HOMEPHONE int32 = 5 /* home phone number */ - NSLCD_USERMOD_OTHER int32 = 6 /* other info */ - NSLCD_USERMOD_HOMEDIR int32 = 7 /* home directory */ - NSLCD_USERMOD_SHELL int32 = 8 /* login shell */ -) - -/* Request result codes. */ -const ( - NSLCD_RESULT_BEGIN int32 = 1 - NSLCD_RESULT_END int32 = 2 -) - -/* Partial list of PAM result codes. */ -const ( - NSLCD_PAM_SUCCESS int32 = 0 /* everything ok */ - NSLCD_PAM_PERM_DENIED int32 = 6 /* Permission denied */ - NSLCD_PAM_AUTH_ERR int32 = 7 /* Authc failure */ - NSLCD_PAM_CRED_INSUFFICIENT int32 = 8 /* Cannot access authc data */ - NSLCD_PAM_AUTHINFO_UNAVAIL int32 = 9 /* Cannot retrieve authc info */ - NSLCD_PAM_USER_UNKNOWN int32 = 10 /* User not known */ - NSLCD_PAM_MAXTRIES int32 = 11 /* Retry limit reached */ - NSLCD_PAM_NEW_AUTHTOK_REQD int32 = 12 /* Password expired */ - NSLCD_PAM_ACCT_EXPIRED int32 = 13 /* Account expired */ - NSLCD_PAM_SESSION_ERR int32 = 14 /* Cannot make/remove session record */ - NSLCD_PAM_AUTHTOK_ERR int32 = 20 /* Authentication token manipulation error */ - NSLCD_PAM_AUTHTOK_DISABLE_AGING int32 = 23 /* Password aging disabled */ - NSLCD_PAM_IGNORE int32 = 25 /* Ignore module */ - NSLCD_PAM_ABORT int32 = 26 /* Fatal error */ - NSLCD_PAM_AUTHTOK_EXPIRED int32 = 27 /* authentication token has expired */ -) diff --git a/proto/server/.gitignore b/proto/server/.gitignore deleted file mode 100644 index ff46733..0000000 --- a/proto/server/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/func_handlerequest.go -/interface_backend.go -/type_nilbackend.go diff --git a/proto/server/Makefile b/proto/server/Makefile deleted file mode 100644 index 1bbfc58..0000000 --- a/proto/server/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2015-2016 Luke Shumaker -# -# 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 - -files.src.gen += interface_backend.go -files.src.gen += func_handlerequest.go -files.src.gen += type_nilbackend.go - -files.generate: $(files.src.gen) -maintainer-clean: - rm -f -- $(files.src.gen) -.PHONY: files.generate maintainer-clean - -%.go: %.go.sh - ./$^ > $@ - -interface_backend.go: ../requests.txt -func_handlerequest.go: ../requests.txt -type_nilbackend.go: interface_backend.go - -../requests.txt: - $(MAKE) -C $(@D) $(@F) - diff --git a/proto/server/doc.go b/proto/server/doc.go deleted file mode 100644 index 1cf7552..0000000 --- a/proto/server/doc.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2015-2016 Luke Shumaker -// -// 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 - -//go:generate make - -// Package nslcd_server is a framework for implementing an nslcd -// server. -// -// You write an implementation of the Backend interface, then pass -// that to the HandleRequest function for each connection. -package nslcd_server diff --git a/proto/server/func_handlerequest.go.sh b/proto/server/func_handlerequest.go.sh deleted file mode 100755 index ac61e76..0000000 --- a/proto/server/func_handlerequest.go.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env bash -# -*- Mode: Go -*- -# Copyright (C) 2015 Luke Shumaker -# -# 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 - -requests=$1 -printf '//' -printf ' %q' "$0" "$@" -printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' -cat < 0 {' - echo ' _req.OldPassword = sensitive' - echo '}' - echo '_req.NewPassword = sensitive' - echo 'fmt.Fprintf(os.Stderr, "Request: %#v\n", _req)' - ;; - PAM_UserMod) - echo '_req := req' - echo '_req.Password = sensitive' - echo 'fmt.Fprintf(os.Stderr, "Request: %#v\n", _req)' - ;; - *) - echo 'fmt.Fprintf(os.Stderr, "Request: %#v\n", req)' - ;; - esac - ) - _ch := backend.${request}(cred, req) - go func() { - defer close(ch) - for obj := range _ch { - ch <- obj - } - }() -EOT -done < "$requests" -) - default: - close(ch) - panic(p.NslcdError(fmt.Sprintf("Unknown request action: %#08x", action))) - } - p.Write(out, p.NSLCD_VERSION) - p.Write(out, action) - - for result := range ch { - p.Write(out, p.NSLCD_RESULT_BEGIN) - p.Write(out, result) - } - p.Write(out, p.NSLCD_RESULT_END) -} -EOF diff --git a/proto/server/interface_backend.go.sh b/proto/server/interface_backend.go.sh deleted file mode 100755 index 71745ba..0000000 --- a/proto/server/interface_backend.go.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# Copyright (C) 2015 Luke Shumaker -# -# 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 - -requests=$1 -printf '//' -printf ' %q' "$0" "$@" -printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' -cat < -# -# 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 - -interface=$1 -printf '//' -printf ' %q' "$0" "$@" -printf '\n// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n' -cat < -// -// 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" - sd "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.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.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.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.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/systemd/nslcd_systemd.go b/systemd/nslcd_systemd.go deleted file mode 100644 index c5c8c65..0000000 --- a/systemd/nslcd_systemd.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (C) 2015-2016 Luke Shumaker -// -// 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/proto/server" - sd "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.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.Log.Debug("Connection from unknown client") - } else { - sd.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.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.Log.Err(fmt.Sprintf("Could not initialize backend: %v", err)) - sd.Notify(0, false, "STOPPING=1", nil) - return lsb.EXIT_FAILURE - } - defer backend.Close() - - socket, err := get_socket() - if err != nil { - sd.Log.Err(fmt.Sprintf("%v", err)) - sd.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.Log.Notice(fmt.Sprintf("%v", err)) - } - if conn != nil { - sock <- conn.(*net.UnixConn) - } - } - }() - - var wg sync.WaitGroup - defer wg.Wait() - defer sd.Notify(0, false, "STOPPING=1", nil) - sd.Notify(0, false, "READY=1", nil) - for { - select { - case sig := <-sigs: - switch sig { - case syscall.SIGTERM: - sd.Log.Notice("Received SIGTERM, shutting down") - return lsb.EXIT_SUCCESS - case syscall.SIGHUP: - sd.Notify(0, false, "RELOADING=1", nil) - err := backend.Reload() - if err != nil { - sd.Log.Notice(fmt.Sprintf("Could not reload backend: %s", err.Error())) - return lsb.EXIT_NOTRUNNING - } - sd.Notify(0, false, "READY=1", nil) - } - case conn := <-sock: - wg.Add(1) - go func() { - defer lsb.Recover() - defer wg.Done() - handler(conn, backend) - }() - } - } -} -- cgit v1.2.3