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