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