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