]> git.sur5r.net Git - openldap/blob - clients/tools/ldapwhoami.c
Sync with HEAD
[openldap] / clients / tools / ldapwhoami.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdlib.h>
12
13 #include <ac/ctype.h>
14 #include <ac/signal.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
17 #include <ac/time.h>
18 #include <ac/unistd.h>
19
20 #include <ldap.h>
21
22 #include "lutil_ldap.h"
23 #include "ldap_defaults.h"
24
25 static int      verbose = 0;
26
27 static void
28 usage(const char *s)
29 {
30         fprintf(stderr,
31 "Issue LDAP Who am I? operation to request user's authzid\n\n"
32 "usage: %s [options]\n"
33
34 "Common options:\n"
35 "  -d level   set LDAP debugging level to `level'\n"
36 "  -D binddn  bind DN\n"
37 "  -f file    read operations from `file'\n"
38 "  -h host    LDAP server(s)\n"
39 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
40 "  -I         use SASL Interactive mode\n"
41 "  -n         show what would be done but don't actually do it\n"
42 "  -O props   SASL security properties\n"
43 "  -p port    port on LDAP server\n"
44 "  -Q         use SASL Quiet mode\n"
45 "  -R realm   SASL realm\n"
46 "  -U authcid SASL authentication identity\n"
47 "  -v         run in verbose mode (diagnostics to standard output)\n"
48 "  -w passwd  bind passwd (for simple authentication)\n"
49 "  -W         prompt for bind passwd\n"
50 "  -x         Simple authentication\n"
51 "  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
52 "  -Y mech    SASL mechanism\n"
53 "  -Z         Start TLS request (-ZZ to require successful response)\n"
54                 , s );
55
56         exit( EXIT_FAILURE );
57 }
58
59 int
60 main( int argc, char *argv[] )
61 {
62         int rc;
63         char    *prog = NULL;
64         char    *ldaphost = NULL;
65         char    *ldapuri = NULL;
66
67         char    *user = NULL;
68         char    *binddn = NULL;
69
70         struct berval passwd = { 0, NULL };
71         char    *newpw = NULL;
72         char    *oldpw = NULL;
73
74         int             want_bindpw = 0;
75         int             want_newpw = 0;
76         int             want_oldpw = 0;
77
78         int             not = 0;
79         int             i;
80         int             ldapport = 0;
81         int             debug = 0;
82         int             version = -1;
83         int             authmethod = -1;
84         int             manageDSAit = 0;
85 #ifdef HAVE_CYRUS_SASL
86         unsigned        sasl_flags = LDAP_SASL_AUTOMATIC;
87         char            *sasl_realm = NULL;
88         char            *sasl_authc_id = NULL;
89         char            *sasl_authz_id = NULL;
90         char            *sasl_mech = NULL;
91         char            *sasl_secprops = NULL;
92 #endif
93         int             use_tls = 0;
94         int             referrals = 0;
95         LDAP           *ld = NULL;
96
97         int id, code = LDAP_OTHER;
98         LDAPMessage *res;
99         char *matcheddn = NULL, *text = NULL, **refs = NULL;
100         char    *retoid = NULL;
101         struct berval *retdata = NULL;
102
103     prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1;
104
105         while( (i = getopt( argc, argv, "Aa:Ss:"
106                 "Cd:D:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF )
107         {
108                 switch (i) {
109                 /* Password Options */
110                 case 'A':       /* prompt for old password */
111                         want_oldpw++;
112                         break;
113
114                 case 'a':       /* old password (secret) */
115                         oldpw = strdup (optarg);
116
117                         {
118                                 char* p;
119
120                                 for( p = optarg; *p != '\0'; p++ ) {
121                                         *p = '\0';
122                                 }
123                         }
124                         break;
125
126                 case 'S':       /* prompt for user password */
127                         want_newpw++;
128                         break;
129
130                 case 's':       /* new password (secret) */
131                         newpw = strdup (optarg);
132                         {
133                                 char* p;
134
135                                 for( p = optarg; *p != '\0'; p++ ) {
136                                         *p = '\0';
137                                 }
138                         }
139                         break;
140
141         /* Common Options (including options we don't use) */
142         case 'C':
143                 referrals++;
144                 break;
145         case 'd':
146             debug |= atoi( optarg );
147             break;
148         case 'D':       /* bind DN */
149                 if( binddn != NULL ) {
150                         fprintf( stderr, "%s: -D previously specified\n", prog );
151                         return EXIT_FAILURE;
152                 }
153             binddn = strdup( optarg );
154             break;
155         case 'h':       /* ldap host */
156                 if( ldapuri != NULL ) {
157                         fprintf( stderr, "%s: -h incompatible with -H\n", prog );
158                         return EXIT_FAILURE;
159                 }
160                 if( ldaphost != NULL ) {
161                         fprintf( stderr, "%s: -h previously specified\n", prog );
162                         return EXIT_FAILURE;
163                 }
164             ldaphost = strdup( optarg );
165             break;
166         case 'H':       /* ldap URI */
167                 if( ldaphost != NULL ) {
168                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
169                         return EXIT_FAILURE;
170                 }
171                 if( ldapport ) {
172                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
173                         return EXIT_FAILURE;
174                 }
175                 if( ldapuri != NULL ) {
176                         fprintf( stderr, "%s: -H previously specified\n", prog );
177                         return EXIT_FAILURE;
178                 }
179             ldapuri = strdup( optarg );
180             break;
181         case 'I':
182 #ifdef HAVE_CYRUS_SASL
183                 if( version == LDAP_VERSION2 ) {
184                         fprintf( stderr, "%s: -I incompatible with version %d\n",
185                                 prog, version );
186                         return EXIT_FAILURE;
187                 }
188                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
189                         fprintf( stderr, "%s: incompatible previous "
190                                 "authentication choice\n",
191                                 prog );
192                         return EXIT_FAILURE;
193                 }
194                 authmethod = LDAP_AUTH_SASL;
195                 version = LDAP_VERSION3;
196                 sasl_flags = LDAP_SASL_INTERACTIVE;
197                 break;
198 #else
199                 fprintf( stderr, "%s: was not compiled with SASL support\n",
200                         prog );
201                 return( EXIT_FAILURE );
202 #endif
203         case 'k':       /* kerberos bind */
204 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
205                 if( version > LDAP_VERSION2 ) {
206                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
207                                 prog, version );
208                         return EXIT_FAILURE;
209                 }
210
211                 if( authmethod != -1 ) {
212                         fprintf( stderr, "%s: -k incompatible with previous "
213                                 "authentication choice\n", prog );
214                         return EXIT_FAILURE;
215                 }
216                         
217                 authmethod = LDAP_AUTH_KRBV4;
218 #else
219                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
220                 return EXIT_FAILURE;
221 #endif
222             break;
223         case 'K':       /* kerberos bind, part one only */
224 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
225                 if( version > LDAP_VERSION2 ) {
226                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
227                                 prog, version );
228                         return EXIT_FAILURE;
229                 }
230                 if( authmethod != -1 ) {
231                         fprintf( stderr, "%s: incompatible with previous "
232                                 "authentication choice\n", prog );
233                         return EXIT_FAILURE;
234                 }
235
236                 authmethod = LDAP_AUTH_KRBV41;
237 #else
238                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
239                 return( EXIT_FAILURE );
240 #endif
241             break;
242         case 'M':
243                 /* enable Manage DSA IT */
244                 if( version == LDAP_VERSION2 ) {
245                         fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
246                                 prog, version );
247                         return EXIT_FAILURE;
248                 }
249                 manageDSAit++;
250                 version = LDAP_VERSION3;
251                 break;
252         case 'n':       /* print deletes, don't actually do them */
253             ++not;
254             break;
255         case 'O':
256 #ifdef HAVE_CYRUS_SASL
257                 if( sasl_secprops != NULL ) {
258                         fprintf( stderr, "%s: -O previously specified\n", prog );
259                         return EXIT_FAILURE;
260                 }
261                 if( version == LDAP_VERSION2 ) {
262                         fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
263                                 prog, version );
264                         return EXIT_FAILURE;
265                 }
266                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
267                         fprintf( stderr, "%s: incompatible previous "
268                                 "authentication choice\n", prog );
269                         return EXIT_FAILURE;
270                 }
271                 authmethod = LDAP_AUTH_SASL;
272                 version = LDAP_VERSION3;
273                 sasl_secprops = strdup( optarg );
274 #else
275                 fprintf( stderr, "%s: not compiled with SASL support\n",
276                         prog );
277                 return( EXIT_FAILURE );
278 #endif
279                 break;
280         case 'p':
281                 if( ldapport ) {
282                         fprintf( stderr, "%s: -p previously specified\n", prog );
283                         return EXIT_FAILURE;
284                 }
285             ldapport = atoi( optarg );
286             break;
287         case 'P':
288                 switch( atoi(optarg) ) {
289                 case 2:
290                         if( version == LDAP_VERSION3 ) {
291                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
292                                         prog, version );
293                                 return EXIT_FAILURE;
294                         }
295                         version = LDAP_VERSION2;
296                         break;
297                 case 3:
298                         if( version == LDAP_VERSION2 ) {
299                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
300                                         prog, version );
301                                 return EXIT_FAILURE;
302                         }
303                         version = LDAP_VERSION3;
304                         break;
305                 default:
306                         fprintf( stderr, "%s: protocol version should be 2 or 3\n",
307                                 prog );
308                         usage( prog );
309                         return( EXIT_FAILURE );
310                 } break;
311         case 'Q':
312 #ifdef HAVE_CYRUS_SASL
313                 if( version == LDAP_VERSION2 ) {
314                         fprintf( stderr, "%s: -Q incompatible with version %d\n",
315                                 prog, version );
316                         return EXIT_FAILURE;
317                 }
318                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
319                         fprintf( stderr, "%s: incompatible previous "
320                                 "authentication choice\n",
321                                 prog );
322                         return EXIT_FAILURE;
323                 }
324                 authmethod = LDAP_AUTH_SASL;
325                 version = LDAP_VERSION3;
326                 sasl_flags = LDAP_SASL_QUIET;
327                 break;
328 #else
329                 fprintf( stderr, "%s: not compiled with SASL support\n",
330                         prog );
331                 return( EXIT_FAILURE );
332 #endif
333         case 'R':
334 #ifdef HAVE_CYRUS_SASL
335                 if( sasl_realm != NULL ) {
336                         fprintf( stderr, "%s: -R previously specified\n", prog );
337                         return EXIT_FAILURE;
338                 }
339                 if( version == LDAP_VERSION2 ) {
340                         fprintf( stderr, "%s: -R incompatible with version %d\n",
341                                 prog, version );
342                         return EXIT_FAILURE;
343                 }
344                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
345                         fprintf( stderr, "%s: incompatible previous "
346                                 "authentication choice\n",
347                                 prog );
348                         return EXIT_FAILURE;
349                 }
350                 authmethod = LDAP_AUTH_SASL;
351                 version = LDAP_VERSION3;
352                 sasl_realm = strdup( optarg );
353 #else
354                 fprintf( stderr, "%s: not compiled with SASL support\n",
355                         prog );
356                 return( EXIT_FAILURE );
357 #endif
358                 break;
359         case 'U':
360 #ifdef HAVE_CYRUS_SASL
361                 if( sasl_authc_id != NULL ) {
362                         fprintf( stderr, "%s: -U previously specified\n", prog );
363                         return EXIT_FAILURE;
364                 }
365                 if( version == LDAP_VERSION2 ) {
366                         fprintf( stderr, "%s: -U incompatible with version %d\n",
367                                 prog, version );
368                         return EXIT_FAILURE;
369                 }
370                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
371                         fprintf( stderr, "%s: incompatible previous "
372                                 "authentication choice\n",
373                                 prog );
374                         return EXIT_FAILURE;
375                 }
376                 authmethod = LDAP_AUTH_SASL;
377                 version = LDAP_VERSION3;
378                 sasl_authc_id = strdup( optarg );
379 #else
380                 fprintf( stderr, "%s: not compiled with SASL support\n",
381                         prog );
382                 return( EXIT_FAILURE );
383 #endif
384                 break;
385         case 'v':       /* verbose mode */
386             verbose++;
387             break;
388         case 'w':       /* password */
389             passwd.bv_val = strdup( optarg );
390                 {
391                         char* p;
392
393                         for( p = optarg; *p != '\0'; p++ ) {
394                                 *p = '\0';
395                         }
396                 }
397                 passwd.bv_len = strlen( passwd.bv_val );
398             break;
399         case 'W':
400                 want_bindpw++;
401                 break;
402         case 'Y':
403 #ifdef HAVE_CYRUS_SASL
404                 if( sasl_mech != NULL ) {
405                         fprintf( stderr, "%s: -Y previously specified\n", prog );
406                         return EXIT_FAILURE;
407                 }
408                 if( version == LDAP_VERSION2 ) {
409                         fprintf( stderr, "%s: -Y incompatible with version %d\n",
410                                 prog, version );
411                         return EXIT_FAILURE;
412                 }
413                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
414                         fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
415                         return EXIT_FAILURE;
416                 }
417                 authmethod = LDAP_AUTH_SASL;
418                 version = LDAP_VERSION3;
419                 sasl_mech = strdup( optarg );
420 #else
421                 fprintf( stderr, "%s: not compiled with SASL support\n",
422                         prog );
423                 return( EXIT_FAILURE );
424 #endif
425                 break;
426         case 'x':
427                 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
428                         fprintf( stderr, "%s: incompatible with previous "
429                                 "authentication choice\n", prog );
430                         return EXIT_FAILURE;
431                 }
432                 authmethod = LDAP_AUTH_SIMPLE;
433                 break;
434         case 'X':
435 #ifdef HAVE_CYRUS_SASL
436                 if( sasl_authz_id != NULL ) {
437                         fprintf( stderr, "%s: -X previously specified\n", prog );
438                         return EXIT_FAILURE;
439                 }
440                 if( version == LDAP_VERSION2 ) {
441                         fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
442                                 prog, version );
443                         return EXIT_FAILURE;
444                 }
445                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
446                         fprintf( stderr, "%s: -X incompatible with "
447                                 "authentication choice\n", prog );
448                         return EXIT_FAILURE;
449                 }
450                 authmethod = LDAP_AUTH_SASL;
451                 version = LDAP_VERSION3;
452                 sasl_authz_id = strdup( optarg );
453 #else
454                 fprintf( stderr, "%s: not compiled with SASL support\n",
455                         prog );
456                 return( EXIT_FAILURE );
457 #endif
458                 break;
459         case 'Z':
460 #ifdef HAVE_TLS
461                 if( version == LDAP_VERSION2 ) {
462                         fprintf( stderr, "%s: -Z incompatible with version %d\n",
463                                 prog, version );
464                         return EXIT_FAILURE;
465                 }
466                 version = LDAP_VERSION3;
467                 use_tls++;
468 #else
469                 fprintf( stderr, "%s: not compiled with TLS support\n",
470                         prog );
471                 return( EXIT_FAILURE );
472 #endif
473                 break;
474
475
476                 default:
477                         fprintf( stderr, "%s: unrecognized option -%c\n",
478                                 prog, optopt );
479                         usage (prog);
480                 }
481         }
482
483         if (authmethod == -1) {
484 #ifdef HAVE_CYRUS_SASL
485                 authmethod = LDAP_AUTH_SASL;
486 #else
487                 authmethod = LDAP_AUTH_SIMPLE;
488 #endif
489         }
490
491         if( argc - optind > 1 ) {
492                 usage( prog );
493         } else if ( argc - optind == 1 ) {
494                 user = strdup( argv[optind] );
495         } else {
496                 user = NULL;
497         }
498
499         if( want_oldpw && oldpw == NULL ) {
500                 /* prompt for old password */
501                 char *ckoldpw;
502                 oldpw = strdup(getpassphrase("Old password: "));
503                 ckoldpw = getpassphrase("Re-enter old password: ");
504
505                 if( oldpw== NULL || ckoldpw == NULL ||
506                         strcmp( oldpw, ckoldpw ))
507                 {
508                         fprintf( stderr, "passwords do not match\n" );
509                         return EXIT_FAILURE;
510                 }
511         }
512
513         if( want_newpw && newpw == NULL ) {
514                 /* prompt for new password */
515                 char *cknewpw;
516                 newpw = strdup(getpassphrase("New password: "));
517                 cknewpw = getpassphrase("Re-enter new password: ");
518
519                 if( newpw== NULL || cknewpw == NULL ||
520                         strcmp( newpw, cknewpw ))
521                 {
522                         fprintf( stderr, "passwords do not match\n" );
523                         return EXIT_FAILURE;
524                 }
525         }
526
527         if (want_bindpw && passwd.bv_val == NULL ) {
528                 /* handle bind password */
529                 passwd.bv_val = strdup( getpassphrase("Enter bind password: "));
530                 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
531         }
532
533         if ( debug ) {
534                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
535                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
536                 }
537                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
538                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
539                 }
540         }
541
542 #ifdef SIGPIPE
543         (void) SIGNAL( SIGPIPE, SIG_IGN );
544 #endif
545
546         /* connect to server */
547         if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
548                 if ( verbose ) {
549                         fprintf( stderr, "ldap_init( %s, %d )\n",
550                                 ldaphost != NULL ? ldaphost : "<DEFAULT>",
551                                 ldapport );
552                 }
553
554                 ld = ldap_init( ldaphost, ldapport );
555                 if( ld == NULL ) {
556                         perror("ldapwhoami: ldap_init");
557                         return EXIT_FAILURE;
558                 }
559
560         } else {
561                 if ( verbose ) {
562                         fprintf( stderr, "ldap_initialize( %s )\n",
563                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
564                 }
565
566                 rc = ldap_initialize( &ld, ldapuri );
567                 if( rc != LDAP_SUCCESS ) {
568                         fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
569                                 rc, ldap_err2string(rc) );
570                         return EXIT_FAILURE;
571                 }
572         }
573
574         /* referrals */
575         if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
576                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
577         {
578                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
579                         referrals ? "on" : "off" );
580                 return EXIT_FAILURE;
581         }
582
583         /* LDAPv3 only */
584         version = LDAP_VERSION3;
585         rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
586
587         if(rc != LDAP_OPT_SUCCESS ) {
588                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
589                 return EXIT_FAILURE;
590         }
591
592         if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
593                 ldap_perror( ld, "ldap_start_tls" );
594                 if ( use_tls > 1 ) {
595                         return( EXIT_FAILURE );
596                 }
597         }
598
599         if ( authmethod == LDAP_AUTH_SASL ) {
600 #ifdef HAVE_CYRUS_SASL
601                 void *defaults;
602
603                 if( sasl_secprops != NULL ) {
604                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
605                                 (void *) sasl_secprops );
606                         
607                         if( rc != LDAP_OPT_SUCCESS ) {
608                                 fprintf( stderr,
609                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
610                                         sasl_secprops );
611                                 return( EXIT_FAILURE );
612                         }
613                 }
614                 
615                 defaults = lutil_sasl_defaults( ld,
616                         sasl_mech,
617                         sasl_realm,
618                         sasl_authc_id,
619                         passwd.bv_val,
620                         sasl_authz_id );
621
622                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
623                         sasl_mech, NULL, NULL,
624                         sasl_flags, lutil_sasl_interact, defaults );
625
626                 if( rc != LDAP_SUCCESS ) {
627                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
628                         return( EXIT_FAILURE );
629                 }
630 #else
631                 fprintf( stderr, "%s: not compiled with SASL support\n",
632                         prog );
633                 return( EXIT_FAILURE );
634 #endif
635         }
636         else {
637                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
638                                 != LDAP_SUCCESS ) {
639                         ldap_perror( ld, "ldap_bind" );
640                         return( EXIT_FAILURE );
641                 }
642         }
643
644         if ( not ) {
645                 rc = LDAP_SUCCESS;
646                 goto skip;
647         }
648
649         rc = ldap_extended_operation( ld,
650                 LDAP_EXOP_X_WHO_AM_I, NULL, 
651                 NULL, NULL, &id );
652
653         if( rc != LDAP_SUCCESS ) {
654                 ldap_perror( ld, "ldap_extended_operation" );
655                 ldap_unbind( ld );
656                 return EXIT_FAILURE;
657         }
658
659         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
660         if ( rc < 0 ) {
661                 ldap_perror( ld, "ldappasswd: ldap_result" );
662                 return rc;
663         }
664
665         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 0 );
666
667         if( rc != LDAP_SUCCESS ) {
668                 ldap_perror( ld, "ldap_parse_result" );
669                 return rc;
670         }
671
672         rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
673
674         if( rc != LDAP_SUCCESS ) {
675                 ldap_perror( ld, "ldap_parse_result" );
676                 return rc;
677         }
678
679         if( retdata != NULL ) {
680                 if( retdata->bv_len == 0 ) {
681                         printf("anonymous\n" );
682                 } else {
683                         printf("%s\n", retdata->bv_val );
684                 }
685         }
686
687         if( verbose || ( code != LDAP_SUCCESS ) || matcheddn || text || refs ) {
688                 printf( "Result: %s (%d)\n", ldap_err2string( code ), code );
689
690                 if( text && *text ) {
691                         printf( "Additional info: %s\n", text );
692                 }
693
694                 if( matcheddn && *matcheddn ) {
695                         printf( "Matched DN: %s\n", matcheddn );
696                 }
697
698                 if( refs ) {
699                         int i;
700                         for( i=0; refs[i]; i++ ) {
701                                 printf("Referral: %s\n", refs[i] );
702                         }
703                 }
704         }
705
706         ber_memfree( text );
707         ber_memfree( matcheddn );
708         ber_memvfree( (void **) refs );
709         ber_memfree( retoid );
710         ber_bvfree( retdata );
711
712 skip:
713         /* disconnect from server */
714         ldap_unbind (ld);
715
716         return code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
717 }