/* Copyright (C) 2005 Luke Howard. This file is part of the nss_ldap library. Contributed by Luke Howard, , 2005. The nss_ldap library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The nss_ldap library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the nss_ldap library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id: ldap-automount.c,v 2.10 2009/11/06 10:15:26 lukeh Exp $ */ static char rcsId[] = "$Id: ldap-automount.c,v 2.10 2009/11/06 10:15:26 lukeh Exp $"; #include "config.h" #ifdef HAVE_PORT_BEFORE_H #include #endif #if defined(HAVE_THREAD_H) && !defined(_AIX) #include #elif defined(HAVE_PTHREAD_H) #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_LBER_H #include #endif #ifdef HAVE_LDAP_H #include #endif #include "ldap-nss.h" #include "ldap-automount.h" #include "util.h" #ifdef HAVE_PORT_AFTER_H #include #endif static NSS_STATUS _nss_ldap_parse_automount (LDAPMessage * e, ldap_state_t * pvt, void *result, char *buffer, size_t buflen) { NSS_STATUS stat; char ***keyval = result; stat = _nss_ldap_assign_attrval (e, AT (automountKey), keyval[0], &buffer, &buflen); if (stat != NSS_SUCCESS) return stat; stat = _nss_ldap_assign_attrval (e, AT (automountInformation), keyval[1], &buffer, &buflen); if (stat != NSS_SUCCESS) return stat; return NSS_SUCCESS; } NSS_STATUS _nss_ldap_am_context_alloc(ldap_automount_context_t **pContext) { ldap_automount_context_t *context; context = (ldap_automount_context_t *)malloc (sizeof(*context)); if (context == NULL) { return NSS_TRYAGAIN; } context->lac_state = NULL; context->lac_dn_size = 1; /* number of slots allocated */ context->lac_dn_count = 0; /* number of slots used */ context->lac_dn_index = 0; /* enumeration index */ /* List of DNs, grown on demand */ context->lac_dn_list = (char **)malloc (context->lac_dn_size * sizeof(char *)); if (context->lac_dn_list == NULL) { free (context); return NSS_TRYAGAIN; } if (_nss_ldap_ent_context_init_locked (&context->lac_state) == NULL) { free (context->lac_dn_list); free (context); return NSS_UNAVAIL; } *pContext = context; return NSS_SUCCESS; } void _nss_ldap_am_context_free(ldap_automount_context_t **pContext) { ldap_automount_context_t *context; size_t i; context = *pContext; if (context == NULL) return; if (context->lac_dn_list != NULL) { for (i = 0; i < context->lac_dn_count; i++) { #ifdef HAVE_LDAP_MEMFREE ldap_memfree (context->lac_dn_list[i]); #else free (context->lac_dn_list[i]); #endif /* HAVE_LDAP_MEMFREE */ } free (context->lac_dn_list); } if (context->lac_state != NULL) { _nss_ldap_ent_context_release (&(context->lac_state)); } memset (context, 0, sizeof (*context)); free (context); *pContext = NULL; return; } static NSS_STATUS am_context_add_dn (LDAPMessage * e, ldap_state_t * pvt, void *result, char *buffer, size_t buflen) { ldap_automount_context_t *context = (ldap_automount_context_t *) result; char *dn; dn = _nss_ldap_get_dn (e); if (dn == NULL) { return NSS_NOTFOUND; } if (context->lac_dn_count >= context->lac_dn_size) { char **new_dns; new_dns = (char **)realloc(context->lac_dn_list, 2 * context->lac_dn_size * sizeof(char *)); if (new_dns == NULL) { #ifdef HAVE_LDAP_MEMFREE ldap_memfree (dn); #else free (dn); #endif /* HAVE_LDAP_MEMFREE */ return NSS_TRYAGAIN; } context->lac_dn_list = new_dns; context->lac_dn_size *= 2; } context->lac_dn_list[context->lac_dn_count++] = dn; return NSS_SUCCESS; } NSS_STATUS _nss_ldap_am_context_init(const char *mapname, ldap_automount_context_t **pContext) { NSS_STATUS stat; ldap_automount_context_t *context = NULL; const char *no_attrs[] = { NULL }; ldap_args_t a; ent_context_t *key = NULL; int errnop; *pContext = NULL; stat = _nss_ldap_am_context_alloc (&context); if (stat != NSS_SUCCESS) return stat; LA_INIT (a); LA_TYPE (a) = LA_TYPE_STRING; LA_STRING (a) = mapname; do { stat = _nss_ldap_getent_ex (&a, &key, (void *)context, NULL, 0, &errnop, _nss_ldap_filt_setautomntent, LM_AUTOMOUNT, no_attrs, am_context_add_dn); } while (stat == NSS_SUCCESS); if (key != NULL) { _nss_ldap_ent_context_release (&key); } if (context->lac_dn_count == 0) { _nss_ldap_am_context_free (&context); return NSS_NOTFOUND; } else if (stat == NSS_NOTFOUND) { stat = NSS_SUCCESS; } context->lac_dn_index = 0; *pContext = context; return NSS_SUCCESS; } #ifdef HAVE_NSS_H NSS_STATUS _nss_ldap_setautomntent(const char *mapname, void **private) { ldap_automount_context_t *context = NULL; NSS_STATUS stat; debug ("==> _nss_ldap_setautomntent"); _nss_ldap_enter (); stat = _nss_ldap_init (); if (stat != NSS_SUCCESS) { _nss_ldap_leave (); debug ("<== _nss_ldap_setautomntent"); return stat; } stat = _nss_ldap_am_context_init (mapname, &context); if (stat != NSS_SUCCESS) { _nss_ldap_leave (); debug ("<== _nss_ldap_setautomntent"); return stat; } *private = (void *)context; _nss_ldap_leave (); debug ("<== _nss_ldap_setautomntent"); return stat; } NSS_STATUS _nss_ldap_getautomntent_r(void *private, const char **key, const char **value, char *buffer, size_t buflen, int *errnop) { NSS_STATUS stat; ldap_automount_context_t *context = (ldap_automount_context_t *)private; ldap_args_t a; char **keyval[2]; if (context == NULL) return NSS_NOTFOUND; debug ("==> _nss_ldap_getautomntent_r"); keyval[0] = (char **)key; keyval[1] = (char **)value; _nss_ldap_enter (); do { assert (context->lac_dn_index < context->lac_dn_count); LA_INIT (a); LA_TYPE (a) = LA_TYPE_NONE; LA_BASE (a) = context->lac_dn_list[context->lac_dn_index]; stat = _nss_ldap_getent_ex (&a, &context->lac_state, (void *)keyval, buffer, buflen, errnop, _nss_ldap_filt_getautomntent, LM_AUTOMOUNT, NULL, _nss_ldap_parse_automount); if (stat == NSS_NOTFOUND) { if (context->lac_dn_index < context->lac_dn_count - 1) context->lac_dn_index++; else break; /* move along, nothing more to see here */ } } while (stat == NSS_NOTFOUND); _nss_ldap_leave (); debug ("<== _nss_ldap_getautomntent_r"); return stat; } NSS_STATUS _nss_ldap_endautomntent(void **private) { ldap_automount_context_t **pContext = (ldap_automount_context_t **)private; debug ("==> _nss_ldap_endautomntent"); _nss_ldap_enter (); _nss_ldap_am_context_free (pContext); /* workaround because Linux automounter spawns a lot of processes */ _nss_ldap_close (); _nss_ldap_leave (); debug ("<== _nss_ldap_endautomntent"); return NSS_SUCCESS; } NSS_STATUS _nss_ldap_getautomntbyname_r(void *private, const char *key, const char **canon_key, const char **value, char *buffer, size_t buflen, int *errnop) { NSS_STATUS stat = NSS_NOTFOUND; ldap_automount_context_t *context = (ldap_automount_context_t *)private; ldap_args_t a; char **keyval[2]; size_t i; if (context == NULL) return NSS_NOTFOUND; debug ("==> _nss_ldap_getautomntbyname_r"); keyval[0] = (char **)canon_key; keyval[1] = (char **)value; for (i = 0; i < context->lac_dn_count; i++) { LA_INIT (a); LA_TYPE (a) = LA_TYPE_STRING; LA_STRING (a) = key; LA_BASE (a) = context->lac_dn_list[i]; /* we do not acquire lock in this case */ stat = _nss_ldap_getbyname (&a, (void *)keyval, buffer, buflen, errnop, _nss_ldap_filt_getautomntbyname, LM_AUTOMOUNT, _nss_ldap_parse_automount); if (stat != NSS_NOTFOUND) { break; /* on success or error other than not found */ } } debug ("<== _nss_ldap_getautomntbyname_r"); return stat; } #endif /* HAVE_NSS_H */