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