2 * query.c: for rcpt500 (X.500 email query responder)
4 * 18 June 1992 by Mark C Smith
5 * Copyright (c) 1992 The Regents of The University of Michigan
14 #include <ac/string.h>
15 #include <ac/syslog.h>
21 #if LDAP_VERSION < LDAP_VERSION3
22 /* quick fix until we have ldap_set_options */
23 #include "../libraries/libldap/ldap-int.h"
29 #include "ldapconfig.h"
34 extern int derefaliases;
37 extern char *ldaphost;
38 extern char *searchbase;
40 extern char *filterfile;
41 extern char *templatefile;
43 static char buf[ MAXSIZE ];
44 static char *errpreface = "Your query failed: ";
46 extern int strcasecmp();
52 query_cmd( msgp, reply )
57 LDAPMessage *ldmsgp, *entry;
62 struct ldap_disptmpl *tmpllist = NULL;
63 static char *attrs[] = { "cn", "title",
64 #ifdef RCPT500_SORT_ATTR
71 if ( msgp->msg_arg == NULL ) {
72 return( help_cmd( msgp, reply ));
75 remove_trailing_space( msgp->msg_arg );
76 if ( *msgp->msg_arg == '\0' ) {
77 return( help_cmd( msgp, reply ));
80 if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
81 strcat( reply, errpreface );
82 strcat( reply, "filter file configuration error. Try again later." );
87 * open connection to LDAP server and bind as dapuser
89 #ifdef LDAP_CONNECTIONLESS
91 ldp = cldap_open( ldaphost, ldapport );
93 #endif /* LDAP_CONNECTIONLESS */
94 ldp = ldap_open( ldaphost, ldapport );
97 strcat( reply, errpreface );
98 strcat( reply, "X.500 service unavailable. Try again later." );
99 ldap_getfilter_free( lfdp );
103 #ifdef LDAP_CONNECTIONLESS
105 #endif /* LDAP_CONNECTIONLESS */
106 if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
107 report_ldap_err( ldp, reply );
109 ldap_getfilter_free( lfdp );
114 * set options for search and build filter
116 ldp->ld_deref = derefaliases;
117 ldp->ld_sizelimit = sizelimit;
122 #ifdef LDAP_CONNECTIONLESS
123 if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
124 #else /* LDAP_CONNECTIONLESS */
125 if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
126 #endif /* LDAP_CONNECTIONLESS */
129 ldap_ufn_setprefix( ldp, searchbase );
130 if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
131 != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
132 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
133 report_ldap_err( ldp, reply );
135 ldap_getfilter_free( lfdp );
138 matches = ldap_count_entries( ldp, ldmsgp );
141 #endif /* RCPT500_UFN */
143 for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
144 lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
145 #ifdef LDAP_CONNECTIONLESS
147 rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
148 lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
150 #endif /* LDAP_CONNECTIONLESS */
151 rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
152 lfi->lfi_filter, attrs, 0, &ldmsgp );
154 if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
155 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
156 report_ldap_err( ldp, reply );
158 ldap_getfilter_free( lfdp );
162 if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
166 if ( ldmsgp != NULL ) {
167 ldap_msgfree( ldmsgp );
172 #endif /* RCPT500_UFN */
174 if ( matches == 0 ) {
175 sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
176 strcat( reply, buf );
178 ldap_getfilter_free( lfdp );
182 if ( ldp->ld_errno == LDAP_TIMELIMIT_EXCEEDED
183 || ldp->ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
184 strcat( reply, "(Partial results only - a limit was exceeded)\n" );
187 if ( matches <= RCPT500_LISTLIMIT ) {
188 sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
189 ufn ? "UFN" : lfi->lfi_desc,
190 ( matches > 1 ) ? "es" : "", msgp->msg_arg );
191 strcat( reply, buf );
193 if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
194 sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
195 errpreface, templatefile, rc );
196 strcat( reply, buf );
199 for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
200 dn = ldap_get_dn( ldp, entry );
201 if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
202 report_ldap_err( ldp, reply );
205 if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
206 strcat( reply, "\n-------\n\n" );
210 if ( tmpllist != NULL ) {
211 ldap_free_templates( tmpllist );
213 ldap_msgfree( ldmsgp );
216 sprintf( buf, "%d %s matches were found for '%s':\n",
217 matches, ufn ? "UFN" : lfi->lfi_desc, msgp->msg_arg );
218 strcat( reply, buf );
219 append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
220 ldap_msgfree( ldmsgp );
224 ldap_getfilter_free( lfdp );
230 close_ldap( LDAP *ld )
232 #ifdef LDAP_CONNECTIONLESS
236 #endif /* LDAP_CONNECTIONLESS */
241 append_entry_list( reply, query, ldp, ldmsgp )
248 char *dn, *rdn, *s, **title;
251 #ifdef RCPT500_SORT_ATTR
252 ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
255 for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
256 e = ldap_next_entry( ldp, e )) {
257 dn = ldap_get_dn( ldp, e );
258 if (( s = strchr( dn, ',' )) != NULL ) {
261 if (( s = strchr( dn, '=' )) == NULL ) {
269 * if this entry's rdn is an exact match for the thing looked up, we
270 * return the CN that has a digit after it, so that the user is
271 * returned something guaranteed to yield exactly one match if they
272 * pick it from the list and query it
275 if ( strcasecmp( rdn, query ) == 0 ) {
279 if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
280 for ( i = 0; cn[i] != NULL; i++ ) {
281 if ( isdigit( *( cn[i] + strlen( cn[i] ) - 1 ))) {
282 rdn = strdup( cn[i] );
287 ldap_value_free( cn );
292 title = ldap_get_values( ldp, e, "title" );
293 sprintf( buf, " %-20s %s\n", rdn, title ? title[0] : "" );
294 strcat( reply, buf );
295 if ( title != NULL ) {
296 ldap_value_free( title );
307 append_text( reply, text, len )
312 strcat( reply, text );
318 do_read( ldp, dn, reply, tmpll )
322 struct ldap_disptmpl *tmpll;
325 static char *maildefvals[] = { "None registered in this service", NULL };
326 static char *defattrs[] = { "mail", NULL };
327 static char **defvals[] = { maildefvals, NULL };
330 rc = ldap_entry2text_search( ldp, dn, searchbase, NULLMSG, tmpll,
331 defattrs, defvals, append_text, (void *)reply, "\n",
332 rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
338 report_ldap_err( ldp, reply )
342 strcat( reply, errpreface );
343 strcat( reply, ldap_err2string( ldp->ld_errno ));
344 strcat( reply, "\n" );
348 remove_trailing_space( s )
351 char *p = s + strlen( s ) - 1;
353 while ( isspace( *p ) && p > s ) {