Major clients cleanout

This commit is contained in:
Kurt Zeilenga 2001-07-07 05:05:38 +00:00
parent 9e3613228e
commit 0e1c9551a9
21 changed files with 1 additions and 4998 deletions

View file

@ -4,4 +4,4 @@
##
## Clients Makefile.in for OpenLDAP
SUBDIRS= tools ud finger gopher mail500 fax500 rcpt500 maildap
SUBDIRS= tools ud finger mail500 maildap

View file

@ -1,45 +0,0 @@
# $OpenLDAP$
UNIX_PRGS = rp500 fax500
EXEPRGS = $(@PLAT@_PRGS)
PROGRAMS = xrpcomp.tmp $(EXEPRGS)
SRCS= main.c faxtotpc.c rp500.c
XSRCS=fax5version.c rpversion.c
FAX5OBJS = main.o faxtotpc.o
RPOBJS = rp500.o faxtotpc.o
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
XLIBS = -lldap -llber -llutil
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
rp500 : rpversion.o
$(LTLINK) -o $@ $(RPOBJS) rpversion.o $(LIBS)
fax500 : fax5version.o
$(LTLINK) -o $@ $(RPOBJS) fax5version.o $(LIBS)
rpversion.c: ${RPOBJS} $(LDAP_LIBDEPEND)
@-$(RM) $@
$(MKVERSION) rp500 > $@
fax5version.c: ${FAX5OBJS} $(LDAP_LIBDEPEND)
@-$(RM) $@
$(MKVERSION) fax500 > $@
xrpcomp.tmp: xrpcomp
$(SED) -e 's|%LIBEXECDIR%|$(libexecdir)|' $(srcdir)/xrpcomp > xrpcomp.tmp
install-local: $(PROGRAMS) FORCE
-$(MKDIR) $(DESTDIR)$(libexecdir)
@( \
for prg in $(EXEPRGS); do \
$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
$(DESTDIR)$(libexecdir); \
done \
)
$(INSTALL_SCRIPT) $(INSTALLFLAGS) xrpcomp.tmp \
$(DESTDIR)$(libexecdir)/xrpcomp

View file

