3 * query.c: for rcpt500 (X.500 email query responder)
5 * 18 June 1992 by Mark C Smith
6 * Copyright (c) 1992 The Regents of The University of Michigan
12 #include <ac/stdlib.h>
15 #include <ac/string.h>
16 #include <ac/syslog.h>
25 #include "ldap_defaults.h"
27 static char buf[ MAXSIZE ];
28 static char *errpreface = "Your query failed: ";
30 static void close_ldap(LDAP *ld);
31 static void append_entry_list(char *rep, char *qu, LDAP *ld, LDAPMessage *msg);
32 static int append_text(void *reply, char *text, ber_len_t len);
33 static int do_read (LDAP *ld, char *dn, char *rep, struct ldap_disptmpl *tmp);
34 static void report_ldap_err (LDAP *ldp, char *reply);
35 static void remove_trailing_space (char *s);
39 query_cmd( struct msginfo *msgp, char *reply )
42 LDAPMessage *ldmsgp, *entry;
44 int matches, rc, ld_errno, ufn;
47 struct ldap_disptmpl *tmpllist = NULL;
48 static char *attrs[] = { "cn", "title",
49 #ifdef RCPT500_SORT_ATTR
56 if ( msgp->msg_arg == NULL ) {
57 return( help_cmd( msgp, reply ));
60 remove_trailing_space( msgp->msg_arg );
61 if ( *msgp->msg_arg == '\0' ) {
62 return( help_cmd( msgp, reply ));
65 if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
66 strcat( reply, errpreface );
67 strcat( reply, "filter file configuration error. Try again later." );
72 * open connection to LDAP server and bind as dapuser
74 #ifdef LDAP_CONNECTIONLESS
76 ldp = cldap_open( ldaphost, ldapport );
78 #endif /* LDAP_CONNECTIONLESS */
79 ldp = ldap_init( ldaphost, ldapport );
82 strcat( reply, errpreface );
83 strcat( reply, "X.500 service unavailable. Try again later." );
84 ldap_getfilter_free( lfdp );
88 #ifdef LDAP_CONNECTIONLESS
90 #endif /* LDAP_CONNECTIONLESS */
91 if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
92 report_ldap_err( ldp, reply );
94 ldap_getfilter_free( lfdp );
99 * set options for search and build filter
101 ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
102 ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
107 #ifdef LDAP_CONNECTIONLESS
108 if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
109 #else /* LDAP_CONNECTIONLESS */
110 if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
111 #endif /* LDAP_CONNECTIONLESS */
114 ldap_ufn_setprefix( ldp, searchbase );
115 if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
116 != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
117 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
118 report_ldap_err( ldp, reply );
120 ldap_getfilter_free( lfdp );
123 matches = ldap_count_entries( ldp, ldmsgp );
126 #endif /* RCPT500_UFN */
128 for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
129 lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
130 #ifdef LDAP_CONNECTIONLESS
132 rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
133 lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
135 #endif /* LDAP_CONNECTIONLESS */
136 rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
137 lfi->lfi_filter, attrs, 0, &ldmsgp );
139 if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
140 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
141 report_ldap_err( ldp, reply );
143 ldap_getfilter_free( lfdp );
147 if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
151 if ( ldmsgp != NULL ) {
152 ldap_msgfree( ldmsgp );
157 #endif /* RCPT500_UFN */
159 if ( matches == 0 ) {
160 sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
161 strcat( reply, buf );
163 ldap_getfilter_free( lfdp );
168 ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
170 if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
171 || ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
172 strcat( reply, "(Partial results only - a limit was exceeded)\n" );
175 if ( matches <= RCPT500_LISTLIMIT ) {
176 sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
177 ufn ? "UFN" : lfi->lfi_desc,
178 ( matches > 1 ) ? "es" : "", msgp->msg_arg );
179 strcat( reply, buf );
181 if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
182 sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
183 errpreface, templatefile, rc );
184 strcat( reply, buf );
187 for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
188 dn = ldap_get_dn( ldp, entry );
189 if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
190 report_ldap_err( ldp, reply );
193 if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
194 strcat( reply, "\n-------\n\n" );
198 if ( tmpllist != NULL ) {
199 ldap_free_templates( tmpllist );
201 ldap_msgfree( ldmsgp );
204 sprintf( buf, "%d %s matches were found for '%s':\n",
205 matches, ufn ? "UFN" : lfi->lfi_desc, msgp->msg_arg );
206 strcat( reply, buf );
207 append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
208 ldap_msgfree( ldmsgp );
212 ldap_getfilter_free( lfdp );
218 close_ldap( LDAP *ld )
220 #ifdef LDAP_CONNECTIONLESS
224 #endif /* LDAP_CONNECTIONLESS */
230 append_entry_list( char *reply, char *query, LDAP *ldp, LDAPMessage *ldmsgp )
233 char *dn, *rdn, *s, **title;
236 #ifdef RCPT500_SORT_ATTR
237 ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
240 for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
241 e = ldap_next_entry( ldp, e )) {
242 dn = ldap_get_dn( ldp, e );
243 if (( s = strchr( dn, ',' )) != NULL ) {
246 if (( s = strchr( dn, '=' )) == NULL ) {
254 * if this entry's rdn is an exact match for the thing looked up, we
255 * return the CN that has a digit after it, so that the user is
256 * returned something guaranteed to yield exactly one match if they
257 * pick it from the list and query it
260 if ( strcasecmp( rdn, query ) == 0 ) {
264 if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
265 for ( i = 0; cn[i] != NULL; i++ ) {
266 if ( isdigit((unsigned char) cn[i][strlen( cn[i] ) - 1])) {
267 rdn = strdup( cn[i] );
272 ldap_value_free( cn );
277 title = ldap_get_values( ldp, e, "title" );
278 sprintf( buf, " %-20s %s\n", rdn, title ? title[0] : "" );
279 strcat( reply, buf );
280 if ( title != NULL ) {
281 ldap_value_free( title );
292 append_text( void *reply, char *text, ber_len_t len )
294 strcat( (char *) reply, text );
300 do_read( LDAP *ldp, char *dn, char *reply, struct ldap_disptmpl *tmpll )
303 static char *maildefvals[] = { "None registered in this service", NULL };
304 static char *defattrs[] = { "mail", NULL };
305 static char **defvals[] = { maildefvals, NULL };
308 rc = ldap_entry2text_search( ldp, dn, searchbase, NULL, tmpll,
309 defattrs, defvals, append_text, (void *)reply, "\n",
310 rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
317 report_ldap_err( LDAP *ldp, char *reply )
320 ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
322 strcat( reply, errpreface );
323 strcat( reply, ldap_err2string( ld_errno ));
324 strcat( reply, "\n" );
329 remove_trailing_space( char *s )
331 char *p = s + strlen( s ) - 1;
333 while ( isspace( (unsigned char) *p ) && p > s ) {