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