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