@ -1,104 +0,0 @@
README file for fax500
xrpcomp
-------
This directory contains a modified version of the rpcomp program, used
with the Internet remote-printing experiment. More info on the experiment
can be found in /mrose/tpc on ftp.ics.uci.edu.
The xrpcomp program (it's a shell script) is like rpcomp, except that it
will look in X.500 if no fax recipients are found in the .rpdb file.
It still uses .rpdb to extract the originator information.
There are a couple of things in rp500.c you will want to tailor to use
xrpcomp at your site:
DAPUSER This is the user the rp500 program, called from
xrpcomp will bind to the directory as. It can
be set to NULL.
DEFAULT_BASE This is the search base rp500 will use when looking
in the directory for fax recipients.
DEFAULT_FILTERCONF
Where to find the ldapfilter.conf file. Should
make setting this automatic, but for now...
PHONE_PREFIX The prefix of phones in your local area. If
rp500 finds a fax number in the directory that is
not fully qualified, it will append as many of
these digits as necessary to make it fully
qualified. NB it assumes US-format numbers.
DEFAULT_LDAPHOST
The host running the default ldap server to
contact.
Things to note:
The rp500 program knows a little about the US phone number format, in
an attempt to deal with (evil) people who have not put fully qualified
international format (e.g. +1 ... ) phone numbers in their entry. If
your users do not have US-format phone numbers, you'll need to take a
look at the fax2email() routine in rp500.c and change it around a bit.
7/30/93 -- Tim
fax500
------
This directory also contains the fax500 program. fax500 is just like
mail500, except that it looks up the facsimileTelephoneNumber
attribute, constructs an appropriate "remote-printer@blah.tpc.int"
address, and send the mail there. For example, the facsimile number
"+1 313 555 1212" corresponds to the address
"remote-printer@2.1.2.1.5.5.5.3.1.3.1.tpc.int." For a complete
explanation of the Internet remote-printing experiment, look in
/mrose/tpc on ftp.ics.uci.edu, or send mail to tpc-faq@town.hall.org.
The general idea is that you can set things up so that mail sent to
"user@fax.domain" will get printed on the user's fax machine, if
they've entered a fax number in their X.500 entry.
NOTE: you will need to modify faxtotpc.c if you have any "abbreviated"
phone number capabilities. For example, our telephone switches allow
you to dial only the last 5 digits of campus telephone numbers. People,
therefore, tend to list the last 5 digits of their fax numbers. The
routine "munge_phone()" takes care of fixing up abbreviated phone
numbers. You may need to write your own code.
fax500 is not yet complete. In particular, the following work still needs
to be done:
- If the group entry itself has a fax number, don't send to all the members'
individual fax numbers. Instead, just send to the group's fax number.
- The -h flag for fax500 defines both the host name and the search base.
This causes problems because the host name we want is "fax.umich.edu"
but we need to search "umich.edu." The workaround is to add an
Associated Domain corresponding to the domain you want for your fax
service to each X.500 group which is to be accessible.
- We're working toward mail500 and fax500 being the same binary. Depending
on what argv[0] is, you'll get different behavior. Although this
binary should work just like mail500 if you name it "mail500" it's
not yet been tested.
- fax500 currently assumes that incoming messages are plain text, and
therefore constructs a destination address like
"remote-printer.user_name@2.1.2.1.5.5.5.3.1.3.1.tpc.int". If
the message is already MIME-compliant with an "application/remote-printing"
content type, we lose, since the remote-printing software assumes
that anything other than "remote-printer" on ther lhs of the address
means the message is plain text. Not sure about the solution to this.
- Regarding group support - typically, when we collect all the fax numbers
for a group, we'll end up either with (a) people who haven't registered
fax numbers, or (b) "email-only" group members who do not have entries
in X.500 (they only have an email address associated with the group).
The question is: what do you do with faxes for these folks? You could
(1) bounce to the sender (current behavior) or you could (2) send
email to the members with no fax numbers, informing them that someone
tried to send them a fax. I tend to prefer solution (2) for case (a),
and solution (1) for case (b).
- A configuration file-driven "munge_phone()" would be nice.
8/23/93 - Gordon

View file

@ -1,11 +0,0 @@
/* $OpenLDAP$ */
#ifndef FAX500_H
#define FAX500_H 1
/* in faxtotpc.c */
void strip_nonnum ( char *str );
char *remove_parens( char *ibuf, char *obuf );
char *munge_phone ( char *ibuf, char *obuf );
char *faxtotpc ( char *phone, char *userinfo );
#endif

View file

@ -1,239 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright (c) 1993 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*
*
* Routines for parsing the facsimileTelephoneNumber field out of
* an X.500 entry and converting it to a "tpc.int" domain name.
*
* char *faxtotpc( char *str, char *userinfo)
*
* faxtotpc() returns a pointer to a string allocated with malloc(3).
*/
#include "portable.h"
#include <stdio.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/unistd.h>
#include "fax500.h"
#define TPCDOMAIN "tpc.int"
/*
* Remove everything from 'str' which is not a digit
*/
void
strip_nonnum( char *str )
{
char *p, *q;
p = q = str;
for (;;) {
if (*p == '\0') {
*q = *p;
return;
}
if (isdigit((u_char) *p)) {
*q = *p;
p++;
q++;
} else {
p++;
}
}
}
/*
* Remove anything of the form (blah) where
* "blah" contains a non-numeric character.
*/
char *
remove_parens( char *ibuf, char *obuf )
{
char *p = ibuf;
char *q = obuf;
while (*p != '\0') {
char *s;
char *t;
if (*p == '(') {
/* look for a closing paren */
if (( s = strchr(p, ')')) != NULL) {
/* Check the string between p and s */
/* for non-numeric characters */
t = p + 1;
while (t < s) {
if (!isdigit((u_char) *t)) {
/* garbage, delete */
p = s + 1;
t = p;
break;
}
t++;
}
/* when we get here, p points to the first */
/* thing we want to keep, t to the last. */
strncpy(q, p, t - p);
q += t - p;
p = t;
} else {
/* no closing paren, what to do? keep it */
*q = *p;
p++;
q++;
}
} else {
/* not a paren - copy out */
*q = *p;
p++;
q++;
}
}
*q = '\0'; /* terminate output string */
return(obuf);
}
/*
* Apply local fixups to phone numbers here. Replace this routine
* with code to expand common "abbreviations" for phone numbers. For
* example, on the U-M campus, it's only necessary to dial the last
* 5 digits of the telephone number, and hence people here tend to
* give only the last 5 digits of their fax numbers.
*
* Local U-M mods:
* If exactly 5 digits were provided, assume it's a campus
* phone number and prepend "1313nm" where "mn" are computed
* according to the following:
* first digit of
* 5-digit "Local"
* phone mn
* ----- --
* 3 76 e.g. "31234" -> "7631234"
* 4 76
* 7 74
* 6 93
* 8 99
*/
char *
munge_phone( char *ibuf, char *obuf )
{
#define UMAREACODE "1313"
char prefix[3];
if (strlen(ibuf) == 7) {
/* Assume local number w/o area code */
sprintf(obuf, "%s%s", UMAREACODE, ibuf);
return(obuf);
}
if (strlen(ibuf) == 10) {
/* Assume local number with area code */
sprintf(obuf, "%s%s", "1", ibuf);
return(obuf);
}
if (strlen(ibuf) != 5) {
/* Not 5 digits - leave alone */
strcpy(obuf, ibuf);
return(obuf);
}
switch (ibuf[0]) {
case '3' :
case '4' : strcpy(prefix, "76");
break;
case '7' : strcpy(prefix, "74");
break;
case '6' : strcpy(prefix, "93");
break;
case '8' : strcpy(prefix, "99");
break;
default : /* Unknown, leave alone */
strcpy(obuf, ibuf);
return(obuf);
}
sprintf(obuf, "%s%s%s", UMAREACODE, prefix, ibuf);
return(obuf);
}
/*
* Convert string to "tpc.int" domain name.
*/
char *
faxtotpc( char *phone, char *userinfo )
{
char *p;
char *q;
char ibuf[255];
char obuf[255];
/* nuke spaces */
strcpy(ibuf, phone);
for (p = ibuf, q = obuf; *p != '\0'; p++) {
if (*p != ' ') {
*q = *p;
q++;
}
}
*q = '\0';
strcpy(ibuf, obuf);
remove_parens(ibuf, obuf);
strcpy(ibuf, obuf);
/* Look for "+" - if followed by a number,
assume it's an international number and leave
it alone.
*/
if ((p = strchr(ibuf, '+')) != NULL) {
if (isdigit((u_char) *(p + 1))) {
/* strip any non-digits */
strip_nonnum(ibuf);
}
} else {
strip_nonnum(ibuf);
/* Apply local munges */
munge_phone(ibuf, obuf);
strcpy(ibuf, obuf);
}
/* Convert string of form abcd to remote-printer@d.c.b.a.tpc.int */
q = obuf;
for (p = ibuf + strlen(ibuf) - 1; p >= ibuf; p--) {
*q++ = *p;
*q++ = '.';
}
*q = '\0';
strcpy(ibuf, obuf);
strcpy(obuf, "remote-printer");
/* include userinfo if present */
if (userinfo != NULL && strlen(userinfo)) {
strcat(obuf, ".");
strcat(obuf, userinfo);
}
strcat(obuf, "@");
strcat(obuf, ibuf); /* tack on reversed phone number */
strcat(obuf, TPCDOMAIN); /* tack on domain name */
p = strdup(obuf);
return(p);
}

File diff suppressed because it is too large Load diff

View file

@ -1,278 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <ldap.h>
#include "fax500.h"
#include "ldap_defaults.h"
#define DEFAULT_PORT 79
#define DEFAULT_SIZELIMIT 50
int debug;
char *ldaphost = NULL;
char *base = NULL;
int deref = LDAP_DEREF_ALWAYS;
int sizelimit = DEFAULT_SIZELIMIT;
LDAPFiltDesc *filtd;
static void print_entry(LDAP *ld, LDAPMessage *e);
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-d debuglevel] [-x ldaphost] [-b searchbase] [-a] [-z sizelimit] [-f filterfile] searchstring\r\n", name );
exit( -1 );
}
int
main( int argc, char **argv )
{
int i, rc, matches;
char *filterfile = FILTERFILE;
char buf[10];
char *key;
LDAP *ld;
LDAPMessage *result, *e;
LDAPFiltDesc *filtd;
LDAPFiltInfo *fi;
static char *attrs[] = { "title", "o", "ou", "postalAddress",
"telephoneNumber", "mail",
"facsimileTelephoneNumber", NULL };
while ( (i = getopt( argc, argv, "ab:d:f:x:z:" )) != EOF ) {
switch( i ) {
case 'a': /* do not deref aliases when searching */
deref = LDAP_DEREF_FINDING;
break;
case 'b': /* search base */
base = strdup( optarg );
break;
case 'd': /* turn on debugging */
debug = atoi( optarg );
break;
case 'f': /* ldap filter file */
filterfile = strdup( optarg );
break;
case 'x': /* specify ldap host */
ldaphost = strdup( optarg );
break;
case 'z': /* size limit */
sizelimit = atoi( optarg );
break;
default:
usage( argv[0] );
}
}
if ( optind == argc ) {
usage( argv[0] );
}
key = argv[optind];
if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n", filterfile );
exit( -1 );
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
perror( "ldap_init" );
exit( -1 );
}
ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
fprintf( stderr, "X.500 is temporarily unavailable.\n" );
ldap_perror( ld, "ldap_simple_bind_s" );
exit( -1 );
}
result = NULL;
{
for ( fi = ldap_getfirstfilter( filtd, "rp500", key );
fi != NULL; fi = ldap_getnextfilter( filtd ) ) {
if ( (rc = ldap_search_s( ld, base, LDAP_SCOPE_SUBTREE,
fi->lfi_filter, attrs, 0, &result ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
&& rc != LDAP_TIMELIMIT_EXCEEDED )
{
ldap_perror( ld, "ldap_search" );
exit( -1 );
}
if ( (matches = ldap_count_entries( ld, result )) != 0
|| rc != LDAP_SUCCESS ) {
break;
}
}
}
if ( matches == 1 ) {
e = ldap_first_entry( ld, result );
print_entry( ld, e );
} else if ( matches > 1 ) {
fprintf( stderr, "%d %s matches for \"%s\":\r\n", matches,
fi->lfi_desc, key );
for ( i = 1, e = ldap_first_entry( ld, result ); e != NULL;
i++, e = ldap_next_entry( ld, e ) ) {
int j;
char *p, *dn, *rdn;
char **title;
dn = ldap_get_dn( ld, e );
rdn = dn;
if ( (p = strchr( dn, ',' )) != NULL )
*p = '\0';
while ( *rdn && *rdn != '=' )
rdn++;
if ( *rdn )
rdn++;
if ( strcasecmp( rdn, buf ) == 0 ) {
char **cn;
int i, last;
cn = ldap_get_values( ld, e, "cn" );
for ( i = 0; cn[i] != NULL; i++ ) {
last = strlen( cn[i] ) - 1;
if ( isdigit((unsigned char) cn[i][last]) ) {
rdn = strdup( cn[i] );
break;
}
}
}
title = ldap_get_values( ld, e, "title" );
fprintf( stderr, " %d: %-20s %s\r\n", i, rdn,
title ? title[0] : "" );
if ( title != NULL ) {
for ( j = 1; title[j] != NULL; j++ )
fprintf( stderr, " %-20s %s\r\n",
"", title[j] );
}
if ( title != NULL )
ldap_value_free( title );
free( dn );
}
if ( rc == LDAP_SIZELIMIT_EXCEEDED
|| rc == LDAP_TIMELIMIT_EXCEEDED ) {
fprintf( stderr, "(Size or time limit exceeded)\n" );
}
fprintf( stderr, "Enter the number of the person you want: ");
if ( fgets( buf, sizeof(buf), stdin ) == NULL
|| buf[0] == '\n' ) {
exit( EXIT_FAILURE );
}
i = atoi( buf ) - 1;
e = ldap_first_entry( ld, result );
for ( ; i > 0 && e != NULL; i-- ) {
e = ldap_next_entry( ld, e );
}
if ( e == NULL ) {
fprintf( stderr, "Invalid choice!\n" );
exit( EXIT_FAILURE );
}
print_entry( ld, e );
} else if ( matches == 0 ) {
fprintf( stderr, "No matches found for \"%s\"\n", key );
exit( EXIT_FAILURE );
} else {
fprintf( stderr, "Error return from ldap_count_entries\n" );
exit( -1 );
}
ldap_unbind( ld );
return( 0 );
}
static void
print_entry( LDAP *ld, LDAPMessage *e )
{
int i;
char *dn, *rdn;
char **ufn;
char **title, **dept, **addr, **phone, **fax, **mail;
char *faxmail, *org;
dn = ldap_get_dn( ld, e );
ufn = ldap_explode_dn( dn, 0 );
rdn = strchr( ufn[0], '=' ) + 1;
if ( (fax = ldap_get_values( ld, e, "facsimileTelephoneNumber" ))
== NULL ) {
fprintf( stderr, "Entry \"%s\" has no fax number.\n", dn );
exit( EXIT_FAILURE );
}
faxmail = faxtotpc( fax[0], NULL );
title = ldap_get_values( ld, e, "title" );
phone = ldap_get_values( ld, e, "telephoneNumber" );
mail = ldap_get_values( ld, e, "mail" );
dept = ldap_get_values( ld, e, "ou" );
addr = ldap_get_values( ld, e, "postalAddress" );
org = "";
for ( i = 0; ufn[i] != NULL; i++ ) {
if ( strncmp( "o=", ufn[i], 2 ) == 0 ) {
org = strdup( strchr( ufn[i], '=' ) + 1 );
break;
}
}
printf( "To: %s\n", faxmail );
printf( "Subject:\n" );
printf( "--------\n" );
printf( "#<application/remote-printing\n" );
printf( "Recipient: %s\r\n", rdn );
printf( "Title: %s\r\n", title ? title[0] : "" );
printf( "Organization: %s\r\n", org );
printf( "Department: %s\r\n", dept ? dept[0] : "" );
printf( "Telephone: %s\r\n", phone ? phone[0] : "" );
printf( "Facsimile: %s\r\n", fax ? fax[0] : "" );
printf( "Email: %s\r\n", mail ? mail[0] : "" );
}

View file

@ -1,85 +0,0 @@
#! /bin/sh
RP500=%LIBEXECDIR%/rp500
NAME="$1"
if [ -z "$NAME" ]; then
echo "usage: xrpcomp name [arguments for comp]" 2>&1
exit 1
fi
DB=".rpdb"
if [ ! -s "$DB" ]; then
DB="$HOME/.rpdb"
fi
if [ ! -s "$DB" ]; then
echo "unable to read $DB" 2>&1
exit 1
fi
C=/tmp/rp$$.comp S=/tmp/rp$$.sh O=/tmp/rp$$.orig
trap "rm -f $C $S $O" 0 1 2 3 13 15
cp /dev/null $S
gawk -v NAME="$NAME" -v S="$S" -v O="$O" '
function rev(f) {
s = ""
for (l = length(f); l > 0; l--)
s = s "." substr(f, l, 1)
return substr(s, 2, length(s) - 1)
}
BEGIN {
RS= ""; FS = "\n"
}
{
if (NR == 1) {
from = $2
gsub("Recipient[ ]*:", "Originator:", from);
orig = "\r\n" from
for (i = 3; i <= NF; i++)
orig = orig "\r\n" $i;
printf orig "\r\n" > O
}
if ($1 != NAME)
next
for (i = 2; i <= NF; i++) {
if (match($i, "Facsimile[ ]*:") > 0) {
fax = substr($i, RSTART+RLENGTH)
gsub("[ +-]", "", fax)
printf "ADDR=\"remote-printer@%s.tpc.int\"\n", rev(fax) > S
printf "To: remote-printer@%s.tpc.int\n", rev(fax)
printf "Subject:\n"
printf "--------\n"
printf "#<application/remote-printing\n"
recip = $2
for (i = 3; i <= NF; i++)
recip = recip "\r\n" $i;
printf "%s\r\n%s\r\n", recip, orig
printf "#\n"
exit(0)
}
}
}' < $DB > $C
. $S
if [ -z "$ADDR" ]; then
echo "recipient \"$NAME\" not in $DB, checking X.500..." 2>&1
$RP500 "$NAME" > $C
RC=$?
if [ $RC = 1 ]; then
exit 1
elif [ $RC = 0 ]; then
cat $O >> $C
echo "#" >> $C
else
echo "error searching X.500" 2>&1
exit 1
fi
fi
shift
comp -form $C $* -editor rpprompter

View file

@ -1,45 +0,0 @@
# $OpenLDAP$
##
## Makefile for gopher clients
##
UNIX_PRGS= go500gw go500
PROGRAMS = $(@PLAT@_PRGS)
SRCS= go500.c go500gw.c
XSRCS= gwversion.c goversion.c
GOOBJS = go500.o
GWOBJS = go500gw.o
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
XLIBS = -lldap -llber -llutil
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
go500 : goversion.o
$(LTLINK) -o $@ $(GOOBJS) goversion.o $(LIBS)
go500gw : gwversion.o
$(LTLINK) -o $@ $(GWOBJS) gwversion.o $(LIBS)
goversion.c: ${GOOBJS} $(LDAP_LIBDEPEND)
@-$(RM) $@
$(MKVERSION) go500 > $@
gwversion.c: ${GWOBJS} $(LDAP_LIBDEPEND)
@-$(RM) $@
$(MKVERSION) go500gw > $@
install-local: $(PROGRAMS) go500gw.help FORCE
-$(MKDIR) $(DESTDIR)$(libexecdir) $(DESTDIR)$(datadir)
@( \
for prg in $(PROGRAMS); do \
$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
$(DESTDIR)$(libexecdir); \
done \
)
-$(MV) $(DESTDIR)$(datadir)/go500gw.help $(DESTDIR)$(datadir)/go500gw.help-
$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/go500gw.help $(DESTDIR)$(datadir)

View file

@ -1,184 +0,0 @@
This directory contains source for two programs:
go500 A gopher index search server to X.500 gateway
go500gw A more general gopher to X.500 gateway
Both programs use the LDAP protocol to talk to X.500.
What you are trying to set up looks like this:
-------- ----------------- -------- --------
| gopher | | gopher to| LDAP | | LDAP | | X.500 |
| client |<- gophr ->| LDAP g/w | API |<- LDAP ->| server |<- DAP ->| server |
|________| |__________|______| |________| |________|
go500gw ldapd
or
go500
Both go500 and go500gw can be run either from inetd or as stand-alone
servers.
go500 is useful when you always want to search a fixed portion of the X.500
tree. It does not let you browse around or change where you search.
go500gw is useful when you want to provide a more general and flexible
gateway from gopher to X.500. It allows users to browse around anywhere
in the X.500 tree, doing searches at any point.
**************************************************************************
* RUNNING go500 *
**************************************************************************
1) Make and install the ldap distribution if you have not already done so:
(cd ../; make lib-only; make inst-lib)
or
(cd ../; make all; make install)
Use the second form if you don't already have an ldapd running
somewhere you can connect to. Note that to make an ldap server,
you will need the ISODE libraries and include files.
2) Tailor go500 to your site before compiling:
vi go500.c
There are a couple of things to change in go500.c:
DAPUSER - This is the DN go500 will bind to the directory as.
You can specify NULL if you want.
DEFAULT_BASE - This is the DN of the object below which go500
will conduct its search. You typically want this to
be the DN or your organization.
DEFAULT_LDAPHOST - This is the host that is running the ldap
server. If it's not on the localhost, you'll need to
change this.
3) Make go500:
make
4) Start the ldap daemon:
ldapd [-c dsaname]
You only need to do this if you're not already running one.
5) Start go500 as a stand-alone server:
go500
or arrange to have it start from inetd:
# vi /etc/services /* add the following line */
go500 5555/tcp go500 # go500 server
# vi /etc/inetd.conf /* add the following line */
go500 stream tcp nowait nobody $(ETCDIR)/go500 go500 -I
# kill -HUP <inetdpid> /* make inetd notice the change */
where $(ETCDIR) is replaced by the ETCDIR from the top level Makefile
and <inetdpid> is replaced by the pid of the inetd process.
6) Configure your local gopher server to have an entry for go500.
A sample .link file is given below, with the things you should
change given in <>'s:
Name=<Label of your choice>
Type=7
Port=5555
Path=
Host=<host.running.go500.here>
You may also have to restart your gopher daemon, or remove
the .cache file.
7) Run a gopher client and try it out.
**************************************************************************
* RUNNING go500gw *
**************************************************************************
1) Make the ldap distribution if you have not already done so:
(cd ../; make lib-only)
or
(cd ../; make lib-only ldap-server)
Use the second form if you don't already have an ldapd running
somewhere you can connect to. Note that to make an ldap server,
you will need the ISODE libraries and include files.
2) Tailor go500gw to your site before compiling:
vi go500gw.c
There are a couple of things to change in go500gw.c:
GO500DN - This is the DN go500gw will bind to the directory as.
You can specify NULL if you want.
HELPFILE - This is the pathname of the helpfile (actually, the
file that's displayed when a user chooses "About the
Gopher to X.500 Gateway").
LDAPHOST - This is the host that is running the ldap server.
If it's not on the localhost, you'll need to change this.
3) Make go500gw:
make
4) Start the ldap daemon:
ldapd [-c dsaname]
You only need to do this if you're not already running one.
5) Start go500gw either as a stand-alone server:
go500gw
or arrange to have it start from inetd:
# vi /etc/services /* add the following line */
go500gw 5555/tcp go500gw # go500gw server
# vi /etc/inetd.conf /* add the following line */
go500gw stream tcp nowait nobody $(ETCDIR)/go500gw go500gw -I
# kill -HUP <inetdpid> /* make inetd notice the change */
where $(ETCDIR) is replaced by the ETCDIR from the top level Makefile
and <inetdpid> is replaced by the pid of the inetd process.
6) Configure your local gopher server to have an entry for go500gw.
A sample .link file is given below, with the things you should
change given in <>'s:
Name=<Label of your choice>
Type=1
Port=7777
Path=M
Host=<host.running.go500gw.here>
You may also have to restart your gopher daemon, or remove
the .cache file.
If you want to start go500gw at some point in the X.500 tree
other than the root, you can change the Path parameter above
to something like this, for example:
Path=Mo=University of Michigan,c=US
Of course, you would substitute your own organization's DN.
7) Run a gopher client and try it out.

