diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /ldapaddressbook | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'ldapaddressbook')
| -rw-r--r-- | ldapaddressbook/.gitignore | 1 | ||||
| -rw-r--r-- | ldapaddressbook/Makefile.am | 25 | ||||
| -rw-r--r-- | ldapaddressbook/abookadd.c | 28 | ||||
| -rw-r--r-- | ldapaddressbook/abookdel.c | 53 | ||||
| -rw-r--r-- | ldapaddressbook/abookfind.c | 24 | ||||
| -rw-r--r-- | ldapaddressbook/abookread.c | 244 | ||||
| -rw-r--r-- | ldapaddressbook/abooksearch.c | 142 | ||||
| -rw-r--r-- | ldapaddressbook/configure.in | 87 | ||||
| -rw-r--r-- | ldapaddressbook/ldapaddressbook.dist | 16 | ||||
| -rw-r--r-- | ldapaddressbook/ldapaddressbook.h | 108 | ||||
| -rw-r--r-- | ldapaddressbook/ldapsearch.c | 62 | ||||
| -rw-r--r-- | ldapaddressbook/libldapsearch.c | 449 | ||||
| -rw-r--r-- | ldapaddressbook/libldapsearch.h | 73 | ||||
| -rw-r--r-- | ldapaddressbook/noldapsearch.c | 16 | 
14 files changed, 1328 insertions, 0 deletions
| diff --git a/ldapaddressbook/.gitignore b/ldapaddressbook/.gitignore new file mode 100644 index 0000000..66ba562 --- /dev/null +++ b/ldapaddressbook/.gitignore @@ -0,0 +1 @@ +/ldapsearch diff --git a/ldapaddressbook/Makefile.am b/ldapaddressbook/Makefile.am new file mode 100644 index 0000000..450375a --- /dev/null +++ b/ldapaddressbook/Makefile.am @@ -0,0 +1,25 @@ +# +# Copyright 2000-2005 Double Precision, Inc.  See COPYING for +# distribution information. + + +EXTRA_DIST=ldapaddressbook.dist +noinst_LTLIBRARIES=libaddressbook.la +noinst_PROGRAMS=ldapsearch + +libaddressbook_la_SOURCES=abookadd.c abookdel.c abookfind.c abookread.c \ +	abooksearch.c ldapaddressbook.h + +if HAVE_OPENLDAP +ldapsearch_SOURCES=ldapsearch.c +ldapsearch_LDADD=libldapsearch.la +noinst_LTLIBRARIES += libldapsearch.la + +libldapsearch_la_SOURCES=libldapsearch.h libldapsearch.c +libldapsearch_la_LIBADD=@OPENLDAP_LIBS@ + +else + +ldapsearch_SOURCES=noldapsearch.c + +endif diff --git a/ldapaddressbook/abookadd.c b/ldapaddressbook/abookadd.c new file mode 100644 index 0000000..11c6136 --- /dev/null +++ b/ldapaddressbook/abookadd.c @@ -0,0 +1,28 @@ +/* +** Copyright 2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include	"config.h" +#include	"ldapaddressbook.h" + +#include	<stdio.h> +#include	<string.h> +#include	<stdlib.h> + +int ldapabook_add(const char *f, const struct ldapabook *a) +{ +FILE	*fp=fopen(f, "a"); + +	if (!fp)	return (-1); + +	ldapabook_writerec(a, fp); + +	if (fflush(fp) || fclose(fp)) +	{ +		fclose(fp); +		return (-1); +	} +	return (0); +} diff --git a/ldapaddressbook/abookdel.c b/ldapaddressbook/abookdel.c new file mode 100644 index 0000000..a5da9d0 --- /dev/null +++ b/ldapaddressbook/abookdel.c @@ -0,0 +1,53 @@ +/* +** Copyright 2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include	"config.h" +#include	"ldapaddressbook.h" + +#include	<stdio.h> +#include	<string.h> +#include	<stdlib.h> +#include	<unistd.h> + +int ldapabook_del(const char *filename, const char *tempname, +		const char *delname) +{ +/* This is cheating, but we won't really have many abooks, come on... */ +struct ldapabook *a=ldapabook_read(filename), *b; + +FILE	*fp; + +	if (!a)	return (0); + +	if ((fp=fopen(tempname, "w")) == 0) +	{ +		ldapabook_free(a); +		return (-1); +	} + +	for (b=a; b; b=b->next) +	{ +		if (strcmp(b->name, delname) == 0)	continue; + +		ldapabook_writerec(b, fp); +	} +	ldapabook_free(a); + +	if (fflush(fp) || fclose(fp)) +	{ +		fclose(fp); +		unlink(tempname); +		return (-1); +	} + +	if (rename(tempname, filename)) +	{ +		unlink(tempname); +		return (-1); +	} + +	return (0); +} diff --git a/ldapaddressbook/abookfind.c b/ldapaddressbook/abookfind.c new file mode 100644 index 0000000..48c1007 --- /dev/null +++ b/ldapaddressbook/abookfind.c @@ -0,0 +1,24 @@ +/* +** Copyright 2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include	"config.h" +#include	"ldapaddressbook.h" + +#include	<stdio.h> +#include	<string.h> +#include	<stdlib.h> + +const struct ldapabook *ldapabook_find(const struct ldapabook *l, +					const char *n) +{ +	while (l) +	{ +		if (strcmp(l->name, n) == 0)	return (l); + +		l=l->next; +	} +	return (0); +} diff --git a/ldapaddressbook/abookread.c b/ldapaddressbook/abookread.c new file mode 100644 index 0000000..63e75e9 --- /dev/null +++ b/ldapaddressbook/abookread.c @@ -0,0 +1,244 @@ +/* +** +** Copyright 2003-2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include	"config.h" +#include	"ldapaddressbook.h" + +#include	<stdio.h> +#include	<string.h> +#include	<stdlib.h> + +static void dequote(char *); + +struct ldapabook *ldapabook_read(const char *filename) +{ +char	buf[BUFSIZ]; +FILE	*fp; +struct	ldapabook *list, *last; +char	*s; +char	*name; +char	*host; +char	*port; +char	*suffix; +char	*binddn; +char	*bindpw; + +	if ((fp=fopen(filename, "r")) == 0)	return (0); + +	list=last=0; +	while (fgets(buf, sizeof(buf), fp)) +	{ +	struct	ldapabook *p; + +	struct	ldapabook_opts *opts=NULL, *lastopt=NULL; +	struct ldapabook_opts *nextopt; + +		s=strchr(buf, '\n'); +		if (s)	*s=0; +		if ((s=strchr(buf, '#')) != 0)	*s=0; +		name=buf; +		s=strchr(buf, '\t'); +		if (!s)	continue; +		*s++=0; +		host=s; +		s=strchr(s, '\t'); +		if (s) *s++=0; +		port=s; +		if (s)	s=strchr(s, '\t'); +		if (s)	*s++=0; +		suffix=s; +		if (s)	s=strchr(s, '\t'); +		if (s)	*s++=0; +		binddn=s; +		if (s)	s=strchr(s, '\t'); +		if (s)	*s++=0; +		bindpw=s; +		if (!port || !*port)	port="389"; +		if (!suffix)	suffix=""; +		if (!binddn)	binddn=""; +		if (!bindpw)	bindpw=""; + +		if (s)	s=strchr(s, '\t'); +		if (s)	*s++=0; + +		while (s && *s) +		{ +			char *t; + +			t=strchr(s, ','); +			if (t) +				*t++=0; + +			if ((nextopt=(struct ldapabook_opts *) +			     malloc(sizeof(struct ldapabook_opts))) == NULL +			    || (nextopt->options=strdup(s)) == NULL) +			{ +				if (nextopt) +					free(nextopt); +				ldapabook_free(list); +				fclose(fp); +				return (NULL); +			} + +			dequote(nextopt->options); +			if (!lastopt) +				opts=nextopt; +			else +				lastopt->next=nextopt; +			nextopt->next=NULL; +			lastopt=nextopt; +			s=t; +		} + +		if ((p=malloc(sizeof(struct ldapabook))) == 0) +		{ +			struct ldapabook_opts *nextopt; + +			while ((nextopt=opts) != NULL) +			{ +				opts=nextopt->next; +				free(nextopt->options); +				free(nextopt); +			} + +			ldapabook_free(list); +			fclose(fp); +			return (0); +		} + +		memset(p, 0, sizeof(*p)); +		p->opts=opts; + +		if ( (p->name=strdup(name)) != 0) +		{ +			if ((p->host=strdup(host)) != 0) +			{ +				if ((p->port=strdup(port)) != 0) +				{ +					if ((p->suffix=strdup(suffix)) != 0) +					{ +						if ((p->binddn=strdup(binddn)) +							!= 0) +						{ +							if ((p->bindpw=strdup +								(bindpw)) != 0) +							{ +								if (!list) +								   list=last=p; +								else +								   last->next=p; +								last=p; +								p->next=0; +								continue; +							} +							free(p->binddn); +						} +						free(p->suffix); +					} +					free(p->port); +				} +				free(p->host); +			} +			free(p->name); +		} +		free(p); +		while ((nextopt=opts) != NULL) +		{ +			opts=nextopt->next; +			free(nextopt->options); +			free(nextopt); +		} +		ldapabook_free(list); +		fclose(fp); +		return (0); +	} +	fclose(fp); +	return (list); +} + +void ldapabook_free(struct ldapabook *p) +{ +	while (p) +	{ +		struct ldapabook *n=p->next; +		struct ldapabook_opts *opts; + +		while ((opts=p->opts) != NULL) +		{ +			p->opts=opts->next; +			free(opts->options); +			free(opts); +		} + +		free(p->bindpw); +		free(p->binddn); +		free(p->suffix); +		free(p->port); +		free(p->host); +		free(p->name); +		free(p); +		p=n; +	} +} + +static const char hex[]="0123456789ABCDEF"; + +static int nybble(char c) +{ +	char	*p=strchr(hex, c); + +	if (p)	return (p-hex); +	return (0); +} + +static void dequote(char *p) +{ +	char *q; + +	for (q=p; *q; q++) +	{ +		if (*q == '+' && q[1] && q[2]) +		{ +			*p++=nybble(q[1])*16 + nybble(q[2]); +			q += 2; +			continue; +		} +		*p++=*q; +	} +	*p=0; +} + +void ldapabook_writerec(const struct ldapabook *b, FILE *fp) +{ +	struct	ldapabook_opts *opts; +	char	*sep="\t"; + +	fprintf(fp, "%s\t%s\t%s\t%s\t%s\t%s", b->name, b->host, +		b->port ? b->port:"", b->suffix, +		b->binddn ? b->binddn:"", +		b->bindpw ? b->bindpw:""); + +	for (opts=b->opts; opts; opts=opts->next) +	{ +		char *p; + +		fprintf(fp, "%s", sep); +		sep=","; + +		for (p=opts->options; *p; p++) +		{ +			if (*p <= ' ' || *p >= 127 || +			    *p == ',' || *p == '+') +			{ +				fprintf(fp, "+%02X", (int)(unsigned char)*p); +				continue; +			} +			putc(*p, fp); +		} +	} +	fprintf(fp, "\n"); +} diff --git a/ldapaddressbook/abooksearch.c b/ldapaddressbook/abooksearch.c new file mode 100644 index 0000000..7751445 --- /dev/null +++ b/ldapaddressbook/abooksearch.c @@ -0,0 +1,142 @@ +/* +** +** Copyright 2003-2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include	"config.h" +#include	"ldapaddressbook.h" + +#include	<stdio.h> +#include	<string.h> +#include	<signal.h> +#include	<stdlib.h> +#include	<unistd.h> +#include	<errno.h> +#include	<sys/types.h> +#if HAVE_SYS_WAIT_H +#include	<sys/wait.h> +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +#define exit(_a_) _exit(_a_) + +int ldapabook_search(const struct ldapabook *b,	/* Search this address book */ +		     const char *script, +		     const char *search, +		     int (*callback_func)(const char *utf8_name, +					  const char *address, +					  void *callback_arg), +		     void (*callback_err)(const char *errmsg, +					  void *callback_arg), +		     void *callback_arg) +{ +	int	pipefd[2]; +	pid_t	p; +	const char *argv[40]; +	char	buf1[BUFSIZ]; +	char	buf2[BUFSIZ]; +	FILE	*t, *fp; +	int	rc_code=0; +	pid_t p2; +	int waitstat; + +	signal(SIGCHLD, SIG_DFL); + +	if (pipe(pipefd) < 0)	return (-1); + +	if ((t=tmpfile()) == NULL) +	{ +		close(pipefd[0]); +		close(pipefd[1]); +		return (-1); +	} + +	if ((p=fork()) == -1) +	{ +		fclose(t); +		close(pipefd[0]); +		close(pipefd[1]); +		return (-1); +	} + +	if (p == 0) +	{ +		dup2(pipefd[1], 1); +		close(pipefd[0]); +		close(pipefd[1]); + +		dup2(fileno(t), 2); +		fclose(t); + +		argv[0]=script; +		argv[1]=b->host; +		argv[2]=b->port; +		argv[3]=b->suffix; +		argv[4]=search; +		argv[5]=NULL; + +		execvp(script, (char **)argv); +		perror(script); +		exit(1); +	} + +	fp=fdopen(pipefd[0], "r"); +	close(pipefd[1]); + +	if (!fp) +	{ +		sprintf(buf1, "%1.256s", strerror(errno)); + +		close(pipefd[0]); + +		while ((p2=wait(NULL)) != p) +			; +		fclose(t); + +		(*callback_err)(buf1, callback_arg); +		return -1; +	} + +	while (fgets(buf1, sizeof(buf1), fp) != NULL && +	       fgets(buf2, sizeof(buf2), fp) != NULL) +	{ +		char *p=strchr(buf1, '\n'); + +		if (p) *p=0; + +		p=strchr(buf2, '\n'); +		if (p) *p=0; + +		if (rc_code == 0) +			rc_code=(*callback_func)(buf1, buf2, callback_arg); +	} + +	fclose(fp); +	close(pipefd[0]); + +	while ((p2=wait(&waitstat)) != p) +		; + +	if (waitstat && rc_code == 0) +	{ +		rc_code= -1; +		fseek(t, 0L, SEEK_SET); + +		if (fgets(buf1, sizeof(buf1), t)) +		{ +			char *p=strchr(buf1, '\n'); +			if (p) *p=0; + +			(*callback_err)(buf1, callback_arg); +		} +	} +	fclose(t); +	return rc_code; +} diff --git a/ldapaddressbook/configure.in b/ldapaddressbook/configure.in new file mode 100644 index 0000000..f5cb1b1 --- /dev/null +++ b/ldapaddressbook/configure.in @@ -0,0 +1,87 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +dnl Copyright 2000 - 2006 Double Precision, Inc.  See COPYING for +dnl distribution information. + +AC_INIT(ldapaddressbook, 0.10, [courier-users@lists.sourceforge.net]) + +>confdefs.h  # Kill PACKAGE_ macros + +AC_CONFIG_SRCDIR(Makefile.am) +AC_CONFIG_AUX_DIR(../..) +AM_INIT_AUTOMAKE([foreign no-define]) +LPATH="$PATH:/usr/local/bin" +AM_CONFIG_HEADER(config.h) + +dnl Checks for programs. +AC_USE_SYSTEM_EXTENSIONS +AC_PROG_CC +AC_PROG_LIBTOOL + +dnl Checks for libraries. + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(stdio.h sys/wait.h sys/time.h) +AC_HEADER_TIME + +AC_ARG_WITH(ldapaddressbook, +[  --without-ldapaddressbook   Disable LDAP address book code ], +   HAVE_OPENLDAP="$withval", +   HAVE_OPENLDAP=1) + +OPENLDAP_LIBS="" + +if test "$HAVE_OPENLDAP" = 1 +then +	HAVE_OPENLDAP=0 + +AC_CHECK_HEADERS([lber.h]) +AC_CHECK_HEADERS([ldap.h], +	[ HAVE_OPENLDAP=1 ],,[ +#if HAVE_LBER_H +#include <lber.h> +#endif +]) + +if test "$HAVE_OPENLDAP" = 1 +then +	save_LIBS="$LIBS" +	LIBS="$LIBS -lldap" +	AC_TRY_LINK([ +#include <stdio.h> +#if HAVE_LBER_H +#include <lber.h> +#endif +#include <ldap.h> +], +[ +	LDAP *p=NULL; + +	ldap_search(p, "", 0, NULL, NULL, 0); +], +[ +	: +], +[ +	AC_MSG_ERROR([ldap.h header found, but a test compile failed -- check ldapaddressbook/config.log for more details]) +]) +	LIBS="$save_LIBS" +	OPENLDAP_LIBS="-lldap" +fi +fi + +AC_DEFINE_UNQUOTED(HAVE_OPENLDAP, $HAVE_OPENLDAP, +		[ Whether openldap support has been detected ]) + +AM_CONDITIONAL(HAVE_OPENLDAP, [test $HAVE_OPENLDAP = 1]) +AC_SUBST(OPENLDAP_LIBS) + +AC_HEADER_SYS_WAIT +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_SYS_LARGEFILE + +dnl Checks for library functions. + +AC_OUTPUT(Makefile) diff --git a/ldapaddressbook/ldapaddressbook.dist b/ldapaddressbook/ldapaddressbook.dist new file mode 100644 index 0000000..7d176a0 --- /dev/null +++ b/ldapaddressbook/ldapaddressbook.dist @@ -0,0 +1,16 @@ +##VERSION: $Id:$ +# +# ldapaddressbook created from ldapaddressbook.dist by sysconftool +# +# Do not alter lines that begin with ##, they are used when upgrading +# this configuration. +# +#  This is a list of some public LDAP address books.  This is a global +#  list -- all clients will have this list by default. +# +##NAME: ldapaddressbook:0 + +Bigfoot	ldap.bigfoot.com	389	c=US		 +Infospace	ldap.infospace.com	389	c=US		 +Netscape Netcenter	memberdir.netscape.com	389	ou=member_directory,o=netcenter.com	ou=people,o=netcenter.com	 +WhoWhere	ldap.whowhere.com	389	c=US		 diff --git a/ldapaddressbook/ldapaddressbook.h b/ldapaddressbook/ldapaddressbook.h new file mode 100644 index 0000000..bbef9c0 --- /dev/null +++ b/ldapaddressbook/ldapaddressbook.h @@ -0,0 +1,108 @@ +#ifndef	ldapaddressbook_h +#define	ldapaddressbook_h + + +#include <stdio.h> + +/* +** Copyright 2000-2002 Double Precision, Inc.  See COPYING for +** distribution information. +*/ + +#ifdef  __cplusplus +extern "C" { +#endif + +/* +** This module implements an abstraction of an interface to an LDAP address +** book.  There's no reason to reinvent the wheel, so we simply run ldapsearch +** as a child process, and read its output.  ldapsearch is run indirectly, via +** a stub shell script that can be customized on a given system.  The template +** for the stub shell script is provided. +** +** There's a small library here that can be used to maintain a configuration +** file listing available address books that can be contacted.  The format +** of each line in this library is simply: +** +** name<tab>host<tab>port<tab>suffix<tab>binddn<tab>bindpw +** +** Functions are provided to add and remove names from this configuration +** file easily.  The above is parsed into the following structure: +*/ + +struct ldapabook { +	struct ldapabook *next; + +	char	*name; +	char	*host; +	char	*port; +	char	*suffix; +	char	*binddn; +	char	*bindpw; + +	struct	ldapabook_opts *opts; + +	} ; + +struct ldapabook_opts { +	struct ldapabook_opts *next; +	char	*options;	/* First char - name, rest - value */ +} ; + +	/* Potential first chars: */ + +#define SASL_SECURITY_PROPERTIES	'O' +#define SASL_AUTHENTICATION_ID		'U' +#define	SASL_AUTHENTICATION_RID		'X'  /* u:username, or dn:dn */ +#define	SASL_AUTHENTICATION_MECHANISM	'Y' +#define SASL_STARTTLS			'Z' + +/* Read a configuration file, and create a link list of ldapabook structs */ + +struct ldapabook *ldapabook_read(const char *);		/* filename */ + +/* Free memory allocated by ldapabook_init */ + +void ldapabook_free(struct ldapabook *); + +/* Find a certain address book */ + +const struct ldapabook *ldapabook_find(const struct ldapabook *, +					const char *); + +/* Add a new entry to the address book */ + +int ldapabook_add(const char *,			/* filename */ +		const struct ldapabook *);	/* new entry */ + +/* Delete an entry from the address book */ + +int ldapabook_del(const char *,		/* filename */ +		const char *,		/* temporary filename on same filesys */ +		const char *);		/* name to delete */ + +/* Run ldapsearch in the background, return a file descriptor containing +** ldapsearch's output. +*/ + +int ldapabook_search(const struct ldapabook *b,	/* Search this address book */ +		     const char *script, +		     const char *search, +		     int (*callback_func)(const char *utf8_name, +					  const char *address, +					  void *callback_arg), +		     void (*callback_err)(const char *errmsg, +					  void *callback_arg), +		     void *callback_arg); + +/* +** Internal function: +*/ + +void ldapabook_writerec(const struct ldapabook *, FILE *); + +#ifdef  __cplusplus +} +#endif + +#endif diff --git a/ldapaddressbook/ldapsearch.c b/ldapaddressbook/ldapsearch.c new file mode 100644 index 0000000..d0deec6 --- /dev/null +++ b/ldapaddressbook/ldapsearch.c @@ -0,0 +1,62 @@ +/* +** Copyright 2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include "libldapsearch.h" +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +static int cb(const char *utf8_name, +	      const char *address, +	      void *callback_arg) +{ +	if (strchr(utf8_name, '\n') == NULL && +	    strchr(address, '\n') == NULL) +		/* filter out if it looks funny */ + +		printf("%s\n%s\n", utf8_name, address); +	return 0; +} + +int main(int argc, char **argv) +{ +	const char *host, *port, *suffix, *search; +	int port_n; +	struct ldapsearch *s; + +	if (argc < 5) +	{ +		fprintf(stderr, "INTERNAL ERROR: Invalid # of parameters to ldapsearch\n"); +		exit(1); +	} + +	host=argv[1]; +	port=argv[2]; +	suffix=argv[3]; +	search=argv[4]; + +	port_n=atoi(port); + +	if (port_n <= 0) +		port_n=LDAP_PORT; + +	s=l_search_alloc(host, port_n, argc > 5 ? argv[5]:NULL, +			 argc > 6 ?argv[6]:NULL, suffix); + +	if (!s) +	{ +		perror("l_search_alloc"); +		exit(1); +	} + +	if (l_search_do(s, search, cb, NULL)) +	{ +		perror("l_search_do"); +		exit(1); +	} +	l_search_free(s); +	exit(0); +} diff --git a/ldapaddressbook/libldapsearch.c b/ldapaddressbook/libldapsearch.c new file mode 100644 index 0000000..71ef2ed --- /dev/null +++ b/ldapaddressbook/libldapsearch.c @@ -0,0 +1,449 @@ +/* +** Copyright 2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include "libldapsearch.h" +#include <stdlib.h> +#include <errno.h> +#include <time.h> +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +#  include <sys/time.h> +# else +#  include <time.h> +# endif +#endif + +/* +** Allocate and deallocate the ldapsearch struct. +*/ + +struct ldapsearch *l_search_alloc(const char *host, +				  int port, +				  const char *userid, +				  const char *password, +				  const char *base) +{ +	char *buf; + +	struct ldapsearch *p=(struct ldapsearch *) +		malloc(sizeof(struct ldapsearch)); + +	if (!p) +		return NULL; + +	if ((p->base=strdup(base)) == NULL) +	{ +		free(p); +		return NULL; +	} + +	if ((buf=malloc(strlen(host)+100)) == NULL) +	{ +		free(p->base); +		free(p); +		return NULL; +	} + +	sprintf(buf, "ldap://%s:%d", host, port); + +	if (ldap_initialize(&p->handle, buf) != LDAP_SUCCESS) +	{ +		free(buf); +		free(p->base); +		free(p); +		return NULL; +	} +	free(buf); + +	if (userid && *userid) +	{ +		struct berval cred; + +		cred.bv_len=password && *password ? strlen(password):0; +		cred.bv_val=password && *password ? (char *)password:NULL; + +		if (ldap_sasl_bind_s(p->handle, userid, NULL, &cred, NULL, +				     NULL, NULL)) +		{ +			l_search_free(p); +			errno=EPERM; +			return NULL; +		} +	} + +	return p; +} + +void l_search_free(struct ldapsearch *s) +{ +	if (s->handle) +		ldap_unbind_ext(s->handle, NULL, NULL); +	free(s->base); +	free(s); +} + +/* +** See RFC 2254 section 4. +*/ + +static char *encode_key(const char *lookupkey) +{ +	const char *cp; + +	char *p=NULL, *q; +	int pass; +	size_t l=0; + +	for (pass=0; pass<2; pass++) +	{ +		if (pass) +		{ +			p=malloc(l); +			if (!p) +				return NULL; +		} +		l=1; +		q=p; +		for (cp=lookupkey; *cp; cp++) +		{ +			const char *h; + +			switch (*cp) { +			case '*': +				h="\\2a"; +				break; +			case '(': +				h="\\28"; +				break; +			case ')': +				h="\\29"; +				break; +			case '\\': +				h="\\5c"; +				break; +			default: +				if (pass) +					*q++= *cp; +				++l; +				continue; +			} + +			if (pass) +				while ((*q++ = *h++) != 0) +					; +			l += 3; +		} +		if (pass) +			*q=0; +	} +	return p; +} + +/* +** Insert lookup key into the search filter. +*/ + +static char *make_search_key(const char *filter, const char *lookupkey) +{ +	size_t l=strlen(filter)+1; +	char *p, *q; +	const char *cp; + +	for (cp=filter; *cp; cp++) +		if (*cp == '@') +			l += strlen(lookupkey); + +	p=malloc(l); +	if (!p) +		return NULL; + +	for (q=p, cp=filter; *cp; cp++) +	{ +		if (*cp == '@') +		{ +			const char *k=lookupkey; + +			while ( (*q++ = *k++ ) != 0) +				; +			--q; +			continue; +		} +		*q++ = *cp; +	} +	*q=0; +	return p; +} + +static int l_search_do_filter(struct ldapsearch *s, + +			      int (*callback_func)(const char *utf8_name, +						   const char *address, +						   void *callback_arg), +			      void *callback_arg, + +			      const char *filter, +			      const char *lookup_key, +			      int *found); + + +int l_search_do(struct ldapsearch *s, +		const char *lookupkey, + +		int (*callback_func)(const char *utf8_name, +				     const char *address, +				     void *callback_arg), +		void *callback_arg) +{ +	char *k; +	const char *filter; +	int rc_code; +	int found; + +	k=encode_key(lookupkey); +	if (!k) +		return -1; + +	filter=getenv("LDAP_SEARCH_FILTER_EXACT"); +	if (!filter) +		filter="(|(uid=@)(sn=@)(cn=@))"; + +	rc_code=l_search_do_filter(s, callback_func, callback_arg, +				   filter, k, &found); + +	if (rc_code == 0 && !found) +	{ +		filter=getenv("LDAP_SEARCH_FILTER_APPROX"); +		if (!filter) +			filter="(|(uid=@*)(sn=@*)(mail=@*)(cn=@*))"; + +		rc_code=l_search_do_filter(s, callback_func, callback_arg, +					   filter, k, &found); +	} +	free(k); +	return rc_code; +} + +static int l_search_do_filter(struct ldapsearch *s, +			      int (*callback_func)(const char *utf8_name, +						   const char *address, +						   void *callback_arg), +			      void *callback_arg, +			      const char *filter, +			      const char *lookup_key, +			      int *found) +{ +	char *kk; +	struct timeval tv; +	LDAPMessage *result; +	char *attrs[3]; +	int rc_code=0; +	int msgidp; + +	*found=0; + +	kk=make_search_key(filter, lookup_key); + +	if (!kk) +		return -1; + +	if (s->handle == NULL) +	{ +		errno=ETIMEDOUT;  /* Timeout previously */ +		return -1; +	} + + +	attrs[0]="cn"; +	attrs[1]="mail"; +	attrs[2]=NULL; + +	tv.tv_sec=60*60; +	tv.tv_usec=0; + +	if (ldap_search_ext(s->handle, s->base, LDAP_SCOPE_SUBTREE, +			    kk, attrs, 0, NULL, NULL, &tv, 1000000, &msgidp) +	    != LDAP_SUCCESS) +		return -1; + +	do +	{ +		int rc; +		LDAPMessage *msg; + +		const char *timeout=getenv("LDAP_SEARCH_TIMEOUT"); + +		tv.tv_sec=atoi(timeout ? timeout:"30"); +		tv.tv_usec=0; + +		rc=ldap_result(s->handle, msgidp, 0, &tv, &result); + +		if (rc <= 0) +		{ +			if (rc == 0) +				errno=ETIMEDOUT; + +			ldap_unbind_ext(s->handle, NULL, NULL); +			s->handle=NULL; +			rc_code= -1; +			break; +		} + +		if (rc == LDAP_RES_SEARCH_RESULT) +		{ +			ldap_msgfree(result); +			break; /* End of search */ +		} + +		if (rc != LDAP_RES_SEARCH_ENTRY) +		{ +			ldap_msgfree(result); +			continue; +		} + +		for (msg=ldap_first_message(s->handle, result); msg; +		     msg=ldap_next_message(s->handle, msg)) +		{ +			struct berval **n_val= +				ldap_get_values_len(s->handle, msg, "cn"); +			struct berval **a_val= +				ldap_get_values_len(s->handle, msg, "mail"); + +			if (n_val && a_val) +			{ +				size_t i, j; + +				for (i=0; n_val[i]; i++) +					for (j=0; a_val[j]; j++) +					{ +						char *p=malloc(n_val[i]->bv_len +							       +1); +						char *q=malloc(a_val[j]->bv_len +							       +1); + +						if (!p || !q) +						{ +							if (p) free(p); +							if (q) free(q); +							rc_code= -1; +							break; +						} + +						memcpy(p, n_val[i]->bv_val, +						       n_val[i]->bv_len); +						p[n_val[i]->bv_len]=0; + +						memcpy(q, a_val[j]->bv_val, +						       a_val[j]->bv_len); +						q[a_val[j]->bv_len]=0; + +						rc_code=(*callback_func) +							(p, q, callback_arg); +						free(p); +						free(q); +						if (rc_code) +							break; +						*found=1; +					} +			} +			if (n_val) +				ldap_value_free_len(n_val); +			if (a_val) +				ldap_value_free_len(a_val); +		} + +		ldap_msgfree(result); +	} while (rc_code == 0); +	return rc_code; +} + +int l_search_ping(struct ldapsearch *s) +{ +	char *attrs[2]; +	struct timeval tv; +	LDAPMessage *result; +	int rc; +	int msgid; + +	if (s->handle == NULL) +	{ +		errno=ETIMEDOUT;  /* Timeout previously */ +		return -1; +	} + +	attrs[0]="objectClass"; +	attrs[1]=NULL; + +	tv.tv_sec=60*60; +	tv.tv_usec=0; + +	if (ldap_search_ext(s->handle, s->base, LDAP_SCOPE_BASE, +			    "objectClass=*", attrs, 0, NULL, NULL, &tv, +			    1000000, &msgid) < 0) +		return -1; + +	do +	{ +		const char *timeout=getenv("LDAP_SEARCH_TIMEOUT"); + +		tv.tv_sec=atoi(timeout ? timeout:"30"); +		tv.tv_usec=0; + +		rc=ldap_result(s->handle, msgid, 0, &tv, &result); + +		if (rc <= 0) +		{ +			if (rc == 0) +				errno=ETIMEDOUT; + +			ldap_unbind_ext(s->handle, NULL, NULL); +			s->handle=NULL; + +			return -1; +		} + +		ldap_msgfree(result); +	} while (rc != LDAP_RES_SEARCH_RESULT); +	return 0; +} + +#if 0 + +#include <stdio.h> + +static int cb(const char *utf8_name, +	      const char *address, +	      void *callback_arg) +{ +	printf("\"%s\" <%s>\n", utf8_name, address); +	return 0; +} + +int main(int argc, char **argv) +{ +	struct ldapsearch *s=l_search_alloc("localhost", 389, +					    "dc=courier-mta,dc=com"); +	int n; + +	if (!s) +	{ +		perror("l_search_alloc"); +		exit(1); +	} + +	for (n=1; n<argc; n++) +	{ +		if (l_search_do(s, argv[n], cb, NULL) != 0) +		{ +			printf("l_search_do: error\n"); +		} +	} +	l_search_free(s); +	return 0; +} +#endif diff --git a/ldapaddressbook/libldapsearch.h b/ldapaddressbook/libldapsearch.h new file mode 100644 index 0000000..58241a7 --- /dev/null +++ b/ldapaddressbook/libldapsearch.h @@ -0,0 +1,73 @@ +/* +** Copyright 2006, Double Precision Inc. +** +*/ + +#ifndef ldapsearch_h +#define ldapsearch_h + +#ifdef  __cplusplus +extern "C" { +#endif + +/* +** Encapsulate interface for search address book in LDAP +*/ + +#include "config.h" +#if HAVE_LBER_H +#include <lber.h> +#endif +#include <ldap.h> +#include <stdio.h> + +struct ldapsearch { + +	LDAP *handle; + +	char *base;   /* Saved base of the search */ +}; + +/* +** Allocate and deallocate the ldapsearch struct. +*/ + +struct ldapsearch *l_search_alloc(const char *host, +				  int port, +				  const char *userid, +				  const char *password, +				  const char *base); +/* base - the starting point of the search in the LDAP tree */ + +void l_search_free(struct ldapsearch *s); + +/* +** Search the address book, and invoke the callback function for each +** match found.  The callback function receives the name & address of the +** found entry.  'exact_match' is nonzero if the lookupkey matched on of the +** LDAP attributes. +** +** The callback function must return zero.   A non-zero return stops the +** search. +*/ + +int l_search_do(struct ldapsearch *s, +		const char *lookupkey, + +		int (*callback_func)(const char *utf8_name, +				     const char *address, +				     void *callback_arg), +		void *callback_arg); + +/* +** Ping the LDAP server (makes sure that host/port were valid, because +** any connection attempt is deferred). +*/ + +int l_search_ping(struct ldapsearch *s); + +#ifdef  __cplusplus +} +#endif + +#endif diff --git a/ldapaddressbook/noldapsearch.c b/ldapaddressbook/noldapsearch.c new file mode 100644 index 0000000..fa93b7e --- /dev/null +++ b/ldapaddressbook/noldapsearch.c @@ -0,0 +1,16 @@ +/* +** Copyright 2006, Double Precision Inc. +** +** See COPYING for distribution information. +*/ + +#include <stdio.h> + +/* +** Stub ldapsearch binary when openldap is not available. +*/ + +int main() +{ +	return (0); +} | 
