openldap/clients/rcpt500/query.c
Kurt Zeilenga b5494457d8 Remove extern declarations of library functions from source.c.
This could cause problems on odd systems.  The generic
  headers should be extended as needed to include necessary
  system headers or, if necessary, make explicit declarations.
Extended ac/string.h header to look for string.h/strings.h if
  STDC_HEADERS is not defined.  Also provide basic declarations for
  str*() functions.  This could cause problems on odd systems.
Extended ac/unistd.h header to define basic declaration for misc
  functions that might be missing from headers.   This includes
  externs for getenv(), getopt(), mktemp(), tempname().
Protect fax500.h from multiple inclusion.  Moved includes of
  system/generic headers back to source files.
Made mail500 helper functions static.
Fixed includes of ctype.h, signal.h, etc. to use generics.
lutil/tempname.c: was including stdlib.h twice, one should stdio.h.
Wrapped <sys/resource.h> with HAVE_SYS_RESOURCE_H.
lber/io.c/ber_get_next(): Changed noctets back to signed.
  Used with BerRead which expects signed int as second arg and
  returns signed int.
1998-11-16 05:07:27 +00:00

338 lines
8.0 KiB
C

/*
* 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 <stdio.h>
#include <stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/syslog.h>
#include <ac/time.h>
#include "lber.h"
#include "ldap.h"
#include "disptmpl.h"
#include "rcpt500.h"
#include "ldapconfig.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, int 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 *s, *dn;
int matches, rc, ld_errno, ufn;
LDAPFiltDesc *lfdp;
LDAPFiltInfo *lfi;
struct ldap_disptmpl *tmpllist = NULL;
static char *attrs[] = { "cn", "title",
#ifdef RCPT500_SORT_ATTR
RCPT500_SORT_ATTR,
#endif
NULL };
ufn = 0;
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
*/
#ifdef LDAP_CONNECTIONLESS
if ( do_cldap )
ldp = cldap_open( ldaphost, ldapport );
else
#endif /* LDAP_CONNECTIONLESS */
ldp = ldap_open( ldaphost, ldapport );
if ( ldp == NULL ) {
strcat( reply, errpreface );
strcat( reply, "X.500 service unavailable. Try again later." );
ldap_getfilter_free( lfdp );
return( 0 );
}
#ifdef LDAP_CONNECTIONLESS
if ( !do_cldap )
#endif /* LDAP_CONNECTIONLESS */
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;
#ifdef RCPT500_UFN
#ifdef LDAP_CONNECTIONLESS
if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
#else /* LDAP_CONNECTIONLESS */
if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
#endif /* LDAP_CONNECTIONLESS */
struct timeval tv;
ldap_ufn_setprefix( ldp, searchbase );
if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
!= LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
&& rc != LDAP_TIMELIMIT_EXCEEDED ) {
report_ldap_err( ldp, reply );
close_ldap( ldp );
ldap_getfilter_free( lfdp );
return( 0 );
}
matches = ldap_count_entries( ldp, ldmsgp );
ufn = 1;
} else {
#endif /* RCPT500_UFN */
for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
#ifdef LDAP_CONNECTIONLESS
if ( do_cldap )
rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
else
#endif /* LDAP_CONNECTIONLESS */
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 );
}
}
#ifdef RCPT500_UFN
}
#endif /* RCPT500_UFN */
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,
ufn ? "UFN" : 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, ufn ? "UFN" : 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 )
{
#ifdef LDAP_CONNECTIONLESS
if ( do_cldap )
cldap_close( ld );
else
#endif /* LDAP_CONNECTIONLESS */
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( *( 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, int 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, NULLMSG, 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( *p ) && p > s ) {
--p;
}
*(++p) = '\0';
}