View file

@ -1,583 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#include <ac/param.h>
#include <ac/setproctitle.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <ldap.h>
#include <disptmpl.h>
#include "ldap_defaults.h"
#define ldap_debug debug
#include "ldap_log.h"
#include "lutil.h"
int debug;
int dosyslog;
int ldap_syslog;
int ldap_syslog_level;
int inetd;
int dtblsize;
char *ldaphost = NULL;
char *base = NULL;
int rdncount = GO500_RDNCOUNT;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
char myhost[MAXHOSTNAMELEN];
int myport;
static void usage ( char *name ) LDAP_GCCATTR((noreturn));
static int set_socket (int port);
static RETSIGTYPE wait4child(int sig);
static void do_queries (int s) LDAP_GCCATTR((noreturn));
static void do_error (FILE *fp, char *s);
static void do_search (LDAP *ld, FILE *fp, char *buf);
static void do_read (LDAP *ld, FILE *fp, char *dn);
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-d debuglevel] [-f filterfile] [-t templatefile]\r\n\t[-a] [-l] [-p port] [-x ldaphost] [-b searchbase] [-c rdncount]\r\n", name );
exit( EXIT_FAILURE );
}
int
main( int argc, char **argv )
{
int s, ns, rc;
int port = -1;
int i, pid;
char *myname;
fd_set readfds;
struct hostent *hp;
struct sockaddr_in from;
socklen_t fromlen;
#if defined( LDAP_PROCTITLE ) && !defined( HAVE_SETPROCTITLE )
/* for setproctitle */
Argv = argv;
Argc = argc;
#endif
while ( (i = getopt( argc, argv, "b:d:f:lp:c:t:x:I" )) != EOF ) {
switch( i ) {
case 'b': /* searchbase */
base = strdup( optarg );
break;
case 'd': /* debug level */
debug |= atoi( optarg );
break;
case 'f': /* ldap filter file */
filterfile = strdup( optarg );
break;
case 'l': /* log via LOG_LOCAL3 */
dosyslog = 1;
break;
case 'p': /* port to listen to */
port = atoi( optarg );
break;
case 'c': /* number of DN components to show */
rdncount = atoi( optarg );
break;
case 't': /* ldap template file */
templatefile = strdup( optarg );
break;
case 'x': /* ldap server hostname */
ldaphost = strdup( optarg );
break;
case 'I': /* run from inetd */
inetd = 1;
break;
default:
usage( argv[0] );
}
}
#ifdef GO500_HOSTNAME
strcpy( myhost, GO500_HOSTNAME );
#else
if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 )
== -1 ) {
perror( "gethostname" );
exit( EXIT_FAILURE );
}
myhost[sizeof(myhost)-1] = '\0';
#endif
#ifdef HAVE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
#elif HAVE_GETDTABLESIZE
dtblsize = getdtablesize();
#else
dtblsize = FD_SETSIZE;
#endif
#ifdef FD_SETSIZE
if (dtblsize > FD_SETSIZE) {
dtblsize = FD_SETSIZE;
}
#endif /* FD_SETSIZE*/
/* detach if stderr is redirected or no debugging */
if ( inetd == 0 )
lutil_detach( debug && !isatty( 1 ), 1 );
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
if ( debug ) {
ber_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
if ( dosyslog ) {
#ifdef LOG_LOCAL3
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
#elif LOG_DEBUG
openlog( myname, OPENLOG_OPTIONS );
#endif
}
if ( dosyslog )
syslog( LOG_INFO, "initializing" );
/* set up the socket to listen on */
if ( inetd == 0 ) {
s = set_socket( port );
/* arrange to reap children */
(void) SIGNAL( SIGCHLD, wait4child );
} else {
myport = GO500_PORT;
fromlen = sizeof(from);
if ( getpeername( 0, (struct sockaddr *) &from, &fromlen )
== 0 ) {
hp = gethostbyaddr( (char *) &(from.sin_addr),
sizeof(from.sin_addr), AF_INET );
Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
(hp == NULL) ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ), 0 );
if ( dosyslog ) {
syslog( LOG_INFO, "connection from %s (%s)",
(hp == NULL) ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ) );
}
#ifdef LDAP_PROCTITLE
setproctitle( "%s", hp == NULL ? inet_ntoa( from.sin_addr ) :
hp->h_name );
#endif
}
do_queries( 0 );
exit( EXIT_SUCCESS );
}
for ( ;; ) {
FD_ZERO( &readfds );
FD_SET( s, &readfds );
if ( (rc = select( dtblsize, &readfds, 0, 0 ,0 )) == -1 ) {
if ( debug ) perror( "select" );
continue;
} else if ( rc == 0 ) {
continue;
}
if ( ! FD_ISSET( s, &readfds ) )
continue;
fromlen = sizeof(from);
if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen ))
== -1 ) {
if ( debug ) perror( "accept" );
exit( EXIT_FAILURE );
}
hp = gethostbyaddr( (char *) &(from.sin_addr),
sizeof(from.sin_addr), AF_INET );
if ( dosyslog ) {
syslog( LOG_INFO, "TCP connection from %s (%s)",
(hp == NULL) ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ) );
}
switch( pid = fork() ) {
case 0: /* child */
tcp_close( s );
do_queries( ns );
break;
case -1: /* failed */
perror( "fork" );
break;
default: /* parent */
tcp_close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
}
}
/* NOT REACHED */
}
static int
set_socket( int port )
{
int s, one;
struct sockaddr_in addr;
if ( port == -1 )
port = GO500_PORT;
myport = port;
if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
perror( "socket" );
exit( EXIT_FAILURE );
}
#ifdef SO_REUSEADDR
/* set option so clients can't keep us from coming back up */
one = 1;
if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one) ) < 0 ) {
perror( "setsockopt" );
exit( EXIT_FAILURE );
}
#endif
#ifdef SO_KEEPALIVE
/* enable keep alives */
one = 1;
if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
sizeof(one) ) < 0 ) {
perror( "setsockopt" );
exit( EXIT_FAILURE );
}
#endif
/* bind to a name */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons( port );
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
perror( "bind" );
exit( EXIT_FAILURE );
}
/* listen for connections */
if ( listen( s, 5 ) == -1 ) {
perror( "listen" );
exit( EXIT_FAILURE );
}
if ( debug ) printf("tcp socket allocated, bound, and listening\n");
return( s );
}
static RETSIGTYPE
wait4child( int sig )
{
#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
if ( debug ) printf( "parent: catching child status\n" );
#ifdef HAVE_WAITPID
while (waitpid ((pid_t) -1, (int *) NULL, WAIT_FLAGS) > 0)
; /* NULL */
#else
while ( wait4((pid_t) -1, &status, WAIT_FLAGS, 0 ) > 0 )
; /* NULL */
#endif
(void) SIGNAL_REINSTALL ( SIGCHLD, wait4child );
}
static void
do_queries( int s )
{
char buf[1024], *query;
int len;
FILE *fp;
int rc;
struct timeval timeout;
fd_set readfds;
LDAP *ld;
if ( (fp = fdopen( s, "a+")) == NULL ) {
exit( EXIT_FAILURE );
}
timeout.tv_sec = GO500_TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO( &readfds );
FD_SET( fileno( fp ), &readfds );
if ( (rc = select( dtblsize, &readfds, 0, 0, &timeout )) <= 0 )
exit( EXIT_FAILURE );
if ( fgets( buf, sizeof(buf), fp ) == NULL )
exit( EXIT_FAILURE );
len = strlen( buf );
if ( debug ) {
fprintf( stderr, "got %d bytes\n", len );
#ifdef LDAP_DEBUG
ber_bprint( buf, len );
#endif
}
/* strip of \r \n */
if ( buf[len - 1] == '\n' )
buf[len - 1] = '\0';
len--;
if ( buf[len - 1] == '\r' )
buf[len - 1] = '\0';
len--;
query = buf;
/* strip off leading white space */
while ( isspace( (unsigned char) *query )) {
++query;
--len;
}
rewind(fp);
if ( *query == '~' || *query == '@' ) {
ld = NULL;
} else if ( (ld = ldap_init( ldaphost, 0 )) == NULL ) {
fprintf(fp,
"0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
LDAP_SERVER_DOWN, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
exit( EXIT_FAILURE );
} else {
int deref = GO500_DEREF;
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
rc = ldap_simple_bind_s( ld, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf(fp,
"0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
rc, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
exit( EXIT_FAILURE );
}
}
switch ( *query ) {
case '~':
fprintf( fp, "The query you specified was not specific enough, causing a size limit\r\n" );
fprintf( fp, "to be exceeded and the first several matches found to be returned.\r\n" );
fprintf( fp, "If you did not find the match you were looking for, try issuing a more\r\n" );
fprintf( fp, "specific query, for example one that contains both first and last name.\r\n" );
fprintf( fp, ".\r\n" );
break;
case '=':
do_read( ld, fp, ++query );
break;
case '@':
do_error( fp, ++query );
break;
default:
do_search( ld, fp, query );
break;
}
fprintf( fp, ".\r\n" );
rewind(fp);
if ( ld != NULL) {
ldap_unbind( ld );
}
exit( EXIT_FAILURE );
/* NOT REACHED */
}
static void
do_error( FILE *fp, char *s )
{
int code;
code = atoi( s );
fprintf( fp, "An error occurred searching X.500. The error code was %d\r\n", code );
fprintf( fp, "The corresponding error is: %s\r\n", ldap_err2string( code ) );
fprintf( fp, "No additional information is available\r\n" );
fprintf( fp, ".\r\n" );
}
static void
do_search( LDAP *ld, FILE *fp, char *buf )
{
char *dn, *rdn;
char **title;
int rc, matches = 0;
struct timeval tv;
LDAPFiltInfo *fi;
LDAPFiltDesc *filtd;
LDAPMessage *e, *res;
static char *attrs[] = { "title", 0 };
if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
exit( EXIT_FAILURE );
}
tv.tv_sec = GO500_TIMEOUT;
tv.tv_usec = 0;
for ( fi = ldap_getfirstfilter( filtd, "go500", buf );
fi != NULL;
fi = ldap_getnextfilter( filtd ) )
{
if ( (rc = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE,
fi->lfi_filter, attrs, 0, &tv, &res ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf(fp, "0An error occurred (explanation)\t@%d\t%s\t%d\r\n",
rc, myhost, myport );
ldap_getfilter_free( filtd );
return;
}
if ( (matches = ldap_count_entries( ld, res )) != 0 )
break;
}
ldap_getfilter_free( filtd );
if ( matches <= 0 ) {
return;
}
#ifdef GO500_SORT_ATTR
ldap_sort_entries( ld, &res, GO500_SORT_ATTR, strcasecmp );
#endif
for ( e = ldap_first_entry( ld, res ); e != NULL;
e = ldap_next_entry( ld, e ) ) {
char *s;
dn = ldap_get_dn( ld, e );
rdn = strdup( dn );
if ( (s = strchr( rdn, ',' )) != NULL )
*s = '\0';
if ( (s = strchr( rdn, '=' )) == NULL )
s = rdn;
else
++s;
title = ldap_get_values( ld, e, "title" );
if ( title != NULL ) {
char *p;
for ( p = title[0]; *p; p++ ) {
if ( *p == '/' )
*p = '\\';
}
}
fprintf( fp, "0%-20s %s\t=%s\t%s\t%d\r\n", s,
title ? title[0] : "", dn, myhost, myport );
if ( title != NULL )
ldap_value_free( title );
free( rdn );
free( dn );
}
if ( ldap_result2error( ld, res, 1 ) == LDAP_SIZELIMIT_EXCEEDED ) {
fprintf( fp, "0A size limit was exceeded (explanation)\t~\t%s\t%d\r\n",
myhost, myport );
}
}
static int
entry2textwrite( void *fp, char *buf, ber_len_t len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
static void
do_read( LDAP *ld, FILE *fp, char *dn )
{
static struct ldap_disptmpl *tmpllist;
ldap_init_templates( templatefile, &tmpllist );
if ( ldap_entry2text_search( ld, dn, base, NULL, tmpllist, NULL, NULL,
entry2textwrite, (void *) fp, "\r\n", rdncount,
LDAP_DISP_OPT_DOSEARCHACTIONS ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_entry2text_search" );
exit( EXIT_FAILURE );
}
if ( tmpllist != NULL ) {
ldap_free_templates( tmpllist );
}
}

View file

@ -1,915 +0,0 @@
/* $OpenLDAP$ */
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/time.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#include <ac/param.h>
#include <ac/setproctitle.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <ldap.h>
#include <disptmpl.h>
#define ldap_debug debug
#include "ldap_log.h"
#include "lutil.h"
#include "ldap_defaults.h"
int debug;
int ldap_syslog;
int ldap_syslog_level;
int dosyslog;
int inetd;
int dtblsize;
char *ldaphost = NULL;
int ldapport = 0;
int searchaliases = 1;
char *helpfile = GO500GW_HELPFILE;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
char *friendlyfile = FRIENDLYFILE;
int rdncount = GO500GW_RDNCOUNT;
static void usage ( char *name ) LDAP_GCCATTR((noreturn));
static int set_socket (int port);
static RETSIGTYPE wait4child(int sig);
static void do_queries (int s) LDAP_GCCATTR((noreturn));
static char *pick_oc ( char **oclist );
static int isnonleaf ( LDAP *ld, char **oclist, char *dn );
static void do_menu (LDAP *ld, FILE *fp, char *dn);
static void do_list (LDAP *ld, FILE *fp, char *dn);
static int isoc ( char **ocl, char *oc );
static int make_scope ( LDAP *ld, char *dn );
static void do_search (LDAP *ld, FILE *fp, char *query);
static int entry2textwrite( void *fp, char *buf, ber_len_t len );
static void do_read (LDAP *ld, FILE *fp, char *dn);
static void do_help (FILE *op);
static void do_sizelimit(FILE *fp, char type);
static void do_error (FILE *fp, char *s);
char myhost[MAXHOSTNAMELEN];
int myport = GO500GW_PORT;
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-d debuglevel] [-I] [-p port] [-P ldapport] [-l]\r\n\t[-x ldaphost] [-a] [-h helpfile] [-f filterfile] [-t templatefile] [-c rdncount]\r\n", name );
exit( EXIT_FAILURE );
}
int
main (int argc, char **argv )
{
int s, ns, rc;
int port = -1;
int i, pid;
char *myname;
fd_set readfds;
struct hostent *hp;
struct sockaddr_in from;
socklen_t fromlen;
#if defined( LDAP_PROCTITLE ) && !defined( HAVE_SETPROCTITLE )
/* for setproctitle */
Argv = argv;
Argc = argc;
#endif
while ( (i = getopt( argc, argv, "P:ad:f:h:lp:t:x:Ic:" )) != EOF ) {
switch( i ) {
case 'a': /* search aliases */
searchaliases = 0;
break;
case 'd': /* debugging level */
debug |= atoi( optarg );
break;
case 'f': /* ldap filter file */
filterfile = strdup( optarg );
break;
case 'h': /* gopher help file */
helpfile = strdup( optarg );
break;
case 'l': /* log to LOG_LOCAL3 */
dosyslog = 1;
break;
case 'p': /* port to listen on */
port = atoi( optarg );
break;
case 'P': /* port to connect to ldap server */
ldapport = atoi( optarg );
break;
case 't': /* ldap template file */
templatefile = strdup( optarg );
break;
case 'x': /* ldap server hostname */
ldaphost = strdup( optarg );
break;
case 'I': /* run from inetd */
inetd = 1;
break;
case 'c': /* count of DN components to show */
rdncount = atoi( optarg );
break;
default:
usage( argv[0] );
}
}
#ifdef HAVE_SYSCONF
dtblsize = sysconf( _SC_OPEN_MAX );
#elif HAVE_GETDTABLESIZE
dtblsize = getdtablesize();
#else
dtblsize = FD_SETSIZE;
#endif
#ifdef FD_SETSIZE
if ( dtblsize > FD_SETSIZE ) {
dtblsize = FD_SETSIZE;
}
#endif /* FD_SETSIZE*/
#ifdef GO500GW_HOSTNAME
strcpy( myhost, GO500GW_HOSTNAME );
#else
if ( myhost[0] == '\0' && gethostname( myhost, sizeof(myhost)-1 )
== -1 ) {
perror( "gethostname" );
exit( EXIT_FAILURE );
}
myhost[sizeof(myhost)-1] = '\0';
#endif
/* detach if stderr is redirected or no debugging */
if ( inetd == 0 )
lutil_detach( debug && !isatty( 1 ), 1 );
if ( (myname = strrchr( argv[0], '/' )) == NULL )
myname = strdup( argv[0] );
else
myname = strdup( myname + 1 );
if ( debug ) {
ber_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
if ( dosyslog ) {
#ifdef LOG_LOCAL3
openlog( myname, OPENLOG_OPTIONS, LOG_LOCAL3 );
#elif LOG_DEBUG
openlog( myname, OPENLOG_OPTIONS );
#endif
}
if ( dosyslog )
syslog( LOG_INFO, "initializing" );
/* set up the socket to listen on */
if ( inetd == 0 ) {
s = set_socket( port );
/* arrange to reap children */
(void) SIGNAL( SIGCHLD, wait4child );
}
if ( inetd ) {
fromlen = sizeof(from);
if ( getpeername( 0, (struct sockaddr *) &from, &fromlen )
== 0 ) {
hp = gethostbyaddr( (char *) &(from.sin_addr),
sizeof(from.sin_addr), AF_INET );
Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
(hp == NULL) ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ), 0 );
if ( dosyslog ) {
syslog( LOG_INFO, "connection from %s (%s)",
(hp == NULL) ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ) );
}
#ifdef LDAP_PROCTITLE
setproctitle( "%s", hp == NULL ? inet_ntoa( from.sin_addr ) :
hp->h_name );
#endif
}
do_queries( 0 );
tcp_close( 0 );
exit( EXIT_SUCCESS );
}
for ( ;; ) {
FD_ZERO( &readfds );
FD_SET( s, &readfds );
if ( (rc = select( dtblsize, &readfds, 0, 0 ,0 )) == -1 ) {
if ( debug ) perror( "select" );
continue;
} else if ( rc == 0 ) {
continue;
}
if ( ! FD_ISSET( s, &readfds ) )
continue;
fromlen = sizeof(from);
if ( (ns = accept( s, (struct sockaddr *) &from, &fromlen ))
== -1 ) {
if ( debug ) perror( "accept" );
exit( EXIT_FAILURE );
}
hp = gethostbyaddr( (char *) &(from.sin_addr),
sizeof(from.sin_addr), AF_INET );
if ( dosyslog ) {
syslog( LOG_INFO, "TCP connection from %s (%s)",
(hp == NULL) ? "unknown" : hp->h_name,
inet_ntoa( from.sin_addr ) );
}
switch( pid = fork() ) {
case 0: /* child */
tcp_close( s );
do_queries( ns );
break;
case -1: /* failed */
perror( "fork" );
break;
default: /* parent */
tcp_close( ns );
if ( debug )
fprintf( stderr, "forked child %d\n", pid );
break;
}
}
/* NOT REACHED */
}
static int
set_socket( int port )
{
int s, one;
struct sockaddr_in addr;
if ( port == -1 )
port = GO500GW_PORT;
myport = port;
if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
perror( "socket" );
exit( EXIT_FAILURE );
}
#ifdef SO_REUSEADDR
/* set option so clients can't keep us from coming back up */
one = 1;
if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
sizeof(one) ) < 0 ) {
perror( "setsockopt" );
exit( EXIT_FAILURE );
}
#endif
#ifdef SO_KEEPALIVE
/* enable keep alives */
one = 1;
if ( setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one,
sizeof(one) ) < 0 ) {
perror( "setsockopt" );
exit( EXIT_FAILURE );
}
#endif
/* bind to a name */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons( port );
if ( bind( s, (struct sockaddr *) &addr, sizeof(addr) ) ) {
perror( "bind" );
exit( EXIT_FAILURE );
}
/* listen for connections */
if ( listen( s, 5 ) == -1 ) {
perror( "listen" );
exit( EXIT_FAILURE );
}
if ( debug )
printf( "go500gw listening on port %d\n", port );
return( s );
}
static RETSIGTYPE
wait4child( int sig )
{
#ifndef HAVE_WAITPID
WAITSTATUSTYPE status;
#endif
if ( debug ) printf( "parent: catching child status\n" );
#ifdef HAVE_WAITPID
while (waitpid ((pid_t) -1, (int *) NULL, WAIT_FLAGS) > 0)
; /* NULL */
#else
while (wait4( (pid_t) -1, &status, WAIT_FLAGS, 0 ) > 0 )
; /* NULL */
#endif
(void) SIGNAL_REINSTALL ( SIGCHLD, wait4child );
}
static void
do_queries( int s )
{
char buf[1024], *query;
int len;
FILE *fp;
int rc;
int deref;
struct timeval timeout;
fd_set readfds;
LDAP *ld;
if ( (fp = fdopen( s, "a+")) == NULL ) {
perror( "fdopen" );
exit( EXIT_FAILURE );
}
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO( &readfds );
FD_SET( fileno( fp ), &readfds );
if ( (rc = select( dtblsize, &readfds, 0, 0, &timeout )) <= 0 )
exit( EXIT_FAILURE );
if ( fgets( buf, sizeof(buf), fp ) == NULL )
exit( EXIT_FAILURE );
len = strlen( buf );
if ( debug ) {
fprintf( stderr, "got %d bytes\n", len );
#ifdef LDAP_DEBUG
ber_bprint( buf, len );
#endif
}
/* strip of \r \n */
if ( buf[len - 1] == '\n' )
buf[len - 1] = '\0';
len--;
if ( buf[len - 1] == '\r' )
buf[len - 1] = '\0';
len--;
query = buf;
/* strip off leading white space */
while ( isspace( (unsigned char) *query )) {
++query;
--len;
}
rewind(fp);
if ( *query == 'H' || *query == 'L' || *query == 'E' ) {
switch ( *query++ ) {
case 'H': /* help file */
do_help( fp );
break;
case 'L': /* size limit explanation */
do_sizelimit( fp, *query );
break;
case 'E': /* error explanation */
do_error( fp, query );
break;
}
fprintf( fp, ".\r\n" );
rewind(fp);
exit( EXIT_SUCCESS );
/* NOT REACHED */
}
if ( (ld = ldap_init( ldaphost, ldapport )) == NULL ) {
if ( debug ) perror( "ldap_init" );
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
LDAP_SERVER_DOWN, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
exit( EXIT_FAILURE );
}
deref = LDAP_DEREF_ALWAYS;
if ( !searchaliases )
deref = LDAP_DEREF_FINDING;
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
if ( (rc = ldap_simple_bind_s( ld, NULL, NULL ))
!= LDAP_SUCCESS ) {
if ( debug ) ldap_perror( ld, "ldap_simple_bind_s" );
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
rc, myhost, myport );
fprintf( fp, ".\r\n" );
rewind(fp);
exit( EXIT_FAILURE );
}
switch ( *query++ ) {
case 'R': /* read an entry */
do_read( ld, fp, query );
break;
case 'S': /* search */
do_search( ld, fp, query );
break;
case 'M': /* X.500 menu */
do_menu( ld, fp, query );
break;
default:
do_menu( ld, fp, "" );
break;
}
fprintf( fp, ".\r\n" );
rewind(fp);
exit( EXIT_SUCCESS );
/* NOT REACHED */
}
static char *
pick_oc( char **oclist )
{
int i;
if ( oclist == NULL )
return( "unknown" );
for ( i = 0; oclist[i] != NULL; i++ ) {
if ( strcasecmp( oclist[i], "top" ) != 0 &&
strcasecmp( oclist[i], "quipuObject" ) != 0 &&
strcasecmp( oclist[i], "quipuNonLeafObject" ) != 0 )
return( oclist[i] );
}
return( "unknown" );
}
static int
isnonleaf( LDAP *ld, char **oclist, char *dn )
{
int i, quipuobject = 0;
if ( oclist == NULL )
return( 0 );
for ( i = 0; oclist[i] != NULL; i++ ) {
if ( strcasecmp( oclist[i], "quipuObject" ) == 0 )
quipuobject = 1;
if ( strcasecmp( oclist[i], "quipuNonLeafObject" ) == 0 ||
strcasecmp( oclist[i], "externalNonLeafObject" ) == 0 )
return( 1 );
}
/*
* not a quipu thang - no easy way to tell leaves from nonleaves
* except by trying to search or list. ldap only lets us search.
*/
/* expensive - just guess for now */
return( quipuobject ? 0 : 1 );
#ifdef notdef
if ( !quipuobject ) {
int rc, numentries;
struct timeval timeout;
LDAPMessage *res = NULL;
static char *attrs[] = { "objectClass", 0 };
int sizelimit = 1;
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
NULL, attrs, 0, &timeout, &res ))
== LDAP_SUCCESS || rc == LDAP_SIZELIMIT_EXCEEDED ) {
sizelimit = LDAP_NO_LIMIT;
ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit);
numentries = ldap_count_entries( ld, res );
if ( res != NULL )
ldap_msgfree( res );
return( numentries == 1 ? 1 : 0 );
}
}
return( 0 );
#endif
}
static void
do_menu( LDAP *ld, FILE *fp, char *dn )
{
char **s;
char *rdn = NULL;
LDAPFriendlyMap *fm = NULL;
if ( strcmp( dn, "" ) != 0 ) {
s = ldap_explode_dn( dn, 1 );
if ( s[1] == NULL )
rdn = ldap_friendly_name( friendlyfile, s[0], &fm );
else
rdn = s[0];
fprintf( fp, "0Read %s entry\tR%s\t%s\t%d\r\n", rdn ? rdn: s[0],
dn, myhost, myport );
ldap_value_free( s );
} else {
fprintf( fp, "0About the Gopher to X.500 Gateway\tH\t%s\t%d\r\n",
myhost, myport );
}
fprintf( fp, "7Search %s\tS%s\t%s\t%d\r\n", rdn ? rdn : "root", dn,
myhost, myport );
do_list( ld, fp, dn );
ldap_free_friendlymap( &fm );
}
static void
do_list( LDAP *ld, FILE *fp, char *dn )
{
int rc;
LDAPMessage *e, *res;
struct timeval timeout;
LDAPFriendlyMap *fm = NULL;
static char *attrs[] = { "objectClass", 0 };
int deref = LDAP_DEREF_FINDING;
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_ONELEVEL,
"(!(objectClass=dSA))", attrs, 0, &timeout, &res )) != LDAP_SUCCESS
&& rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
rc, myhost, myport );
return;
}
deref = LDAP_DEREF_ALWAYS;
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
if ( ldap_count_entries( ld, res ) < 1 ) {
return;
}
#ifdef GO500GW_SORT_ATTR
ldap_sort_entries( ld, &res, GO500GW_SORT_ATTR, strcasecmp );
#endif
fm = NULL;
for ( e = ldap_first_entry( ld, res ); e != NULL;
e = ldap_next_entry( ld, e ) ) {
char **s, **oc;
char *rdn, *doc;
dn = ldap_get_dn( ld, e );
s = ldap_explode_dn( dn, 1 );
oc = ldap_get_values( ld, e, "objectClass" );
doc = pick_oc( oc );
if ( strcasecmp( doc, "country" ) == 0 ) {
rdn = ldap_friendly_name( friendlyfile, s[0], &fm );
} else {
rdn = s[0];
}
if ( rdn == NULL ) {
rdn = s[0];
}
if ( strncasecmp( rdn, "{ASN}", 5 ) != 0 ) {
if ( isnonleaf( ld, oc, dn ) ) {
fprintf( fp, "1%s (%s)\tM%s\t%s\t%d\r\n", rdn,
doc, dn, myhost, myport );
} else {
fprintf( fp, "0%s (%s)\tR%s\t%s\t%d\r\n", rdn,
doc, dn, myhost, myport );
}
}
free( dn );
ldap_value_free( s );
ldap_value_free( oc );
}
ldap_free_friendlymap( &fm );
if ( ldap_result2error( ld, res, 1 ) == LDAP_SIZELIMIT_EXCEEDED ) {
fprintf( fp, "0A size limit was exceeded (explanation)\tLL\t%s\t%d\r\n",
myhost, myport );
}
}
static int
isoc( char **ocl, char *oc )
{
int i;
for ( i = 0; ocl[i] != NULL; i++ ) {
if ( strcasecmp( ocl[i], oc ) == 0 )
return( 1 );
}
return( 0 );
}
static int
make_scope( LDAP *ld, char *dn )
{
int scope;
char **oc;
LDAPMessage *res;
struct timeval timeout;
static char *attrs[] = { "objectClass", 0 };
if ( strcmp( dn, "" ) == 0 )
return( LDAP_SCOPE_ONELEVEL );
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
if ( ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL,
attrs, 0, &timeout, &res ) != LDAP_SUCCESS ) {
return( -1 );
}
oc = ldap_get_values( ld, ldap_first_entry( ld, res ), "objectClass" );
if ( isoc( oc, "organization" ) || isoc( oc, "organizationalUnit" ) )
scope = LDAP_SCOPE_SUBTREE;
else
scope = LDAP_SCOPE_ONELEVEL;
ldap_value_free( oc );
ldap_msgfree( res );
return( scope );
}
static void
do_search( LDAP *ld, FILE *fp, char *query )
{
int deref;
int scope;
char *base, *filter;
char *filtertype;
int count, rc;
struct timeval timeout;
LDAPFiltInfo *fi;
LDAPMessage *e, *res;
LDAPFiltDesc *filtd;
static char *attrs[] = { "objectClass", 0 };
if ( (filter = strchr( query, '\t' )) == NULL ) {
fprintf( fp, "3Missing filter!\r\n" );
exit( EXIT_FAILURE );
}
*filter++ = '\0';
base = query;
if ( (scope = make_scope( ld, base )) == -1 ) {
fprintf( fp, "3Bad scope\r\n" );
exit( EXIT_FAILURE );
}
filtertype = (scope == LDAP_SCOPE_ONELEVEL ?
"go500gw onelevel" : "go500gw subtree");
deref = (scope == LDAP_SCOPE_ONELEVEL ?
LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS);
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
timeout.tv_sec = GO500GW_TIMEOUT;
timeout.tv_usec = 0;
if ( (filtd = ldap_init_getfilter( filterfile )) == NULL ) {
fprintf( stderr, "Cannot open filter file (%s)\n",
filterfile );
exit( EXIT_FAILURE );
}
count = 0;
res = NULL;
for ( fi = ldap_getfirstfilter( filtd, filtertype, filter );
fi != NULL; fi = ldap_getnextfilter( filtd ) )
{
if ( (rc = ldap_search_st( ld, base, scope,
fi->lfi_filter, attrs, 0, &timeout, &res ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED ) {
fprintf(fp, "0An error occurred (explanation)\tE%d\t%s\t%d\r\n",
rc, myhost, myport );
return;
}
if ( (count = ldap_count_entries( ld, res )) != 0 )
break;
}
deref = LDAP_DEREF_ALWAYS;
ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
ldap_getfilter_free( filtd );
if ( count == 0 ) {
return;
}
if ( count == 1 ) {
char *dn, **oc;
e = ldap_first_entry( ld, res );
oc = ldap_get_values( ld, e, "objectClass" );
dn = ldap_get_dn( ld, e );
if ( isnonleaf( ld, oc, dn ) ) {
do_menu( ld, fp, dn );
free( dn );
return;
}
free( dn );
ldap_value_free( oc );
}
#ifdef GO500GW_SORT_ATTR
ldap_sort_entries( ld, &res, GO500GW_SORT_ATTR, strcasecmp );
#endif
for ( e = ldap_first_entry( ld, res ); e != NULL;
e = ldap_next_entry( ld, e ) ) {
char **s, **oc;
char *dn;
dn = ldap_get_dn( ld, e );
s = ldap_explode_dn( dn, 1 );
oc = ldap_get_values( ld, e, "objectClass" );
if ( isnonleaf( ld, oc, dn ) )
fprintf( fp, "1%s (%s)\tM%s\t%s\t%d\r\n", s[0],
pick_oc( oc ), dn, myhost, myport );
else
fprintf( fp, "0%s (%s)\tR%s\t%s\t%d\r\n", s[0],
pick_oc( oc ), dn, myhost, myport );
free( dn );
ldap_value_free( s );
ldap_value_free( oc );
}
if ( ldap_result2error( ld, res, 1 ) == LDAP_SIZELIMIT_EXCEEDED ) {
fprintf( fp, "0A size limit was exceeded (explanation)\tLS\t%s\t%d\r\n",
myhost, myport );
}
}
static int
entry2textwrite( void *fp, char *buf, ber_len_t len )
{
return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
}
static void
do_read( LDAP *ld, FILE *fp, char *dn )
{
static struct ldap_disptmpl *tmpllist;
ldap_init_templates( templatefile, &tmpllist );
if ( ldap_entry2text_search( ld, dn, NULL, NULL, tmpllist, NULL, NULL,
entry2textwrite,(void *) fp, "\r\n", rdncount, 0 )
!= LDAP_SUCCESS ) {
int ld_errno = 0;
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
fprintf(fp,
"0An error occurred (explanation)\t@%s\t%s\t%d\r\n",
ldap_err2string( ld_errno ), myhost, myport );
}
if ( tmpllist != NULL ) {
ldap_free_templates( tmpllist );
}
}
static void
do_help( FILE *op )
{
FILE *fp;
char line[BUFSIZ];
if ( (fp = fopen( helpfile, "r" )) == NULL ) {
fprintf( op, "Cannot access helpfile (%s)\r\n", helpfile );
return;
}
while ( fgets( line, sizeof(line), fp ) != NULL ) {
line[ strlen( line ) - 1 ] = '\0';
fprintf( op, "%s\r\n", line );
}
fclose( fp );
}
static void
do_sizelimit( FILE *fp, char type )
{
if ( type == 'S' ) {
fprintf( fp, "The query you specified was not specific enough, causing a size limit\r\n" );
fprintf( fp, "to be exceeded and the first several matches found to be returned.\r\n" );
fprintf( fp, "If you did not find the match you were looking for, try issuing a more\r\n" );
fprintf( fp, "specific query, for example one that contains both first and last name.\r\n" );
} else {
fprintf( fp, "Not all entries could be returned because a size limit was exceeded.\r\n" );
fprintf( fp, "There is no way to defeat this feature, but if you know who you are\r\n" );
fprintf( fp, "looking for, try choosing the \"Search\" option listed above and\r\n" );
fprintf( fp, "specifying the name of the person you want.\r\n" );
}
fprintf( fp, ".\r\n" );
}
static void
do_error( FILE *fp, char *s )
{
int code;
code = atoi( s );
fprintf( fp, "An error occurred searching X.500. The error code was %d\r\n", code );
fprintf( fp, "The corresponding error is: %s\r\n", ldap_err2string( code ) );
fprintf( fp, "No additional information is available\r\n" );
fprintf( fp, ".\r\n" );
}

View file

@ -1,22 +0,0 @@
This is a second pass at a general Gopher to X.500 gateway. It is
somewhat tailored to white pages usage, but is pretty general.
There are two modes of operation that the gateway supports: browsing
and searching. To browse, simply choose one of the countries,
organizations, etc. that appear in gopher as menu items. The next
level of the X.500 DIT will then be displayed. To search, choose the
search item (second choice in all menus) and type the name of whatever
it is you're looking for. At the upper levels of the tree (i.e. root
or country level) searches are assumed to be for organizations or
localities and are one-level in scope. At the lower levels of the tree
(i.e. organization or organizationalunit level) searches are assumed to
be for people and are subtree in scope. What sort of search is done
depends on what you type, but a variety of things are tried.
We would appreciate any feedback you can provide. If you have
problems, report them using our Issue Tracking System:
http://www.OpenLDAP.com/its/
or by sending e-mail to:
OpenLDAP-its@OpenLDAP.org
Additional mailing lists are available. Please see:
http://www.OpenLDAP.com/lists/

View file

@ -1,34 +0,0 @@
# $OpenLDAP$
UNIX_PRGS = rcpt500
PROGRAMS = $(@PLAT@_PRGS)
SRCS= main.c cmds.c help.c query.c
XSRCS= version.c
OBJS= main.o cmds.o help.o query.o
HDRS= rcpt500.h
LDAP_INCDIR= ../../include
LDAP_LIBDIR= ../../libraries
XLIBS = -lldap -llber -llutil
XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS)
rcpt500 : version.o
$(LTLINK) -o $@ version.o $(OBJS) $(LIBS)
version.c: ${OBJS} $(LDAP_LIBDEPEND)
@-$(RM) $@
$(MKVERSION) rcpt500 > $@
install-local: $(PROGRAMS) rcpt500.help FORCE
-$(MKDIR) $(DESTDIR)$(libexecdir) $(DESTDIR)$(datadir)
@( \
for prg in $(PROGRAMS); do \
$(LTINSTALL) $(INSTALLFLAGS) -s -m 755 $$prg$(EXEEXT) \
$(DESTDIR)$(libexecdir); \
done \
)
-$(MV) $(DESTDIR)$(datadir)/rcpt500.help $(DESTDIR)$(datadir)/rcpt500.help-
$(INSTALL) $(INSTALLFLAGS) -m 644 $(srcdir)/rcpt500.help $(DESTDIR)$(datadir)

