#include <sys/param.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinfo/ni.h>
#include <NetInfo/config.h>
#ifdef _UNIX_BSD_43_
extern char *strdup(char *);
#endif
#include "lber.h"
#include "ldap_ldap-int.h"
#include "ldap.h"
#define GETCONF_SUCCESS 0
#define GETCONF_FAILED (-1)
static int env_getconf(char **ldaphost, char **basedn, int *port);
static int ni_getconf(char **ldaphost, char **basedn, int *port);
static ni_status ni_getConfiguration(void *ni, char **ldaphost, char **basedn, int *port);
#define NI_GETNAME_FIRST_VALUE 0
#define NI_GETNAME_ALL_VALUES 1
static int ni_getName(ni_namelist *nl, char **val, int getall);
#define MAX_NI_LEVELS 256
#define NAME_NI_LDAP_DIRECTORY "/locations/lookupd/agents/LDAPAgent"
#define NAME_HOST "host"
#define NAME_SUFFIX "suffix"
#define NAME_PORT "port"
static char *ff_getLineFromFile(FILE *fp);
static void ff_truncateString(char *string);
static int ff_parseLine(const char *data, char **key, char **val);
static int ff_getconf(char **ldaphost, char **basedn, int *port);
#define NAME_FF_LDAP_DIRECTORY "/etc/lookupd/agents/LDAPAgent/global"
typedef int (*locator_t)(char **, char **, int *);
static locator_t locators[] = { env_getconf, ni_getconf, ff_getconf, NULL };
#ifdef notdef
static locator_t locators[] = { ff_getconf, ni_getconf, NULL };
#endif
LDAP *ldap_new( void )
{
char *host = NULL;
char *base = NULL;
int port = LDAP_PORT;
LDAP *res;
locator_t *plocator;
for (plocator = locators; *plocator != NULL; plocator++)
{
if (((*plocator)(&host, &base, &port)) == GETCONF_SUCCESS)
{
#ifdef notdef
printf("ldap_new(): host %s, base %s, port %d\n",
host == NULL ? "(null)" : host,
base == NULL ? "(null)" : base,
port );
#endif
res = ldap_open(host, port);
if (res != NULL)
res->ld_defbase = base;
else
free(base);
free(host);
return res;
}
}
return NULL;
}
static int env_getconf(char **ldaphost, char **basedn, int *port)
{
char *sport;
char *host, *base;
host = getenv("LDAPHOST");
if (host == NULL)
return GETCONF_FAILED;
*ldaphost = strdup(host);
base = getenv("LDAP_BINDDN");
*basedn = (base == NULL) ? NULL : strdup(base);
sport = getenv("LDAPPORT");
*port = (sport == NULL) ? LDAP_PORT : atoi(sport);
return GETCONF_SUCCESS;
}
static int ni_getconf(char **ldaphost, char **basedn, int *port)
{
void *ni = NULL;
void *lastni = NULL;
int i;
ni_status nis;
*ldaphost = NULL;
*basedn = NULL;
*port = LDAP_PORT;
nis = ni_open(NULL, ".", &ni);
if (nis != NI_OK)
return GETCONF_FAILED;
for (i = 0; i < MAX_NI_LEVELS - 1; ++i)
{
if (nis != NI_OK || ni_getConfiguration(ni, ldaphost, basedn, port) == NI_OK)
{
break;
}
if (lastni != NULL)
{
ni_free(lastni);
}
lastni = ni;
nis = ni_open(lastni, "..", &ni);
}
if (lastni != NULL && ni != lastni)
{
ni_free(lastni);
}
if (ni != NULL)
{
ni_free(ni);
}
if (*ldaphost == NULL)
{
ldap_memfree(*basedn);
return GETCONF_FAILED;
}
return GETCONF_SUCCESS;
}
static int ni_getName(ni_namelist *nl, char **val, int get_all)
{
if (nl->ninl_len > 0)
{
if (get_all == NI_GETNAME_FIRST_VALUE)
{
*val = ni_name_dup(nl->ninl_val[0]);
}
else
{
int i;
int len = 0;
for (i = 0; i < nl->ninl_len; i++)
{
len += strlen(nl->ninl_val[i]) + 1;
}
*val = (char *)malloc(len);
if (*val == NULL) return GETCONF_FAILED;
strcpy(*val, "");
for (i = 0; i < nl->ninl_len; i++)
{
if (i > 0)
strcat(*val, " ");
strcat(*val, nl->ninl_val[i]);
}
}
return GETCONF_SUCCESS;
}
return GETCONF_FAILED;
}
static ni_status ni_getConfiguration(void *ni, char **ldaphost, char **basedn, int *port)
{
ni_id nid;
ni_proplist pl;
ni_status nis;
int i;
char *sPort = NULL;
NI_INIT(&pl);
if ((nis = ni_pathsearch(ni, &nid, NAME_NI_LDAP_DIRECTORY)) != NI_OK)
{
return nis;
}
if ((nis = ni_read(ni, &nid, &pl)) != NI_OK)
{
return nis;
}
for (i = 0; i < pl.ni_proplist_len; i++)
{
if (ni_name_match(pl.nipl_val[i].nip_name, NAME_HOST))
{
if (ni_getName(&pl.nipl_val[i].nip_val, ldaphost, NI_GETNAME_ALL_VALUES) == GETCONF_FAILED)
{
return NI_FAILED;
}
}
else if (ni_name_match(pl.nipl_val[i].nip_name, NAME_SUFFIX))
{
(void)ni_getName(&pl.nipl_val[i].nip_val, basedn, NI_GETNAME_FIRST_VALUE);
}
else if (ni_name_match(pl.nipl_val[i].nip_name, NAME_PORT))
{
if (ni_getName(&pl.nipl_val[i].nip_val, &sPort, NI_GETNAME_FIRST_VALUE) == GETCONF_SUCCESS)
{
*port = atoi(sPort);
}
}
}
ni_proplist_free(&pl);
if (sPort != NULL)
free(sPort);
return NI_OK;
}
static char *ff_getLineFromFile(FILE *fp)
{
char s[1024];
char *out;
int len;
s[0] = '\0';
fgets(s, sizeof(s), fp);
if (s == NULL || s[0] == '\0')
return NULL;
if (s[0] == '#')
return strdup("#");
len = strlen(s) - 1;
s[len] = '\0';
out = strdup(s);
return out;
}
static void ff_truncateString(char *string)
{
char *sepLoc;
sepLoc = strchr(string, ' ');
if (sepLoc != NULL)
*sepLoc = '\0';
return;
}
static int ff_parseLine(const char *data, char **key, char **val)
{
int i, j, len;
char buf[4096];
int scanning;
char sep[] = " \t";
const char *p;
len = strlen(sep);
p = data;
*key = NULL;
*val = NULL;
while (p[0] != '\0')
{
while ((p[0] == ' ') || (p[0] == '\t') || (p[0] == '\n')) p++;
if (p[0] == '\0') break;
i = 0;
scanning = 1;
for (j = 0; (j < len) && scanning; j++)
{
if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0;
}
while (scanning)
{
buf[i++] = p[0];
p++;
for (j = 0; (j < len) && scanning; j++)
{
if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0;
}
}
i--;
while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--;
buf[++i] = '\0';
if (*key == NULL)
{
*key = strdup(buf);
if (*key == NULL) return GETCONF_FAILED;
}
else
{
if (*val == NULL)
{
*val = (char *)malloc(strlen(data) - strlen(*key));
if (*val == NULL) return GETCONF_FAILED;
strcpy(*val, "");
}
else
{
strcat(*val, " ");
}
strcat(*val, buf);
}
if (p[0] == '\0') break;
scanning = 1;
for (j = 0; (j < len) && scanning; j++)
{
if (p[0] == sep[j])
{
p++;
scanning = 0;
}
}
}
return GETCONF_SUCCESS;
}
static int ff_getconf(char **ldaphost, char **basedn, int *port)
{
FILE *fp;
char *line;
fp = fopen(NAME_FF_LDAP_DIRECTORY, "r");
if (fp == NULL)
return GETCONF_FAILED;
while (NULL != (line = ff_getLineFromFile(fp)))
{
char *key, *val;
if (line[0] == '#')
{
ldap_memfree(line);
line = NULL;
continue;
}
if (ff_parseLine(line, &key, &val) == GETCONF_FAILED)
return GETCONF_FAILED;
if (key == NULL)
continue;
if (!strcmp(key, NAME_HOST))
{
if (val != NULL)
{
if (*ldaphost != NULL)
free(*ldaphost);
*ldaphost = val;
}
}
else if (!strcmp(key, NAME_SUFFIX))
{
if (val != NULL)
{
ff_truncateString(val);
if (*basedn != NULL)
free(*basedn);
*basedn = val;
}
}
else if (!strcmp(key, NAME_PORT))
{
if (val != NULL)
{
ff_truncateString(val);
*port = atoi(val);
free(val);
}
}
}
if (*ldaphost == NULL)
{
free(*basedn);
*basedn = NULL;
return GETCONF_FAILED;
}
return GETCONF_SUCCESS;
}