summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2014-10-04 16:12:13 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2014-10-04 16:12:13 -0400
commitbe4588009b7106859e1beae6038aaea8d7f85825 (patch)
treeee0010a7003d23a686888fc9585de4e0ec429547
parent8e54633a2b520dff0a237349f5fc4cbcf4719f40 (diff)
remove non-nslcd stuff
-rw-r--r--Makefile.am15
-rw-r--r--configure.ac8
-rw-r--r--ldapns.ldif19
-rw-r--r--ldapns.schema20
-rw-r--r--man/Makefile.am13
-rw-r--r--man/chsh.ldap.1.xml148
-rw-r--r--man/getent.ldap.1.xml334
-rw-r--r--man/pam_ldap.8.xml220
-rw-r--r--man/pynslcd.8.xml159
-rw-r--r--nss/Makefile.am55
-rw-r--r--nss/aliases.c82
-rw-r--r--nss/bsdnss.c209
-rw-r--r--nss/common.c29
-rw-r--r--nss/common.h201
-rw-r--r--nss/ethers.c184
-rw-r--r--nss/exports.freebsd19
-rw-r--r--nss/exports.glibc91
-rw-r--r--nss/exports.solaris28
-rw-r--r--nss/group.c277
-rw-r--r--nss/hosts.c312
-rw-r--r--nss/netgroup.c370
-rw-r--r--nss/networks.c239
-rw-r--r--nss/passwd.c169
-rw-r--r--nss/protocols.c166
-rw-r--r--nss/prototypes.h156
-rw-r--r--nss/rpc.c165
-rw-r--r--nss/services.c176
-rw-r--r--nss/shadow.c164
-rw-r--r--nss/solnss.c49
-rw-r--r--nss/solnss.h113
-rw-r--r--pam/Makefile.am43
-rw-r--r--pam/common.h100
-rw-r--r--pam/pam.c791
-rw-r--r--pam/pam_ldap.map16
-rw-r--r--pynslcd/Makefile.am42
-rw-r--r--pynslcd/alias.py99
-rw-r--r--pynslcd/attmap.py174
-rw-r--r--pynslcd/cache.py194
-rw-r--r--pynslcd/cfg.py332
-rw-r--r--pynslcd/common.py138
-rw-r--r--pynslcd/config.py45
-rw-r--r--pynslcd/constants.py.in51
-rw-r--r--pynslcd/ether.py102
-rw-r--r--pynslcd/expr.py223
-rw-r--r--pynslcd/group.py229
-rw-r--r--pynslcd/host.py123
-rw-r--r--pynslcd/invalidator.py112
-rw-r--r--pynslcd/mypidfile.py71
-rw-r--r--pynslcd/netgroup.py116
-rw-r--r--pynslcd/network.py124
-rw-r--r--pynslcd/pam.py372
-rw-r--r--pynslcd/passwd.py146
-rw-r--r--pynslcd/protocol.py107
-rwxr-xr-xpynslcd/pynslcd.py382
-rw-r--r--pynslcd/rpc.py107
-rw-r--r--pynslcd/search.py195
-rw-r--r--pynslcd/service.py156
-rw-r--r--pynslcd/shadow.py127
-rw-r--r--pynslcd/tio.py106
-rw-r--r--pynslcd/usermod.py129
-rw-r--r--utils/Makefile.am42
-rwxr-xr-xutils/chsh.py71
-rw-r--r--utils/cmdline.py68
-rwxr-xr-xutils/getent.py353
-rw-r--r--utils/nslcd.py136
-rw-r--r--utils/shells.py64
-rw-r--r--utils/users.py60
67 files changed, 2 insertions, 9934 deletions
diff --git a/Makefile.am b/Makefile.am
index d51a9ad..f68955e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,28 +20,15 @@
# 02110-1301 USA
SUBDIRS = compat common
-if ENABLE_NSS
- SUBDIRS += nss
-endif
-if ENABLE_PAM
- SUBDIRS += pam
-endif
if ENABLE_NSLCD
SUBDIRS += nslcd
endif
-if ENABLE_PYNSLCD
- SUBDIRS += pynslcd
-endif
-if ENABLE_UTILS
- SUBDIRS += utils
-endif
SUBDIRS += man tests
EXTRA_DIST = nslcd.conf nslcd.h $(wildcard ChangeLog-20??) \
$(wildcard m4/*.m4) HACKING ldapns.schema ldapns.ldif
-DISTCHECK_CONFIGURE_FLAGS = --enable-warnings --enable-pynslcd --enable-utils \
- --with-pam-seclib-dir="\$${libdir}/security" \
+DISTCHECK_CONFIGURE_FLAGS = --enable-warnings \
--with-ldap-conf-file="\$${prefix}/nslcd.conf" \
CPPFLAGS=$(CPPFLAGS) LDFLAGS=$(LDFLAGS)
diff --git a/configure.ac b/configure.ac
index 90cfb14..0f80fbf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,14 +92,6 @@ then
AC_MSG_WARN([not installing man pages (no generator and not pre-generated)])
fi
-# check for Python and modules
-AM_PATH_PYTHON(2.5,, [:])
-AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != ":"])
-if test "x$PYTHON" != "x:"
-then
- AX_PYTHON_MODULE(argparse)
-fi
-
# check for debugging options
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
diff --git a/ldapns.ldif b/ldapns.ldif
deleted file mode 100644
index a86f8f5..0000000
--- a/ldapns.ldif
+++ /dev/null
@@ -1,19 +0,0 @@
-# LDAP Name Service Additional Schema
-# Source: pam_ldap package by Luke Howard converted to LDIF
-# Has not been published in Internet Draft or RFC.
-
-dn: cn=ldapns,cn=schema,cn=config
-objectClass: olcSchemaConfig
-cn: ldapns
-olcAttributeTypes: {0}( 1.3.6.1.4.1.5322.17.2.1 NAME 'authorizedService'
- DESC 'IANA GSS-API authorized service name'
- EQUALITY caseIgnoreMatch
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
-olcObjectClasses: {0}( 1.3.6.1.4.1.5322.17.1.1 NAME 'authorizedServiceObject'
- DESC 'Auxiliary object class for adding authorizedService attribute'
- SUP top AUXILIARY
- MAY authorizedService )
-olcObjectClasses: {1}( 1.3.6.1.4.1.5322.17.1.2 NAME 'hostObject'
- DESC 'Auxiliary object class for adding host attribute'
- SUP top AUXILIARY
- MAY host )
diff --git a/ldapns.schema b/ldapns.schema
deleted file mode 100644
index 542bcd0..0000000
--- a/ldapns.schema
+++ /dev/null
@@ -1,20 +0,0 @@
-# LDAP Name Service Additional Schema
-# Source: pam_ldap package by Luke Howard
-# Has not been published in Internet Draft or RFC.
-
-attributetype ( 1.3.6.1.4.1.5322.17.2.1 NAME 'authorizedService'
- DESC 'IANA GSS-API authorized service name'
- EQUALITY caseIgnoreMatch
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
-
-objectclass ( 1.3.6.1.4.1.5322.17.1.1 NAME 'authorizedServiceObject'
- DESC 'Auxiliary object class for adding authorizedService attribute'
- SUP top
- AUXILIARY
- MAY authorizedService )
-
-objectclass ( 1.3.6.1.4.1.5322.17.1.2 NAME 'hostObject'
- DESC 'Auxiliary object class for adding host attribute'
- SUP top
- AUXILIARY
- MAY host )
diff --git a/man/Makefile.am b/man/Makefile.am
index 636d68c..b6ca770 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -17,26 +17,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
-PAM_MANS = pam_ldap.8
-UTILS_MANS = getent.ldap.1 chsh.ldap.1
NSLCD_MANS = nslcd.conf.5 nslcd.8
-PYNSLCD_MANS = pynslcd.8
-ALL_MANS = $(PAM_MANS) $(UTILS_MANS) $(NSLCD_MANS) $(PYNSLCD_MANS)
+ALL_MANS = $(NSLCD_MANS)
# figure out which manual pages to install
if INSTMAN
man_MANS =
-if ENABLE_PAM
- man_MANS += $(PAM_MANS)
-endif
-if ENABLE_UTILS
- man_MANS += $(UTILS_MANS)
-endif
if ENABLE_NSLCD
man_MANS += $(NSLCD_MANS)
endif
-if ENABLE_PYNSLCD
- man_MANS += $(PYNSLCD_MANS)
if !ENABLE_NSLCD
man_MANS += nslcd.conf.5
endif
diff --git a/man/chsh.ldap.1.xml b/man/chsh.ldap.1.xml
deleted file mode 100644
index 3260ed3..0000000
--- a/man/chsh.ldap.1.xml
+++ /dev/null
@@ -1,148 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-
-<!--
- chsh.ldap.1.xml - docbook manual page for chsh.ldap
-
- Copyright (C) 2013-2014 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
--->
-
-<refentry id="chshldap1">
-
- <refentryinfo>
- <author>
- <firstname>Arthur</firstname>
- <surname>de Jong</surname>
- </author>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>chsh.ldap</refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo class="version">Version 0.9.4</refmiscinfo>
- <refmiscinfo class="manual">User Commands</refmiscinfo>
- <refmiscinfo class="date">Jun 2014</refmiscinfo>
- </refmeta>
-
- <refnamediv id="name">
- <refname>chsh.ldap</refname>
- <refpurpose>change login shell in LDAP</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv id="synopsis">
- <cmdsynopsis>
- <command>chsh.ldap</command>
- <arg choice="opt"><replaceable>options</replaceable></arg>
- <arg choice="opt"><replaceable>LOGIN</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1 id="description">
- <title>Description</title>
- <para>
- The <command>chsh.ldap</command> command can be used to change user's
- login shell (command interpreter).
- </para>
- <para>
- The actual change in <acronym>LDAP</acronym> is performed by the
- <command>nslcd</command> daemon and is subject to the access controls
- configured in the <acronym>LDAP</acronym> server.
- </para>
- </refsect1>
-
- <refsect1 id="options">
- <title>Options</title>
- <para>
- The options that may be specified to the <command>chsh.ldap</command>
- command are:
- </para>
- <variablelist remap="TP">
-
- <varlistentry id="shell">
- <term>
- <option>-s</option>, <option>--shell</option>
- <replaceable>SHELL</replaceable>
- </term>
- <listitem>
- <para>
- The name of the user's new login shell.
- Setting this field to blank causes the system to select the default
- login shell.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="listshells">
- <term>
- <option>-l</option>, <option>--list-shells</option>
- </term>
- <listitem>
- <para>
- Print the list of shells found in <filename>/etc/shells</filename> and exit.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="help">
- <term>
- <option>-h</option>, <option>--help</option>
- </term>
- <listitem>
- <para>Display short help and exit.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="version">
- <term>
- <option>-V, --version</option>
- </term>
- <listitem>
- <para>Output version information and exit.</para>
- </listitem>
- </varlistentry>
-
- </variablelist>
- <para>
- If no option is specified <command>chsh.ldap</command> will prompt the
- user to enter a value for the shell.
- </para>
- </refsect1>
-
- <refsect1 id="files">
- <title>Files</title>
- <para>
- <filename>/etc/shells</filename> - list of valid login shells
- </para>
- </refsect1>
-
- <refsect1 id="see_also">
- <title>See Also</title>
- <para>
- <citerefentry><refentrytitle>chsh</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>shells</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>nslcd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- </para>
- </refsect1>
-
- <refsect1 id="author">
- <title>Author</title>
- <para>This manual was written by Arthur de Jong &lt;arthur@arthurdejong.org&gt;.</para>
- </refsect1>
-
-</refentry>
diff --git a/man/getent.ldap.1.xml b/man/getent.ldap.1.xml
deleted file mode 100644
index 9b0d039..0000000
--- a/man/getent.ldap.1.xml
+++ /dev/null
@@ -1,334 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-
-<!--
- getent.ldap.1.xml - docbook manual page for chsh.ldap
-
- Copyright (C) 2013-2014 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
--->
-
-<refentry id="getentldap1">
-
- <refentryinfo>
- <author>
- <firstname>Arthur</firstname>
- <surname>de Jong</surname>
- </author>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>getent.ldap</refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo class="version">Version 0.9.4</refmiscinfo>
- <refmiscinfo class="manual">User Commands</refmiscinfo>
- <refmiscinfo class="date">Jun 2014</refmiscinfo>
- </refmeta>
-
- <refnamediv id="name">
- <refname>getent.ldap</refname>
- <refpurpose>query information from LDAP</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv id="synopsis">
- <cmdsynopsis>
- <command>getent.ldap</command>
- <arg choice="opt"><replaceable>options</replaceable></arg>
- <arg><replaceable>DATABASE</replaceable></arg>
- <arg choice="opt"><replaceable>KEY</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1 id="description">
- <title>Description</title>
- <para>
- The <command>getent.ldap</command> command can be used to lookup or
- enumerate information from <acronym>LDAP</acronym>.
- Unlike the
- <citerefentry><refentrytitle>getent</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- command, this command completely bypasses the lookups configured in
- <filename>/etc/nsswitch.conf</filename> and queries the
- <citerefentry><refentrytitle>nslcd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- daemon directly.
- </para>
- <para>
- <command>getent.ldap</command> tries to match the behaviour and output of
- <command>getent</command> and the format in the corresponding flat files
- as much as possible, however there are a number of differences.
- If multiple entries are found in <acronym>LDAP</acronym> that match a
- specific query, multiple values are printed (e.g. ethernet addresses that
- have multiple names, services that support multiple protocols, etc.).
- Also, some databases have extra options as described below.
- </para>
- </refsect1>
-
- <refsect1 id="options">
- <title>Options</title>
- <para>
- The options that may be specified to the <command>getent.ldap</command>
- command are:
- </para>
- <variablelist remap="TP">
-
- <varlistentry id="help">
- <term>
- <option>-h</option>, <option>--help</option>
- </term>
- <listitem>
- <para>Display short help and exit.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="version">
- <term>
- <option>-V, --version</option>
- </term>
- <listitem>
- <para>Output version information and exit.</para>
- </listitem>
- </varlistentry>
-
- </variablelist>
- </refsect1>
-
- <refsect1 id="databases">
- <title>Databases</title>
- <para>
- The <replaceable>DATABASE</replaceable> argument may be any of the
- supported databases below:
- </para>
- <variablelist remap="TP">
-
- <varlistentry id="aliases">
- <term><option>aliases</option></term>
- <listitem>
- <para>
- Lists or queries email aliases.
- If <replaceable>KEY</replaceable> is given it searches for the alias
- by name, otherwise it returns all aliases from
- <acronym>LDAP</acronym>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="ethers">
- <term><option>ethers</option></term>
- <listitem>
- <para>
- Lists or queries ethernet addresses.
- If <replaceable>KEY</replaceable> matches the format of an ethernet
- address a search by address is performed, otherwise a search by name
- is performed or all entries are returned if
- <replaceable>KEY</replaceable> is omitted.
- Unlike <command>getent</command>, <command>getent.ldapd</command>
- does support enumerating all ethernet addresses.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="group">
- <term><option>group</option></term>
- <listitem>
- <para>
- Lists or queries groups.
- If <replaceable>KEY</replaceable> is numeric, it searches for the
- group by group id.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="group.bymember">
- <term><option>group.bymember</option></term>
- <listitem>
- <para>
- The <replaceable>KEY</replaceable> is a user name and groups are
- returned for which this user is a member.
- The format is similar to the <option>group</option> output but the
- group members are left out for performance reasons.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="hosts">
- <term><option>hosts</option></term>
- <listitem>
- <para>
- List or search host names and addresses by either host name,
- IPv4 or IPv6 address. This returns both IPv4 and IPv6 addresses
- (if available).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="hostsv4">
- <term><option>hostsv4</option></term>
- <listitem>
- <para>
- Similar to <option>hosts</option> but any supplied IPv6 addresses are
- treated as host names and only IPv4 addresses are returned.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="hostsv6">
- <term><option>hostsv6</option></term>
- <listitem>
- <para>
- Similar to <option>hosts</option> but <replaceable>KEY</replaceable>
- is treated as an IPv6 address or a host name and only IPv6 addresses
- are returned.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="netgroup">
- <term><option>netgroup</option></term>
- <listitem>
- <para>
- List or query netgroups and netgroup triples (host, user, domain) that
- are a member of the netgroup.
- Unlike <command>getent</command>, <command>getent.ldapd</command>
- does support enumerating all ethernet addresses.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="netgroup.norec">
- <term><option>netgroup.norec</option></term>
- <listitem>
- <para>
- Similar to <option>netgroup</option> except that no subsequent
- lookups are done to expand netgroups which are member of the
- supplied netgroup and the output may contain both other netgroup
- names and netgroup triples.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="networks">
- <term><option>networks</option></term>
- <listitem>
- <para>
- List or query network names and addresses.
- <replaceable>KEY</replaceable> may be a network name or address.
- This map can return both IPv4 and IPv6 network addresses.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="networksv4">
- <term><option>networksv4</option></term>
- <listitem>
- <para>
- Only return IPv4 network addresses.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="networksv6">
- <term><option>networksv6</option></term>
- <listitem>
- <para>
- Only return IPv6 network addresses.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="passwd">
- <term><option>passwd</option></term>
- <listitem>
- <para>
- Enumerate or search the user account database.
- <replaceable>KEY</replaceable> may be a user name or numeric user id
- or be omitted to list all users.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="protocols">
- <term><option>protocols</option></term>
- <listitem>
- <para>
- Enumerate the internet protocols database.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="rpc">
- <term><option>rpc</option></term>
- <listitem>
- <para>
- List or search user readable names that map to RPC program numbers.
- Searching by <replaceable>KEY</replaceable> can be done on name or
- rpc program number.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="services">
- <term><option>services</option></term>
- <listitem>
- <para>
- List or search the mapping between names for internet services and
- their corresponding port numbers and protocol types.
- The <replaceable>KEY</replaceable> can be either a service name or
- number, followed by an optional slash and protocol name to restrict
- the search to only entries for the specified protocol.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="shadow">
- <term><option>shadow</option></term>
- <listitem>
- <para>
- Enumerate or search extended user account information.
- Note that shadow information is likely only exposed to the root user
- and by default <command>nslcd</command> does not expose password
- hashes, even to root.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
- </refsect1>
-
-
- <refsect1 id="see_also">
- <title>See Also</title>
- <para>
- <citerefentry><refentrytitle>getent</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>nslcd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- </para>
- </refsect1>
-
- <refsect1 id="author">
- <title>Author</title>
- <para>This manual was written by Arthur de Jong &lt;arthur@arthurdejong.org&gt;.</para>
- </refsect1>
-
- <refsect1 id="bugs">
- <title>Bugs</title>
- <para>
- Currently, <command>getent.ldapd</command> does not correctly set an
- exit code. It should return the same kind of exit codes as
- <command>getent</command> does (e.g. for missing entries).
- </para>
- </refsect1>
-
-</refentry>
diff --git a/man/pam_ldap.8.xml b/man/pam_ldap.8.xml
deleted file mode 100644
index 280f642..0000000
--- a/man/pam_ldap.8.xml
+++ /dev/null
@@ -1,220 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-
-<!--
- pam_ldap.8.xml - docbook manual page for pam_ldap PAM module
-
- Copyright (C) 2009-2014 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
--->
-
-<refentry id="pamldap8">
-
- <refentryinfo>
- <author>
- <firstname>Arthur</firstname>
- <surname>de Jong</surname>
- </author>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>pam_ldap</refentrytitle>
- <manvolnum>8</manvolnum>
- <refmiscinfo class="version">Version 0.9.4</refmiscinfo>
- <refmiscinfo class="manual">System Manager's Manual</refmiscinfo>
- <refmiscinfo class="date">Jun 2014</refmiscinfo>
- </refmeta>
-
- <refnamediv id="name">
- <refname>pam_ldap</refname>
- <refpurpose>PAM module for LDAP-based authentication</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv id="synopsis">
- <cmdsynopsis>
- <command>pam_ldap.so</command>
- <arg choice="opt"><replaceable>...</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1 id="description">
- <title>Description</title>
- <para>
- This is a <acronym>PAM</acronym> module that uses an
- <acronym>LDAP</acronym> server to verify user access rights and
- credentials.
- </para>
- </refsect1>
-
- <refsect1 id="options">
- <title>Options</title>
- <variablelist remap="TP">
- <varlistentry id="use_first_pass">
- <term>
- <option>use_first_pass</option>
- </term>
- <listitem>
- <para>
- Specifies that the <acronym>PAM</acronym> module should use the first
- password provided in the authentication stack and not prompt the user
- for a password.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="try_first_pass">
- <term>
- <option>try_first_pass</option>
- </term>
- <listitem>
- <para>
- Specifies that the <acronym>PAM</acronym> module should use the first
- password provided in the authentication stack and if that fails prompt
- the user for a password.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="nullok">
- <term>
- <option>nullok</option>
- </term>
- <listitem>
- <para>
- Specifying this option allows users to log in with a blank password.
- Normally logins without a password are denied.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="ignore_unknown_user">
- <term>
- <option>ignore_unknown_user</option>
- </term>
- <listitem>
- <para>
- Specifies that the <acronym>PAM</acronym> module should return
- PAM_IGNORE for users that are not present in the <acronym>LDAP</acronym>
- directory.
- This causes the <acronym>PAM</acronym> framework to ignore this module.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="ignore_authinfo_unavail">
- <term>
- <option>ignore_authinfo_unavail</option>
- </term>
- <listitem>
- <para>
- Specifies that the <acronym>PAM</acronym> module should return
- PAM_IGNORE if it cannot contact the <acronym>LDAP</acronym> server.
- This causes the <acronym>PAM</acronym> framework to ignore this module.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="no_warn">
- <term>
- <option>no_warn</option>
- </term>
- <listitem>
- <para>
- Specifies that warning messages should not be propagated to the
- <acronym>PAM</acronym> application.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="use_authtok">
- <term>
- <option>use_authtok</option>
- </term>
- <listitem>
- <para>
- This causes the <acronym>PAM</acronym> module to use the earlier
- provided password when changing the password. The module will not
- prompt the user for a new password (it is analogous to
- <option>use_first_pass</option>).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="debug">
- <term>
- <option>debug</option>
- </term>
- <listitem>
- <para>
- This option causes the <acronym>PAM</acronym> module to log debugging
- information to
- <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry id="minimum_uid">
- <term>
- <option>minimum_uid=<replaceable>UID</replaceable></option>
- </term>
- <listitem>
- <para>
- This option causes the <acronym>PAM</acronym> module to ignore the user
- if the user id is lower than the specified value. This can be used to
- bypass <acronym>LDAP</acronym> checks for system users
- (e.g. by setting it to <literal>1000</literal>).
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1 id="moduleservices">
- <title>Module Services Provided</title>
- <para>
- All services are provided by this module but currently sessions changes
- are not implemented in the nslcd daemon.
- </para>
- </refsect1>
-
- <refsect1 id="files">
- <title>Files</title>
- <variablelist remap="TP">
- <varlistentry>
- <term><filename>/etc/pam.conf</filename></term>
- <listitem><para>the main PAM configuration file</para></listitem>
- </varlistentry>
- <varlistentry>
- <term><filename>/etc/nslcd.conf</filename></term>
- <listitem><para>
- The configuration file for the <command>nslcd</command> daemon
- (see <citerefentry><refentrytitle>nslcd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1 id="see_also">
- <title>See Also</title>
- <para>
- <citerefentry><refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>nslcd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>nslcd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- </para>
- </refsect1>
-
- <refsect1 id="author">
- <title>Author</title>
- <para>
- This manual was written by Arthur de Jong &lt;arthur@arthurdejong.org&gt;.
- </para>
- </refsect1>
-
-</refentry>
diff --git a/man/pynslcd.8.xml b/man/pynslcd.8.xml
deleted file mode 100644
index 26142f6..0000000
--- a/man/pynslcd.8.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-
-<!--
- pynslcd.8.xml - docbook manual page for pynslcd
-
- Copyright (C) 2012-2014 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
--->
-
-<refentry id="pynslcd8">
-
- <refentryinfo>
- <author>
- <firstname>Arthur</firstname>
- <surname>de Jong</surname>
- </author>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>pynslcd</refentrytitle>
- <manvolnum>8</manvolnum>
- <refmiscinfo class="version">Version 0.9.4</refmiscinfo>
- <refmiscinfo class="manual">System Manager's Manual</refmiscinfo>
- <refmiscinfo class="date">Jun 2014</refmiscinfo>
- </refmeta>
-
- <refnamediv id="name">
- <refname>pynslcd</refname>
- <refpurpose>local LDAP name service daemon</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv id="synopsis">
- <cmdsynopsis>
- <command>pynslcd</command>
- <arg choice="opt"><replaceable>options</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1 id="description">
- <title>Description</title>
- <para>
- <command>pynslcd</command> is a daemon that will do LDAP queries for local
- processes that want to do user, group and other naming lookups (NSS) or do
- user authentication, authorisation or password modification (PAM).
- </para>
- <para>
- <command>pynslcd</command> is configured through a configuration file
- (see <citerefentry><refentrytitle>nslcd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
- </para>
- <para>
- See the included README for information on configuring the LDAP server.
- </para>
- </refsect1>
-
- <refsect1 id="options">
- <title>Options</title>
- <para>
- <command>pynslcd</command> accepts the following options:</para>
- <variablelist remap="TP">
-
- <varlistentry id="check">
- <term>
- <option>-c</option>, <option>--check</option>
- </term>
- <listitem>
- <para>
- Check if the daemon is running.
- This causes <command>pynslcd</command> to return 0 if the daemon is already running and 1 if it is not.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="debug">
- <term>
- <option>-d</option>, <option>--debug</option>
- </term>
- <listitem>
- <para>
- Enable debugging mode.
- <command>pynslcd</command> will not put itself in the background and sends
- verbose debugging info to stderr.
- <command>pynslcd</command> will handle connections as usual.
- This option is for debugging purposes only.
- Specify this option multiple times to also include more detailed logging
- from the LDAP library.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="nofork">
- <term>
- <option>-n</option>, <option>--nofork</option>
- </term>
- <listitem>
- <para>
- Do not fork or daemonise and run <command>pynslcd</command> in the
- foreground.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="help">
- <term>
- <option>--help</option>
- </term>
- <listitem>
- <para>Display short help and exit.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry id="version">
- <term>
- <option>-V</option>, <option>--version</option>
- </term>
- <listitem>
- <para>Output version information and exit.</para>
- </listitem>
- </varlistentry>
-
- </variablelist>
- </refsect1>
-
- <refsect1 id="files">
- <title>Files</title>
- <para>
- <filename>/etc/nslcd.conf</filename> - the configuration file
- (see <citerefentry><refentrytitle>nslcd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
- </para>
- </refsect1>
-
- <refsect1 id="see_also">
- <title>See Also</title>
- <para>
- <citerefentry><refentrytitle>nslcd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- </para>
- </refsect1>
-
- <refsect1 id="author">
- <title>Author</title>
- <para>This manual was written by Arthur de Jong &lt;arthur@arthurdejong.org&gt;.</para>
- </refsect1>
-
-</refentry>
diff --git a/nss/Makefile.am b/nss/Makefile.am
deleted file mode 100644
index 6bb2b24..0000000
--- a/nss/Makefile.am
+++ /dev/null
@@ -1,55 +0,0 @@
-# Makefile.am - use automake to generate Makefile.in
-#
-# Copyright (C) 2006 Luke Howard
-# Copyright (C) 2006 West Consulting
-# Copyright (C) 2006, 2007, 2009, 2010, 2011 Arthur de Jong
-# Copyright (C) 2010 Symas Corporation
-#
-# 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
-
-noinst_PROGRAMS = nss_ldap.so
-
-AM_CPPFLAGS=-I$(top_srcdir)
-AM_CFLAGS = -fPIC
-
-nss_ldap_so_SOURCES = common.c common.h prototypes.h solnss.h \
- ../nslcd.h ../common/nslcd-prot.h \
- ../compat/attrs.h
-EXTRA_nss_ldap_so_SOURCES = aliases.c ethers.c group.c hosts.c netgroup.c \
- networks.c passwd.c protocols.c rpc.c services.c \
- shadow.c solnss.c bsdnss.c
-nss_ldap_so_LDADD = $(NSS_MODULE_OBJS)
-if NSS_FLAVOUR_SOLARIS
-nss_ldap_so_LDADD += solnss.$(OBJEXT) ../common/libdict.a
-endif
-if NSS_FLAVOUR_FREEBSD
-nss_ldap_so_LDADD += bsdnss.$(OBJEXT)
-endif
-nss_ldap_so_LDADD += ../common/libtio.a ../common/libprot.a
-nss_ldap_so_DEPENDENCIES = $(nss_ldap_so_LDADD)
-
-EXTRA_DIST = exports.glibc exports.solaris exports.freebsd
-
-install-exec-local: install-nss_ldap_so
-uninstall-local: uninstall-nss_ldap_so
-
-install-nss_ldap_so: nss_ldap.so
- -rm -f $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME)
- $(mkinstalldirs) $(DESTDIR)$(libdir)
- $(INSTALL_PROGRAM) nss_ldap.so $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME)
-
-uninstall-nss_ldap_so:
- -rm -f $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME)
diff --git a/nss/aliases.c b/nss/aliases.c
deleted file mode 100644
index 261c92d..0000000
--- a/nss/aliases.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- aliases.c - NSS lookup functions for aliases database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-
-/* read an alias entry from the stream */
-static nss_status_t read_aliasent(TFILE *fp, struct aliasent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct aliasent));
- /* read the name of the alias */
- READ_BUF_STRING(fp, result->alias_name);
- /* read the members */
- READ_BUF_STRINGLIST(fp, result->alias_members);
- /* tmp3int32 holds the number of entries read */
- result->alias_members_len = tmp3int32;
- /* fill in remaining gaps in struct */
- result->alias_local = 0;
- /* we're done */
- return NSS_STATUS_SUCCESS;
-}
-
-/* get an alias entry by name */
-nss_status_t _nss_ldap_getaliasbyname_r(const char *name,
- struct aliasent *result,
- char *buffer, size_t buflen,
- int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_ALIAS_BYNAME,
- WRITE_STRING(fp, name),
- read_aliasent(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *aliasentfp;
-
-/* start a request to read all aliases */
-nss_status_t _nss_ldap_setaliasent(void)
-{
- NSS_SETENT(aliasentfp);
-}
-
-/* read a single alias entry from the stream */
-nss_status_t _nss_ldap_getaliasent_r(struct aliasent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(aliasentfp, NSLCD_ACTION_ALIAS_ALL,
- read_aliasent(aliasentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened with setaliasent() above */
-nss_status_t _nss_ldap_endaliasent(void)
-{
- NSS_ENDENT(aliasentfp);
-}
diff --git a/nss/bsdnss.c b/nss/bsdnss.c
deleted file mode 100644
index 85c62b8..0000000
--- a/nss/bsdnss.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- bsdnss.c - BSD NSS functions
- This file was part of the nss-pam-ldapd FreeBSD port and part of the
- nss_ldap FreeBSD port before that.
-
- Copyright (C) 2003 Jacques Vidrine
- Copyright (C) 2006 Artem Kazakov
- Copyright (C) 2009 Alexander V. Chernikov
- Copyright (C) 2011, 2012, 2013 Arthur de Jong
- Copyright (C) 2011 Tom Judge
-
- 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
-*/
-
-#include "config.h"
-
-#include <errno.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-#define BUFFER_SIZE 1024
-
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_setgrent);
-NSS_METHOD_PROTOTYPE(__nss_compat_endgrent);
-NSS_METHOD_PROTOTYPE(__freebsd_getgroupmembership);
-
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
-NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
-NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
-
-NSS_METHOD_PROTOTYPE(__nss_compat_gethostbyname);
-NSS_METHOD_PROTOTYPE(__nss_compat_gethostbyname2);
-NSS_METHOD_PROTOTYPE(__nss_compat_gethostbyaddr);
-
-static ns_mtab methods[] = {
- { NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_ldap_getgrnam_r },
- { NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_ldap_getgrgid_r },
- { NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_ldap_getgrent_r },
- { NSDB_GROUP, "setgrent", __nss_compat_setgrent, _nss_ldap_setgrent },
- { NSDB_GROUP, "endgrent", __nss_compat_endgrent, _nss_ldap_endgrent },
- { NSDB_GROUP, "getgroupmembership", __freebsd_getgroupmembership, NULL },
-
- { NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_ldap_getpwnam_r },
- { NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_ldap_getpwuid_r },
- { NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_ldap_getpwent_r },
- { NSDB_PASSWD, "setpwent", __nss_compat_setpwent, _nss_ldap_setpwent },
- { NSDB_PASSWD, "endpwent", __nss_compat_endpwent, _nss_ldap_endpwent },
-
- { NSDB_HOSTS, "gethostbyname", __nss_compat_gethostbyname, _nss_ldap_gethostbyname_r },
- { NSDB_HOSTS, "gethostbyaddr", __nss_compat_gethostbyaddr, _nss_ldap_gethostbyaddr_r },
- { NSDB_HOSTS, "gethostbyname2", __nss_compat_gethostbyname2, _nss_ldap_gethostbyname2_r },
-
- { NSDB_GROUP_COMPAT, "getgrnam_r", __nss_compat_getgrnam_r, _nss_ldap_getgrnam_r },
- { NSDB_GROUP_COMPAT, "getgrgid_r", __nss_compat_getgrgid_r, _nss_ldap_getgrgid_r },
- { NSDB_GROUP_COMPAT, "getgrent_r", __nss_compat_getgrent_r, _nss_ldap_getgrent_r },
- { NSDB_GROUP_COMPAT, "setgrent", __nss_compat_setgrent, _nss_ldap_setgrent },
- { NSDB_GROUP_COMPAT, "endgrent", __nss_compat_endgrent, _nss_ldap_endgrent },
-
- { NSDB_PASSWD_COMPAT, "getpwnam_r", __nss_compat_getpwnam_r, _nss_ldap_getpwnam_r },
- { NSDB_PASSWD_COMPAT, "getpwuid_r", __nss_compat_getpwuid_r, _nss_ldap_getpwuid_r },
- { NSDB_PASSWD_COMPAT, "getpwent_r", __nss_compat_getpwent_r, _nss_ldap_getpwent_r },
- { NSDB_PASSWD_COMPAT, "setpwent", __nss_compat_setpwent, _nss_ldap_setpwent },
- { NSDB_PASSWD_COMPAT, "endpwent", __nss_compat_endpwent, _nss_ldap_endpwent },
-};
-
-int __nss_compat_gethostbyname(void UNUSED(*retval), void *mdata, va_list ap)
-{
- nss_status_t (*fn)(const char *, struct hostent *, char *, size_t, int *, int *);
- const char *name;
- struct hostent *result;
- char buffer[BUFFER_SIZE];
- int errnop;
- int h_errnop;
- int af;
- nss_status_t status;
- fn = mdata;
- name = va_arg(ap, const char *);
- af = va_arg(ap, int);
- result = va_arg(ap, struct hostent *);
- status = fn(name, result, buffer, sizeof(buffer), &errnop, &h_errnop);
- status = __nss_compat_result(status, errnop);
- h_errno = h_errnop;
- return status;
-}
-
-int __nss_compat_gethostbyname2(void UNUSED(*retval), void *mdata, va_list ap)
-{
- nss_status_t (*fn)(const char *, struct hostent *, char *, size_t, int *, int *);
- const char *name;
- struct hostent *result;
- char buffer[BUFFER_SIZE];
- int errnop;
- int h_errnop;
- int af;
- nss_status_t status;
- fn = mdata;
- name = va_arg(ap, const char *);
- af = va_arg(ap, int);
- result = va_arg(ap, struct hostent *);
- status = fn(name, result, buffer, sizeof(buffer), &errnop, &h_errnop);
- status = __nss_compat_result(status, errnop);
- h_errno = h_errnop;
- return status;
-}
-
-int __nss_compat_gethostbyaddr(void UNUSED(*retval), void *mdata, va_list ap)
-{
- struct in_addr *addr;
- int len;
- int type;
- struct hostent *result;
- char buffer[BUFFER_SIZE];
- int errnop;
- int h_errnop;
- nss_status_t (*fn)(struct in_addr *, int, int, struct hostent *, char *, size_t, int *, int *);
- nss_status_t status;
- fn = mdata;
- addr = va_arg(ap, struct in_addr *);
- len = va_arg(ap, int);
- type = va_arg(ap, int);
- result = va_arg(ap, struct hostent *);
- status = fn(addr, len, type, result, buffer, sizeof(buffer), &errnop, &h_errnop);
- status = __nss_compat_result(status, errnop);
- h_errno = h_errnop;
- return status;
-}
-
-static int __gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *groupc)
-{
- int ret, dupc;
- /* skip duplicates */
- for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++)
- {
- if (groups[dupc] == gid)
- return 1;
- }
- ret = 1;
- if (*groupc < maxgrp) /* add this gid */
- groups[*groupc] = gid;
- else
- ret = 0;
- (*groupc)++;
- return ret;
-}
-
-int __freebsd_getgroupmembership(void UNUSED(*retval), void UNUSED(*mdata_),
- va_list ap)
-{
- int err;
- nss_status_t s;
- gid_t group;
- gid_t *tmpgroups;
- const char *user;
- gid_t *groups;
- int maxgrp, *grpcnt;
- int i;
- long int lstart, lsize;
- user = va_arg(ap, const char *);
- group = va_arg(ap, gid_t);
- groups = va_arg(ap, gid_t *);
- maxgrp = va_arg(ap, int);
- grpcnt = va_arg(ap, int *);
- tmpgroups = malloc(maxgrp * sizeof(gid_t));
- if (tmpgroups == NULL)
- return NSS_STATUS_UNAVAIL;
- /* insert primary membership */
- __gr_addgid(group, groups, maxgrp, grpcnt);
- lstart = 0;
- lsize = maxgrp;
- s = _nss_ldap_initgroups_dyn(user, group, &lstart, &lsize, &tmpgroups, 0, &err);
- if (s == NSS_STATUS_SUCCESS)
- {
- for (i = 0; i < lstart; i++)
- __gr_addgid(tmpgroups[i], groups, maxgrp, grpcnt);
- s = NSS_STATUS_NOTFOUND;
- }
- free(tmpgroups);
- return __nss_compat_result(s, 0);
-}
-
-ns_mtab *nss_module_register(const char UNUSED(*source), unsigned int *mtabsize,
- nss_module_unregister_fn *unreg)
-{
- *mtabsize = sizeof(methods) / sizeof(methods[0]);
- *unreg = NULL;
- return methods;
-}
diff --git a/nss/common.c b/nss/common.c
deleted file mode 100644
index 1e00475..0000000
--- a/nss/common.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- common.c - common definitions
-
- Copyright (C) 2010, 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
-*/
-
-#include "config.h"
-
-#include <stddef.h>
-
-int _nss_ldap_enablelookups = 1;
-
-/* version information about the NSS module */
-char *_nss_ldap_version[3] = { PACKAGE, VERSION, NULL };
diff --git a/nss/common.h b/nss/common.h
deleted file mode 100644
index 254a5bb..0000000
--- a/nss/common.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- common.h - common functions for NSS lookups
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 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 NSS__COMMON_H
-#define NSS__COMMON_H 1
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "nslcd.h"
-#include "common/nslcd-prot.h"
-#include "compat/attrs.h"
-#include "compat/nss_compat.h"
-
-#ifdef NSS_FLAVOUR_SOLARIS
-#include "solnss.h"
-#endif /* NSS_FLAVOUR_SOLARIS */
-
-/* skip timeout determines the maximum time to wait when closing the
- connection and reading whatever data that is available */
-#define SKIP_TIMEOUT 500
-
-/* These are macros for handling read and write problems, they are
- NSS specific due to the return code so are defined here. They
- genrally close the open file, set an error code and return with
- an error status. */
-
-/* Macro is called to handle errors in opening a client connection. */
-#define ERROR_OUT_OPENERROR \
- *errnop = ENOENT; \
- return (errno == EAGAIN) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
-
-/* Macro is called to handle errors on read operations. */
-#define ERROR_OUT_READERROR(fp) \
- (void)tio_close(fp); \
- fp = NULL; \
- *errnop = ENOENT; \
- return NSS_STATUS_UNAVAIL;
-
-/* Macro is called to handle problems with too small a buffer.
- This triggers the caller to call the function with a larger
- buffer (see NSS_GETENT below). */
-#define ERROR_OUT_BUFERROR(fp) \
- *errnop = ERANGE; \
- return NSS_STATUS_TRYAGAIN;
-
-/* This macro is called if there was a problem with a write
- operation. */
-#define ERROR_OUT_WRITEERROR(fp) \
- ERROR_OUT_READERROR(fp)
-
-/* This macro is called if the read status code is not
- NSLCD_RESULT_BEGIN. */
-#define ERROR_OUT_NOSUCCESS(fp) \
- (void)tio_close(fp); \
- fp = NULL; \
- return NSS_STATUS_NOTFOUND;
-
-/* These are some general macros that are used to build parts of the
- genral macros below. */
-
-/* check to see if we should answer NSS requests */
-#define NSS_AVAILCHECK \
- if (!_nss_ldap_enablelookups) \
- return NSS_STATUS_UNAVAIL;
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* extra definitions we need (nothing for Glibc) */
-#define NSS_EXTRA_DEFS ;
-
-/* check validity of passed buffer (Glibc flavour) */
-#define NSS_BUFCHECK \
- if (buffer == NULL) \
- { \
- *errnop = EINVAL; \
- return NSS_STATUS_UNAVAIL; \
- } \
- if (buflen == 0) \
- { \
- *errnop = ERANGE; \
- return NSS_STATUS_TRYAGAIN; \
- }
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-/* The following macros to automatically generate get..byname(),
- get..bynumber(), setent(), getent() and endent() function
- bodies. These functions have very common code so this can
- easily be reused. */
-
-/* This is a generic get..by..() generation macro. The action
- parameter is the NSLCD_ACTION_.. action, the writefn is the
- operation for writing the parameters and readfn is the function
- name for reading a single result entry. The function is assumed
- to have result, buffer, buflen and errnop parameters that define
- the result structure, the user buffer with length and the
- errno to return. This macro should be called through some of
- the customized ones below. */
-#define NSS_GETONE(action, writefn, readfn) \
- TFILE *fp; \
- int32_t tmpint32; \
- nss_status_t retv; \
- NSS_EXTRA_DEFS; \
- NSS_AVAILCHECK; \
- NSS_BUFCHECK; \
- /* open socket and write request */ \
- NSLCD_REQUEST(fp, action, writefn); \
- /* read response */ \
- READ_RESPONSE_CODE(fp); \
- retv = readfn; \
- /* close socket and we're done */ \
- if ((retv == NSS_STATUS_SUCCESS) || (retv == NSS_STATUS_TRYAGAIN)) \
- { \
- (void)tio_skipall(fp, SKIP_TIMEOUT); \
- (void)tio_close(fp); \
- } \
- return retv;
-
-/* This macro generates a simple setent() function body. This closes any
- open streams so that NSS_GETENT() can open a new file. */
-#define NSS_SETENT(fp) \
- NSS_AVAILCHECK; \
- if (fp != NULL) \
- { \
- (void)tio_close(fp); \
- fp = NULL; \
- } \
- return NSS_STATUS_SUCCESS;
-
-/* This macro generates a getent() function body. If the stream is not yet
- open, a new one is opened, a request is written and a check is done for
- a response header. A single entry is read with the readfn() function. */
-#define NSS_GETENT(fp, action, readfn) \
- int32_t tmpint32; \
- nss_status_t retv; \
- NSS_EXTRA_DEFS; \
- NSS_AVAILCHECK; \
- NSS_BUFCHECK; \
- /* check that we have a valid file descriptor */ \
- if (fp == NULL) \
- { \
- /* open a new stream and write the request */ \
- NSLCD_REQUEST(fp, action, /* no writefn */ ;); \
- } \
- /* prepare for buffer errors */ \
- tio_mark(fp); \
- /* read a response */ \
- READ_RESPONSE_CODE(fp); \
- retv = readfn; \
- /* check read result */ \
- if (retv == NSS_STATUS_TRYAGAIN) \
- { \
- /* if we have a full buffer try to reset the stream */ \
- if (tio_reset(fp)) \
- { \
- /* reset failed, we close and give up with a permanent error \
- because we cannot retry just the getent() call because it \
- may not be only the first entry that failed */ \
- tio_close(fp); \
- fp = NULL; \
- *errnop = EINVAL; \
- return NSS_STATUS_UNAVAIL; \
- } \
- } \
- else if (retv != NSS_STATUS_SUCCESS) \
- fp = NULL; /* file should be closed by now */ \
- return retv;
-
-/* This macro generates an endent() function body. This just closes
- the stream. */
-#define NSS_ENDENT(fp) \
- NSS_AVAILCHECK; \
- if (fp != NULL) \
- { \
- (void)tio_skipall(fp, SKIP_TIMEOUT); \
- (void)tio_close(fp); \
- fp = NULL; \
- } \
- return NSS_STATUS_SUCCESS;
-
-#endif /* not NSS__COMMON_H */
diff --git a/nss/ethers.c b/nss/ethers.c
deleted file mode 100644
index b094a66..0000000
--- a/nss/ethers.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- ethers.c - NSS lookup functions for ethers database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read an ethernet entry from the stream */
-static nss_status_t read_etherent(TFILE *fp, struct etherent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct etherent));
- READ_BUF_STRING(fp, result->e_name);
- READ(fp, &(result->e_addr), sizeof(uint8_t[6]));
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* map a hostname to the corresponding ethernet address */
-nss_status_t _nss_ldap_gethostton_r(const char *name,
- struct etherent *result, char *buffer,
- size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_ETHER_BYNAME,
- WRITE_STRING(fp, name),
- read_etherent(fp, result, buffer, buflen, errnop));
-}
-
-/* map an ethernet address to the corresponding hostname */
-nss_status_t _nss_ldap_getntohost_r(const struct ether_addr *addr,
- struct etherent *result, char *buffer,
- size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_ETHER_BYETHER,
- WRITE(fp, addr, sizeof(uint8_t[6])),
- read_etherent(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *etherentfp;
-
-/* open a connection to read all ether entries */
-nss_status_t _nss_ldap_setetherent(int UNUSED(stayopen))
-{
- NSS_SETENT(etherentfp);
-}
-
-/* read a single ethernet entry from the stream */
-nss_status_t _nss_ldap_getetherent_r(struct etherent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(etherentfp, NSLCD_ACTION_ETHER_ALL,
- read_etherent(etherentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened with setetherent() above */
-nss_status_t _nss_ldap_endetherent(void)
-{
- NSS_ENDENT(etherentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-/* we disable NSS_BUFCHECK because these functions do not use the buffer */
-#undef NSS_BUFCHECK
-#define NSS_BUFCHECK ;
-
-/* provide a fallback definition */
-#ifndef NSS_BUFLEN_ETHERS
-#define NSS_BUFLEN_ETHERS HOST_NAME_MAX
-#endif /* NSS_BUFLEN_ETHERS */
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *etherent2str(struct etherent *result, char *buffer,
- size_t buflen)
-{
- int res;
- res = snprintf(buffer, buflen, "%s %s", ether_ntoa(&result->e_addr),
- result->e_name);
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args, int wantname)
-{
- struct etherent result;
- char buffer[NSS_BUFLEN_ETHERS];
- nss_status_t retv;
- /* read the result entry from the stream */
- retv = read_etherent(fp, &result, buffer, sizeof(buffer), &args->erange);
- if (retv != NSS_STATUS_SUCCESS)
- return retv;
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
- /* try to return in string format if requested */
- if ((args->buf.buffer != NULL) && (args->buf.buflen > 0))
- {
- if (etherent2str(&result, args->buf.buffer, args->buf.buflen) == NULL)
- {
- args->erange = 1;
- return NSS_NOTFOUND;
- }
- args->returnval = args->buf.buffer;
- args->returnlen = strlen(args->returnval);
- return NSS_SUCCESS;
- }
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
- /* return the result entry */
- if (wantname)
- {
- /* we expect the buffer to have enough room for the name (buflen == 0) */
- strcpy(args->buf.buffer, result.e_name);
- args->returnval = args->buf.buffer;
- }
- else /* address */
- {
- memcpy(args->buf.result, &result.e_addr, sizeof(result.e_addr));
- args->returnval = args->buf.result;
- }
- return NSS_SUCCESS;
-}
-
-/* map a hostname to the corresponding ethernet address */
-static nss_status_t ethers_gethostton(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_ETHER_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, args, 0));
-}
-
-/* map an ethernet address to the corresponding hostname */
-static nss_status_t ethers_getntohost(nss_backend_t UNUSED(*be), void *args)
-{
- struct ether_addr *addr = (struct ether_addr *)(NSS_ARGS(args)->key.ether);
- NSS_GETONE(NSLCD_ACTION_ETHER_BYETHER,
- WRITE(fp, addr, sizeof(uint8_t[6])),
- read_result(fp, args, 1));
-}
-
-static nss_backend_op_t ethers_ops[] = {
- nss_ldap_destructor,
- ethers_gethostton,
- ethers_getntohost
-};
-
-nss_backend_t *_nss_ldap_ethers_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(ethers_ops, sizeof(ethers_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/exports.freebsd b/nss/exports.freebsd
deleted file mode 100644
index 765b8fe..0000000
--- a/nss/exports.freebsd
+++ /dev/null
@@ -1,19 +0,0 @@
-EXPORTED {
-
- # published NSS service functions
- global:
-
- # flag to enable or disable lookups
- _nss_ldap_enablelookups;
-
- # version information of NSS module
- _nss_ldap_version;
-
- # module init
- nss_module_register;
-
- # everything else should not be exported
- local:
- *;
-
-};
diff --git a/nss/exports.glibc b/nss/exports.glibc
deleted file mode 100644
index a22c256..0000000
--- a/nss/exports.glibc
+++ /dev/null
@@ -1,91 +0,0 @@
-EXPORTED {
-
- # published NSS service functions
- global:
-
- # flag to enable or disable lookups
- _nss_ldap_enablelookups;
-
- # version information of NSS module
- _nss_ldap_version;
-
- # aliases - mail aliases
- _nss_ldap_getaliasbyname_r;
- _nss_ldap_setaliasent;
- _nss_ldap_getaliasent_r;
- _nss_ldap_endaliasent;
-
- # ethers - ethernet numbers
- _nss_ldap_gethostton_r;
- _nss_ldap_getntohost_r;
- _nss_ldap_setetherent;
- _nss_ldap_getetherent_r;
- _nss_ldap_endetherent;
-
- # group - groups of users
- _nss_ldap_getgrnam_r;
- _nss_ldap_getgrgid_r;
- _nss_ldap_initgroups_dyn;
- _nss_ldap_setgrent;
- _nss_ldap_getgrent_r;
- _nss_ldap_endgrent;
-
- # hosts - host names and numbers
- _nss_ldap_gethostbyname_r;
- _nss_ldap_gethostbyname2_r;
- _nss_ldap_gethostbyaddr_r;
- _nss_ldap_sethostent;
- _nss_ldap_gethostent_r;
- _nss_ldap_endhostent;
-
- # netgroup - list of host and users
- _nss_ldap_setnetgrent;
- _nss_ldap_getnetgrent_r;
- _nss_ldap_endnetgrent;
-
- # networks - network names and numbers
- _nss_ldap_getnetbyname_r;
- _nss_ldap_getnetbyaddr_r;
- _nss_ldap_setnetent;
- _nss_ldap_getnetent_r;
- _nss_ldap_endnetent;
-
- # passwd - user database and passwords
- _nss_ldap_getpwnam_r;
- _nss_ldap_getpwuid_r;
- _nss_ldap_setpwent;
- _nss_ldap_getpwent_r;
- _nss_ldap_endpwent;
-
- # protocols - network protocols
- _nss_ldap_getprotobyname_r;
- _nss_ldap_getprotobynumber_r;
- _nss_ldap_setprotoent;
- _nss_ldap_getprotoent_r;
- _nss_ldap_endprotoent;
-
- # rpc - remote procedure call names and numbers
- _nss_ldap_getrpcbyname_r;
- _nss_ldap_getrpcbynumber_r;
- _nss_ldap_setrpcent;
- _nss_ldap_getrpcent_r;
- _nss_ldap_endrpcent;
-
- # services - network services
- _nss_ldap_getservbyname_r;
- _nss_ldap_getservbyport_r;
- _nss_ldap_setservent;
- _nss_ldap_getservent_r;
- _nss_ldap_endservent;
-
- # shadow - extended user information
- _nss_ldap_getspnam_r;
- _nss_ldap_setspent;
- _nss_ldap_getspent_r;
- _nss_ldap_endspent;
-
- # everything else should not be exported
- local:
- *;
-
-};
diff --git a/nss/exports.solaris b/nss/exports.solaris
deleted file mode 100644
index 5874a45..0000000
--- a/nss/exports.solaris
+++ /dev/null
@@ -1,28 +0,0 @@
-nss_ldap.so.1 {
-
- # published NSS service functions
- global:
-
- # flag to enable or disable lookups
- _nss_ldap_enablelookups;
-
- # version information of NSS module
- _nss_ldap_version;
-
- # published NSS service module constructors
- _nss_ldap_ethers_constr;
- _nss_ldap_group_constr;
- _nss_ldap_hosts_constr;
- _nss_ldap_networks_constr;
- _nss_ldap_protocols_constr;
- _nss_ldap_passwd_constr;
- _nss_ldap_rpc_constr;
- _nss_ldap_services_constr;
- _nss_ldap_shadow_constr;
- _nss_ldap_netgroup_constr;
-
- # everything else should not be exported
- local:
- *;
-
-};
diff --git a/nss/group.c b/nss/group.c
deleted file mode 100644
index 5945718..0000000
--- a/nss/group.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- group.c - NSS lookup functions for group database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read a single group entry from the stream */
-static nss_status_t read_group(TFILE *fp, struct group *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct group));
- READ_BUF_STRING(fp, result->gr_name);
- READ_BUF_STRING(fp, result->gr_passwd);
- READ_INT32(fp, result->gr_gid);
- READ_BUF_STRINGLIST(fp, result->gr_mem);
- return NSS_STATUS_SUCCESS;
-}
-
-/* read all group entries from the stream and add
- gids of these groups to the list */
-static nss_status_t read_gids(TFILE *fp, gid_t skipgroup, long int *start,
- long int *size, gid_t **groupsp,
- long int limit, int *errnop)
-{
- int32_t res = (int32_t)NSLCD_RESULT_BEGIN;
- int32_t tmpint32, tmp2int32, tmp3int32;
- gid_t gid;
-#ifdef NSS_FLAVOUR_GLIBC
- gid_t *newgroups;
- long int newsize;
-#endif /* NSS_FLAVOUR_GLIBC */
- /* loop over results */
- while (res == (int32_t)NSLCD_RESULT_BEGIN)
- {
- /* skip group name */
- SKIP_STRING(fp);
- /* skip passwd entry */
- SKIP_STRING(fp);
- /* read gid */
- READ_INT32(fp, gid);
- /* skip members */
- SKIP_STRINGLIST(fp);
- /* only add the group to the list if it is not the specified group */
- if (gid != skipgroup)
- {
-#ifdef NSS_FLAVOUR_GLIBC
- /* check if we reached the limit */
- if ((limit > 0) && (*start >= limit))
- return NSS_STATUS_TRYAGAIN;
- /* check if our buffer is large enough */
- if ((*start) >= (*size))
- {
- /* for some reason Glibc expects us to grow the array (completely
- different from all other NSS functions) */
- /* calculate new size */
- newsize = 2 * (*size);
- if ((limit > 0) && (*start >= limit))
- newsize = limit;
- /* allocate new memory */
- newgroups = realloc(*groupsp, newsize * sizeof(gid_t));
- if (newgroups == NULL)
- return NSS_STATUS_TRYAGAIN;
- *groupsp = newgroups;
- *size = newsize;
- }
-#endif /* NSS_FLAVOUR_GLIBC */
-#ifdef NSS_FLAVOUR_SOLARIS
- /* check if we reached the limit */
- if ((limit > 0) && (*start >= limit))
- {
- *errnop = 1; /* this is args->erange */
- return NSS_STATUS_NOTFOUND;
- }
-#endif /* NSS_FLAVOUR_SOLARIS */
- /* add gid to list */
- (*groupsp)[(*start)++] = gid;
- }
- /* read next response code (don't bail out on not success since we
- just want to build up a list) */
- READ_INT32(fp, res);
- }
- /* return the proper status code */
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a group entry by name */
-nss_status_t _nss_ldap_getgrnam_r(const char *name, struct group *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_GROUP_BYNAME,
- WRITE_STRING(fp, name),
- read_group(fp, result, buffer, buflen, errnop));
-}
-
-/* get a group entry by numeric gid */
-nss_status_t _nss_ldap_getgrgid_r(gid_t gid, struct group *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_GROUP_BYGID,
- WRITE_INT32(fp, gid),
- read_group(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *grentfp;
-
-/* start a request to read all groups */
-nss_status_t _nss_ldap_setgrent(int UNUSED(stayopen))
-{
- NSS_SETENT(grentfp);
-}
-
-/* read a single group from the stream */
-nss_status_t _nss_ldap_getgrent_r(struct group *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(grentfp, NSLCD_ACTION_GROUP_ALL,
- read_group(grentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened with setgrent() above */
-nss_status_t _nss_ldap_endgrent(void)
-{
- NSS_ENDENT(grentfp);
-}
-
-/* this function returns a list of groups, documentation for the
- interface is scarce (any pointers are welcome) but this is
- what is assumed the parameters mean:
-
- user IN - the user name to find groups for
- skipgroup IN - a group to not include in the list
- *start IN/OUT - where to write in the array, is incremented
- *size IN/OUT - the size of the supplied array (gid_t entries, not bytes)
- **groupsp IN/OUT - pointer to the array of returned groupids
- limit IN - the maxium size of the array
- *errnop OUT - for returning errno
-*/
-nss_status_t _nss_ldap_initgroups_dyn(const char *user, gid_t skipgroup,
- long int *start, long int *size,
- gid_t **groupsp, long int limit,
- int *errnop)
-{
-/* temporarily map the buffer and buflen names so the check in NSS_GETONE
- for validity of the buffer works (renaming the parameters may cause
- confusion) */
-#define buffer groupsp
-#define buflen *size
- NSS_GETONE(NSLCD_ACTION_GROUP_BYMEMBER,
- WRITE_STRING(fp, user),
- read_gids(fp, skipgroup, start, size, groupsp, limit, errnop));
-#undef buffer
-#undef buflen
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *group2str(struct group *result, char *buffer, size_t buflen)
-{
- int res, i;
- res = snprintf(buffer, buflen, "%s:%s:%d:", result->gr_name,
- result->gr_passwd, (int)result->gr_gid);
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- if (result->gr_mem)
- for (i = 0; result->gr_mem[i]; i++)
- {
- if (i)
- strlcat(buffer, ",", buflen);
- strlcat(buffer, result->gr_mem[i], buflen);
- }
- /* check if buffer overflowed */
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(group, &args->erange);
-}
-
-static nss_status_t group_getgrnam(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_GROUP_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, args));
-}
-
-static nss_status_t group_getgrgid(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_GROUP_BYGID,
- WRITE_INT32(fp, NSS_ARGS(args)->key.gid),
- read_result(fp, args));
-}
-
-static nss_status_t group_setgrent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t group_getgrent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_GROUP_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-static nss_status_t group_endgrent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t group_getgroupsbymember(nss_backend_t UNUSED(*be), void *args)
-{
- struct nss_groupsbymem *argp = (struct nss_groupsbymem *)args;
- long int start = (long int)argp->numgids;
- gid_t skipgroup = (start > 0) ? argp->gid_array[0] : (gid_t)-1;
- NSS_GETONE(NSLCD_ACTION_GROUP_BYMEMBER,
- WRITE_STRING(fp, argp->username),
- read_gids(fp, skipgroup, &start, NULL, (gid_t **)&argp->gid_array,
- argp->maxgids, &NSS_ARGS(args)->erange);
- argp->numgids = (int)start);
-}
-
-static nss_backend_op_t group_ops[] = {
- nss_ldap_destructor,
- group_endgrent,
- group_setgrent,
- group_getgrent,
- group_getgrnam,
- group_getgrgid,
- group_getgroupsbymember
-};
-
-nss_backend_t *_nss_ldap_group_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(group_ops, sizeof(group_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/hosts.c b/nss/hosts.c
deleted file mode 100644
index acbdb1e..0000000
--- a/nss/hosts.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- hosts.c - NSS lookup functions for hosts database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* Redefine some ERROR_OUT macros as we also want to set h_errnop. */
-
-#undef ERROR_OUT_OPENERROR
-#define ERROR_OUT_OPENERROR \
- *errnop = ENOENT; \
- *h_errnop = HOST_NOT_FOUND; \
- return (errno == EAGAIN) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
-
-#undef ERROR_OUT_READERROR
-#define ERROR_OUT_READERROR(fp) \
- (void)tio_close(fp); \
- fp = NULL; \
- *errnop = ENOENT; \
- *h_errnop = NO_RECOVERY; \
- return NSS_STATUS_UNAVAIL;
-
-#undef ERROR_OUT_BUFERROR
-#define ERROR_OUT_BUFERROR(fp) \
- *errnop = ERANGE; \
- *h_errnop = NETDB_INTERNAL; \
- return NSS_STATUS_TRYAGAIN;
-
-#undef ERROR_OUT_WRITEERROR
-#define ERROR_OUT_WRITEERROR(fp) \
- ERROR_OUT_READERROR(fp)
-
-/* read a single host entry from the stream, filtering on the
- specified address family, result is stored in result
- it will an empty entry if no addresses in the address family
- were available */
-static nss_status_t read_one_hostent(TFILE *fp, struct hostent *result,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop, int af)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- int32_t numaddr;
- int i;
- int readaf;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct hostent));
- /* read the host entry */
- READ_BUF_STRING(fp, result->h_name);
- READ_BUF_STRINGLIST(fp, result->h_aliases);
- result->h_addrtype = af;
- result->h_length = 0;
- /* read number of addresses to follow */
- READ_INT32(fp, numaddr);
- /* allocate memory for array */
- /* Note: this may allocate too much memory (e.g. also for address records
- of other address families) but this is a simple way to do it */
- BUF_ALLOC(fp, result->h_addr_list, char *, numaddr + 1);
- /* go through the address list and filter on af */
- i = 0;
- while (--numaddr >= 0)
- {
- /* read address family and size */
- READ_INT32(fp, readaf);
- READ_INT32(fp, tmp2int32);
- if (readaf == af)
- {
- /* read the address */
- result->h_length = tmp2int32;
- READ_BUF(fp, result->h_addr_list[i++], tmp2int32);
- }
- else
- {
- SKIP(fp, tmpint32);
- }
- }
- /* null-terminate address list */
- result->h_addr_list[i] = NULL;
- return NSS_STATUS_SUCCESS;
-}
-
-/* this is a wrapper around read_one_hostent() that checks whether the read
- address list is empty and tries the next result if available if
- retry is set */
-static nss_status_t read_hostent(TFILE *fp, struct hostent *result,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop, int af, int retry)
-{
- int32_t tmpint32;
- nss_status_t retv;
- /* check until we read an non-empty entry, error or */
- while (1)
- {
- retv = read_one_hostent(fp, result, buffer, buflen, errnop, h_errnop, af);
- /* check result */
- if ((retv != NSS_STATUS_SUCCESS) || (result->h_addr_list[0] != NULL))
- return retv;
- /* error of if we are not retrying */
- if (!retry)
- {
- *errnop = ENOENT;
- *h_errnop = NO_ADDRESS;
- (void)tio_close(fp);
- return NSS_STATUS_NOTFOUND;
- }
- /* skip to the next entry */
- READ_RESPONSE_CODE(fp);
- }
-}
-
-/* write an address value */
-#define WRITE_ADDRESS(fp, af, len, addr) \
- WRITE_INT32(fp, af); \
- WRITE_INT32(fp, len); \
- WRITE(fp, addr, len);
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* this function looks up a single host entry and returns all the addresses
- associated with the host in a single address familiy
- name - IN - hostname to lookup
- af - IN - address familty to present results for
- result - OUT - entry found
- buffer,buflen - OUT - buffer to store allocated stuff on
- errnop,h_errnop - OUT - for reporting errors */
-nss_status_t _nss_ldap_gethostbyname2_r(const char *name, int af,
- struct hostent *result, char *buffer,
- size_t buflen, int *errnop,
- int *h_errnop)
-{
- NSS_GETONE(NSLCD_ACTION_HOST_BYNAME,
- WRITE_STRING(fp, name),
- read_hostent(fp, result, buffer, buflen, errnop, h_errnop, af, 0));
-}
-
-/* this function just calls the gethostbyname2() variant with the address
- familiy set */
-nss_status_t _nss_ldap_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- size_t buflen, int *errnop,
- int *h_errnop)
-{
- return _nss_ldap_gethostbyname2_r(name, AF_INET, result, buffer, buflen,
- errnop, h_errnop);
-}
-
-/* this function looks up a single host entry and returns all the addresses
- associated with the host in a single address familiy
- addr - IN - the address to look up
- len - IN - the size of the addr struct
- af - IN - address familty the address is specified as
- result - OUT - entry found
- buffer,buflen - OUT - buffer to store allocated stuff on
- errnop,h_errnop - OUT - for reporting errors */
-nss_status_t _nss_ldap_gethostbyaddr_r(const void *addr, socklen_t len,
- int af, struct hostent *result,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop)
-{
- NSS_GETONE(NSLCD_ACTION_HOST_BYADDR,
- WRITE_ADDRESS(fp, af, len, addr),
- read_hostent(fp, result, buffer, buflen, errnop, h_errnop, af, 0));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *hostentfp;
-
-nss_status_t _nss_ldap_sethostent(int UNUSED(stayopen))
-{
- NSS_SETENT(hostentfp);
-}
-
-/* this function only returns addresses of the AF_INET address family */
-nss_status_t _nss_ldap_gethostent_r(struct hostent *result,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop)
-{
- NSS_GETENT(hostentfp, NSLCD_ACTION_HOST_ALL,
- read_hostent(hostentfp, result, buffer, buflen, errnop, h_errnop,
- AF_INET, 1));
-}
-
-/* close the stream opened with sethostent() above */
-nss_status_t _nss_ldap_endhostent(void)
-{
- NSS_ENDENT(hostentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *hostent2str(struct hostent *result, char *buffer, size_t buflen)
-{
- int i, j;
- /* build the formatted string, one line per address */
- buffer[0] = '\0';
- if (result->h_addr_list != NULL)
- {
- for (i = 0; result->h_addr_list[i]; i++)
- {
- if (i > 0)
- strlcat(buffer, "\n", buflen);
- /* snprintf writes a terminating \0 on Solaris */
- snprintf(buffer, buflen - strlen(buffer) - 1,
- "%s %s",
- inet_ntoa(*((struct in_addr *)result->h_addr_list[i])),
- result->h_name);
- /* add aliases for first line only */
- if ((i == 0) && (result->h_aliases))
- {
- for (j = 0; result->h_aliases[j]; j++)
- {
- strlcat(buffer, " ", buflen);
- strlcat(buffer, result->h_aliases[j], buflen);
- }
- }
- }
- }
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, int af, int retry,
- nss_XbyY_args_t *args)
-{
- READ_RESULT(hostent, &args->erange, &args->h_errno, af, retry);
-}
-
-/* hack to set the correct h_errno */
-#define h_errnop &(NSS_ARGS(args)->h_errno)
-
-static nss_status_t hosts_gethostbyname(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_HOST_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, AF_INET, 0, args));
-}
-
-static nss_status_t hosts_gethostbyaddr(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_HOST_BYADDR,
- WRITE_ADDRESS(fp, NSS_ARGS(args)->key.hostaddr.type,
- NSS_ARGS(args)->key.hostaddr.len,
- NSS_ARGS(args)->key.hostaddr.addr),
- read_result(fp, NSS_ARGS(args)->key.hostaddr.type, 0, args));
-}
-
-static nss_status_t hosts_sethostent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t hosts_gethostent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_HOST_ALL,
- read_result(LDAP_BE(be)->fp, AF_INET, 1, args));
-}
-
-static nss_status_t hosts_endhostent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t hosts_ops[] = {
- nss_ldap_destructor,
- hosts_endhostent,
- hosts_sethostent,
- hosts_gethostent,
- hosts_gethostbyname,
- hosts_gethostbyaddr
-};
-
-nss_backend_t *_nss_ldap_hosts_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(hosts_ops, sizeof(hosts_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/netgroup.c b/nss/netgroup.c
deleted file mode 100644
index 81eb33d..0000000
--- a/nss/netgroup.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- netgroup.c - NSS lookup functions for netgroup entries
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006-2014 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-#include "common/set.h"
-
-/* function for reading a single result entry */
-static nss_status_t read_netgrent_line(TFILE *fp, struct __netgrent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32;
- int type;
- size_t bufptr = 0;
- /* read netgroup type */
- READ_INT32(fp, type);
- if (type == NSLCD_NETGROUP_TYPE_NETGROUP)
- {
- /* the response is a reference to another netgroup */
- result->type = group_val;
- READ_BUF_STRING(fp, result->val.group);
- return NSS_STATUS_SUCCESS;
- }
- else if (type == NSLCD_NETGROUP_TYPE_TRIPLE)
- {
- /* the response is a host/user/domain triple */
- result->type = triple_val;
- /* read host and revert to NULL on empty string */
- READ_BUF_STRING(fp, result->val.triple.host);
-#ifdef NSS_FLAVOUR_GLIBC
- if (result->val.triple.host[0] == '\0')
- {
- result->val.triple.host = NULL;
- bufptr--; /* free unused space */
- }
-#endif /* NSS_FLAVOUR_GLIBC */
- /* read user and revert to NULL on empty string */
- READ_BUF_STRING(fp, result->val.triple.user);
-#ifdef NSS_FLAVOUR_GLIBC
- if (result->val.triple.user[0] == '\0')
- {
- result->val.triple.user = NULL;
- bufptr--; /* free unused space */
- }
-#endif /* NSS_FLAVOUR_GLIBC */
- /* read domain and revert to NULL on empty string */
- READ_BUF_STRING(fp, result->val.triple.domain);
-#ifdef NSS_FLAVOUR_GLIBC
- if (result->val.triple.domain[0] == '\0')
- {
- result->val.triple.domain = NULL;
- bufptr--; /* free unused space */
- }
-#endif /* NSS_FLAVOUR_GLIBC */
- return NSS_STATUS_SUCCESS;
- }
- else if (type == NSLCD_NETGROUP_TYPE_END)
- /* make _nss_ldap_getnetgrent_r() indicate the end of the netgroup */
- return NSS_STATUS_RETURN;
- /* we got something unexpected */
- ERROR_OUT_NOSUCCESS(fp);
- return NSS_STATUS_UNAVAIL;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *netgrentfp;
-
-/* start a request to get a netgroup by name */
-nss_status_t _nss_ldap_setnetgrent(const char *group,
- struct __netgrent UNUSED(*result))
-{
- /* we cannot use NSS_SETENT() here because we have a parameter that is only
- available in this function */
- int32_t tmpint32;
- int errnocp;
- int *errnop = &errnocp;
- NSS_EXTRA_DEFS
- NSS_AVAILCHECK;
- /* check parameter */
- if ((group == NULL) || (group[0] == '\0'))
- return NSS_STATUS_UNAVAIL;
- /* open a new stream and write the request */
- NSLCD_REQUEST(netgrentfp, NSLCD_ACTION_NETGROUP_BYNAME,
- WRITE_STRING(netgrentfp, group));
- /* read response code */
- READ_RESPONSE_CODE(netgrentfp);
- SKIP_STRING(netgrentfp); /* netgroup name */
- return NSS_STATUS_SUCCESS;
-}
-
-/* get a single netgroup tuple from the stream */
-nss_status_t _nss_ldap_getnetgrent_r(struct __netgrent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- nss_status_t retv;
- NSS_EXTRA_DEFS;
- NSS_AVAILCHECK;
- NSS_BUFCHECK;
- /* check that we have a valid file descriptor */
- if (netgrentfp == NULL)
- return NSS_STATUS_UNAVAIL;
- /* prepare for buffer errors */
- tio_mark(netgrentfp);
- /* read a response */
- retv = read_netgrent_line(netgrentfp, result, buffer, buflen, errnop);
- /* check read result */
- if (retv == NSS_STATUS_TRYAGAIN)
- {
- /* if we have a full buffer try to reset the stream */
- if (tio_reset(netgrentfp))
- {
- /* reset failed, we close and give up with a permanent error
- because we cannot retry just the getent() call because it
- may not be only the first entry that failed */
- tio_close(netgrentfp);
- netgrentfp = NULL;
- *errnop = EINVAL;
- return NSS_STATUS_UNAVAIL;
- }
- }
- else if ((retv != NSS_STATUS_SUCCESS) && (retv != NSS_STATUS_RETURN))
- netgrentfp = NULL; /* file should be closed by now */
- return retv;
-}
-
-/* close the stream opened with setnetgrent() above */
-nss_status_t _nss_ldap_endnetgrent(struct __netgrent UNUSED(*result))
-{
- NSS_ENDENT(netgrentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-/* this is the custom backend structure for the {set,get,end}ent() functions */
-struct setnetgrent_backend {
- nss_backend_op_t *ops; /* function-pointer table */
- int n_ops; /* number of function pointers */
- TFILE *fp; /* the file pointer for {set,get,end}ent() functions */
- SET *seen_groups; /* netgroups seen, for loop detection */
- SET *unseen_groups; /* netgroups that need to be chased */
-};
-
-/* easy way to get sets from back-end */
-#define NETGROUP_BE(be) ((struct setnetgrent_backend*)(be))
-
-/* access arguments */
-#define SETNETGRENT_ARGS(args) ((struct nss_setnetgrent_args *)(args))
-#define GETNETGRENT_ARGS(args) ((struct nss_getnetgrent_args *)(args))
-
-/* return a netgroup that has not been traversed (the caller should use
- free() to free it) */
-static char *find_unseen_netgroup(struct setnetgrent_backend *be)
-{
- char *group;
- while (1)
- {
- group = set_pop(be->unseen_groups);
- if (group == NULL)
- return NULL;
- if (!set_contains(be->seen_groups, group))
- return group;
- free(group);
- }
-}
-
-static nss_status_t start_netgroup_request(struct setnetgrent_backend *be,
- const char *group)
-{
- /* we cannot use NSS_SETENT() here because we have a parameter that is only
- available in this function */
- int32_t tmpint32;
- int *errnop = &errno;
- /* check parameter */
- if ((group == NULL) || (group[0] == '\0'))
- return NSS_STATUS_UNAVAIL;
- set_add(be->seen_groups, group);
- /* open a new stream and write the request */
- NSLCD_REQUEST(NETGROUP_BE(be)->fp, NSLCD_ACTION_NETGROUP_BYNAME,
- WRITE_STRING(NETGROUP_BE(be)->fp, group));
- /* read response code */
- READ_RESPONSE_CODE(NETGROUP_BE(be)->fp);
- SKIP_STRING(NETGROUP_BE(be)->fp); /* netgroup name */
- return NSS_STATUS_SUCCESS;
-}
-
-static nss_status_t netgroup_setnetgrent_setnetgrent(nss_backend_t UNUSED(*be),
- void UNUSED(*args))
-{
- return NSS_STATUS_SUCCESS;
-}
-
-static nss_status_t netgroup_setnetgrent_getnetgrent(nss_backend_t *be,
- void *args)
-{
- struct __netgrent result;
- nss_status_t retv;
- /* check that we have a valid file descriptor */
- if (NETGROUP_BE(be)->fp == NULL)
- return NSS_STATUS_UNAVAIL;
- /* go over the result lines */
- while (1)
- {
- /* prepare for buffer errors */
- tio_mark(NETGROUP_BE(be)->fp);
- /* read single line from the netgroup information */
- retv = read_netgrent_line(NETGROUP_BE(be)->fp, &result, GETNETGRENT_ARGS(args)->buffer,
- GETNETGRENT_ARGS(args)->buflen, &errno);
- /* check read result */
- if ((retv == NSS_STATUS_SUCCESS) && (result.type == group_val))
- {
- /* a netgroup nested within the current netgroup */
- set_add(NETGROUP_BE(be)->unseen_groups, result.val.group);
- }
- else if ((retv == NSS_STATUS_SUCCESS) && (result.type == triple_val))
- {
- /* a netgroup line we can return */
- GETNETGRENT_ARGS(args)->status = NSS_NETGR_FOUND;
- GETNETGRENT_ARGS(args)->retp[NSS_NETGR_MACHINE] = result.val.triple.host;
- GETNETGRENT_ARGS(args)->retp[NSS_NETGR_USER] = result.val.triple.user;
- GETNETGRENT_ARGS(args)->retp[NSS_NETGR_DOMAIN] = result.val.triple.domain;
- return NSS_STATUS_SUCCESS;
- }
- else if (retv == NSS_STATUS_TRYAGAIN)
- {
- /* we have a full buffer, try to reset the stream */
- if (tio_reset(NETGROUP_BE(be)->fp))
- {
- /* reset failed, we close and give up with a permanent error
- because we cannot retry just the getent() call because it
- may not be only the first entry that failed */
- tio_close(NETGROUP_BE(be)->fp);
- NETGROUP_BE(be)->fp = NULL;
- return NSS_STATUS_UNAVAIL;
- }
- GETNETGRENT_ARGS(args)->status = NSS_NETGR_NOMEM;
- return NSS_STATUS_TRYAGAIN;
- }
- else if (retv == NSS_STATUS_RETURN)
- {
- /* done with the current netgroup */
- tio_close(NETGROUP_BE(be)->fp);
- NETGROUP_BE(be)->fp = NULL;
- /* explore nested netgroups, if any */
- while (retv != NSS_STATUS_SUCCESS)
- {
- /* find a nested netgroup to pursue further */
- char *group = find_unseen_netgroup(NETGROUP_BE(be));
- if (group == NULL)
- {
- /* no more netgroups to explore */
- GETNETGRENT_ARGS(args)->status = NSS_NETGR_NO;
- return NSS_STATUS_SUCCESS;
- }
- /* start a new search with this netgroup */
- retv = start_netgroup_request(NETGROUP_BE(be), group);
- free(group);
- }
- }
- else
- {
- /* some error occurred when reading the line (stream should be closed by now) */
- NETGROUP_BE(be)->fp = NULL;
- GETNETGRENT_ARGS(args)->status = NSS_NETGR_NO;
- return retv;
- }
- }
-}
-
-static nss_status_t netgroup_setnetgrent_endnetgrent(nss_backend_t
- UNUSED(*be),
- void UNUSED(*args))
-{
- NSS_ENDENT(NETGROUP_BE(be)->fp);
-}
-
-static nss_status_t netgroup_setnetgrent_destructor(nss_backend_t *be,
- void *UNUSED(args))
-{
- struct setnetgrent_backend *ngbe = (struct setnetgrent_backend *)be;
- if (ngbe->fp != NULL)
- (void)tio_close(ngbe->fp);
- set_free(ngbe->seen_groups);
- set_free(ngbe->unseen_groups);
- free(ngbe);
- return NSS_STATUS_SUCCESS;
-}
-
-static nss_backend_op_t netgroup_setnetgrent_ops[] = {
- netgroup_setnetgrent_destructor,
- netgroup_setnetgrent_endnetgrent,
- netgroup_setnetgrent_setnetgrent,
- netgroup_setnetgrent_getnetgrent,
-};
-
-static nss_status_t netgroup_setnetgrent_constructor(nss_backend_t UNUSED(*be),
- void *args)
-{
- struct setnetgrent_backend *ngbe;
- nss_status_t retv;
- NSS_AVAILCHECK;
- SETNETGRENT_ARGS(args)->iterator = NULL; /* initialize */
- /* allocate a back-end specific to this request */
- ngbe = (struct setnetgrent_backend *)malloc(sizeof(struct setnetgrent_backend));
- if (ngbe == NULL)
- return NSS_STATUS_UNAVAIL;
- ngbe->ops = netgroup_setnetgrent_ops;
- ngbe->n_ops = sizeof(netgroup_setnetgrent_ops) / sizeof(nss_backend_op_t);
- ngbe->fp = NULL;
- ngbe->seen_groups = set_new();
- ngbe->unseen_groups = set_new();
- /* start the first search */
- retv = start_netgroup_request(ngbe, SETNETGRENT_ARGS(args)->netgroup);
- if (retv != NSS_STATUS_SUCCESS)
- {
- netgroup_setnetgrent_destructor((nss_backend_t *)ngbe, args);
- return retv;
- }
- /* return the new back-end */
- SETNETGRENT_ARGS(args)->iterator = (nss_backend_t *)ngbe;
- return NSS_STATUS_SUCCESS;
-}
-
-static nss_backend_op_t netgroup_ops[] = {
- nss_ldap_destructor,
- NULL,
- NULL,
- NULL,
- NULL, /* TODO:_nss_ldap_netgr_in */
- netgroup_setnetgrent_constructor
-};
-
-nss_backend_t *_nss_ldap_netgroup_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(netgroup_ops, sizeof(netgroup_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/networks.c b/nss/networks.c
deleted file mode 100644
index 3ffea52..0000000
--- a/nss/networks.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- networks.c - NSS lookup functions for networks database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* Redefine some ERROR_OUT macros as we also want to set h_errnop. */
-
-#undef ERROR_OUT_OPENERROR
-#define ERROR_OUT_OPENERROR \
- *errnop = ENOENT; \
- *h_errnop = HOST_NOT_FOUND; \
- return (errno == EAGAIN) ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
-
-#undef ERROR_OUT_READERROR
-#define ERROR_OUT_READERROR(fp) \
- (void)tio_close(fp); \
- fp = NULL; \
- *errnop = ENOENT; \
- *h_errnop = NO_RECOVERY; \
- return NSS_STATUS_UNAVAIL;
-
-#undef ERROR_OUT_BUFERROR
-#define ERROR_OUT_BUFERROR(fp) \
- *errnop = ERANGE; \
- *h_errnop = NETDB_INTERNAL; \
- return NSS_STATUS_TRYAGAIN;
-
-#undef ERROR_OUT_WRITEERROR
-#define ERROR_OUT_WRITEERROR(fp) \
- ERROR_OUT_READERROR(fp)
-
-/* read a single network entry from the stream, ignoring entries
- that are not AF_INET (IPv4), result is stored in result */
-static nss_status_t read_netent(TFILE *fp, struct netent *result,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- int32_t numaddr;
- int readaf;
- size_t bufptr = 0;
- nss_status_t retv = NSS_STATUS_NOTFOUND;
- memset(result, 0, sizeof(struct netent));
- /* read the network entry */
- READ_BUF_STRING(fp, result->n_name);
- READ_BUF_STRINGLIST(fp, result->n_aliases);
- result->n_addrtype = AF_INET;
- /* read number of addresses to follow */
- READ_INT32(fp, numaddr);
- /* go through the address list and filter on af */
- while (--numaddr >= 0)
- {
- /* read address family and size */
- READ_INT32(fp, readaf);
- READ_INT32(fp, tmp2int32); /* address length */
- if ((readaf == AF_INET) && (tmp2int32 == 4))
- {
- /* read address and translate to host byte order */
- READ_INT32(fp, result->n_net);
- /* signal that we've read a proper entry */
- retv = NSS_STATUS_SUCCESS;
- /* don't return here to not upset the stream */
- }
- else
- {
- /* skip unsupported address families */
- SKIP(fp, tmpint32);
- }
- }
- return retv;
-}
-
-/* write an address value */
-/* version 2.10 of glibc changed the address from network to host order
- (changelog entry 2009-07-01) */
-#define WRITE_ADDRESS(fp, addr) \
- WRITE_INT32(fp, AF_INET); \
- WRITE_INT32(fp, 4); \
- WRITE_INT32(fp, addr);
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a network entry by name */
-nss_status_t _nss_ldap_getnetbyname_r(const char *name,
- struct netent *result, char *buffer,
- size_t buflen, int *errnop,
- int *h_errnop)
-{
- NSS_GETONE(NSLCD_ACTION_NETWORK_BYNAME,
- WRITE_STRING(fp, name),
- read_netent(fp, result, buffer, buflen, errnop, h_errnop));
-}
-
-/* Note: the af parameter is ignored and is assumed to be AF_INET */
-/* TODO: implement handling of af parameter */
-nss_status_t _nss_ldap_getnetbyaddr_r(uint32_t addr, int UNUSED(af),
- struct netent *result, char *buffer,
- size_t buflen, int *errnop,
- int *h_errnop)
-{
- NSS_GETONE(NSLCD_ACTION_NETWORK_BYADDR,
- WRITE_ADDRESS(fp, addr),
- read_netent(fp, result, buffer, buflen, errnop, h_errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *netentfp;
-
-/* start a request to read all networks */
-nss_status_t _nss_ldap_setnetent(int UNUSED(stayopen))
-{
- NSS_SETENT(netentfp);
-}
-
-/* get a single network entry from the stream */
-nss_status_t _nss_ldap_getnetent_r(struct netent *result,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop)
-{
- NSS_GETENT(netentfp, NSLCD_ACTION_NETWORK_ALL,
- read_netent(netentfp, result, buffer, buflen, errnop, h_errnop));
-}
-
-/* close the stream opened by setnetent() above */
-nss_status_t _nss_ldap_endnetent(void)
-{
- NSS_ENDENT(netentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *netent2str(struct netent *result, char *buffer, size_t buflen)
-{
- int i, res;
- struct in_addr priv_in_addr;
- priv_in_addr.s_addr = result->n_net;
- res = snprintf(buffer, buflen, "%s %s", result->n_name, inet_ntoa(priv_in_addr));
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- if (result->n_aliases)
- for (i = 0; result->n_aliases[i]; i++)
- {
- strlcat(buffer, " ", buflen);
- strlcat(buffer, result->n_aliases[i], buflen);
- }
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(netent, &args->erange, &args->h_errno);
-}
-
-/* more of a dirty hack */
-#define h_errnop (&(NSS_ARGS(args)->h_errno))
-
-static nss_status_t networks_getnetbyname(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_NETWORK_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, args));
-}
-
-static nss_status_t networks_getnetbyaddr(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_NETWORK_BYADDR,
- WRITE_ADDRESS(fp, NSS_ARGS(args)->key.netaddr.net),
- read_result(fp, args));
-}
-
-static nss_status_t networks_setnetent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t networks_getnetent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_NETWORK_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-static nss_status_t networks_endnetent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t networks_ops[] = {
- nss_ldap_destructor,
- networks_endnetent,
- networks_setnetent,
- networks_getnetent,
- networks_getnetbyname,
- networks_getnetbyaddr
-};
-
-nss_backend_t *_nss_ldap_networks_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(networks_ops, sizeof(networks_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/passwd.c b/nss/passwd.c
deleted file mode 100644
index c17d8cc..0000000
--- a/nss/passwd.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- passwd.c - NSS lookup functions for passwd database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read a passwd entry from the stream */
-static nss_status_t read_passwd(TFILE *fp, struct passwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct passwd));
- READ_BUF_STRING(fp, result->pw_name);
- READ_BUF_STRING(fp, result->pw_passwd);
- READ_INT32(fp, result->pw_uid);
- READ_INT32(fp, result->pw_gid);
- READ_BUF_STRING(fp, result->pw_gecos);
- READ_BUF_STRING(fp, result->pw_dir);
- READ_BUF_STRING(fp, result->pw_shell);
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- /* set the user access class to an empty string */
- result->pw_class = result->pw_name + strlen(result->pw_name);
-#endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a single passwd entry by name */
-nss_status_t _nss_ldap_getpwnam_r(const char *name, struct passwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_PASSWD_BYNAME,
- WRITE_STRING(fp, name),
- read_passwd(fp, result, buffer, buflen, errnop));
-}
-
-/* get a single passwd entry by uid */
-nss_status_t _nss_ldap_getpwuid_r(uid_t uid, struct passwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_PASSWD_BYUID,
- WRITE_INT32(fp, uid),
- read_passwd(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *pwentfp;
-
-/* open a connection to read all passwd entries */
-nss_status_t _nss_ldap_setpwent(int UNUSED(stayopen))
-{
- NSS_SETENT(pwentfp);
-}
-
-/* read password data from an opened stream */
-nss_status_t _nss_ldap_getpwent_r(struct passwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(pwentfp, NSLCD_ACTION_PASSWD_ALL,
- read_passwd(pwentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened with setpwent() above */
-nss_status_t _nss_ldap_endpwent(void)
-{
- NSS_ENDENT(pwentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *passwd2str(struct passwd *result, char *buffer, size_t buflen)
-{
- int res;
- res = snprintf(buffer, buflen, "%s:%s:%d:%d:%s:%s:%s",
- result->pw_name, result->pw_passwd, (int)result->pw_uid,
- (int)result->pw_gid, result->pw_gecos, result->pw_dir,
- result->pw_shell);
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(passwd, &args->erange);
-}
-
-static nss_status_t passwd_getpwnam(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_PASSWD_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, args));
-}
-
-static nss_status_t passwd_getpwuid(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_PASSWD_BYUID,
- WRITE_INT32(fp, NSS_ARGS(args)->key.uid),
- read_result(fp, args));
-}
-
-/* open a connection to the nslcd and write the request */
-static nss_status_t passwd_setpwent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-/* read password data from an opened stream */
-static nss_status_t passwd_getpwent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_PASSWD_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-/* close the stream opened with setpwent() above */
-static nss_status_t passwd_endpwent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t passwd_ops[] = {
- nss_ldap_destructor,
- passwd_endpwent,
- passwd_setpwent,
- passwd_getpwent,
- passwd_getpwnam,
- passwd_getpwuid
-};
-
-nss_backend_t *_nss_ldap_passwd_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(passwd_ops, sizeof(passwd_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/protocols.c b/nss/protocols.c
deleted file mode 100644
index 4944dff..0000000
--- a/nss/protocols.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- protocols.c - NSS lookup functions for protocol database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read a single protocol entry from the stream */
-static nss_status_t read_protoent(TFILE *fp, struct protoent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct protoent));
- READ_BUF_STRING(fp, result->p_name);
- READ_BUF_STRINGLIST(fp, result->p_aliases);
- READ_INT32(fp, result->p_proto);
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a protocol entry by name */
-nss_status_t _nss_ldap_getprotobyname_r(const char *name,
- struct protoent *result,
- char *buffer, size_t buflen,
- int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_PROTOCOL_BYNAME,
- WRITE_STRING(fp, name),
- read_protoent(fp, result, buffer, buflen, errnop));
-}
-
-/* get a protocol entry by number */
-nss_status_t _nss_ldap_getprotobynumber_r(int number, struct protoent *result,
- char *buffer, size_t buflen,
- int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_PROTOCOL_BYNUMBER,
- WRITE_INT32(fp, number),
- read_protoent(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *protoentfp;
-
-/* start a request to read all protocol entries */
-nss_status_t _nss_ldap_setprotoent(int UNUSED(stayopen))
-{
- NSS_SETENT(protoentfp);
-}
-
-/* get a single protocol entry */
-nss_status_t _nss_ldap_getprotoent_r(struct protoent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(protoentfp, NSLCD_ACTION_PROTOCOL_ALL,
- read_protoent(protoentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened by setprotoent() above */
-nss_status_t _nss_ldap_endprotoent(void)
-{
- NSS_ENDENT(protoentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *protoent2str(struct protoent *result, char *buffer, size_t buflen)
-{
- int res, i;
- res = snprintf(buffer, buflen, "%s\t\t%d", result->p_name, result->p_proto);
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- if (result->p_aliases)
- for (i = 0; result->p_aliases[i]; i++)
- {
- strlcat(buffer, " ", buflen);
- strlcat(buffer, result->p_aliases[i], buflen);
- }
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(protoent, &args->erange);
-}
-
-static nss_status_t protocols_getprotobyname(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_PROTOCOL_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, args));
-}
-
-static nss_status_t protocols_getprotobynumber(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_PROTOCOL_BYNUMBER,
- WRITE_INT32(fp, NSS_ARGS(args)->key.number),
- read_result(fp, args));
-}
-
-static nss_status_t protocols_setprotoent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t protocols_getprotoent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_PROTOCOL_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-static nss_status_t protocols_endprotoent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t protocols_ops[] = {
- nss_ldap_destructor,
- protocols_endprotoent,
- protocols_setprotoent,
- protocols_getprotoent,
- protocols_getprotobyname,
- protocols_getprotobynumber
-};
-
-nss_backend_t *_nss_ldap_protocols_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(protocols_ops, sizeof(protocols_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/prototypes.h b/nss/prototypes.h
deleted file mode 100644
index 0f7a6a9..0000000
--- a/nss/prototypes.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- prototypes.h - all functions exported by the NSS library
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2008, 2010, 2011, 2012 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 NSS__PROTOTYPES_H
-#define NSS__PROTOTYPES_H 1
-
-#include "compat/nss_compat.h"
-
-/* flag to gloabally disable lookups (all _nss_ldap_*() functions will return
- NSS_STATUS_UNAVAIL */
-extern int _nss_ldap_enablelookups;
-
-#ifdef NSS_FLAVOUR_FREEBSD
-
-/* for FreeBSD we want the GlibC prototypes and functions to be built
- (we provide some wrappers in bsdnss.c) */
-#define NSS_FLAVOUR_GLIBC 1
-
-/* FreeBSD specific register function */
-ns_mtab *nss_module_register(const char *source, unsigned int *mtabsize,
- nss_module_unregister_fn *unreg);
-
-#endif /* NSS_FLAVOUR_FREEBSD */
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/*
- These are prototypes for functions exported from the ldap NSS module.
- For more complete definitions of these functions check the GLIBC
- documentation.
-
- Other services than those mentioned here are currently not implemented.
-
- These definitions partially came from examining the GLIBC source code
- as no complete documentation of the NSS interface is available.
- This however is a useful pointer:
- http://www.gnu.org/software/libc/manual/html_node/Name-Service-Switch.html
-*/
-
-/* aliases - mail aliases */
-nss_status_t _nss_ldap_getaliasbyname_r(const char *name, struct aliasent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setaliasent(void);
-nss_status_t _nss_ldap_getaliasent_r(struct aliasent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endaliasent(void);
-
-/* ethers - ethernet numbers */
-nss_status_t _nss_ldap_gethostton_r(const char *name, struct etherent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_getntohost_r(const struct ether_addr *addr, struct etherent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setetherent(int stayopen);
-nss_status_t _nss_ldap_getetherent_r(struct etherent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endetherent(void);
-
-/* group - groups of users */
-nss_status_t _nss_ldap_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_initgroups_dyn(const char *user, gid_t skipgroup, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop);
-nss_status_t _nss_ldap_setgrent(int stayopen);
-nss_status_t _nss_ldap_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endgrent(void);
-
-/* hosts - host names and numbers */
-nss_status_t _nss_ldap_gethostbyname_r(const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_gethostbyname2_r(const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_sethostent(int stayopen);
-nss_status_t _nss_ldap_gethostent_r(struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_endhostent(void);
-
-/* netgroup - list of host and users */
-nss_status_t _nss_ldap_setnetgrent(const char *group, struct __netgrent *result);
-nss_status_t _nss_ldap_getnetgrent_r(struct __netgrent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endnetgrent(struct __netgrent *result);
-
-/* networks - network names and numbers */
-nss_status_t _nss_ldap_getnetbyname_r(const char *name, struct netent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_getnetbyaddr_r(uint32_t addr, int af, struct netent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_setnetent(int stayopen);
-nss_status_t _nss_ldap_getnetent_r(struct netent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop);
-nss_status_t _nss_ldap_endnetent(void);
-
-/* passwd - user database and passwords */
-nss_status_t _nss_ldap_getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setpwent(int stayopen);
-nss_status_t _nss_ldap_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endpwent(void);
-
-/* protocols - network protocols */
-nss_status_t _nss_ldap_getprotobyname_r(const char *name, struct protoent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_getprotobynumber_r(int number, struct protoent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setprotoent(int stayopen);
-nss_status_t _nss_ldap_getprotoent_r(struct protoent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endprotoent(void);
-
-/* rpc - remote procedure call names and numbers */
-nss_status_t _nss_ldap_getrpcbyname_r(const char *name, struct rpcent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_getrpcbynumber_r(int number, struct rpcent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setrpcent(int stayopen);
-nss_status_t _nss_ldap_getrpcent_r(struct rpcent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endrpcent(void);
-
-/* services - network services */
-nss_status_t _nss_ldap_getservbyname_r(const char *name, const char *protocol, struct servent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_getservbyport_r(int port, const char *protocol, struct servent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setservent(int stayopen);
-nss_status_t _nss_ldap_getservent_r(struct servent *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endservent(void);
-
-/* shadow - extended user information */
-nss_status_t _nss_ldap_getspnam_r(const char *name, struct spwd *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_setspent(int stayopen);
-nss_status_t _nss_ldap_getspent_r(struct spwd *result, char *buffer, size_t buflen, int *errnop);
-nss_status_t _nss_ldap_endspent(void);
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-/* helper marcos to do casts */
-#define NSS_ARGS(args) ((nss_XbyY_args_t *)args)
-#define LDAP_BE(be) ((struct nss_ldap_backend*)(be))
-
-/* these are the constructors we provide */
-nss_backend_t *_nss_ldap_ethers_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_group_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_hosts_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_netgroup_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_networks_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_passwd_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_protocols_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_rpc_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_services_constr(const char *db_name, const char *src_name, const char *cfg_args);
-nss_backend_t *_nss_ldap_shadow_constr(const char *db_name, const char *src_name, const char *cfg_args);
-
-#endif /* NSS_FLAVOUR_SOLARIS */
-
-#endif /* not NSS__PROTOTYPES_H */
diff --git a/nss/rpc.c b/nss/rpc.c
deleted file mode 100644
index 6b0bcc8..0000000
--- a/nss/rpc.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- rpc.c - NSS lookup functions for rpc database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read a sinlge rpc entry from the stream */
-static nss_status_t read_rpcent(TFILE *fp, struct rpcent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct rpcent));
- READ_BUF_STRING(fp, result->r_name);
- READ_BUF_STRINGLIST(fp, result->r_aliases);
- READ_INT32(fp, result->r_number);
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a rpc entry by name */
-nss_status_t _nss_ldap_getrpcbyname_r(const char *name,
- struct rpcent *result, char *buffer,
- size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_RPC_BYNAME,
- WRITE_STRING(fp, name),
- read_rpcent(fp, result, buffer, buflen, errnop));
-}
-
-/* get a rpc entry by number */
-nss_status_t _nss_ldap_getrpcbynumber_r(int number, struct rpcent *result,
- char *buffer, size_t buflen,
- int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_RPC_BYNUMBER,
- WRITE_INT32(fp, number),
- read_rpcent(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *rpcentfp;
-
-/* request a stream to list all rpc entries */
-nss_status_t _nss_ldap_setrpcent(int UNUSED(stayopen))
-{
- NSS_SETENT(rpcentfp);
-}
-
-/* get an rpc entry from the list */
-nss_status_t _nss_ldap_getrpcent_r(struct rpcent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(rpcentfp, NSLCD_ACTION_RPC_ALL,
- read_rpcent(rpcentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened by setrpcent() above */
-nss_status_t _nss_ldap_endrpcent(void)
-{
- NSS_ENDENT(rpcentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *rpcent2str(struct rpcent *result, char *buffer, size_t buflen)
-{
- int res, i;
- res = snprintf(buffer, buflen, "%s %d", result->r_name, result->r_number);
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- if (result->r_aliases)
- for (i = 0; result->r_aliases[i]; i++)
- {
- strlcat(buffer, " ", buflen);
- strlcat(buffer, result->r_aliases[i], buflen);
- }
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(rpcent, &args->erange);
-}
-
-static nss_status_t rpc_getrpcbyname(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_RPC_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.name),
- read_result(fp, args));
-}
-
-static nss_status_t rpc_getrpcbynumber(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_RPC_BYNUMBER,
- WRITE_INT32(fp, NSS_ARGS(args)->key.number),
- read_result(fp, args));
-}
-
-static nss_status_t rpc_setrpcent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t rpc_getrpcent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_RPC_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-static nss_status_t rpc_endrpcent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t rpc_ops[] = {
- nss_ldap_destructor,
- rpc_endrpcent,
- rpc_setrpcent,
- rpc_getrpcent,
- rpc_getrpcbyname,
- rpc_getrpcbynumber
-};
-
-nss_backend_t *_nss_ldap_rpc_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(rpc_ops, sizeof(rpc_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/services.c b/nss/services.c
deleted file mode 100644
index aa2c5b7..0000000
--- a/nss/services.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- service.c - NSS lookup functions for services database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006-2014 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read a single services result entry from the stream */
-static nss_status_t read_servent(TFILE *fp, struct servent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32, tmp2int32, tmp3int32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct servent));
- READ_BUF_STRING(fp, result->s_name);
- READ_BUF_STRINGLIST(fp, result->s_aliases);
- /* store port number in network byte order */
- READ_INT32(fp, tmp2int32);
- result->s_port = htons((uint16_t)tmp2int32);
- READ_BUF_STRING(fp, result->s_proto);
- /* we're done */
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a service entry by name and protocol */
-nss_status_t _nss_ldap_getservbyname_r(const char *name, const char *protocol,
- struct servent *result, char *buffer,
- size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_SERVICE_BYNAME,
- WRITE_STRING(fp, name);
- WRITE_STRING(fp, protocol),
- read_servent(fp, result, buffer, buflen, errnop));
-}
-
-/* get a service entry by port and protocol */
-nss_status_t _nss_ldap_getservbyport_r(int port, const char *protocol,
- struct servent *result, char *buffer,
- size_t buflen, int *errnop)
-{
- /* port is already in network byte order */
- NSS_GETONE(NSLCD_ACTION_SERVICE_BYNUMBER,
- tmpint32 = ntohs(port);
- WRITE_INT32(fp, tmpint32);
- WRITE_STRING(fp, protocol),
- read_servent(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *serventfp;
-
-/* open request to get all services */
-nss_status_t _nss_ldap_setservent(int UNUSED(stayopen))
-{
- NSS_SETENT(serventfp);
-}
-
-/* read a single returned service definition */
-nss_status_t _nss_ldap_getservent_r(struct servent *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(serventfp, NSLCD_ACTION_SERVICE_ALL,
- read_servent(serventfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened by setservent() above */
-nss_status_t _nss_ldap_endservent(void)
-{
- NSS_ENDENT(serventfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *servent2str(struct servent *result, char *buffer, size_t buflen)
-{
- int res, i;
- res = snprintf(buffer, buflen, "%s %d/%s", result->s_name, ntohs(result->s_port),
- result->s_proto);
- if ((res < 0) || (res >= (int)buflen))
- return NULL;
- if (result->s_aliases)
- for (i = 0; result->s_aliases[i]; i++)
- {
- strlcat(buffer, " ", buflen);
- strlcat(buffer, result->s_aliases[i], buflen);
- }
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(servent, &args->erange);
-}
-
-static nss_status_t services_getservbyname(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_SERVICE_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key.serv.serv.name);
- WRITE_STRING(fp, NSS_ARGS(args)->key.serv.proto),
- read_result(fp, args));
-}
-
-static nss_status_t services_getservbyport(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_SERVICE_BYNUMBER,
- WRITE_INT32(fp, ntohs(NSS_ARGS(args)->key.serv.serv.port));
- WRITE_STRING(fp, NSS_ARGS(args)->key.serv.proto),
- read_result(fp, args));
-}
-
-static nss_status_t services_setservent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t services_getservent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_SERVICE_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-static nss_status_t services_endservent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t services_ops[] = {
- nss_ldap_destructor,
- services_endservent,
- services_setservent,
- services_getservent,
- services_getservbyname,
- services_getservbyport
-};
-
-nss_backend_t *_nss_ldap_services_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(services_ops, sizeof(services_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/shadow.c b/nss/shadow.c
deleted file mode 100644
index 29fc810..0000000
--- a/nss/shadow.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- shadow.c - NSS lookup functions for shadow database
-
- Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2010, 2012, 2013 Arthur de Jong
- Copyright (C) 2010 Symas Corporation
-
- 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
-*/
-
-#include "config.h"
-
-#include <string.h>
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-/* read a single shadow entry from the stream */
-static nss_status_t read_spwd(TFILE *fp, struct spwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- int32_t tmpint32;
- size_t bufptr = 0;
- memset(result, 0, sizeof(struct spwd));
- READ_BUF_STRING(fp, result->sp_namp);
- READ_BUF_STRING(fp, result->sp_pwdp);
- READ_INT32(fp, result->sp_lstchg);
- READ_INT32(fp, result->sp_min);
- READ_INT32(fp, result->sp_max);
- READ_INT32(fp, result->sp_warn);
- READ_INT32(fp, result->sp_inact);
- READ_INT32(fp, result->sp_expire);
- READ_INT32(fp, result->sp_flag);
- return NSS_STATUS_SUCCESS;
-}
-
-#ifdef NSS_FLAVOUR_GLIBC
-
-/* get a shadow entry by name */
-nss_status_t _nss_ldap_getspnam_r(const char *name, struct spwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETONE(NSLCD_ACTION_SHADOW_BYNAME,
- WRITE_STRING(fp, name),
- read_spwd(fp, result, buffer, buflen, errnop));
-}
-
-/* thread-local file pointer to an ongoing request */
-static TLS TFILE *spentfp;
-
-/* start listing all shadow users */
-nss_status_t _nss_ldap_setspent(int UNUSED(stayopen))
-{
- NSS_SETENT(spentfp);
-}
-
-/* return a single shadow entry read from the stream */
-nss_status_t _nss_ldap_getspent_r(struct spwd *result,
- char *buffer, size_t buflen, int *errnop)
-{
- NSS_GETENT(spentfp, NSLCD_ACTION_SHADOW_ALL,
- read_spwd(spentfp, result, buffer, buflen, errnop));
-}
-
-/* close the stream opened by setspent() above */
-nss_status_t _nss_ldap_endspent(void)
-{
- NSS_ENDENT(spentfp);
-}
-
-#endif /* NSS_FLAVOUR_GLIBC */
-
-#ifdef NSS_FLAVOUR_SOLARIS
-
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-static char *spwd2str(struct spwd *result, char *buffer, size_t buflen)
-{
- /* snprintf writes a terminating \0 on Solaris */
- snprintf(buffer, buflen, "%s:%s:", result->sp_namp, result->sp_pwdp);
- if (result->sp_lstchg >= 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%d", result->sp_lstchg);
- strlcat(buffer, ":", buflen);
- if (result->sp_min >= 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%d", result->sp_min);
- strlcat(buffer, ":", buflen);
- if (result->sp_max >= 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%d", result->sp_max);
- strlcat(buffer, ":", buflen);
- if (result->sp_warn >= 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%d", result->sp_warn);
- strlcat(buffer, ":", buflen);
- if (result->sp_inact >= 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%d", result->sp_inact);
- strlcat(buffer, ":", buflen);
- if (result->sp_expire >= 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%d", result->sp_expire);
- strlcat(buffer, ":", buflen);
- if (result->sp_flag > 0)
- snprintf(buffer, buflen - strlen(buffer) - 1, "%x", result->sp_flag);
- if (strlen(buffer) >= buflen - 1)
- return NULL;
- return buffer;
-}
-#endif /* HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-static nss_status_t read_result(TFILE *fp, nss_XbyY_args_t *args)
-{
- READ_RESULT(spwd, &args->erange);
-}
-
-static nss_status_t shadow_getspnam(nss_backend_t UNUSED(*be), void *args)
-{
- NSS_GETONE(NSLCD_ACTION_SHADOW_BYNAME,
- WRITE_STRING(fp, NSS_ARGS(args)->key. name),
- read_result(fp, args));
-}
-
-static nss_status_t shadow_setspent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_SETENT(LDAP_BE(be)->fp);
-}
-
-static nss_status_t shadow_getspent(nss_backend_t *be, void *args)
-{
- NSS_GETENT(LDAP_BE(be)->fp, NSLCD_ACTION_SHADOW_ALL,
- read_result(LDAP_BE(be)->fp, args));
-}
-
-static nss_status_t shadow_endspent(nss_backend_t *be, void UNUSED(*args))
-{
- NSS_ENDENT(LDAP_BE(be)->fp);
-}
-
-static nss_backend_op_t shadow_ops[] = {
- nss_ldap_destructor,
- shadow_endspent,
- shadow_setspent,
- shadow_getspent,
- shadow_getspnam
-};
-
-nss_backend_t *_nss_ldap_shadow_constr(const char UNUSED(*db_name),
- const char UNUSED(*src_name),
- const char UNUSED(*cfg_args))
-{
- return nss_ldap_constructor(shadow_ops, sizeof(shadow_ops));
-}
-
-#endif /* NSS_FLAVOUR_SOLARIS */
diff --git a/nss/solnss.c b/nss/solnss.c
deleted file mode 100644
index bc00252..0000000
--- a/nss/solnss.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- solnss.c - Solaris specific NSS interface functions
-
- Copyright (C) 2010, 2012 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
-*/
-
-#include "config.h"
-
-#include <errno.h>
-
-#include "prototypes.h"
-#include "common.h"
-#include "compat/attrs.h"
-
-nss_backend_t *nss_ldap_constructor(nss_backend_op_t *ops, size_t sizeofops)
-{
- struct nss_ldap_backend *ldapbe;
- ldapbe = (struct nss_ldap_backend *)malloc(sizeof(struct nss_ldap_backend));
- if (ldapbe == NULL)
- return NULL;
- ldapbe->ops = ops;
- ldapbe->n_ops = sizeofops / sizeof(nss_backend_op_t);
- ldapbe->fp = NULL;
- return (nss_backend_t *)ldapbe;
-}
-
-nss_status_t nss_ldap_destructor(nss_backend_t *be, void UNUSED(*args))
-{
- struct nss_ldap_backend *ldapbe = (struct nss_ldap_backend *)be;
- if (ldapbe->fp != NULL)
- (void)tio_close(ldapbe->fp);
- free(ldapbe);
- return NSS_STATUS_SUCCESS;
-}
diff --git a/nss/solnss.h b/nss/solnss.h
deleted file mode 100644
index a01d520..0000000
--- a/nss/solnss.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- solnss.h - common functions for NSS lookups on Solaris
-
- Copyright (C) 2012 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 NSS__SOLNSS_H
-#define NSS__SOLNSS_H 1
-#ifdef NSS_FLAVOUR_SOLARIS
-
-/* extra definitions we need (Solaris NSS functions don't pass errno)
- also clear the output values */
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-#define NSS_EXTRA_DEFS \
- int *errnop = &(errno); \
- NSS_ARGS(args)->returnval = NULL; \
- NSS_ARGS(args)->returnlen = 0; \
- NSS_ARGS(args)->erange = 0; \
- NSS_ARGS(args)->h_errno = 0;
-#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-#define NSS_EXTRA_DEFS \
- int *errnop = &(errno); \
- NSS_ARGS(args)->returnval = NULL; \
- NSS_ARGS(args)->erange = 0; \
- NSS_ARGS(args)->h_errno = 0;
-#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-/* check validity of passed buffer (Solaris flavour) */
-#define NSS_BUFCHECK \
- if ((NSS_ARGS(args)->buf.buffer == NULL) || \
- (NSS_ARGS(args)->buf.buflen <= 0)) \
- { \
- NSS_ARGS(args)->erange = 1; \
- return NSS_STATUS_TRYAGAIN; \
- }
-
-/* wrapper function body for read_xxxent that does the buffer handling,
- return code handling and conversion to strings for nscd
- (also see READ_RESULT_STRING below) */
-#define READ_RESULT(ent, extra...) \
- nss_status_t retv; \
- READ_RESULT_STRING(ent, ##extra) \
- /* read the entry */ \
- retv = read_##ent(fp, args->buf.result, args->buf.buffer, \
- args->buf.buflen, ##extra); \
- if (retv != NSS_STATUS_SUCCESS) \
- return retv; \
- args->returnval = args->buf.result; \
- return NSS_STATUS_SUCCESS;
-
-/* provide result handling for when libc (or nscd) expects the returned
- values to be in string format */
-#ifdef HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN
-#define READ_RESULT_STRING(ent, extra...) \
- struct ent result; \
- char *buffer; \
- /* try to return in string format if requested */ \
- if (args->buf.result == NULL) \
- { \
- /* read the entry into a temporary buffer */ \
- buffer = (char *)malloc(args->buf.buflen); \
- if (buffer == NULL) \
- return NSS_STATUS_UNAVAIL; \
- retv = read_##ent(fp, &result, buffer, args->buf.buflen, ##extra); \
- /* format to string */ \
- if (retv == NSS_STATUS_SUCCESS) \
- if (ent##2str(&result, args->buf.buffer, args->buf.buflen) == NULL) \
- { \
- args->erange = 1; \
- retv = NSS_NOTFOUND; \
- } \
- /* clean up and return result */ \
- free(buffer); \
- if (retv != NSS_STATUS_SUCCESS) \
- return retv; \
- args->returnval = args->buf.buffer; \
- args->returnlen = strlen(args->returnval); \
- return NSS_STATUS_SUCCESS; \
- }
-#else /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-#define READ_RESULT_STRING(ent, extra...) ;
-#endif /* not HAVE_STRUCT_NSS_XBYY_ARGS_RETURNLEN */
-
-/* this is the backend structure for Solaris */
-struct nss_ldap_backend {
- nss_backend_op_t *ops; /* function-pointer table */
- int n_ops; /* number of function pointers */
- TFILE *fp; /* file pointer for {set,get,end}ent() functions */
-};
-
-/* constructor for LDAP backends */
-nss_backend_t *nss_ldap_constructor(nss_backend_op_t *ops, size_t sizeofops);
-
-/* destructor for LDAP backends */
-nss_status_t nss_ldap_destructor(nss_backend_t *be, void UNUSED(*args));
-
-#endif /* NSS_FLAVOUR_SOLARIS */
-#endif /* not NSS__COMMON_H */
diff --git a/pam/Makefile.am b/pam/Makefile.am
deleted file mode 100644
index ce2fabf..0000000
--- a/pam/Makefile.am
+++ /dev/null
@@ -1,43 +0,0 @@
-# Makefile.am - use automake to generate Makefile.in
-#
-# Copyright (C) 2009, 2010, 2011 Arthur de Jong
-# Copyright (C) 2010 Symas Corporation
-#
-# 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
-
-noinst_PROGRAMS = pam_ldap.so
-
-AM_CPPFLAGS=-I$(top_srcdir)
-AM_CFLAGS = -fPIC
-
-pam_ldap_so_SOURCES = ../nslcd.h ../common/nslcd-prot.h \
- ../compat/attrs.h pam.c common.h
-pam_ldap_so_LDADD = ../common/libtio.a ../common/libprot.a \
- ../compat/libcompat.a \
- -lpam
-
-EXTRA_DIST = pam_ldap.map
-
-install-exec-local: install-pam_ldap_so
-uninstall-local: uninstall-pam_ldap_so
-
-install-pam_ldap_so: pam_ldap.so
- -rm -f $(DESTDIR)$(PAM_SECLIB_DIR)/$(PAM_LDAP_SONAME)
- $(mkinstalldirs) $(DESTDIR)$(PAM_SECLIB_DIR)
- $(INSTALL_PROGRAM) pam_ldap.so $(DESTDIR)$(PAM_SECLIB_DIR)/$(PAM_LDAP_SONAME)
-
-uninstall-pam_ldap_so:
- -rm -f $(DESTDIR)$(PAM_SECLIB_DIR)/$(PAM_LDAP_SONAME)
diff --git a/pam/common.h b/pam/common.h
deleted file mode 100644
index 0cde6c7..0000000
--- a/pam/common.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- common.h - common functions for PAM lookups
-
- Copyright (C) 2009, 2010, 2011, 2012 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 PAM__COMMON_H
-#define PAM__COMMON_H 1
-
-#include <stdio.h>
-
-#include "nslcd.h"
-#include "common/nslcd-prot.h"
-#include "compat/attrs.h"
-
-/* These are macros for handling read and write problems, they are
- PAM specific due to the return code so are defined here. They
- genrally close the open file, set an error code and return with
- an error status. */
-
-/* Macro is called to handle errors in opening a client connection. */
-#define ERROR_OUT_OPENERROR \
- pam_syslog(pamh, LOG_ERR, "error opening connection to nslcd: %s", \
- strerror(errno)); \
- return PAM_AUTHINFO_UNAVAIL;
-
-/* Macro is called to handle errors on read operations. */
-#define ERROR_OUT_READERROR(fp) \
- pam_syslog(pamh, LOG_ERR, "error reading from nslcd: %s", \
- strerror(errno)); \
- (void)tio_close(fp); \
- return PAM_AUTHINFO_UNAVAIL;
-
-/* Macro is called to handle problems with too small a buffer. */
-#define ERROR_OUT_BUFERROR(fp) \
- pam_syslog(pamh, LOG_CRIT, "buffer %d bytes too small", tmpint32); \
- (void)tio_close(fp); \
- return PAM_SYSTEM_ERR;
-
-/* This macro is called if there was a problem with a write
- operation. */
-#define ERROR_OUT_WRITEERROR(fp) \
- pam_syslog(pamh, LOG_ERR, "error writing to nslcd: %s", \
- strerror(errno)); \
- (void)tio_close(fp); \
- return PAM_AUTHINFO_UNAVAIL;
-
-/* This macro is called if the read status code is not
- NSLCD_RESULT_BEGIN. */
-#define ERROR_OUT_NOSUCCESS(fp) \
- (void)tio_close(fp); \
- if (cfg->debug) \
- pam_syslog(pamh, LOG_DEBUG, "user not handled by nslcd"); \
- return PAM_USER_UNKNOWN;
-
-/* This is a generic PAM request generation macro. The action
- parameter is the NSLCD_ACTION_.. action, the writefn is the
- operation for writing the parameter and readfn is the function
- name for reading a single result entry. The function is assumed
- to have result, buffer, buflen and errnop parameters that define
- the result structure, the user buffer with length and the
- errno to return. This macro should be called through some of
- the customized ones below. */
-#define PAM_REQUEST(action, debuglog, writefn, readfn) \
- TFILE *fp; \
- int32_t tmpint32; \
- if (cfg->debug) \
- debuglog; \
- /* open socket and write request */ \
- NSLCD_REQUEST(fp, action, writefn); \
- /* read response code */ \
- READ_RESPONSE_CODE(fp); \
- /* read the response */ \
- readfn; \
- /* close socket and we're done */ \
- (void)tio_close(fp); \
- return PAM_SUCCESS;
-
-/* helper macro to read PAM status code (auto-translated from NSLCD PAM
- status code */
-#define READ_PAM_CODE(fp, i) \
- READ(fp, &tmpint32, sizeof(int32_t)); \
- (i) = nslcd2pam_rc(pamh, ntohl(tmpint32));
-
-#endif /* not PAM__COMMON_H */
diff --git a/pam/pam.c b/pam/pam.c
deleted file mode 100644
index 3068e2a..0000000
--- a/pam/pam.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- pam.c - pam module functions
-
- Copyright (C) 2009 Howard Chu
- Copyright (C) 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
-*/
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <pwd.h>
-
-/* these are defined (before including pam_modules.h) for staticly linking */
-#define PAM_SM_AUTH
-#define PAM_SM_ACCOUNT
-#define PAM_SM_SESSION
-#define PAM_SM_PASSWORD
-
-#include "common.h"
-#include "compat/attrs.h"
-#include "compat/pam_compat.h"
-
-#ifdef HAVE_SECURITY_PAM_APPL_H
-#include <security/pam_appl.h>
-#endif /* HAVE_SECURITY_PAM_APPL_H */
-#ifndef HAVE_PAM_PAM_MODULES_H
-#include <security/pam_modules.h>
-#ifdef HAVE_SECURITY_PAM_EXT_H
-#include <security/pam_ext.h>
-#endif /* HAVE_SECURITY_PAM_EXT_H */
-#else /* not HAVE_PAM_PAM_MODULES_H */
-#include <pam/pam_modules.h>
-#endif /* not HAVE_PAM_PAM_MODULES_H */
-
-/* the name we store our context under */
-#define PLD_CTX "PAM_LDAPD_CTX"
-
-/* structure that stores the results for an nslcd call */
-struct nslcd_resp {
- int res;
- char msg[1024];
-};
-
-/* this struct represents the context that the PAM module keeps
- between calls */
-struct pld_ctx {
- char *username;
- struct nslcd_resp saved_authz;
- struct nslcd_resp saved_session;
- int asroot;
- char *oldpassword;
-};
-
-/* clear the context to all empty values */
-static void ctx_clear(struct pld_ctx *ctx)
-{
- if (ctx->username)
- {
- free(ctx->username);
- ctx->username = NULL;
- }
- ctx->saved_authz.res = PAM_SUCCESS;
- memset(ctx->saved_authz.msg, 0, sizeof(ctx->saved_authz.msg));
- ctx->saved_session.res = PAM_SUCCESS;
- memset(ctx->saved_session.msg, 0, sizeof(ctx->saved_session.msg));
- ctx->asroot = 0;
- if (ctx->oldpassword)
- {
- memset(ctx->oldpassword, 0, strlen(ctx->oldpassword));
- free(ctx->oldpassword);
- ctx->oldpassword = NULL;
- }
-}
-
-/* free the context (this is installed as handler into PAM) */
-static void ctx_free(pam_handle_t UNUSED(*pamh), void *data, int UNUSED(err))
-{
- struct pld_ctx *ctx = data;
- ctx_clear(ctx);
- free(ctx);
-}
-
-/* try to get the module's context, returns a PAM status code */
-static int ctx_get(pam_handle_t *pamh, const char *username, struct pld_ctx **pctx)
-{
- struct pld_ctx *ctx = NULL;
- int rc;
- /* try to get the context from PAM */
- rc = pam_get_data(pamh, PLD_CTX, (const void **)&ctx);
- if ((rc == PAM_SUCCESS) && (ctx != NULL))
- {
- /* if the user is different clear the context */
- if ((ctx->username != NULL) && (strcmp(ctx->username, username) != 0))
- ctx_clear(ctx);
- }
- else
- {
- /* allocate a new context */
- ctx = calloc(1, sizeof(struct pld_ctx));
- if (ctx == NULL)
- {
- pam_syslog(pamh, LOG_CRIT, "calloc(): failed to allocate memory: %s",
- strerror(errno));
- return PAM_BUF_ERR;
- }
- ctx_clear(ctx);
- /* store the new context with the handler to free it */
- rc = pam_set_data(pamh, PLD_CTX, ctx, ctx_free);
- if (rc != PAM_SUCCESS)
- {
- ctx_free(pamh, ctx, 0);
- pam_syslog(pamh, LOG_ERR, "failed to store context: %s",
- pam_strerror(pamh, rc));
- return rc;
- }
- }
- /* save the username in the context */
- if (ctx->username == NULL)
- ctx->username = strdup(username);
- /* return the context */
- *pctx = ctx;
- return PAM_SUCCESS;
-}
-
-/* our PAM module configuration */
-struct pld_cfg {
- int nullok;
- int no_warn;
- int ignore_unknown_user;
- int ignore_authinfo_unavail;
- int debug;
- uid_t minimum_uid;
-};
-
-static void cfg_init(pam_handle_t *pamh, int flags,
- int argc, const char **argv,
- struct pld_cfg *cfg)
-{
- int i;
- /* initialise config with defaults */
- cfg->nullok = 0;
- cfg->no_warn = 0;
- cfg->ignore_unknown_user = 0;
- cfg->ignore_authinfo_unavail = 0;
- cfg->debug = 0;
- cfg->minimum_uid = 0;
- /* go over arguments */
- for (i = 0; i < argc; i++)
- {
- if (strcmp(argv[i], "use_first_pass") == 0)
- /* ignore, this option is used by pam_get_authtok() internally */ ;
- else if (strcmp(argv[i], "try_first_pass") == 0)
- /* ignore, this option is used by pam_get_authtok() internally */ ;
- else if (strcmp(argv[i], "nullok") == 0)
- cfg->nullok = 1;
- else if (strcmp(argv[i], "use_authtok") == 0)
- /* ignore, this option is used by pam_get_authtok() internally */ ;
- else if (strcmp(argv[i], "no_warn") == 0)
- cfg->no_warn = 1;
- else if (strcmp(argv[i], "ignore_unknown_user") == 0)
- cfg->ignore_unknown_user = 1;
- else if (strcmp(argv[i], "ignore_authinfo_unavail") == 0)
- cfg->ignore_authinfo_unavail = 1;
- else if (strcmp(argv[i], "debug") == 0)
- cfg->debug = 1;
- else if (strncmp(argv[i], "minimum_uid=", 12) == 0)
- cfg->minimum_uid = (uid_t)atoi(argv[i] + 12);
- else
- pam_syslog(pamh, LOG_ERR, "unknown option: %s", argv[i]);
- }
- /* check flags */
- if (flags & PAM_SILENT)
- cfg->no_warn = 1;
-}
-
-static int init(pam_handle_t *pamh, struct pld_cfg *cfg, struct pld_ctx **ctx,
- const char **username, const char **service, const char **ruser,
- const char **rhost, const char **tty)
-{
- int rc;
- struct passwd *pwent;
- /* get user name */
- rc = pam_get_user(pamh, username, NULL);
- if (rc != PAM_SUCCESS)
- {
- pam_syslog(pamh, LOG_ERR, "failed to get user name: %s", pam_strerror(pamh, rc));
- return rc;
- }
- if ((*username == NULL) || ((*username)[0] == '\0'))
- {
- pam_syslog(pamh, LOG_ERR, "got empty user name");
- return PAM_USER_UNKNOWN;
- }
- /* check uid */
- if (cfg->minimum_uid > 0)
- {
- pwent = pam_modutil_getpwnam(args->pamh, *username);
- if ((pwent != NULL) && (pwent->pw_uid < cfg->minimum_uid))
- {
- if (cfg->debug)
- pam_syslog(pamh, LOG_DEBUG, "uid below minimum_uid; user=%s uid=%ld",
- *username, (long)pwent->pw_uid);
- return cfg->ignore_unknown_user ? PAM_IGNORE : PAM_USER_UNKNOWN;
- }
- }
- /* get our context */
- rc = ctx_get(pamh, *username, ctx);
- if (rc != PAM_SUCCESS)
- return rc;
- /* get service name */
- rc = pam_get_item(pamh, PAM_SERVICE, (PAM_ITEM_CONST void **)service);
- if (rc != PAM_SUCCESS)
- {
- pam_syslog(pamh, LOG_ERR, "failed to get service name: %s",
- pam_strerror(pamh, rc));
- return rc;
- }
- /* get more PAM information (ignore errors) */
- pam_get_item(pamh, PAM_RUSER, (PAM_ITEM_CONST void **)ruser);
- pam_get_item(pamh, PAM_RHOST, (PAM_ITEM_CONST void **)rhost);
- pam_get_item(pamh, PAM_TTY, (PAM_ITEM_CONST void **)tty);
- return PAM_SUCCESS;
-}
-
-/* map a NSLCD PAM status code to a PAM status code */
-static int nslcd2pam_rc(pam_handle_t *pamh, int rc)
-{
-#define map(i) case NSLCD_##i: return i;
- switch (rc)
- {
- map(PAM_SUCCESS);
- map(PAM_PERM_DENIED);
- map(PAM_AUTH_ERR);
- map(PAM_CRED_INSUFFICIENT);
- map(PAM_AUTHINFO_UNAVAIL);
- map(PAM_USER_UNKNOWN);
- map(PAM_MAXTRIES);
- map(PAM_NEW_AUTHTOK_REQD);
- map(PAM_ACCT_EXPIRED);
- map(PAM_SESSION_ERR);
- map(PAM_AUTHTOK_ERR);
- map(PAM_AUTHTOK_DISABLE_AGING);
- map(PAM_IGNORE);
- map(PAM_ABORT);
- map(PAM_AUTHTOK_EXPIRED);
- default:
- pam_syslog(pamh, LOG_ERR, "unknown NSLCD_PAM_* code returned: %d", rc);
- return PAM_ABORT;
- }
-}
-
-/* check whether the specified user is handled by nslcd */
-static int nslcd_request_exists(pam_handle_t *pamh, struct pld_cfg *cfg,
- const char *username)
-{
- PAM_REQUEST(
- NSLCD_ACTION_PASSWD_BYNAME,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd account check; user=%s", username),
- /* write the request parameters */
- WRITE_STRING(fp, username),
- /* read the result entry (skip it completely) */
- SKIP_STRING(fp); /* user name */
- SKIP_STRING(fp); /* passwd entry */
- SKIP(fp, sizeof(int32_t)); /* uid */
- SKIP(fp, sizeof(int32_t)); /* gid */
- SKIP_STRING(fp); /* gecos */
- SKIP_STRING(fp); /* home dir */
- SKIP_STRING(fp); /* shell */
- )
-}
-
-/* perform an authentication call over nslcd */
-static int nslcd_request_authc(pam_handle_t *pamh, struct pld_cfg *cfg,
- const char *username, const char *service,
- const char *ruser, const char *rhost,
- const char *tty, const char *passwd,
- struct nslcd_resp *authc_resp,
- struct nslcd_resp *authz_resp)
-{
- PAM_REQUEST(
- NSLCD_ACTION_PAM_AUTHC,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd authentication; user=%s", username),
- /* write the request parameters */
- WRITE_STRING(fp, username);
- WRITE_STRING(fp, service);
- WRITE_STRING(fp, ruser);
- WRITE_STRING(fp, rhost);
- WRITE_STRING(fp, tty);
- WRITE_STRING(fp, passwd),
- /* read the result entry */
- READ_PAM_CODE(fp, authc_resp->res);
- READ_STRING(fp, authc_resp->msg); /* user name */
- /* if we want the authorisation response, save it, otherwise skip it */
- if (authz_resp != NULL)
- {
- READ_PAM_CODE(fp, authz_resp->res);
- READ_STRING(fp, authz_resp->msg);
- }
- else
- {
- SKIP(fp, sizeof(int32_t));
- SKIP_STRING(fp);
- }
- )
-}
-
-/* perform an authorisation call over nslcd */
-static int nslcd_request_authz(pam_handle_t *pamh, struct pld_cfg *cfg,
- const char *username, const char *service,
- const char *ruser, const char *rhost,
- const char *tty, struct nslcd_resp *resp)
-{
- PAM_REQUEST(
- NSLCD_ACTION_PAM_AUTHZ,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd authorisation; user=%s", username),
- /* write the request parameters */
- WRITE_STRING(fp, username);
- WRITE_STRING(fp, service);
- WRITE_STRING(fp, ruser);
- WRITE_STRING(fp, rhost);
- WRITE_STRING(fp, tty),
- /* read the result entry */
- READ_PAM_CODE(fp, resp->res);
- READ_STRING(fp, resp->msg);
- )
-}
-
-/* do a session open nslcd request */
-static int nslcd_request_sess_o(pam_handle_t *pamh, struct pld_cfg *cfg,
- const char *username, const char *service,
- const char *ruser, const char *rhost,
- const char *tty, struct nslcd_resp *resp)
-{
- PAM_REQUEST(
- NSLCD_ACTION_PAM_SESS_O,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd session open; user=%s", username),
- /* write the request parameters */
- WRITE_STRING(fp, username);
- WRITE_STRING(fp, service);
- WRITE_STRING(fp, ruser);
- WRITE_STRING(fp, rhost);
- WRITE_STRING(fp, tty),
- /* read the result entry */
- READ_STRING(fp, resp->msg)
- )
-}
-
-/* do a session close nslcd request */
-static int nslcd_request_sess_c(pam_handle_t *pamh, struct pld_cfg *cfg,
- const char *username, const char *service,
- const char *ruser, const char *rhost,
- const char *tty, const char *sessid)
-{
- PAM_REQUEST(
- NSLCD_ACTION_PAM_SESS_C,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd session close; user=%s", username),
- /* write the request parameters */
- WRITE_STRING(fp, username);
- WRITE_STRING(fp, service);
- WRITE_STRING(fp, ruser);
- WRITE_STRING(fp, rhost);
- WRITE_STRING(fp, tty);
- WRITE_STRING(fp, sessid),
- /* no result entry to read */ ;
- )
-}
-
-/* do a password modification nslcd call */
-static int nslcd_request_pwmod(pam_handle_t *pamh, struct pld_cfg *cfg,
- const char *username, const char *service,
- const char *ruser, const char *rhost,
- const char *tty, int asroot,
- const char *oldpasswd, const char *newpasswd,
- struct nslcd_resp *resp)
-{
- PAM_REQUEST(
- NSLCD_ACTION_PAM_PWMOD,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd password modify; user=%s", username),
- /* write the request parameters */
- WRITE_STRING(fp, username);
- WRITE_STRING(fp, service);
- WRITE_STRING(fp, ruser);
- WRITE_STRING(fp, rhost);
- WRITE_STRING(fp, tty);
- WRITE_INT32(fp, asroot);
- WRITE_STRING(fp, oldpasswd);
- WRITE_STRING(fp, newpasswd),
- /* read the result entry */
- READ_PAM_CODE(fp, resp->res);
- READ_STRING(fp, resp->msg);
- )
-}
-
-static int nslcd_request_config_get(pam_handle_t *pamh, struct pld_cfg *cfg,
- int cfgopt, struct nslcd_resp *resp)
-{
- PAM_REQUEST(
- NSLCD_ACTION_CONFIG_GET,
- /* log debug message */
- pam_syslog(pamh, LOG_DEBUG, "nslcd request config (%d)", cfgopt),
- /* write the request parameter */
- WRITE_INT32(fp, cfgopt),
- /* read the result entry */
- READ_STRING(fp, resp->msg);
- )
-}
-
-/* remap the return code based on the configuration */
-static int remap_pam_rc(int rc, struct pld_cfg *cfg)
-{
- if ((rc == PAM_AUTHINFO_UNAVAIL) && cfg->ignore_authinfo_unavail)
- return PAM_IGNORE;
- if ((rc == PAM_USER_UNKNOWN) && cfg->ignore_unknown_user)
- return PAM_IGNORE;
- return rc;
-}
-
-/* PAM authentication check */
-int pam_sm_authenticate(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int rc;
- struct pld_cfg cfg;
- struct pld_ctx *ctx;
- const char *username, *service;
- const char *ruser = NULL, *rhost = NULL, *tty = NULL;
- char *passwd = NULL;
- struct nslcd_resp resp;
- /* set up configuration */
- cfg_init(pamh, flags, argc, argv, &cfg);
- rc = init(pamh, &cfg, &ctx, &username, &service, &ruser, &rhost, &tty);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* if service is "passwd" and pwdmod is not allowed alert user */
- if (!strcmp(service, "passwd"))
- {
- rc = nslcd_request_config_get(pamh, &cfg, NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE,
- &resp);
- if ((rc == PAM_SUCCESS) && (resp.msg != NULL) && (resp.msg[0] != '\0'))
- {
- /* we silently ignore errors to get the configuration option */
- pam_syslog(pamh, LOG_NOTICE, "password change prohibited: %s; user=%s",
- resp.msg, username);
- if (!cfg.no_warn)
- pam_error(pamh, "%s", resp.msg);
- return remap_pam_rc(PAM_PERM_DENIED, &cfg);
- }
- }
- /* prompt the user for a password */
- rc = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **)&passwd, NULL);
- if (rc != PAM_SUCCESS)
- {
- pam_syslog(pamh, LOG_ERR, "failed to get password: %s",
- pam_strerror(pamh, rc));
- return rc;
- }
- /* check password */
- if (!cfg.nullok && ((passwd == NULL) || (passwd[0] == '\0')))
- {
- if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "user has empty password, access denied");
- return PAM_AUTH_ERR;
- }
- /* do the nslcd request */
- rc = nslcd_request_authc(pamh, &cfg, username, service, ruser, rhost, tty,
- passwd, &resp, &(ctx->saved_authz));
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* check the authentication result */
- if (resp.res != PAM_SUCCESS)
- {
- pam_syslog(pamh, LOG_NOTICE, "%s; user=%s",
- pam_strerror(pamh, resp.res), username);
- return remap_pam_rc(resp.res, &cfg);
- }
- /* debug log */
- if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "authentication succeeded");
- /* if password change is required, save old password in context */
- if ((ctx->saved_authz.res == PAM_NEW_AUTHTOK_REQD) && (ctx->oldpassword == NULL))
- ctx->oldpassword = strdup(passwd);
- /* update caller's idea of the user name */
- if ((resp.msg[0] != '\0') && (strcmp(resp.msg, username) != 0))
- {
- pam_syslog(pamh, LOG_INFO, "username changed from %s to %s",
- username, resp.msg);
- rc = pam_set_item(pamh, PAM_USER, resp.msg);
- /* empty the username in the context to not loose our context */
- if (ctx->username == NULL)
- {
- free(ctx->username);
- ctx->username = NULL;
- }
- }
- return rc;
-}
-
-/* called to update the authentication credentials */
-int pam_sm_setcred(pam_handle_t UNUSED(*pamh), int UNUSED(flags),
- int UNUSED(argc), const char UNUSED(**argv))
-{
- /* we don't need to do anything here */
- return PAM_SUCCESS;
-}
-
-/* PAM authorisation check */
-int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int rc;
- struct pld_cfg cfg;
- struct pld_ctx *ctx;
- const char *username, *service;
- const char *ruser = NULL, *rhost = NULL, *tty = NULL;
- struct nslcd_resp authz_resp;
- const char *msg = NULL;
- /* set up configuration */
- cfg_init(pamh, flags, argc, argv, &cfg);
- rc = init(pamh, &cfg, &ctx, &username, &service, &ruser, &rhost, &tty);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* do the nslcd request */
- rc = nslcd_request_authz(pamh, &cfg, username, service, ruser, rhost, tty,
- &authz_resp);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* check the returned authorisation value and the value from authentication */
- if (authz_resp.res != PAM_SUCCESS)
- {
- rc = authz_resp.res;
- msg = authz_resp.msg;
- }
- else if (ctx->saved_authz.res != PAM_SUCCESS)
- {
- rc = ctx->saved_authz.res;
- msg = ctx->saved_authz.msg;
- }
- if (rc != PAM_SUCCESS)
- {
- /* turn in to generic PAM error message if message is empty */
- if ((msg == NULL) || (msg[0] == '\0'))
- {
- msg = pam_strerror(pamh, rc);
- pam_syslog(pamh, LOG_NOTICE, "%s; user=%s", msg, username);
- }
- else
- pam_syslog(pamh, LOG_NOTICE, "%s; user=%s; err=%s",
- msg, username, pam_strerror(pamh, rc));
- rc = remap_pam_rc(rc, &cfg);
- if ((rc != PAM_IGNORE) && (!cfg.no_warn))
- pam_error(pamh, "%s", msg);
- return rc;
- }
- if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "authorization succeeded");
- /* present any informational messages to the user */
- if ((authz_resp.msg[0] != '\0') && (!cfg.no_warn))
- pam_info(pamh, "%s", authz_resp.msg);
- if ((ctx->saved_authz.msg[0] != '\0') && (!cfg.no_warn))
- pam_info(pamh, "%s", ctx->saved_authz.msg);
- return PAM_SUCCESS;
-}
-
-/* PAM session open call */
-int pam_sm_open_session(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int rc;
- struct pld_cfg cfg;
- struct pld_ctx *ctx;
- const char *username, *service;
- const char *ruser = NULL, *rhost = NULL, *tty = NULL;
- /* set up configuration */
- cfg_init(pamh, flags, argc, argv, &cfg);
- rc = init(pamh, &cfg, &ctx, &username, &service, &ruser, &rhost, &tty);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* do the nslcd request */
- rc = nslcd_request_sess_o(pamh, &cfg, username, service, ruser, rhost,
- tty, &(ctx->saved_session));
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* debug log */
- if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "session open succeeded; session_id=%s",
- ctx->saved_session.msg);
- return PAM_SUCCESS;
-}
-
-/* PAM session close call */
-int pam_sm_close_session(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int rc;
- struct pld_cfg cfg;
- struct pld_ctx *ctx;
- const char *username, *service;
- const char *ruser = NULL, *rhost = NULL, *tty = NULL;
- /* set up configuration */
- cfg_init(pamh, flags, argc, argv, &cfg);
- rc = init(pamh, &cfg, &ctx, &username, &service, &ruser, &rhost, &tty);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* do the nslcd request */
- rc = nslcd_request_sess_c(pamh, &cfg, username, service, ruser, rhost,
- tty, ctx->saved_session.msg);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* debug log */
- if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "session close succeeded; session_id=%s",
- ctx->saved_session.msg);
- return PAM_SUCCESS;
-}
-
-/* Change the password of the user. This function is first called with
- PAM_PRELIM_CHECK set in the flags and then without the flag. In the first
- pass it is determined whether we can contact the LDAP server and the
- provided old password is valid. In the second pass we get the new
- password and actually modify the password. */
-int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
-{
- int rc;
- struct pld_cfg cfg;
- struct pld_ctx *ctx;
- const char *username, *service;
- const char *ruser = NULL, *rhost = NULL, *tty = NULL;
- const char *oldpassword = NULL, *newpassword = NULL;
- struct passwd *pwent;
- uid_t myuid;
- struct nslcd_resp resp;
- const char *msg;
- /* set up configuration */
- cfg_init(pamh, flags, argc, argv, &cfg);
- rc = init(pamh, &cfg, &ctx, &username, &service, &ruser, &rhost, &tty);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* check if password modification is allowed */
- rc = nslcd_request_config_get(pamh, &cfg, NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE,
- &resp);
- if ((rc == PAM_SUCCESS) && (resp.msg != NULL) && (resp.msg[0] != '\0'))
- {
- /* we silently ignore errors to get the configuration option */
- pam_syslog(pamh, LOG_NOTICE, "password change prohibited: %s; user=%s",
- resp.msg, username);
- if (!cfg.no_warn)
- pam_error(pamh, "%s", resp.msg);
- return remap_pam_rc(PAM_PERM_DENIED, &cfg);
- }
- /* see if we are dealing with an LDAP user first */
- rc = nslcd_request_exists(pamh, &cfg, username);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* preliminary check, just see if we can authenticate with the current password */
- if (flags & PAM_PRELIM_CHECK)
- {
- ctx->asroot = 0;
- /* see if the user is trying to modify another user's password */
- /* TODO: perhaps this can be combined with the nslcd_request_exists() call above */
- pwent = pam_modutil_getpwnam(args->pamh, username);
- myuid = getuid();
- if ((pwent != NULL) && (pwent->pw_uid != myuid) && (!(flags & PAM_CHANGE_EXPIRED_AUTHTOK)))
- {
- /* we are root so we can test if nslcd will allow us to change the
- user's password without the admin password */
- if (myuid == 0)
- {
- rc = nslcd_request_authc(pamh, &cfg, "", service, ruser, rhost, tty,
- "", &resp, NULL);
- if ((rc == PAM_SUCCESS) && (resp.res == PAM_SUCCESS))
- {
- ctx->asroot = 1;
- return pam_set_item(pamh, PAM_OLDAUTHTOK, "");
- }
- }
- /* try to authenticate with the LDAP administrator password by passing
- an empty username to the authc request */
- rc = pam_get_authtok(pamh, PAM_OLDAUTHTOK, &oldpassword,
- "LDAP administrator password: ");
- if (rc != PAM_SUCCESS)
- return rc;
- ctx->asroot = 1;
- username = "";
- }
- else if ((ctx->oldpassword != NULL) && (*ctx->oldpassword != '\0'))
- {
- /* we already have an old password stored (from a previous
- authentication phase) so we'll use that and don't re-check */
- rc = pam_set_item(pamh, PAM_OLDAUTHTOK, ctx->oldpassword);
- return remap_pam_rc(rc, &cfg);
- }
- else
- {
- /* prompt the user for a password if needed */
- rc = pam_get_authtok(pamh, PAM_OLDAUTHTOK, (const char **)&oldpassword,
- "(current) LDAP Password: ");
- if (rc != PAM_SUCCESS)
- return rc;
- }
- /* check for empty password */
- if (!cfg.nullok && ((oldpassword == NULL) || (oldpassword[0] == '\0')))
- {
- if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "user has empty password, access denied");
- return PAM_AUTH_ERR;
- }
- /* try authenticating */
- rc = nslcd_request_authc(pamh, &cfg, username, service, ruser, rhost,
- tty, oldpassword, &resp, NULL);
- if (rc != PAM_SUCCESS)
- return remap_pam_rc(rc, &cfg);
- /* handle authentication result */
- if (resp.res != PAM_SUCCESS)
- pam_syslog(pamh, LOG_NOTICE, "%s; user=%s",
- pam_strerror(pamh, resp.res), username);
- else if (cfg.debug)
- pam_syslog(pamh, LOG_DEBUG, "authentication succeeded");
- /* remap error code */
- return remap_pam_rc(resp.res, &cfg);
- }
- /* get the old password (from the previous call) */
- rc = pam_get_item(pamh, PAM_OLDAUTHTOK, (PAM_ITEM_CONST void **)&oldpassword);
- if (rc != PAM_SUCCESS)
- return rc;
- /* prompt for new password */
- rc = pam_get_authtok(pamh, PAM_AUTHTOK, &newpassword, NULL);
- if (rc != PAM_SUCCESS)
- return rc;
- /* perform the password modification */
- rc = nslcd_request_pwmod(pamh, &cfg, username, service, ruser, rhost, tty,
- ctx->asroot, oldpassword, newpassword, &resp);
- if (rc != PAM_SUCCESS)
- msg = pam_strerror(pamh, rc);
- else
- {
- rc = resp.res;
- msg = resp.msg;
- }
- /* remap error code */
- rc = remap_pam_rc(rc, &cfg);
- /* check the returned value */
- if (rc != PAM_SUCCESS)
- {
- pam_syslog(pamh, LOG_NOTICE, "password change failed: %s; user=%s",
- msg, username);
- if ((rc != PAM_IGNORE) && (!cfg.no_warn))
- pam_error(pamh, "%s", msg);
- return rc;
- }
- pam_syslog(pamh, LOG_NOTICE, "password changed for %s", username);
- return PAM_SUCCESS;
-}
-
-#ifdef PAM_STATIC
-struct pam_module _pam_ldap_modstruct = {
- "pam_ldap",
- pam_sm_authenticate,
- pam_sm_setcred,
- pam_sm_acct_mgmt,
- pam_sm_open_session,
- pam_sm_close_session,
- pam_sm_chauthtok
-};
-#endif /* PAM_STATIC */
diff --git a/pam/pam_ldap.map b/pam/pam_ldap.map
deleted file mode 100644
index 21c98f8..0000000
--- a/pam/pam_ldap.map
+++ /dev/null
@@ -1,16 +0,0 @@
-EXPORTED {
-
- # published PAM service functions
- global:
- pam_sm_acct_mgmt;
- pam_sm_authenticate;
- pam_sm_chauthtok;
- pam_sm_close_session;
- pam_sm_open_session;
- pam_sm_setcred;
-
- # everything else should not be exported
- local:
- *;
-
-};
diff --git a/pynslcd/Makefile.am b/pynslcd/Makefile.am
deleted file mode 100644
index a61ff65..0000000
--- a/pynslcd/Makefile.am
+++ /dev/null
@@ -1,42 +0,0 @@
-# Makefile.am - use automake to generate Makefile.in
-#
-# Copyright (C) 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
-
-pynslcddir = $(datadir)/pynslcd
-
-pynslcd_PYTHON = pynslcd.py attmap.py cache.py cfg.py common.py expr.py \
- mypidfile.py invalidator.py search.py tio.py \
- config.py alias.py ether.py group.py host.py netgroup.py \
- network.py passwd.py protocol.py rpc.py service.py \
- shadow.py pam.py usermod.py
-nodist_pynslcd_PYTHON = constants.py
-CLEANFILES = $(nodist_pynslcd_PYTHON)
-
-all-local: $(nodist_pynslcd_PYTHON)
-
-# clean up locally created compiled Python files
-clean-local:
- rm -f *.pyc *.pyo
-
-constants.py: constants.py.in $(top_srcdir)/nslcd.h
-
-# create a symbolic link for the pynslcd daemon and fix permissions
-install-data-hook:
- chmod a+rx $(DESTDIR)$(pynslcddir)/pynslcd.py
- $(MKDIR_P) $(DESTDIR)$(sbindir)
- [ -L $(DESTDIR)$(sbindir)/pynslcd ] || $(LN_S) $(pynslcddir)/pynslcd.py $(DESTDIR)$(sbindir)/pynslcd
diff --git a/pynslcd/alias.py b/pynslcd/alias.py
deleted file mode 100644
index 371ac2e..0000000
--- a/pynslcd/alias.py
+++ /dev/null
@@ -1,99 +0,0 @@
-
-# alias.py - lookup functions for email aliases
-#
-# Copyright (C) 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
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(cn='cn', rfc822MailMember='rfc822MailMember')
-filter = '(objectClass=nisMailAlias)'
-
-
-class Search(search.LDAPSearch):
-
- case_insensitive = ('cn', )
- limit_attributes = ('cn', )
- required = ('cn', 'rfc822MailMember')
-
-
-class Cache(cache.Cache):
-
- tables = ('alias_cache', 'alias_member_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `alias_cache`
- ( `cn` TEXT PRIMARY KEY COLLATE NOCASE,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `alias_member_cache`
- ( `alias` TEXT NOT NULL COLLATE NOCASE,
- `rfc822MailMember` TEXT NOT NULL,
- FOREIGN KEY(`alias`) REFERENCES `alias_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `alias_member_idx` ON `alias_member_cache`(`alias`);
- '''
-
- retrieve_sql = '''
- SELECT `alias_cache`.`cn` AS `cn`,
- `alias_member_cache`.`rfc822MailMember` AS `rfc822MailMember`,
- `alias_cache`.`mtime` AS `mtime`
- FROM `alias_cache`
- LEFT JOIN `alias_member_cache`
- ON `alias_member_cache`.`alias` = `alias_cache`.`cn`
- '''
-
- retrieve_by = dict(
- rfc822MailMember='''
- `cn` IN (
- SELECT `a`.`alias`
- FROM `alias_member_cache` `a`
- WHERE `a`.`rfc822MailMember` = ?)
- ''',
- )
-
- group_by = (0, ) # cn
- group_columns = (1, ) # rfc822MailMember
-
-
-class AliasRequest(common.Request):
-
- def write(self, name, members):
- self.fp.write_string(name)
- self.fp.write_stringlist(members)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['cn']
- members = attributes['rfc822MailMember']
- for name in names:
- yield (name, members)
-
-
-class AliasByNameRequest(AliasRequest):
-
- action = constants.NSLCD_ACTION_ALIAS_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class AliasAllRequest(AliasRequest):
-
- action = constants.NSLCD_ACTION_ALIAS_ALL
diff --git a/pynslcd/attmap.py b/pynslcd/attmap.py
deleted file mode 100644
index b64a048..0000000
--- a/pynslcd/attmap.py
+++ /dev/null
@@ -1,174 +0,0 @@
-
-# attmap.py - attribute mapping class
-#
-# Copyright (C) 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
-
-"""Module for handling attribute mappings used for LDAP searches.
-
->>> attrs = Attributes(uid='uid',
-... userPassword='userPassword',
-... uidNumber='uidNumber',
-... gidNumber='gidNumber',
-... gecos='"${gecos:-$cn}"',
-... homeDirectory='homeDirectory',
-... loginShell='loginShell')
->>> 'cn' in attrs.attributes()
-True
->>> attrs.translate({'uid': ['UIDVALUE', '2nduidvalue'], 'cn': ['COMMON NAME', ]})
-{'uid': ['UIDVALUE', '2nduidvalue'], 'loginShell': [], 'userPassword': [], 'uidNumber': [], 'gidNumber': [], 'gecos': ['COMMON NAME'], 'homeDirectory': []}
->>> attrs['uidNumber'] # a representation fit for logging and filters
-'uidNumber'
->>> attrs['gecos']
-'"${gecos:-$cn}"'
-"""
-
-import re
-
-from ldap.filter import escape_filter_chars
-import ldap.dn
-
-from expr import Expression
-
-
-# exported names
-__all__ = ('Attributes', )
-
-
-# TODO: support objectSid attributes
-
-
-# regular expression to match function attributes
-attribute_func_re = re.compile('^(?P<function>[a-z]+)\((?P<attribute>.*)\)$')
-
-
-class SimpleMapping(str):
- """Simple mapping to another attribute name."""
-
- def attributes(self):
- return [self]
-
- def mk_filter(self, value):
- return '(%s=%s)' % (
- self, escape_filter_chars(str(value))
- )
-
- def values(self, variables):
- """Expand the expression using the variables specified."""
- return variables.get(self, [])
-
-
-class ExpressionMapping(str):
- """Class for parsing and expanding an expression."""
-
- def __init__(self, value):
- """Parse the expression as a string."""
- self.expression = Expression(value)
- super(ExpressionMapping, self).__init__(value)
-
- def values(self, variables):
- """Expand the expression using the variables specified."""
- return [self.expression.value(variables)]
-
- def attributes(self):
- """Return the attributes defined in the expression."""
- return self.expression.variables()
-
-
-class FunctionMapping(str):
- """Mapping to a function to another attribute."""
-
- def __init__(self, mapping):
- self.mapping = mapping
- m = attribute_func_re.match(mapping)
- self.attribute = m.group('attribute')
- self.function = getattr(self, m.group('function'))
- super(FunctionMapping, self).__init__(mapping)
-
- def upper(self, value):
- return value.upper()
-
- def lower(self, value):
- return value.lower()
-
- def attributes(self):
- return [self.attribute]
-
- def mk_filter(self, value):
- return '(%s=%s)' % (
- self.attribute, escape_filter_chars(value)
- )
-
- def values(self, variables):
- return [self.function(value)
- for value in variables.get(self.attribute, [])]
-
-
-class Attributes(dict):
- """Dictionary-like class for handling attribute mapping."""
-
- def __init__(self, *args, **kwargs):
- self.update(*args, **kwargs)
-
- def __setitem__(self, attribute, mapping):
- # translate the mapping into a mapping object
- if mapping[0] == '"' and mapping[-1] == '"':
- mapping = ExpressionMapping(mapping[1:-1])
- elif '(' in mapping:
- mapping = FunctionMapping(mapping)
- else:
- mapping = SimpleMapping(mapping)
- super(Attributes, self).__setitem__(attribute, mapping)
-
- def update(self, *args, **kwargs):
- for arg in args:
- other = dict(arg)
- for key in other:
- self[key] = other[key]
- for key in kwargs:
- self[key] = kwargs[key]
-
- def attributes(self):
- """Return the list of attributes that are referenced in this
- attribute mapping. These are the attributes that should be
- requested in the search."""
- attributes = set()
- for mapping in self.itervalues():
- attributes.update(mapping.attributes())
- return list(attributes)
-
- def mk_filter(self, attribute, value):
- """Construct a search filter for searching for the attribute value
- combination."""
- mapping = self.get(attribute, SimpleMapping(attribute))
- return mapping.mk_filter(value)
-
- def translate(self, variables):
- """Return a dictionary with every attribute mapped to their value from
- the specified variables."""
- results = dict()
- for attribute, mapping in self.iteritems():
- results[attribute] = mapping.values(variables)
- return results
-
- def get_rdn_value(self, dn, attribute):
- """Extract the attribute value from from DN if possible. Return None
- otherwise."""
- return self.translate(dict(
- (x, [y])
- for x, y, z in ldap.dn.str2dn(dn)[0]
- ))[attribute][0]
diff --git a/pynslcd/cache.py b/pynslcd/cache.py
deleted file mode 100644
index 99b520d..0000000
--- a/pynslcd/cache.py
+++ /dev/null
@@ -1,194 +0,0 @@
-
-# cache.py - caching layer for pynslcd
-#
-# Copyright (C) 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
-
-import datetime
-import os
-import sys
-
-import sqlite3
-
-
-# TODO: probably create a config table
-# FIXME: have some way to remove stale entries from the cache if all items from LDAP are queried (perhas use TTL from all request)
-
-
-class regroup(object):
-
- def __init__(self, results, group_by=None, group_column=None):
- """Regroup the results in the group column by the key columns."""
- self.group_by = tuple(group_by)
- self.group_column = group_column
- self.it = iter(results)
- self.tgtkey = self.currkey = self.currvalue = object()
-
- def keyfunc(self, row):
- return tuple(row[x] for x in self.group_by)
-
- def __iter__(self):
- return self
-
- def next(self):
- # find a start row
- while self.currkey == self.tgtkey:
- self.currvalue = next(self.it) # Exit on StopIteration
- self.currkey = self.keyfunc(self.currvalue)
- self.tgtkey = self.currkey
- # turn the result row into a list of columns
- row = list(self.currvalue)
- # replace the group column
- row[self.group_column] = list(self._grouper(self.tgtkey))
- return row
-
- def _grouper(self, tgtkey):
- """Generate the group columns."""
- while self.currkey == tgtkey:
- value = self.currvalue[self.group_column]
- if value is not None:
- yield value
- self.currvalue = next(self.it) # Exit on StopIteration
- self.currkey = self.keyfunc(self.currvalue)
-
-
-class Query(object):
- """Helper class to build an SQL query for the cache."""
-
- def __init__(self, query):
- self.query = query
- self.wheres = []
- self.parameters = []
-
- def add_where(self, where, parameters):
- self.wheres.append(where)
- self.parameters += parameters
-
- def execute(self, con):
- query = self.query
- if self.wheres:
- query += ' WHERE ' + ' AND '.join(self.wheres)
- cursor = con.cursor()
- return cursor.execute(query, self.parameters)
-
-
-class Cache(object):
- """The description of the cache."""
-
- retrieve_sql = None
- retrieve_by = dict()
- group_by = ()
- group_columns = ()
-
- def __init__(self):
- self.con = _get_connection()
- self.db = sys.modules[self.__module__].__name__
- if not hasattr(self, 'tables'):
- self.tables = ['%s_cache' % self.db]
- self.create()
-
- def create(self):
- """Create the needed tables if neccesary."""
- self.con.executescript(self.create_sql)
-
- def store(self, *values):
- """Store the values in the cache for the specified table.
- The order of the values is the order returned by the Reques.convert()
- function."""
- # split the values into simple (flat) values and one-to-many values
- simple_values = []
- multi_values = []
- for v in values:
- if isinstance(v, (list, tuple, set)):
- multi_values.append(v)
- else:
- simple_values.append(v)
- # insert the simple values
- simple_values.append(datetime.datetime.now())
- args = ', '.join(len(simple_values) * ('?', ))
- self.con.execute('''
- INSERT OR REPLACE INTO %s
- VALUES
- (%s)
- ''' % (self.tables[0], args), simple_values)
- # insert the one-to-many values
- for n, vlist in enumerate(multi_values):
- self.con.execute('''
- DELETE FROM %s
- WHERE `%s` = ?
- ''' % (self.tables[n + 1], self.db), (values[0], ))
- self.con.executemany('''
- INSERT INTO %s
- VALUES
- (?, ?)
- ''' % (self.tables[n + 1]), ((values[0], x) for x in vlist))
-
- def retrieve(self, parameters):
- """Retrieve all items from the cache based on the parameters
- supplied."""
- query = Query(self.retrieve_sql or '''
- SELECT *
- FROM %s
- ''' % self.tables[0])
- if parameters:
- for k, v in parameters.items():
- where = self.retrieve_by.get(k, '`%s`.`%s` = ?' % (self.tables[0], k))
- query.add_where(where, where.count('?') * [v])
- # group by
- # FIXME: find a nice way to turn group_by and group_columns into names
- results = query.execute(self.con)
- group_by = list(self.group_by + self.group_columns)
- for column in self.group_columns[::-1]:
- group_by.pop()
- results = regroup(results, group_by, column)
- # strip the mtime from the results
- return (list(x)[:-1] for x in results)
-
- def __enter__(self):
- return self.con.__enter__();
-
- def __exit__(self, *args):
- return self.con.__exit__(*args);
-
-
-# the connection to the sqlite database
-_connection = None
-
-
-# FIXME: make tread safe (is this needed the way the caches are initialised?)
-def _get_connection():
- global _connection
- if _connection is None:
- filename = '/tmp/pynslcd_cache.sqlite'
- dirname = os.path.dirname(filename)
- if not os.path.isdir(dirname):
- os.mkdir(dirname)
- connection = sqlite3.connect(
- filename, detect_types=sqlite3.PARSE_DECLTYPES,
- check_same_thread=False)
- connection.row_factory = sqlite3.Row
- # initialise connection properties
- connection.executescript('''
- -- store temporary tables in memory
- PRAGMA temp_store = MEMORY;
- -- disable sync() on database (corruption on disk failure)
- PRAGMA synchronous = OFF;
- -- put journal in memory (corruption if crash during transaction)
- PRAGMA journal_mode = MEMORY;
- ''')
- _connection = connection
- return _connection
diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py
deleted file mode 100644
index 90acbeb..0000000
--- a/pynslcd/cfg.py
+++ /dev/null
@@ -1,332 +0,0 @@
-
-# cfg.py - module for accessing configuration information
-#
-# Copyright (C) 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
-
-import logging
-import re
-
-import ldap
-
-
-# the number of threads to start
-threads = 5
-# the user id nslcd should be run as
-uid = None
-# the group id nslcd should be run as
-gid = None
-# the configured loggers
-logs = []
-
-# the LDAP server to use
-uri = None # FIXME: support multiple servers and have a fail-over mechanism
-# LDAP protocol version to use (perhaps fix at 3?)
-ldap_version = ldap.VERSION3
-# the DN to use when binding
-binddn = None # FIXME: add support
-bindpw = None # FIXME: add support
-# the DN to use to perform password modifications as root
-rootpwmoddn = None
-rootpwmodpw = None
-
-# SASL configuration
-sasl_mech = None # FIXME: add support
-sasl_realm = None # FIXME: add support
-sasl_authcid = None # FIXME: add support
-sasl_authzid = None # FIXME: add support
-sasl_secprops = None # FIXME: add support
-sasl_canonicalize = None # FIXME: add support
-
-# LDAP bases to search
-bases = []
-# default search scope for searches
-scope = ldap.SCOPE_SUBTREE
-
-deref = ldap.DEREF_NEVER
-referrals = True
-
-# timing configuration
-bind_timelimit = 10 # FIXME: add support
-timelimit = ldap.NO_LIMIT
-idle_timelimit = 0 # FIXME: add support
-reconnect_sleeptime = 1 # FIXME: add support
-reconnect_retrytime = 10
-
-# SSL/TLS options
-ssl = None
-tls_reqcert = None
-tls_cacertdir = None
-tls_cacertfile = None
-tls_randfile = None
-tls_ciphers = None
-tls_cert = None
-tls_key = None
-
-# other options
-pagesize = 0 # FIXME: add support
-nss_initgroups_ignoreusers = set()
-nss_min_uid = 0
-nss_nested_groups = False
-validnames = re.compile(r'^[a-z0-9._@$][a-z0-9._@$ \\~-]{0,98}[a-z0-9._@$~-]$', re.IGNORECASE)
-pam_authz_searches = []
-pam_password_prohibit_message = None
-reconnect_invalidate = set()
-
-
-# allowed boolean values
-_boolean_options = {'on': True, 'yes': True, 'true': True, '1': True,
- 'off': False, 'no': False, 'false': False, '0': False}
-
-# allowed log levels (we log notice which is unsupported in Python to warning)
-_log_levels = {'crit': logging.CRITICAL, 'error': logging.ERROR,
- 'err': logging.ERROR, 'warning': logging.WARNING,
- 'notice': logging.WARNING, 'info': logging.INFO,
- 'debug': logging.DEBUG, 'none': logging.INFO}
-
-# allowed values for scope option
-if not hasattr(ldap, 'SCOPE_CHILDREN') and ldap.VENDOR_VERSION >= 20400:
- ldap.SCOPE_CHILDREN = 3 # OpenLDAP extension
-_scope_options = dict(sub=ldap.SCOPE_SUBTREE, subtree=ldap.SCOPE_SUBTREE,
- one=ldap.SCOPE_ONELEVEL, onelevel=ldap.SCOPE_ONELEVEL,
- base=ldap.SCOPE_BASE)
-if hasattr(ldap, 'SCOPE_CHILDREN'):
- _scope_options['children'] = ldap.SCOPE_CHILDREN
-
-# allowed values for the deref option
-_deref_options = dict(never=ldap.DEREF_NEVER,
- searching=ldap.DEREF_SEARCHING,
- finding=ldap.DEREF_FINDING,
- always=ldap.DEREF_ALWAYS)
-
-# allowed values for the ssl option
-_ssl_options = dict(start_tls='STARTTLS', starttls='STARTTLS',
- on='LDAPS', off=None)
-
-# allowed values for the tls_reqcert option
-_tls_reqcert_options = {'never': ldap.OPT_X_TLS_NEVER,
- 'no': ldap.OPT_X_TLS_NEVER,
- 'allow': ldap.OPT_X_TLS_ALLOW,
- 'try': ldap.OPT_X_TLS_TRY,
- 'demand': ldap.OPT_X_TLS_DEMAND,
- 'yes': ldap.OPT_X_TLS_DEMAND,
- 'hard': ldap.OPT_X_TLS_HARD}
-
-
-def _get_maps():
- # separate function as not to pollute the namespace and avoid import loops
- import alias, ether, group, host, netgroup, network, passwd
- import protocol, rpc, service, shadow
- import sys
- return dict(
- alias=alias, aliases=alias,
- ether=ether, ethers=ether,
- group=group,
- host=host, hosts=host,
- netgroup=netgroup,
- network=network, networks=network,
- passwd=passwd,
- protocol=protocol, protocols=protocol,
- rpc=rpc,
- service=service, services=service,
- shadow=shadow,
- none=sys.modules[__name__]
- )
-
-
-class ParseError(Exception):
-
- def __init__(self, filename, lineno, message):
- self.message = '%s:%d: %s' % (filename, lineno, message)
-
- def __repr__(self):
- return self.message
-
- __str__ = __repr__
-
-
-def read(filename):
- maps = _get_maps()
- lineno = 0
- for line in open(filename, 'r'):
- lineno += 1
- line = line.strip()
- # skip comments and blank lines
- if re.match('(#.*)?$', line, re.IGNORECASE):
- continue
- # parse options with a single integer argument
- m = re.match('(?P<keyword>threads|ldap_version|bind_timelimit|timelimit|idle_timelimit|reconnect_sleeptime|reconnect_retrytime|pagesize|nss_min_uid)\s+(?P<value>\d+)',
- line, re.IGNORECASE)
- if m:
- globals()[m.group('keyword').lower()] = int(m.group('value'))
- continue
- # parse options with a single boolean argument
- m = re.match('(?P<keyword>referrals|nss_nested_groups)\s+(?P<value>%s)' %
- '|'.join(_boolean_options.keys()),
- line, re.IGNORECASE)
- if m:
- globals()[m.group('keyword').lower()] = _boolean_options[m.group('value').lower()]
- continue
- # parse options with a single no-space value
- m = re.match('(?P<keyword>uid|gid|bindpw|rootpwmodpw|sasl_mech)\s+(?P<value>\S+)',
- line, re.IGNORECASE)
- if m:
- globals()[m.group('keyword').lower()] = m.group('value')
- continue
- # parse options with a single value that can contain spaces
- m = re.match('(?P<keyword>binddn|rootpwmoddn|sasl_realm|sasl_authcid|sasl_authzid|sasl_secprops|krb5_ccname|tls_cacertdir|tls_cacertfile|tls_randfile|tls_ciphers|tls_cert|tls_key|pam_password_prohibit_message)\s+(?P<value>\S.*)',
- line, re.IGNORECASE)
- if m:
- globals()[m.group('keyword').lower()] = m.group('value')
- continue
- # log <SCHEME> [<LEVEL>]
- m = re.match('log\s+(?P<scheme>syslog|/\S*)(\s+(?P<level>%s))?' %
- '|'.join(_log_levels.keys()),
- line, re.IGNORECASE)
- if m:
- logs.append((m.group('scheme'), _log_levels[str(m.group('level')).lower()]))
- continue
- # uri <URI>
- m = re.match('uri\s+(?P<uri>\S+)', line, re.IGNORECASE)
- if m:
- # FIXME: support multiple URI values
- # FIXME: support special DNS and DNS:domain values
- global uri
- uri = m.group('uri')
- continue
- # base <MAP>? <BASEDN>
- m = re.match('base\s+((?P<map>%s)\s+)?(?P<value>\S.*)' %
- '|'.join(maps.keys()),
- line, re.IGNORECASE)
- if m:
- mod = maps[str(m.group('map')).lower()]
- if not hasattr(mod, 'bases'):
- mod.bases = []
- mod.bases.append(m.group('value'))
- continue
- # filter <MAP> <SEARCHFILTER>
- m = re.match('filter\s+(?P<map>%s)\s+(?P<value>\S.*)' %
- '|'.join(maps.keys()),
- line, re.IGNORECASE)
- if m:
- mod = maps[m.group('map').lower()]
- mod.filter = m.group('value')
- continue
- # scope <MAP>? <SCOPE>
- m = re.match('scope\s+((?P<map>%s)\s+)?(?P<value>%s)' % (
- '|'.join(maps.keys()),
- '|'.join(_scope_options.keys())),
- line, re.IGNORECASE)
- if m:
- mod = maps[str(m.group('map')).lower()]
- mod.scope = _scope_options[m.group('value').lower()]
- continue
- # map <MAP> <ATTRIBUTE> <ATTMAPPING>
- m = re.match('map\s+(?P<map>%s)\s+(?P<attribute>\S+)\s+(?P<value>\S.*)' %
- '|'.join(maps.keys()),
- line, re.IGNORECASE)
- if m:
- mod = maps[m.group('map').lower()]
- attribute = m.group('attribute')
- if attribute not in mod.attmap:
- raise ParseError(filename, lineno, 'attribute %s unknown' % attribute)
- mod.attmap[attribute] = m.group('value')
- # TODO: filter out attributes that cannot be an expression
- continue
- # deref <DEREF>
- m = re.match('deref\s+(?P<value>%s)' % '|'.join(_deref_options.keys()),
- line, re.IGNORECASE)
- if m:
- global deref
- deref = _deref_options[m.group('value').lower()]
- continue
- # nss_initgroups_ignoreusers <USER,USER>|<ALLLOCAL>
- m = re.match('nss_initgroups_ignoreusers\s+(?P<value>\S.*)',
- line, re.IGNORECASE)
- if m:
- users = m.group('value')
- if users.lower() == 'alllocal':
- # get all users known to the system currently (since nslcd
- # isn't yet running, this should work)
- import pwd
- users = (x.pw_name for x in pwd.getpwall())
- else:
- users = users.split(',')
- # TODO: warn about unknown users
- nss_initgroups_ignoreusers.update(users)
- continue
- # pam_authz_search <FILTER>
- m = re.match('pam_authz_search\s+(?P<value>\S.*)', line, re.IGNORECASE)
- if m:
- from expr import Expression
- pam_authz_searches.append(Expression(m.group('value')))
- # TODO: check pam_authz_search expression to only contain
- # username, service, ruser, rhost, tty, hostname, fqdn, dn or
- # uid variables
- continue
- # ssl <on|off|start_tls>
- m = re.match('ssl\s+(?P<value>%s)' % '|'.join(_ssl_options.keys()),
- line, re.IGNORECASE)
- if m:
- global ssl
- ssl = _ssl_options[m.group('value').lower()]
- continue
- # sasl_canonicalize yes|no
- m = re.match('(ldap_?)?sasl_(?P<no>no)?canon(icali[sz]e)?\s+(?P<value>%s)' %
- '|'.join(_boolean_options.keys()),
- line, re.IGNORECASE)
- if m:
- global sasl_canonicalize
- sasl_canonicalize = _boolean_options[m.group('value').lower()]
- if m.group('no'):
- sasl_canonicalize = not sasl_canonicalize
- continue
- # tls_reqcert <demand|hard|yes...>
- m = re.match('tls_reqcert\s+(?P<value>%s)' %
- '|'.join(_tls_reqcert_options.keys()),
- line, re.IGNORECASE)
- if m:
- global tls_reqcert
- tls_reqcert = _tls_reqcert_options[m.group('value').lower()]
- continue
- # validnames /REGEX/i?
- m = re.match('validnames\s+/(?P<value>.*)/(?P<flags>[i]?)$',
- line, re.IGNORECASE)
- if m:
- global validnames
- flags = 0 | re.IGNORECASE if m.group('flags') == 'i' else 0
- validnames = re.compile(m.group('value'), flags=flags)
- continue
- # reconnect_invalidate <MAP>,<MAP>,...
- m = re.match('reconnect_invalidate\s+(?P<value>\S.*)',
- line, re.IGNORECASE)
- if m:
- dbs = re.split('[ ,]+', m.group('value').lower())
- for db in dbs:
- if db not in maps.keys() + ['nfsidmap']:
- raise ParseError(filename, lineno, 'map %s unknown' % db)
- reconnect_invalidate.update(dbs)
- continue
- # unrecognised line
- raise ParseError(filename, lineno, 'error parsing line %r' % line)
- # if logging is not configured, default to syslog
- if not logs:
- logs.append(('syslog', logging.INFO))
- # dump config (debugging code)
- for k, v in globals().items():
- if not k.startswith('_'):
- logging.debug('%s=%r', k, v)
diff --git a/pynslcd/common.py b/pynslcd/common.py
deleted file mode 100644
index 97899ad..0000000
--- a/pynslcd/common.py
+++ /dev/null
@@ -1,138 +0,0 @@
-
-# common.py - functions that are used by different modules
-#
-# Copyright (C) 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
-
-import logging
-import sys
-
-import ldap
-
-from attmap import Attributes
-#import cache
-import cfg
-import constants
-
-
-def is_valid_name(name):
- """Checks to see if the specified name seems to be a valid user or group
- name.
-
- This test is based on the definition from POSIX (IEEE Std 1003.1, 2004,
- 3.426 User Name, 3.189 Group Name and 3.276 Portable Filename Character Set):
- http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_426
- http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_189
- http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276
-
- The standard defines user names valid if they contain characters from
- the set [A-Za-z0-9._-] where the hyphen should not be used as first
- character. As an extension this test allows some more characters."""
- return bool(cfg.validnames.search(name))
-
-
-def validate_name(name):
- """Checks to see if the specified name seems to be a valid user or group
- name. See is_valid_name()."""
- if not cfg.validnames.search(name):
- raise ValueError('%r: denied by validnames option' % name)
-
-
-class Request(object):
- """
- Request handler class. Subclasses are expected to handle actual requests
- and should implement the following members:
-
- action - the NSLCD_ACTION_* action that should trigger this handler
-
- read_parameters() - a function that reads the request parameters of the
- request stream
- write() - function that writes a single LDAP entry to the result stream
-
- """
-
- def __init__(self, fp, conn, calleruid):
- self.fp = fp
- self.conn = conn
- self.calleruid = calleruid
- module = sys.modules[self.__module__]
- self.search = getattr(module, 'Search', None)
- #if not hasattr(module, 'cache_obj'):
- # cache_cls = getattr(module, 'Cache', None)
- # module.cache_obj = cache_cls() if cache_cls else None
- #self.cache = module.cache_obj
- self.cache = None
-
- def read_parameters(self, fp):
- """This method should read and return the parameters from the
- stream."""
- pass
-
- def get_results(self, parameters):
- """Provide the result entries by performing a search."""
- for dn, attributes in self.search(self.conn, parameters=parameters):
- for values in self.convert(dn, attributes, parameters):
- yield values
-
- def handle_request(self, parameters):
- """This method handles the request based on the parameters read
- with read_parameters()."""
- try:
- #with cache.con:
- if True:
- for values in self.get_results(parameters):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.write(*values)
- if self.cache:
- self.cache.store(*values)
- except ldap.SERVER_DOWN:
- if self.cache:
- logging.debug('read from cache')
- # we assume server went down before writing any entries
- for values in self.cache.retrieve(parameters):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.write(*values)
- else:
- raise
- # write the final result code
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def log(self, parameters):
- parameters = dict(parameters)
- for param in ('password', 'oldpassword', 'newpassword'):
- if parameters.get(param):
- parameters[param] = '***'
- logging.debug('%s(%r)', self.__class__.__name__, parameters)
-
- def __call__(self):
- parameters = self.read_parameters(self.fp) or {}
- self.log(parameters)
- self.fp.write_int32(constants.NSLCD_VERSION)
- self.fp.write_int32(self.action)
- self.handle_request(parameters)
-
-
-def get_handlers(module):
- """Return a dictionary mapping actions to Request classes."""
- import inspect
- res = {}
- if isinstance(module, basestring):
- module = __import__(module, globals())
- for name, cls in inspect.getmembers(module, inspect.isclass):
- if issubclass(cls, Request) and hasattr(cls, 'action'):
- res[cls.action] = cls
- return res
diff --git a/pynslcd/config.py b/pynslcd/config.py
deleted file mode 100644
index ee57db3..0000000
--- a/pynslcd/config.py
+++ /dev/null
@@ -1,45 +0,0 @@
-
-# config.py - routines for getting configuration information
-#
-# Copyright (C) 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
-
-import cfg
-import common
-import constants
-
-
-class ConfigGetRequest(common.Request):
-
- action = constants.NSLCD_ACTION_CONFIG_GET
-
- def read_parameters(self, fp):
- return dict(cfgopt=fp.read_int32())
- # TODO: log call with parameters
-
- def write(self, value):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.fp.write_string(value)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def handle_request(self, parameters):
- cfgopt = parameters['cfgopt']
- if cfgopt == constants.NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE:
- self.write(cfg.pam_password_prohibit_message or '')
- else:
- # return empty response
- self.fp.write_int32(constants.NSLCD_RESULT_END)
diff --git a/pynslcd/constants.py.in b/pynslcd/constants.py.in
deleted file mode 100644
index 4f57e34..0000000
--- a/pynslcd/constants.py.in
+++ /dev/null
@@ -1,51 +0,0 @@
-
-# constants.py - configured information and constants, this file is processed
-# and extended by the configure script
-#
-# Copyright (C) 2012 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
-
-
-# Name of package
-PACKAGE = '''@PACKAGE@'''
-
-# Define to the address where bug reports for this package should be sent.
-PACKAGE_BUGREPORT = '''@PACKAGE_BUGREPORT@'''
-
-# Define to the full name of this package.
-PACKAGE_NAME = '''@PACKAGE_NAME@'''
-
-# Define to the full name and version of this package.
-PACKAGE_STRING = '''@PACKAGE_STRING@'''
-
-# Define to the home page for this package.
-PACKAGE_URL = '''@PACKAGE_URL@'''
-
-# Version number of package
-VERSION = '''@VERSION@'''
-
-# Path to nslcd configuration file.
-NSLCD_CONF_PATH = '''@NSLCD_CONF_PATH@'''
-
-# The location of the pidfile used for checking availability of the nslcd.
-NSLCD_PIDFILE = '''@NSLCD_PIDFILE@'''
-
-# The location of the socket used for communicating.
-NSLCD_SOCKET = '''@NSLCD_SOCKET@'''
-
-# The SONAME of the NSS library module.
-NSS_LDAP_SONAME = '''@NSS_LDAP_SONAME@'''
diff --git a/pynslcd/ether.py b/pynslcd/ether.py
deleted file mode 100644
index e5060ca..0000000
--- a/pynslcd/ether.py
+++ /dev/null
@@ -1,102 +0,0 @@
-
-# ether.py - lookup functions for ethernet addresses
-#
-# Copyright (C) 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
-
-import struct
-
-import cache
-import common
-import constants
-import search
-
-
-def ether_aton(ether):
- """Converst an ethernet address to binary form in network byte order."""
- return struct.pack('BBBBBB', *(int(x, 16) for x in ether.split(':')))
-
-
-def ether_ntoa(ether):
- """Conversts an ethernet address in network byte order to the string
- representation."""
- return ':'.join('%x' % x for x in struct.unpack('6B', ether))
-
-
-attmap = common.Attributes(cn='cn', macAddress='macAddress')
-filter = '(objectClass=ieee802Device)'
-
-
-class Search(search.LDAPSearch):
-
- case_insensitive = ('cn', )
- limit_attributes = ('cn', 'macAddress')
- required = ('cn', 'macAddress')
-
- def mk_filter(self):
- # we need a custom mk_filter because this is an | query
- if 'macAddress' in self.parameters:
- ether = self.parameters['macAddress']
- alt_ether = ':'.join('%02x' % int(x, 16) for x in ether.split(':'))
- return '(&%s(|(%s=%s)(%s=%s)))' % (self.filter,
- attmap['macAddress'], ether,
- attmap['macAddress'], alt_ether)
- return super(Search, self).mk_filter()
-
-
-class Cache(cache.Cache):
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `ether_cache`
- ( `cn` TEXT NOT NULL COLLATE NOCASE,
- `macAddress` TEXT NOT NULL COLLATE NOCASE,
- `mtime` TIMESTAMP NOT NULL,
- UNIQUE (`cn`, `macAddress`) );
- '''
-
-
-class EtherRequest(common.Request):
-
- def write(self, name, ether):
- self.fp.write_string(name)
- self.fp.write(ether_aton(ether))
-
- def convert(self, dn, attributes, parameters):
- for name in attributes['cn']:
- for ether in attributes['macAddress']:
- yield (name, ether)
-
-
-class EtherByNameRequest(EtherRequest):
-
- action = constants.NSLCD_ACTION_ETHER_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class EtherByEtherRequest(EtherRequest):
-
- action = constants.NSLCD_ACTION_ETHER_BYETHER
-
- def read_parameters(self, fp):
- return dict(macAddress=ether_ntoa(fp.read(6)))
-
-
-class EtherAllRequest(EtherRequest):
-
- action = constants.NSLCD_ACTION_ETHER_ALL
diff --git a/pynslcd/expr.py b/pynslcd/expr.py
deleted file mode 100644
index 24728cc..0000000
--- a/pynslcd/expr.py
+++ /dev/null
@@ -1,223 +0,0 @@
-
-# expr.py - expression handling functions
-#
-# Copyright (C) 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
-
-"""Module for handling expressions used for LDAP searches.
-
->>> expr = Expression('foo=$foo')
->>> expr.value(dict(foo='XX'))
-'foo=XX'
->>> expr = Expression('foo=${foo:-$bar}')
->>> expr.value(dict(foo='', bar='YY'))
-'foo=YY'
->>> expr.value(dict(bar=['YY', 'ZZ']))
-'foo=YY'
->>> Expression(r'${passwd#{crypt\}}').value(dict(passwd='{crypt}HASH'))
-'HASH'
->>> Expression('${var#trim}').value(dict(var='notrimme'))
-'notrimme'
->>> Expression('${var#?trim}').value(dict(var='xtrimme'))
-'me'
->>> Expression('${var#*trim}').value(dict(var='xxxtrimme'))
-'me'
->>> Expression('${var%.txt}').value(dict(var='foo.txt'))
-'foo'
->>> Expression('${x#$y}').value(dict(x='a/b', y='a'))
-'/b'
->>> Expression('${var#t*is}').value(dict(var='this is a test'))
-' is a test'
->>> Expression('${var##t*is}').value(dict(var='this is a test'))
-' a test'
->>> Expression('${var%t*st}').value(dict(var='this is a test'))
-'this is a '
->>> Expression('${var%%t*st}').value(dict(var='this is a test'))
-''
-"""
-
-import fnmatch
-import re
-
-
-# exported names
-__all__ = ('Expression', )
-
-
-# TODO: do more expression validity checking
-
-
-class MyIter(object):
- """Custom iterator-like class with a back() method."""
-
- def __init__(self, value):
- self.value = value
- self.pos = 0
-
- def next(self):
- self.pos += 1
- try:
- return self.value[self.pos - 1]
- except IndexError:
- return None
-
- def back(self):
- self.pos -= 1
-
- def __iter__(self):
- return self
-
- def get_name(self):
- """Read a variable name from the value iterator."""
- name = ''
- for c in self:
- if not c or not c.isalnum():
- self.back()
- return name
- name += c
- return name
-
-
-class DollarExpression(object):
- """Class for handling a variable $xxx ${xxx}, ${xxx:-yyy} or ${xxx:+yyy}
- expression."""
-
- def __init__(self, value):
- """Parse the expression as the start of a $-expression."""
- self.op = None
- self.expr = None
- c = value.next()
- if c == '{':
- self.name = value.get_name()
- c = value.next()
- if c == '}':
- return
- elif c == ':':
- self.op = c + value.next()
- elif c in ('#', '%'):
- c2 = value.next()
- if c2 in ('#', '%'):
- c += c2
- else:
- value.back()
- self.op = c
- else:
- raise ValueError('Expecting operator')
- self.expr = Expression(value, endat='}')
- elif c == '(':
- self.name = None
- self.op = value.get_name()
- c = value.next()
- if c != '(':
- raise ValueError("Expecting '('")
- self.expr = Expression(value, endat=')')
- c = value.next()
- if c != ')':
- raise ValueError("Expecting ')'")
- else:
- value.back()
- self.name = value.get_name()
-
- def value(self, variables):
- """Expand the expression using the variables specified."""
- # lookup the value
- value = variables.get(self.name, '')
- if value in (None, [], ()):
- value = ''
- elif isinstance(value, (list, tuple)):
- value = value[0]
- # TODO: try to return multiple values, one for each value of the list
- if self.op == ':-':
- return value if value else self.expr.value(variables)
- elif self.op == ':+':
- return self.expr.value(variables) if value else ''
- elif self.op in ('#', '##', '%', '%%'):
- match = fnmatch.translate(self.expr.value(variables))
- if self.op == '#':
- match = match.replace('*', '*?').replace(r'\Z', r'(?P<replace>.*)\Z')
- elif self.op == '##':
- match = match.replace(r'\Z', r'(?P<replace>.*?)\Z')
- elif self.op == '%':
- match = r'(?P<replace>.*)' + match.replace('*', '*?')
- elif self.op == '%%':
- match = r'(?P<replace>.*?)' + match
- match = re.match(match, value)
- return match.group('replace') if match else value
- elif self.op == 'lower':
- return self.expr.value(variables).lower()
- elif self.op == 'upper':
- return self.expr.value(variables).upper()
- return value
-
- def variables(self, results):
- """Add the variables used in the expression to results."""
- if self.name:
- results.add(self.name)
- if self.expr:
- self.expr.variables(results)
-
-
-class Expression(object):
- """Class for parsing and expanding an expression."""
-
- def __init__(self, value, endat=None):
- """Parse the expression as a string."""
- if not isinstance(value, MyIter):
- self.expression = value
- value = MyIter(value)
- expr = []
- literal = ''
- c = value.next()
- while c != endat:
- if c == '$':
- if literal:
- expr.append(literal)
- expr.append(DollarExpression(value))
- literal = ''
- elif c == '\\':
- literal += value.next()
- else:
- literal += c
- c = value.next()
- if literal:
- expr.append(literal)
- self.expr = expr
-
- def value(self, variables):
- """Expand the expression using the variables specified."""
- res = ''
- for x in self.expr:
- if hasattr(x, 'value'):
- res += x.value(variables)
- else:
- res += x
- return res
-
- def variables(self, results=None):
- """Return the variables defined in the expression."""
- if not results:
- results = set()
- for x in self.expr:
- if hasattr(x, 'variables'):
- x.variables(results)
- return results
-
- def __str__(self):
- return self.expression
-
- def __repr__(self):
- return repr(str(self))
diff --git a/pynslcd/group.py b/pynslcd/group.py
deleted file mode 100644
index c8abfe5..0000000
--- a/pynslcd/group.py
+++ /dev/null
@@ -1,229 +0,0 @@
-
-# group.py - group entry lookup routines
-#
-# Copyright (C) 2010-2014 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
-
-import logging
-
-from ldap.filter import escape_filter_chars
-import ldap
-
-import cache
-import cfg
-import common
-import constants
-import passwd
-import search
-
-
-def clean(lst):
- if lst:
- for i in lst:
- yield i.replace('\0', '')
-
-
-attmap = common.Attributes(cn='cn',
- userPassword='"*"',
- gidNumber='gidNumber',
- memberUid='memberUid',
- member='member')
-filter = '(objectClass=posixGroup)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('cn', )
- limit_attributes = ('cn', 'gidNumber')
-
- def __init__(self, *args, **kwargs):
- super(Search, self).__init__(*args, **kwargs)
- if 'memberUid' in self.parameters or 'member' in self.parameters:
- # set up our own attributes that leave out membership attributes
- self.attributes = list(self.attributes)
- if attmap['memberUid'] in self.attributes:
- self.attributes.remove(attmap['memberUid'])
- if attmap['member'] in self.attributes:
- self.attributes.remove(attmap['member'])
-
- def mk_filter(self):
- # we still need a custom mk_filter because this is an | query
- if attmap['member'] and 'memberUid' in self.parameters:
- memberuid = self.parameters['memberUid']
- entry = passwd.uid2entry(self.conn, memberuid)
- if entry:
- return '(&%s(|(%s=%s)(%s=%s)))' % (
- self.filter,
- attmap['memberUid'], escape_filter_chars(memberuid),
- attmap['member'], escape_filter_chars(entry[0])
- )
- return super(Search, self).mk_filter()
-
-
-class Cache(cache.Cache):
-
- tables = ('group_cache', 'group_member_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `group_cache`
- ( `cn` TEXT PRIMARY KEY,
- `userPassword` TEXT,
- `gidNumber` INTEGER NOT NULL UNIQUE,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `group_member_cache`
- ( `group` TEXT NOT NULL,
- `memberUid` TEXT NOT NULL,
- FOREIGN KEY(`group`) REFERENCES `group_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `group_member_idx` ON `group_member_cache`(`group`);
- '''
-
- retrieve_sql = '''
- SELECT `group_cache`.`cn` AS `cn`, `userPassword`, `gidNumber`,
- `memberUid`, `mtime`
- FROM `group_cache`
- LEFT JOIN `group_member_cache`
- ON `group_member_cache`.`group` = `group_cache`.`cn`
- '''
-
- retrieve_by = dict(
- memberUid='''
- `cn` IN (
- SELECT `a`.`group`
- FROM `group_member_cache` `a`
- WHERE `a`.`memberUid` = ?)
- ''',
- )
-
- group_by = (0, ) # cn
- group_columns = (3, ) # memberUid
-
-
-class GroupRequest(common.Request):
-
- def write(self, name, passwd, gid, members):
- self.fp.write_string(name)
- self.fp.write_string(passwd)
- self.fp.write_int32(gid)
- self.fp.write_stringlist(members)
-
- def get_members(self, attributes, members, subgroups, seen):
- # add the memberUid values
- for member in clean(attributes['memberUid']):
- if common.is_valid_name(member):
- members.add(member)
- # translate and add the member values
- if attmap['member']:
- for memberdn in clean(attributes['member']):
- if memberdn in seen:
- continue
- seen.add(memberdn)
- member = passwd.dn2uid(self.conn, memberdn)
- if member and common.is_valid_name(member):
- members.add(member)
- elif cfg.nss_nested_groups:
- subgroups.append(memberdn)
-
- def convert(self, dn, attributes, parameters):
- # get group names and check against requested group name
- names = attributes['cn']
- # get group password
- try:
- passwd = attributes['userPassword'][0]
- except IndexError:
- passwd = None
- if not passwd or self.calleruid != 0:
- passwd = '*'
- # get group id(s)
- gids = [int(x) for x in attributes['gidNumber']]
- # build member list
- members = set()
- subgroups = []
- seen = set([dn])
- self.get_members(attributes, members, subgroups, seen)
- # go over subgroups to find more members
- while subgroups:
- memberdn = subgroups.pop(0)
- for dn2, attributes2 in self.search(self.conn, base=memberdn, scope=ldap.SCOPE_BASE):
- self.get_members(attributes2, members, subgroups, seen)
- # actually return the results
- for name in names:
- if not common.is_valid_name(name):
- logging.warning('%s: %s: denied by validnames option', dn,
- attmap['cn'])
- else:
- for gid in gids:
- yield (name, passwd, gid, members)
-
-
-class GroupByNameRequest(GroupRequest):
-
- action = constants.NSLCD_ACTION_GROUP_BYNAME
-
- def read_parameters(self, fp):
- name = fp.read_string()
- common.validate_name(name)
- return dict(cn=name)
-
-
-class GroupByGidRequest(GroupRequest):
-
- action = constants.NSLCD_ACTION_GROUP_BYGID
-
- def read_parameters(self, fp):
- return dict(gidNumber=fp.read_int32())
-
-
-class GroupByMemberRequest(GroupRequest):
-
- action = constants.NSLCD_ACTION_GROUP_BYMEMBER
-
- def read_parameters(self, fp):
- memberuid = fp.read_string()
- common.validate_name(memberuid)
- return dict(memberUid=memberuid)
-
- def get_results(self, parameters):
- seen = set()
- for dn, attributes in self.search(self.conn, parameters=parameters):
- seen.add(dn)
- for values in self.convert(dn, attributes, parameters):
- yield values
- if cfg.nss_nested_groups and attmap['member']:
- tocheck = list(seen)
- # find parent groups
- while tocheck:
- group = tocheck.pop(0)
- for dn, attributes in self.search(self.conn, parameters=dict(member=group)):
- if dn not in seen:
- seen.add(dn)
- tocheck.append(dn)
- for result in self.convert(dn, attributes, parameters):
- yield result
-
- def handle_request(self, parameters):
- # check whether requested user is in nss_initgroups_ignoreusers
- if parameters['memberUid'] in cfg.nss_initgroups_ignoreusers:
- # write the final result code to signify empty results
- self.fp.write_int32(constants.NSLCD_RESULT_END)
- return
- return super(GroupByMemberRequest, self).handle_request(parameters)
-
-
-class GroupAllRequest(GroupRequest):
-
- action = constants.NSLCD_ACTION_GROUP_ALL
diff --git a/pynslcd/host.py b/pynslcd/host.py
deleted file mode 100644
index 04f5337..0000000
--- a/pynslcd/host.py
+++ /dev/null
@@ -1,123 +0,0 @@
-
-# host.py - lookup functions for host names and addresses
-#
-# Copyright (C) 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
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(cn='cn', ipHostNumber='ipHostNumber')
-filter = '(objectClass=ipHost)'
-
-
-class Search(search.LDAPSearch):
-
- canonical_first = ('cn', )
- required = ('cn', )
-
-
-class Cache(cache.Cache):
-
- tables = ('host_cache', 'host_alias_cache', 'host_address_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `host_cache`
- ( `cn` TEXT PRIMARY KEY COLLATE NOCASE,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `host_alias_cache`
- ( `host` TEXT NOT NULL COLLATE NOCASE,
- `cn` TEXT NOT NULL COLLATE NOCASE,
- FOREIGN KEY(`host`) REFERENCES `host_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `host_alias_idx` ON `host_alias_cache`(`host`);
- CREATE TABLE IF NOT EXISTS `host_address_cache`
- ( `host` TEXT NOT NULL COLLATE NOCASE,
- `ipHostNumber` TEXT NOT NULL,
- FOREIGN KEY(`host`) REFERENCES `host_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `host_address_idx` ON `host_address_cache`(`host`);
- '''
-
- retrieve_sql = '''
- SELECT `host_cache`.`cn` AS `cn`,
- `host_alias_cache`.`cn` AS `alias`,
- `host_address_cache`.`ipHostNumber` AS `ipHostNumber`,
- `host_cache`.`mtime` AS `mtime`
- FROM `host_cache`
- LEFT JOIN `host_alias_cache`
- ON `host_alias_cache`.`host` = `host_cache`.`cn`
- LEFT JOIN `host_address_cache`
- ON `host_address_cache`.`host` = `host_cache`.`cn`
- '''
-
- retrieve_by = dict(
- cn='''
- ( `host_cache`.`cn` = ? OR
- `host_cache`.`cn` IN (
- SELECT `by_alias`.`host`
- FROM `host_alias_cache` `by_alias`
- WHERE `by_alias`.`cn` = ?))
- ''',
- ipHostNumber='''
- `host_cache`.`cn` IN (
- SELECT `by_ipHostNumber`.`host`
- FROM `host_address_cache` `by_ipHostNumber`
- WHERE `by_ipHostNumber`.`ipHostNumber` = ?)
- ''',
- )
-
- group_by = (0, ) # cn
- group_columns = (1, 2) # alias, ipHostNumber
-
-
-class HostRequest(common.Request):
-
- def write(self, hostname, aliases, addresses):
- self.fp.write_string(hostname)
- self.fp.write_stringlist(aliases)
- self.fp.write_int32(len(addresses))
- for address in addresses:
- self.fp.write_address(address)
-
- def convert(self, dn, attributes, parameters):
- hostnames = attributes['cn']
- yield (hostnames[0], hostnames[1:], attributes['ipHostNumber'])
-
-
-class HostByNameRequest(HostRequest):
-
- action = constants.NSLCD_ACTION_HOST_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class HostByAddressRequest(HostRequest):
-
- action = constants.NSLCD_ACTION_HOST_BYADDR
-
- def read_parameters(self, fp):
- return dict(ipHostNumber=fp.read_address())
-
-
-class HostAllRequest(HostRequest):
-
- action = constants.NSLCD_ACTION_HOST_ALL
diff --git a/pynslcd/invalidator.py b/pynslcd/invalidator.py
deleted file mode 100644
index 4f260c3..0000000
--- a/pynslcd/invalidator.py
+++ /dev/null
@@ -1,112 +0,0 @@
-
-# invalidator.py - functions for invalidating external caches
-#
-# Copyright (C) 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
-
-import fcntl
-import logging
-import os
-import subprocess
-
-import cfg
-
-
-# the file descriptor used for sending messages to the child process
-signalfd = None
-
-
-# mapping between map name and signal character
-_db_to_char = dict(
- aliases='A', ethers='E', group='G', hosts='H', netgroup='U',
- networks='N', passwd='P', protocols='L', rpc='R', services='V',
- shadow='S', nfsidmap='F',
- )
-_char_to_db = dict((reversed(item) for item in _db_to_char.items()))
-
-
-def exec_invalidate(*args):
- cmd = ' '.join(args)
- logging.debug('invalidator: %s', cmd)
- try:
- p = subprocess.Popen(args, bufsize=4096, close_fds=True,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- output, ignored = p.communicate()
- if output:
- output = ': %s' % output[:1024].strip()
- if p.returncode == 0:
- logging.debug('invalidator: %s (pid %d) success%s',
- cmd, p.pid, output)
- elif p.returncode > 0:
- logging.debug('invalidator: %s (pid %d) failed (%d)%s',
- cmd, p.pid, p.returncode, output)
- else: # p.returncode < 0
- logging.error('invalidator: %s (pid %d) killed by signal %d%s',
- cmd, p.pid, -p.returncode, output)
- except:
- logging.warn('invalidator: %s failed', cmd, exc_info=True)
-
-
-def loop(fd):
- # set process title
- try:
- import setproctitle
- setproctitle.setproctitle('(invalidator)')
- except ImportError:
- pass
- # set up clean environment
- os.chdir('/')
- os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin'
- while True:
- db = os.read(fd, 1)
- if db == '':
- break # close process down
- db = _char_to_db.get(db, None)
- if db == 'nfsidmap':
- exec_invalidate('nfsidmap', '-c')
- elif db:
- exec_invalidate('nscd', '-i', db)
-
-
-def start_invalidator():
- r, w = os.pipe()
- # mark write end as non-blocking
- flags = fcntl.fcntl(w, fcntl.F_GETFL)
- fcntl.fcntl(w, fcntl.F_SETFL, flags | os.O_NONBLOCK)
- cpid = os.fork()
- if cpid == 0:
- # we are the child
- os.close(w)
- loop(r)
- os._exit(1)
- # we are the parent
- global signalfd
- signalfd = w
- os.close(r)
-
-
-def invalidate(db=None):
- if signalfd is None:
- return # nothing to do
- if db:
- db = _db_to_char.get(db, '')
- else:
- db = ''.join(_db_to_char[x] for x in cfg.reconnect_invalidate)
- try:
- os.write(signalfd, db)
- except:
- logging.warn('requesting invalidation (%s) failed', db, exc_info=True)
diff --git a/pynslcd/mypidfile.py b/pynslcd/mypidfile.py
deleted file mode 100644
index e386f3e..0000000
--- a/pynslcd/mypidfile.py
+++ /dev/null
@@ -1,71 +0,0 @@
-
-# mypidfile.py - functions for properly locking a PIDFile
-#
-# Copyright (C) 2010, 2011, 2012 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
-
-import errno
-import fcntl
-import os
-
-
-class MyPIDLockFile(object):
- """Implementation of a PIDFile fit for use with the daemon module
- that locks the PIDFile with fcntl.lockf()."""
-
- def __init__(self, path):
- self.path = path
-
- def __enter__(self):
- """Lock the PID file and write the process ID to the file."""
- fd = os.open(self.path, os.O_RDWR | os.O_CREAT, 0644)
- try:
- fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
- pidfile = os.fdopen(fd, 'w')
- except:
- os.close(fd)
- raise
- pidfile.write('%d\n' % os.getpid())
- pidfile.truncate()
- pidfile.flush()
- self.pidfile = pidfile
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- """Release the lock (close the lockfile)."""
- fcntl.lockf(self.pidfile.fileno(), fcntl.LOCK_UN)
- self.pidfile.close()
- del self.pidfile
-
- def is_locked(self):
- """Check whether the file is already present and locked."""
- try:
- fd = os.open(self.path, os.O_RDWR, 0644)
- # Python doesn't seem to have F_TEST so we'll just try to lock
- fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
- # if we're here we must have aquired the lock
- fcntl.lockf(fd, fcntl.LOCK_UN)
- return False
- except (IOError, OSError), e:
- if e.errno == errno.ENOENT:
- return False
- if e.errno in (errno.EACCES, errno.EAGAIN):
- return True
- raise
- finally:
- if 'fd' in locals():
- os.close(fd)
diff --git a/pynslcd/netgroup.py b/pynslcd/netgroup.py
deleted file mode 100644
index d86e38c..0000000
--- a/pynslcd/netgroup.py
+++ /dev/null
@@ -1,116 +0,0 @@
-
-# netgroup.py - lookup functions for netgroups
-#
-# Copyright (C) 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
-
-import re
-
-import cache
-import common
-import constants
-import search
-
-
-_netgroup_triple_re = re.compile(r'^\s*\(\s*(?P<host>.*)\s*,\s*(?P<user>.*)\s*,\s*(?P<domain>.*)\s*\)\s*$')
-
-
-attmap = common.Attributes(cn='cn',
- nisNetgroupTriple='nisNetgroupTriple',
- memberNisNetgroup='memberNisNetgroup')
-filter = '(objectClass=nisNetgroup)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('cn', )
- required = ('cn', )
-
-
-class Cache(cache.Cache):
-
- tables = ('netgroup_cache', 'netgroup_triple_cache', 'netgroup_member_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `netgroup_cache`
- ( `cn` TEXT PRIMARY KEY COLLATE NOCASE,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `netgroup_triple_cache`
- ( `netgroup` TEXT NOT NULL COLLATE NOCASE,
- `nisNetgroupTriple` TEXT NOT NULL COLLATE NOCASE,
- FOREIGN KEY(`netgroup`) REFERENCES `netgroup_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `netgroup_triple_idx` ON `netgroup_triple_cache`(`netgroup`);
- CREATE TABLE IF NOT EXISTS `netgroup_member_cache`
- ( `netgroup` TEXT NOT NULL COLLATE NOCASE,
- `memberNisNetgroup` TEXT NOT NULL,
- FOREIGN KEY(`netgroup`) REFERENCES `netgroup_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `netgroup_membe_idx` ON `netgroup_member_cache`(`netgroup`);
- '''
-
- retrieve_sql = '''
- SELECT `netgroup_cache`.`cn` AS `cn`,
- `netgroup_triple_cache`.`nisNetgroupTriple` AS `nisNetgroupTriple`,
- `netgroup_member_cache`.`memberNisNetgroup` AS `memberNisNetgroup`,
- `netgroup_cache`.`mtime` AS `mtime`
- FROM `netgroup_cache`
- LEFT JOIN `netgroup_triple_cache`
- ON `netgroup_triple_cache`.`netgroup` = `netgroup_cache`.`cn`
- LEFT JOIN `netgroup_member_cache`
- ON `netgroup_member_cache`.`netgroup` = `netgroup_cache`.`cn`
- '''
-
- group_by = (0, ) # cn
- group_columns = (1, 2) # nisNetgroupTriple, memberNisNetgroup
-
-
-class NetgroupRequest(common.Request):
-
- def write(self, name, triples, members):
- self.fp.write_string(name)
- for triple in triples:
- m = _netgroup_triple_re.match(triple)
- if m:
- self.fp.write_int32(constants.NSLCD_NETGROUP_TYPE_TRIPLE)
- self.fp.write_string(m.group('host'))
- self.fp.write_string(m.group('user'))
- self.fp.write_string(m.group('domain'))
- for member in members:
- self.fp.write_int32(constants.NSLCD_NETGROUP_TYPE_NETGROUP)
- self.fp.write_string(member)
- self.fp.write_int32(constants.NSLCD_NETGROUP_TYPE_END)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['cn']
- triples = attributes['nisNetgroupTriple']
- members = attributes['memberNisNetgroup']
- for name in names:
- yield (name, triples, members)
-
-
-class NetgroupByNameRequest(NetgroupRequest):
-
- action = constants.NSLCD_ACTION_NETGROUP_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class NetgroupAllRequest(NetgroupRequest):
-
- action = constants.NSLCD_ACTION_NETGROUP_ALL
diff --git a/pynslcd/network.py b/pynslcd/network.py
deleted file mode 100644
index 01bf6c2..0000000
--- a/pynslcd/network.py
+++ /dev/null
@@ -1,124 +0,0 @@
-
-# network.py - lookup functions for network names and addresses
-#
-# Copyright (C) 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
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(cn='cn',
- ipNetworkNumber='ipNetworkNumber')
-filter = '(objectClass=ipNetwork)'
-
-
-class Search(search.LDAPSearch):
-
- canonical_first = ('cn', )
- required = ('cn', )
-
-
-class Cache(cache.Cache):
-
- tables = ('network_cache', 'network_alias_cache', 'network_address_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `network_cache`
- ( `cn` TEXT PRIMARY KEY COLLATE NOCASE,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `network_alias_cache`
- ( `network` TEXT NOT NULL COLLATE NOCASE,
- `cn` TEXT NOT NULL COLLATE NOCASE,
- FOREIGN KEY(`network`) REFERENCES `network_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `network_alias_idx` ON `network_alias_cache`(`network`);
- CREATE TABLE IF NOT EXISTS `network_address_cache`
- ( `network` TEXT NOT NULL COLLATE NOCASE,
- `ipNetworkNumber` TEXT NOT NULL,
- FOREIGN KEY(`network`) REFERENCES `network_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `network_address_idx` ON `network_address_cache`(`network`);
- '''
-
- retrieve_sql = '''
- SELECT `network_cache`.`cn` AS `cn`,
- `network_alias_cache`.`cn` AS `alias`,
- `network_address_cache`.`ipNetworkNumber` AS `ipNetworkNumber`,
- `network_cache`.`mtime` AS `mtime`
- FROM `network_cache`
- LEFT JOIN `network_alias_cache`
- ON `network_alias_cache`.`network` = `network_cache`.`cn`
- LEFT JOIN `network_address_cache`
- ON `network_address_cache`.`network` = `network_cache`.`cn`
- '''
-
- retrieve_by = dict(
- cn='''
- ( `network_cache`.`cn` = ? OR
- `network_cache`.`cn` IN (
- SELECT `by_alias`.`network`
- FROM `network_alias_cache` `by_alias`
- WHERE `by_alias`.`cn` = ?))
- ''',
- ipNetworkNumber='''
- `network_cache`.`cn` IN (
- SELECT `by_ipNetworkNumber`.`network`
- FROM `network_address_cache` `by_ipNetworkNumber`
- WHERE `by_ipNetworkNumber`.`ipNetworkNumber` = ?)
- ''',
- )
-
- group_by = (0, ) # cn
- group_columns = (1, 2) # alias, ipNetworkNumber
-
-
-class NetworkRequest(common.Request):
-
- def write(self, networkname, aliases, addresses):
- self.fp.write_string(networkname)
- self.fp.write_stringlist(aliases)
- self.fp.write_int32(len(addresses))
- for address in addresses:
- self.fp.write_address(address)
-
- def convert(self, dn, attributes, parameters):
- netnames = attributes['cn']
- yield (netnames[0], netnames[1:], attributes['ipNetworkNumber'])
-
-
-class NetworkByNameRequest(NetworkRequest):
-
- action = constants.NSLCD_ACTION_NETWORK_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class NetworkByAddressRequest(NetworkRequest):
-
- action = constants.NSLCD_ACTION_NETWORK_BYADDR
-
- def read_parameters(self, fp):
- return dict(ipNetworkNumber=fp.read_address())
-
-
-class NetworkAllRequest(NetworkRequest):
-
- action = constants.NSLCD_ACTION_NETWORK_ALL
diff --git a/pynslcd/pam.py b/pynslcd/pam.py
deleted file mode 100644
index 43d6a91..0000000
--- a/pynslcd/pam.py
+++ /dev/null
@@ -1,372 +0,0 @@
-
-# pam.py - functions authentication, authorisation and session handling
-#
-# Copyright (C) 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
-
-import logging
-import random
-import socket
-import time
-
-from ldap.controls.ppolicy import PasswordPolicyControl, PasswordPolicyError
-from ldap.filter import escape_filter_chars
-import ldap
-
-import cfg
-import common
-import constants
-import passwd
-import search
-import shadow
-
-
-random = random.SystemRandom()
-
-
-def authenticate(binddn, password):
- # open a new connection
- conn = search.Connection()
- # bind using the specified credentials
- pwctrl = PasswordPolicyControl()
- res, data, msgid, ctrls = conn.simple_bind_s(binddn, password, serverctrls=[pwctrl])
- # go over bind result server controls
- for ctrl in ctrls:
- if ctrl.controlType == PasswordPolicyControl.controlType:
- # found a password policy control
- logging.debug('PasswordPolicyControl found: error=%s (%s), timeBeforeExpiration=%s, graceAuthNsRemaining=%s',
- 'None' if ctrl.error is None else PasswordPolicyError(ctrl.error).prettyPrint(),
- ctrl.error, ctrl.timeBeforeExpiration, ctrl.graceAuthNsRemaining)
- if ctrl.error == 0: # passwordExpired
- return conn, constants.NSLCD_PAM_AUTHTOK_EXPIRED, PasswordPolicyError(ctrl.error).prettyPrint()
- elif ctrl.error == 1: # accountLocked
- return conn, constants.NSLCD_PAM_ACCT_EXPIRED, PasswordPolicyError(ctrl.error).prettyPrint()
- elif ctrl.error == 2: # changeAfterReset
- return conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password change is needed after reset'
- elif ctrl.error:
- return conn, constants.NSLCD_PAM_PERM_DENIED, PasswordPolicyError(ctrl.error).prettyPrint()
- elif ctrl.timeBeforeExpiration is not None:
- return conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password will expire in %d seconds' % ctrl.timeBeforeExpiration
- elif ctrl.graceAuthNsRemaining is not None:
- return conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password expired, %d grace logins left' % ctrl.graceAuthNsRemaining
- # perform search for own object (just to do any kind of search)
- results = search.LDAPSearch(conn, base=binddn, scope=ldap.SCOPE_BASE,
- filter='(objectClass=*)', attributes=['dn', ])
- for entry in results:
- if entry[0] == binddn:
- return conn, constants.NSLCD_PAM_SUCCESS, ''
- # if our DN wasn't found raise an error to signal bind failure
- raise ldap.NO_SUCH_OBJECT()
-
-
-def pwmod(conn, userdn, oldpassword, newpassword):
- # perform request without old password
- try:
- conn.passwd_s(userdn, None, newpassword)
- except ldap.LDAPError:
- # retry with old password
- if oldpassword:
- conn.passwd_s(userdn, oldpassword, newpassword)
- else:
- raise
-
-
-def update_lastchange(conns, userdn):
- """Try to update the shadowLastChange attribute of the entry."""
- attribute = shadow.attmap['shadowLastChange']
- if attribute == '${shadowLastChange:--1}':
- attribute = 'shadowLastChange'
- if not attribute or '$' in attribute:
- raise ValueError('shadowLastChange has unsupported mapping')
- # build the value for the new attribute
- if attribute.lower() == 'pwdlastset':
- # for AD we use another timestamp */
- value = '%d000000000' % (time.time() / 100L + (134774L * 864L))
- else:
- # time in days since Jan 1, 1970
- value = '%d' % (time.time() / (60 * 60 * 24))
- # perform the modification, return at first success
- for conn in conns:
- try:
- conn.modify_s(userdn, [(ldap.MOD_REPLACE, attribute, [value])])
- return
- except ldap.LDAPError:
- pass # ignore error and try next connection
-
-
-class PAMRequest(common.Request):
-
- def validate(self, parameters):
- """This method checks the provided username for validity and fills
- in the DN if needed."""
- # check username for validity
- common.validate_name(parameters['username'])
- # look up user DN
- entry = passwd.uid2entry(self.conn, parameters['username'])
- if not entry:
- # FIXME: we should close the stream with an empty response here
- raise ValueError('%r: user not found' % parameters['username'])
- # save the DN
- parameters['userdn'] = entry[0]
- # get the "real" username
- value = passwd.attmap.get_rdn_value(entry[0], 'uid')
- if not value:
- # get the username from the uid attribute
- values = entry[1]['uid']
- if not values or not values[0]:
- logging.warning('%s: is missing a %s attribute', entry[0], passwd.attmap['uid'])
- value = values[0]
- # check the username
- if value and not common.is_valid_name(value):
- raise ValueError('%s: has invalid %s attribute', entry[0], passwd.attmap['uid'])
- # check if the username is different and update it if needed
- if value != parameters['username']:
- logging.info('username changed from %r to %r', parameters['username'], value)
- parameters['username'] = value
-
-
-class PAMAuthenticationRequest(PAMRequest):
-
- action = constants.NSLCD_ACTION_PAM_AUTHC
-
- def read_parameters(self, fp):
- return dict(username=fp.read_string(),
- service=fp.read_string(),
- ruser=fp.read_string(),
- rhost=fp.read_string(),
- tty=fp.read_string(),
- password=fp.read_string())
- # TODO: log call with parameters
-
- def write(self, username, authc=constants.NSLCD_PAM_SUCCESS,
- authz=constants.NSLCD_PAM_SUCCESS, msg=''):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.fp.write_int32(authc)
- self.fp.write_string(username)
- self.fp.write_int32(authz)
- self.fp.write_string(msg)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def handle_request(self, parameters):
- # if the username is blank and rootpwmoddn is configured, try to
- # authenticate as administrator, otherwise validate request as usual
- if not parameters['username'] and cfg.rootpwmoddn:
- # authenticate as rootpwmoddn
- binddn = cfg.rootpwmoddn
- # if the caller is root we will allow the use of rootpwmodpw
- if not parameters['password'] and self.calleruid == 0 and cfg.rootpwmodpw:
- password = cfg.rootpwmodpw
- elif parameters['password']:
- password = parameters['password']
- else:
- raise ValueError('password missing')
- else:
- self.validate(parameters)
- binddn = parameters['userdn']
- password = parameters['password']
- # try authentication
- try:
- conn, authz, msg = authenticate(binddn, password)
- except ldap.INVALID_CREDENTIALS, e:
- try:
- msg = e[0]['desc']
- except:
- msg = str(e)
- logging.debug('bind failed: %s', msg)
- self.write(parameters['username'], authc=constants.NSLCD_PAM_AUTH_ERR, msg=msg)
- return
- if authz != constants.NSLCD_PAM_SUCCESS:
- logging.warning('%s: %s: %s', binddn, parameters['username'], msg)
- else:
- logging.debug('bind successful')
- # FIXME: perform shadow attribute checks with check_shadow()
- self.write(parameters['username'], authz=authz, msg=msg)
-
-
-class PAMAuthorisationRequest(PAMRequest):
-
- action = constants.NSLCD_ACTION_PAM_AUTHZ
-
- def read_parameters(self, fp):
- return dict(username=fp.read_string(),
- service=fp.read_string(),
- ruser=fp.read_string(),
- rhost=fp.read_string(),
- tty=fp.read_string())
- # TODO: log call with parameters
-
- def write(self, authz=constants.NSLCD_PAM_SUCCESS, msg=''):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.fp.write_int32(authz)
- self.fp.write_string(msg)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def check_authzsearch(self, parameters):
- if not cfg.pam_authz_searches:
- return
- # escape all parameters
- variables = dict((k, escape_filter_chars(v)) for k, v in parameters.items())
- variables.update(
- hostname=escape_filter_chars(socket.gethostname()),
- fqdn=escape_filter_chars(socket.getfqdn()),
- dn=variables['userdn'],
- uid=variables['username'],
- )
- # go over all authz searches
- for x in cfg.pam_authz_searches:
- filter = x.value(variables)
- logging.debug('trying pam_authz_search "%s"', filter)
- srch = search.LDAPSearch(self.conn, filter=filter, attributes=('dn', ))
- try:
- dn, values = srch.items().next()
- except StopIteration:
- logging.error('pam_authz_search "%s" found no matches', filter)
- raise
- logging.debug('pam_authz_search found "%s"', dn)
-
- def handle_request(self, parameters):
- # fill in any missing userdn, etc.
- self.validate(parameters)
- # check authorisation search
- try:
- self.check_authzsearch(parameters)
- except StopIteration:
- self.write(constants.NSLCD_PAM_PERM_DENIED,
- 'LDAP authorisation check failed')
- return
- # all tests passed, return OK response
- self.write()
-
-
-class PAMPasswordModificationRequest(PAMRequest):
-
- action = constants.NSLCD_ACTION_PAM_PWMOD
-
- def read_parameters(self, fp):
- return dict(username=fp.read_string(),
- service=fp.read_string(),
- ruser=fp.read_string(),
- rhost=fp.read_string(),
- tty=fp.read_string(),
- asroot=fp.read_int32(),
- oldpassword=fp.read_string(),
- newpassword=fp.read_string())
- # TODO: log call with parameters
-
- def write(self, rc=constants.NSLCD_PAM_SUCCESS, msg=''):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.fp.write_int32(rc)
- self.fp.write_string(msg)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def handle_request(self, parameters):
- # fill in any missing userdn, etc.
- self.validate(parameters)
- # check if pam_password_prohibit_message is set
- if cfg.pam_password_prohibit_message:
- self.write(constants.NSLCD_PAM_PERM_DENIED,
- cfg.pam_password_prohibit_message)
- return
- # check if the the user passed the rootpwmoddn
- if parameters['asroot']:
- binddn = cfg.rootpwmoddn
- # check if rootpwmodpw should be used
- if not parameters['oldpassword'] and self.calleruid == 0 and cfg.rootpwmodpw:
- password = cfg.rootpwmodpw
- elif parameters['oldpassword']:
- password = parameters['oldpassword']
- else:
- raise ValueError('password missing')
- else:
- binddn = parameters['userdn']
- password = parameters['oldpassword']
- # TODO: check if shadow properties allow password change
- # perform password modification
- try:
- conn, authz, msg = authenticate(binddn, password)
- pwmod(conn, parameters['userdn'], parameters['oldpassword'], parameters['newpassword'])
- # try to update lastchange with normal or user connection
- update_lastchange((self.conn, conn), parameters['userdn'])
- except ldap.INVALID_CREDENTIALS, e:
- try:
- msg = e[0]['desc']
- except:
- msg = str(e)
- logging.debug('pwmod failed: %s', msg)
- self.write(constants.NSLCD_PAM_PERM_DENIED, msg)
- return
- logging.debug('pwmod successful')
- self.write()
-
-
-SESSION_ID_LENGTH = 25
-SESSION_ID_ALPHABET = (
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
- "abcdefghijklmnopqrstuvwxyz" +
- "01234567890"
-)
-
-
-def generate_session_id():
- return ''.join(
- random.choice(SESSION_ID_ALPHABET)
- for i in range(SESSION_ID_LENGTH)
- )
-
-
-class PAMSessionOpenRequest(PAMRequest):
-
- action = constants.NSLCD_ACTION_PAM_SESS_O
-
- def read_parameters(self, fp):
- return dict(username=fp.read_string(),
- service=fp.read_string(),
- ruser=fp.read_string(),
- rhost=fp.read_string(),
- tty=fp.read_string())
- # TODO: log call with parameters
-
- def write(self, sessionid):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.fp.write_string(sessionid)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def handle_request(self, parameters):
- # generate a session id
- session_id = generate_session_id()
- self.write(session_id)
-
-
-class PAMSessionCloseRequest(PAMRequest):
-
- action = constants.NSLCD_ACTION_PAM_SESS_C
-
- def read_parameters(self, fp):
- return dict(username=fp.read_string(),
- service=fp.read_string(),
- ruser=fp.read_string(),
- rhost=fp.read_string(),
- tty=fp.read_string(),
- session_id=fp.read_string())
- # TODO: log call with parameters
-
- def write(self):
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
- def handle_request(self, parameters):
- self.write()
diff --git a/pynslcd/passwd.py b/pynslcd/passwd.py
deleted file mode 100644
index d65e556..0000000
--- a/pynslcd/passwd.py
+++ /dev/null
@@ -1,146 +0,0 @@
-
-# passwd.py - lookup functions for user account information
-#
-# Copyright (C) 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
-
-import logging
-
-import cache
-import cfg
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(uid='uid',
- userPassword='"*"',
- uidNumber='uidNumber',
- gidNumber='gidNumber',
- gecos='"${gecos:-$cn}"',
- homeDirectory='homeDirectory',
- loginShell='loginShell',
- objectClass='objectClass')
-filter = '(objectClass=posixAccount)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('uid', 'uidNumber', )
- limit_attributes = ('uid', 'uidNumber', )
- required = ('uid', 'uidNumber', 'gidNumber', 'gecos', 'homeDirectory',
- 'loginShell')
-
-
-class Cache(cache.Cache):
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `passwd_cache`
- ( `uid` TEXT PRIMARY KEY,
- `userPassword` TEXT,
- `uidNumber` INTEGER NOT NULL UNIQUE,
- `gidNumber` INTEGER NOT NULL,
- `gecos` TEXT,
- `homeDirectory` TEXT,
- `loginShell` TEXT,
- `mtime` TIMESTAMP NOT NULL );
- '''
-
-
-class PasswdRequest(common.Request):
-
- def write(self, name, passwd, uid, gid, gecos, home, shell):
- self.fp.write_string(name)
- self.fp.write_string(passwd)
- self.fp.write_int32(uid)
- self.fp.write_int32(gid)
- self.fp.write_string(gecos)
- self.fp.write_string(home)
- self.fp.write_string(shell)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['uid']
- if 'shadowAccount' in attributes['objectClass']:
- passwd = 'x'
- else:
- try:
- passwd = attributes['userPassword'][0]
- except IndexError:
- passwd = None
- if not passwd or self.calleruid != 0:
- passwd = '*'
- uids = [int(x) for x in attributes['uidNumber']]
- gid = int(attributes['gidNumber'][0])
- gecos = attributes['gecos'][0]
- home = attributes['homeDirectory'][0]
- shell = attributes['loginShell'][0]
- for name in names:
- if not common.is_valid_name(name):
- logging.warning('%s: %s: denied by validnames option', dn, attmap['uid'])
- else:
- for uid in uids:
- if uid >= cfg.nss_min_uid:
- yield (name, passwd, uid, gid, gecos, home, shell)
-
-
-class PasswdByNameRequest(PasswdRequest):
-
- action = constants.NSLCD_ACTION_PASSWD_BYNAME
-
- def read_parameters(self, fp):
- name = fp.read_string()
- common.validate_name(name)
- return dict(uid=name)
-
-
-class PasswdByUidRequest(PasswdRequest):
-
- action = constants.NSLCD_ACTION_PASSWD_BYUID
-
- def read_parameters(self, fp):
- return dict(uidNumber=fp.read_int32())
-
- def handle_request(self, parameters):
- # check requested numeric id
- if parameters['uidNumber'] >= cfg.nss_min_uid:
- return super(PasswdByUidRequest, self).handle_request(parameters)
- # write the final result code to signify empty results
- self.fp.write_int32(constants.NSLCD_RESULT_END)
-
-
-class PasswdAllRequest(PasswdRequest):
-
- action = constants.NSLCD_ACTION_PASSWD_ALL
-
-
-def uid2entry(conn, uid):
- """Look up the user by uid and return the LDAP entry or None if the user
- was not found."""
- for dn, attributes in Search(conn, parameters=dict(uid=uid)):
- if any(int(x) >= cfg.nss_min_uid for x in attributes['uidNumber']):
- return dn, attributes
-
-
-# FIXME: use cache of dn2uid and try to use DN to get uid attribute
-
-
-def dn2uid(conn, dn):
- """Look up the user by dn and return a uid or None if the user was
- not found."""
- for dn, attributes in Search(conn, base=dn):
- if any(int(x) >= cfg.nss_min_uid for x in attributes['uidNumber']):
- return attributes['uid'][0]
diff --git a/pynslcd/protocol.py b/pynslcd/protocol.py
deleted file mode 100644
index 1472c04..0000000
--- a/pynslcd/protocol.py
+++ /dev/null
@@ -1,107 +0,0 @@
-
-# protocol.py - protocol name and number lookup routines
-#
-# Copyright (C) 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
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(cn='cn', ipProtocolNumber='ipProtocolNumber')
-filter = '(objectClass=ipProtocol)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('cn', )
- canonical_first = ('cn', )
- required = ('cn', 'ipProtocolNumber')
-
-
-class Cache(cache.Cache):
-
- tables = ('protocol_cache', 'protocol_alias_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `protocol_cache`
- ( `cn` TEXT PRIMARY KEY,
- `ipProtocolNumber` INTEGER NOT NULL,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `protocol_alias_cache`
- ( `protocol` TEXT NOT NULL,
- `cn` TEXT NOT NULL,
- FOREIGN KEY(`protocol`) REFERENCES `protocol_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `protocol_alias_idx` ON `protocol_alias_cache`(`protocol`);
- '''
-
- retrieve_sql = '''
- SELECT `protocol_cache`.`cn` AS `cn`, `protocol_alias_cache`.`cn` AS `alias`,
- `ipProtocolNumber`, `mtime`
- FROM `protocol_cache`
- LEFT JOIN `protocol_alias_cache`
- ON `protocol_alias_cache`.`protocol` = `protocol_cache`.`cn`
- '''
-
- retrieve_by = dict(
- cn='''
- ( `protocol_cache`.`cn` = ? OR
- `protocol_cache`.`cn` IN (
- SELECT `by_alias`.`protocol`
- FROM `protocol_alias_cache` `by_alias`
- WHERE `by_alias`.`cn` = ?))
- ''',
- )
-
- group_by = (0, ) # cn
- group_columns = (1, ) # alias
-
-
-class ProtocolRequest(common.Request):
-
- def write(self, name, names, number):
- self.fp.write_string(name)
- self.fp.write_stringlist(names)
- self.fp.write_int32(number)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['cn']
- yield (names[0], names[1:], int(attributes['ipProtocolNumber'][0]))
-
-
-class ProtocolByNameRequest(ProtocolRequest):
-
- action = constants.NSLCD_ACTION_PROTOCOL_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class ProtocolByNumberRequest(ProtocolRequest):
-
- action = constants.NSLCD_ACTION_PROTOCOL_BYNUMBER
-
- def read_parameters(self, fp):
- return dict(ipProtocolNumber=fp.read_int32())
-
-
-class ProtocolAllRequest(ProtocolRequest):
-
- action = constants.NSLCD_ACTION_PROTOCOL_ALL
diff --git a/pynslcd/pynslcd.py b/pynslcd/pynslcd.py
deleted file mode 100755
index 27b31d8..0000000
--- a/pynslcd/pynslcd.py
+++ /dev/null
@@ -1,382 +0,0 @@
-#!/usr/bin/env python
-
-# pynslcd.py - main daemon module
-#
-# Copyright (C) 2010-2014 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
-
-import logging
-import logging.handlers
-import os
-import signal
-import sys
-import syslog
-import threading
-
-import daemon
-import ldap
-
-from tio import TIOStream
-import cfg
-import common
-import constants
-import invalidator
-import mypidfile
-import search
-
-
-# the name of the program
-program_name = 'pynslcd'
-
-# flag to indicate whether we are in debugging mode
-debugging = 0
-
-# flag to indicate we shouldn't daemonize
-nofork = False
-
-# flag to indicate user requested the --check option
-checkonly = False
-
-
-class MyFormatter(logging.Formatter):
-
- def format(self, record):
- record.prefix = 'DEBUG: ' if record.levelno == logging.DEBUG else ''
- return super(MyFormatter, self).format(record)
-
-
-class MySysLogHandler(logging.Handler):
-
- mapping = {
- logging.DEBUG: syslog.LOG_DEBUG,
- logging.INFO: syslog.LOG_INFO,
- logging.WARNING: syslog.LOG_WARNING,
- logging.ERROR: syslog.LOG_ERR,
- logging.CRITICAL: syslog.LOG_CRIT,
- }
-
- def __init__(self):
- super(MySysLogHandler, self).__init__()
- syslog.openlog(program_name, syslog.LOG_PID, syslog.LOG_DAEMON)
-
- def emit(self, record):
- priority = self.mapping.get(record.levelno, syslog.LOG_WARNING)
- msg = self.format(record)
- for line in msg.splitlines():
- syslog.syslog(priority, line)
-
-
-# configure logging
-stderrhandler = logging.StreamHandler(sys.stderr)
-stderrhandler.setFormatter(MyFormatter('pynslcd: %(prefix)s%(message)s'))
-logging.getLogger().addHandler(stderrhandler)
-logging.getLogger().setLevel(logging.INFO)
-
-
-def display_version(fp):
- fp.write('%(PACKAGE_STRING)s\n'
- 'Written by Arthur de Jong.\n'
- '\n'
- 'Copyright (C) 2010-2014 Arthur de Jong\n'
- 'This is free software; see the source for copying conditions. There is NO\n'
- 'warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n'
- % {'PACKAGE_STRING': constants.PACKAGE_STRING, })
-
-
-def display_usage(fp):
- fp.write("Usage: %(program_name)s [OPTION]...\n"
- "Name Service LDAP connection daemon.\n"
- " -c, --check check if the daemon already is running\n"
- " -d, --debug don't fork and print debugging to stderr\n"
- " -n, --nofork don't fork\n"
- " --help display this help and exit\n"
- " --version output version information and exit\n"
- "\n"
- "Report bugs to <%(PACKAGE_BUGREPORT)s>.\n"
- % {'program_name': program_name,
- 'PACKAGE_BUGREPORT': constants.PACKAGE_BUGREPORT, })
-
-
-def parse_cmdline():
- """Parse command-line arguments."""
- import getopt
- global program_name
- program_name = sys.argv[0] or program_name
- try:
- optlist, args = getopt.gnu_getopt(
- sys.argv[1:], 'cdnhV',
- ('check', 'debug', 'nofork', 'help', 'version'))
- for flag, arg in optlist:
- if flag in ('-c', '--check'):
- global checkonly
- checkonly = True
- elif flag in ('-d', '--debug'):
- global debugging
- debugging += 1
- elif flag in ('-n', '--nofork'):
- global nofork
- nofork = True
- elif flag in ('-h', '--help'):
- display_usage(sys.stdout)
- sys.exit(0)
- elif flag in ('-V', '--version'):
- display_version(sys.stdout)
- sys.exit(0)
- if len(args):
- raise getopt.GetoptError('unrecognized option \'%s\'' % args[0], args[0])
- except getopt.GetoptError, reason:
- sys.stderr.write(
- "%(program_name)s: %(reason)s\n"
- "Try '%(program_name)s --help' for more information.\n" % {
- 'program_name': program_name,
- 'reason': reason,
- })
- sys.exit(1)
-
-
-def create_socket():
- """Returns a socket ready to answer requests from the client."""
- import socket
- import fcntl
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- # remove existing named socket
- try:
- os.unlink(constants.NSLCD_SOCKET)
- except OSError:
- pass # ignore any problems
- # bind to named socket
- sock.bind(constants.NSLCD_SOCKET)
- # close the file descriptor on exit
- fcntl.fcntl(sock, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- # set permissions of socket so anybody can do requests
- os.chmod(constants.NSLCD_SOCKET, 0666)
- # start listening for connections
- sock.listen(socket.SOMAXCONN)
- return sock
-
-
-def log_newsession():
- pass
- # FIXME: implement
-
-
-def getpeercred(fd):
- """Return uid, gid and pid of calling application."""
- import struct
- import socket
- try:
- SO_PEERCRED = getattr(socket, 'SO_PEERCRED', 17)
- creds = fd.getsockopt(socket.SOL_SOCKET, SO_PEERCRED, struct.calcsize('3i'))
- pid, uid, gid = struct.unpack('3i', creds)
- return uid, gid, pid
- except socket.error:
- return None, None, None
-
-
-handlers = {}
-handlers.update(common.get_handlers('config'))
-handlers.update(common.get_handlers('alias'))
-handlers.update(common.get_handlers('ether'))
-handlers.update(common.get_handlers('group'))
-handlers.update(common.get_handlers('host'))
-handlers.update(common.get_handlers('netgroup'))
-handlers.update(common.get_handlers('network'))
-handlers.update(common.get_handlers('passwd'))
-handlers.update(common.get_handlers('protocol'))
-handlers.update(common.get_handlers('rpc'))
-handlers.update(common.get_handlers('service'))
-handlers.update(common.get_handlers('shadow'))
-handlers.update(common.get_handlers('pam'))
-handlers.update(common.get_handlers('usermod'))
-
-
-def acceptconnection(session):
- # accept a new connection
- conn, addr = nslcd_serversocket.accept()
- # See: http://docs.python.org/library/socket.html#socket.socket.settimeout
- fp = None
- try:
- # indicate new connection to logging module (generates unique id)
- log_newsession()
- # log connection
- uid, gid, pid = getpeercred(conn)
- logging.debug('connection from pid=%r uid=%r gid=%r', pid, uid, gid)
- # create a stream object
- fp = TIOStream(conn)
- # read request
- version = fp.read_int32()
- if version != constants.NSLCD_VERSION:
- logging.debug('wrong nslcd version id (%r)', version)
- return
- action = fp.read_int32()
- try:
- handler = handlers[action]
- except KeyError:
- logging.warning('invalid action id: 0x%08x', action)
- return
- handler(fp, session, uid)()
- finally:
- if fp:
- fp.close()
-
-
-def disable_nss_ldap():
- """Disable the nss_ldap module to avoid lookup loops."""
- import ctypes
- try:
- lib = ctypes.CDLL(constants.NSS_LDAP_SONAME)
- except OSError:
- return # ignore errors in opening NSS module
- try:
- ctypes.c_int.in_dll(lib, '_nss_ldap_enablelookups').value = 0
- except ValueError:
- logging.warn('probably older NSS module loaded', exc_info=True)
- try:
- version_info = (ctypes.c_char_p * 2).in_dll(lib, '_nss_ldap_version')
- logging.debug('NSS_LDAP %s %s', version_info[0], version_info[1])
- except ValueError:
- logging.warn('probably older NSS module loaded', exc_info=True)
-
-
-def worker():
- session = search.Connection()
- while True:
- try:
- acceptconnection(session)
- except:
- logging.exception('exception in worker')
- # ignore all exceptions, just keep going
-
-
-if __name__ == '__main__':
- # parse options
- parse_cmdline()
- # clean the environment
- os.environ.clear()
- os.environ['HOME'] = '/'
- os.environ['TMPDIR'] = '/tmp'
- os.environ['LDAPNOINIT'] = '1'
- # set log level
- if debugging:
- logging.getLogger().setLevel(logging.DEBUG)
- # disable ldap lookups of host names to avoid lookup loop
- disable_nss_ldap()
- # TODO: implement
- #if myldap_set_debuglevel(cfg.debug) != LDAP_SUCCESS:
- # sys.exit(1)
- # read configuration file
- cfg.read(constants.NSLCD_CONF_PATH)
- # set process title
- try:
- import setproctitle
- setproctitle.setproctitle('pynslcd')
- except ImportError:
- pass
- # set a default umask for the pidfile and socket
- os.umask(0022)
- # see if someone already locked the pidfile
- pidfile = mypidfile.MyPIDLockFile(constants.NSLCD_PIDFILE)
- # see if --check option was given
- if checkonly:
- if pidfile.is_locked():
- logging.debug('pidfile (%s) is locked', constants.NSLCD_PIDFILE)
- sys.exit(0)
- else:
- logging.debug('pidfile (%s) is not locked', constants.NSLCD_PIDFILE)
- sys.exit(1)
- # normal check for pidfile locked
- if pidfile.is_locked():
- logging.error('daemon may already be active, cannot acquire lock (%s)',
- constants.NSLCD_PIDFILE)
- sys.exit(1)
- # daemonize
- if debugging or nofork:
- ctx = pidfile
- else:
- ctx = daemon.DaemonContext(
- pidfile=pidfile,
- signal_map={
- signal.SIGTERM: 'terminate',
- signal.SIGINT: 'terminate',
- signal.SIGPIPE: None,
- })
- # start daemon
- with ctx:
- try:
- # start normal logging as configured
- if not debugging:
- for method, level in cfg.logs:
- if method == 'syslog':
- handler = MySysLogHandler()
- handler.setFormatter(MyFormatter('%(prefix)s%(message)s'))
- else:
- handler = logging.FileHandler(method, encoding='utf-8')
- handler.setFormatter(MyFormatter('%(asctime)s %(prefix)s%(message)s'))
- handler.setLevel(level)
- logging.getLogger().addHandler(handler)
- logging.getLogger().setLevel(min(level for method, level in cfg.logs))
- logging.getLogger().removeHandler(stderrhandler)
- logging.info('version %s starting', constants.VERSION)
- # start invalidator sub-process if needed
- if cfg.reconnect_invalidate:
- invalidator.start_invalidator()
- # create socket
- nslcd_serversocket = create_socket()
- # load supplementary groups
- if cfg.uid is not None:
- import pwd
- import grp
- u = pwd.getpwnam(cfg.uid)
- if cfg.gid is None:
- gid = u.pw_gid
- else:
- gid = grp.getgrnam(cfg.gid).gr_gid
- # set supplementary groups, gid and uid
- os.initgroups(u.pw_name, gid)
- os.setgid(gid)
- os.setuid(u.pw_uid)
- os.environ['HOME'] = u.pw_dir
- logging.info('accepting connections')
- # set global LDAP configuration
- if cfg.tls_reqcert is not None:
- ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, cfg.tls_reqcert)
- if cfg.tls_cacertdir:
- ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, cfg.tls_cacertdir)
- if cfg.tls_cacertfile:
- ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, cfg.tls_cacertfile)
- if cfg.tls_randfile:
- ldap.set_option(ldap.OPT_X_TLS_RANDOM_FILE, cfg.tls_randfile)
- if cfg.tls_ciphers:
- ldap.set_option(ldap.OPT_X_TLS_CIPHER_SUITE, cfg.tls_ciphers)
- if cfg.tls_cert:
- ldap.set_option(ldap.OPT_X_TLS_CERTFILE, cfg.tls_cert)
- if cfg.tls_key:
- ldap.set_option(ldap.OPT_X_TLS_KEYFILE, cfg.tls_key)
- # start worker threads
- threads = []
- for i in range(cfg.threads):
- thread = threading.Thread(target=worker, name='thread%d' % i)
- thread.setDaemon(True)
- thread.start()
- logging.debug('started thread %s', thread.getName())
- threads.append(thread)
- # wait for all threads to die
- for thread in threads:
- thread.join(10000)
- except:
- logging.exception('main loop exit')
- # no need to re-raise since we are exiting anyway
diff --git a/pynslcd/rpc.py b/pynslcd/rpc.py
deleted file mode 100644
index 2a241fd..0000000
--- a/pynslcd/rpc.py
+++ /dev/null
@@ -1,107 +0,0 @@
-
-# rpc.py - rpc name lookup routines
-#
-# Copyright (C) 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
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(cn='cn', oncRpcNumber='oncRpcNumber')
-filter = '(objectClass=oncRpc)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('cn', )
- canonical_first = ('cn', )
- required = ('cn', 'oncRpcNumber')
-
-
-class Cache(cache.Cache):
-
- tables = ('rpc_cache', 'rpc_alias_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `rpc_cache`
- ( `cn` TEXT PRIMARY KEY,
- `oncRpcNumber` INTEGER NOT NULL,
- `mtime` TIMESTAMP NOT NULL );
- CREATE TABLE IF NOT EXISTS `rpc_alias_cache`
- ( `rpc` TEXT NOT NULL,
- `cn` TEXT NOT NULL,
- FOREIGN KEY(`rpc`) REFERENCES `rpc_cache`(`cn`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `rpc_alias_idx` ON `rpc_alias_cache`(`rpc`);
- '''
-
- retrieve_sql = '''
- SELECT `rpc_cache`.`cn` AS `cn`, `rpc_alias_cache`.`cn` AS `alias`,
- `oncRpcNumber`, `mtime`
- FROM `rpc_cache`
- LEFT JOIN `rpc_alias_cache`
- ON `rpc_alias_cache`.`rpc` = `rpc_cache`.`cn`
- '''
-
- retrieve_by = dict(
- cn='''
- ( `rpc_cache`.`cn` = ? OR
- `rpc_cache`.`cn` IN (
- SELECT `by_alias`.`rpc`
- FROM `rpc_alias_cache` `by_alias`
- WHERE `by_alias`.`cn` = ?))
- ''',
- )
-
- group_by = (0, ) # cn
- group_columns = (1, ) # alias
-
-
-class RpcRequest(common.Request):
-
- def write(self, name, aliases, number):
- self.fp.write_string(name)
- self.fp.write_stringlist(aliases)
- self.fp.write_int32(number)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['cn']
- yield (names[0], names[1:], int(attributes['oncRpcNumber'][0]))
-
-
-class RpcByNameRequest(RpcRequest):
-
- action = constants.NSLCD_ACTION_RPC_BYNAME
-
- def read_parameters(self, fp):
- return dict(cn=fp.read_string())
-
-
-class RpcByNumberRequest(RpcRequest):
-
- action = constants.NSLCD_ACTION_RPC_BYNUMBER
-
- def read_parameters(self, fp):
- return dict(oncRpcNumber=fp.read_int32())
-
-
-class RpcAllRequest(RpcRequest):
-
- action = constants.NSLCD_ACTION_RPC_ALL
diff --git a/pynslcd/search.py b/pynslcd/search.py
deleted file mode 100644
index 4a57ab3..0000000
--- a/pynslcd/search.py
+++ /dev/null
@@ -1,195 +0,0 @@
-
-# search.py - functions for searching the LDAP database
-#
-# Copyright (C) 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
-
-import logging
-import sys
-
-import ldap
-import ldap.ldapobject
-
-import cfg
-
-
-# global indicator that there was some error connection to an LDAP server
-server_error = False
-
-# global indicator of first search operation
-first_search = True
-
-
-class Connection(ldap.ldapobject.ReconnectLDAPObject):
-
- def __init__(self):
- ldap.ldapobject.ReconnectLDAPObject.__init__(self, cfg.uri,
- retry_max=1, retry_delay=cfg.reconnect_retrytime)
- # set connection-specific LDAP options
- if cfg.ldap_version:
- self.set_option(ldap.OPT_PROTOCOL_VERSION, cfg.ldap_version)
- if cfg.deref:
- self.set_option(ldap.OPT_DEREF, cfg.deref)
- if cfg.timelimit:
- self.set_option(ldap.OPT_TIMELIMIT, cfg.timelimit)
- self.set_option(ldap.OPT_TIMEOUT, cfg.timelimit)
- self.set_option(ldap.OPT_NETWORK_TIMEOUT, cfg.timelimit)
- if cfg.referrals:
- self.set_option(ldap.OPT_REFERRALS, cfg.referrals)
- if cfg.sasl_canonicalize is not None:
- self.set_option(ldap.OPT_X_SASL_NOCANON, not cfg.sasl_canonicalize)
- self.set_option(ldap.OPT_RESTART, True)
- # TODO: register a connection callback (like dis?connect_cb() in myldap.c)
- if cfg.ssl or cfg.uri.startswith('ldaps://'):
- self.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_HARD)
- # TODO: the following should probably be done on the first search
- # together with binding, not when creating the connection object
- if cfg.ssl == 'STARTTLS':
- self.start_tls_s()
-
- def reconnect_after_fail(self):
- import invalidator
- logging.info('connected to LDAP server %s', cfg.uri)
- invalidator.invalidate()
-
- def search_s(self, *args, **kwargs):
- # wrapper function to keep the global server_error state
- global server_error, first_search
- try:
- res = ldap.ldapobject.ReconnectLDAPObject.search_s(self, *args, **kwargs)
- except ldap.SERVER_DOWN:
- server_error = True
- raise
- if server_error or first_search:
- self.reconnect_after_fail()
- server_error = False
- first_search = False
- return res
-
-
-class LDAPSearch(object):
- """
- Class that performs an LDAP search. Subclasses are expected to define the
- actual searches and should implement the following members:
-
- case_sensitive - check that these attributes are present in the response
- if they were in the request
- case_insensitive - check that these attributes are present in the
- response if they were in the request
- limit_attributes - override response attributes with request attributes
- (ensure that only one copy of the value is returned)
- required - attributes that are required
- canonical_first - search the DN for these attributes and ensure that
- they are listed first in the attribute values
- mk_filter() (optional) - function that returns the LDAP search filter
-
- The module that contains the Search class can also contain the following
- definitions:
-
- bases - list of search bases to be used, if absent or empty falls back
- to cfg.bases
- scope - search scope, falls back to cfg.scope if absent or empty
- filter - an LDAP search filter
- attmap - an attribute mapping definition (using he Attributes class)
-
- """
-
- canonical_first = []
- required = []
- case_sensitive = []
- case_insensitive = []
- limit_attributes = []
-
- def __init__(self, conn, base=None, scope=None, filter=None,
- attributes=None, parameters=None):
- self.conn = conn
- # load information from module that defines the class
- module = sys.modules[self.__module__]
- if base:
- self.bases = [base]
- else:
- self.bases = getattr(module, 'bases', cfg.bases)
- self.scope = scope or getattr(module, 'scope', cfg.scope)
- self.filter = filter or getattr(module, 'filter', None)
- self.attmap = getattr(module, 'attmap', None)
- self.attributes = attributes or self.attmap.attributes()
- self.parameters = parameters or {}
-
- def __iter__(self):
- return self.items()
-
- def items(self):
- """Return the results from the search."""
- filter = self.mk_filter()
- for base in self.bases:
- logging.debug('LDAPSearch(base=%r, filter=%r)', base, filter)
- try:
- for entry in self.conn.search_s(base, self.scope, filter, self.attributes):
- if entry[0]:
- entry = self._transform(entry[0], entry[1])
- if entry:
- yield entry
- except ldap.NO_SUCH_OBJECT:
- # FIXME: log message
- pass
-
- def mk_filter(self):
- """Return the active search filter (based on the read parameters)."""
- if self.parameters:
- return '(&%s%s)' % (
- self.filter,
- ''.join(self.attmap.mk_filter(attribute, value)
- for attribute, value in self.parameters.items()))
- return self.filter
-
- def _transform(self, dn, attributes):
- """Handle a single search result entry filtering it with the request
- parameters, search options and attribute mapping."""
- # translate the attributes using the attribute mapping
- if self.attmap:
- attributes = self.attmap.translate(attributes)
- # make sure value from DN is first value
- for attr in self.canonical_first:
- primary_value = self.attmap.get_rdn_value(dn, attr)
- if primary_value:
- values = attributes[attr]
- if primary_value in values:
- values.remove(primary_value)
- attributes[attr] = [primary_value] + values
- # check that these attributes have at least one value
- for attr in self.required:
- if not attributes.get(attr, None):
- logging.warning('%s: %s: missing', dn, self.attmap[attr])
- return
- # check that requested attribute is present (case sensitive)
- for attr in self.case_sensitive:
- value = self.parameters.get(attr, None)
- if value and str(value) not in attributes[attr]:
- logging.debug('%s: %s: does not contain %r value', dn, self.attmap[attr], value)
- return # not found, skip entry
- # check that requested attribute is present (case insensitive)
- for attr in self.case_insensitive:
- value = self.parameters.get(attr, None)
- if value and str(value).lower() not in (x.lower() for x in attributes[attr]):
- logging.debug('%s: %s: does not contain %r value', dn, self.attmap[attr], value)
- return # not found, skip entry
- # limit attribute values to requested value
- for attr in self.limit_attributes:
- if attr in self.parameters:
- attributes[attr] = [self.parameters[attr]]
- # return the entry
- return dn, attributes
diff --git a/pynslcd/service.py b/pynslcd/service.py
deleted file mode 100644
index c27f485..0000000
--- a/pynslcd/service.py
+++ /dev/null
@@ -1,156 +0,0 @@
-
-# service.py - service entry lookup routines
-#
-# Copyright (C) 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
-
-import datetime
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(cn='cn',
- ipServicePort='ipServicePort',
- ipServiceProtocol='ipServiceProtocol')
-filter = '(objectClass=ipService)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('cn', 'ipServiceProtocol')
- limit_attributes = ('ipServiceProtocol', )
- canonical_first = ('cn', )
- required = ('cn', 'ipServicePort', 'ipServiceProtocol')
-
-
-class Cache(cache.Cache):
-
- tables = ('service_cache', 'service_alias_cache')
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `service_cache`
- ( `cn` TEXT NOT NULL,
- `ipServicePort` INTEGER NOT NULL,
- `ipServiceProtocol` TEXT NOT NULL,
- `mtime` TIMESTAMP NOT NULL,
- UNIQUE (`ipServicePort`, `ipServiceProtocol`) );
- CREATE TABLE IF NOT EXISTS `service_alias_cache`
- ( `ipServicePort` INTEGER NOT NULL,
- `ipServiceProtocol` TEXT NOT NULL,
- `cn` TEXT NOT NULL,
- FOREIGN KEY(`ipServicePort`) REFERENCES `service_cache`(`ipServicePort`)
- ON DELETE CASCADE ON UPDATE CASCADE,
- FOREIGN KEY(`ipServiceProtocol`) REFERENCES `service_cache`(`ipServiceProtocol`)
- ON DELETE CASCADE ON UPDATE CASCADE );
- CREATE INDEX IF NOT EXISTS `service_alias_idx1` ON `service_alias_cache`(`ipServicePort`);
- CREATE INDEX IF NOT EXISTS `service_alias_idx2` ON `service_alias_cache`(`ipServiceProtocol`);
- '''
-
- retrieve_sql = '''
- SELECT `service_cache`.`cn` AS `cn`,
- `service_alias_cache`.`cn` AS `alias`,
- `service_cache`.`ipServicePort`,
- `service_cache`.`ipServiceProtocol`,
- `mtime`
- FROM `service_cache`
- LEFT JOIN `service_alias_cache`
- ON `service_alias_cache`.`ipServicePort` = `service_cache`.`ipServicePort`
- AND `service_alias_cache`.`ipServiceProtocol` = `service_cache`.`ipServiceProtocol`
- '''
-
- retrieve_by = dict(
- cn='''
- ( `service_cache`.`cn` = ? OR
- 0 < (
- SELECT COUNT(*)
- FROM `service_alias_cache` `by_alias`
- WHERE `by_alias`.`cn` = ?
- AND `by_alias`.`ipServicePort` = `service_cache`.`ipServicePort`
- AND `by_alias`.`ipServiceProtocol` = `service_cache`.`ipServiceProtocol`
- ))
- ''',
- )
-
- group_by = (0, 2, 3) # cn, ipServicePort, ipServiceProtocol
- group_columns = (1, ) # alias
-
- def store(self, name, aliases, port, protocol):
- self.con.execute('''
- INSERT OR REPLACE INTO `service_cache`
- VALUES
- (?, ?, ?, ?)
- ''', (name, port, protocol, datetime.datetime.now()))
- self.con.execute('''
- DELETE FROM `service_alias_cache`
- WHERE `ipServicePort` = ?
- AND `ipServiceProtocol` = ?
- ''', (port, protocol))
- self.con.executemany('''
- INSERT INTO `service_alias_cache`
- VALUES
- (?, ?, ?)
- ''', ((port, protocol, alias) for alias in aliases))
-
-
-class ServiceRequest(common.Request):
-
- def write(self, name, aliases, port, protocol):
- self.fp.write_string(name)
- self.fp.write_stringlist(aliases)
- self.fp.write_int32(port)
- self.fp.write_string(protocol)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['cn']
- port = int(attributes['ipServicePort'][0])
- protocols = attributes['ipServiceProtocol']
- for protocol in protocols:
- yield (names[0], names[1:], port, protocol)
-
-
-class ServiceByNameRequest(ServiceRequest):
-
- action = constants.NSLCD_ACTION_SERVICE_BYNAME
-
- def read_parameters(self, fp):
- name = fp.read_string()
- protocol = fp.read_string()
- if protocol:
- return dict(cn=name, ipServiceProtocol=protocol)
- else:
- return dict(cn=name)
-
-
-class ServiceByNumberRequest(ServiceRequest):
-
- action = constants.NSLCD_ACTION_SERVICE_BYNUMBER
-
- def read_parameters(self, fp):
- number = fp.read_int32()
- protocol = fp.read_string()
- if protocol:
- return dict(ipServicePort=number, ipServiceProtocol=protocol)
- else:
- return dict(ipServicePort=number)
-
-
-class ServiceAllRequest(ServiceRequest):
-
- action = constants.NSLCD_ACTION_SERVICE_ALL
diff --git a/pynslcd/shadow.py b/pynslcd/shadow.py
deleted file mode 100644
index 89dbbfa..0000000
--- a/pynslcd/shadow.py
+++ /dev/null
@@ -1,127 +0,0 @@
-
-# shadow.py - lookup functions for shadow information
-#
-# Copyright (C) 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
-
-import cache
-import common
-import constants
-import search
-
-
-attmap = common.Attributes(uid='uid',
- userPassword='"*"',
- shadowLastChange='"${shadowLastChange:--1}"',
- shadowMin='"${shadowMin:--1}"',
- shadowMax='"${shadowMax:--1}"',
- shadowWarning='"${shadowWarning:--1}"',
- shadowInactive='"${shadowInactive:--1}"',
- shadowExpire='"${shadowExpire:--1}"',
- shadowFlag='"${shadowFlag:-0}"')
-filter = '(objectClass=shadowAccount)'
-
-
-class Search(search.LDAPSearch):
-
- case_sensitive = ('uid', )
- limit_attributes = ('uid', )
- required = ('uid', )
-
-
-class Cache(cache.Cache):
-
- create_sql = '''
- CREATE TABLE IF NOT EXISTS `shadow_cache`
- ( `uid` TEXT PRIMARY KEY,
- `userPassword` TEXT,
- `shadowLastChange` INTEGER,
- `shadowMin` INTEGER,
- `shadowMax` INTEGER,
- `shadowWarning` INTEGER,
- `shadowInactive` INTEGER,
- `shadowExpire` INTEGER,
- `shadowFlag` INTEGER,
- `mtime` TIMESTAMP NOT NULL );
- '''
-
-
-class ShadowRequest(common.Request):
-
- def write(self, name, passwd, lastchangedate, mindays, maxdays, warndays,
- inactdays, expiredate, flag):
- self.fp.write_string(name)
- self.fp.write_string(passwd)
- self.fp.write_int32(lastchangedate)
- self.fp.write_int32(mindays)
- self.fp.write_int32(maxdays)
- self.fp.write_int32(warndays)
- self.fp.write_int32(inactdays)
- self.fp.write_int32(expiredate)
- self.fp.write_int32(flag)
-
- def convert(self, dn, attributes, parameters):
- names = attributes['uid']
- try:
- passwd = attributes['userPassword'][0]
- except IndexError:
- passwd = None
- if not passwd or self.calleruid != 0:
- passwd = '*'
- # function for making an int
- def mk_int(attr):
- try:
- return int(attr)
- except TypeError:
- return None
- # get lastchange date
- lastchangedate = mk_int(attributes.get('shadowLastChange', [0])[0])
- # we expect an AD 64-bit datetime value;
- # we should do date=date/864000000000-134774
- # but that causes problems on 32-bit platforms,
- # first we devide by 1000000000 by stripping the
- # last 9 digits from the string and going from there */
- if attmap['shadowLastChange'] == 'pwdLastSet':
- lastchangedate = (lastchangedate / 864000000000) - 134774
- # get longs
- mindays = mk_int(attributes.get('shadowMin', [-1])[0])
- maxdays = mk_int(attributes.get('shadowMax', [-1])[0])
- warndays = mk_int(attributes.get('shadowWarning', [-1])[0])
- inactdays = mk_int(attributes.get('shadowInactive', [-1])[0])
- expiredate = mk_int(attributes.get('shadowExpire', [-1])[0])
- flag = mk_int(attributes.get('shadowFlag', [0])[0])
- if attmap['shadowFlag'] == 'pwdLastSet':
- if flag & 0x10000:
- maxdays = -1
- flag = 0
- # return results
- for name in names:
- yield (name, passwd, lastchangedate, mindays, maxdays, warndays,
- inactdays, expiredate, flag)
-
-
-class ShadowByNameRequest(ShadowRequest):
-
- action = constants.NSLCD_ACTION_SHADOW_BYNAME
-
- def read_parameters(self, fp):
- return dict(uid=fp.read_string())
-
-
-class ShadowAllRequest(ShadowRequest):
-
- action = constants.NSLCD_ACTION_SHADOW_ALL
diff --git a/pynslcd/tio.py b/pynslcd/tio.py
deleted file mode 100644
index ef0fda7..0000000
--- a/pynslcd/tio.py
+++ /dev/null
@@ -1,106 +0,0 @@
-
-# tio.py - I/O functions
-#
-# Copyright (C) 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
-
-import os
-import socket
-import struct
-
-
-# definition for reading and writing INT32 values
-_int32 = struct.Struct('!i')
-
-# FIXME: use something from constants.py to determine the correct size
-_struct_timeval = struct.Struct('ll')
-
-
-class TIOStreamError(Exception):
- pass
-
-
-class TIOStream(object):
- """File-like object that allows reading and writing nslcd-protocol
- entities."""
-
- def __init__(self, conn):
- conn.setblocking(1)
- conn.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, _struct_timeval.pack(0, 500000))
- conn.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, _struct_timeval.pack(60, 0))
- self.fp = os.fdopen(conn.fileno(), 'w+b', 1024 * 1024)
-
- def read(self, size):
- return self.fp.read(size)
-
- def read_int32(self):
- return _int32.unpack(self.read(_int32.size))[0]
-
- def read_string(self, maxsize=None):
- num = self.read_int32()
- if maxsize and num >= maxsize:
- raise TIOStreamError()
- return self.read(num)
-
- def read_address(self):
- """Read an address (usually IPv4 or IPv6) from the stream and return
- the address as a string representation."""
- af = self.read_int32()
- return socket.inet_ntop(af, self.read_string(maxsize=64))
-
- def write(self, value):
- self.fp.write(value)
-
- def write_int32(self, value):
- self.write(_int32.pack(value))
-
- def write_string(self, value):
- self.write_int32(len(value))
- self.write(value)
-
- def write_stringlist(self, value):
- lst = tuple(value)
- self.write_int32(len(lst))
- for string in lst:
- self.write_string(string)
-
- @staticmethod
- def _to_address(value):
- # try IPv4 first
- try:
- return socket.AF_INET, socket.inet_pton(socket.AF_INET, value)
- except socket.error:
- pass # try the next one
- # fall back to IPv6
- return socket.AF_INET6, socket.inet_pton(socket.AF_INET6, value)
-
- def write_address(self, value):
- """Write an address (usually IPv4 or IPv6) in a string representation
- to the stream."""
- # first try to make it into an IPv6 address
- af, address = TIOStream._to_address(value)
- self.write_int32(af)
- self.write_string(address)
-
- def close(self):
- try:
- self.fp.close()
- except IOError:
- pass
-
- def __del__(self):
- self.close()
diff --git a/pynslcd/usermod.py b/pynslcd/usermod.py
deleted file mode 100644
index 9622fb2..0000000
--- a/pynslcd/usermod.py
+++ /dev/null
@@ -1,129 +0,0 @@
-
-# usermod.py - functions for modifying user information
-#
-# Copyright (C) 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
-
-import ctypes
-import ctypes.util
-import logging
-import os
-import os.path
-
-import ldap
-
-import cfg
-import constants
-import pam
-import passwd
-
-
-def list_shells():
- """List the shells from /etc/shells."""
- libc = ctypes.CDLL(ctypes.util.find_library("c"))
- libc.setusershell()
- while True:
- shell = ctypes.c_char_p(libc.getusershell()).value
- if not shell:
- break
- yield shell
- libc.endusershell()
-
-
-class UserModRequest(pam.PAMRequest):
-
- action = constants.NSLCD_ACTION_USERMOD
-
- def read_parameters(self, fp):
- username = fp.read_string()
- asroot = fp.read_int32()
- password = fp.read_string()
- mods = {}
- while True:
- key = fp.read_int32()
- if key == constants.NSLCD_USERMOD_END:
- break
- mods[key] = fp.read_string()
- return dict(username=username,
- asroot=asroot,
- password=password,
- mods=mods)
-
- def write_result(self, mod, message):
- self.fp.write_int32(mod)
- self.fp.write_string(message)
-
- def handle_request(self, parameters):
- # fill in any missing userdn, etc.
- self.validate(parameters)
- is_root = (self.calleruid == 0) and parameters['asroot']
- mods = []
- # check if the the user passed the rootpwmoddn
- if parameters['asroot']:
- binddn = cfg.rootpwmoddn
- # check if rootpwmodpw should be used
- if not parameters['password'] and is_root and cfg.rootpwmodpw:
- password = cfg.rootpwmodpw
- else:
- password = parameters['password']
- else:
- binddn = parameters['userdn']
- password = parameters['password']
- # write response header
- self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
- # check home directory modification
- homedir = parameters['mods'].get(constants.NSLCD_USERMOD_HOMEDIR)
- if homedir:
- if is_root:
- mods.append((ldap.MOD_REPLACE, passwd.attmap['homeDirectory'], [homedir]))
- elif not os.path.isabs(homedir):
- self.write_result(constants.NSLCD_USERMOD_HOMEDIR,
- 'should be an absolute path')
- elif not os.path.isdir(homedir):
- self.write_result(constants.NSLCD_USERMOD_HOMEDIR,
- 'not a directory')
- else:
- mods.append((ldap.MOD_REPLACE, passwd.attmap['homeDirectory'], [homedir]))
- # check login shell modification
- shell = parameters['mods'].get(constants.NSLCD_USERMOD_SHELL)
- if shell:
- if is_root:
- mods.append((ldap.MOD_REPLACE, passwd.attmap['loginShell'], [shell]))
- elif shell not in list_shells():
- self.write_result(constants.NSLCD_USERMOD_SHELL,
- 'unlisted shell')
- elif not os.path.isfile(shell) or not os.access(shell, os.X_OK):
- self.write_result(constants.NSLCD_USERMOD_SHELL,
- 'not an executable')
- else:
- mods.append((ldap.MOD_REPLACE, passwd.attmap['loginShell'], [shell]))
- # get a connection and perform the modification
- if mods:
- try:
- conn, authz, msg = pam.authenticate(binddn, password)
- conn.modify_s(parameters['userdn'], mods)
- logging.info('changed information for %s', parameters['userdn'])
- except (ldap.INVALID_CREDENTIALS, ldap.INSUFFICIENT_ACCESS), e:
- try:
- msg = e[0]['desc']
- except:
- msg = str(e)
- logging.debug('modification failed: %s', msg)
- self.write_result(constants.NSLCD_USERMOD_RESULT, msg)
- # write closing statement
- self.fp.write_int32(constants.NSLCD_USERMOD_END)
- self.fp.write_int32(constants.NSLCD_RESULT_END)
diff --git a/utils/Makefile.am b/utils/Makefile.am
deleted file mode 100644
index e59516a..0000000
--- a/utils/Makefile.am
+++ /dev/null
@@ -1,42 +0,0 @@
-# Makefile.am - use automake to generate Makefile.in
-#
-# Copyright (C) 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
-
-utilsdir = $(datadir)/nslcd-utils
-
-utils_PYTHON = cmdline.py nslcd.py getent.py chsh.py shells.py users.py
-nodist_utils_PYTHON = constants.py
-CLEANFILES = $(nodist_utils_PYTHON)
-
-all-local: $(nodist_utils_PYTHON)
-
-# clean up locally created compiled Python files
-clean-local:
- rm -f *.pyc *.pyo
-
-# copy constants module
-constants.py: ../pynslcd/constants.py
- cp ../pynslcd/constants.py .
-
-# create symbolic links to the commands and fix permissions
-install-data-hook:
- $(MKDIR_P) $(DESTDIR)$(bindir)
- set -ex; for cmd in getent chsh ; do \
- chmod a+rx $(DESTDIR)$(utilsdir)/$$cmd.py ; \
- [ -L $(DESTDIR)$(bindir)/$$cmd.ldap ] || $(LN_S) $(utilsdir)/$$cmd.py $(DESTDIR)$(bindir)/$$cmd.ldap ; \
- done
diff --git a/utils/chsh.py b/utils/chsh.py
deleted file mode 100755
index 2f81f13..0000000
--- a/utils/chsh.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-
-# chsh.py - program for changing the login shell using nslcd
-#
-# Copyright (C) 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
-
-import argparse
-
-from cmdline import VersionAction, ListShellsAction
-import constants
-import nslcd
-import shells
-import users
-
-
-# set up command line parser
-parser = argparse.ArgumentParser(
- description='Change the user login shell in LDAP.',
- epilog='Report bugs to <%s>.' % constants.PACKAGE_BUGREPORT)
-parser.add_argument('-V', '--version', action=VersionAction)
-parser.add_argument('-s', '--shell', help='login shell for the user account')
-parser.add_argument('-l', '--list-shells', action=ListShellsAction)
-parser.add_argument('username', metavar='USER', nargs='?',
- help="the user who's shell to change")
-
-
-def ask_shell(oldshell):
- """Ask the user to provide a shell."""
- shell = raw_input(' Login Shell [%s]: ' % oldshell)
- return shell or oldshell
-
-
-if __name__ == '__main__':
- # parse arguments
- args = parser.parse_args()
- # check username part
- user = users.User(args.username)
- user.check()
- # check the command line shell if one was provided (to fail early)
- shell = args.shell
- if shell is not None:
- shells.check(shell, user.asroot)
- # prompt for a password if required
- password = user.get_passwd()
- # prompt for a shell if it was not specified on the command line
- if shell is None:
- print 'Enter the new value, or press ENTER for the default'
- shell = ask_shell(user.shell)
- shells.check(shell, user.asroot)
- # perform the modification
- result = nslcd.usermod(
- user.username, user.asroot, password, {
- constants.NSLCD_USERMOD_SHELL: shell,
- })
- # TODO: print proper response
diff --git a/utils/cmdline.py b/utils/cmdline.py
deleted file mode 100644
index 3d7d58f..0000000
--- a/utils/cmdline.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# coding: utf-8
-
-# cmdline.py - functions for handling command-line options
-#
-# Copyright (C) 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
-
-import argparse
-
-import constants
-
-
-version_string = '''
-%s
-Written by Arthur de Jong.
-
-Copyright (C) 2013 Arthur de Jong
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-'''.strip() % constants.PACKAGE_STRING
-
-
-class VersionAction(argparse.Action):
-
- def __init__(self, option_strings, dest,
- help='output version information and exit'):
- super(VersionAction, self).__init__(
- option_strings=option_strings,
- dest=argparse.SUPPRESS,
- default=argparse.SUPPRESS,
- nargs=0,
- help=help)
-
- def __call__(self, parser, namespace, values, option_string=None):
- print version_string
- parser.exit()
-
-
-class ListShellsAction(argparse.Action):
-
- def __init__(self, option_strings, dest,
- help='list the shells found in /etc/shells'):
- super(ListShellsAction, self).__init__(
- option_strings=option_strings,
- dest=argparse.SUPPRESS,
- default=argparse.SUPPRESS,
- nargs=0,
- help=help)
-
- def __call__(self, parser, namespace, values, option_string=None):
- import shells
- for shell in shells.list_shells():
- print shell
- parser.exit()
diff --git a/utils/getent.py b/utils/getent.py
deleted file mode 100755
index bd27c11..0000000
--- a/utils/getent.py
+++ /dev/null
@@ -1,353 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-
-# getent.py - program for querying nslcd
-#
-# Copyright (C) 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
-
-import argparse
-import re
-import socket
-import struct
-import sys
-
-from cmdline import VersionAction
-from nslcd import NslcdClient
-import constants
-
-
-epilog = '''
-supported databases:
- aliases, ethers, group, group.bymember, hosts, hostsv4, hostsv6,
- netgroup, netgroup.norec, networks, networksv4, networksv6, passwd,
- protocols, rpc, services, shadow
-
-Report bugs to <%s>.
-'''.strip() % constants.PACKAGE_BUGREPORT
-
-# set up command line parser
-parser = argparse.ArgumentParser(
- formatter_class=argparse.RawDescriptionHelpFormatter,
- description='Query information in LDAP via nslcd.',
- epilog=epilog)
-parser.add_argument('-V', '--version', action=VersionAction)
-parser.add_argument('database', metavar='DATABASE',
- help='any database supported by nslcd')
-parser.add_argument('key', metavar='KEY', nargs='?',
- help='filter returned database values by key')
-
-
-def getent_aliases(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_ALIAS_ALL)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_ALIAS_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- print '%-16s%s' % (
- con.read_string() + ': ',
- ', '.join(con.read_stringlist()),
- )
-
-
-def getent_ethers(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_ETHER_ALL)
- elif re.match('^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$', key):
- con = NslcdClient(constants.NSLCD_ACTION_ETHER_BYETHER)
- con.write_ether(key)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_ETHER_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- name = con.read_string()
- ether = con.read_ether()
- print '%s %s' % (ether, name)
-
-
-def getent_group(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_GROUP_ALL)
- elif database == 'group.bymember':
- con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYMEMBER)
- con.write_string(key)
- elif re.match('^\d+$', key):
- con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYGID)
- con.write_int32(int(key))
- else:
- con = NslcdClient(constants.NSLCD_ACTION_GROUP_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- print '%s:%s:%d:%s' % (
- con.read_string(),
- con.read_string(),
- con.read_int32(),
- ','.join(con.read_stringlist()),
- )
-
-
-def _get_ipv4(value):
- try:
- return socket.inet_pton(socket.AF_INET, value)
- except socket.error:
- return None
-
-
-def _get_ipv6(value):
- try:
- return socket.inet_pton(socket.AF_INET6, value)
- except socket.error:
- return None
-
-
-def _get_af(database):
- if database.endswith('v4'):
- return socket.AF_INET
- elif database.endswith('v6'):
- return socket.AF_INET6
- else:
- return None
-
-
-def getent_hosts(database, key=None):
- db_af = _get_af(database)
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_HOST_ALL)
- else:
- ipv4_addr = _get_ipv4(key)
- ipv6_addr = _get_ipv6(key)
- if ipv4_addr and db_af in (socket.AF_INET, None):
- con = NslcdClient(constants.NSLCD_ACTION_HOST_BYADDR)
- con.write_address(socket.AF_INET, ipv4_addr)
- elif ipv6_addr and db_af in (socket.AF_INET, None):
- con = NslcdClient(constants.NSLCD_ACTION_HOST_BYADDR)
- con.write_address(socket.AF_INET6, ipv6_addr)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_HOST_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- names = ' '.join([con.read_string()] + con.read_stringlist())
- for af, address in con.read_addresslist():
- if db_af in (af, None):
- print '%-15s %s' % (address, names)
-
-
-def _read_netgroup(con):
- """Read netgroup name, members and tripples from stream."""
- name = con.read_string()
- members = []
- tripples = []
- while True:
- member_type = con.read_int32()
- if member_type == constants.NSLCD_NETGROUP_TYPE_NETGROUP:
- members.append(con.read_string())
- elif member_type == constants.NSLCD_NETGROUP_TYPE_TRIPLE:
- tripples.append((
- con.read_string(), con.read_string(),
- con.read_string()
- ))
- else:
- break
- return name, members, tripples
-
-
-def _get_getgroups(con, recurse, netgroups=None):
- if netgroups is None:
- netgroups = {}
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- name, members, tripples = _read_netgroup(con)
- if not recurse:
- yield (name, members, tripples)
- else:
- netgroups[name] = None
- for netgroup in members:
- if netgroup not in netgroups:
- con2 = NslcdClient(constants.NSLCD_ACTION_NETGROUP_BYNAME)
- con2.write_string(netgroup)
- all(_get_getgroups(con2, recurse, netgroups))
- if netgroups.get(netgroup, None) is not None:
- tripples += netgroups[netgroup][1]
- netgroups[name] = (members, tripples)
- yield (name, [], tripples)
-
-
-def getent_netgroup(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_NETGROUP_ALL)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_NETGROUP_BYNAME)
- con.write_string(key)
- for name, members, tripples in _get_getgroups(con, database == 'netgroup'):
- print '%-15s %s' % (name, ' '.join(
- members +
- ['(%s, %s, %s)' % (host, user, domain)
- for host, user, domain in tripples]
- ))
-
-
-def getent_networks(database, key=None):
- db_af = _get_af(database)
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_NETWORK_ALL)
- else:
- ipv4_addr = _get_ipv4(key)
- ipv6_addr = _get_ipv6(key)
- if ipv4_addr and db_af in (socket.AF_INET, None):
- con = NslcdClient(constants.NSLCD_ACTION_NETWORK_BYADDR)
- con.write_address(socket.AF_INET, ipv4_addr)
- elif ipv6_addr and db_af in (socket.AF_INET, None):
- con = NslcdClient(constants.NSLCD_ACTION_NETWORK_BYADDR)
- con.write_address(socket.AF_INET6, ipv6_addr)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_NETWORK_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- names = ' '.join([con.read_string()] + con.read_stringlist())
- for af, address in con.read_addresslist():
- if db_af in (af, None):
- print '%-15s %s' % (address, names)
-
-
-def getent_passwd(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_PASSWD_ALL)
- elif re.match('^\d+$', key):
- con = NslcdClient(constants.NSLCD_ACTION_PASSWD_BYUID)
- con.write_int32(int(key))
- else:
- con = NslcdClient(constants.NSLCD_ACTION_PASSWD_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- print '%s:%s:%d:%d:%s:%s:%s' % (
- con.read_string(),
- con.read_string(),
- con.read_int32(),
- con.read_int32(),
- con.read_string(),
- con.read_string(),
- con.read_string(),
- )
-
-
-def getent_protocols(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_ALL)
- elif re.match('^\d+$', key):
- con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_BYNUMBER)
- con.write_int32(int(key))
- else:
- con = NslcdClient(constants.NSLCD_ACTION_PROTOCOL_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- name = con.read_string()
- aliases = con.read_stringlist()
- number = con.read_int32()
- print '%-21s %d %s' % (name, number, ' '.join(aliases))
-
-
-def getent_rpc(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_RPC_ALL)
- elif re.match('^\d+$', key):
- con = NslcdClient(constants.NSLCD_ACTION_RPC_BYNUMBER)
- con.write_int32(int(key))
- else:
- con = NslcdClient(constants.NSLCD_ACTION_RPC_BYNAME)
- con.write_string(key)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- name = con.read_string()
- aliases = con.read_stringlist()
- number = con.read_int32()
- print '%-15s %d %s' % (name, number, ' '.join(aliases))
-
-
-def getent_services(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_SERVICE_ALL)
- else:
- value = key
- protocol = ''
- if '/' in value:
- value, protocol = value.split('/', 1)
- if re.match('^\d+$', value):
- con = NslcdClient(constants.NSLCD_ACTION_SERVICE_BYNUMBER)
- con.write_int32(int(value))
- con.write_string(protocol)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_SERVICE_BYNAME)
- con.write_string(value)
- con.write_string(protocol)
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- name = con.read_string()
- aliases = con.read_stringlist()
- number = con.read_int32()
- protocol = con.read_string()
- print '%-21s %d/%s %s' % (name, number, protocol, ' '.join(aliases))
-
-
-def getent_shadow(database, key=None):
- if not key:
- con = NslcdClient(constants.NSLCD_ACTION_SHADOW_ALL)
- else:
- con = NslcdClient(constants.NSLCD_ACTION_SHADOW_BYNAME)
- con.write_string(key)
- value2str = lambda x: str(x) if x != -1 else ''
- while con.get_response() == constants.NSLCD_RESULT_BEGIN:
- print '%s:%s:%s:%s:%s:%s:%s:%s:%s' % (
- con.read_string(),
- con.read_string(),
- value2str(con.read_int32()),
- value2str(con.read_int32()),
- value2str(con.read_int32()),
- value2str(con.read_int32()),
- value2str(con.read_int32()),
- value2str(con.read_int32()),
- value2str(con.read_int32()),
- )
-
-
-if __name__ == '__main__':
- args = parser.parse_args()
- try:
- if args.database == 'aliases':
- getent_aliases(args.database, args.key)
- elif args.database == 'ethers':
- getent_ethers(args.database, args.key)
- elif args.database in ('group', 'group.bymember'):
- getent_group(args.database, args.key)
- elif args.database in ('hosts', 'hostsv4', 'hostsv6'):
- getent_hosts(args.database, args.key)
- elif args.database in ('netgroup', 'netgroup.norec'):
- getent_netgroup(args.database, args.key)
- elif args.database in ('networks', 'networksv4', 'networksv6'):
- getent_networks(args.database, args.key)
- elif args.database == 'passwd':
- getent_passwd(args.database, args.key)
- elif args.database == 'protocols':
- getent_protocols(args.database, args.key)
- elif args.database == 'rpc':
- getent_rpc(args.database, args.key)
- elif args.database == 'services':
- getent_services(args.database, args.key)
- elif args.database == 'shadow':
- getent_shadow(args.database, args.key)
- else:
- parser.error('Unknown database: %s' % args.database)
- except struct.error:
- print 'Problem communicating with nslcd'
- sys.exit(1)
diff --git a/utils/nslcd.py b/utils/nslcd.py
deleted file mode 100644
index 22d18b7..0000000
--- a/utils/nslcd.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# coding: utf-8
-
-# nslcd.py - functions for doing nslcd requests
-#
-# Copyright (C) 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
-
-import fcntl
-import os
-import socket
-import struct
-
-import constants
-
-
-# definition for reading and writing INT32 values
-_int32 = struct.Struct('!i')
-
-
-class NslcdClient(object):
-
- def __init__(self, action):
- # set up the socket (store in class to avoid closing it)
- self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- fcntl.fcntl(self.sock, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
- # connect to nslcd
- self.sock.connect(constants.NSLCD_SOCKET)
- #self.sock.setblocking(1)
- self.fp = os.fdopen(self.sock.fileno(), 'r+b', 1024 * 1024)
- # write a request header with a request code
- self.action = action
- self.write_int32(constants.NSLCD_VERSION)
- self.write_int32(action)
-
- def write(self, value):
- self.fp.write(value)
-
- def write_int32(self, value):
- self.write(_int32.pack(value))
-
- def write_string(self, value):
- self.write_int32(len(value))
- self.write(value)
-
- def write_ether(self, value):
- value = struct.pack('BBBBBB', *(int(x, 16) for x in value.split(':')))
- self.write(value)
-
- def write_address(self, af, value):
- self.write_int32(af)
- self.write_string(value)
-
- def read(self, size):
- return self.fp.read(size)
-
- def read_int32(self):
- return _int32.unpack(self.read(_int32.size))[0]
-
- def read_string(self):
- num = self.read_int32()
- return self.read(num)
-
- def read_stringlist(self):
- num = self.read_int32()
- return [self.read_string() for x in xrange(num)]
-
- def read_ether(self):
- value = self.fp.read(6)
- return ':'.join('%x' % x for x in struct.unpack('6B', value))
-
- def read_address(self):
- af = self.read_int32()
- return af, socket.inet_ntop(af, self.read_string())
-
- def read_addresslist(self):
- num = self.read_int32()
- return [self.read_address() for x in xrange(num)]
-
- def get_response(self):
- # complete the request if required and check response header
- if self.action:
- # flush the stream
- self.fp.flush()
- # read and check response version number
- assert self.read_int32() == constants.NSLCD_VERSION
- assert self.read_int32() == self.action
- self.action = None
- # get the NSLCD_RESULT_* marker and return it
- return self.read_int32()
-
- def close(self):
- if hasattr(self, 'fp'):
- try:
- self.fp.close()
- except IOError:
- pass
-
- def __del__(self):
- self.close()
-
-
-def usermod(username, asroot=False, password=None, args=None):
- # open a connection to nslcd
- con = NslcdClient(constants.NSLCD_ACTION_USERMOD)
- # write the request information
- con.write_string(username)
- con.write_int32(1 if asroot else 0)
- con.write_string(password)
- for k, v in args.items():
- con.write_int32(k)
- con.write_string(v)
- con.write_int32(constants.NSLCD_USERMOD_END)
- # read the response
- assert con.get_response() == constants.NSLCD_RESULT_BEGIN
- response = {}
- while True:
- key = con.read_int32()
- if key == constants.NSLCD_USERMOD_END:
- break
- response[key] = con.read_string()
- # return the response
- return response
diff --git a/utils/shells.py b/utils/shells.py
deleted file mode 100644
index cc3fca1..0000000
--- a/utils/shells.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# coding: utf-8
-
-# shells.py - functions for validating user shells
-#
-# Copyright (C) 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
-
-import ctypes
-import ctypes.util
-import os
-import sys
-
-
-def list_shells():
- """List the shells from /etc/shells."""
- libc = ctypes.CDLL(ctypes.util.find_library("c"))
- libc.setusershell()
- while True:
- shell = ctypes.c_char_p(libc.getusershell()).value
- if not shell:
- break
- yield shell
- libc.endusershell()
-
-
-def shellexists(shell):
- """Check if the provided shell exists and is executable."""
- return os.path.isfile(shell) and os.access(shell, os.X_OK)
-
-
-def check(shell, asroot=False):
- """Check if the specified shell is valid and exit if it isn't."""
- # if the shell is listed in /etc/shells, everything should be OK
- if shell in list_shells():
- return
- # if we are not root, bail out
- if not asroot:
- if not shell:
- # FIXME: print to stderr
- print '%s: empty shell not allowed' % sys.argv[0]
- else:
- # FIXME: print to stderr
- print '%s: %s is an invalid shell' % (sys.argv[0], shell)
- sys.exit(1)
- # warn if something seems wrong
- if not shell:
- # FIXME: print to stderr
- print '%s: Warning: setting empty shell' % sys.argv[0]
- elif not shellexists(shell):
- print '%s: Warning: %s does not exist' % (sys.argv[0], shell)
diff --git a/utils/users.py b/utils/users.py
deleted file mode 100644
index 3387318..0000000
--- a/utils/users.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# coding: utf-8
-
-# users.py - functions for validating the user to change information for
-#
-# Copyright (C) 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
-
-import getpass
-import os
-import pwd
-import sys
-
-
-class User(object):
-
- def __init__(self, username):
- self.myuid = os.getuid()
- if username:
- userinfo = pwd.getpwnam(username)
- else:
- self.asroot = False
- userinfo = pwd.getpwuid(self.myuid)
- (self.username, self.password, self.uid, self.gid, self.gecos,
- self.homedir, self.shell) = userinfo
- # if we are trying to modify another user we should be root
- self.asroot = self.myuid != self.uid
-
- def check(self):
- """Check if the user we want to modify is an LDAP user and whether
- we may modify the user information."""
- if self.asroot and self.myuid != 0:
- print "%s: you may not modify user '%s'.\n" % \
- (sys.argv[0], self.username)
- sys.exit(1)
- # FIXME: check if the user is an LDAP user
-
- def get_passwd(self):
- """Ask and return a password that is required to change the user."""
- # FIXME: only ask the password if we require it
- # (e.g. when root and nslcd has userpwmoddn we don't need to)
- return getpass.getpass(
- 'LDAP administrator password: '
- if self.asroot else
- 'LDAP password for %s: ' % self.username
- )
- # FIXME: check if the provided password is valid