1 /* Copyright (C) 1997-2005 Luke Howard.
2    This file is part of the nss_ldap library.
3    Contributed by Luke Howard, <lukeh@padl.com>, 1997.
4 
5    The nss_ldap library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    The nss_ldap library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public
16    License along with the nss_ldap library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.
19 
20    $Id: ldap-nss.h,v 2.141 2009/11/06 10:15:26 lukeh Exp $
21  */
22 
23 #ifndef _LDAP_NSS_LDAP_LDAP_NSS_H
24 #define _LDAP_NSS_LDAP_LDAP_NSS_H
25 
26 #ifdef HAVE_MALLOC_H
27 #include <malloc.h>
28 #endif
29 
30 /* for glibc, use weak aliases to pthreads functions */
31 #ifdef HAVE_LIBC_LOCK_H
32 #include <libc-lock.h>
33 #elif defined(HAVE_BITS_LIBC_LOCK_H)
34 #include <bits/libc-lock.h>
35 #endif
36 
37 #include <errno.h>
38 #include <time.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #ifdef HAVE_SHADOW_H
42 #include <shadow.h>
43 #endif
44 
45 #ifndef __P
46 # if defined(__STDC__) || defined(__GNUC__)
47 #  define __P(x) x
48 # else
49 #  define __P(x) ()
50 # endif
51 #endif
52 
53 #include <netdb.h>
54 #include <netinet/in.h>
55 #include <syslog.h>
56 
57 #ifdef HAVE_NSSWITCH_H
58 #include <nss_common.h>
59 #include <nss_dbdefs.h>
60 #include <nsswitch.h>
61 #elif defined(HAVE_NSS_H)
62 #include <nss.h>
63 #elif defined(HAVE_IRS_H)
64 #include "irs-nss.h"
65 #endif
66 
67 #include "ldap-schema.h"
68 
69 #ifndef NSS_BUFSIZ
70 #define NSS_BUFSIZ	      1024
71 #endif
72 
73 #ifndef NSS_BUFLEN_GROUP
74 #define NSS_BUFLEN_GROUP	LDAP_NSS_BUFLEN_GROUP
75 #endif
76 
77 #ifndef NSS_BUFLEN_PASSWD
78 #define NSS_BUFLEN_PASSWD       NSS_BUFSIZ
79 #endif
80 
81 #ifndef HAVE_NSSWITCH_H
82 #define NSS_BUFLEN_HOSTS	(NSS_BUFSIZ + (MAXALIASES + MAXALIASES + 2) * sizeof (char *))
83 #define NSS_BUFLEN_NETGROUP     (MAXHOSTNAMELEN * 2 + LOGNAME_MAX + 3)
84 #define NSS_BUFLEN_NETWORKS     NSS_BUFSIZ
85 #define NSS_BUFLEN_PROTOCOLS    NSS_BUFSIZ
86 #define NSS_BUFLEN_RPC	  NSS_BUFSIZ
87 #define NSS_BUFLEN_SERVICES     NSS_BUFSIZ
88 #define NSS_BUFLEN_SHADOW       NSS_BUFSIZ
89 #define NSS_BUFLEN_ETHERS       NSS_BUFSIZ
90 #define NSS_BUFLEN_BOOTPARAMS   NSS_BUFSIZ
91 #endif /* HAVE_NSSWITCH_H */
92 
93 /*
94  * Timeouts for reconnecting code. Similar to rebind
95  * logic in Darwin NetInfo. Some may find sleeping
96  * unacceptable, in which case you may wish to adjust
97  * the constants below.
98  */
99 #define LDAP_NSS_TRIES	   5	/* number of sleeping reconnect attempts */
100 #define LDAP_NSS_SLEEPTIME       4	/* seconds to sleep; doubled until max */
101 #define LDAP_NSS_MAXSLEEPTIME    64	/* maximum seconds to sleep */
102 #define LDAP_NSS_MAXCONNTRIES    2	/* reconnect attempts before sleeping */
103 
104 #if defined(HAVE_NSSWITCH_H) || defined(HAVE_IRS_H)
105 #define LDAP_NSS_MAXNETGR_DEPTH  16	/* maximum depth of netgroup nesting for innetgr() */
106 #endif /* HAVE_NSSWITCH_H */
107 
108 #define LDAP_NSS_MAXGR_DEPTH     16     /* maximum depth of group nesting for getgrent()/initgroups() */
109 
110 #if LDAP_NSS_NGROUPS > 64
111 #define LDAP_NSS_BUFLEN_GROUP	(NSS_BUFSIZ + (LDAP_NSS_NGROUPS * (sizeof (char *) + LOGNAME_MAX)))
112 #else
113 #define LDAP_NSS_BUFLEN_GROUP	NSS_BUFSIZ
114 #endif /* LDAP_NSS_NGROUPS > 64 */
115 
116 #define LDAP_NSS_BUFLEN_DEFAULT	0
117 
118 #ifdef HAVE_USERSEC_H
119 #define LDAP_NSS_MAXUESS_ATTRS	8	/* maximum number of attributes in a getentry call */
120 #endif /* HAVE_USERSEC_H */
121 
122 #define LDAP_PAGESIZE 1000
123 
124 #ifndef LDAP_FILT_MAXSIZ
125 #define LDAP_FILT_MAXSIZ 1024
126 #endif /* !LDAP_FILT_MAXSIZ */
127 
128 #ifndef LDAPS_PORT
129 #define LDAPS_PORT 636
130 #endif /* !LDAPS_PORT */
131 
132 #ifndef LOGNAME_MAX
133 #define LOGNAME_MAX 8
134 #endif /* LOGNAME_MAX */
135 
136 #ifndef MAP_KEY_MAXSIZ
137 #define MAP_KEY_MAXSIZ 64
138 #endif
139 
140 #ifdef DEBUG
141 #ifdef DEBUG_SYSLOG
142 #ifdef HAVE_NSSWITCH_H
143 #define debug(fmt, args...) syslog(LOG_DEBUG, "nss_ldap: %s:%d thread %u - " fmt, __FILE__, __LINE__, thr_self() , ## args)
144 #else
145 #define debug(fmt, args...) syslog(LOG_DEBUG, "nss_ldap: %s:%d thread %u - " fmt, __FILE__, __LINE__, pthread_self() , ## args)
146 #endif /* HAVE_NSSWITCH_H */
147 #else
148 #ifndef __GNUC__
149 #include <stdarg.h>
150 #include <stdio.h>
151 static void
debug(char * fmt,...)152 debug (char *fmt, ...)
153 {
154   va_list ap;
155 
156   va_start (ap, fmt);
157   fprintf (stderr, "nss_ldap: ");
158   vfprintf (stderr, fmt, ap);
159   va_end (ap);
160   fprintf (stderr, "\n");
161 }
162 #else
163 #define debug(fmt, args...) fprintf(stderr, "nss_ldap: " fmt "\n" , ## args)
164 #endif /* __GNUC__ */
165 #endif /* DEBUG_SYSLOG */
166 #else
167 #ifndef __GNUC__
168 static void
debug(char * fmt,...)169 debug (char *fmt, ...)
170 {
171 }
172 #else
173 #define debug(fmt, args...)
174 #endif /* __GNUC__ */
175 #endif /* DEBUG */
176 
177 #ifdef __GNUC__
178 #define alignof(ptr) __alignof__(ptr)
179 #define INLINE inline
180 #elif defined(HAVE_ALIGNOF_H)
181 #include <alignof.h>
182 #define INLINE
183 #else
184 #define alignof(ptr) (sizeof(char *))
185 #define INLINE
186 #endif /* __GNUC__ */
187 
188 #define align(ptr, blen, TYPE)	      do { \
189 					char *qtr = ptr; \
190 					ptr += alignof(TYPE) - 1; \
191 					ptr -= ((ptr - (char *)NULL) % alignof(TYPE)); \
192 					blen -= (ptr - qtr); \
193 				} while (0)
194 
195 /* worst case */
196 #define bytesleft(ptr, blen, TYPE)    ( (blen < alignof(TYPE)) ? \
197 					    0 : (blen - alignof(TYPE) + 1))
198 
199 /* selectors for different maps */
200 enum ldap_map_selector
201 {
202   LM_PASSWD,
203   LM_SHADOW,
204   LM_GROUP,
205   LM_HOSTS,
206   LM_SERVICES,
207   LM_NETWORKS,
208   LM_PROTOCOLS,
209   LM_RPC,
210   LM_ETHERS,
211   LM_NETMASKS,
212   LM_BOOTPARAMS,
213   LM_ALIASES,
214   LM_NETGROUP,
215   LM_AUTOMOUNT,
216   LM_NONE
217 };
218 
219 typedef enum ldap_map_selector ldap_map_selector_t;
220 
221 enum ldap_userpassword_selector
222 {
223   LU_RFC2307_USERPASSWORD,
224   LU_RFC3112_AUTHPASSWORD,
225   LU_OTHER_PASSWORD
226 };
227 
228 typedef enum ldap_userpassword_selector ldap_userpassword_selector_t;
229 
230 enum ldap_shadow_selector
231 {
232   LS_RFC2307_SHADOW,
233   LS_AD_SHADOW,
234   LS_OTHER_SHADOW
235 };
236 
237 typedef enum ldap_shadow_selector ldap_shadow_selector_t;
238 
239 #ifndef UF_DONT_EXPIRE_PASSWD
240 #define UF_DONT_EXPIRE_PASSWD 0x10000
241 #endif
242 
243 enum ldap_ssl_options
244 {
245   SSL_OFF,
246   SSL_LDAPS,
247   SSL_START_TLS
248 };
249 
250 typedef enum ldap_ssl_options ldap_ssl_options_t;
251 
252 enum ldap_reconnect_policy
253 {
254   LP_RECONNECT_HARD_INIT,
255   LP_RECONNECT_HARD_OPEN,
256   LP_RECONNECT_SOFT
257 };
258 
259 typedef enum ldap_reconnect_policy ldap_reconnect_policy_t;
260 
261 /*
262  * POSIX profile information (not used yet)
263  * see draft-joslin-config-schema-00.txt
264  */
265 struct ldap_service_search_descriptor
266 {
267   /* search base, qualified */
268   char *lsd_base;
269   /* scope */
270   int lsd_scope;
271   /* filter */
272   char *lsd_filter;
273   /* next */
274   struct ldap_service_search_descriptor *lsd_next;
275 };
276 
277 typedef struct ldap_service_search_descriptor
278   ldap_service_search_descriptor_t;
279 
280 /* maximum number of URIs */
281 #define NSS_LDAP_CONFIG_URI_MAX		31
282 
283 /*
284  * linked list of configurations pointing to LDAP servers. The first
285  * which has a successful ldap_open() is used. Conceivably the rest
286  * could be used after a failed or exhausted search.
287  */
288 struct ldap_config
289 {
290   /* NULL terminated list of URIs */
291   char *ldc_uris[NSS_LDAP_CONFIG_URI_MAX + 1];
292   /* default port, if not specified in URI */
293   int ldc_port;
294   /* base DN, eg. dc=gnu,dc=org */
295   char *ldc_base;
296   /* scope for searches */
297   int ldc_scope;
298   /* dereference aliases/links */
299   int ldc_deref;
300   /* bind DN */
301   char *ldc_binddn;
302   /* bind cred */
303   char *ldc_bindpw;
304   /* sasl auth id */
305   char *ldc_saslid;
306   /* do we use sasl when binding? */
307   int ldc_usesasl;
308   /* shadow bind DN */
309   char *ldc_rootbinddn;
310   /* shadow bind cred */
311   char *ldc_rootbindpw;
312   /* shadow sasl auth id */
313   char *ldc_rootsaslid;
314   /* do we use sasl for root? */
315   int ldc_rootusesasl;
316   /* protocol version */
317   int ldc_version;
318   /* search timelimit */
319   int ldc_timelimit;
320   /* bind timelimit */
321   int ldc_bind_timelimit;
322   /* SSL enabled */
323   ldap_ssl_options_t ldc_ssl_on;
324   /* SSL certificate path */
325   char *ldc_sslpath;
326   /* Chase referrals */
327   int ldc_referrals;
328   int ldc_restart;
329   /* naming contexts */
330   ldap_service_search_descriptor_t *ldc_sds[LM_NONE];
331   /* tls check peer */
332   int ldc_tls_checkpeer;
333   /* tls ca certificate file */
334   char *ldc_tls_cacertfile;
335   /* tls ca certificate dir */
336   char *ldc_tls_cacertdir;
337   /* tls ciphersuite */
338   char *ldc_tls_ciphers;
339   /* tls certificate */
340   char *ldc_tls_cert;
341   /* tls key */
342   char *ldc_tls_key;
343   /* tls randfile */
344   char *ldc_tls_randfile;
345   /* idle timeout */
346   time_t ldc_idle_timelimit;
347   /* reconnect policy */
348   ldap_reconnect_policy_t ldc_reconnect_pol;
349   int ldc_reconnect_tries;
350   int ldc_reconnect_sleeptime;
351   int ldc_reconnect_maxsleeptime;
352   int ldc_reconnect_maxconntries;
353 
354   /* sasl security */
355   char *ldc_sasl_secprops;
356   /* DNS SRV RR domain */
357   char *ldc_srv_domain;
358   /* directory for debug files */
359   char *ldc_logdir;
360   /* LDAP debug level */
361   int ldc_debug;
362   int ldc_pagesize;
363 #ifdef CONFIGURE_KRB5_CCNAME
364   /* krb5 ccache name */
365   char *ldc_krb5_ccname;
366   char *ldc_krb5_rootccname;
367   int ldc_krb5_autorenew;
368   int ldc_krb5_rootautorenew;
369 #endif /* CONFIGURE_KRB5_CCNAME */
370 #ifdef CONFIGURE_KRB5_KEYTAB
371   /* krb5 keytab name */
372   char *ldc_krb5_keytabname;
373   char *ldc_krb5_rootkeytabname;
374   int ldc_krb5_usekeytab;
375   int ldc_krb5_rootusekeytab;
376 #endif /* CONFIGURE_KRB5_KEYTAB */
377   /*
378    * attribute/objectclass maps relative to this config
379    */
380   void *ldc_maps[LM_NONE + 1][6]; /* must match MAP_MAX */
381 
382   /*
383    * is userPassword "userPassword" or not?
384    * ie. do we need {crypt} to be stripped
385    */
386   ldap_userpassword_selector_t ldc_password_type;
387   /*
388    * Use active directory time offsets?
389    */
390   ldap_shadow_selector_t ldc_shadow_type;
391 
392   /*
393    * attribute table for ldap search requensts
394    */
395   const char **ldc_attrtab[LM_NONE + 1];
396 
397   unsigned int ldc_flags;
398 
399   /* last modification time */
400   time_t ldc_mtime;
401 
402   char **ldc_initgroups_ignoreusers;
403 };
404 
405 typedef struct ldap_config ldap_config_t;
406 
407 #ifdef HAVE_SOCKLEN_T
408 typedef socklen_t NSS_LDAP_SOCKLEN_T;
409 #else
410 typedef int NSS_LDAP_SOCKLEN_T;
411 #endif /* HAVE_SOCKLEN_T */
412 
413 #if defined(__GLIBC__) && __GLIBC_MINOR__ > 1
414 typedef struct sockaddr_storage NSS_LDAP_SOCKADDR_STORAGE;
415 #else
416 typedef struct sockaddr NSS_LDAP_SOCKADDR_STORAGE;
417 #define ss_family sa_family
418 #endif /* __GLIBC__ */
419 
420 enum ldap_session_state
421 {
422   LS_UNINITIALIZED = -1,
423   LS_INITIALIZED,
424   LS_CONNECTED_TO_DSA
425 };
426 
427 typedef enum ldap_session_state ldap_session_state_t;
428 
429 /*
430  * convenient wrapper around pointer into global config list, and a
431  * connection to an LDAP server.
432  */
433 struct ldap_session
434 {
435   /* the connection */
436   LDAP *ls_conn;
437   /* pointer into config table */
438   ldap_config_t *ls_config;
439   /* timestamp of last activity */
440   time_t ls_timestamp;
441   /* has session been connected? */
442   ldap_session_state_t ls_state;
443   /* keep track of the LDAP sockets */
444   NSS_LDAP_SOCKADDR_STORAGE ls_sockname;
445   NSS_LDAP_SOCKADDR_STORAGE ls_peername;
446   /* index into ldc_uris: currently connected DSA */
447   int ls_current_uri;
448 };
449 
450 typedef struct ldap_session ldap_session_t;
451 
452 #ifndef HAVE_NSSWITCH_H
453 #ifndef UID_NOBODY
454 #define UID_NOBODY      (-2)
455 #endif
456 #endif
457 
458 #ifndef GID_NOBODY
459 #define GID_NOBODY     UID_NOBODY
460 #endif
461 
462 enum ldap_args_types
463 {
464   LA_TYPE_STRING,
465   LA_TYPE_NUMBER,
466   LA_TYPE_STRING_AND_STRING,
467   LA_TYPE_NUMBER_AND_STRING,
468   LA_TYPE_TRIPLE,
469   LA_TYPE_STRING_LIST_OR,
470   LA_TYPE_STRING_LIST_AND,
471   LA_TYPE_NONE
472 };
473 
474 typedef enum ldap_args_types ldap_args_types_t;
475 
476 enum ldap_map_type
477 {
478   MAP_ATTRIBUTE = 0,
479   MAP_OBJECTCLASS,
480   MAP_OVERRIDE,
481   MAP_DEFAULT,
482   MAP_ATTRIBUTE_REVERSE,
483   MAP_OBJECTCLASS_REVERSE, /* XXX not used yet? */
484   MAP_MAX = MAP_OBJECTCLASS_REVERSE
485 };
486 
487 typedef enum ldap_map_type ldap_map_type_t;
488 
489 struct ldap_args
490 {
491   ldap_args_types_t la_type;
492   union
493   {
494     const char *la_string;
495     long la_number;
496     struct {
497       /* for Solaris netgroup support */
498       const char *host;
499       const char *user;
500       const char *domain;
501     } la_triple;
502     const char **la_string_list;
503   }
504   la_arg1;
505   union
506   {
507     const char *la_string;
508   }
509   la_arg2;
510   const char *la_base; /* override default base */
511 };
512 
513 typedef struct ldap_args ldap_args_t;
514 
515 #define LA_INIT(q)				do { \
516 						(q).la_type = LA_TYPE_STRING; \
517 						(q).la_arg1.la_string = NULL; \
518 						(q).la_arg2.la_string = NULL; \
519 						(q).la_base = NULL; \
520 						} while (0)
521 #define LA_TYPE(q)				((q).la_type)
522 #define LA_STRING(q)				((q).la_arg1.la_string)
523 #define LA_NUMBER(q)				((q).la_arg1.la_number)
524 #define LA_TRIPLE(q)				((q).la_arg1.la_triple)
525 #define LA_STRING_LIST(q)			((q).la_arg1.la_string_list)
526 #define LA_STRING2(q)				((q).la_arg2.la_string)
527 #define LA_BASE(q)				((q).la_base)
528 
529 #include "ldap-parse.h"
530 
531 /*
532  * the state consists of the desired attribute value or an offset into a list of
533  * values for the desired attribute. This is necessary to support services.
534  *
535  * Be aware of the arbitary distinction between state and context. Context is
536  * the enumeration state of a lookup subsystem (which may be per-subsystem,
537  * or per-subsystem/per-thread, depending on the OS). State is the state
538  * of a particular lookup, and is only concerned with resolving and enumerating
539  * services. State is represented as instances of ldap_state_t; context as
540  * instances of ent_context_t. The latter contains the former.
541  */
542 struct ldap_state
543 {
544   int ls_type;
545   int ls_retry;
546   int ls_eof;
547 #define LS_TYPE_KEY	(0)
548 #define LS_TYPE_INDEX	(1)
549   union
550   {
551     /* ls_key is the requested attribute value.
552        ls_index is the desired offset into the value list.
553      */
554     const char *ls_key;
555     int ls_index;
556   }
557   ls_info;
558 };
559 
560 typedef struct ldap_state ldap_state_t;
561 /*
562  * LS_INIT only used for enumeration contexts
563  */
564 #define LS_INIT(state)	do { state.ls_type = LS_TYPE_INDEX; state.ls_retry = 0; state.ls_info.ls_index = -1; } while (0)
565 
566 /*
567  * thread specific context: result chain, and state data
568  */
569 struct ent_context
570 {
571   ldap_state_t ec_state;	/* eg. for services */
572   int ec_msgid;			/* message ID */
573   LDAPMessage *ec_res;		/* result chain */
574   ldap_service_search_descriptor_t *ec_sd;	/* current sd */
575   struct berval *ec_cookie;     /* cookie for paged searches */
576   int ec_eof;			/* reached notional end of file */
577 };
578 
579 typedef struct ent_context ent_context_t;
580 
581 struct name_list
582 {
583   char *name;
584   struct name_list *next;
585 };
586 
587 #ifdef HAVE_NSSWITCH_H
588 
589 struct nss_ldap_backend
590 {
591   nss_backend_op_t *ops;
592   int n_ops;
593   ent_context_t *state;
594 };
595 
596 typedef struct nss_ldap_backend nss_ldap_backend_t;
597 
598 struct nss_ldap_netgr_backend
599 {
600   nss_backend_op_t *ops;
601   int n_ops;
602   ent_context_t *state;
603   struct name_list *known_groups; /* netgroups seen, for loop detection */
604   struct name_list *needed_groups; /* nested netgroups to chase */
605 };
606 
607 typedef struct nss_ldap_netgr_backend nss_ldap_netgr_backend_t;
608 
609 typedef nss_status_t NSS_STATUS;
610 
611 #define NSS_RETURN		NSS_UNAVAIL
612 
613 #elif defined(HAVE_IRS_H)
614 
615 typedef enum
616 {
617   NSS_TRYAGAIN = -2,
618   NSS_UNAVAIL,
619   NSS_NOTFOUND,
620   NSS_SUCCESS,
621   NSS_RETURN
622 }
623 NSS_STATUS;
624 
625 struct nss_ldap_netgr_backend
626 {
627   char buffer[NSS_BUFLEN_NETGROUP];
628   ent_context_t *state;
629   struct name_list *known_groups; /* netgroups seen, for loop detection */
630   struct name_list *needed_groups; /* nested netgroups to chase */
631 };
632 
633 typedef struct nss_ldap_netgr_backend nss_ldap_netgr_backend_t;
634 #elif defined(HAVE_NSS_H)
635 
636 typedef enum nss_status NSS_STATUS;
637 
638 #define NSS_SUCCESS		NSS_STATUS_SUCCESS
639 #define NSS_NOTFOUND	NSS_STATUS_NOTFOUND
640 #define NSS_UNAVAIL		NSS_STATUS_UNAVAIL
641 #define NSS_TRYAGAIN	NSS_STATUS_TRYAGAIN
642 #define NSS_RETURN		NSS_STATUS_RETURN
643 
644 /* to let us index a lookup table on NSS_STATUSes */
645 
646 #define _NSS_LOOKUP_OFFSET      NSS_STATUS_TRYAGAIN
647 
648 #endif /* HAVE_NSSWITCH_H */
649 
650 #ifndef _NSS_LOOKUP_OFFSET
651 #define _NSS_LOOKUP_OFFSET      (0)
652 #endif
653 
654 typedef NSS_STATUS (*parser_t) (LDAPMessage *, ldap_state_t *, void *,
655 				char *, size_t);
656 
657 #ifdef HPUX
658 extern int __thread_mutex_lock(pthread_mutex_t *);
659 extern int __thread_mutex_unlock(pthread_mutex_t *);
660 #endif /* HPUX */
661 
662 #ifdef _AIX
663 extern int __multi_threaded;
664 #endif /* _AIX */
665 
666 /*
667  * Portable locking macro.
668  */
669 #if defined(HAVE_THREAD_H) && !defined(_AIX) && !defined(__FreeBSD__)
670 #define NSS_LDAP_LOCK(m)		mutex_lock(&m)
671 #define NSS_LDAP_UNLOCK(m)		mutex_unlock(&m)
672 #define NSS_LDAP_DEFINE_LOCK(m)		static mutex_t m = DEFAULTMUTEX
673 #elif defined(HAVE_LIBC_LOCK_H) || defined(HAVE_BITS_LIBC_LOCK_H)
674 #define NSS_LDAP_LOCK(m)		__libc_lock_lock(m)
675 #define NSS_LDAP_UNLOCK(m)		__libc_lock_unlock(m)
676 #define NSS_LDAP_DEFINE_LOCK(m)		static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
677 #elif defined(HAVE_PTHREAD_H)
678 #ifdef HPUX
679 # define NSS_LDAP_LOCK(m)		__thread_mutex_lock(&m)
680 # define NSS_LDAP_UNLOCK(m)		__thread_mutex_unlock(&m)
681 # define NSS_LDAP_DEFINE_LOCK(m)		static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
682 #elif defined(_AIX)
683 # define NSS_LDAP_LOCK(m)		do { \
684 						if (__multi_threaded) \
685 							pthread_mutex_lock(&m); \
686 					} while (0)
687 # define NSS_LDAP_UNLOCK(m)		do { \
688 						if (__multi_threaded) \
689 							pthread_mutex_unlock(&m); \
690 					} while (0)
691 # define NSS_LDAP_DEFINE_LOCK(m)		static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
692 #elif defined(__FreeBSD__)
693 # define NSS_LDAP_LOCK(m)	      do { \
694 					       if (__isthreaded) \
695 						       pthread_mutex_lock(&m); \
696 				       } while (0)
697 # define NSS_LDAP_UNLOCK(m)	    do { \
698 					       if (__isthreaded) \
699 						       pthread_mutex_unlock(&m); \
700 				       } while (0)
701 # define NSS_LDAP_DEFINE_LOCK(m)	       static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
702 #else
703 # define NSS_LDAP_LOCK(m)		pthread_mutex_lock(&m)
704 # define NSS_LDAP_UNLOCK(m)		pthread_mutex_unlock(&m)
705 # define NSS_LDAP_DEFINE_LOCK(m)		static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER
706 #endif /* HPUX || _AIX */
707 #else
708 #define NSS_LDAP_LOCK(m)
709 #define NSS_LDAP_UNLOCK(m)
710 #define NSS_LDAP_DEFINE_LOCK(m)
711 #endif
712 
713 /*
714  * Acquire global nss_ldap lock and blocks SIGPIPE.
715  * Generally this should only be done within ldap-nss.c.
716  */
717 void _nss_ldap_enter (void);
718 
719 /*
720  * Release global nss_ldap lock and blocks SIGPIPE.
721  * Generally this should only be done within ldap-nss.c.
722  */
723 void _nss_ldap_leave (void);
724 
725 #ifdef LDAP_OPT_THREAD_FN_PTRS
726 /*
727  * Netscape's libldap is threadsafe, but we use a
728  * lock before it is initialized
729  */
730 
731 struct ldap_error
732 {
733   int le_errno;
734   char *le_matched;
735   char *le_errmsg;
736 };
737 
738 typedef struct ldap_error ldap_error_t;
739 
740 #endif /* LDAP_OPT_THREAD_FN_PTRS */
741 
742 #ifdef HAVE_NSSWITCH_H
743 NSS_STATUS _nss_ldap_default_destr (nss_backend_t *, void *);
744 #endif
745 
746 /*
747  * context management routines.
748  * _nss_ldap_default_constr() is called once in the constructor
749  */
750 #ifdef HAVE_NSSWITCH_H
751 NSS_STATUS _nss_ldap_default_constr (nss_ldap_backend_t * be);
752 #endif
753 
754 /*
755  * _nss_ldap_ent_context_init() is called for each getXXent() call
756  * This will acquire the global mutex.
757  */
758 ent_context_t *_nss_ldap_ent_context_init (ent_context_t **);
759 
760 /*
761  * _nss_ldap_ent_context_init_locked() has the same behaviour
762  * as above, except it assumes that the caller has acquired
763  * the lock
764  */
765 
766 ent_context_t *_nss_ldap_ent_context_init_locked (ent_context_t **);
767 
768 /*
769  * _nss_ldap_ent_context_release() is used to manually free a context
770  */
771 void _nss_ldap_ent_context_release (ent_context_t **);
772 
773 /*
774  * these are helper functions for ldap-grp.c only on Solaris
775  */
776 char **_nss_ldap_get_values (LDAPMessage * e, const char *attr);
777 char *_nss_ldap_get_dn (LDAPMessage * e);
778 LDAPMessage *_nss_ldap_first_entry (LDAPMessage * res);
779 LDAPMessage *_nss_ldap_next_entry (LDAPMessage * res);
780 char *_nss_ldap_first_attribute (LDAPMessage * entry, BerElement **berptr);
781 char *_nss_ldap_next_attribute (LDAPMessage * entry, BerElement *ber);
782 const char **_nss_ldap_get_attributes (ldap_map_selector_t sel);
783 
784 /*
785  * Synchronous search cover (caller acquires lock).
786  */
787 NSS_STATUS _nss_ldap_search_s (const ldap_args_t * args,	/* IN */
788 			       const char *filterprot,	/* IN */
789 			       ldap_map_selector_t sel,	/* IN */
790 			       const char **user_attrs, /* IN */
791 			       int sizelimit,	/* IN */
792 			       LDAPMessage ** pRes /* OUT */ );
793 
794 /*
795  * Asynchronous search cover (caller acquires lock).
796  */
797 NSS_STATUS _nss_ldap_search (const ldap_args_t * args,	/* IN */
798 			     const char *filterprot,	/* IN */
799 			     ldap_map_selector_t sel,	/* IN */
800 			     const char **user_attrs, /* IN */
801 			     int sizelimit,	/* IN */
802 			     int *pMsgid, /* OUT */
803   			     ldap_service_search_descriptor_t **s /*IN/OUT*/ );
804 
805 /*
806  * Emulate X.500 read operation.
807  */
808 NSS_STATUS _nss_ldap_read (const char *dn,	/* IN */
809 			   const char **attributes,	/* IN */
810 			   LDAPMessage ** pRes /* OUT */ );
811 
812 /*
813  * extended enumeration routine; uses asynchronous API.
814  * Caller must have acquired the global mutex
815  */
816 NSS_STATUS _nss_ldap_getent_ex (ldap_args_t * args, /* IN */
817 				ent_context_t ** key,	/* IN/OUT */
818 				void *result,	/* IN/OUT */
819 				char *buffer,	/* IN */
820 				size_t buflen,	/* IN */
821 				int *errnop,	/* OUT */
822 				const char *filterprot,	/* IN */
823 				ldap_map_selector_t sel,	/* IN */
824 				const char **user_attrs, /* IN */
825 				parser_t parser /* IN */ );
826 
827 /*
828  * common enumeration routine; uses asynchronous API.
829  * Acquires the global mutex
830  */
831 NSS_STATUS _nss_ldap_getent (ent_context_t ** key,	/* IN/OUT */
832 			     void *result,	/* IN/OUT */
833 			     char *buffer,	/* IN */
834 			     size_t buflen,	/* IN */
835 			     int *errnop,	/* OUT */
836 			     const char *filterprot,	/* IN */
837 			     ldap_map_selector_t sel,	/* IN */
838 			     parser_t parser /* IN */ );
839 
840 /*
841  * common lookup routine; uses synchronous API.
842  */
843 NSS_STATUS _nss_ldap_getbyname (ldap_args_t * args,	/* IN/OUT */
844 				void *result,	/* IN/OUT */
845 				char *buffer,	/* IN */
846 				size_t buflen,	/* IN */
847 				int *errnop,	/* OUT */
848 				const char *filterprot,	/* IN */
849 				ldap_map_selector_t sel,	/* IN */
850 				parser_t parser /* IN */ );
851 
852 /* parsing utility functions */
853 NSS_STATUS _nss_ldap_assign_attrvals (LDAPMessage * e,	/* IN */
854 				      const char *attr,	/* IN */
855 				      const char *omitvalue,	/* IN */
856 				      char ***valptr,	/* OUT */
857 				      char **buffer,	/* IN/OUT */
858 				      size_t * buflen,	/* IN/OUT */
859 				      size_t * pvalcount /* OUT */ );
860 
861 NSS_STATUS _nss_ldap_assign_attrval (LDAPMessage * e,	/* IN */
862 				     const char *attr,	/* IN */
863 				     char **valptr,	/* OUT */
864 				     char **buffer,	/* IN/OUT */
865 				     size_t * buflen /* IN/OUT */ );
866 
867 
868 const char *_nss_ldap_locate_userpassword (char **vals);
869 
870 NSS_STATUS _nss_ldap_assign_userpassword (LDAPMessage * e,	/* IN */
871 					  const char *attr,	/* IN */
872 					  char **valptr,	/* OUT */
873 					  char **buffer,	/* IN/OUT */
874 					  size_t * buflen);	/* IN/OUT */
875 
876 NSS_STATUS _nss_ldap_oc_check (LDAPMessage * e, const char *oc);
877 
878 NSS_STATUS _nss_ldap_shadow_date(const char *val, long default_date,
879 				 long *value);
880 #if defined(HAVE_SHADOW_H)
881 void _nss_ldap_shadow_handle_flag(struct spwd *sp);
882 #else
883 #define _nss_ldap_shadow_handle_flag(_sp)	do { /* nothing */ } while (0)
884 #endif /* HAVE_SHADOW_H */
885 
886 NSS_STATUS _nss_ldap_map_put (ldap_config_t * config,
887 			      ldap_map_selector_t sel,
888 			      ldap_map_type_t map,
889 			      const char *key, const char *value);
890 
891 NSS_STATUS _nss_ldap_map_get (ldap_config_t * config,
892 			      ldap_map_selector_t sel,
893 			      ldap_map_type_t map,
894 			      const char *key, const char **value);
895 
896 const char *_nss_ldap_map_at (ldap_map_selector_t sel, const char *pChar2);
897 const char *_nss_ldap_unmap_at (ldap_map_selector_t sel, const char *attribute);
898 
899 const char *_nss_ldap_map_oc (ldap_map_selector_t sel, const char *pChar);
900 const char *_nss_ldap_unmap_oc (ldap_map_selector_t sel, const char *pChar);
901 
902 const char *_nss_ldap_map_ov (const char *pChar);
903 const char *_nss_ldap_map_df (const char *pChar);
904 
905 /*
906  * Proxy bind support for AIX.
907  */
908 struct ldap_proxy_bind_args
909 {
910   char *binddn;
911   const char *bindpw;
912 };
913 
914 typedef struct ldap_proxy_bind_args ldap_proxy_bind_args_t;
915 
916 NSS_STATUS _nss_ldap_proxy_bind (const char *user, const char *password);
917 
918 NSS_STATUS _nss_ldap_init (void);
919 void _nss_ldap_close (void);
920 
921 int _nss_ldap_test_config_flag (unsigned int flag);
922 int _nss_ldap_test_initgroups_ignoreuser (const char *user);
923 int _nss_ldap_get_ld_errno (char **m, char **s);
924 
925 #ifdef CONFIGURE_KRB5_KEYTAB
926 int do_init_krb5_cache (ldap_config_t *config);
927 int do_select_krb5_cache (ldap_config_t * config);
928 int do_restore_krb5_cache (ldap_config_t * config);
929 #endif /* CONFIGURE_KRB5_KEYTAB */
930 #endif /* _LDAP_NSS_LDAP_LDAP_NSS_H */
931