View file

@ -1,112 +0,0 @@
OpenLDAP rcpt500 mail query server README
OVERVIEW
This is a mail-query server that answers LDAP white pages queries.
It is designed to be run out of your mail systems alias file, or the
equivalent. It expects to be fed the entire contents (including
headers) of an RFC822 message via standard input. It parses the
message, looking in the Subject: field or the body of the message
for a command that it recognizes.
The commands currently recognized are listed in the file cmd.c. They
all map into two actual operations the server performs: an X.500 query
or a help command. If no recognizable command is found in the
Subject: or body of the message, help is assumed. An appropriate
reply is sent to the sender of the message in response to the command.
The help command returns the contents of the file rcpt500.help. You
can modify the contents as appropriate for your local site.
The query command performs a series of LDAP searches to try to find
a person that matches the object of the query. If more than one
X.500 entry matches, a list is returned. If exactly one is matched,
detailed information is returned. Here is an example message and rcpt500
generated reply:
Query message:
Mail ldap-query@example.com
Subject: find tim howes
.
Reply from rcpt500:
Message-Id: <199209161526.AA12041@example.com>
Date: Wed, 16 Sep 1992 11:26:17 -0400
From: "LDAP Query Program" <ldap-query@example.com>
Subject: Re: find tim howes
In-Reply-To: Your message of "Wed, 16 Sep 1992 11:26:12 -0400"
<199209161526.AA26144@terminator.cc.example.com>
To: "Mark Smith" <mcs@terminator.cc.example.com>
One exact match was found for 'tim howes':
"Timothy A Howes, Information Technology Division, Faculty and Staff"
Also known as:
Timothy Howes
Timothy A Howes 1
Timothy A Howes
Tim Howes
E-mail address:
tim@terminator.cc.umich.edu
Fax number:
+1 313 764 5140 (argus building)
Business phone:
+1 313 747-4454
Business address:
ITD Research Systems
535 W William St.
Ann Arbor, MI 48103-4943
Title:
Systems Research Programmer II, Research Systems
Uniqname:
tim
If you want to try out rcpt500 yourself before installing it at your site,
send a message to ldap-query@umich.edu (we have a server running
there that serves University of Michigan white pages information).
CONFIGURING AND RUNNING rcpt500 AT YOUR LOCAL SITE
You will probably need to make changes to the file ldapconfig.h.edit to
configure rcpt500 for your local site. There are comments in the file
describing each variable you might need to change. Then type make in
the rcpt500 directory to make sure things are up to date. You will
need to install the rcpt500 binary and help files (make install). This
all assumes you have built the LDAP libraries already. If in doubt,
just do a make from the top of the LDAP distribution.
You will then need to set up an alias that your users can send mail
to that will feed the messages to rcpt500. At our site, we run sendmail
so the alias is in /usr/lib/aliases and looks like:
ldap-query: "|/usr/local/etc/rcpt500 -l"
The available command line options for rcpt500 are:
-l enable logging of requests via the syslog
LOG_DAEMON facility
-h ldaphost specify LDAP server host to connect to
-b searchbase specify starting point of LDAP searches
-a don't deference aliases during searches
-s stripcount remove "stripcount" DN components from user
friendly form names that are displayed
-z sizelimit return at most "sizelimit" entries
-u dapuser DN to bind to LDAP as when searching
The search and display behavior is defined in the ldapfilter.conf and
ldaptemplates.conf files.
FEEDBACK / PROBLEM REPORTS / DISCUSSIONS
The software is provided as is without any express or implied
warranty, but you can report problems using our Issue Tracking
System:
http://www.OpenLDAP.com/its/
or by sending e-mail to:
OpenLDAP-its@OpenLDAP.org
Mailing lists are available. Please see:
http://www.OpenLDAP.com/lists/

