From: Kurt Zeilenga Date: Sat, 7 Jul 2001 05:05:38 +0000 (+0000) Subject: Major clients cleanout X-Git-Tag: LDBM_PRE_GIANT_RWLOCK~1255 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=0e1c9551a9b810b1b31289a992ac5844b611a60b;p=openldap Major clients cleanout --- diff --git a/clients/Makefile.in b/clients/Makefile.in index 5bc6b69eb7..8880a410f5 100644 --- a/clients/Makefile.in +++ b/clients/Makefile.in @@ -4,4 +4,4 @@ ## ## Clients Makefile.in for OpenLDAP -SUBDIRS= tools ud finger gopher mail500 fax500 rcpt500 maildap +SUBDIRS= tools ud finger mail500 maildap diff --git a/clients/fax500/Makefile.in b/clients/fax500/Makefile.in deleted file mode 100644 index eefd45123c..0000000000 --- a/clients/fax500/Makefile.in +++ /dev/null @@ -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 diff --git a/clients/fax500/README b/clients/fax500/README deleted file mode 100644 index 5b0e1a35dc..0000000000 --- a/clients/fax500/README +++ /dev/null @@ -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 diff --git a/clients/fax500/fax500.h b/clients/fax500/fax500.h deleted file mode 100644 index f494e107b6..0000000000 --- a/clients/fax500/fax500.h +++ /dev/null @@ -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 diff --git a/clients/fax500/faxtotpc.c b/clients/fax500/faxtotpc.c deleted file mode 100644 index 1579c84fde..0000000000 --- a/clients/fax500/faxtotpc.c +++ /dev/null @@ -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 - -#include -#include -#include - -#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); -} diff --git a/clients/fax500/main.c b/clients/fax500/main.c deleted file mode 100644 index 8362a7b520..0000000000 --- a/clients/fax500/main.c +++ /dev/null @@ -1,1496 +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 - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif - -#include - -#include "fax500.h" -#include "ldap_defaults.h" - -#define USER 0 -#define GROUP_ERRORS 1 -#define GROUP_REQUEST 2 -#define GROUP_MEMBERS 3 - -#define ERRORS "errors" -#define REQUEST "request" -#define MEMBERS "members" - -LDAP *ld; -char *errorsfrom = NULL; -char *mailfrom = NULL; -char *host = NULL; -int hostlen = 0; - -int identity; -#define MAIL500 1 -#define FAX500 2 - -typedef struct errs { - int e_code; -#define E_USERUNKNOWN 1 -#define E_AMBIGUOUS 2 -#define E_NOEMAIL 3 -#define E_NOREQUEST 4 -#define E_NOERRORS 5 -#define E_BADMEMBER 6 -#define E_JOINMEMBERNOEMAIL 7 -#define E_MEMBERNOEMAIL 8 -#define E_NOFAXNUM 9 -#define E_JOINMEMBERNOFAXNUM 10 -#define E_MEMBERNOFAXNUM 11 -#define E_FAXTOEMAILMBR 12 - - char *e_addr; - LDAPMessage *e_msg; -} Error; - -typedef struct groupto { - char *g_dn; - char *g_errorsto; - char **g_members; -} Group; - -typedef struct baseinfo { - char *b_dn; /* dn to start searching at */ - char b_rdnpref; /* give rdn's preference when searching? */ - char *b_filter[3]; /* filter to apply - name substituted for %s */ - /* (up to three of them) */ -} Base; - -Base base[] = - { "ou=People, o=University of Michigan, c=US", 0, - "uid=%s", "cn=%s", NULL, - "ou=System Groups, ou=Groups, o=University of Michigan, c=US", 1, - "(&(cn=%s)(associatedDomain=%h))", NULL, NULL, - "ou=User Groups, ou=Groups, o=University of Michigan, c=US", 1, - "(&(cn=%s)(associatedDomain=%h))", NULL, NULL, - NULL - }; - -char *sendmailargs[] = { FAX_SENDMAIL, "-oMrX.500", "-odi", "-oi", "-f", NULL, NULL }; - -static char *attrs[] = { "objectClass", "title", "postaladdress", - "telephoneNumber", "mail", "description", - "errorsTo", "rfc822ErrorsTo", "requestsTo", - "rfc822RequestsTo", "joinable", "cn", "member", - "facsimileTelephoneNumber", NULL }; - - -static void do_address(char *name, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr, int type); -static int do_group(LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr); -static void do_group_members(LDAPMessage *e, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr); -static void send_message(char **to); -static void send_errors(Error *err, int nerr); -static void do_noemailorfax(FILE *fp, Error *err, int namelen, int errtype); -static void do_ambiguous(FILE *fp, Error *err, int namelen); -static int count_values(char **list); -static void add_to(char ***list, int *nlist, char **new); -static int isgroup(LDAPMessage *e); -static void add_error(Error **err, int *nerr, int code, char *addr, LDAPMessage *msg); -static void add_group(char *dn, Group **list, int *nlist); -static void unbind_and_exit(int rc) LDAP_GCCATTR((noreturn)); -static int group_loop(char *dn); -static void send_group(Group *group, int ngroup); -static int has_attributes(LDAPMessage *e, char *attr1, char *attr2); -static char **get_attributes_mail_dn(LDAPMessage *e, char *attr1, char *attr2); -static char *canonical(char *s); -static int connect_to_x500 (void); -static void do_group_errors (LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr); -static void do_group_request (LDAPMessage *e, char *dn, char ***to, int *nto, Error **err, int *nerr); -static void add_member (char *gdn, char *dn, char ***to, int *nto, Group **togroups, int *ngroups, Error **err, int *nerr); - - -int -main ( int argc, char **argv ) -{ - char *myname; - char **tolist; - Error *errlist; - Group *togroups; - int numto, ngroups, numerr, nargs; - int i, j; - - while ( (i = getopt( argc, argv, "f:h:m:" )) != EOF ) { - switch( i ) { - case 'f': /* who it's from & where errors should go */ - mailfrom = strdup( optarg ); - for ( j = 0; sendmailargs[j] != NULL; j++ ) { - if ( strcmp( sendmailargs[j], "-f" ) == 0 ) { - sendmailargs[j+1] = mailfrom; - break; - } - } - break; - - case 'h': /* hostname */ - host = strdup( optarg ); - hostlen = strlen(host); - break; - - /* mailer-daemon address - who we should */ - case 'm': /* say errors come from */ - errorsfrom = strdup( optarg ); - break; - - default: - syslog( LOG_ALERT, "unknown option" ); - break; - } - } - - if ( (myname = strrchr( argv[0], '/' )) == NULL ) - myname = strdup( argv[0] ); - else - myname = strdup( myname + 1 ); - if (!strcmp(myname, "mail500")) { - identity = MAIL500; - } else if (!strcmp(myname, "fax500")) { - identity = FAX500; - } else { - /* I give up, I must be mail500 */ - identity = MAIL500; - } - -#ifdef SIGPIPE - (void) SIGNAL( SIGPIPE, SIG_IGN ); -#endif - -#ifdef LOG_MAIL - openlog( myname, OPENLOG_OPTIONS, LOG_MAIL ); -#elif LOG_DEBUG - openlog( myname, OPENLOG_OPTIONS ); -#endif - - if ( mailfrom == NULL ) { - syslog( LOG_ALERT, "required argument -f not present" ); - exit( EX_TEMPFAIL ); - } - if ( errorsfrom == NULL ) { - syslog( LOG_ALERT, "required argument -m not present" ); - exit( EX_TEMPFAIL ); - } - if ( host == NULL ) { - syslog( LOG_ALERT, "required argument -h not present" ); - exit( EX_TEMPFAIL ); - } - - if ( connect_to_x500() != 0 ) - exit( EX_TEMPFAIL ); - - setuid( geteuid() ); -/* -{ - char buf[1024]; - int i; - - strcpy( buf, argv[0] ); - for ( i = 1; i < argc; i++ ) { - strcat( buf, " " ); - strcat( buf, argv[i] ); - } - - syslog( LOG_ALERT, "args: (%s)", buf ); -} -*/ - numto = 0; - add_to( &tolist, &numto, sendmailargs ); - nargs = numto; - ngroups = numerr = 0; - togroups = NULL; - errlist = NULL; - for ( i = optind; i < argc; i++ ) { - char *s; - int type; - - for ( j = 0; argv[i][j] != '\0'; j++ ) { - if ( argv[i][j] == '.' || argv[i][j] == '_' ) - argv[i][j] = ' '; - } - - type = USER; - if ( (s = strrchr( argv[i], '-' )) != NULL ) { - s++; - - if ( strcmp( s, ERRORS ) == 0 ) { - type = GROUP_ERRORS; - *(--s) = '\0'; - } else if ( strcmp( s, REQUEST ) == 0 ) { - type = GROUP_REQUEST; - *(--s) = '\0'; - } else if ( strcmp( s, MEMBERS ) == 0 ) { - type = GROUP_MEMBERS; - *(--s) = '\0'; - } - } - - do_address( argv[i], &tolist, &numto, &togroups, &ngroups, - &errlist, &numerr, type ); - } - - /* - * If we have both errors and successful deliveries to make or if - * if there are any groups to deliver to, we basically need to read - * the message twice. So, we have to put it in a tmp file. - */ - - if ( numerr > 0 && numto > nargs || ngroups > 0 ) { - FILE *fp; - char buf[BUFSIZ]; - - umask( 077 ); - if ( (fp = tmpfile()) == NULL ) { - syslog( LOG_ALERT, "could not open tmp file" ); - unbind_and_exit( EX_TEMPFAIL ); - } - - /* copy the message to a temp file */ - while ( fgets( buf, sizeof(buf), stdin ) != NULL ) { - if ( fputs( buf, fp ) == EOF ) { - syslog( LOG_ALERT, "error writing tmpfile" ); - unbind_and_exit( EX_TEMPFAIL ); - } - } - - if ( dup2( fileno( fp ), 0 ) == -1 ) { - syslog( LOG_ALERT, "could not dup2 tmpfile" ); - unbind_and_exit( EX_TEMPFAIL ); - } - - fclose( fp ); - } - - /* deal with errors */ - if ( numerr > 0 ) { - (void) rewind( stdin ); - send_errors( errlist, numerr ); - } - - (void) ldap_unbind( ld ); - - /* send to groups with errorsTo */ - if ( ngroups > 0 ) { - (void) rewind( stdin ); - send_group( togroups, ngroups ); - } - - /* send to expanded aliases and groups w/o errorsTo */ - if ( numto > nargs ) { - (void) rewind( stdin ); - send_message( tolist ); - } - - return( EX_OK ); -} - -static int -connect_to_x500( void ) -{ - int sizelimit = FAX_MAXAMBIGUOUS; - int deref = LDAP_DEREF_ALWAYS; - - if ( (ld = ldap_init( NULL, 0 )) == NULL ) { - syslog( LOG_ALERT, "ldap_init failed" ); - return( -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 ) { - syslog( LOG_ALERT, "ldap_simple_bind_s failed" ); - return( -1 ); - } - - return( 0 ); -} - - -static void -do_address( - char *name, - char ***to, - int *nto, - Group **togroups, - int *ngroups, - Error **err, - int *nerr, - int type -) -{ - int rc, b, f, match; - LDAPMessage *e, *res; - struct timeval timeout; - char *dn; - char filter[1024]; - char **mail; - char **fax; - - /* - * Look up the name in X.500, add the appropriate addresses found - * to the to list, or to the err list in case of error. Groups are - * handled by the do_group routine, individuals are handled here. - * When looking up name, we follow the bases hierarchy, looking - * in base[0] first, then base[1], etc. For each base, there is - * a set of search filters to try, in order. If something goes - * wrong here trying to contact X.500, we exit with EX_TEMPFAIL. - * If the b_rdnpref flag is set, then we give preference to entries - * that matched name because it's their rdn, otherwise not. - */ - - timeout.tv_sec = FAX_TIMEOUT; - timeout.tv_usec = 0; - for ( b = 0, match = 0; !match && base[b].b_dn != NULL; b++ ) { - for ( f = 0; base[b].b_filter[f] != NULL; f++ ) { - char *format, *p, *argv[3]; - int argc; - - for ( argc = 0; argc < 3; argc++ ) { - argv[argc] = NULL; - } - - format = strdup( base[b].b_filter[f] ); - for ( argc = 0, p = format; *p; p++ ) { - if ( *p == '%' ) { - switch ( *++p ) { - case 's': /* %s is the name */ - argv[argc] = name; - break; - - case 'h': /* %h is the host */ - *p = 's'; - argv[argc] = host; - break; - - default: - syslog( LOG_ALERT, - "unknown format %c", *p ); - break; - } - - argc++; - } - } - - /* three names ought to do... */ - sprintf( filter, format, argv[0], argv[1], argv[2] ); - free( format ); - - res = NULL; - rc = ldap_search_st( ld, base[b].b_dn, - LDAP_SCOPE_SUBTREE, filter, attrs, 0, &timeout, - &res ); - - /* some other trouble - try again later */ - if ( rc != LDAP_SUCCESS && - rc != LDAP_SIZELIMIT_EXCEEDED ) { - syslog( LOG_ALERT, "return %d from X.500", rc ); - unbind_and_exit( EX_TEMPFAIL ); - } - - if ( (match = ldap_count_entries( ld, res )) != 0 ) - break; - - ldap_msgfree( res ); - } - - if ( match ) - break; - } - - /* trouble - try again later */ - if ( match == -1 ) { - syslog( LOG_ALERT, "error parsing result from X.500" ); - unbind_and_exit( EX_TEMPFAIL ); - } - - /* no matches - bounce with user unknown */ - if ( match == 0 ) { - add_error( err, nerr, E_USERUNKNOWN, name, NULL ); - return; - } - - /* more than one match - bounce with ambiguous user? */ - if ( match > 1 ) { - LDAPMessage *next, *tmpres = NULL; - char *dn; - char **xdn; - - /* not giving rdn preference - bounce with ambiguous user */ - if ( base[b].b_rdnpref == 0 ) { - add_error( err, nerr, E_AMBIGUOUS, name, res ); - return; - } - - /* - * giving rdn preference - see if any entries were matched - * because of their rdn. If so, collect them to deal with - * later (== 1 we deliver, > 1 we bounce). - */ - - for ( e = ldap_first_entry( ld, res ); e != NULL; e = next ) { - next = ldap_next_entry( ld, e ); - dn = ldap_get_dn( ld, e ); - xdn = ldap_explode_dn( dn, 1 ); - - /* XXX bad, but how else can we do it? XXX */ - if ( strcasecmp( xdn[0], name ) == 0 ) { - ldap_delete_result_entry( &res, e ); - ldap_add_result_entry( &tmpres, e ); - } - - ldap_value_free( xdn ); - free( dn ); - } - - /* nothing matched by rdn - go ahead and bounce */ - if ( tmpres == NULL ) { - add_error( err, nerr, E_AMBIGUOUS, name, res ); - return; - - /* more than one matched by rdn - bounce with rdn matches */ - } else if ( (match = ldap_count_entries( ld, tmpres )) > 1 ) { - add_error( err, nerr, E_AMBIGUOUS, name, tmpres ); - return; - - /* trouble... */ - } else if ( match < 0 ) { - syslog( LOG_ALERT, "error parsing result from X.500" ); - unbind_and_exit( EX_TEMPFAIL ); - } - - /* otherwise one matched by rdn - send to it */ - ldap_msgfree( res ); - res = tmpres; - } - - /* - * if we get this far, it means that we found a single match for - * name. for a user, we deliver to the mail attribute or bounce - * with address and phone if no mail attr. for a group, we - * deliver to all members or bounce to rfc822ErrorsTo if no members. - */ - - /* trouble */ - if ( (e = ldap_first_entry( ld, res )) == NULL ) { - syslog( LOG_ALERT, "error parsing entry from X.500" ); - unbind_and_exit( EX_TEMPFAIL ); - } - - dn = ldap_get_dn( ld, e ); - - if ( type == GROUP_ERRORS ) { - /* sent to group-errors - resend to [rfc822]ErrorsTo attr */ - do_group_errors( e, dn, to, nto, err, nerr ); - - } else if ( type == GROUP_REQUEST ) { - /* sent to group-request - resend to [rfc822]RequestsTo attr */ - do_group_request( e, dn, to, nto, err, nerr ); - - } else if ( type == GROUP_MEMBERS ) { - /* sent to group-members - expand */ - do_group_members( e, dn, to, nto, togroups, ngroups, err, - nerr ); - - } else if ( isgroup( e ) ) { - /* - * sent to group - resend from [rfc822]ErrorsTo if it's there, - * otherwise, expand the group - */ - - do_group( e, dn, to, nto, togroups, ngroups, err, nerr ); - - ldap_msgfree( res ); - - } else { - /* - * sent to user - mail attribute => add it to the to list, - * otherwise bounce - */ - switch (identity) { - case FAX500 : - if ( (mail = ldap_get_values( ld, e, - "facsimileTelephoneNumber" )) != NULL ) { - char *fdn; - char **ufn; - int i; - - fdn = ldap_get_dn( ld, e ); - ufn = ldap_explode_dn( fdn, 1 ); - /* Convert spaces to underscores for rp */ - for (i = 0; ufn[0][i] != '\0'; i++) { - if (ufn[0][i] == ' ') { - ufn[0][i] = '_'; - } - } - *mail = faxtotpc(*mail, ufn[0]); - - add_to(to, nto, mail); - - if (fdn != NULL) { - free(fdn); - } - ldap_value_free( ufn ); - ldap_value_free( mail ); - ldap_msgfree( res ); - } else { - add_error( err, nerr, E_NOFAXNUM, - name, res ); - } - break; - case MAIL500 : - if ( (mail = ldap_get_values( ld, e, "mail" )) - != NULL ) { - add_to( to, nto, mail ); - - ldap_value_free( mail ); - ldap_msgfree( res ); - } else { - add_error( err, nerr, E_NOEMAIL, - name, res ); - } - break; - } - } - - free( dn ); - - return; -} - -static int -do_group( - LDAPMessage *e, - char *dn, - char ***to, - int *nto, - Group **togroups, - int *ngroups, - Error **err, - int *nerr -) -{ - /* - * If this group has an rfc822ErrorsTo attribute, we need to - * arrange for errors involving this group to go there, not - * to the sender. Since sendmail only has the concept of a - * single sender, we arrange for errors to go to groupname-errors, - * which we then handle specially when (if) it comes back to us - * by expanding to all the rfc822ErrorsTo addresses. If it has no - * rfc822ErrorsTo attribute, we call do_group_members() to expand - * the group. - */ - - if ( group_loop( dn ) ) { - return( -1 ); - } - - if ( has_attributes( e, "rfc822ErrorsTo", "errorsTo" ) ) { - add_group( dn, togroups, ngroups ); - - return( 0 ); - } - - do_group_members( e, dn, to, nto, togroups, ngroups, err, nerr ); - - return( 0 ); -} - -/* ARGSUSED */ -static void -do_group_members( - LDAPMessage *e, - char *dn, - char ***to, - int *nto, - Group **togroups, - int *ngroups, - Error **err, - int *nerr -) -{ - int i, rc; - char *ndn; - char **mail, **member, **joinable; - char filter[256]; - LDAPMessage *ee, *res; - struct timeval timeout; - - /* - * if all has gone according to plan, we've already arranged for - * errors to go to the [rfc822]ErrorsTo attributes (if they exist), - * so all we have to do here is arrange to send to the - * rfc822Mailbox attribute, the member attribute, and anyone who - * has joined the group by setting memberOfGroup equal to the - * group dn. - */ - - /* add members in the group itself - mail attribute */ - if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) { - /* - * These are only email addresses - impossible - * to have a fax number - */ - switch (identity) { - case FAX500 : - /* XXX How do we want to inform sender that the */ - /* group they sent to has email-only members? */ - break; - case MAIL500 : - add_to( to, nto, mail ); - break; - } - - ldap_value_free( mail ); - } - - /* add members in the group itself - member attribute */ - if ( (member = ldap_get_values( ld, e, "member" )) != NULL ) { - for ( i = 0; member[i] != NULL; i++ ) { - add_member( dn, member[i], to, nto, togroups, - ngroups, err, nerr ); - } - - ldap_value_free( member ); - } - - /* add members who have joined by setting memberOfGroup */ - if ( (joinable = ldap_get_values( ld, e, "joinable" )) != NULL ) { - if ( strcasecmp( joinable[0], "FALSE" ) == 0 ) { - ldap_value_free( joinable ); - return; - } - ldap_value_free( joinable ); - - sprintf( filter, "(memberOfGroup=%s)", dn ); - - timeout.tv_sec = FAX_TIMEOUT; - timeout.tv_usec = 0; - - /* for each subtree to look in... */ - { - int sizelimit = FAX_MAXMEMBERS; - ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit); - } - for ( i = 0; base[i].b_dn != NULL; i++ ) { - /* find entries that have joined this group... */ - rc = ldap_search_st( ld, base[i].b_dn, - LDAP_SCOPE_SUBTREE, filter, attrs, 0, &timeout, - &res ); - - if ( rc == LDAP_SIZELIMIT_EXCEEDED || - rc == LDAP_TIMELIMIT_EXCEEDED ) { - syslog( LOG_ALERT, - "group search limit exceeded %d", rc ); - unbind_and_exit( EX_TEMPFAIL ); - } - - if ( rc != LDAP_SUCCESS ) { - syslog( LOG_ALERT, "group search bad return %d", - rc ); - unbind_and_exit( EX_TEMPFAIL ); - } - - /* for each entry that has joined... */ - for ( ee = ldap_first_entry( ld, res ); ee != NULL; - ee = ldap_next_entry( ld, ee ) ) { - if ( isgroup( ee ) ) { - ndn = ldap_get_dn( ld, ee ); - - if ( do_group( e, ndn, to, nto, - togroups, ngroups, err, nerr ) - == -1 ) { - syslog( LOG_ALERT, - "group loop (%s) (%s)", - dn, ndn ); - } - - free( ndn ); - - continue; - } - - /* add them to the to list */ - switch (identity) { - case FAX500 : - if ( (mail = ldap_get_values( ld, ee, - "facsimileTelephoneNumber" )) - != NULL ) { - char *fdn; - char **ufn; - int i; - - fdn = ldap_get_dn( ld, ee ); - ufn = ldap_explode_dn( fdn, 1 ); - /* - * Convert spaces to - * underscores for rp - */ - for (i = 0; ufn[0][i] != '\0'; - i++) { - if (ufn[0][i] == ' ') { - ufn[0][i] = '_'; - } - } - *mail = faxtotpc(*mail, ufn[0]); - add_to(to, nto, mail); - - ldap_value_free( mail ); - ldap_msgfree( res ); - } else { - ndn = ldap_get_dn( ld, ee ); - - add_error( err, nerr, - E_JOINMEMBERNOFAXNUM, ndn, - NULL ); - - free( ndn ); - } - break; - case MAIL500 : - if ( (mail = ldap_get_values( ld, ee, - "mail" )) != NULL ) { - add_to( to, nto, mail ); - - ldap_value_free( mail ); - - /* else generate a bounce */ - } else { - ndn = ldap_get_dn( ld, ee ); - - add_error( err, nerr, - E_JOINMEMBERNOEMAIL, ndn, - NULL ); - - free( ndn ); - } - break; - } - } - - ldap_msgfree( res ); - } - { - int sizelimit = FAX_MAXAMBIGUOUS; - ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &sizelimit); - } - } - - return; -} - -static void -add_member( - char *gdn, - char *dn, - char ***to, - int *nto, - Group **togroups, - int *ngroups, - Error **err, - int *nerr -) -{ - char *ndn; - char **mail; - int rc; - LDAPMessage *res, *e; - struct timeval timeout; - - timeout.tv_sec = FAX_TIMEOUT; - timeout.tv_usec = 0; - if ( (rc = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, NULL, - attrs, 0, &timeout, &res )) != LDAP_SUCCESS ) { - if ( rc == LDAP_NO_SUCH_OBJECT ) { - add_error( err, nerr, E_BADMEMBER, dn, NULL ); - - return; - } else { - syslog( LOG_ALERT, "member search bad return %d", rc ); - - unbind_and_exit( EX_TEMPFAIL ); - } - } - - if ( (e = ldap_first_entry( ld, res )) == NULL ) { - syslog( LOG_ALERT, "member search error parsing entry" ); - - unbind_and_exit( EX_TEMPFAIL ); - } - ndn = ldap_get_dn( ld, e ); - - /* allow groups within groups */ - if ( isgroup( e ) ) { - if ( do_group( e, ndn, to, nto, togroups, ngroups, err, nerr ) - == -1 ) { - syslog( LOG_ALERT, "group loop (%s) (%s)", gdn, ndn ); - } - - free( ndn ); - - return; - } - - switch (identity) { - case FAX500 : - if ( (mail = ldap_get_values( ld, e, - "facsimileTelephoneNumber" )) != NULL ) { - char *fdn; - char **ufn; - int i; - fdn = ldap_get_dn( ld, e ); - ufn = ldap_explode_dn( fdn, 1 ); - /* Convert spaces to underscores for rp */ - for (i = 0; ufn[0][i] != '\0'; i++) { - if (ufn[0][i] == ' ') { - ufn[0][i] = '_'; - } - } - *mail = faxtotpc(*mail, ufn[0]); - add_to(to, nto, mail); - - ldap_value_free( mail ); - ldap_msgfree( res ); - } else { - add_error( err, nerr, E_MEMBERNOFAXNUM, ndn, NULL ); - } - break; - case MAIL500 : - /* send to the member's mail attribute */ - if ( (mail = ldap_get_values( ld, e, "mail" )) != NULL ) { - add_to( to, nto, mail ); - - ldap_value_free( mail ); - - /* else generate a bounce */ - } else { - add_error( err, nerr, E_MEMBERNOEMAIL, ndn, NULL ); - } - - free( ndn ); - } - return; -} - -static void -do_group_request( - LDAPMessage *e, - char *dn, - char ***to, - int *nto, - Error **err, - int *nerr -) -{ - char **requeststo; - - if ( (requeststo = get_attributes_mail_dn( e, "rfc822RequestsTo", - "requestsTo" )) != NULL ) { - add_to( to, nto, requeststo ); - - ldap_value_free( requeststo ); - } else { - add_error( err, nerr, E_NOREQUEST, dn, NULL ); - } -} - -static void -do_group_errors( - LDAPMessage *e, - char *dn, - char ***to, - int *nto, - Error **err, - int *nerr -) -{ - char **errorsto; - - if ( (errorsto = get_attributes_mail_dn( e, "rfc822ErrorsTo", - "errorsTo" )) != NULL ) { - add_to( to, nto, errorsto ); - - ldap_value_free( errorsto ); - } else { - add_error( err, nerr, E_NOERRORS, dn, NULL ); - } -} - -static void -send_message( char **to ) -{ - int pid; -#ifndef HAVE_WAITPID - WAITSTATUSTYPE status; -#endif - - - /* parent */ - if ( (pid = fork()) != 0 ) { -#ifdef HAVE_WAITPID - waitpid( pid, (int *) NULL, 0 ); -#else - wait4( pid, &status, WAIT_FLAGS, 0 ); -#endif - /* child */ - } else { - /* to includes sendmailargs */ - execv( FAX_SENDMAIL, to ); - - syslog( LOG_ALERT, "execv failed" ); - - exit( EX_TEMPFAIL ); - } -} - -static void -send_group( Group *group, int ngroup ) -{ - int i, pid; - char **argv; - int argc; - char *iargv[7]; -#ifndef HAVE_WAITPID - WAITSTATUSTYPE status; -#endif - - for ( i = 0; i < ngroup; i++ ) { - (void) rewind( stdin ); - - iargv[0] = FAX_SENDMAIL; - iargv[1] = "-f"; - iargv[2] = group[i].g_errorsto; - iargv[3] = "-oMrX.500"; - iargv[4] = "-odi"; - iargv[5] = "-oi"; - iargv[6] = NULL; - - argv = NULL; - argc = 0; - add_to( &argv, &argc, iargv ); - add_to( &argv, &argc, group[i].g_members ); - - - /* parent */ - if ( (pid = fork()) != 0 ) { -#ifdef HAVE_WAITPID - waitpid( pid, (int *) NULL, 0 ); -#else - wait4( pid, &status, WAIT_FLAGS, 0 ); -#endif - /* child */ - } else { - execv( FAX_SENDMAIL, argv ); - - syslog( LOG_ALERT, "execv failed" ); - - exit( EX_TEMPFAIL ); - } - } - - return; -} - -static void -send_errors( Error *err, int nerr ) -{ - int i, namelen; - FILE *fp; - char buf[1024]; - - sprintf( buf, "%s -oMrX.500 -odi -oi -f %s %s", FAX_SENDMAIL, errorsfrom, - mailfrom ); - if ( (fp = popen( buf, "w" )) == NULL ) { - syslog( LOG_ALERT, "could not popen sendmail for errs" ); - return; - } - - fprintf( fp, "To: %s\n", mailfrom ); - fprintf( fp, "From: %s\n", errorsfrom ); - fprintf( fp, "Subject: undeliverable mail\n" ); - fprintf( fp, "\n" ); - fprintf( fp, "The following errors occurred when trying to deliver the attached mail:\n" ); - for ( i = 0; i < nerr; i++ ) { - namelen = strlen( err[i].e_addr ); - fprintf( fp, "\n" ); - - switch ( err[i].e_code ) { - case E_USERUNKNOWN: - fprintf( fp, "%s: User unknown\n", err[i].e_addr ); - break; - - case E_BADMEMBER: - fprintf( fp, "%s: Group member does not exist\n", - err[i].e_addr ); - break; - - case E_NOREQUEST: - fprintf( fp, "%s: Group exists but has no request address\n", - err[i].e_addr ); - break; - - case E_NOERRORS: - fprintf( fp, "%s: Group exists but has no errors-to address\n", - err[i].e_addr ); - break; - - case E_AMBIGUOUS: - do_ambiguous( fp, &err[i], namelen ); - break; - - case E_NOEMAIL: - do_noemailorfax( fp, &err[i], namelen, E_NOEMAIL ); - break; - - case E_MEMBERNOEMAIL: - fprintf( fp, "%s: Group member exists but does not have an email address\n", - err[i].e_addr ); - break; - - case E_JOINMEMBERNOEMAIL: - fprintf( fp, "%s: User has joined group but does not have an email address\n", - err[i].e_addr ); - break; - - case E_NOFAXNUM: - do_noemailorfax( fp, &err[i], namelen, E_NOFAXNUM ); - break; - - case E_MEMBERNOFAXNUM: - fprintf( fp, "%s: Group member exists but does not have a fax number\n", - err[i].e_addr ); - break; - - case E_JOINMEMBERNOFAXNUM: - fprintf( fp, "%s: User has joined group but does not have a fax number\n", - err[i].e_addr ); - break; - - default: - syslog( LOG_ALERT, "unknown error %d", err[i].e_code ); - unbind_and_exit( EX_TEMPFAIL ); - break; - } - } - - fprintf( fp, "\n------- The original message sent:\n\n" ); - - while ( fgets( buf, sizeof(buf), stdin ) != NULL ) { - fputs( buf, fp ); - } - - if ( pclose( fp ) == -1 ) { - syslog( LOG_ALERT, "pclose failed" ); - unbind_and_exit( EX_TEMPFAIL ); - } - - return; -} - - -static void -do_noemailorfax( FILE *fp, Error *err, int namelen, int errtype ) -{ - int i, last; - char *dn, *rdn; - char **ufn, **vals; - - if (errtype == E_NOFAXNUM) { - fprintf(fp, "%s: User has no facsimile number registered.\n", - err->e_addr ); - } else if (errtype == E_NOEMAIL) { - fprintf(fp, "%s: User has no email address registered.\n", - err->e_addr ); - } - fprintf( fp, "%*s Name, title, postal address and phone for '%s':\n\n", - namelen, " ", err->e_addr ); - - /* name */ - dn = ldap_get_dn( ld, err->e_msg ); - ufn = ldap_explode_dn( dn, 1 ); - rdn = strdup( ufn[0] ); - if ( strcasecmp( rdn, err->e_addr ) == 0 ) { - if ( (vals = ldap_get_values( ld, err->e_msg, "cn" )) - != NULL ) { - for ( i = 0; vals[i]; i++ ) { - last = strlen( vals[i] ) - 1; - if ( isdigit((unsigned char) vals[i][last]) ) { - rdn = strdup( vals[i] ); - break; - } - } - - ldap_value_free( vals ); - } - } - fprintf( fp, "%*s %s\n", namelen, " ", rdn ); - free( dn ); - free( rdn ); - ldap_value_free( ufn ); - - /* titles or descriptions */ - if ( (vals = ldap_get_values( ld, err->e_msg, "title" )) == NULL && - (vals = ldap_get_values( ld, err->e_msg, "description" )) - == NULL ) { - fprintf( fp, "%*s No title or description registered\n", - namelen, " " ); - } else { - for ( i = 0; vals[i] != NULL; i++ ) { - fprintf( fp, "%*s %s\n", namelen, " ", vals[i] ); - } - - ldap_value_free( vals ); - } - - /* postal address */ - if ( (vals = ldap_get_values( ld, err->e_msg, "postalAddress" )) - == NULL ) { - fprintf( fp, "%*s No postal address registered\n", namelen, - " " ); - } else { - fprintf( fp, "%*s ", namelen, " " ); - for ( i = 0; vals[0][i] != '\0'; i++ ) { - if ( vals[0][i] == '$' ) { - fprintf( fp, "\n%*s ", namelen, " " ); - while ( isspace((unsigned char) vals[0][i+1]) ) - i++; - } else { - fprintf( fp, "%c", vals[0][i] ); - } - } - fprintf( fp, "\n" ); - - ldap_value_free( vals ); - } - - /* telephone number */ - if ( (vals = ldap_get_values( ld, err->e_msg, "telephoneNumber" )) - == NULL ) { - fprintf( fp, "%*s No phone number registered\n", namelen, - " " ); - } else { - for ( i = 0; vals[i] != NULL; i++ ) { - fprintf( fp, "%*s %s\n", namelen, " ", vals[i] ); - } - - ldap_value_free( vals ); - } -} - -/* ARGSUSED */ -static void -do_ambiguous( FILE *fp, Error *err, int namelen ) -{ - int i, last; - char *dn, *rdn; - char **ufn, **vals; - LDAPMessage *e; - - i = ldap_result2error( ld, err->e_msg, 0 ); - - fprintf( fp, "%s: Ambiguous user. %s%d matches found:\n\n", - err->e_addr, i == LDAP_SIZELIMIT_EXCEEDED ? "First " : "", - ldap_count_entries( ld, err->e_msg ) ); - - for ( e = ldap_first_entry( ld, err->e_msg ); e != NULL; - e = ldap_next_entry( ld, e ) ) { - dn = ldap_get_dn( ld, e ); - ufn = ldap_explode_dn( dn, 1 ); - rdn = strdup( ufn[0] ); - if ( strcasecmp( rdn, err->e_addr ) == 0 ) { - if ( (vals = ldap_get_values( ld, e, "cn" )) != NULL ) { - for ( i = 0; vals[i]; i++ ) { - last = strlen( vals[i] ) - 1; - if ( isdigit((unsigned char) vals[i][last]) ) { - rdn = strdup( vals[i] ); - break; - } - } - - ldap_value_free( vals ); - } - } - - if ( isgroup( e ) ) { - vals = ldap_get_values( ld, e, "description" ); - } else { - vals = ldap_get_values( ld, e, "title" ); - } - - fprintf( fp, " %-20s %s\n", rdn, vals ? vals[0] : "" ); - for ( i = 1; vals && vals[i] != NULL; i++ ) { - fprintf( fp, " %s\n", vals[i] ); - } - - free( dn ); - free( rdn ); - ldap_value_free( ufn ); - if ( vals != NULL ) - ldap_value_free( vals ); - } -} - -static int -count_values( char **list ) -{ - int i; - - for ( i = 0; list && list[i] != NULL; i++ ) - ; /* NULL */ - - return( i ); -} - -static void -add_to( char ***list, int *nlist, char **new ) -{ - int i, nnew, oldnlist; - - nnew = count_values( new ); - - oldnlist = *nlist; - if ( *list == NULL || *nlist == 0 ) { - *list = (char **) malloc( (nnew + 1) * sizeof(char *) ); - *nlist = nnew; - } else { - *list = (char **) realloc( *list, *nlist * sizeof(char *) + - nnew * sizeof(char *) + sizeof(char *) ); - *nlist += nnew; - } - - for ( i = 0; i < nnew; i++ ) { - (*list)[i + oldnlist] = strdup( new[i] ); - } - (*list)[*nlist] = NULL; - - return; -} - -static int -isgroup( LDAPMessage *e ) -{ - int i; - char **oclist; - - oclist = ldap_get_values( ld, e, "objectClass" ); - - for ( i = 0; oclist[i] != NULL; i++ ) { - if ( strcasecmp( oclist[i], "rfc822MailGroup" ) == 0 ) { - ldap_value_free( oclist ); - return( 1 ); - } - } - ldap_value_free( oclist ); - - return( 0 ); -} - -static void -add_error( Error **err, int *nerr, int code, char *addr, LDAPMessage *msg ) -{ - if ( *nerr == 0 ) { - *err = (Error *) malloc( sizeof(Error) ); - } else { - *err = (Error *) realloc( *err, (*nerr + 1) * sizeof(Error) ); - } - - (*err)[*nerr].e_code = code; - (*err)[*nerr].e_addr = strdup( addr ); - (*err)[*nerr].e_msg = msg; - (*nerr)++; - - return; -} - -static void -add_group( char *dn, Group **list, int *nlist ) -{ - int i, namelen; - char **ufn; - - for ( i = 0; i < *nlist; i++ ) { - if ( strcmp( dn, (*list)[i].g_dn ) == 0 ) { - syslog( LOG_ALERT, "group loop 2 detected (%s)", dn ); - return; - } - } - - ufn = ldap_explode_dn( dn, 1 ); - namelen = strlen( ufn[0] ); - - if ( *nlist == 0 ) { - *list = (Group *) malloc( sizeof(Group) ); - } else { - *list = (Group *) realloc( *list, (*nlist + 1) * - sizeof(Group) ); - } - - /* send errors to groupname-errors@host */ - (*list)[*nlist].g_errorsto = (char *) malloc( namelen + sizeof(ERRORS) - + hostlen + 2 ); - sprintf( (*list)[*nlist].g_errorsto, "%s-%s@%s", ufn[0], ERRORS, host ); - (void) canonical( (*list)[*nlist].g_errorsto ); - - /* send to groupname-members@host - make it a list for send_group */ - (*list)[*nlist].g_members = (char **) malloc( 2 * sizeof(char *) ); - (*list)[*nlist].g_members[0] = (char *) malloc( namelen + - sizeof(MEMBERS) + hostlen + 2 ); - sprintf( (*list)[*nlist].g_members[0], "%s-%s@%s", ufn[0], MEMBERS, - host ); - (void) canonical( (*list)[*nlist].g_members[0] ); - (*list)[*nlist].g_members[1] = NULL; - - /* save the group's dn so we can check for loops above */ - (*list)[*nlist].g_dn = strdup( dn ); - - (*nlist)++; - - ldap_value_free( ufn ); - - return; -} - -static void -unbind_and_exit( int rc ) -{ - int i; - - if ( (i = ldap_unbind( ld )) != LDAP_SUCCESS ) - syslog( LOG_ALERT, "ldap_unbind failed %d\n", i ); - - exit( rc ); -} - -static char * -canonical( char *s ) -{ - char *saves = s; - - for ( ; *s != '\0'; s++ ) { - if ( *s == ' ' ) - *s = '.'; - } - - return( saves ); -} - -static int -group_loop( char *dn ) -{ - int i; - static char **groups; - static int ngroups; - - for ( i = 0; i < ngroups; i++ ) { - if ( strcmp( dn, groups[i] ) == 0 ) - return( 1 ); - } - - if ( ngroups == 0 ) - groups = (char **) malloc( sizeof(char *) ); - else - groups = (char **) realloc( groups, - (ngroups + 1) * sizeof(char *) ); - - groups[ngroups++] = strdup( dn ); - - return( 0 ); -} - -static int -has_attributes( LDAPMessage *e, char *attr1, char *attr2 ) -{ - char **attr; - - if ( (attr = ldap_get_values( ld, e, attr1 )) != NULL ) { - ldap_value_free( attr ); - return( 1 ); - } - - if ( (attr = ldap_get_values( ld, e, attr2 )) != NULL ) { - ldap_value_free( attr ); - return( 1 ); - } - - return( 0 ); -} - -static char ** -get_attributes_mail_dn( LDAPMessage *e, char *attr1, char *attr2 ) -{ - LDAPMessage *ee, *res; - char **vals, **dnlist, **mail; - int nto, i, rc; - struct timeval timeout; - - vals = ldap_get_values( ld, e, attr1 ); - for ( nto = 0; vals != NULL && vals[nto] != NULL; nto++ ) - ; /* NULL */ - - if ( (dnlist = ldap_get_values( ld, e, attr2 )) != NULL ) { - timeout.tv_sec = FAX_TIMEOUT; - timeout.tv_usec = 0; - - for ( i = 0; dnlist[i] != NULL; i++ ) { - if ( (rc = ldap_search_st( ld, dnlist[i], - LDAP_SCOPE_BASE, NULL, attrs, 0, - &timeout, &res )) != LDAP_SUCCESS ) { - if ( rc != LDAP_NO_SUCH_OBJECT ) { - unbind_and_exit( EX_TEMPFAIL ); - } - - syslog( LOG_ALERT, "bad (%s) dn (%s)", attr2, - dnlist[i] ); - - continue; - } - - if ( (ee = ldap_first_entry( ld, res )) == NULL ) { - syslog( LOG_ALERT, "error parsing x500 entry" ); - continue; - } - - if ( (mail = ldap_get_values( ld, ee, "mail" )) - != NULL ) { - add_to( &vals, &nto, mail ); - - ldap_value_free( mail ); - } - - ldap_msgfree( res ); - } - } - - return( vals ); -} diff --git a/clients/fax500/rp500.c b/clients/fax500/rp500.c deleted file mode 100644 index 40cd2c000d..0000000000 --- a/clients/fax500/rp500.c +++ /dev/null @@ -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 - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif - -#include - -#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( "#&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 "# $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 diff --git a/clients/gopher/Makefile.in b/clients/gopher/Makefile.in deleted file mode 100644 index 27e2ba136a..0000000000 --- a/clients/gopher/Makefile.in +++ /dev/null @@ -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) - diff --git a/clients/gopher/README b/clients/gopher/README deleted file mode 100644 index 6ed7feb3c4..0000000000 --- a/clients/gopher/README +++ /dev/null @@ -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 /* make inetd notice the change */ - - where $(ETCDIR) is replaced by the ETCDIR from the top level Makefile - and 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=