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>
24 #include "ldapconfig.h"
29 extern int derefaliases;
32 extern char *ldaphost;
33 extern char *searchbase;
35 extern char *filterfile;
36 extern char *templatefile;
38 static char buf[ MAXSIZE ];
39 static char *errpreface = "Your query failed: ";
41 extern int strcasecmp();
47 query_cmd( msgp, reply )
52 LDAPMessage *ldmsgp, *entry;
54 int matches, rc, ld_errno, ufn;
57 struct ldap_disptmpl *tmpllist = NULL;
58 static char *attrs[] = { "cn", "title",
59 #ifdef RCPT500_SORT_ATTR
66 if ( msgp->msg_arg == NULL ) {
67 return( help_cmd( msgp, reply ));
70 remove_trailing_space( msgp->msg_arg );
71 if ( *msgp->msg_arg == '\0' ) {
72 return( help_cmd( msgp, reply ));
75 if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
76 strcat( reply, errpreface );
77 strcat( reply, "filter file configuration error. Try again later." );
82 * open connection to LDAP server and bind as dapuser
84 #ifdef LDAP_CONNECTIONLESS
86 ldp = cldap_open( ldaphost, ldapport );
88 #endif /* LDAP_CONNECTIONLESS */
89 ldp = ldap_open( ldaphost, ldapport );
92 strcat( reply, errpreface );
93 strcat( reply, "X.500 service unavailable. Try again later." );
94 ldap_getfilter_free( lfdp );
98 #ifdef LDAP_CONNECTIONLESS
100 #endif /* LDAP_CONNECTIONLESS */
101 if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
102 report_ldap_err( ldp, reply );
104 ldap_getfilter_free( lfdp );
109 * set options for search and build filter
111 ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
112 ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
117 #ifdef LDAP_CONNECTIONLESS
118 if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
119 #else /* LDAP_CONNECTIONLESS */
120 if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
121 #endif /* LDAP_CONNECTIONLESS */
124 ldap_ufn_setprefix( ldp, searchbase );
125 if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
126 != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
127 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
128 report_ldap_err( ldp, reply );
130 ldap_getfilter_free( lfdp );
133 matches = ldap_count_entries( ldp, ldmsgp );
136 #endif /* RCPT500_UFN */
138 for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
139 lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
140 #ifdef LDAP_CONNECTIONLESS
142 rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
143 lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
145 #endif /* LDAP_CONNECTIONLESS */
146 rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
147 lfi->lfi_filter, attrs, 0, &ldmsgp );
149 if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
150 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
151 report_ldap_err( ldp, reply );
153 ldap_getfilter_free( lfdp );
157 if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
161 if ( ldmsgp != NULL ) {
162 ldap_msgfree( ldmsgp );
167 #endif /* RCPT500_UFN */
169 if ( matches == 0 ) {
170 sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
171 strcat( reply, buf );
173 ldap_getfilter_free( lfdp );
178 ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
180 if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
181 || ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
182 strcat( reply, "(Partial results only - a limit was exceeded)\n" );
185 if ( matches <= RCPT500_LISTLIMIT ) {
186 sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
187 ufn ? "UFN" : lfi->lfi_desc,
188 ( matches > 1 ) ? "es" : "", msgp->msg_arg );
189 strcat( reply, buf );
191 if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
192 sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
193 errpreface, templatefile, rc );
194 strcat( reply, buf );
197 for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
198 dn = ldap_get_dn( ldp, entry );
199 if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
200 report_ldap_err( ldp, reply );
203 if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
204 strcat( reply, "\n-------\n\n" );
208 if ( tmpllist != NULL ) {
209 ldap_free_templates( tmpllist );
211 ldap_msgfree( ldmsgp );
214 sprintf( buf, "%d %s matches were found for '%s':\n",
215 matches, ufn ? "UFN" : lfi->lfi_desc, msgp->msg_arg );
216 strcat( reply, buf );
217 append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
218 ldap_msgfree( ldmsgp );
222 ldap_getfilter_free( lfdp );
228 close_ldap( LDAP *ld )
230 #ifdef LDAP_CONNECTIONLESS
234 #endif /* LDAP_CONNECTIONLESS */
239 append_entry_list( reply, query, ldp, ldmsgp )
246 char *dn, *rdn, *s, **title;
249 #ifdef RCPT500_SORT_ATTR
250 ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
253 for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
254 e = ldap_next_entry( ldp, e )) {
255 dn = ldap_get_dn( ldp, e );
256 if (( s = strchr( dn, ',' )) != NULL ) {
259 if (( s = strchr( dn, '=' )) == NULL ) {
267 * if this entry's rdn is an exact match for the thing looked up, we
268 * return the CN that has a digit after it, so that the user is
269 * returned something guaranteed to yield exactly one match if they
270 * pick it from the list and query it
273 if ( strcasecmp( rdn, query ) == 0 ) {
277 if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
278 for ( i = 0; cn[i] != NULL; i++ ) {
279 if ( isdigit( *( cn[i] + strlen( cn[i] ) - 1 ))) {
280 rdn = strdup( cn[i] );
285 ldap_value_free( cn );
290 title = ldap_get_values( ldp, e, "title" );
291 sprintf( buf, " %-20s %s\n", rdn, title ? title[0] : "" );
292 strcat( reply, buf );
293 if ( title != NULL ) {
294 ldap_value_free( title );
305 append_text( reply, text, len )
310 strcat( reply, text );
316 do_read( ldp, dn, reply, tmpll )
320 struct ldap_disptmpl *tmpll;
323 static char *maildefvals[] = { "None registered in this service", NULL };
324 static char *defattrs[] = { "mail", NULL };
325 static char **defvals[] = { maildefvals, NULL };
328 rc = ldap_entry2text_search( ldp, dn, searchbase, NULLMSG, tmpll,
329 defattrs, defvals, append_text, (void *)reply, "\n",
330 rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
336 report_ldap_err( ldp, reply )
341 ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
343 strcat( reply, errpreface );
344 strcat( reply, ldap_err2string( ld_errno ));
345 strcat( reply, "\n" );
349 remove_trailing_space( s )
352 char *p = s + strlen( s ) - 1;
354 while ( isspace( *p ) && p > s ) {