mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
b5494457d8
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.
338 lines
8.0 KiB
C
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';
|
|
}
|