diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2014-10-04 16:12:13 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2014-10-04 16:12:13 -0400 |
commit | be4588009b7106859e1beae6038aaea8d7f85825 (patch) | |
tree | ee0010a7003d23a686888fc9585de4e0ec429547 | |
parent | 8e54633a2b520dff0a237349f5fc4cbcf4719f40 (diff) |
remove non-nslcd stuff
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 <arthur@arthurdejong.org>.</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 <arthur@arthurdejong.org>.</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 <arthur@arthurdejong.org>. - </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 <arthur@arthurdejong.org>.</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 |