mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-27 03:20:22 +08:00
73db912500
These functions require their arguments to be in the range of `unsigned char'.
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((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, 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( (unsigned char) *p ) && p > s ) {
|
|
--p;
|
|
}
|
|
*(++p) = '\0';
|
|
}
|