summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2015-08-25 14:19:33 -0600
committerLuke Shumaker <lukeshu@sbcglobal.net>2015-08-25 14:19:33 -0600
commit75c89781ab3ed908307920e4acdeb86f275f2faa (patch)
treee9cf634a2d1990949b915bc17e6d48b8c3f4322a
initial commit
-rw-r--r--src/main.go2
-rw-r--r--src/nslcd-proto/.gitignore1
-rw-r--r--src/nslcd-proto/Makefile10
-rw-r--r--src/nslcd-proto/handle.go11
-rw-r--r--src/nslcd-proto/io.go141
-rw-r--r--src/nslcd-proto/nslcd.h307
-rw-r--r--src/nslcd-proto/structures.go249
-rw-r--r--src/nslcd-proto/util.go47
-rw-r--r--src/sd-daemon/listen_fds.go51
-rw-r--r--src/sd-daemon/logger/logger.go20
10 files changed, 839 insertions, 0 deletions
diff --git a/src/main.go b/src/main.go
new file mode 100644
index 0000000..9067cdf
--- /dev/null
+++ b/src/main.go
@@ -0,0 +1,2 @@
+//include "nslcd.h"
+import "C"
diff --git a/src/nslcd-proto/.gitignore b/src/nslcd-proto/.gitignore
new file mode 100644
index 0000000..75e7f93
--- /dev/null
+++ b/src/nslcd-proto/.gitignore
@@ -0,0 +1 @@
+/backend.go
diff --git a/src/nslcd-proto/Makefile b/src/nslcd-proto/Makefile
new file mode 100644
index 0000000..fce3d2f
--- /dev/null
+++ b/src/nslcd-proto/Makefile
@@ -0,0 +1,10 @@
+backend.go: structures.go Makefile
+ { \
+ echo 'package nslcd_proto' && \
+ echo 'type Backend interface {' && \
+ sed -rn 's/^type Request_([^_ ]+)(_\S+)?.*/\1\2(Request_\1\2) []\1/p' $< | grep -v PAM && \
+ sed -rn 's/^type Request_(PAM)(_\S+)?.*/\1\2(Request_\1\2) []\1\2/p' $< && \
+ echo '}' && \
+ :; } | gofmt > $@
+
+.DELETE_ON_ERROR:
diff --git a/src/nslcd-proto/handle.go b/src/nslcd-proto/handle.go
new file mode 100644
index 0000000..07f8d84
--- /dev/null
+++ b/src/nslcd-proto/handle.go
@@ -0,0 +1,11 @@
+package nslcd_proto
+
+import "io"
+
+// Initialize() error { func
+// e := c.SetReadDeadline(...)
+// e := c.SetWriteDeadline(...)
+// }
+
+func Handle(in io.Reader, out io.Writer) {
+
diff --git a/src/nslcd-proto/io.go b/src/nslcd-proto/io.go
new file mode 100644
index 0000000..9ed6fd5
--- /dev/null
+++ b/src/nslcd-proto/io.go
@@ -0,0 +1,141 @@
+package nslcd_proto
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "net"
+ "reflect"
+)
+
+//#include <sys/socket.h>
+import "C"
+
+func write(fd io.Writer, data interface{}) {
+ switch data := data.(type) {
+ // basic data types
+ case []byte:
+ _, err := fd.Write(data)
+ if err != nil {
+ panic(err)
+ }
+ case int32:
+ err := binary.Write(fd, binary.BigEndian, data)
+ if err != nil {
+ panic(err)
+ }
+ case NslcdObject:
+ data.NslcdWrite(fd)
+ // 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 = C.AF_INET
+ case net.IPv6len: af = C.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("invalid NSLCD protocol data")
+ }
+ }
+ panic("not reached")
+}
+
+func read(fd io.Reader, data interface{}) {
+ switch data := data.(type) {
+ // basic data types
+ case *[]byte:
+ _, err := fd.Read(*data)
+ if err != nil {
+ panic(err)
+ }
+ case *int32:
+ err := binary.Read(fd, binary.BigEndian, data)
+ if err != nil {
+ panic(err)
+ }
+ case NslcdObjectPtr:
+ data.NslcdRead(fd)
+ // composite datatypes
+ case *string:
+ var len int32
+ read(fd, &len)
+ buf := make([]byte, len)
+ read(fd, &buf)
+ *data = string(buf)
+ case *[]string:
+ var num int32
+ read(fd, &num)
+ *data = make([]string, num)
+ 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 C.AF_INET: _len = net.IPv4len;
+ case C.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)
+ for i := 0; i < int(num); i++ {
+ read(fd, &((*data)[i]))
+ }
+ // Entities
+ case Netgroup:
+ read(fd, &data.Name)
+ default:
+ v := reflect.ValueOf(data)
+ switch v.Kind() {
+ case reflect.Struct:
+ for i, n := 0, v.NumField(); i < n; i++ {
+ read(fd, v.Field(i).Interface())
+ }
+ default:
+ panic("invalid NSLCD protocol data")
+ }
+ }
+ panic("not reached")
+}
diff --git a/src/nslcd-proto/nslcd.h b/src/nslcd-proto/nslcd.h
new file mode 100644
index 0000000..4a73fbf
--- /dev/null
+++ b/src/nslcd-proto/nslcd.h
@@ -0,0 +1,307 @@
+/*
+ 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
+*/
+
+#ifndef _NSLCD_H
+#define _NSLCD_H 1
+
+/*
+ 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:
+ INT32 NSLCD_RESULT_BEGIN
+ [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.
+*/
+
+/* The current version of the protocol. This protocol should only be
+ updated with major backwards-incompatible changes. */
+#define NSLCD_VERSION 0x00000002
+
+/* Get a NSLCD configuration option. There is one request parameter:
+ INT32 NSLCD_CONFIG_*
+ the result value is:
+ STRING value, interpretation depending on request */
+#define NSLCD_ACTION_CONFIG_GET 0x00010001
+
+/* return the message, if any, that is presented to the user when password
+ modification through PAM is prohibited */
+#define NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE 1
+
+/* Email alias (/etc/aliases) NSS requests. The result values for a
+ single entry are:
+ STRING alias name
+ STRINGLIST alias rcpts */
+#define NSLCD_ACTION_ALIAS_BYNAME 0x00020001
+#define NSLCD_ACTION_ALIAS_ALL 0x00020008
+
+/* Ethernet address/name mapping NSS requests. The result values for a
+ single entry are:
+ STRING ether name
+ TYPE(uint8_t[6]) ether address */
+#define NSLCD_ACTION_ETHER_BYNAME 0x00030001
+#define NSLCD_ACTION_ETHER_BYETHER 0x00030002
+#define NSLCD_ACTION_ETHER_ALL 0x00030008
+
+/* Group and group membership related NSS requests. The result values
+ for a single entry are:
+ STRING group name
+ STRING group password
+ INT32 group id
+ STRINGLIST members (usernames) of the group
+ (note that the BYMEMER call returns an emtpy members list) */
+#define NSLCD_ACTION_GROUP_BYNAME 0x00040001
+#define NSLCD_ACTION_GROUP_BYGID 0x00040002
+#define NSLCD_ACTION_GROUP_BYMEMBER 0x00040006
+#define NSLCD_ACTION_GROUP_ALL 0x00040008
+
+/* Hostname (/etc/hosts) lookup NSS requests. The result values
+ for an entry are:
+ STRING host name
+ STRINGLIST host aliases
+ ADDRESSLIST host addresses */
+#define NSLCD_ACTION_HOST_BYNAME 0x00050001
+#define NSLCD_ACTION_HOST_BYADDR 0x00050002
+#define NSLCD_ACTION_HOST_ALL 0x00050008
+
+/* 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
+ */
+#define NSLCD_ACTION_NETGROUP_BYNAME 0x00060001
+#define NSLCD_ACTION_NETGROUP_ALL 0x00060008
+#define NSLCD_NETGROUP_TYPE_NETGROUP 1
+#define NSLCD_NETGROUP_TYPE_TRIPLE 2
+#define NSLCD_NETGROUP_TYPE_END 3
+
+/* Network name (/etc/networks) NSS requests. Result values for a single
+ entry are:
+ STRING network name
+ STRINGLIST network aliases
+ ADDRESSLIST network addresses */
+#define NSLCD_ACTION_NETWORK_BYNAME 0x00070001
+#define NSLCD_ACTION_NETWORK_BYADDR 0x00070002
+#define NSLCD_ACTION_NETWORK_ALL 0x00070008
+
+/* User account (/etc/passwd) NSS requests. Result values are:
+ STRING user name
+ STRING user password
+ INT32 user id
+ INT32 group id
+ STRING gecos information
+ STRING home directory
+ STRING login shell */
+#define NSLCD_ACTION_PASSWD_BYNAME 0x00080001
+#define NSLCD_ACTION_PASSWD_BYUID 0x00080002
+#define NSLCD_ACTION_PASSWD_ALL 0x00080008
+
+/* Protocol information requests. Result values are:
+ STRING protocol name
+ STRINGLIST protocol aliases
+ INT32 protocol number */
+#define NSLCD_ACTION_PROTOCOL_BYNAME 0x00090001
+#define NSLCD_ACTION_PROTOCOL_BYNUMBER 0x00090002
+#define NSLCD_ACTION_PROTOCOL_ALL 0x00090008
+
+/* RPC information requests. Result values are:
+ STRING rpc name
+ STRINGLIST rpc aliases
+ INT32 rpc number */
+#define NSLCD_ACTION_RPC_BYNAME 0x000a0001
+#define NSLCD_ACTION_RPC_BYNUMBER 0x000a0002
+#define NSLCD_ACTION_RPC_ALL 0x000a0008
+
+/* 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:
+ STRING service name
+ STRINGLIST service aliases
+ INT32 service (port) number
+ STRING service protocol */
+#define NSLCD_ACTION_SERVICE_BYNAME 0x000b0001
+#define NSLCD_ACTION_SERVICE_BYNUMBER 0x000b0002
+#define NSLCD_ACTION_SERVICE_ALL 0x000b0008
+
+/* Extended user account (/etc/shadow) information requests. Result
+ values for a single entry are:
+ STRING user name
+ STRING user password
+ INT32 last password change
+ INT32 mindays
+ INT32 maxdays
+ INT32 warn
+ INT32 inact
+ INT32 expire
+ INT32 flag */
+/* It is my understanding that an empty value for those INT32 fields
+ is expressed with a negative number. -- lukeshu */
+#define NSLCD_ACTION_SHADOW_BYNAME 0x000c0001
+#define NSLCD_ACTION_SHADOW_ALL 0x000c0008
+
+/* PAM-related requests. The request parameters for all these requests
+ begin with:
+ STRING user name
+ STRING service name
+ STRING ruser
+ STRING rhost
+ STRING tty
+ 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:
+ STRING password
+ and the result value consists of:
+ INT32 authc NSLCD_PAM_* result code
+ STRING user name (the cannonical user name)
+ INT32 authz NSLCD_PAM_* result code
+ STRING authorisation error message
+ 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. */
+#define NSLCD_ACTION_PAM_AUTHC 0x000d0001
+
+/* PAM authorisation check request. The result value consists of:
+ INT32 authz NSLCD_PAM_* result code
+ STRING authorisation error message
+ 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. */
+#define NSLCD_ACTION_PAM_AUTHZ 0x000d0002
+
+/* PAM session open request. The result value consists of:
+ STRING session id
+ This session id may be used to close this session with. */
+#define NSLCD_ACTION_PAM_SESS_O 0x000d0003
+
+/* PAM session close request. This request has the following
+ extra request value:
+ STRING session id
+ and this calls only returns an empty response value. */
+#define NSLCD_ACTION_PAM_SESS_C 0x000d0004
+
+/* PAM password modification request. This requests has the following extra
+ request values:
+ INT32 asroot: 0=oldpasswd is user passwd, 1=oldpasswd is root passwd
+ STRING old password
+ STRING new password
+ and returns there extra result values:
+ INT32 NSLCD_PAM_* result code
+ STRING error message */
+#define NSLCD_ACTION_PAM_PWMOD 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)
+ */
+#define NSLCD_ACTION_USERMOD 0x000e0001
+
+/* These are the possible values for the NSLCD_ACTION_USERMOD operation
+ above. */
+#define NSLCD_USERMOD_END 0 /* end of change values */
+#define NSLCD_USERMOD_RESULT 1 /* global result value */
+#define NSLCD_USERMOD_FULLNAME 2 /* full name */
+#define NSLCD_USERMOD_ROOMNUMBER 3 /* room number */
+#define NSLCD_USERMOD_WORKPHONE 4 /* office phone number */
+#define NSLCD_USERMOD_HOMEPHONE 5 /* home phone number */
+#define NSLCD_USERMOD_OTHER 6 /* other info */
+#define NSLCD_USERMOD_HOMEDIR 7 /* home directory */
+#define NSLCD_USERMOD_SHELL 8 /* login shell */
+
+/* Request result codes. */
+#define NSLCD_RESULT_BEGIN 1
+#define NSLCD_RESULT_END 2
+
+/* Partial list of PAM result codes. */
+#define NSLCD_PAM_SUCCESS 0 /* everything ok */
+#define NSLCD_PAM_PERM_DENIED 6 /* Permission denied */
+#define NSLCD_PAM_AUTH_ERR 7 /* Authc failure */
+#define NSLCD_PAM_CRED_INSUFFICIENT 8 /* Cannot access authc data */
+#define NSLCD_PAM_AUTHINFO_UNAVAIL 9 /* Cannot retrieve authc info */
+#define NSLCD_PAM_USER_UNKNOWN 10 /* User not known */
+#define NSLCD_PAM_MAXTRIES 11 /* Retry limit reached */
+#define NSLCD_PAM_NEW_AUTHTOK_REQD 12 /* Password expired */
+#define NSLCD_PAM_ACCT_EXPIRED 13 /* Account expired */
+#define NSLCD_PAM_SESSION_ERR 14 /* Cannot make/remove session record */
+#define NSLCD_PAM_AUTHTOK_ERR 20 /* Authentication token manipulation error */
+#define NSLCD_PAM_AUTHTOK_DISABLE_AGING 23 /* Password aging disabled */
+#define NSLCD_PAM_IGNORE 25 /* Ignore module */
+#define NSLCD_PAM_ABORT 26 /* Fatal error */
+#define NSLCD_PAM_AUTHTOK_EXPIRED 27 /* authentication token has expired */
+
+#endif /* not _NSLCD_H */
diff --git a/src/nslcd-proto/structures.go b/src/nslcd-proto/structures.go
new file mode 100644
index 0000000..7d36940
--- /dev/null
+++ b/src/nslcd-proto/structures.go
@@ -0,0 +1,249 @@
+
+package nslcd_proto
+
+import (
+ "io"
+ "fmt"
+ "net"
+)
+
+//#include "nslcd.h"
+import "C"
+
+type Config struct {
+ Value string
+}
+type Request_Config struct { Key int32 }
+
+type Alias struct {
+ Name string
+ Recipients []string
+}
+type Request_Alias_ByName struct { Name string }
+type Request_Alias_All struct {}
+
+type Ether struct {
+ Name string
+ Address [6]byte
+}
+type Request_Ether_ByName struct { Name string }
+type Request_Ether_ByEther struct { Address [6]byte }
+type Request_Ether_All struct {}
+
+type Group struct {
+ Name string
+ Password string
+ ID int32
+ Members []string
+}
+type Request_Group_ByName struct { Name string }
+type Request_Group_ByGid struct { GID int32 }
+type Request_Group_ByMember struct { Member string }
+type Request_Group_All struct {}
+
+type Host struct {
+ Name string
+ Aliases []string
+ Addresses []net.IP
+}
+type Request_Host_ByName struct { Name string }
+type Request_Host_ByAddr struct { Address net.IP }
+type Request_Host_All struct {}
+
+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 = C.NSLCD_NETGROUP_TYPE_NETGROUP
+ case Netgroup_Triple: t = C.NSLCD_NETGROUP_TYPE_TRIPLE
+ }
+ if t < 0 {
+ panic("invalid netgroup type")
+ }
+ write(fd, t)
+ write(fd, part)
+ }
+ write(fd, int32(C.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 C.NSLCD_NETGROUP_TYPE_NETGROUP:
+ v = Netgroup_Netgroup{}
+ case C.NSLCD_NETGROUP_TYPE_TRIPLE:
+ v = Netgroup_Triple{}
+ case C.NSLCD_NETGROUP_TYPE_END:
+ return
+ default:
+ panic(NslcdError(fmt.Sprintf("unrecognized netgroup type: %d", t)))
+ }
+ read(fd, &v)
+ *data = append(*data, v)
+ }
+}
+var _ NslcdObject = Netgroup_PartList{}
+var _ NslcdObjectPtr = &Netgroup_PartList{}
+type Netgroup struct {
+ Name string
+ Parts Netgroup_PartList
+}
+type Request_Netgroup_ByName struct { Name string }
+type Request_Netgroup_All struct {}
+
+type Network struct {
+ Name string
+ Aliases []string
+ Addresses []net.IP
+}
+type Request_Network_ByName struct { Name string }
+type Request_Network_ByAddr struct { Address net.IP }
+type Request_Network_All struct {}
+
+type Passwd struct {
+ Name string
+ Password string
+ UID int32
+ GID int32
+ GECOS string
+ HomeDir string
+ Shell string
+}
+type Request_Passwd_ByName struct { Name string }
+type Request_Passwd_ByUID struct { UID int32 }
+type Request_Passwd_All struct {}
+
+type Protocol struct {
+ Name string
+ Aliases []string
+ Number int32
+}
+type Request_Protocol_ByName struct { Name string }
+type Request_Protocol_ByNumber struct { Number int32 }
+type Request_Protocol_All struct {}
+
+type RPC struct {
+ Name string
+ Aliases []string
+ Number int32
+}
+type Request_RPC_ByName struct { Name string }
+type Request_RPC_ByNumber struct { Number int32 }
+type Request_RPC_All struct {}
+
+type Service struct {
+ Name string
+ Aliases []string
+ PortNumber int32
+ Protocol string
+}
+type Request_Service_ByName struct { Name string }
+type Request_Service_ByNumber struct { Number int32 }
+type Request_Service_All struct {}
+
+type Shadow struct {
+ Name string
+ Password string
+ LastChangeDate int32
+ MinDays int32
+ MaxDays int32
+ WarnDays int32
+ InactDays int32
+ ExpireDate int32
+ Flag int32
+}
+type Request_Shadow_ByName struct { Name string }
+type Request_Shadow_All struct {}
+
+type PAM_Base struct {
+ UserName string
+ ServiceName string
+ RUser string
+ RHost string
+ TTY string
+}
+
+type Request_PAM_Authentication struct {
+ Base PAM_Base
+ Password string
+}
+type PAM_Authentication struct {
+ AuthenticationResult int32
+ UserName string
+ AuthorizationResult int32
+ AuthorizationError string
+}
+
+type PAM_Authorization struct {
+ Result int32
+ Error string
+}
+type Request_PAM_Authorization struct {}
+
+type PAM_SessionOpen struct {
+ SessionID string
+}
+type Request_PAM_SessionOpen struct {}
+
+type PAM_SessionClose struct {}
+type Request_PAM_SessionClose struct {
+ SessionID string
+}
+
+type Request_PAM_PwMod struct {
+ AsRoot int32
+ OldPassword string
+ NewPassword string
+}
+type PAM_PwMod struct {
+ Result int32
+ Error string
+}
+
+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, int32(C.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 == C.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
+}
diff --git a/src/nslcd-proto/util.go b/src/nslcd-proto/util.go
new file mode 100644
index 0000000..ec74df2
--- /dev/null
+++ b/src/nslcd-proto/util.go
@@ -0,0 +1,47 @@
+package nslcd_proto
+
+import "io"
+
+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)
+}
+
+func Write(fd io.Writer, data interface{}) (err error) {
+ err = nil
+ defer func() {
+ if r := recover(); r != nil {
+ switch r := r.(type) {
+ case error:
+ err = r
+ default:
+ panic(r)
+ }
+ }
+ }()
+ write(fd, data)
+ return
+}
+
+func Read(fd io.Reader, data interface{}) (err error) {
+ err = nil
+ defer func() {
+ if r := recover(); r != nil {
+ switch r := r.(type) {
+ case error:
+ err = r
+ default:
+ panic(r)
+ }
+ }
+ }()
+ read(fd, data);
+ return
+}
diff --git a/src/sd-daemon/listen_fds.go b/src/sd-daemon/listen_fds.go
new file mode 100644
index 0000000..c90d373
--- /dev/null
+++ b/src/sd-daemon/listen_fds.go
@@ -0,0 +1,51 @@
+// Copyright 2015 CoreOS, Inc.
+// Copyright 2015 Luke Shumaker
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package activation implements primitives for systemd socket activation.
+package listen
+
+import (
+ "os"
+ "strconv"
+ "syscall"
+)
+
+//#include <systemd/sd-daemon.h>
+import "C"
+
+func ListenFds(unsetEnv bool) []*os.File {
+ if unsetEnv {
+ defer os.Unsetenv("LISTEN_PID")
+ defer os.Unsetenv("LISTEN_FDS")
+ }
+
+ pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
+ if err != nil || pid != os.Getpid() {
+ return nil
+ }
+
+ nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
+ if err != nil || nfds == 0 {
+ return nil
+ }
+
+ files := make([]*os.File, 0, nfds)
+ for fd := C.SD_LISTEN_FDS_START; fd < C.SD_LISTEN_FDS_START+nfds; fd++ {
+ syscall.CloseOnExec(fd)
+ files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd)))
+ }
+
+ return files
+}
diff --git a/src/sd-daemon/logger/logger.go b/src/sd-daemon/logger/logger.go
new file mode 100644
index 0000000..cfabe9f
--- /dev/null
+++ b/src/sd-daemon/logger/logger.go
@@ -0,0 +1,20 @@
+package logger
+
+import ("fmt"; "os")
+
+//#include <systemd/sd-daemon.h>
+import "C"
+
+func log(level string, format string, a ...interface{}) {
+ f := level + format + "\n";
+ fmt.Fprintf(os.Stderr, f, a);
+}
+
+/* system is unusable */ func Emerg( format string, a ...interface{}) { log(C.SD_EMERG , format, a); }
+/* action must be taken immediately */ func Alert( format string, a ...interface{}) { log(C.SD_ALERT , format, a); }
+/* critical conditions */ func Crit( format string, a ...interface{}) { log(C.SD_CRIT , format, a); }
+/* error conditions */ func Err( format string, a ...interface{}) { log(C.SD_ERR , format, a); }
+/* warning conditions */ func Warning(format string, a ...interface{}) { log(C.SD_WARNING, format, a); }
+/* normal but significant condition */ func Notice( format string, a ...interface{}) { log(C.SD_NOTICE , format, a); }
+/* informational */ func Info( format string, a ...interface{}) { log(C.SD_INFO , format, a); }
+/* debug-level messages */ func Debug( format string, a ...interface{}) { log(C.SD_DEBUG , format, a); }