]> git.sur5r.net Git - openldap/blob - clients/ud/find.c
Remove lint
[openldap] / clients / ud / find.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * Copyright (c) 1991, 1992, 1993 
8  * Regents of the University of Michigan.  All rights reserved.
9  *
10  * Redistribution and use in source and binary forms are permitted
11  * provided that this notice is preserved and that due credit is given
12  * to the University of Michigan at Ann Arbor. The name of the University
13  * may not be used to endorse or promote products derived from this
14  * software without specific prior written permission. This software
15  * is provided ``as is'' without express or implied warranty.
16  */
17
18 #include "portable.h"
19
20 #include <stdio.h>
21
22 #include <ac/stdlib.h>
23
24 #include <ac/ctype.h>
25 #include <ac/string.h>
26 #include <ac/time.h>
27
28 #include <lber.h>
29 #include <ldap.h>
30
31 #include "ud.h"
32
33 static int num_picked = 0;      /* used when user picks entry at More prompt */
34
35
36 int
37 vrfy( char *dn )
38 {
39         LDAPMessage *results;
40         static char *attrs[2] = { "objectClass", NULL };
41         int ld_errno = 0;
42
43 #ifdef DEBUG
44         if (debug & D_TRACE)
45                 printf("->vrfy(%s)\n", dn);
46 #endif
47         /* verify that this DN exists in the directory */
48         (void) ldap_search_s(ld, dn, LDAP_SCOPE_BASE, "objectClass=*", attrs, TRUE, &results);
49         (void) ldap_msgfree(results);
50
51         ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
52
53         if ((ld_errno == LDAP_NO_SUCH_OBJECT) || (ld_errno == LDAP_INVALID_DN_SYNTAX))
54                 return(0);
55         else if (ld_errno == LDAP_SUCCESS)
56                 return(1);
57         else {
58                 ldap_perror(ld, "ldap_search");
59                 return(0);
60         }
61 }
62         
63
64 static LDAPMessage *
65 disambiguate( LDAPMessage *result, int matches, char **read_attrs, char *who )
66 {
67         int choice;                     /* entry that user chooses */
68         int i;
69         char *namelist[MAX_NUM_NAMES];  /* names found */
70         char response[SMALL_BUF_SIZE];  /* results from user */
71         char *name = NULL;              /* DN to lookup */
72         LDAPMessage *mp;
73         int ld_errno = 0;
74
75 #ifdef DEBUG
76         if (debug & D_TRACE)
77                 printf("->disambiguate(%x, %d, %x, %s)\n", result, matches, 
78                                                         read_attrs, who);
79 #endif
80
81         ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
82
83         /*
84          *  If we are here, it means that we got back multiple answers.
85          */
86         if ((ld_errno == LDAP_TIMELIMIT_EXCEEDED)
87             || (ld_errno == LDAP_SIZELIMIT_EXCEEDED)) {
88                 if (verbose) {
89                         printf("  Your query was too general and a limit was exceeded.  The results listed\n");
90                         printf("  are not complete.  You may want to try again with a more refined query.\n\n");
91                 }
92                 else
93                         printf("  Time or size limit exceeded.  Partial results follow.\n\n");
94         }
95         printf("  %1d names matched \"%s\".\n", matches, who);
96         for (;;) {
97                 printf("  Do you wish to see a list of names? ");
98                 fflush(stdout);
99                 (void) memset(response, 0, sizeof(response));
100                 fetch_buffer(response, sizeof(response), stdin);
101                 switch (response[0]) {
102                 case 'n' :
103                 case 'N' :
104                 case '\0' :
105                 case '\n' :
106                         return(NULL);
107                         /* NOTREACHED */
108                 case 'y' :
109                 case 'Y' :
110                         print_list(result, namelist, &matches);
111                         if (num_picked == 0)
112                                 choice = pick_one(matches);
113                         else
114                                 choice = num_picked;
115                         num_picked = 0;
116                         if (choice >= 0)
117                                 name = strdup(namelist[choice]);
118                         /*
119                          *  Now free up all of the pointers allocated in
120                          *  namelist.  The print_list() routine that filled
121                          *  in this collection of strings starts at 1, not 0.
122                          */
123                         for (i = 1; namelist[i] != NULL; i++)
124                                 Free(namelist[i]);
125                         if (choice < 0) {
126                                 if (name != NULL)
127                                         Free(name);
128                                 return(NULL);
129                         }
130 #ifdef DEBUG
131                         if (debug & D_FIND) {
132                                 printf("  Calling ldap_search_s()\n");
133                                 printf("     ld = 0x%x\n", ld);
134                                 printf("     search base = %s\n", name);
135                                 printf("     scope = LDAP_SCOPE_BASE\n");
136                                 printf("     filter = objectClass=*\n");
137                                 for (i = 0; read_attrs[i] != NULL; i++)
138                                         printf("     read_attrs[%d] = %s\n", i, read_attrs[i]);
139                                 printf("     read_attrs[%d] = NULL\n", i);
140                                 printf("     attrsonly = FALSE\n");
141                                 printf("     &mp = 0x%x\n", &mp);
142                         }
143 #endif
144                         if (ldap_search_s(ld, name, LDAP_SCOPE_BASE, "objectClass=*", read_attrs, FALSE, &mp) != LDAP_SUCCESS) {
145                                 ldap_perror(ld, "ldap_search_s");
146                                 Free(name);
147                                 ldap_msgfree(mp);
148                                 return(NULL);
149                         }
150                         Free(name);
151                         return(mp);
152                         /* NOTREACHED */
153                 default :
154                         printf("  Please enter 'y', 'n', or RETURN.\n");
155                         break;
156                 }
157         }
158 }
159
160 LDAPMessage *
161 find( char *who, int quiet )
162 {
163         register int i, j, k;           /* general ints */
164         int matches;                    /* from ldap_count_entries() */
165         int admonished = FALSE;
166         static int attrs_set = 0;
167         static char *read_attrs[MAX_ATTRS];     /* attrs to use in a read op */
168         static char *search_attrs[MAX_ATTRS];   /* attrs to use in a srch op */
169         static int rc;                  /* return from ldap_search */
170         LDAPMessage *ldtmp, *res;       /* results returned from search */
171         char name[MED_BUF_SIZE];
172         char response[SMALL_BUF_SIZE];
173         char *cp, *dn, **rdns;
174         LDAPFiltInfo *fi;
175
176 #ifdef DEBUG
177         if (debug & D_TRACE)
178                 fprintf(stderr, "->find(%s)\n", who);
179 #endif
180         /* did not specify a 'who' */
181         if (who == NULL) {
182                 printf("  Locate whose entry? ");
183                 fflush(stdout);
184                 fetch_buffer(name, sizeof(name), stdin);
185                 if (name[0] != '\0')
186                         who = name;
187                 else
188                         return(NULL);
189         }
190         if (attrs_set == 0) {
191                 j = k = 0;
192                 attrs_set = 1;
193                 for (i = 0; attrlist[i].quipu_name != NULL; i++) {
194                         if (attrlist[i].flags & ATTR_FLAG_READ)
195                                 read_attrs[j++] = attrlist[i].quipu_name;
196                         if (attrlist[i].flags & ATTR_FLAG_SEARCH)
197                                 search_attrs[k++] = attrlist[i].quipu_name;
198                 }
199                 read_attrs[j] = NULL;
200                 search_attrs[k] = NULL;
201         }
202
203         /*
204          *  If the user-supplied name has any commas in it, we
205          *  assume that it is a UFN, and do everything right
206          *  here.  If we don't find it, treat it as NOT a UFN.
207          */
208         if (strchr(who, ',') != NULL) {
209                 int     savederef, deref;
210 #ifdef DEBUG
211                 if (debug & D_FIND)
212                         printf("\"%s\" appears to be a UFN\n", who);
213 #endif
214                 ldap_get_option(ld, LDAP_OPT_DEREF, &savederef);
215                 deref = LDAP_DEREF_FINDING;
216                 ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
217
218                 if ((rc = ldap_ufn_search_s(ld, who, search_attrs, FALSE, &res)) !=
219                     LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED &&
220                     rc != LDAP_TIMELIMIT_EXCEEDED) {
221                         ldap_perror(ld, "ldap_ufn_search_s");
222                         ldap_set_option(ld, LDAP_OPT_DEREF, &savederef);
223                         return(NULL);
224                 }
225                 if ((matches = ldap_count_entries(ld, res)) < 0) {
226                         ldap_perror(ld, "ldap_count_entries");
227                         ldap_set_option(ld, LDAP_OPT_DEREF, &savederef);
228                         return(NULL);
229                 } else if (matches == 1) {
230                         dn = ldap_get_dn(ld, ldap_first_entry(ld, res));
231                         rc = ldap_search_s(ld, dn, LDAP_SCOPE_BASE, "objectClass=*", read_attrs, FALSE, &res);
232                         ldap_memfree(dn);
233                         if (rc != LDAP_SUCCESS) {
234                                 int ld_errno = 0;
235                                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
236                                 if (ld_errno == LDAP_UNAVAILABLE)
237                                         printf("  Could not contact the LDAP server to find \"%s\".\n", who);
238                                 else
239                                         ldap_perror(ld, "ldap_search_s");
240                                 return(NULL);
241                         }
242                         ldap_set_option(ld, LDAP_OPT_DEREF, &savederef);
243                         return(res);
244                 } else if (matches > 1 ) {
245                         return disambiguate( res, matches, read_attrs, who );
246                 }
247                 ldap_set_option(ld, LDAP_OPT_DEREF, &savederef);
248         }
249
250         /*
251          *  Old users of the MTS *USERDIRECTORY will likely wrap the name
252          *  in quotes.  Not only is this unnecessary, but it also won't work.
253          */
254         for (cp = strchr(who, '"'); cp != NULL; cp = strchr(cp, '"')) {
255                 if (!admonished) {
256                         printf("  You do not need to enclose names in quotes.\n");
257                         admonished = TRUE;
258                 }
259                 *cp++ = ' ';
260                 if (*cp == '\0')
261                         break;
262         }
263
264         /*
265          *  It wasn't a UFN, so look it up in the usual method.
266          */
267         for (fi = ldap_getfirstfilter(lfdp, "ud", who); fi != NULL;
268              fi = ldap_getnextfilter(lfdp)) {
269 #ifdef DEBUG
270                 if (debug & D_FIND)
271                         printf("Searching, filter = %s\n", fi->lfi_filter);
272 #endif
273
274                 if ((rc = ldap_search_s(ld, search_base, fi->lfi_scope, 
275                 fi->lfi_filter, search_attrs, FALSE, &res)) != LDAP_SUCCESS &&
276                 rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_TIMELIMIT_EXCEEDED) {
277                         ldap_perror(ld, "ldap_search_s");
278                         ldap_msgfree(res);
279                         return(NULL);
280                 }
281                 if ((matches = ldap_count_entries(ld, res)) < 0) {
282                         ldap_perror(ld, "ldap_count_entries");
283                         ldap_msgfree(res);
284                         return(NULL);
285                 }
286                 else if (matches == 1) {
287                         dn = ldap_get_dn(ld, ldap_first_entry(ld, res));
288                         ldap_msgfree(res);
289                         if (!quiet)
290                                 printf("  Found one %s match for \"%s\"\n", 
291                                                         fi->lfi_desc, who);
292                         if (!fi->lfi_isexact) {
293                                 rdns = ldap_explode_dn(dn, TRUE);
294                                 printf("  Do you mean %s? ", *rdns);
295                                 (void) ldap_value_free(rdns);
296                                 fflush(stdout);
297                                 fetch_buffer(response, sizeof(response), stdin);
298                                 if ((response[0] == 'n') || (response[0] == 'N'))
299                                 {
300                                         ldap_memfree(dn);
301                                         return(NULL);
302                                 }
303                         }
304 #ifdef DEBUG
305                         if (debug & D_FIND) {
306                                 printf("  Calling ldap_search_s()\n");
307                                 printf("     ld = 0x%x\n", ld);
308                                 printf("     dn = %s\n", dn);
309                                 printf("     scope = LDAP_SCOPE_BASE\n");
310                                 printf("     filter = %s\n", "objectClass=*");
311                                 for (i = 0; read_attrs[i] != NULL; i++)
312                                         printf("     read_attrs[%d] = %s\n", i, read_attrs[i]);
313                                 printf("     read_attrs[%d] = NULL\n", i);
314                                 printf("     attrsonly = FALSE\n");
315                                 printf("     &results = 0x%x\n", &res);
316                         }
317 #endif
318                         if (ldap_search_s(ld, dn, LDAP_SCOPE_BASE, "objectClass=*", read_attrs, FALSE, &res) != LDAP_SUCCESS) {
319                                 ldap_perror(ld, "ldap_search_s");
320                                 ldap_msgfree(res);
321                                 res = NULL;
322                         }
323                         ldap_memfree(dn);
324                         return(res);
325                 }
326                 else if (matches > 0) {
327                         ldtmp = disambiguate(res, matches, read_attrs, who);
328                         ldap_msgfree(res);
329                         return(ldtmp);
330                 }
331                 /* if we're here, there were zero matches */
332                 ldap_msgfree(res);
333         }
334         return(NULL);
335 }
336
337 int
338 pick_one( int i )
339 {
340         int n;
341         char user_pick[SMALL_BUF_SIZE];
342
343 #ifdef DEBUG
344         if (debug & D_TRACE)
345                 printf("->pick_one(%d)\n", i);
346 #endif
347         
348         /* make the user pick an entry */
349         for (;;) {
350                 printf("  Enter the number of the name you want or Q to quit: ");
351                 fflush(stdout);
352                 fetch_buffer(user_pick, sizeof(user_pick), stdin);
353                 if (user_pick[0] == 'q' || user_pick[0] == 'Q')
354                         return(-1);
355                 n = atoi(user_pick);
356                 if ((n > 0) && (n <= i))
357                         return(n);
358                 printf("  Invalid response\n");
359         }
360         /* NOTREACHED */
361 }
362
363 void
364 print_list( LDAPMessage *list, char **names, int *matches )
365 {
366         char **rdns, **cpp;
367         char resp[SMALL_BUF_SIZE];
368         register LDAPMessage *ep;
369         register int i = 1;
370         register int rest = 4;          /* 4, not 1 */
371
372 #ifdef DEBUG
373         if (debug & D_TRACE)
374                 printf("->print_list(%x, %x, %x)\n", list, names, matches);
375 #endif
376         /* print a list of names from which the user will select */
377         for (ep = ldap_first_entry(ld, list); ep != NULL; ep = ldap_next_entry(ld, ep)) {
378                 
379                 names[i] = ldap_get_dn(ld, ep);
380                 rdns = ldap_explode_dn(names[i], TRUE);
381                 cpp = ldap_get_values(ld, ep, "title");
382                 if (cpp == NULL)
383                         printf(" %3d. %s\n", i, *rdns);
384                 else
385                         printf(" %3d. %s, %s\n", i, *rdns, *cpp);
386                 ldap_value_free(rdns);
387                 ldap_value_free(cpp);
388                 i++;
389                 if ((rest++ > (lpp - 1)) && (i < *matches)) {
390 again:
391                         printf("  More? ");
392                         fflush(stdout);
393                         fetch_buffer(resp, sizeof(resp), stdin);
394                         if ((resp[0] == 'n') || (resp[0] == 'N'))
395                                 break;
396                         else if ((num_picked = atoi(resp)) != 0) {
397                                 if (num_picked < i)
398                                         break;
399                                 else
400                                         goto again;
401                         }
402                         rest = 1;
403                 }
404         }
405         *matches = i - 1;
406         names[i] = NULL;
407         return;
408 }
409
410 int
411 find_all_subscribers( char **sub, char *group )
412 {
413         int count;
414         LDAPMessage *result;
415         static char *attributes[] = { "cn", NULL };
416         char filter[MED_BUF_SIZE];
417         register LDAPMessage *ep;
418         register int i = 0;
419
420 #ifdef DEBUG
421         if (debug & D_TRACE)
422                 printf("->find_all_subscribers(%x, %s)\n", sub, group);
423 #endif
424
425         sprintf(filter, "%s=%s", "memberOfGroup", group);
426         if (ldap_search_s(ld, search_base, LDAP_SCOPE_SUBTREE, filter, attributes, FALSE, &result) != LDAP_SUCCESS) {
427                 int ld_errno = 0;
428                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
429                 if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
430                         return(0);
431                 ldap_perror(ld, "ldap_search_s");
432                 return(0);
433         }
434         count = ldap_count_entries(ld, result);
435         if (count < 1) {
436                 ldap_msgfree(result);
437                 return(0);
438         }
439         if ( count > MAX_VALUES ) {
440                 printf( "  Only retrieving the first %d subscribers....\n",
441                         MAX_VALUES );
442         }
443
444         for (ep = ldap_first_entry(ld, result); i < MAX_VALUES && ep != NULL; ep = ldap_next_entry(ld, ep)) {
445                 sub[i++] = ldap_get_dn(ld, ep);
446 #ifdef DEBUG
447                 if (debug & D_PARSE)
448                         printf("sub[%d] = %s\n", i - 1, sub[i - 1]);
449 #endif
450         }
451         sub[i] = NULL;
452         ldap_msgfree(result);
453         return(count);
454 }
455
456 char *
457 fetch_boolean_value( char *who, struct attribute attr )
458 {
459         LDAPMessage *result;            /* from the search below */
460         register LDAPMessage *ep;       /* entry pointer */
461         register char **vp;             /* for parsing the result */
462         static char *attributes[] = { NULL, NULL };
463
464 #ifdef DEBUG
465         if (debug & D_TRACE)
466                 printf("->fetch_boolean_value(%s, %s)\n", who, attr.quipu_name);
467 #endif
468         attributes[0] = attr.quipu_name;
469         if (ldap_search_s(ld, who, LDAP_SCOPE_BASE, "objectClass=*", attributes, FALSE, &result) != LDAP_SUCCESS) {
470                 int ld_errno = 0;
471                 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
472                 if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
473                         return("FALSE");
474                 ldap_perror(ld, "ldap_search_s");
475                 ldap_msgfree(result);
476                 return(NULL);
477         }
478
479         /*
480          *  We did a read on one name and only asked for one attribute.
481          *  There's no reason to loop through any of these structures.
482          *
483          *  If ldap_first_attribute() returns NULL, then this entry did
484          *  not have this particular attribute.
485          */
486         ep = ldap_first_entry(ld, result);
487         if ((vp = (char **) ldap_get_values(ld, ep, attr.quipu_name)) == NULL) {
488                 ldap_msgfree(result);
489                 return("FALSE");
490         }
491         else {
492                 ldap_msgfree(result);
493                 if (!strcasecmp(*vp, "TRUE")) {
494                         ldap_value_free(vp);
495                         return("TRUE");
496                 }
497                 else if (!strcasecmp(*vp, "FALSE")) {
498                         ldap_value_free(vp);
499                         return("FALSE");
500                 }
501                 else {
502                         fprintf(stderr, "  Got garbage -> [%s]\n", *vp);
503                         ldap_value_free(vp);
504                         return(NULL);
505                 }
506         }
507 }