mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-26 09:39:45 -05:00
Major clients cleanout
This commit is contained in:
parent
9e3613228e
commit
0e1c9551a9
21 changed files with 1 additions and 4998 deletions
|
|
@ -4,4 +4,4 @@
|
|||
##
|
||||
## Clients Makefile.in for OpenLDAP
|
||||
|
||||
SUBDIRS= tools ud finger gopher mail500 fax500 rcpt500 maildap
|
||||
SUBDIRS= tools ud finger mail500 maildap
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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] : "" );
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -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" );
|
||||
}
|
||||
|
|
@ -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/
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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/
|
||||
|
|
@ -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 */
|
||||
};
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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';
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
Loading…
Reference in a new issue