View file

@ -1,31 +0,0 @@
/* $OpenLDAP$ */
/*
* cmds.c: command table for rcpt500 (X.500 email query responder)
*
* 18 June 1992 by Mark C Smith
* Copyright (c) 1992 The Regents of The University of Michigan
* All Rights Reserved
*/
#include "portable.h"
#include <ac/stdlib.h>
#include "rcpt500.h"
struct command rcpt_cmds[] = {
"help", help_cmd, /* help must be the first command */
"query for", query_cmd, /* must come before "query for" */
"query", query_cmd,
"find", query_cmd,
"read", query_cmd,
"search for", query_cmd, /* must come before "search" */
"search", query_cmd,
"lookup", query_cmd,
"look up", query_cmd,
"show", query_cmd,
"finger", query_cmd,
"whois", query_cmd,
"who is", query_cmd,
"locate", query_cmd,
NULL, NULL /* end of command list */
};

View file

@ -1,52 +0,0 @@
/* $OpenLDAP$ */
/*
* help.c: for rcpt500 (X.500 email query responder)
*
* 16 June 1992 by Mark C Smith
* Copyright (c) 1992 The Regents of The University of Michigan
* All Rights Reserved
*/
#include "portable.h"
#include <stdio.h>
#include <ac/syslog.h>
#include <ac/string.h>
#include <ac/unistd.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include "ldap_defaults.h"
#include "rcpt500.h"
int
help_cmd(struct msginfo *msgp, char *reply)
{
int fd, len;
if (( fd = open( RCPT500_HELPFILE, O_RDONLY )) == -1 ) {
if ( dosyslog ) {
syslog( LOG_ERR, "open help file: %m" );
}
strcat( reply, "Unable to access the help file. Sorry!\n" );
return( 0 );
}
len = read( fd, reply + strlen( reply ), MAXSIZE );
close( fd );
if ( len == -1 ) {
if ( dosyslog ) {
syslog( LOG_ERR, "read help file: %m" );
}
strcat( reply, "Unable to read the help file. Sorry!\n" );
return( 0 );
}
*(reply + len ) = '\0';
return( 0 );
}

