diff options
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | man/nss-ldapd.conf.5.xml | 482 | ||||
-rw-r--r-- | nslcd/attmap.c | 128 | ||||
-rw-r--r-- | nslcd/attmap.h | 3 | ||||
-rw-r--r-- | nslcd/cfg.c | 1205 | ||||
-rw-r--r-- | nslcd/cfg.h | 94 | ||||
-rw-r--r-- | nslcd/ldap-nss.c | 4 | ||||
-rw-r--r-- | nslcd/ldap-schema.h | 16 | ||||
-rw-r--r-- | nslcd/nslcd.c | 7 | ||||
-rw-r--r-- | nss-ldapd.conf | 183 |
10 files changed, 976 insertions, 1154 deletions
diff --git a/configure.ac b/configure.ac index e69a79f..3dba332 100644 --- a/configure.ac +++ b/configure.ac @@ -107,14 +107,6 @@ AC_ARG_WITH(ldap-conf-file, AC_DEFINE_UNQUOTED(NSS_LDAP_PATH_CONF,"$NSS_LDAP_PATH_CONF",[Path to LDAP configuration file.]) AC_SUBST(NSS_LDAP_PATH_CONF) -AC_ARG_WITH(ldap-secret-file, - AS_HELP_STRING([--with-ldap-secret-file=PATH], - [path to LDAP root secret file @<:@/etc/nss-ldapd.secret@:>@]), - [ NSS_LDAP_PATH_ROOTPASSWD="$with_ldap_secret_file" ], - [ NSS_LDAP_PATH_ROOTPASSWD="/etc/nss-ldapd.secret" ]) -AC_DEFINE_UNQUOTED(NSS_LDAP_PATH_ROOTPASSWD,"$NSS_LDAP_PATH_ROOTPASSWD",[Path to LDAP root secret file.]) -AC_SUBST(NSS_LDAP_PATH_ROOTPASSWD) - AC_ARG_WITH(nslcd-pidfile, AS_HELP_STRING([--with-nslcd-pidfile=PATH], [path to pidfile @<:@/var/run/nslcd/nslcd.pid@:>@]), diff --git a/man/nss-ldapd.conf.5.xml b/man/nss-ldapd.conf.5.xml index 404e27e..d88f441 100644 --- a/man/nss-ldapd.conf.5.xml +++ b/man/nss-ldapd.conf.5.xml @@ -21,7 +21,7 @@ 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 + 02110-1301 USA --> <refentry id="nssldapdconf5"> @@ -201,6 +201,7 @@ </variablelist> </refsect2> +<!-- DO NOT DOCUMENT FOR NOW BECAUSE IT'S NOT SUPPORTED <refsect2 id='sasl_authentication_options'> <title>SASL authentication options</title> <variablelist> @@ -214,7 +215,7 @@ </varlistentry> <varlistentry> - <term><emphasis remap="B">rootsasl_auth_id <authid></emphasis></term> + <term><emphasis remap="B">rootsasl_authid <authid></emphasis></term> <listitem> <para>Specifies the authorization identity to be used when performing SASL authentication as root (when the effective user ID is zero).</para> @@ -232,7 +233,7 @@ </varlistentry> <varlistentry> - <term><emphasis remap="B">rootuse_sasl <yes|no></emphasis></term> + <term><emphasis remap="B"><opional>root</opional>use_sasl <yes|no></emphasis></term> <listitem> <para>Specifies whether SASL authentication should be used when the effective user ID is zero.</para> @@ -241,7 +242,9 @@ </variablelist> </refsect2> +--> +<!-- DO NOT DOCUMENT FOR NOW BECAUSE IT'S NOT SUPPORTED <refsect2 id='kerberos_authentication_options'> <title>Kerberos authentication options</title> <variablelist> @@ -258,132 +261,117 @@ </variablelist> </refsect2> +--> <refsect2 id='search_mapping_options'> <title>Search/mapping options</title> <variablelist> - <varlistentry> - <term><emphasis remap="B">base <base></emphasis></term> - <listitem> - <para>Specifies the default base distinguished name (DN) to use for searches.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><emphasis remap="B">scope <sub|one|base></emphasis></term> + <varlistentry> + <term><option>base</option> + <optional><emphasis remap="I">MAP</emphasis></optional> + <emphasis remap="I">DN</emphasis></term> <listitem> - <para>Specifies the search scope (subtree, one level or base object). The - default scope is subtree; base scope is almost never useful for - nameservice lookups.</para> + <para> + Specifies the base distinguished name (<acronym>DN</acronym>) + to use as search base. + A global search base may be specified or a MAP-specific one. + If no MAP-specific search base is defined the global one is used. + </para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> - <term><emphasis remap="B">deref <never|searching|finding|always></emphasis></term> + <varlistentry> + <term><option>scope</option> + <optional><emphasis remap="I">MAP</emphasis></optional> + sub<optional>tree</optional>|one<optional>level</optional>|base</term> <listitem> - <para>Specifies the policy for dereferencing aliases. The default policy is - to never dereference aliases.</para> + <para> + Specifies the search scope (subtree, one level or base object). + The default scope is subtree; base scope is almost never useful for + nameservice lookups. + </para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> - <term><emphasis remap="B">referrals <yes|no></emphasis></term> + <varlistentry> + <term><option>deref</option> never|searching|finding|always</term> <listitem> - <para>Specifies whether automatic referral chasing should be enabled. The - default behaviour is specifed by the - <emphasis remap="I">LDAP</emphasis> - client library.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><emphasis remap="B">nss_base_<map> <basedn?scope?filter></emphasis></term> - <listitem> - <para>Specify the search base, scope and filter to be used for specific - maps. (Note that - <emphasis remap="B">map</emphasis> - forms part of the configuration file keyword and is one of - passwd, shadow, group, hosts, services, networks, protocols, - rpc, ethers, netmasks, bootparams, aliases and netgroup.) - The syntax of - <emphasis remap="B">basedn</emphasis> - and - <emphasis remap="B">scope</emphasis> - are the same as for the configuration file options of the same - name, with the addition of being able to omit the trailing suffix - of the base DN (in which case the global base DN will be appended - instead). The - <emphasis remap="B">filter</emphasis> - is a search filter to be added to the default search filter for a - specific map, such that the effective filter is the logical - intersection of the two. The base DN, scope and filter are separated - with literal question marks (?) as given above; this is for - compatibility with the DUA configuration profile schema and the - <emphasis remap="B">ldapprofile</emphasis> - tool. This option may be specified multiple times.</para> + <para> + Specifies the policy for dereferencing aliases. + The default policy is to never dereference aliases. + </para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> - <term><emphasis remap="B">nss_map_attribute <from_attribute> <to_attribute></emphasis></term> + <varlistentry> + <term><option>referrals</option> yes|no</term> <listitem> - <para>This option may be specified multiple times, and directs - <emphasis remap="B">nss_ldap</emphasis> - to use the attribute - <emphasis remap="B">to_attribute</emphasis> - instead of the RFC 2307 attribute - <emphasis remap="B">from_attribute</emphasis> - in all lookups. - If - <emphasis remap="B">nss_ldap</emphasis> - was built without schema mapping support, then this option - is ignored.</para> + <para> + Specifies whether automatic referral chasing should be enabled. + The default behaviour is to chase referrals. + </para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> - <term><emphasis remap="B">nss_map_objectclass <from_objectclass> <to_objectclass></emphasis></term> + <varlistentry> + <term><option>filter</option> + <emphasis remap="I">MAP</emphasis> + <emphasis remap="I">FILTER</emphasis></term> <listitem> - <para>This option may be specified multiple times, and directs - <emphasis remap="B">nss_ldap</emphasis> - to use the object class - <emphasis remap="B">to_objectclass</emphasis> - instead of the RFC 2307 object class - <emphasis remap="B">from_objectclass</emphasis> - in all lookups. - If - <emphasis remap="B">nss_ldap</emphasis> - was built without schema mapping support, then this option - is ignored.</para> + <para> + The <emphasis remap="I">FILTER</emphasis> + is an <acronym>LDAP</acronym> search filter to use for a + specific map. + The default filter is a basic search on the + objectClass for the map (e.g. <code>(objectClass=posixAccount)</code>). + </para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> - <term><emphasis remap="B">nss_default_attribute_value <attribute> <value></emphasis></term> + <varlistentry> + <term><option>map</option> + <emphasis remap="I">MAP</emphasis> + <emphasis remap="I">ATTRIBUTE</emphasis> + <emphasis remap="I">NEWATTRIBUTE</emphasis></term> <listitem> - <para>Specifies the default value to use for entries that lack the - specified attribute. This option may be specified multiple times, - for different attributes. - If - <emphasis remap="B">nss_ldap</emphasis> - was built without schema mapping support, then this option - is ignored.</para> + <para> + This option allows for custom attributes to be looked up instead of + the default RFC 2307 attributes that are used. + The <emphasis remap="I">MAP</emphasis> may be one of + the supported maps below. + The <emphasis remap="I">ATTRIBUTE</emphasis> is the one as + used in <acronym>RFC</acronym> 2307 (e.g. <code>userPassword</code>, + <code>ipProtocolNumber</code> or <code>macAddress</code>). + The <emphasis remap="I">NEWATTRIBUTE</emphasis> may be any attribute + as it is available in the directory. +<!-- + If the <emphasis remap="I">NEWATTRIBUTE</emphasis> is presented in + quotes (") the specfied value will be used instead of looking up the + value in the directory. + Specifies a value to use for the specified attribute in preference + to that contained in the actual entry. +--> + </para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> - <term><emphasis remap="B">nss_override_attribute_value <attribute> <value></emphasis></term> +<!-- + <varlistentry> + <term><option>default</option> <emphasis remap="I">MAP.ATTRIBUTE</emphasis> "<emphasis remap="I">VALUE</emphasis>"</term> <listitem> - <para>Specifies a value to use for the specified attribute in preference - to that contained in the actual entry. This option may be specified - multiple times, for different attributes. - If - <emphasis remap="B">nss_ldap</emphasis> - was built without schema mapping support, then this option - is ignored.</para> + <para> + Specifies the default value to use for entries that lack the + specified attribute. + Use the specified <emphasis remap="I">VALUE</emphasis> if the + lookup in the directory for the specified attribute would not return + any data. + Note that if the <acronym>LDAP</acronym> server returns an empty string + for the attribute an empty string is returned. + </para> </listitem> - </varlistentry> + </varlistentry> +--> </variablelist> </refsect2> @@ -392,68 +380,68 @@ <title>Timing/reconnect options</title> <variablelist> - <varlistentry> + <varlistentry> <term><emphasis remap="B">timelimit <timelimit></emphasis></term> <listitem> - <para>Specifies the time limit (in seconds) to use when performing searches. A value - of zero (0), which is the default, is to wait indefinitely for - searches to be completed.</para> + <para>Specifies the time limit (in seconds) to use when performing searches. A value + of zero (0), which is the default, is to wait indefinitely for + searches to be completed.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">bind_timelimit <timelimit></emphasis></term> <listitem> - <para>Specifies the time limit (in seconds) to use when connecting to the directory - server. This is distinct from the time limit specified in - <emphasis remap="B">timelimit</emphasis> - and affects the initial server connection only. (Server connections - are otherwise cached.) Only some - <emphasis remap="I">LDAP</emphasis> - client libraries have the underlying functionality necessary to - support this option. The default bind timelimit is 30 seconds.</para> + <para>Specifies the time limit (in seconds) to use when connecting to the directory + server. This is distinct from the time limit specified in + <emphasis remap="B">timelimit</emphasis> + and affects the initial server connection only. (Server connections + are otherwise cached.) Only some + <acronym>LDAP</acronym> + client libraries have the underlying functionality necessary to + support this option. The default bind timelimit is 30 seconds.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">bind_policy <hard_open|hard_init|soft></emphasis></term> <listitem> - <para>Specifies the policy to use for reconnecting to an unavailable - <emphasis remap="I">LDAP</emphasis> - server. The default is - <emphasis remap="B">hard_open,</emphasis> - which reconnects if opening the connection to the directory server - failed. By contrast, - <emphasis remap="B">hard_init</emphasis> - reconnects if initializing the connection failed. Initializing may not - actually contact the directory server, and it is possible that a - malformed configuration file will trigger reconnection. If - <emphasis remap="B">soft</emphasis> - is specified, then - <emphasis remap="B">nss_ldap</emphasis> - will return immediately on server failure. All "hard" reconnect - policies block with exponential backoff before retrying.</para> + <para>Specifies the policy to use for reconnecting to an unavailable + <acronym>LDAP</acronym> + server. The default is + <emphasis remap="B">hard_open,</emphasis> + which reconnects if opening the connection to the directory server + failed. By contrast, + <emphasis remap="B">hard_init</emphasis> + reconnects if initializing the connection failed. Initializing may not + actually contact the directory server, and it is possible that a + malformed configuration file will trigger reconnection. If + <emphasis remap="B">soft</emphasis> + is specified, then + <emphasis remap="B">nss_ldap</emphasis> + will return immediately on server failure. All "hard" reconnect + policies block with exponential backoff before retrying.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">nss_connect_policy <persist|oneshot></emphasis></term> <listitem> - <para>Determines whether nss_ldap persists connections. The default - is for the connection to the LDAP server to remain open after - the first request.</para> + <para>Determines whether nss_ldap persists connections. The default + is for the connection to the LDAP server to remain open after + the first request.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">idle_timelimit <timelimit></emphasis></term> <listitem> - <para>Specifies the time (in seconds) after which - <emphasis remap="B">nss_ldap</emphasis> - will close connections to the directory server. The default is not to - time out connections.</para> + <para>Specifies the time (in seconds) after which + <emphasis remap="B">nss_ldap</emphasis> + will close connections to the directory server. The default is not to + time out connections.</para> </listitem> - </varlistentry> + </varlistentry> </variablelist> </refsect2> @@ -462,89 +450,87 @@ <title>SSL/TLS options</title> <variablelist> - <varlistentry> + <varlistentry> <term><emphasis remap="B">ssl <on|off|start_tls></emphasis></term> <listitem> - <para>Specifies whether to use SSL/TLS or not (the default is not to). If - <emphasis remap="B">start_tls</emphasis> - is specified then StartTLS is used rather than raw LDAP over SSL. - Not all - <emphasis remap="I">LDAP</emphasis> - client libraries support both SSL and StartTLS, and all related - configuration options.</para> + <para>Specifies whether to use SSL/TLS or not (the default is not to). If + <emphasis remap="B">start_tls</emphasis> + is specified then StartTLS is used rather than raw LDAP over SSL. + Not all <acronym>LDAP</acronym> client libraries support both SSL + and StartTLS, and all related configuration options.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">sslpath <cert7_path></emphasis></term> <listitem> - <para>For the Netscape and Mozilla - <emphasis remap="I">LDAP</emphasis> - client libraries only, this specifies the path to the X.509 - certificate database.</para> + <para>For the Netscape and Mozilla + <acronym>LDAP</acronym> + client libraries only, this specifies the path to the X.509 + certificate database.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_checkpeer <yes|no></emphasis></term> <listitem> - <para>Specifies whether to require and verify the server certificate - or not, when using SSL/TLS with the OpenLDAP client library. - The default is to use the default behaviour of the client - library; for OpenLDAP 2.0 and earlier it is "no", for OpenLDAP - 2.1 and later it is "yes". At least one of - <emphasis remap="B">tls_cacertdir</emphasis> - and - <emphasis remap="B">tls_cacertfile</emphasis> - is required if peer verification is enabled.</para> + <para>Specifies whether to require and verify the server certificate + or not, when using SSL/TLS with the OpenLDAP client library. + The default is to use the default behaviour of the client + library; for OpenLDAP 2.0 and earlier it is "no", for OpenLDAP + 2.1 and later it is "yes". At least one of + <emphasis remap="B">tls_cacertdir</emphasis> + and + <emphasis remap="B">tls_cacertfile</emphasis> + is required if peer verification is enabled.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_cacertdir <certificate_dir></emphasis></term> <listitem> - <para>Specifies the directory containing X.509 certificates for peer - authentication.</para> + <para>Specifies the directory containing X.509 certificates for peer + authentication.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_cacertfile <certificate_file></emphasis></term> <listitem> - <para>Specifies the path to the X.509 certificate for peer authentication.</para> + <para>Specifies the path to the X.509 certificate for peer authentication.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_randfile <entropy_file></emphasis></term> <listitem> - <para>Specifies the path to an entropy source.</para> + <para>Specifies the path to an entropy source.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_ciphers <ciphers></emphasis></term> <listitem> - <para>Specifies the ciphers to use for TLS. See your TLS implementation's - documentation for further information.</para> + <para>Specifies the ciphers to use for TLS. See your TLS implementation's + documentation for further information.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_cert <certificate_file></emphasis></term> <listitem> - <para>Specifies the path to the file containing the local certificate for - client TLS authentication.</para> + <para>Specifies the path to the file containing the local certificate for + client TLS authentication.</para> </listitem> - </varlistentry> + </varlistentry> - <varlistentry> + <varlistentry> <term><emphasis remap="B">tls_key <key_file></emphasis></term> <listitem> - <para>Specifies the path to the file containing the private key for client - TLS authentication.</para> + <para>Specifies the path to the file containing the private key for client + TLS authentication.</para> </listitem> - </varlistentry> + </varlistentry> </variablelist> </refsect2> @@ -566,31 +552,6 @@ </listitem> </varlistentry> - <varlistentry> - <term><emphasis remap="B">logdir <directory></emphasis></term> - <listitem> - <para>Specifies the directory used for logging by the - <emphasis remap="I">LDAP</emphasis> - client library. This feature is not supported by all client - libraries.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><emphasis remap="B">debug <level></emphasis></term> - <listitem> - <para>Specifies the debug level used for logging by the - <emphasis remap="I">LDAP</emphasis> - client library. This feature is not supported by all client - libraries, and does not apply to the - <emphasis remap="B">nss_ldap</emphasis> - and - <emphasis remap="B">pam_ldap</emphasis> - modules themselves (debugging, if any, is configured separately - and usually at compile time).</para> - </listitem> - </varlistentry> - <varlistentry> <term><option>pagesize</option> <emphasis remap="I">NUMBER</emphasis></term> <listitem> @@ -614,33 +575,6 @@ TODO: remove the above option and always support mulitple schema checking based on the contenst of the directory - <varlistentry> - <term><emphasis remap="B">nss_initgroups <backlink></emphasis></term> - <listitem> - <para>This option directs the - <emphasis remap="B">nss_ldap</emphasis> - implementation of - <emphasis remap="B">initgroups(3)</emphasis> - to determine a user's group membership by reading the memberOf - attribute of their directory entry (and of any nested groups), - rather than querying on uniqueMember. This may provide increased - performance with certain directory servers that have peculiar - indexing configurations. - If RFC2307bis support is disabled, then this option is ignored.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><emphasis remap="B">nss_initgroups_ignoreusers <user1,user2,...,userN></emphasis></term> - <listitem> - <para>This option directs the - <emphasis remap="B">nss_ldap</emphasis> - implementation of - <emphasis remap="B">initgroups(3)</emphasis> - to return NSS_STATUS_NOTFOUND if called with a listed users as - its argument.</para> - </listitem> - </varlistentry> </variablelist> </refsect2> @@ -648,6 +582,60 @@ TODO: remove the above option and always support mulitple schema checking based </refsect1> + <refsect1 id="maps"> + <title>Supported maps</title> + <para> + The following maps are supported. They are referenced as + <emphasis remap="I">MAP</emphasis> withthe options. + </para> + <variablelist remap="TP"> + <varlistentry> + <term>alias(es)</term> + <listitem><para>Mail aliases (ignored by most mail servers).</para></listitem> + </varlistentry> + <varlistentry> + <term>ether(s)</term> + <listitem><para>Ethernet numbers (mac addresses).</para></listitem> + </varlistentry> + <varlistentry> + <term>group</term> + <listitem><para>Posix groups.</para></listitem> + </varlistentry> + <varlistentry> + <term>host(s)</term> + <listitem><para>Host names.</para></listitem> + </varlistentry> + <varlistentry> + <term>netgroup</term> + <listitem><para>Host and user groups used for access control.</para></listitem> + </varlistentry> + <varlistentry> + <term>network(s)</term> + <listitem><para>Network numbers.</para></listitem> + </varlistentry> + <varlistentry> + <term>passwd</term> + <listitem><para>Posix users.</para></listitem> + </varlistentry> + <varlistentry> + <term>protocol(s)</term> + <listitem><para>Protocol definitions (like in <filename>/etc/protocols</filename>).</para></listitem> + </varlistentry> + <varlistentry> + <term>rpc</term> + <listitem><para>Remote procedure call names and numbers.</para></listitem> + </varlistentry> + <varlistentry> + <term>service(s)</term> + <listitem><para>Network service names and numbers.</para></listitem> + </varlistentry> + <varlistentry> + <term>shadow</term> + <listitem><para>Shadow user password information.</para></listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1 id="files"> <title>Files</title> <variablelist remap="TP"> diff --git a/nslcd/attmap.c b/nslcd/attmap.c index 4029d43..bec4a51 100644 --- a/nslcd/attmap.c +++ b/nslcd/attmap.c @@ -177,92 +177,92 @@ const char *attmap_shadow_shadowInactive = "shadowInactive"; const char *attmap_shadow_shadowExpire = "shadowExpire"; const char *attmap_shadow_shadowFlag = "shadowFlag"; -const char **attmap_get_var(const char *name) +const char **attmap_get_var(enum ldap_map_selector map,const char *name) { - if (strncasecmp(name,"alias.",6)==0) + if (map==LM_ALIASES) { - if (strcasecmp(name+6,"objectClass")==0) return &attmap_alias_objectClass; - if (strcasecmp(name+6,"cn")==0) return &attmap_alias_cn; - if (strcasecmp(name+6,"rfc822MailMember")==0) return &attmap_alias_rfc822MailMember; + if (strcasecmp(name,"objectClass")==0) return &attmap_alias_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_alias_cn; + if (strcasecmp(name,"rfc822MailMember")==0) return &attmap_alias_rfc822MailMember; } - else if (strncasecmp(name,"ether.",6)==0) + else if (map==LM_ETHERS) { - if (strcasecmp(name+6,"objectClass")==0) return &attmap_ether_objectClass; - if (strcasecmp(name+6,"cn")==0) return &attmap_ether_cn; - if (strcasecmp(name+6,"macAddress")==0) return &attmap_ether_macAddress; + if (strcasecmp(name,"objectClass")==0) return &attmap_ether_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_ether_cn; + if (strcasecmp(name,"macAddress")==0) return &attmap_ether_macAddress; } - else if (strncasecmp(name,"group.",6)==0) + else if (map==LM_GROUP) { - if (strcasecmp(name+6,"objectClass")==0) return &attmap_group_objectClass; - if (strcasecmp(name+6,"cn")==0) return &attmap_group_cn; - if (strcasecmp(name+6,"userPassword")==0) return &attmap_group_userPassword; - if (strcasecmp(name+6,"gidNumber")==0) return &attmap_group_gidNumber; - if (strcasecmp(name+6,"memberUid")==0) return &attmap_group_memberUid; - if (strcasecmp(name+6,"uniqueMember")==0) return &attmap_group_uniqueMember; - if (strcasecmp(name+6,"memberOf")==0) return &attmap_group_memberOf; + if (strcasecmp(name,"objectClass")==0) return &attmap_group_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_group_cn; + if (strcasecmp(name,"userPassword")==0) return &attmap_group_userPassword; + if (strcasecmp(name,"gidNumber")==0) return &attmap_group_gidNumber; + if (strcasecmp(name,"memberUid")==0) return &attmap_group_memberUid; + if (strcasecmp(name,"uniqueMember")==0) return &attmap_group_uniqueMember; + if (strcasecmp(name,"memberOf")==0) return &attmap_group_memberOf; } - else if (strncasecmp(name,"host.",5)==0) + else if (map==LM_HOSTS) { - if (strcasecmp(name+5,"objectClass")==0) return &attmap_host_objectClass; - if (strcasecmp(name+5,"cn")==0) return &attmap_host_cn; - if (strcasecmp(name+5,"ipHostNumber")==0) return &attmap_host_ipHostNumber; + if (strcasecmp(name,"objectClass")==0) return &attmap_host_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_host_cn; + if (strcasecmp(name,"ipHostNumber")==0) return &attmap_host_ipHostNumber; } - else if (strncasecmp(name,"netgroup.",9)==0) + else if (map==LM_NETGROUP) { - if (strcasecmp(name+9,"objectClass")==0) return &attmap_netgroup_objectClass; - if (strcasecmp(name+9,"cn")==0) return &attmap_netgroup_cn; - if (strcasecmp(name+9,"nisNetgroupTriple")==0) return &attmap_netgroup_nisNetgroupTriple; - if (strcasecmp(name+9,"memberNisNetgroup")==0) return &attmap_netgroup_memberNisNetgroup; + if (strcasecmp(name,"objectClass")==0) return &attmap_netgroup_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_netgroup_cn; + if (strcasecmp(name,"nisNetgroupTriple")==0) return &attmap_netgroup_nisNetgroupTriple; + if (strcasecmp(name,"memberNisNetgroup")==0) return &attmap_netgroup_memberNisNetgroup; } - else if (strncasecmp(name,"network.",8)==0) + else if (map==LM_NETWORKS) { - if (strcasecmp(name+8,"objectClass")==0) return &attmap_network_objectClass; - if (strcasecmp(name+8,"cn")==0) return &attmap_network_cn; - if (strcasecmp(name+8,"ipNetworkNumber")==0) return &attmap_network_ipNetworkNumber; + if (strcasecmp(name,"objectClass")==0) return &attmap_network_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_network_cn; + if (strcasecmp(name,"ipNetworkNumber")==0) return &attmap_network_ipNetworkNumber; } - else if (strncasecmp(name,"passwd.",7)==0) + else if (map==LM_PASSWD) { - if (strcasecmp(name+7,"objectClass")==0) return &attmap_passwd_objectClass; - if (strcasecmp(name+7,"uid")==0) return &attmap_passwd_uid; - if (strcasecmp(name+7,"userPassword")==0) return &attmap_passwd_userPassword; - if (strcasecmp(name+7,"uidNumber")==0) return &attmap_passwd_uidNumber; - if (strcasecmp(name+7,"gidNumber")==0) return &attmap_passwd_gidNumber; - if (strcasecmp(name+7,"gecos")==0) return &attmap_passwd_gecos; - if (strcasecmp(name+7,"cn")==0) return &attmap_passwd_cn; - if (strcasecmp(name+7,"homeDirectory")==0) return &attmap_passwd_homeDirectory; - if (strcasecmp(name+7,"loginShell")==0) return &attmap_passwd_loginShell; + if (strcasecmp(name,"objectClass")==0) return &attmap_passwd_objectClass; + if (strcasecmp(name,"uid")==0) return &attmap_passwd_uid; + if (strcasecmp(name,"userPassword")==0) return &attmap_passwd_userPassword; + if (strcasecmp(name,"uidNumber")==0) return &attmap_passwd_uidNumber; + if (strcasecmp(name,"gidNumber")==0) return &attmap_passwd_gidNumber; + if (strcasecmp(name,"gecos")==0) return &attmap_passwd_gecos; + if (strcasecmp(name,"cn")==0) return &attmap_passwd_cn; + if (strcasecmp(name,"homeDirectory")==0) return &attmap_passwd_homeDirectory; + if (strcasecmp(name,"loginShell")==0) return &attmap_passwd_loginShell; } - else if (strncasecmp(name,"protocol.",9)==0) + else if (map==LM_PROTOCOLS) { - if (strcasecmp(name+9,"objectClass")==0) return &attmap_protocol_objectClass; - if (strcasecmp(name+9,"cn")==0) return &attmap_protocol_cn; - if (strcasecmp(name+9,"ipProtocolNumber")==0) return &attmap_protocol_ipProtocolNumber; + if (strcasecmp(name,"objectClass")==0) return &attmap_protocol_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_protocol_cn; + if (strcasecmp(name,"ipProtocolNumber")==0) return &attmap_protocol_ipProtocolNumber; } - else if (strncasecmp(name,"rpc.",4)==0) + else if (map==LM_RPC) { - if (strcasecmp(name+9,"objectClass")==0) return &attmap_rpc_objectClass; - if (strcasecmp(name+9,"cn")==0) return &attmap_rpc_cn; - if (strcasecmp(name+9,"oncRpcNumber")==0) return &attmap_rpc_oncRpcNumber; + if (strcasecmp(name,"objectClass")==0) return &attmap_rpc_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_rpc_cn; + if (strcasecmp(name,"oncRpcNumber")==0) return &attmap_rpc_oncRpcNumber; } - else if (strncasecmp(name,"service.",8)==0) + else if (map==LM_SERVICES) { - if (strcasecmp(name+8,"objectClass")==0) return &attmap_service_objectClass; - if (strcasecmp(name+8,"cn")==0) return &attmap_service_cn; - if (strcasecmp(name+8,"ipServicePort")==0) return &attmap_service_ipServicePort; - if (strcasecmp(name+8,"ipServiceProtocol")==0) return &attmap_service_ipServiceProtocol; + if (strcasecmp(name,"objectClass")==0) return &attmap_service_objectClass; + if (strcasecmp(name,"cn")==0) return &attmap_service_cn; + if (strcasecmp(name,"ipServicePort")==0) return &attmap_service_ipServicePort; + if (strcasecmp(name,"ipServiceProtocol")==0) return &attmap_service_ipServiceProtocol; } - else if (strncasecmp(name,"shadow.",7)==0) + else if (map==LM_SHADOW) { - if (strcasecmp(name+7,"objectClass")==0) return &attmap_shadow_objectClass; - if (strcasecmp(name+7,"uid")==0) return &attmap_shadow_uid; - if (strcasecmp(name+7,"userPassword")==0) return &attmap_shadow_userPassword; - if (strcasecmp(name+7,"shadowLastChange")==0) return &attmap_shadow_shadowLastChange; - if (strcasecmp(name+7,"shadowMin")==0) return &attmap_shadow_shadowMin; - if (strcasecmp(name+7,"shadowMax")==0) return &attmap_shadow_shadowMax; - if (strcasecmp(name+7,"shadowWarning")==0) return &attmap_shadow_shadowWarning; - if (strcasecmp(name+7,"shadowInactive")==0) return &attmap_shadow_shadowInactive; - if (strcasecmp(name+7,"shadowExpire")==0) return &attmap_shadow_shadowExpire; - if (strcasecmp(name+7,"shadowFlag")==0) return &attmap_shadow_shadowFlag; + if (strcasecmp(name,"objectClass")==0) return &attmap_shadow_objectClass; + if (strcasecmp(name,"uid")==0) return &attmap_shadow_uid; + if (strcasecmp(name,"userPassword")==0) return &attmap_shadow_userPassword; + if (strcasecmp(name,"shadowLastChange")==0) return &attmap_shadow_shadowLastChange; + if (strcasecmp(name,"shadowMin")==0) return &attmap_shadow_shadowMin; + if (strcasecmp(name,"shadowMax")==0) return &attmap_shadow_shadowMax; + if (strcasecmp(name,"shadowWarning")==0) return &attmap_shadow_shadowWarning; + if (strcasecmp(name,"shadowInactive")==0) return &attmap_shadow_shadowInactive; + if (strcasecmp(name,"shadowExpire")==0) return &attmap_shadow_shadowExpire; + if (strcasecmp(name,"shadowFlag")==0) return &attmap_shadow_shadowFlag; } return NULL; } diff --git a/nslcd/attmap.h b/nslcd/attmap.h index acf8341..abb1287 100644 --- a/nslcd/attmap.h +++ b/nslcd/attmap.h @@ -23,6 +23,7 @@ #ifndef _ATTMAP_H #define _ATTMAP_H 1 +#include "ldap-nss.h" /* What follows is a list of attribute names per database. */ @@ -179,6 +180,6 @@ extern const char *attmap_shadow_shadowFlag; /* return a reference to the attribute mapping variable for the specified name the name is the name after the attmap_... variables above with the underscode replaced by a dot (e.g passwd.homeDirectory) */ -const char **attmap_get_var(const char *name); +const char **attmap_get_var(enum ldap_map_selector map,const char *name); #endif /* not _ATTMAP_H */ diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 8d44725..74cfa9e 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -32,6 +32,7 @@ #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> +#include <errno.h> #include "ldap-nss.h" #include "util.h" @@ -53,52 +54,11 @@ struct ldap_config *nslcd_cfg=NULL; #define LDAP_NSS_MAXSLEEPTIME 64 /* maximum seconds to sleep */ #define LDAP_NSS_MAXCONNTRIES 2 /* reconnect attempts before sleeping */ -#define NSS_LDAP_KEY_MAP "map" -#define NSS_LDAP_KEY_SCOPE "scope" -#define NSS_LDAP_KEY_BASE "base" -#define NSS_LDAP_KEY_BINDDN "binddn" -#define NSS_LDAP_KEY_BINDPW "bindpw" -#define NSS_LDAP_KEY_USESASL "use_sasl" -#define NSS_LDAP_KEY_SASLID "sasl_auth_id" -#define NSS_LDAP_KEY_DEREF "deref" -#define NSS_LDAP_KEY_ROOTBINDDN "rootbinddn" -#define NSS_LDAP_KEY_ROOTUSESASL "rootuse_sasl" -#define NSS_LDAP_KEY_ROOTSASLID "rootsasl_auth_id" -#define NSS_LDAP_KEY_LDAP_VERSION "ldap_version" -#define NSS_LDAP_KEY_TIMELIMIT "timelimit" -#define NSS_LDAP_KEY_BIND_TIMELIMIT "bind_timelimit" -#define NSS_LDAP_KEY_SSL "ssl" -#define NSS_LDAP_KEY_SSLPATH "sslpath" -#define NSS_LDAP_KEY_REFERRALS "referrals" -#define NSS_LDAP_KEY_RESTART "restart" -#define NSS_LDAP_KEY_URI "uri" -#define NSS_LDAP_KEY_IDLE_TIMELIMIT "idle_timelimit" -#define NSS_LDAP_KEY_RECONNECT_POLICY "bind_policy" -#define NSS_LDAP_KEY_SASL_SECPROPS "sasl_secprops" -#ifdef CONFIGURE_KRB5_CCNAME -#define NSS_LDAP_KEY_KRB5_CCNAME "krb5_ccname" -#endif /* CONFIGURE_KRB5_CCNAME */ -#define NSS_LDAP_KEY_DEBUG "debug" -#define NSS_LDAP_KEY_PAGESIZE "pagesize" - -/* more reconnect policy fine-tuning */ -#define NSS_LDAP_KEY_RECONNECT_TRIES "nss_reconnect_tries" -#define NSS_LDAP_KEY_RECONNECT_SLEEPTIME "nss_reconnect_sleeptime" -#define NSS_LDAP_KEY_RECONNECT_MAXSLEEPTIME "nss_reconnect_maxsleeptime" -#define NSS_LDAP_KEY_RECONNECT_MAXCONNTRIES "nss_reconnect_maxconntries" +/* the maximum line length in the configuration file */ +#define MAX_LINE_LENGTH 4096 -#define NSS_LDAP_KEY_SCHEMA "nss_schema" -#define NSS_LDAP_KEY_CONNECT_POLICY "nss_connect_policy" - -/* - * support separate naming contexts for each map - * eventually this will support the syntax defined in - * the DUAConfigProfile searchDescriptor attribute - */ -#define NSS_LDAP_KEY_NSS_BASE_PREFIX "nss_base_" -#define NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN ( sizeof(NSS_LDAP_KEY_NSS_BASE_PREFIX) - 1 ) - -#define NSS_LDAP_CONFIG_BUFSIZ 4096 +/* the maximum number of keywords/options on the line */ +#define MAX_LINE_OPTIONS 10 int _nss_ldap_test_config_flag(unsigned int flag) { @@ -106,684 +66,611 @@ int _nss_ldap_test_config_flag(unsigned int flag) (nslcd_cfg->ldc_flags&flag); } -static void _nss_ldap_init_config(struct ldap_config *result) +/* clear the configuration information back to the defaults */ +static void cfg_defaults(struct ldap_config *cfg) { - - memset (result, 0, sizeof (*result)); - - result->ldc_scope = LDAP_SCOPE_SUBTREE; - result->ldc_deref = LDAP_DEREF_NEVER; - result->ldc_base = NULL; - result->ldc_binddn = NULL; - result->ldc_bindpw = NULL; - result->ldc_saslid = NULL; - result->ldc_usesasl = 0; - result->ldc_rootbinddn = NULL; - result->ldc_rootbindpw = NULL; - result->ldc_rootsaslid = NULL; - result->ldc_rootusesasl = 0; + int i; + memset(cfg,0,sizeof(struct ldap_config)); + for (i=0;i<(NSS_LDAP_CONFIG_URI_MAX+1);i++) + cfg->ldc_uris[i]=NULL; #ifdef LDAP_VERSION3 - result->ldc_version = LDAP_VERSION3; + cfg->ldc_version=LDAP_VERSION3; #else /* LDAP_VERSION3 */ - result->ldc_version = LDAP_VERSION2; + cfg->ldc_version=LDAP_VERSION2; #endif /* not LDAP_VERSION3 */ - result->ldc_timelimit = LDAP_NO_LIMIT; - result->ldc_bind_timelimit = 30; - result->ldc_ssl_on = SSL_OFF; - result->ldc_sslpath = NULL; - result->ldc_referrals = 1; - result->ldc_restart = 1; - result->ldc_tls_checkpeer = -1; - result->ldc_tls_cacertfile = NULL; - result->ldc_tls_cacertdir = NULL; - result->ldc_tls_ciphers = NULL; - result->ldc_tls_cert = NULL; - result->ldc_tls_key = NULL; - result->ldc_tls_randfile = NULL; - result->ldc_idle_timelimit = 0; - result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN; - result->ldc_sasl_secprops = NULL; - result->ldc_debug = 0; - result->ldc_pagesize = 0; + cfg->ldc_binddn=NULL; + cfg->ldc_bindpw=NULL; + cfg->ldc_rootbinddn=NULL; + cfg->ldc_rootbindpw=NULL; + cfg->ldc_saslid=NULL; + cfg->ldc_rootsaslid=NULL; + cfg->ldc_sasl_secprops=NULL; + cfg->ldc_usesasl=0; + cfg->ldc_rootusesasl=0; #ifdef CONFIGURE_KRB5_CCNAME - result->ldc_krb5_ccname = NULL; + cfg->ldc_krb5_ccname=NULL; #endif /* CONFIGURE_KRB5_CCNAME */ - result->ldc_flags = 0; -#ifdef RFC2307BIS - result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS; -#endif /* RFC2307BIS */ - result->ldc_reconnect_tries = LDAP_NSS_TRIES; - result->ldc_reconnect_sleeptime = LDAP_NSS_SLEEPTIME; - result->ldc_reconnect_maxsleeptime = LDAP_NSS_MAXSLEEPTIME; - result->ldc_reconnect_maxconntries = LDAP_NSS_MAXCONNTRIES; + cfg->ldc_base=NULL; + cfg->ldc_scope=LDAP_SCOPE_SUBTREE; + cfg->ldc_deref=LDAP_DEREF_NEVER; + cfg->ldc_referrals=1; + for (i=0;i<LM_NONE;i++) + cfg->ldc_sds[i]=NULL; + cfg->ldc_timelimit=LDAP_NO_LIMIT; + cfg->ldc_bind_timelimit=30; + cfg->ldc_reconnect_pol=LP_RECONNECT_HARD_OPEN; + cfg->ldc_flags=0; + cfg->ldc_idle_timelimit=0; + cfg->ldc_ssl_on=SSL_OFF; + cfg->ldc_sslpath=NULL; + cfg->ldc_tls_checkpeer=-1; + cfg->ldc_tls_cacertdir=NULL; + cfg->ldc_tls_cacertfile=NULL; + cfg->ldc_tls_randfile=NULL; + cfg->ldc_tls_ciphers=NULL; + cfg->ldc_tls_cert=NULL; + cfg->ldc_tls_key=NULL; + cfg->ldc_restart=1; + cfg->ldc_pagesize=0; + cfg->ldc_reconnect_tries=LDAP_NSS_TRIES; + cfg->ldc_reconnect_sleeptime=LDAP_NSS_SLEEPTIME; + cfg->ldc_reconnect_maxsleeptime=LDAP_NSS_MAXSLEEPTIME; + cfg->ldc_reconnect_maxconntries=LDAP_NSS_MAXCONNTRIES; + cfg->ldc_debug=0; + cfg->ldc_password_type=LU_RFC2307_USERPASSWORD; + cfg->ldc_shadow_type=LS_RFC2307_SHADOW; } -static enum nss_status -_nss_ldap_add_uri (struct ldap_config *result, const char *uri, - char **buffer, size_t *buflen) +/* simple strdup wrapper */ +static char *xstrdup(const char *s) { - /* add a single URI to the list of URIs in the configuration */ - int i; - size_t uri_len; - - log_log(LOG_DEBUG,"==> _nss_ldap_add_uri"); + char *tmp; + if (s==NULL) + { + log_log(LOG_CRIT,"xstrdup() called with NULL"); + exit(EXIT_FAILURE); + } + tmp=strdup(s); + if (tmp==NULL) + { + log_log(LOG_CRIT,"strdup() failed to allocate memory"); + exit(EXIT_FAILURE); + } + return tmp; +} - for (i = 0; result->ldc_uris[i] != NULL; i++) +/* add a single URI to the list of URIs in the configuration */ +static void add_uri(const char *filename,int lnr, + struct ldap_config *cfg,const char *uri) +{ + int i; + log_log(LOG_DEBUG,"add_uri(%s)",uri); + /* find the place where to insert the URI */ + for (i=0;cfg->ldc_uris[i]!=NULL;i++) ; - - if (i == NSS_LDAP_CONFIG_URI_MAX) - { - log_log(LOG_DEBUG,"<== _nss_ldap_add_uri: maximum number of URIs exceeded"); - return NSS_STATUS_UNAVAIL; - } - - assert (i < NSS_LDAP_CONFIG_URI_MAX); - - uri_len = strlen (uri); - - if (*buflen < uri_len + 1) - return NSS_STATUS_TRYAGAIN; - - memcpy (*buffer, uri, uri_len + 1); - - result->ldc_uris[i] = *buffer; - result->ldc_uris[i + 1] = NULL; - - *buffer += uri_len + 1; - *buflen -= uri_len + 1; - - log_log(LOG_DEBUG,"<== _nss_ldap_add_uri: added URI %s", uri); - - return NSS_STATUS_SUCCESS; + /* check for room */ + if (i>=NSS_LDAP_CONFIG_URI_MAX) + { + log_log(LOG_ERR,"%s:%d: maximum number of URIs exceeded",filename,lnr); + exit(EXIT_FAILURE); + } + /* append URI to list */ + cfg->ldc_uris[i]=xstrdup(uri); + cfg->ldc_uris[i+1]=NULL; } -static enum nss_status -do_add_uris (struct ldap_config *result, char *uris, - char **buffer, size_t *buflen) +static int parse_boolean(const char *filename,int lnr,const char *value) { - /* Add a space separated list of URIs */ - char *p; - enum nss_status status = NSS_STATUS_SUCCESS; - - for (p = uris; p != NULL; ) - { - char *q = strchr (p, ' '); - if (q != NULL) - *q = '\0'; - - status = _nss_ldap_add_uri (result, p, buffer, buflen); - - p = (q != NULL) ? ++q : NULL; - - if (status != NSS_STATUS_SUCCESS) - break; - } + if ( (strcasecmp(value,"on")==0) || + (strcasecmp(value,"yes")==0) || + (strcasecmp(value,"true")==0) || + (strcasecmp(value,"1")==0) ) + return 1; + else if ( (strcasecmp(value,"off")==0) || + (strcasecmp(value,"no")==0) || + (strcasecmp(value,"false")==0) || + (strcasecmp(value,"0")==0) ) + return 0; + else + { + log_log(LOG_ERR,"%s:%d: not a boolean argument: '%s'",filename,lnr,value); + exit(EXIT_FAILURE); + } +} - return status; +static int parse_scope(const char *filename,int lnr,const char *value) +{ + if ( (strcasecmp(value,"sub")==0) || (strcasecmp(value,"subtree")==0) ) + return LDAP_SCOPE_SUBTREE; + else if ( (strcasecmp(value,"one")==0) || (strcasecmp(value,"onelevel")==0) ) + return LDAP_SCOPE_ONELEVEL; + else if (strcasecmp(value,"base")==0) + return LDAP_SCOPE_BASE; + else + { + log_log(LOG_ERR,"%s:%d: not a scope argument: '%s'",filename,lnr,value); + exit(EXIT_FAILURE); + } } -static enum ldap_map_selector _nss_ldap_str2selector(const char *key) +static enum ldap_map_selector parse_map(const char *filename,int lnr,const char *value) { - enum ldap_map_selector sel; - - if (!strcasecmp (key, MP_passwd)) - sel = LM_PASSWD; - else if (!strcasecmp (key, MP_shadow)) - sel = LM_SHADOW; - else if (!strcasecmp (key, MP_group)) - sel = LM_GROUP; - else if (!strcasecmp (key, MP_hosts)) - sel = LM_HOSTS; - else if (!strcasecmp (key, MP_services)) - sel = LM_SERVICES; - else if (!strcasecmp (key, MP_networks)) - sel = LM_NETWORKS; - else if (!strcasecmp (key, MP_protocols)) - sel = LM_PROTOCOLS; - else if (!strcasecmp (key, MP_rpc)) - sel = LM_RPC; - else if (!strcasecmp (key, MP_ethers)) - sel = LM_ETHERS; - else if (!strcasecmp (key, MP_aliases)) - sel = LM_ALIASES; - else if (!strcasecmp (key, MP_netgroup)) - sel = LM_NETGROUP; + /* TODO: merge this code with attmap_get_var() */ + if ( (strcasecmp(value,"alias")==0) || (strcasecmp(value,"aliases")==0) ) + return LM_ALIASES; + else if ( (strcasecmp(value,"ether")==0) || (strcasecmp(value,"ethers")==0) ) + return LM_ETHERS; + else if (strcasecmp(value,"group")==0) + return LM_GROUP; + else if ( (strcasecmp(value,"host")==0) || (strcasecmp(value,"hosts")==0) ) + return LM_HOSTS; + else if (strcasecmp(value,"netgroup")==0) + return LM_NETGROUP; + else if ( (strcasecmp(value,"network")==0) || (strcasecmp(value,"networks")==0) ) + return LM_NETWORKS; + else if (strcasecmp(value,"passwd")==0) + return LM_PASSWD; + else if ( (strcasecmp(value,"protocol")==0) || (strcasecmp(value,"protocols")==0) ) + return LM_PROTOCOLS; + else if (strcasecmp(value,"rpc")==0) + return LM_RPC; + else if ( (strcasecmp(value,"service")==0) || (strcasecmp(value,"services")==0) ) + return LM_SERVICES; + else if (strcasecmp(value,"shadow")==0) + return LM_SHADOW; else - sel = LM_NONE; - return sel; + { + log_log(LOG_ERR,"%s:%d: unknown mapping: '%s'",filename,lnr,value); + exit(EXIT_FAILURE); + } } /* this function modifies the statement argument passed */ -static enum nss_status do_parse_map_statement( - struct ldap_config *cfg,char *statement) +static void parse_map_statement(const char *filename,int lnr, + struct ldap_config *cfg,const char **opts) { - char *key,*val; + enum ldap_map_selector map; const char **var; - key=(char *)statement; - val=key; - /* search for the end of the key */ - while (*val!=' '&&*val!='\t') - val++; - *(val++)='\0'; - /* search for the end of the value */ - while (*val==' '||*val=='\t') - val++; + /* get the map */ + map=parse_map(filename,lnr,opts[1]); /* special handling for some attribute mappings */ - if (strcasecmp(key,"passwd.userPassword")==0) + /* TODO: move this stuff to passwd.c or shadow.c or wherever it's used */ + if ((map==LM_PASSWD)&&(strcasecmp(opts[2],"userPassword")==0)) { - if (strcasecmp(val,"userPassword")==0) + if (strcasecmp(opts[3],"userPassword")==0) cfg->ldc_password_type=LU_RFC2307_USERPASSWORD; - else if (strcasecmp (val,"authPassword")==0) + else if (strcasecmp(opts[3],"authPassword")==0) cfg->ldc_password_type=LU_RFC3112_AUTHPASSWORD; else cfg->ldc_password_type=LU_OTHER_PASSWORD; } - else if (strcasecmp(key,"shadow.shadowLastChange")==0) + else if ((map==LM_SHADOW)&&(strcasecmp(opts[2],"shadowLastChange")==0)) { - if (strcasecmp(val,"shadowLastChange")==0) + if (strcasecmp(opts[3],"shadowLastChange")==0) cfg->ldc_shadow_type=LS_RFC2307_SHADOW; - else if (strcasecmp (val,"pwdLastSet")==0) + else if (strcasecmp(opts[3],"pwdLastSet")==0) cfg->ldc_shadow_type=LS_AD_SHADOW; } - var=attmap_get_var(key); + var=attmap_get_var(map,opts[2]); if (var==NULL) - /* the used mapping key was unknown */ - return NSS_STATUS_NOTFOUND; - /* check if the value actually changed */ - if (strcmp(*var,val)!=0) + { + log_log(LOG_ERR,"%s:%d: unknown attribute to map: '%s'",filename,lnr,opts[2]); + exit(EXIT_FAILURE); + } + /* check if the value will be changed */ + if (strcmp(*var,opts[3])!=0) { /* Note: we have a memory leak here if a single mapping is changed multiple times in one config (deemed not a problem) */ - *var=strdup(val); - if (*var==NULL) - /* memory allocation failed */ - return NSS_STATUS_TRYAGAIN; + *var=xstrdup(opts[3]); } - return NSS_STATUS_SUCCESS; } -static enum nss_status -do_searchdescriptorconfig (const char *key, const char *value, size_t len, - struct ldap_service_search_descriptor ** result, - char **buffer, size_t * buflen) +static void alloc_lsd(struct ldap_service_search_descriptor **lsd) { - struct ldap_service_search_descriptor **t, *cur; - char *base; - char *filter, *s; - int scope; - enum ldap_map_selector sel; - - t = NULL; - filter = NULL; - scope = -1; - - if (strncasecmp (key, NSS_LDAP_KEY_NSS_BASE_PREFIX, - NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN) != 0) - return NSS_STATUS_SUCCESS; - - sel = _nss_ldap_str2selector (&key[NSS_LDAP_KEY_NSS_BASE_PREFIX_LEN]); - t = (sel < LM_NONE) ? &result[sel] : NULL; - - if (t == NULL) - return NSS_STATUS_SUCCESS; - - /* we have already checked for room for the value */ - /* len is set to the length of value */ - base = *buffer; - strncpy (base, value, len); - base[len] = '\0'; - - *buffer += len + 1; - *buflen -= len + 1; - - /* probably is some funky escaping needed here. later... */ - s = strchr (base, '?'); - if (s != NULL) - { - *s = '\0'; - s++; - if (!strcasecmp (s, "sub")) - scope = LDAP_SCOPE_SUBTREE; - else if (!strcasecmp (s, "one")) - scope = LDAP_SCOPE_ONELEVEL; - else if (!strcasecmp (s, "base")) - scope = LDAP_SCOPE_BASE; - filter = strchr (s, '?'); - if (filter != NULL) - { - *filter = '\0'; - filter++; - } - } - - if (bytesleft (*buffer, *buflen, struct ldap_service_search_descriptor) < - sizeof (struct ldap_service_search_descriptor)) - return NSS_STATUS_UNAVAIL; - - align (*buffer, *buflen, struct ldap_service_search_descriptor); - - for (cur = *t; cur && cur->lsd_next; cur = cur->lsd_next) - ; - if (!cur) + if (*lsd!=NULL) + return; + *lsd=(struct ldap_service_search_descriptor *)malloc(sizeof(struct ldap_service_search_descriptor)); + if (*lsd==NULL) + { + log_log(LOG_CRIT,"malloc() failed to allocate memory"); + exit(EXIT_FAILURE); + } + /* initialize fields */ + (*lsd)->lsd_base=NULL; + (*lsd)->lsd_scope=-1; + (*lsd)->lsd_filter=NULL; + (*lsd)->lsd_next=NULL; +} + +static void do_setbase(struct ldap_service_search_descriptor **lsd,const char *base) +{ + alloc_lsd(lsd); + (*lsd)->lsd_base=xstrdup(base); +} + +static void do_setscope(struct ldap_service_search_descriptor **lsd,int scope) +{ + alloc_lsd(lsd); + (*lsd)->lsd_scope=scope; +} + +static void do_setfilter(struct ldap_service_search_descriptor **lsd,const char *filter) +{ + alloc_lsd(lsd); + (*lsd)->lsd_filter=xstrdup(filter);; +} + +/* split a line from the configuration file + note that this code is not thread safe! + the line value will be rewritten! */ +static const char **tokenize(const char *filename,int lnr,char *line,int *nopt) +{ + static const char *retv[MAX_LINE_OPTIONS]; + int opt; + for (opt=0;opt<MAX_LINE_OPTIONS;opt++) + { + /* skip beginning spaces */ + while ((*line==' ')||(*line=='\t')) + line++; + /* check for end of line or comment */ + if ((*line=='\0')||(*line=='#')) + break; /* we're done */ + /* we have a new keyword */ + retv[opt]=line; + if (*line=='"') { - *t = (struct ldap_service_search_descriptor *) * buffer; - cur = *t; + line++; + /* find end quote */ + while ((*line!='"')&&(*line!='\0')) + line++; + if (*line!='"') + { + log_log(LOG_ERR,"%s:%d: quoted value not terminated",filename,lnr); + exit(EXIT_FAILURE); + } + line++; } - else + else { - cur->lsd_next = (struct ldap_service_search_descriptor *) * buffer; - cur = cur->lsd_next; + /* find the end of the token */ + while ((*line!=' ')&&(*line!='\t')&&(*line!='\0')) + line++; } + /* mark the end of the token */ + if (*line!='\0') + *line++='\0'; + } + *nopt=opt; + return retv; +} - cur->lsd_base = base; - cur->lsd_scope = scope; - cur->lsd_filter = filter; - cur->lsd_next = NULL; - - *buffer += sizeof (struct ldap_service_search_descriptor); - *buflen -= sizeof (struct ldap_service_search_descriptor); - - return NSS_STATUS_SUCCESS; +/* check that the condition is true and otherwise log an error + and bail out */ +static inline void check_argumentcount(const char *filename,int lnr, + const char *keyword,int condition) +{ + if (!condition) + { + log_log(LOG_ERR,"%s:%d: %s: wrong number of arguments",filename,lnr,keyword); + exit(EXIT_FAILURE); + } } -static enum nss_status _nss_ldap_readconfig(struct ldap_config ** presult, char **buffer, size_t *buflen) +static void cfg_read(const char *filename,struct ldap_config *cfg) { FILE *fp; - char b[NSS_LDAP_CONFIG_BUFSIZ]; - enum nss_status status = NSS_STATUS_SUCCESS; - struct ldap_config *result; + int lnr=0; + char line[MAX_LINE_LENGTH]; + int i; + const char **opts; + int nopts; - if (bytesleft (*buffer, *buflen, struct ldap_config *) < sizeof (struct ldap_config)) + /* open config file */ + if ((fp=fopen (filename, "r"))==NULL) { - return NSS_STATUS_TRYAGAIN; + log_log(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno)); + exit(EXIT_FAILURE); } - align (*buffer, *buflen, struct ldap_config *); - result = *presult = (struct ldap_config *) *buffer; - *buffer += sizeof (struct ldap_config); - *buflen -= sizeof (struct ldap_config); - - _nss_ldap_init_config(result); - - fp = fopen (NSS_LDAP_PATH_CONF, "r"); - if (fp == NULL) - { - return NSS_STATUS_UNAVAIL; - } - - while (fgets (b, sizeof (b), fp) != NULL) - { - char *k, *v; - int len; - char **t = NULL; - - if (*b == '\n' || *b == '\r' || *b == '#') - continue; - - k = b; - v = k; - - /* skip past all characters in keyword */ - while (*v != '\0' && *v != ' ' && *v != '\t') - v++; - - if (*v == '\0') - continue; - - /* terminate keyword */ - *(v++) = '\0'; - - /* skip empty lines with more than 3 spaces at the start of the line */ - /* rds.oliver@samera.com.py 01-set-2004 */ - if (*v == '\n') - continue; - - /* skip all whitespaces between keyword and value */ - /* Lars Oergel <lars.oergel@innominate.de>, 05.10.2000 */ - while (*v == ' ' || *v == '\t') - v++; - - /* kick off all whitespaces and newline at the end of value */ - /* Bob Guo <bob@mail.ied.ac.cn>, 08.10.2001 */ - - /* Also remove \r (CR) to be able to handle files in DOS format (lines - * terminated in CR LF). Alejandro Forero Cuervo - * <azul@freaks-unidos.net>, 10-may-2005 */ - - len = strlen (v) - 1; - while (v[len] == ' ' || v[len] == '\t' || v[len] == '\n' || v[len] == '\r') - --len; - v[++len] = '\0'; - - if (*buflen < (size_t) (len + 1)) - { - status = NSS_STATUS_TRYAGAIN; - break; - } - - else if (!strcasecmp (k, NSS_LDAP_KEY_URI)) - { - status = do_add_uris (result, v, buffer, buflen); - if (status != NSS_STATUS_SUCCESS) - break; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_BASE)) - { - t = &result->ldc_base; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_BINDDN)) - { - t = &result->ldc_binddn; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_BINDPW)) - { - t = &result->ldc_bindpw; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_USESASL)) - { - result->ldc_usesasl = (!strcasecmp (v, "on") - || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_SASLID)) - { - t = &result->ldc_saslid; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTBINDDN)) - { - t = &result->ldc_rootbinddn; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTUSESASL)) - { - result->ldc_rootusesasl = (!strcasecmp (v, "on") - || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_ROOTSASLID)) - { - t = &result->ldc_rootsaslid; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_SSLPATH)) - { - t = &result->ldc_sslpath; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_SCOPE)) - { - if (!strcasecmp (v, "sub")) - { - result->ldc_scope = LDAP_SCOPE_SUBTREE; - } - else if (!strcasecmp (v, "one")) - { - result->ldc_scope = LDAP_SCOPE_ONELEVEL; - } - else if (!strcasecmp (v, "base")) - { - result->ldc_scope = LDAP_SCOPE_BASE; - } - } - else if (!strcasecmp (k, NSS_LDAP_KEY_DEREF)) - { - if (!strcasecmp (v, "never")) - { - result->ldc_deref = LDAP_DEREF_NEVER; - } - else if (!strcasecmp (v, "searching")) - { - result->ldc_deref = LDAP_DEREF_SEARCHING; - } - else if (!strcasecmp (v, "finding")) - { - result->ldc_deref = LDAP_DEREF_FINDING; - } - else if (!strcasecmp (v, "always")) - { - result->ldc_deref = LDAP_DEREF_ALWAYS; - } - } - else if (!strcasecmp (k, NSS_LDAP_KEY_SSL)) - { - if (!strcasecmp (v, "on") || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")) - { - result->ldc_ssl_on = SSL_LDAPS; - } - else if (!strcasecmp (v, "start_tls")) - { - result->ldc_ssl_on = SSL_START_TLS; - } - } - else if (!strcasecmp (k, NSS_LDAP_KEY_REFERRALS)) - { - result->ldc_referrals = (!strcasecmp (v, "on") - || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_RESTART)) - { - result->ldc_restart = (!strcasecmp (v, "on") - || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_LDAP_VERSION)) - { - result->ldc_version = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_TIMELIMIT)) - { - result->ldc_timelimit = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_BIND_TIMELIMIT)) - { - result->ldc_bind_timelimit = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_IDLE_TIMELIMIT)) - { - result->ldc_idle_timelimit = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_POLICY)) - { - if (!strcasecmp (v, "hard") || - !strcasecmp (v, "hard_open")) - { - result->ldc_reconnect_pol = LP_RECONNECT_HARD_OPEN; - } - else if (!strcasecmp (v, "hard_init")) - { - result->ldc_reconnect_pol = LP_RECONNECT_HARD_INIT; - } - else if (!strcasecmp (v, "soft")) - { - result->ldc_reconnect_pol = LP_RECONNECT_SOFT; - } - } - else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_TRIES)) - { - result->ldc_reconnect_tries = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_SLEEPTIME)) - { - result->ldc_reconnect_sleeptime = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXSLEEPTIME)) - { - result->ldc_reconnect_maxsleeptime = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_RECONNECT_MAXCONNTRIES)) - { - result->ldc_reconnect_maxconntries = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_SASL_SECPROPS)) - { - t = &result->ldc_sasl_secprops; - } - else if (!strcasecmp (k, NSS_LDAP_KEY_DEBUG)) - { - result->ldc_debug = atoi (v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_PAGESIZE)) - { - result->ldc_pagesize = atoi (v); - } + + /* read file and parse lines */ + while (fgets(line,MAX_LINE_LENGTH,fp)!=NULL) + { + lnr++; + /* strip newline */ + i=(int)strlen(line); + if ((i<=0)||(line[i-1]!='\n')) + { + log_log(LOG_ERR,"%s:%d: line too long or last line missing newline",filename,lnr); + exit(EXIT_FAILURE); + } + line[i-1]='\0'; + /* split the line in tokens */ + opts=tokenize(filename,lnr,line,&nopts); + + /* ignore empty lines */ + if (nopts==0) + continue; + + /* TODO: replace atoi() calls with proper parser routine with checks */ + + /* general connection options */ + if (strcasecmp(opts[0],"uri")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts>1); + for (i=1;i<nopts;i++) + add_uri(filename,lnr,cfg,opts[i]); + } + else if (strcasecmp(opts[0],"ldap_version")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_version=atoi(opts[1]); + } + else if (strcasecmp(opts[0],"binddn")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_binddn=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"bindpw")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_bindpw=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"rootbinddn")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_rootbinddn=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"rootbindpw")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_rootbindpw=xstrdup(opts[1]); + } + /* SASL authentication options */ + else if (strcasecmp(opts[0], "sasl_authid")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_saslid=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"rootsasl_authid")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_rootsaslid=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"sasl_secprops")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_sasl_secprops=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"use_sasl")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_usesasl=parse_boolean(filename,lnr,opts[1]); + } + else if (strcasecmp(opts[0],"rootuse_sasl")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_rootusesasl=parse_boolean(filename,lnr,opts[1]); + } #ifdef CONFIGURE_KRB5_CCNAME - else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_CCNAME)) - { - t = &result->ldc_krb5_ccname; - } + /* Kerberos authentication options */ + else if (strcasecmp(opts[0],"krb5_ccname")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_krb5_ccname=xstrdup(opts[1]); + } #endif /* CONFIGURE_KRB5_CCNAME */ - else if (!strcasecmp (k, "tls_checkpeer")) - { - if (!strcasecmp (v, "on") || !strcasecmp (v, "yes") - || !strcasecmp (v, "true")) - { - result->ldc_tls_checkpeer = 1; - } - else if (!strcasecmp (v, "off") || !strcasecmp (v, "no") - || !strcasecmp (v, "false")) - { - result->ldc_tls_checkpeer = 0; - } - } - else if (!strcasecmp (k, "tls_cacertfile")) - { - t = &result->ldc_tls_cacertfile; - } - else if (!strcasecmp (k, "tls_cacertdir")) - { - t = &result->ldc_tls_cacertdir; - } - else if (!strcasecmp (k, "tls_ciphers")) - { - t = &result->ldc_tls_ciphers; - } - else if (!strcasecmp (k, "tls_cert")) - { - t = &result->ldc_tls_cert; - } - else if (!strcasecmp (k, "tls_key")) - { - t = &result->ldc_tls_key; - } - else if (!strcasecmp (k, "tls_randfile")) - { - t = &result->ldc_tls_randfile; - } - else if (!strncasecmp (k, NSS_LDAP_KEY_MAP, - strlen (NSS_LDAP_KEY_MAP))) - { - do_parse_map_statement (result, v); - } - else if (!strcasecmp (k, NSS_LDAP_KEY_SCHEMA)) - { - if (!strcasecmp (v, "rfc2307bis")) - { - result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS; - } - else if (!strcasecmp (v, "rfc2307")) - { - result->ldc_flags &= ~(NSS_LDAP_FLAGS_RFC2307BIS); - } - } - else if (!strcasecmp (k, NSS_LDAP_KEY_CONNECT_POLICY)) - { - if (!strcasecmp (v, "oneshot")) - { - result->ldc_flags |= NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT; - } - else if (!strcasecmp (v, "persist")) - { - result->ldc_flags &= ~(NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT); - } - } + /* search/mapping options */ + else if (strcasecmp(opts[0],"base")==0) + { + if (nopts==2) + cfg->ldc_base=xstrdup(opts[1]); + else if (nopts==3) + do_setbase(&(cfg->ldc_sds[parse_map(filename,lnr,opts[1])]),opts[2]); else - { - /* - * check whether the key is a naming context key - * if yes, parse; otherwise just return NSS_STATUS_SUCCESS - * so we can ignore keys we don't understand. - */ - status = - do_searchdescriptorconfig (k, v, len, result->ldc_sds, - buffer, buflen); - if (status == NSS_STATUS_UNAVAIL) - { - break; - } - } - - if (t != NULL) - { - strncpy (*buffer, v, len); - (*buffer)[len] = '\0'; - *t = *buffer; - *buffer += len + 1; - *buflen -= len + 1; - } - } - - fclose (fp); - - if (status != NSS_STATUS_SUCCESS) - { - return status; - } - - if (result->ldc_rootbinddn != NULL) - { - fp = fopen (NSS_LDAP_PATH_ROOTPASSWD, "r"); - if (fp) - { - if (fgets (b, sizeof (b), fp) != NULL) - { - int len; - - len = strlen (b); - /* BUG#138: check for newline before removing */ - if (len > 0 && b[len - 1] == '\n') - len--; - - if (*buflen < (size_t) (len + 1)) - { - return NSS_STATUS_UNAVAIL; - } - - strncpy (*buffer, b, len); - (*buffer)[len] = '\0'; - result->ldc_rootbindpw = *buffer; - *buffer += len + 1; - *buflen -= len + 1; - } - fclose (fp); - } - else if (!result->ldc_rootusesasl) - { - result->ldc_rootbinddn = NULL; - } - } - - if (result->ldc_uris[0] == NULL) - { - status = NSS_STATUS_NOTFOUND; - } - - return status; + check_argumentcount(filename,lnr,opts[0],0); + } + else if (strcasecmp(opts[0],"scope")==0) + { + if (nopts==2) + cfg->ldc_scope=parse_scope(filename,lnr,opts[1]); + else if (nopts==3) + do_setscope(&(cfg->ldc_sds[parse_map(filename,lnr,opts[1])]),parse_scope(filename,lnr,opts[2])); + else + check_argumentcount(filename,lnr,opts[0],0); + } + else if (strcasecmp(opts[0],"deref")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + if (strcasecmp(opts[1],"never")==0) + cfg->ldc_deref=LDAP_DEREF_NEVER; + else if (strcasecmp(opts[1],"searching")==0) + cfg->ldc_deref=LDAP_DEREF_SEARCHING; + else if (strcasecmp(opts[1],"finding")==0) + cfg->ldc_deref=LDAP_DEREF_FINDING; + else if (strcasecmp(opts[1],"always")==0) + cfg->ldc_deref=LDAP_DEREF_ALWAYS; + else + { + log_log(LOG_ERR,"%s:%d: wrong argument: '%s'",filename,lnr,opts[1]); + exit(EXIT_FAILURE); + } + } + else if (strcasecmp(opts[0],"referrals")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_referrals=parse_boolean(filename,lnr,opts[1]); + } + else if (strcasecmp(opts[0],"filter")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==3); + do_setfilter(&(cfg->ldc_sds[parse_map(filename,lnr,opts[1])]),opts[2]); + } + else if (strcasecmp(opts[0],"map")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==4); + parse_map_statement(filename,lnr,cfg,opts); + } + /* timing/reconnect options */ + else if (strcasecmp(opts[0],"timelimit")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_timelimit=atoi(opts[1]); + } + else if (strcasecmp(opts[0],"bind_timelimit")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_bind_timelimit=atoi(opts[1]); + } + else if (strcasecmp(opts[0],"bind_policy")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + if ( (strcasecmp(opts[1],"hard")==0) || + (strcasecmp(opts[1],"hard_open")==0) ) + cfg->ldc_reconnect_pol=LP_RECONNECT_HARD_OPEN; + else if (strcasecmp(opts[1],"hard_init")==0) + cfg->ldc_reconnect_pol=LP_RECONNECT_HARD_INIT; + else if (strcasecmp(opts[1],"soft")==0) + cfg->ldc_reconnect_pol=LP_RECONNECT_SOFT; + } + else if (strcasecmp(opts[0],"nss_connect_policy")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + if (!strcasecmp(opts[1],"oneshot")) + cfg->ldc_flags|=NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT; + else if (!strcasecmp(opts[1],"persist")) + cfg->ldc_flags&=~(NSS_LDAP_FLAGS_CONNECT_POLICY_ONESHOT); + } + else if (strcasecmp(opts[0],"idle_timelimit")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_idle_timelimit=atoi(opts[1]); + } + /* SSL/TLS options */ + else if (strcasecmp(opts[0],"ssl")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + if (strcasecmp(opts[1],"start_tls")==0) + cfg->ldc_ssl_on=SSL_START_TLS; + else if (parse_boolean(filename,lnr,opts[1])) + cfg->ldc_ssl_on=SSL_LDAPS; + } + else if (strcasecmp(opts[0],"sslpath")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_sslpath=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"tls_checkpeer")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_checkpeer=parse_boolean(filename,lnr,opts[1]); + } + else if (strcasecmp(opts[0],"tls_cacertdir")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_cacertdir=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"tls_cacertfile")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_cacertfile=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"tls_randfile")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_randfile=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"tls_ciphers")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_ciphers=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"tls_cert")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_cert=xstrdup(opts[1]); + } + else if (strcasecmp(opts[0],"tls_key")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_tls_key=xstrdup(opts[1]); + } + /* other options */ + else if (strcasecmp(opts[0],"restart")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_restart=parse_boolean(filename,lnr,opts[1]); + } + else if (strcasecmp(opts[0],"pagesize")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_pagesize=atoi(opts[1]); + } + else if (strcasecmp(opts[0],"nss_schema")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + if (strcasecmp(opts[1],"rfc2307bis")==0) + cfg->ldc_flags|=NSS_LDAP_FLAGS_RFC2307BIS; + else if (strcasecmp(opts[1],"rfc2307")==0) + cfg->ldc_flags&=~(NSS_LDAP_FLAGS_RFC2307BIS); + else + { + log_log(LOG_ERR,"%s:%d: wrong argument: '%s'",filename,lnr,opts[1]); + exit(EXIT_FAILURE); + } + } + /* undocumented options */ + else if (strcasecmp(opts[0],"nss_reconnect_tries")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_reconnect_tries=atoi(opts[1]); + } + else if (!strcasecmp(opts[0],"nss_reconnect_sleeptime")) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_reconnect_sleeptime=atoi(opts[1]); + } + else if (strcasecmp(opts[0],"nss_reconnect_maxsleeptime")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_reconnect_maxsleeptime=atoi(opts[1]); + } + else if (strcasecmp(opts[0],"nss_reconnect_maxconntries")==0) + { + check_argumentcount(filename,lnr,opts[0],nopts==2); + cfg->ldc_reconnect_maxconntries=atoi(opts[1]); + } + else + { + log_log(LOG_ERR,"%s:%d: unknown keyword: '%s'",filename,lnr,opts[0]); + exit(EXIT_FAILURE); + } + } + + /* we're done reading file, close */ + fclose(fp); } -int cfg_init(void) +void cfg_init(void) { - static char configbuf[NSS_LDAP_CONFIG_BUFSIZ]; - char *configbufp; - size_t configbuflen; - enum nss_status retv; if (nslcd_cfg==NULL) { - configbufp=configbuf; - configbuflen=sizeof(configbuf); - retv=_nss_ldap_readconfig(&nslcd_cfg,&configbufp,&configbuflen); - if (retv!=NSS_STATUS_SUCCESS) + /* allocate the memory */ + nslcd_cfg=(struct ldap_config *)malloc(sizeof(struct ldap_config)); + if (nslcd_cfg==NULL) + { + log_log(LOG_CRIT,"malloc() failed to allocate memory"); + exit(EXIT_FAILURE); + } + /* clear configuration */ + cfg_defaults(nslcd_cfg); + /* read configfile */ + cfg_read(NSS_LDAP_PATH_CONF,nslcd_cfg); + /* do some sanity checks */ + if (nslcd_cfg->ldc_uris[0] == NULL) { - log_log(LOG_DEBUG,"cfg_init() failed to read config"); - return -1; + log_log(LOG_ERR,"no URIs defined in config"); + exit(EXIT_FAILURE); } } - return 0; } diff --git a/nslcd/cfg.h b/nslcd/cfg.h index c790c57..0709ebf 100644 --- a/nslcd/cfg.h +++ b/nslcd/cfg.h @@ -63,82 +63,90 @@ enum ldap_shadow_selector struct ldap_config { /* NULL terminated list of URIs */ - char *ldc_uris[NSS_LDAP_CONFIG_URI_MAX + 1]; - /* base DN, eg. dc=gnu,dc=org */ - char *ldc_base; - /* scope for searches */ - int ldc_scope; - /* dereference aliases/links */ - int ldc_deref; + char *ldc_uris[NSS_LDAP_CONFIG_URI_MAX+1]; + /* protocol version */ + int ldc_version; /* bind DN */ char *ldc_binddn; /* bind cred */ char *ldc_bindpw; - /* do we use sasl when binding? */ - int ldc_usesasl; - /* sasl auth id */ - char *ldc_saslid; - /* shadow bind DN */ + /* bind DN for root processes */ char *ldc_rootbinddn; - /* shadow bind cred */ + /* bind cred for root processes */ char *ldc_rootbindpw; - /* do we use sasl for root? */ - int ldc_rootusesasl; + /* sasl auth id */ + char *ldc_saslid; /* shadow sasl auth id */ char *ldc_rootsaslid; - /* protocol version */ - int ldc_version; + /* sasl security */ + char *ldc_sasl_secprops; + /* do we use sasl when binding? */ + int ldc_usesasl; + /* do we use sasl for root? */ + int ldc_rootusesasl; +#ifdef CONFIGURE_KRB5_CCNAME + /* krb5 ccache name */ + char *ldc_krb5_ccname; +#endif /* CONFIGURE_KRB5_CCNAME */ + /* base DN, eg. dc=gnu,dc=org */ + char *ldc_base; + /* scope for searches */ + int ldc_scope; + /* dereference aliases/links */ + int ldc_deref; + /* Chase referrals */ + int ldc_referrals; + /* naming contexts */ + struct ldap_service_search_descriptor *ldc_sds[LM_NONE]; /* search timelimit */ int ldc_timelimit; /* bind timelimit */ int ldc_bind_timelimit; + /* reconnect policy */ + enum ldap_reconnect_policy ldc_reconnect_pol; + /* for nss_connect_policy and nss_schema */ + unsigned int ldc_flags; + /* idle timeout */ + time_t ldc_idle_timelimit; /* SSL enabled */ enum ldap_ssl_options ldc_ssl_on; /* SSL certificate path */ char *ldc_sslpath; - /* Chase referrals */ - int ldc_referrals; - int ldc_restart; - /* naming contexts */ - struct ldap_service_search_descriptor *ldc_sds[LM_NONE]; /* tls check peer */ int ldc_tls_checkpeer; - /* tls ca certificate file */ - char *ldc_tls_cacertfile; /* tls ca certificate dir */ char *ldc_tls_cacertdir; + /* tls ca certificate file */ + char *ldc_tls_cacertfile; + /* tls randfile */ + char *ldc_tls_randfile; /* tls ciphersuite */ char *ldc_tls_ciphers; /* tls certificate */ char *ldc_tls_cert; /* tls key */ char *ldc_tls_key; - /* tls randfile */ - char *ldc_tls_randfile; - /* idle timeout */ - time_t ldc_idle_timelimit; - /* reconnect policy */ - enum ldap_reconnect_policy ldc_reconnect_pol; + /* whether the LDAP library should restart the select(2) system call when interrupted */ + int ldc_restart; + /* set to a greater than 0 to enable handling of paged results with the specified size */ + int ldc_pagesize; + /* undocumented settings */ int ldc_reconnect_tries; int ldc_reconnect_sleeptime; int ldc_reconnect_maxsleeptime; int ldc_reconnect_maxconntries; - /* sasl security */ - char *ldc_sasl_secprops; /* LDAP debug level */ int ldc_debug; - int ldc_pagesize; -#ifdef CONFIGURE_KRB5_CCNAME - /* krb5 ccache name */ - char *ldc_krb5_ccname; -#endif /* CONFIGURE_KRB5_CCNAME */ - /* is userPassword "userPassword" or not? ie. do we need {crypt} to be stripped */ + /* is userPassword "userPassword" or not? ie. do we need {crypt} to be stripped + (silently set when mapping is done) TODO: replace this with some runtime detection */ enum ldap_userpassword_selector ldc_password_type; - /* Use active directory time offsets? */ + /* Use active directory time offsets? + (silently set when mapping is done) TODO: replace this with some runtime detection */ enum ldap_shadow_selector ldc_shadow_type; - unsigned int ldc_flags; }; +/* this is a pointer to the global configuration, it should be available + once cfg_init() was called */ extern struct ldap_config *nslcd_cfg; /* @@ -150,7 +158,9 @@ extern struct ldap_config *nslcd_cfg; int _nss_ldap_test_config_flag(unsigned int flag) MUST_USE; -int cfg_init(void) - MUST_USE; +/* Initialize the configuration in nslcd_cfg. This method + will read the default configuration file and call exit() + if an error occurs. */ +void cfg_init(void); #endif /* _CFG_H */ diff --git a/nslcd/ldap-nss.c b/nslcd/ldap-nss.c index a9530a8..ed68dc5 100644 --- a/nslcd/ldap-nss.c +++ b/nslcd/ldap-nss.c @@ -798,10 +798,6 @@ do_init (void) log_log(LOG_DEBUG,"==> do_init"); - /* Initialize schema and LDAP handle (but do not connect) */ - cfg_init(); - /* FIXME: if config was reloaded, do_close() and set __session.ls_current_uri=0 */ - if (__session.ls_state == LS_CONNECTED_TO_DSA) { time_t current_time; diff --git a/nslcd/ldap-schema.h b/nslcd/ldap-schema.h index aeb6c34..391c883 100644 --- a/nslcd/ldap-schema.h +++ b/nslcd/ldap-schema.h @@ -92,20 +92,4 @@ extern char _nss_ldap_filt_getspent[]; /* netgroups */ extern char _nss_ldap_filt_getnetgrent[]; -/* - * Map names - */ -#define MP_passwd "passwd" -#define MP_shadow "shadow" -#define MP_group "group" -#define MP_hosts "hosts" -#define MP_services "services" -#define MP_networks "networks" -#define MP_protocols "protocols" -#define MP_rpc "rpc" -#define MP_ethers "ethers" -#define MP_netmasks "netmasks" -#define MP_aliases "aliases" -#define MP_netgroup "netgroup" - #endif /* _LDAP_NSS_LDAP_LDAP_SCHEMA_H */ diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c index 35fe3ed..a4c5dca 100644 --- a/nslcd/nslcd.c +++ b/nslcd/nslcd.c @@ -48,6 +48,7 @@ #include "nslcd.h" #include "log.h" +#include "cfg.h" #include "common.h" #include "compat/attrs.h" @@ -540,6 +541,10 @@ int main(int argc,char *argv[]) if (__nss_configure_lookup("hosts","files dns")) log_log(LOG_ERR,"unable to override hosts lookup method: %s",strerror(errno)); + /* read configuration file */ + cfg_init(); + nslcd_cfg->ldc_debug=nslcd_debugging; + /* daemonize */ if ((!nslcd_debugging)&&(daemon(0,0)<0)) { @@ -551,7 +556,7 @@ int main(int argc,char *argv[]) (void)umask((mode_t)0022); /* intilialize logging */ - if (!nslcd_debugging) + if (!nslcd_cfg->ldc_debug) log_startlogging(); log_log(LOG_INFO,"version %s starting",VERSION); diff --git a/nss-ldapd.conf b/nss-ldapd.conf index cadcb11..0fcb3c3 100644 --- a/nss-ldapd.conf +++ b/nss-ldapd.conf @@ -1,27 +1,27 @@ # This is the configuration file for the LDAP nameservice -# switch library. +# switch library's nslcd daemon. It configures the mapping +# between NSS names (see /etc/nsswitch.conf) and LDAP +# information in the directory. +# See the manual page nss-ldapd.conf(5) for more information. # The uri pointing to the LDAP server to use for name lookups. -# Mulitple entries may be specified, each separated by a -# space. The address that is used here should be resolvable -# without using LDAP (obviously). +# Mulitple entries may be specified. The address that is used +# here should be resolvable without using LDAP (obviously). #uri ldap://127.0.0.1/ #uri ldaps://127.0.0.1/ #uri ldapi://%2fvar%2frun%2fldapi_sock/ # Note: %2f encodes the '/' used as directory separator uri ldap://127.0.0.1/ -# The distinguished name of the search base. -base dc=example,dc=net - # The LDAP version to use (defaults to 3 # if supported by client library) #ldap_version 3 +# The distinguished name of the search base. +base dc=example,dc=net + # The distinguished name to bind to the server with. # Optional: default is to bind anonymously. -# Please do not put double quotes around it as they -# would be included literally. #binddn cn=proxyuser,dc=padl,dc=com # The credentials to bind with. @@ -29,17 +29,24 @@ base dc=example,dc=net #bindpw secret # The distinguished name to bind to the server with -# if the effective user ID is root. Password is -# stored in /etc/ldap.secret (mode 600) -# Use 'echo -n "mypassword" > /etc/ldap.secret' instead -# of an editor to create the file. +# if the effective user ID is root. #rootbinddn cn=manager,dc=padl,dc=com -# The search scope. +# The root credentials to bind with. +#rootbindpw secret + +# The default search scope. #scope sub #scope one #scope base +# Customize ceirtain database lookups. +#base group ou=Groups,dc=example,dc=net +#base passwd ou=People,dc=example,dc=net +#base shadow ou=People,dc=example,dc=net +#scope group onelevel +#scope hosts sub + # Search timelimit #timelimit 30 @@ -65,98 +72,56 @@ base dc=example,dc=net # for the number of seconds specified below. #idle_timelimit 3600 -# Use paged rseults -#nss_paged_results yes - -# Pagesize: when paged results enable, used to set the -# pagesize to a custom value -#pagesize 1000 - -# Use backlinks for answering initgroups() -#nss_initgroups backlink - -# Enable support for RFC2307bis (distinguished names in group -# members) -#nss_schema rfc2307bis - -# RFC2307bis naming contexts -# Syntax: -# nss_base_XXX base?scope?filter -# where scope is {base,one,sub} -# and filter is a filter to be &'d with the -# default filter. -# You can omit the suffix eg: -# nss_base_passwd ou=People, -# to append the default base DN but this -# may incur a small performance impact. -#nss_base_passwd ou=People,dc=padl,dc=com?one -#nss_base_shadow ou=People,dc=padl,dc=com?one -#nss_base_group ou=Group,dc=padl,dc=com?one -#nss_base_hosts ou=Hosts,dc=padl,dc=com?one -#nss_base_services ou=Services,dc=padl,dc=com?one -#nss_base_networks ou=Networks,dc=padl,dc=com?one -#nss_base_protocols ou=Protocols,dc=padl,dc=com?one -#nss_base_rpc ou=Rpc,dc=padl,dc=com?one -#nss_base_ethers ou=Ethers,dc=padl,dc=com?one -#nss_base_netmasks ou=Networks,dc=padl,dc=com?ne -#nss_base_bootparams ou=Ethers,dc=padl,dc=com?one -#nss_base_aliases ou=Aliases,dc=padl,dc=com?one -#nss_base_netgroup ou=Netgroup,dc=padl,dc=com?one - -# attribute/objectclass mapping -# Syntax: -#nss_map_attribute rfc2307attribute mapped_attribute -#nss_map_objectclass rfc2307objectclass mapped_objectclass - -# configure --enable-nds is no longer supported. # NDS mappings -#nss_map_attribute uniqueMember member - -# Services for UNIX 3.5 mappings -#nss_map_objectclass posixAccount User -#nss_map_objectclass shadowAccount User -#nss_map_attribute uid msSFU30Name -#nss_map_attribute uniqueMember msSFU30PosixMember -#nss_map_attribute userPassword msSFU30Password -#nss_map_attribute homeDirectory msSFU30HomeDirectory -#nss_map_attribute homeDirectory msSFUHomeDirectory -#nss_map_objectclass posixGroup Group - -# Services for UNIX 2.0 mappings -#nss_map_objectclass posixAccount User -#nss_map_objectclass shadowAccount user -#nss_map_attribute uid msSFUName -#nss_map_attribute uniqueMember posixMember -#nss_map_attribute userPassword msSFUPassword -#nss_map_attribute homeDirectory msSFUHomeDirectory -#nss_map_attribute shadowLastChange pwdLastSet -#nss_map_objectclass posixGroup Group -#nss_map_attribute cn msSFUName - -# RFC 2307 (AD) mappings -#nss_map_objectclass posixAccount user -#nss_map_objectclass shadowAccount user -#nss_map_attribute uid sAMAccountName -#nss_map_attribute gecos name -#nss_map_attribute homeDirectory unixHomeDirectory -#nss_map_attribute shadowLastChange pwdLastSet -#nss_map_objectclass posixGroup group -#nss_map_attribute uniqueMember member - -# AuthPassword mappings -#nss_map_attribute userPassword authPassword - -# AIX SecureWay mappings -#nss_map_objectclass posixAccount aixAccount -#nss_base_passwd ou=aixaccount,?one -#nss_map_attribute uid userName -#nss_map_attribute gidNumber gid -#nss_map_attribute uidNumber uid -#nss_map_attribute userPassword passwordChar -#nss_map_objectclass posixGroup aixAccessGroup -#nss_base_group ou=aixgroup,?one -#nss_map_attribute cn groupName -#nss_map_attribute uniqueMember member +#map group uniqueMember member + +# Mappings for Services for UNIX 3.5 +#filter passwd (objectClass=User) +#map passwd uid msSFU30Name +#map passwd userPassword msSFU30Password +#map passwd homeDirectory msSFU30HomeDirectory +#map passwd homeDirectory msSFUHomeDirectory +#filter shadow (objectClass=User) +#map shadow uid msSFU30Name +#map shadow userPassword msSFU30Password +#filter group (objectClass=Group) +#map group uniqueMember msSFU30PosixMember + +# Mappings for Services for UNIX 2.0 +#filter passwd (objectClass=User) +#map passwd uid msSFUName +#map passwd userPassword msSFUPassword +#map passwd homeDirectory msSFUHomeDirectory +#map passwd cn msSFUName +#filter shadow (objectClass=User) +#map shadow uid msSFUName +#map shadow userPassword msSFUPassword +#map shadow shadowLastChange pwdLastSet +#filter group (objectClass=Group) +#map group uniqueMember posixMember + +# Mappings for RFC 2307 (AD) +#filter passwd (objectClass=user) +#map passwd uid sAMAccountName +#map passwd homeDirectory unixHomeDirectory +#map passwd gecos name +#filter shadow (objectClass=user) +#map passwd uid sAMAccountName +#map shadow shadowLastChange pwdLastSet +#filter group (objectClass=group) +#map group uniqueMember member + +# Mappings for AIX SecureWay + +#filter passwd (objectClass=aixAccount) +#map passwd uid userName +#map passwd userPassword passwordChar +#map passwd uidNumber uid +#map passwd gidNumber gid +#filter group (objectClass=aixAccessGroup) +#map group cn groupName +#map group uniqueMember member +#map group gidNumber gid # Netscape SDK LDAPS #ssl on @@ -178,8 +143,8 @@ base dc=example,dc=net # CA certificates for server certificate verification # At least one of these are required if tls_checkpeer is "yes" -#tls_cacertfile /etc/ssl/ca.cert #tls_cacertdir /etc/ssl/certs +#tls_cacertfile /etc/ssl/ca.cert # Seed the PRNG if /dev/urandom is not provided #tls_randfile /var/run/egd-pool @@ -192,9 +157,3 @@ base dc=example,dc=net # Use these, if your server requires client authentication. #tls_cert #tls_key - -# Disable SASL security layers. This is needed for AD. -#sasl_secprops maxssf=0 - -# Override the default Kerberos ticket cache location. -#krb5_ccname FILE:/etc/.ldapcache |