]> git.sur5r.net Git - openldap/blob - clients/rcpt500/query.c
Check LOCK_ID() return
[openldap] / clients / rcpt500 / query.c
1 /*
2  * query.c: for rcpt500 (X.500 email query responder)
3  *
4  * 18 June 1992 by Mark C Smith
5  * Copyright (c) 1992 The Regents of The University of Michigan
6  * All Rights Reserved
7  */
8
9 #include <stdio.h>
10 #include <syslog.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <sys/time.h>
14
15 #include "lber.h"
16 #include "ldap.h"
17 #include "portable.h"
18 #include "ldapconfig.h"
19 #include "disptmpl.h"
20 #include "rcpt500.h"
21
22 extern int dosyslog;
23 extern int do_cldap;
24 extern int rdncount;
25 extern int derefaliases;
26 extern int sizelimit;
27 extern int ldapport;
28 extern char *ldaphost;
29 extern char *searchbase;
30 extern char *dapuser;
31 extern char *filterfile;
32 extern char *templatefile;
33
34 static char buf[ MAXSIZE ];
35 static char *errpreface = "Your query failed: ";
36
37 extern int      strcasecmp();
38
39 void close_ldap();
40
41
42 int
43 query_cmd( msgp, reply )
44     struct msginfo      *msgp;
45     char                *reply;
46 {
47     LDAP                        *ldp;
48     LDAPMessage                 *ldmsgp, *entry;
49     char                        *s, *dn;
50     int                         matches, rc, ufn;
51     LDAPFiltDesc                *lfdp;
52     LDAPFiltInfo                *lfi;
53     struct ldap_disptmpl        *tmpllist = NULL;
54     static char *attrs[] = { "cn", "title",
55 #ifdef RCPT500_SORT_ATTR
56                         RCPT500_SORT_ATTR,
57 #endif
58                         NULL };
59
60     ufn = 0;
61
62     if ( msgp->msg_arg == NULL ) {
63         return( help_cmd( msgp, reply ));
64     }
65
66     remove_trailing_space( msgp->msg_arg );
67     if ( *msgp->msg_arg == '\0' ) {
68         return( help_cmd( msgp, reply ));
69     }
70
71     if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
72         strcat( reply, errpreface );
73         strcat( reply, "filter file configuration error.  Try again later." );
74         return( 0 );
75     }
76
77     /*
78      * open connection to LDAP server and bind as dapuser
79      */
80 #ifdef CLDAP
81     if ( do_cldap )
82         ldp = cldap_open( ldaphost, ldapport );
83     else
84 #endif /* CLDAP */
85         ldp = ldap_open( ldaphost, ldapport );
86
87     if ( ldp == NULL ) {
88         strcat( reply, errpreface );
89         strcat( reply, "X.500 service unavailable.  Try again later." );
90         ldap_getfilter_free( lfdp );
91         return( 0 );
92     }
93
94 #ifdef CLDAP
95     if ( !do_cldap )
96 #endif /* CLDAP */
97         if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
98             report_ldap_err( ldp, reply );
99             close_ldap( ldp );
100             ldap_getfilter_free( lfdp );
101             return( 0 );
102         }
103
104     /*
105      * set options for search and build filter
106      */
107     ldp->ld_deref = derefaliases;
108     ldp->ld_sizelimit = sizelimit;
109
110     matches = 0;
111
112 #ifdef RCPT500_UFN
113 #ifdef CLDAP
114     if ( !do_cldap && strchr( msgp->msg_arg, ',' ) != NULL ) {
115 #else /* CLDAP */
116     if ( strchr( msgp->msg_arg, ',' ) != NULL ) {
117 #endif /* CLDAP */
118         struct timeval  tv;
119
120         ldap_ufn_setprefix( ldp, searchbase );
121         if (( rc = ldap_ufn_search_s( ldp, msgp->msg_arg, attrs, 0, &ldmsgp ))
122                 != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
123                 && rc != LDAP_TIMELIMIT_EXCEEDED ) {
124             report_ldap_err( ldp, reply );
125             close_ldap( ldp );
126             ldap_getfilter_free( lfdp );
127             return( 0 );
128         }
129         matches = ldap_count_entries( ldp, ldmsgp );
130         ufn = 1;
131     } else {
132 #endif /* RCPT500_UFN */
133     
134         for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
135                 lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
136 #ifdef CLDAP
137             if ( do_cldap )
138                 rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
139                         lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
140             else 
141 #endif /* CLDAP */
142                 rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
143                         lfi->lfi_filter, attrs, 0, &ldmsgp );
144
145             if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
146                     && rc != LDAP_TIMELIMIT_EXCEEDED ) {
147                 report_ldap_err( ldp, reply );
148                 close_ldap( ldp );
149                 ldap_getfilter_free( lfdp );
150                 return( 0 );
151             }
152
153             if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
154                 break;
155             }
156
157             if ( ldmsgp != NULL ) {
158                 ldap_msgfree( ldmsgp );
159             }
160         }
161 #ifdef RCPT500_UFN
162     }
163 #endif /* RCPT500_UFN */
164
165     if ( matches == 0 ) {
166         sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
167         strcat( reply, buf );
168         close_ldap( ldp );
169         ldap_getfilter_free( lfdp );
170         return( 0 );
171     }
172
173     if ( ldp->ld_errno == LDAP_TIMELIMIT_EXCEEDED
174             || ldp->ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
175         strcat( reply, "(Partial results only - a limit was exceeded)\n" );
176     }
177
178     if ( matches <= RCPT500_LISTLIMIT ) {
179         sprintf( buf, "%d %s match%s found for '%s':\n\n", matches,
180                 ufn ? "UFN" : lfi->lfi_desc,
181                 ( matches > 1 ) ? "es" : "", msgp->msg_arg );
182         strcat( reply, buf );
183
184         if (( rc = ldap_init_templates( templatefile, &tmpllist )) != 0 ) {
185             sprintf( buf, "%s ldap_init_templates( %s ) failed (error %d)\n",
186                 errpreface, templatefile, rc );
187             strcat( reply, buf );
188         }
189
190         for ( entry = ldap_first_entry( ldp, ldmsgp ); entry != NULL; ) {
191             dn = ldap_get_dn( ldp, entry );
192             if ( do_read( ldp, dn, reply, tmpllist ) != LDAP_SUCCESS ) {
193                 report_ldap_err( ldp, reply );
194             }
195             free( dn );
196             if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
197                 strcat( reply, "\n-------\n\n" );
198             }
199         }
200
201         if ( tmpllist != NULL ) {
202             ldap_free_templates( tmpllist );
203         }
204         ldap_msgfree( ldmsgp );
205
206     } else {
207         sprintf( buf, "%d %s matches were found for '%s':\n",
208                 matches, ufn ? "UFN" : lfi->lfi_desc, msgp->msg_arg );
209         strcat( reply, buf );
210         append_entry_list( reply, msgp->msg_arg, ldp, ldmsgp );
211         ldap_msgfree( ldmsgp );
212     }
213
214     close_ldap( ldp );
215     ldap_getfilter_free( lfdp );
216     return( 0 );
217 }
218
219
220 void
221 close_ldap( LDAP *ld )
222 {
223 #ifdef CLDAP
224     if ( do_cldap )
225         cldap_close( ld );
226     else
227 #endif /* CLDAP */
228         ldap_unbind( ld );
229 }
230
231
232 append_entry_list( reply, query, ldp, ldmsgp )
233     char        *reply;
234     char        *query;
235     LDAP        *ldp;
236     LDAPMessage *ldmsgp;
237 {
238     LDAPMessage *e;
239     char        *dn, *rdn, *s, **title;
240     int         free_rdn = 0;
241
242 #ifdef RCPT500_SORT_ATTR
243     ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
244 #endif
245
246     for ( e = ldap_first_entry( ldp, ldmsgp ); e != NULL;
247                 e = ldap_next_entry( ldp, e )) {
248         dn = ldap_get_dn( ldp, e );
249         if (( s = strchr( dn, ',' )) != NULL ) {
250             *s = '\0';
251         }
252         if (( s = strchr( dn, '=' )) == NULL ) {
253             rdn = dn;
254         } else {
255             rdn = s + 1;
256         }
257
258 #ifdef UOFM
259         /*
260          * if this entry's rdn is an exact match for the thing looked up, we
261          * return the CN that has a digit after it, so that the user is
262          * returned something guaranteed to yield exactly one match if they
263          * pick it from the list and query it
264          */
265
266         if ( strcasecmp( rdn, query ) == 0 ) {
267             char        **cn;
268             int         i;
269
270             if (( cn = ldap_get_values( ldp, e, "cn" )) != NULL ) {
271                 for ( i = 0; cn[i] != NULL; i++ ) {
272                     if ( isdigit( *( cn[i] + strlen( cn[i] ) - 1 ))) {
273                         rdn = strdup( cn[i] );
274                         free_rdn = 1;
275                         break;
276                     }
277                 }
278                 ldap_value_free( cn );
279             }
280         }
281 #endif /* UOFM */
282
283         title = ldap_get_values( ldp, e, "title" );
284         sprintf( buf, "  %-20s    %s\n", rdn, title ? title[0] : "" );
285         strcat( reply, buf );
286         if ( title != NULL ) {
287             ldap_value_free( title );
288         }
289         free( dn );
290         if ( free_rdn ) {
291             free( rdn );
292         }
293     }
294 }
295
296
297 int
298 append_text( reply, text, len )
299     char        *reply;
300     char        *text;
301     int         len;
302 {
303     strcat( reply, text );
304     return( len );
305 }
306     
307
308 int
309 do_read( ldp, dn, reply, tmpll )
310     LDAP                        *ldp;
311     char                        *dn;
312     char                        *reply;
313     struct ldap_disptmpl        *tmpll;
314 {
315     int                         rc;
316     static char *maildefvals[] = { "None registered in this service", NULL };
317     static char *defattrs[] = { "mail", NULL };
318     static char **defvals[] = { maildefvals, NULL };
319
320
321     rc = ldap_entry2text_search( ldp, dn, searchbase, NULLMSG, tmpll,
322             defattrs, defvals, (void *)append_text, (void *)reply, "\n",
323             rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
324
325     return( rc );
326 }
327
328
329 report_ldap_err( ldp, reply )
330     LDAP        *ldp;
331     char        *reply;
332 {
333     strcat( reply, errpreface );
334     strcat( reply, ldap_err2string( ldp->ld_errno ));
335     strcat( reply, "\n" );
336 }
337
338
339 remove_trailing_space( s )
340     char        *s;
341 {
342     char        *p = s + strlen( s ) - 1;
343
344     while ( isspace( *p ) && p > s ) {
345         --p;
346     }
347     *(++p) = '\0';
348 }