View file

@ -1,365 +0,0 @@
/* $OpenLDAP$ */
/*
* main.c: for rcpt500 (X.500 email query responder)
*
* 16 June 1992 by Mark C Smith
* Copyright (c) 1992 The Regents of The University of Michigan
* All Rights Reserved
*/
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/signal.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/unistd.h>
#include "ldap_defaults.h"
#include "rcpt500.h"
int dosyslog = 0;
int derefaliases = 1;
int sizelimit = RCPT500_SIZELIMIT;
int rdncount = RCPT500_RDNCOUNT;
int ldapport = 0;
char *ldaphost = NULL;
char *searchbase = NULL;
char *dapuser = NULL;
char *filterfile = FILTERFILE;
char *templatefile = TEMPLATEFILE;
static char reply[ MAXSIZE * RCPT500_LISTLIMIT ];
/*
* functions
*/
static int read_msg(FILE *fp, struct msginfo *msgp);
static char *read_hdr(FILE *fp, int off, char *buf, int MAXSIZEe, char **ln_p);
static int send_reply(struct msginfo *msgp, char *body);
static int find_command(char *text, char **argp);
/*
* main is invoked by sendmail via the alias file
* the entire incoming message gets piped to our standard input
*/
int
main( int argc, char **argv )
{
char *prog, *usage = "%s [-l] [-U] [-h ldaphost] [-p ldapport] [-b searchbase] [-a] [-z sizelimit] [-u dapuser] [-f filterfile] [-t templatefile] [-c rdncount]\n";
struct msginfo msg;
int c, errflg;
*reply = '\0';
if (( prog = strrchr( argv[ 0 ], '/' )) == NULL ) {
prog = strdup( argv[ 0 ] );
} else {
prog = strdup( prog + 1 );
}
errflg = 0;
while (( c = getopt( argc, argv, "alh:b:s:z:f:t:p:c:" )) != EOF ) {
switch( c ) {
case 'a':
derefaliases = 0;
break;
case 'l':
dosyslog = 1;
break;
case 'b':
searchbase = optarg;
break;
case 'h':
ldaphost = optarg;
break;
case 'p':
ldapport = atoi( optarg );
break;
case 'z':
sizelimit = atoi( optarg );
break;
case 'u':
dapuser = optarg;
break;
case 'f':
filterfile = optarg;
break;
case 't':
templatefile = optarg;
break;
case 'c':
rdncount = atoi( optarg );
break;
default:
++errflg;
}
}
if ( errflg || optind < argc ) {
fprintf( stderr, usage, prog );
exit( EXIT_FAILURE );
}
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
if ( dosyslog ) {
/*
* if syslogging requested, initialize
*/
#ifdef LOG_DAEMON
openlog( prog, OPENLOG_OPTIONS, LOG_DAEMON );
#elif LOG_DEBUG
openlog( prog, OPENLOG_OPTIONS );
#endif
}
if ( read_msg( stdin, &msg ) < 0 ) {
if ( dosyslog ) {
syslog( LOG_INFO, "unparseable message ignored" );
}
exit( 0 ); /* so as not to give sendmail an error */
}
if ( dosyslog ) {
syslog( LOG_INFO, "processing command \"%s %s\" from %s",
( msg.msg_command < 0 ) ? "Unknown" :
rcpt_cmds[ msg.msg_command ].cmd_text,
( msg.msg_arg == NULL ) ? "" : msg.msg_arg, msg.msg_replyto );
}
if ( msg.msg_command < 0 ) {
msg.msg_command = 0; /* unknown command == help command */
}
/*
sprintf( reply, "Your request was interpreted as: %s %s\n\n",
rcpt_cmds[ msg.msg_command ].cmd_text, msg.msg_arg );
*/
(*rcpt_cmds[ msg.msg_command ].cmd_handler)( &msg, reply );
if ( send_reply( &msg, reply ) < 0 ) {
if ( dosyslog ) {
syslog( LOG_INFO, "reply failed: %m" );
}
exit( 0 ); /* so as not to give sendmail an error */
}
if ( dosyslog ) {
syslog( LOG_INFO, "reply OK" );
}
exit( 0 );
}
static int
read_msg( FILE *fp, struct msginfo *msgp )
{
char buf[ MAXSIZE ], *line;
int command = -1;
msgp->msg_replyto = msgp->msg_date = msgp->msg_subject = NULL;
line = NULL;
while( 1 ) {
if ( line == NULL ) {
if (( line = fgets( buf, MAXSIZE, fp )) == NULL ) {
break;
}
buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
}
if ( *buf == '\0' ) { /* start of message body */
break;
}
if ( strncasecmp( buf, "Reply-To:", 9 ) == 0 ) {
if ( msgp->msg_replyto != NULL ) {
free( msgp->msg_replyto );
}
msgp->msg_replyto = read_hdr( fp, 9, buf, MAXSIZE, &line );
} else if ( strncasecmp( buf, "From:", 5 ) == 0 &&
msgp->msg_replyto == NULL ) {
msgp->msg_replyto = read_hdr( fp, 5, buf, MAXSIZE, &line );
} else if ( strncasecmp( buf, "Date:", 5 ) == 0 ) {
msgp->msg_date = read_hdr( fp, 5, buf, MAXSIZE, &line );
} else if ( strncasecmp( buf, "Message-ID:", 5 ) == 0 ) {
msgp->msg_messageid = read_hdr( fp, 11, buf, MAXSIZE, &line );
} else if ( strncasecmp( buf, "Subject:", 8 ) == 0 ) {
if (( msgp->msg_subject =
read_hdr( fp, 8, buf, MAXSIZE, &line )) != NULL ) {
command = find_command( msgp->msg_subject, &msgp->msg_arg );
}
} else {
line = NULL; /* discard current line */
}
}
while ( command < 0 && line != NULL ) {
/*
* read the body of the message, looking for commands
*/
if (( line = fgets( buf, MAXSIZE, fp )) != NULL ) {
buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
command = find_command( buf, &msgp->msg_arg );
}
}
if ( msgp->msg_replyto == NULL ) {
return( -1 );
}
msgp->msg_command = command;
return( 0 );
}
static char *
read_hdr( FILE *fp, int offset, char *buf, int MAXSIZEe, char **linep )
{
char *hdr;
for ( hdr = buf + offset; isspace( (unsigned char) *hdr ); ++hdr ) {
;
}
if (( hdr = strdup( hdr )) == NULL ) {
if ( dosyslog ) {
syslog( LOG_ERR, "strdup: %m" );
}
exit( EXIT_FAILURE );
}
while ( 1 ) {
*linep = fgets( buf, MAXSIZE, fp );
buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
if ( *linep == NULL || !isspace( (unsigned char) **linep )) {
break;
}
if (( hdr = realloc( hdr, strlen( hdr ) +
strlen( *linep ) + 3 )) == NULL) {
if ( dosyslog ) {
syslog( LOG_ERR, "realloc: %m" );
}
exit( EXIT_FAILURE );
}
strcat( hdr, "\n" );
strcat( hdr, *linep );
}
return( hdr );
}
static int
send_reply( struct msginfo *msgp, char *body )
{
char buf[ MAXSIZE ];
FILE *cmdpipe;
int rc;
if (( cmdpipe = popen( RCPT500_PIPEMAILCMD, "w" )) == NULL ) {
if ( dosyslog ) {
syslog( LOG_ERR, "popen pipemailcmd failed: %m" );
}
return( -1 );
}
/*
* send the headers
*/
sprintf( buf, "From: %s\n", RCPT500_FROM );
rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
if ( rc == 1 ) {
if ( msgp->msg_subject != NULL ) {
sprintf( buf, "Subject: Re: %s\n", msgp->msg_subject );
} else {
sprintf( buf, "Subject: query response\n" );
}
rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
}
if ( rc == 1 && msgp->msg_date != NULL ) {
/*
* add "In-reply-to:" header
*/
if ( msgp->msg_messageid == NULL ) {
sprintf( buf, "In-reply-to: Your message of \"%s\"\n",
msgp->msg_date );
} else {
sprintf( buf,
"In-reply-to: Your message of \"%s\"\n %s\n",
msgp->msg_date, msgp->msg_messageid );
}
rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
}
if ( rc == 1 ) {
sprintf( buf, "To: %s\n", msgp->msg_replyto );
rc = fwrite( buf, strlen( buf ), 1, cmdpipe );
}
/*
* send the header/body separator (blank line)
*/
if ( rc == 1 ) {
rc = fwrite( "\n", 1, 1, cmdpipe );
}
/*
* send the body
*/
if ( rc == 1 ) {
rc = fwrite( body, strlen( body ), 1, cmdpipe );
}
if ( rc != 1 && dosyslog ) {
syslog( LOG_ERR, "write to binmail failed: %m" );
}
if ( pclose( cmdpipe ) < 0 ) {
if ( dosyslog ) {
syslog( LOG_ERR, "pclose binmail failed: %m" );
}
return( -1 );
}
return( rc == 1 ? 0 : -1 );
}
static int
find_command( char *text, char **argp )
{
int i;
char *s, *p;
static char argbuf[ MAXSIZE ];
p = text;
for ( s = argbuf; *p != '\0'; ++p ) {
*s++ = TOLOWER( (unsigned char) *p );
}
*s = '\0';
for ( i = 0; rcpt_cmds[ i ].cmd_text != NULL; ++i ) {
if (( s = strstr( argbuf, rcpt_cmds[ i ].cmd_text )) != NULL
&& isspace( (unsigned char) s[ strlen( rcpt_cmds[ i ].cmd_text ) ] )) {
strcpy( argbuf, text + (s - argbuf) + strlen( rcpt_cmds[ i ].cmd_text ));
*argp = argbuf;
while ( isspace( (unsigned char) **argp )) {
++(*argp);
}
return( i );
}
}
return( -1 );
}

