]> git.sur5r.net Git - openldap/blob - clients/rcpt500/query.c
struct ldap is now opaque to clients.
[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 "portable.h"
10
11 #include <stdio.h>
12 #include <ctype.h>
13
14 #include <ac/string.h>
15 #include <ac/syslog.h>
16 #include <ac/time.h>
17
18 #include "lber.h"
19 #include "ldap.h"
20
21 #include "disptmpl.h"
22
23 #include "rcpt500.h"
24 #include "ldapconfig.h"
25
26 extern int dosyslog;
27 extern int do_cldap;
28 extern int rdncount;
29 extern int derefaliases;
30 extern int sizelimit;
31 extern int ldapport;
32 extern char *ldaphost;
33 extern char *searchbase;
34 extern char *dapuser;
35 extern char *filterfile;
36 extern char *templatefile;
37
38 static char buf[ MAXSIZE ];
39 static char *errpreface = "Your query failed: ";
40
41 extern int      strcasecmp();
42
43 void close_ldap();
44
45
46 int
47 query_cmd( msgp, reply )
48     struct msginfo      *msgp;
49     char                *reply;
50 {
51     LDAP                        *ldp;
52     LDAPMessage                 *ldmsgp, *entry;
53     char                        *s, *dn;
54     int                         matches, rc, ld_errno, ufn;
55     LDAPFiltDesc                *lfdp;
56     LDAPFiltInfo                *lfi;
57     struct ldap_disptmpl        *tmpllist = NULL;
58     static char *attrs[] = { "cn", "title",
59 #ifdef RCPT500_SORT_ATTR
60                         RCPT500_SORT_ATTR,
61 #endif
62                         NULL };
63
64     ufn = 0;
65
66     if ( msgp->msg_arg == NULL ) {
67         return( help_cmd( msgp, reply ));
68     }
69
70     remove_trailing_space( msgp->msg_arg );
71     if ( *msgp->msg_arg == '\0' ) {
72         return( help_cmd( msgp, reply ));
73     }
74
75     if (( lfdp = ldap_init_getfilter( filterfile )) == NULL ) {
76         strcat( reply, errpreface );
77         strcat( reply, "filter file configuration error.  Try again later." );
78         return( 0 );
79     }
80
81     /*
82      * open connection to LDAP server and bind as dapuser
83      */
84 #ifdef LDAP_CONNECTIONLESS
85     if ( do_cldap )
86         ldp = cldap_open( ldaphost, ldapport );
87     else
88 #endif /* LDAP_CONNECTIONLESS */
89         ldp = ldap_open( ldaphost, ldapport );
90
91     if ( ldp == NULL ) {
92         strcat( reply, errpreface );
93         strcat( reply, "X.500 service unavailable.  Try again later." );
94         ldap_getfilter_free( lfdp );
95         return( 0 );
96     }
97
98 #ifdef LDAP_CONNECTIONLESS
99     if ( !do_cldap )
100 #endif /* LDAP_CONNECTIONLESS */
101         if ( ldap_simple_bind_s( ldp, dapuser, NULL ) != LDAP_SUCCESS ) {
102             report_ldap_err( ldp, reply );
103             close_ldap( ldp );
104             ldap_getfilter_free( lfdp );
105             return( 0 );
106         }
107
108     /*
109      * set options for search and build filter
110      */
111         ldap_set_option(ldp, LDAP_OPT_DEREF, &derefaliases);
112         ldap_set_option(ldp, LDAP_OPT_SIZELIMIT, &sizelimit);
113
114     matches = 0;
115
116 #ifdef RCPT500_UFN
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 */
122         struct timeval  tv;
123
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 );
129             close_ldap( ldp );
130             ldap_getfilter_free( lfdp );
131             return( 0 );
132         }
133         matches = ldap_count_entries( ldp, ldmsgp );
134         ufn = 1;
135     } else {
136 #endif /* RCPT500_UFN */
137     
138         for ( lfi = ldap_getfirstfilter( lfdp, "rcpt500", msgp->msg_arg );
139                 lfi != NULL; lfi = ldap_getnextfilter( lfdp )) {
140 #ifdef LDAP_CONNECTIONLESS
141             if ( do_cldap )
142                 rc = cldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
143                         lfi->lfi_filter, attrs, 0, &ldmsgp, dapuser );
144             else 
145 #endif /* LDAP_CONNECTIONLESS */
146                 rc = ldap_search_s( ldp, searchbase, LDAP_SCOPE_SUBTREE,
147                         lfi->lfi_filter, attrs, 0, &ldmsgp );
148
149             if ( rc != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED
150                     && rc != LDAP_TIMELIMIT_EXCEEDED ) {
151                 report_ldap_err( ldp, reply );
152                 close_ldap( ldp );
153                 ldap_getfilter_free( lfdp );
154                 return( 0 );
155             }
156
157             if (( matches = ldap_count_entries( ldp, ldmsgp )) != 0 ) {
158                 break;
159             }
160
161             if ( ldmsgp != NULL ) {
162                 ldap_msgfree( ldmsgp );
163             }
164         }
165 #ifdef RCPT500_UFN
166     }
167 #endif /* RCPT500_UFN */
168
169     if ( matches == 0 ) {
170         sprintf( buf, "No matches were found for '%s'\n", msgp->msg_arg );
171         strcat( reply, buf );
172         close_ldap( ldp );
173         ldap_getfilter_free( lfdp );
174         return( 0 );
175     }
176
177         ld_errno = 0;
178         ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
179
180     if ( ld_errno == LDAP_TIMELIMIT_EXCEEDED
181             || ld_errno == LDAP_SIZELIMIT_EXCEEDED ) {
182         strcat( reply, "(Partial results only - a limit was exceeded)\n" );
183     }
184
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 );
190
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 );
195         }
196
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 );
201             }
202             free( dn );
203             if (( entry = ldap_next_entry( ldp, entry )) != NULL ) {
204                 strcat( reply, "\n-------\n\n" );
205             }
206         }
207
208         if ( tmpllist != NULL ) {
209             ldap_free_templates( tmpllist );
210         }
211         ldap_msgfree( ldmsgp );
212
213     } else {
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 );
219     }
220
221     close_ldap( ldp );
222     ldap_getfilter_free( lfdp );
223     return( 0 );
224 }
225
226
227 void
228 close_ldap( LDAP *ld )
229 {
230 #ifdef LDAP_CONNECTIONLESS
231     if ( do_cldap )
232         cldap_close( ld );
233     else
234 #endif /* LDAP_CONNECTIONLESS */
235         ldap_unbind( ld );
236 }
237
238
239 append_entry_list( reply, query, ldp, ldmsgp )
240     char        *reply;
241     char        *query;
242     LDAP        *ldp;
243     LDAPMessage *ldmsgp;
244 {
245     LDAPMessage *e;
246     char        *dn, *rdn, *s, **title;
247     int         free_rdn = 0;
248
249 #ifdef RCPT500_SORT_ATTR
250     ldap_sort_entries( ldp, &ldmsgp, RCPT500_SORT_ATTR, strcasecmp );
251 #endif
252
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 ) {
257             *s = '\0';
258         }
259         if (( s = strchr( dn, '=' )) == NULL ) {
260             rdn = dn;
261         } else {
262             rdn = s + 1;
263         }
264
265 #ifdef UOFM
266         /*
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
271          */
272
273         if ( strcasecmp( rdn, query ) == 0 ) {
274             char        **cn;
275             int         i;
276
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] );
281                         free_rdn = 1;
282                         break;
283                     }
284                 }
285                 ldap_value_free( cn );
286             }
287         }
288 #endif /* UOFM */
289
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 );
295         }
296         free( dn );
297         if ( free_rdn ) {
298             free( rdn );
299         }
300     }
301 }
302
303
304 int
305 append_text( reply, text, len )
306     char        *reply;
307     char        *text;
308     int         len;
309 {
310     strcat( reply, text );
311     return( len );
312 }
313     
314
315 int
316 do_read( ldp, dn, reply, tmpll )
317     LDAP                        *ldp;
318     char                        *dn;
319     char                        *reply;
320     struct ldap_disptmpl        *tmpll;
321 {
322     int                         rc;
323     static char *maildefvals[] = { "None registered in this service", NULL };
324     static char *defattrs[] = { "mail", NULL };
325     static char **defvals[] = { maildefvals, NULL };
326
327
328     rc = ldap_entry2text_search( ldp, dn, searchbase, NULLMSG, tmpll,
329             defattrs, defvals, append_text, (void *)reply, "\n",
330             rdncount, LDAP_DISP_OPT_DOSEARCHACTIONS );
331
332     return( rc );
333 }
334
335
336 report_ldap_err( ldp, reply )
337     LDAP        *ldp;
338     char        *reply;
339 {
340         int ld_errno = 0;
341         ldap_get_option(ldp, LDAP_OPT_ERROR_NUMBER, &ld_errno);
342
343     strcat( reply, errpreface );
344     strcat( reply, ldap_err2string( ld_errno ));
345     strcat( reply, "\n" );
346 }
347
348
349 remove_trailing_space( s )
350     char        *s;
351 {
352     char        *p = s + strlen( s ) - 1;
353
354     while ( isspace( *p ) && p > s ) {
355         --p;
356     }
357     *(++p) = '\0';
358 }