summaryrefslogtreecommitdiffstats
path: root/contrib/amd/amd/info_ldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/amd/amd/info_ldap.c')
-rw-r--r--contrib/amd/amd/info_ldap.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/contrib/amd/amd/info_ldap.c b/contrib/amd/amd/info_ldap.c
new file mode 100644
index 0000000..e2f0367
--- /dev/null
+++ b/contrib/amd/amd/info_ldap.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1989 Jan-Simon Pendry
+ * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: info_ldap.c,v 5.2.2.1 1992/02/09 15:08:29 jsp beta $
+ *
+ */
+
+
+/*
+ * Get info from LDAP (Lightweight Directory Access Protocol)
+ * LDAP Home Page: http://www.umich.edu/~rsug/ldap/
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amd.h>
+
+
+/*
+ * MACROS:
+ */
+#define AMD_LDAP_TYPE "ldap"
+/* Time to live for an LDAP cached in an mnt_map */
+#define AMD_LDAP_TTL 3600
+#define AMD_LDAP_RETRIES 5
+#define AMD_LDAP_HOST "ldap"
+#ifndef LDAP_PORT
+# define LDAP_PORT 389
+#endif /* LDAP_PORT */
+
+/* How timestamps are searched */
+#define AMD_LDAP_TSFILTER "(&(objectClass=amdmapTimestamp)(amdmapName=%s))"
+/* How maps are searched */
+#define AMD_LDAP_FILTER "(&(objectClass=amdmap)(amdmapName=%s)(amdmapKey=%s))"
+/* How timestamps are stored */
+#define AMD_LDAP_TSATTR "amdmaptimestamp"
+/* How maps are stored */
+#define AMD_LDAP_ATTR "amdmapvalue"
+
+/*
+ * TYPEDEFS:
+ */
+typedef struct ald_ent ALD;
+typedef struct cr_ent CR;
+typedef struct he_ent HE;
+
+/*
+ * STRUCTURES:
+ */
+struct ald_ent {
+ LDAP *ldap;
+ HE *hostent;
+ CR *credentials;
+ time_t timestamp;
+};
+
+struct cr_ent {
+ char *who;
+ char *pw;
+ int method;
+};
+
+struct he_ent {
+ char *host;
+ int port;
+ struct he_ent *next;
+};
+
+/*
+ * FORWARD DECLARATIONS:
+ */
+static int amu_ldap_rebind(ALD *a);
+static int get_ldap_timestamp(LDAP *ld, char *map, time_t *ts);
+
+
+/*
+ * FUNCTIONS:
+ */
+
+static void
+he_free(HE *h)
+{
+ XFREE(h->host);
+ if (h->next != NULL)
+ he_free(h->next);
+ XFREE(h);
+}
+
+
+static HE *
+string2he(char *s)
+{
+ char *c, *p;
+ HE *new, *old = NULL;
+
+ if (s == NULL)
+ return (NULL);
+ for (p = s; p; p = strchr(p, ',')) {
+ if (old != NULL) {
+ new = (HE *) xmalloc(sizeof(HE));
+ old->next = new;
+ old = new;
+ } else {
+ old = (HE *) xmalloc(sizeof(HE));
+ old->next = NULL;
+ }
+ c = strchr(p, ':');
+ if (c) { /* Host and port */
+ *c++ = '\0';
+ old->host = strdup(p);
+ old->port = atoi(c);
+ } else
+ old->host = strdup(p);
+
+ }
+ return (old);
+}
+
+
+static void
+cr_free(CR *c)
+{
+ XFREE(c->who);
+ XFREE(c->pw);
+ XFREE(c);
+}
+
+
+static void
+ald_free(ALD *a)
+{
+ he_free(a->hostent);
+ cr_free(a->credentials);
+ if (a->ldap != NULL)
+ ldap_unbind(a->ldap);
+ XFREE(a);
+}
+
+
+int
+amu_ldap_init(mnt_map *m, char *map, time_t *ts)
+{
+ ALD *aldh;
+ CR *creds;
+
+ if (!STREQ(gopt.map_type, AMD_LDAP_TYPE)) {
+ return (ENOENT);
+ }
+#ifdef DEBUG
+ else {
+ dlog("Map %s is ldap\n", map);
+ }
+#endif /* DEBUG */
+
+ aldh = (ALD *) xmalloc(sizeof(ALD));
+ creds = (CR *) xmalloc(sizeof(CR));
+
+ aldh->hostent = string2he(gopt.ldap_hostports);
+ if (aldh->hostent == NULL) {
+ plog(XLOG_USER, "Unable to parse hostport %s for ldap map %s",
+ gopt.ldap_hostports, map);
+ return (ENOENT);
+ }
+ creds->who = "";
+ creds->pw = "";
+ creds->method = LDAP_AUTH_SIMPLE;
+ aldh->credentials = creds;
+ aldh->timestamp = 0;
+#ifdef DEBUG
+ dlog("Trying for %s:%d\n", aldh->hostent->host, aldh->hostent->port);
+#endif /* DEBUG */
+ if (amu_ldap_rebind(aldh)) {
+ ald_free(aldh);
+ return (ENOENT);
+ }
+ m->map_data = (void *) aldh;
+#ifdef DEBUG
+ dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port);
+#endif /* DEBUG */
+ if (get_ldap_timestamp(aldh->ldap, map, ts))
+ return (ENOENT);
+#ifdef DEBUG
+ dlog("Got timestamp for map %s: %d\n", map, *ts);
+#endif /* DEBUG */
+
+ return (0);
+}
+
+
+static int
+amu_ldap_rebind(ALD *a)
+{
+ LDAP *ld;
+ HE *h;
+ CR *c = a->credentials;
+ time_t now = clocktime();
+
+ if (a->ldap != NULL) {
+ if ((a->timestamp - now) > AMD_LDAP_TTL) {
+#ifdef DEBUG
+ dlog("Reestablishing ldap connection\n");
+#endif /* DEBUG */
+ ldap_unbind(a->ldap);
+ a->timestamp = now;
+ } else
+ return (0);
+ }
+
+ while (TRUE) {
+ for (h = a->hostent; h != NULL; h = h->next) {
+ if ((ld = ldap_open(h->host, h->port)) == NULL) {
+ plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port);
+ break;
+ }
+ if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) {
+ plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n",
+ h->host, h->port, c->who);
+ break;
+ }
+ if (gopt.ldap_cache_seconds > 0) {
+ ldap_enable_cache(ld, gopt.ldap_cache_seconds, gopt.ldap_cache_maxmem);
+ a->ldap = ld;
+ a->timestamp = now;
+ return (0);
+ }
+ }
+ plog(XLOG_WARNING, "Exausted list of ldap servers, looping.\n");
+ }
+
+ plog(XLOG_USER, "Unable to (re)bind to any ldap hosts\n");
+ return (ENOENT);
+}
+
+
+static int
+get_ldap_timestamp(LDAP * ld, char *map, time_t *ts)
+{
+ struct timeval tv;
+ char **vals, *end;
+ char filter[MAXPATHLEN];
+ int i, err, nentries = 0;
+ LDAPMessage *res, *entry;
+
+ tv.tv_sec = 3;
+ tv.tv_usec = 0;
+ sprintf(filter, AMD_LDAP_TSFILTER, map);
+#ifdef DEBUG
+ dlog("Getting timestamp for map %s\n", map);
+ dlog("Filter is: %s\n", filter);
+ dlog("Base is: %s\n", gopt.ldap_base);
+#endif /* DEBUG */
+ for (i = 0; i < AMD_LDAP_RETRIES; i++) {
+ err = ldap_search_st(ld,
+ gopt.ldap_base,
+ LDAP_SCOPE_SUBTREE,
+ filter,
+ 0,
+ 0,
+ &tv,
+ &res);
+ if (err == LDAP_SUCCESS)
+ break;
+ dlog("Timestamp search timed out, trying again...\n");
+ }
+
+ if (err != LDAP_SUCCESS) {
+ *ts = 0;
+ plog(XLOG_USER, "LDAP timestamp search failed: %s\n",
+ ldap_err2string(ld->ld_errno));
+ return (ENOENT);
+ }
+
+ nentries = ldap_count_entries(ld, res);
+ if (nentries == 0) {
+ plog(XLOG_USER, "No timestamp entry for map %s\n", map);
+ *ts = 0;
+ ldap_msgfree(res);
+ return (ENOENT);
+ }
+
+ entry = ldap_first_entry(ld, res);
+ vals = ldap_get_values(ld, entry, AMD_LDAP_TSATTR);
+ if (ldap_count_values(vals) == 0) {
+ plog(XLOG_USER, "Missing timestamp value for map %s\n", map);
+ *ts = 0;
+ ldap_value_free(vals);
+ ldap_msgfree(res);
+ ldap_msgfree(entry);
+ return (ENOENT);
+ }
+#ifdef DEBUG
+ dlog("TS value is:%s:\n", vals[0]);
+#endif /* DEBUG */
+
+ if (vals[0]) {
+ *ts = (time_t) strtol(vals[0], &end, 10);
+ if (end == vals[0]) {
+ plog(XLOG_USER, "Unable to decode ldap timestamp %s for map %s\n",
+ vals[0], map);
+ err = ENOENT;
+ }
+ if (!*ts > 0) {
+ plog(XLOG_USER, "Nonpositive timestamp %d for map %s\n",
+ *ts, map);
+ err = ENOENT;
+ }
+ } else {
+ plog(XLOG_USER, "Empty timestamp value for map %s\n", map);
+ *ts = 0;
+ err = ENOENT;
+ }
+
+ ldap_value_free(vals);
+ ldap_msgfree(res);
+ ldap_msgfree(entry);
+#ifdef DEBUG
+ dlog("The timestamp for %s is %d (err=%d)\n", map, *ts, err);
+#endif /* DEBUG */
+ return (err);
+}
+
+
+int
+amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts)
+{
+ char **vals, filter[MAXPATHLEN];
+ struct timeval tv;
+ int i, err, nvals = 0, nentries = 0;
+ LDAPMessage *entry, *res;
+ ALD *a = (ALD *) (m->map_data);
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+ if (a == NULL) {
+ plog(XLOG_USER, "LDAP panic: no map data\n");
+ return (EIO);
+ }
+ if (amu_ldap_rebind(a)) /* Check that's the handle is still valid */
+ return (ENOENT);
+
+ sprintf(filter, AMD_LDAP_FILTER, map, key);
+#ifdef DEBUG
+ dlog("Search with filter: %s\n", filter);
+#endif /* DEBUG */
+ for (i = 0; i < AMD_LDAP_RETRIES; i++) {
+ err = ldap_search_st(a->ldap,
+ gopt.ldap_base,
+ LDAP_SCOPE_SUBTREE,
+ filter,
+ 0,
+ 0,
+ &tv,
+ &res);
+ if (err == LDAP_SUCCESS)
+ break;
+ }
+
+ switch (err) {
+ case LDAP_SUCCESS:
+ break;
+ case LDAP_NO_SUCH_OBJECT:
+#ifdef DEBUG
+ dlog("No object\n");
+#endif /* DEBUG */
+ ldap_msgfree(res);
+ return (ENOENT);
+ default:
+ plog(XLOG_USER, "LDAP search failed: %s\n",
+ ldap_err2string(a->ldap->ld_errno));
+ ldap_msgfree(res);
+ return (EIO);
+ }
+
+ nentries = ldap_count_entries(a->ldap, res);
+#ifdef DEBUG
+ dlog("Search found %d entries\n", nentries);
+#endif /* DEBUG */
+ if (nentries == 0) {
+ ldap_msgfree(res);
+ return (ENOENT);
+ }
+ entry = ldap_first_entry(a->ldap, res);
+ vals = ldap_get_values(a->ldap, entry, AMD_LDAP_ATTR);
+ nvals = ldap_count_values(vals);
+ if (nvals == 0) {
+ plog(XLOG_USER, "Missing value for %s in map %s\n", key, map);
+ ldap_value_free(vals);
+ ldap_msgfree(res);
+ ldap_msgfree(entry);
+ return (EIO);
+ }
+#ifdef DEBUG
+ dlog("Map %s, %s => %s\n", map, key, vals[0]);
+#endif /* DEBUG */
+ if (vals[0]) {
+ *pval = strdup(vals[0]);
+ err = 0;
+ } else {
+ plog(XLOG_USER, "Empty value for %s in map %s\n", key, map);
+ err = ENOENT;
+ }
+ ldap_msgfree(res);
+ ldap_msgfree(entry);
+ ldap_value_free(vals);
+
+ return (err);
+}
+
+
+int
+amu_ldap_mtime(mnt_map *m, char *map, time_t *ts)
+{
+ ALD *aldh = (ALD *) (m->map_data);
+
+ if (aldh == NULL) {
+ dlog("LDAP panic: unable to find map data\n");
+ return (ENOENT);
+ }
+ if (amu_ldap_rebind(aldh)) {
+ return (ENOENT);
+ }
+ if (get_ldap_timestamp(aldh->ldap, map, ts)) {
+ return (ENOENT);
+ }
+ return (0);
+}
OpenPOWER on IntegriCloud