View file

@ -1,291 +0,0 @@
/* $OpenLDAP$ */
/*
* query.c: for rcpt500 (X.500 email query responder)
*
* 18 June 1992 by Mark C Smith
* Copyright (c) 1992 The Regents of The University of Michigan
* All Rights Reserved
*/
#include "portable.h"
#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/time.h>
#include <stdio.h>
#include <ldap.h>
#include <disptmpl.h>
#include "rcpt500.h"
#include "ldap_defaults.h"
static char buf[ MAXSIZE ];
static char *errpreface = "Your query failed: ";
static void close_ldap(LDAP *ld);
static void append_entry_list(char *rep, char *qu, LDAP *ld, LDAPMessage *msg);
static int append_text(void *reply, char *text, ber_len_t len);
static int do_read (LDAP *ld, char *dn, char *rep, struct ldap_disptmpl *tmp);
static void report_ldap_err (LDAP *ldp, char *reply);
static void remove_trailing_space (char *s);
int
query_cmd( struct msginfo *msgp, char *reply )
{
LDAP *ldp;
LDAPMessage *ldmsgp, *entry;
char *dn;
int matches, rc, ld_errno;
LDAPFiltDesc *lfdp;
LDAPFiltInfo *lfi;
struct ldap_disptmpl *tmpllist = NULL;
static char *attrs[] = { "cn", "title",
#ifdef RCPT500_SORT_ATTR
RCPT500_SORT_ATTR,
#endif
NULL };
if ( msgp->msg_arg == NULL ) {
return( help_cmd( msgp, reply ));
}
remove_trailing_space( msgp->msg_arg );
if ( *msgp->msg_arg == '\0' ) {
return( help_cmd( msgp, reply ));
}
if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
strcat( reply, errpreface );
strcat( reply, "filter file configuration error. Try again later." );
return( 0 );
}
/*
* open connection to LDAP server and bind as dapuser
*/
ldp = ldap_init( ldaphost, ldapport );
if ( ldp == NULL ) {
strcat( reply, errpreface );
strcat( reply, "X.500 service unavailable. Try again later." );
ldap_getfilter_free( lfdp );
return( 0 );
}
if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
report_ldap_err( ldp, reply );
close_ldap( ldp );
ldap_getfilter_free( lfdp );
return( 0 );
}
/*
* set options for search and build filter
*/
ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
matches = 0;
for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
lfi->lfi_filter, attrs, 0, &ldmsgp );
if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
&& rc != LDAP_TIMELIMIT_EXCEEDED ) {
report_ldap_err( ldp, reply );
close_ldap( ldp );
ldap_getfilter_free( lfdp );
return( 0 );
}
if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
break;
}
if ( ldmsgp != NULL ) {
ldap_msgfree( ldmsgp );
}
}
if ( matches == 0 ) {
sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
strcat( reply, buf );
close_ldap( ldp );
ldap_getfilter_free( lfdp );
return( 0 );
}
ld_errno = 0;
ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
|| ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
strcat( reply, "(Partial results only - a limit was exceeded)\n" );
}
if ( matches <= RCPT500_LISTLIMIT ) {
sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
lfi->lfi_desc,
( matches > 1 ) ? "es" : "", msgp->msg_arg );
strcat( reply, buf );
if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
errpreface, templatefile, rc );
strcat( reply, buf );
}
for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
dn = ldap_get_dn( ldp, entry );
if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
report_ldap_err( ldp, reply );
}
free( dn );
if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
strcat( reply, "\n-------\n\n" );
}
}
if ( tmpllist != NULL ) {
ldap_free_templates( tmpllist );
}
ldap_msgfree( ldmsgp );
} else {
sprintf( buf, "%d %s matches were found for '%s':\n",
matches, lfi->lfi_desc, msgp->msg_arg );
strcat( reply, buf );
append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
ldap_msgfree( ldmsgp );
}
close_ldap( ldp );
ldap_getfilter_free( lfdp );
return( 0 );
}
static void
close_ldap( LDAP *ld )
{
ldap_unbind( ld );
}
static void
append_entry_list( char *reply, char *query, LDAP *ldp, LDAPMessage *ldmsgp )
{
LDAPMessage *e;
char *dn, *rdn, *s, **title;
int free_rdn = 0;
#ifdef RCPT500_SORT_ATTR
ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
#endif
for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
e = ldap_next_entry( ldp, e )) {
dn = ldap_get_dn( ldp, e );
if (( s = strchr( dn, ',' )) != NULL ) {
*s = '\0';
}
if (( s = strchr( dn, '=' )) == NULL ) {
rdn = dn;
} else {
rdn = s + 1;
}
#ifdef UOFM
/*
* if this entry's rdn is an exact match for the thing looked up, we
* return the CN that has a digit after it, so that the user is
* returned something guaranteed to yield exactly one match if they
* pick it from the list and query it
*/
if ( strcasecmp( rdn, query ) == 0 ) {
char **cn;
int i;
if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
for ( i = 0; cn[i] != NULL; i++ ) {
if ( isdigit((unsigned char) cn[i][strlen( cn[i] ) - 1])) {
rdn = strdup( cn[i] );
free_rdn = 1;
break;
}
}
ldap_value_free( cn );
}
}
#endif /* UOFM */
title = ldap_get_values( ldp, e, "title" );
sprintf( buf, " %-20s %s\n", rdn, title ? title[0] : "" );
strcat( reply, buf );
if ( title != NULL ) {
ldap_value_free( title );
}
free( dn );
if ( free_rdn ) {
free( rdn );
}
}
}
static int
append_text( void *reply, char *text, ber_len_t len )
{
strcat( (char *) reply, text );
return( len );
}
static int
do_read( LDAP *ldp, char *dn, char *reply, struct ldap_disptmpl *tmpll )
{
int rc;
static char *maildefvals[] = { "None registered in this service", NULL };
static char *defattrs[] = { "mail", NULL };
static char **defvals[] = { maildefvals, NULL };
rc = ldap_entry2text_search( ldp, dn, searchbase, NULL, tmpll,
defattrs, defvals, append_text, (void *)reply, "\n",
rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
return( rc );
}
static void
report_ldap_err( LDAP *ldp, char *reply )
{
int ld_errno = 0;
ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
strcat( reply, errpreface );
strcat( reply, ldap_err2string( ld_errno ));
strcat( reply, "\n" );
}
static void
remove_trailing_space( char *s )
{
char *p = s + strlen( s ) - 1;
while ( isspace( (unsigned char) *p ) && p > s ) {
--p;
}
*(++p) = '\0';
}

View file

@ -1,57 +0,0 @@
/* $OpenLDAP$ */
/*
* rcpt500.h: includes for rcpt500 (X.500 email query responder)
*
* 16 June 1992 by Mark C Smith
* Copyright (c) 1992 The Regents of The University of Michigan
* All Rights Reserved
*/
#include <ldap_cdefs.h>
LDAP_BEGIN_DECL
struct msginfo {
char *msg_subject;
char *msg_replyto; /* actually could be from From: line */
char *msg_date;
char *msg_messageid;
int msg_command;
char *msg_arg;
};
struct command {
char *cmd_text; /* text for command, e.g. "HELP" */
/* pointer to handler function */
int (*cmd_handler) LDAP_P((struct msginfo *msgp, char *reply));
};
#define MAXSIZE 8096
/*
* functions
*/
int help_cmd LDAP_P((struct msginfo *msgp, char *reply));
int query_cmd LDAP_P((struct msginfo *msgp, char *reply));
/*
* externs
*/
/* cmds.c */
extern struct command rcpt_cmds[];
/* main.c */
extern int dosyslog;
extern int derefaliases;
extern int sizelimit;
extern int rdncount;
extern int ldapport;
extern char *ldaphost;
extern char *searchbase;
extern char *dapuser;
extern char *filterfile;
extern char *templatefile;
LDAP_END_DECL

View file

@ -1,48 +0,0 @@
How to use the OpenLDAP LDAP Email Query Service
By sending electronic mail to the address:
ldap-query@example.com
you can access the campus LDAP Directory. The Directory contains
information about all faculty, staff, and students of the University,
including phone numbers, mailing addresses, job titles, email
addresses, and more.
To query the service, send a piece of email to this address with a
command similar to:
find <name>
e.g. find robert jones
somewhere in the Subject: field or anywhere in the body (text) of the
message. You will receive a reply that contains information about the
target of your query (in the above example, you would get information
on all "robert jones" who are at the University). The <name> can be
a person's full name, last name, or uniqname. An search for exact
matches is first tried; if there are no exact matches, an approximate
search (using soundex rules) is done.
If your query matches exactly one person, you will receive detailed
information about that person. If more than one is matched, a list will
be returned that should hopefully provide you with enough information
to be able to determine which individual you really want. Another
query can then be made to obtain the detailed information.
This service understands a number of synonyms for the "find" command,
including: "whois", "search", "look up", "show." You can also send
a message with the word "help" in it to get this text returned to you.
Note that this service is entirely automated -- no humans will respond
to requests or other email sent here.
We would appreciate any feedback you can provide.
If you have problems, report them using our Issue Tracking System:
http://www.OpenLDAP.com/its/
or by sending e-mail to:
OpenLDAP-its@OpenLDAP.org
Additional mailing lists are available. Please see:
http://www.OpenLDAP.com/lists/
This is the end of the help text.