3 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/stdlib.h>
14 #include <ac/signal.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
18 #include <ac/unistd.h>
22 #include "lutil_ldap.h"
23 #include "ldap_defaults.h"
25 static int verbose = 0;
31 "Change password of an LDAP user\n\n"
32 "usage: %s [options] [user]\n"
33 " user: the autentication identity, commonly a DN\n"
34 "Password change options:\n"
35 " -a secret old password\n"
36 " -A prompt for old password\n"
37 " -s secret new password\n"
38 " -S prompt for new password\n"
41 " -d level set LDAP debugging level to `level'\n"
42 " -D binddn bind DN\n"
43 " -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
44 " [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
45 " [!]manageDSAit (alternate form, see -M)\n"
47 " -f file read operations from `file'\n"
48 " -h host LDAP server(s)\n"
49 " -H URI LDAP Uniform Resource Indentifier(s)\n"
50 " -I use SASL Interactive mode\n"
51 " -n show what would be done but don't actually update\n"
52 " -O props SASL security properties\n"
53 " -p port port on LDAP server\n"
54 " -Q use SASL Quiet mode\n"
55 " -R realm SASL realm\n"
56 " -U authcid SASL authentication identity\n"
57 " -v run in verbose mode (diagnostics to standard output)\n"
58 " -w passwd bind passwd (for simple authentication)\n"
59 " -W prompt for bind passwd\n"
60 " -x Simple authentication\n"
61 " -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
62 " -Y mech SASL mechanism\n"
63 " -Z Start TLS request (-ZZ to require successful response)\n"
70 main( int argc, char *argv[] )
74 char *ldaphost = NULL;
80 struct berval passwd = { 0, NULL };
97 char *control, *cvalue;
100 #ifdef HAVE_CYRUS_SASL
101 unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
102 char *sasl_realm = NULL;
103 char *sasl_authc_id = NULL;
104 char *sasl_authz_id = NULL;
105 char *sasl_mech = NULL;
106 char *sasl_secprops = NULL;
112 struct berval *bv = NULL;
114 int id, code = LDAP_OTHER;
116 char *matcheddn = NULL, *text = NULL, **refs = NULL;
118 struct berval *retdata = NULL;
120 prog = lutil_progname( "ldappasswd", argc, argv );
122 while( (i = getopt( argc, argv, "Aa:Ss:"
123 "Cd:D:e:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF )
126 /* Password Options */
127 case 'A': /* prompt for old password */
131 case 'a': /* old password (secret) */
132 oldpw = strdup (optarg);
137 for( p = optarg; *p != '\0'; p++ ) {
143 case 'E': /* passwd controls */
144 if( version == LDAP_VERSION2 ) {
145 fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
150 /* should be extended to support comma separated list of
151 * [!]key[=value] parameters, e.g. -E !foo,bar=567
156 if( optarg[0] == '!' ) {
161 control = strdup( optarg );
162 if ( (cvalue = strchr( control, '=' )) != NULL ) {
165 fprintf( stderr, "Invalid passwd control name: %s\n", control );
168 case 'S': /* prompt for user password */
172 case 's': /* new password (secret) */
173 newpw = strdup (optarg);
177 for( p = optarg; *p != '\0'; p++ ) {
183 /* Common Options (including options we don't use) */
188 debug |= atoi( optarg );
190 case 'D': /* bind DN */
191 if( binddn != NULL ) {
192 fprintf( stderr, "%s: -D previously specified\n", prog );
195 binddn = strdup( optarg );
197 case 'e': /* general controls */
198 if( version == LDAP_VERSION2 ) {
199 fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
204 /* should be extended to support comma separated list of
205 * [!]key[=value] parameters, e.g. -e !foo,bar=567
210 if( optarg[0] == '!' ) {
215 control = strdup( optarg );
216 if ( (cvalue = strchr( control, '=' )) != NULL ) {
220 if ( strcasecmp( control, "authzid" ) == 0 ) {
221 if( authzid != NULL ) {
222 fprintf( stderr, "authzid control previously specified\n");
225 if( cvalue == NULL ) {
226 fprintf( stderr, "authzid: control value expected\n" );
231 fprintf( stderr, "authzid: must be marked critical\n" );
236 assert( authzid == NULL );
239 } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
241 fprintf( stderr, "manageDSAit control previously specified\n");
244 if( cvalue != NULL ) {
245 fprintf( stderr, "manageDSAit: no control value expected\n" );
250 manageDSAit = 1 + crit;
252 } else if ( strcasecmp( control, "noop" ) == 0 ) {
253 if( cvalue != NULL ) {
254 fprintf( stderr, "noop: no control value expected\n" );
262 fprintf( stderr, "Invalid general control name: %s\n", control );
267 case 'h': /* ldap host */
268 if( ldapuri != NULL ) {
269 fprintf( stderr, "%s: -h incompatible with -H\n", prog );
272 if( ldaphost != NULL ) {
273 fprintf( stderr, "%s: -h previously specified\n", prog );
276 ldaphost = strdup( optarg );
278 case 'H': /* ldap URI */
279 if( ldaphost != NULL ) {
280 fprintf( stderr, "%s: -H incompatible with -h\n", prog );
284 fprintf( stderr, "%s: -H incompatible with -p\n", prog );
287 if( ldapuri != NULL ) {
288 fprintf( stderr, "%s: -H previously specified\n", prog );
291 ldapuri = strdup( optarg );
294 #ifdef HAVE_CYRUS_SASL
295 if( version == LDAP_VERSION2 ) {
296 fprintf( stderr, "%s: -I incompatible with version %d\n",
300 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
301 fprintf( stderr, "%s: incompatible previous "
302 "authentication choice\n",
306 authmethod = LDAP_AUTH_SASL;
307 version = LDAP_VERSION3;
308 sasl_flags = LDAP_SASL_INTERACTIVE;
311 fprintf( stderr, "%s: was not compiled with SASL support\n",
313 return( EXIT_FAILURE );
315 case 'k': /* kerberos bind */
316 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
317 if( version > LDAP_VERSION2 ) {
318 fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
323 if( authmethod != -1 ) {
324 fprintf( stderr, "%s: -k incompatible with previous "
325 "authentication choice\n", prog );
329 authmethod = LDAP_AUTH_KRBV4;
331 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
335 case 'K': /* kerberos bind, part one only */
336 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
337 if( version > LDAP_VERSION2 ) {
338 fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
342 if( authmethod != -1 ) {
343 fprintf( stderr, "%s: incompatible with previous "
344 "authentication choice\n", prog );
348 authmethod = LDAP_AUTH_KRBV41;
350 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
351 return( EXIT_FAILURE );
355 /* enable Manage DSA IT */
356 if( version == LDAP_VERSION2 ) {
357 fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
362 version = LDAP_VERSION3;
364 case 'n': /* print deletes, don't actually do them */
368 #ifdef HAVE_CYRUS_SASL
369 if( sasl_secprops != NULL ) {
370 fprintf( stderr, "%s: -O previously specified\n", prog );
373 if( version == LDAP_VERSION2 ) {
374 fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
378 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
379 fprintf( stderr, "%s: incompatible previous "
380 "authentication choice\n", prog );
383 authmethod = LDAP_AUTH_SASL;
384 version = LDAP_VERSION3;
385 sasl_secprops = strdup( optarg );
387 fprintf( stderr, "%s: not compiled with SASL support\n",
389 return( EXIT_FAILURE );
394 fprintf( stderr, "%s: -p previously specified\n", prog );
397 ldapport = atoi( optarg );
400 switch( atoi(optarg) ) {
402 if( version == LDAP_VERSION3 ) {
403 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
407 version = LDAP_VERSION2;
410 if( version == LDAP_VERSION2 ) {
411 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
415 version = LDAP_VERSION3;
418 fprintf( stderr, "%s: protocol version should be 2 or 3\n",
421 return( EXIT_FAILURE );
425 #ifdef HAVE_CYRUS_SASL
426 if( version == LDAP_VERSION2 ) {
427 fprintf( stderr, "%s: -Q incompatible with version %d\n",
431 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
432 fprintf( stderr, "%s: incompatible previous "
433 "authentication choice\n",
437 authmethod = LDAP_AUTH_SASL;
438 version = LDAP_VERSION3;
439 sasl_flags = LDAP_SASL_QUIET;
442 fprintf( stderr, "%s: not compiled with SASL support\n",
444 return( EXIT_FAILURE );
447 #ifdef HAVE_CYRUS_SASL
448 if( sasl_realm != NULL ) {
449 fprintf( stderr, "%s: -R previously specified\n", prog );
452 if( version == LDAP_VERSION2 ) {
453 fprintf( stderr, "%s: -R incompatible with version %d\n",
457 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
458 fprintf( stderr, "%s: incompatible previous "
459 "authentication choice\n",
463 authmethod = LDAP_AUTH_SASL;
464 version = LDAP_VERSION3;
465 sasl_realm = strdup( optarg );
467 fprintf( stderr, "%s: not compiled with SASL support\n",
469 return( EXIT_FAILURE );
473 #ifdef HAVE_CYRUS_SASL
474 if( sasl_authc_id != NULL ) {
475 fprintf( stderr, "%s: -U previously specified\n", prog );
478 if( version == LDAP_VERSION2 ) {
479 fprintf( stderr, "%s: -U incompatible with version %d\n",
483 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
484 fprintf( stderr, "%s: incompatible previous "
485 "authentication choice\n",
489 authmethod = LDAP_AUTH_SASL;
490 version = LDAP_VERSION3;
491 sasl_authc_id = strdup( optarg );
493 fprintf( stderr, "%s: not compiled with SASL support\n",
495 return( EXIT_FAILURE );
498 case 'v': /* verbose mode */
501 case 'w': /* password */
502 passwd.bv_val = strdup( optarg );
506 for( p = optarg; *p != '\0'; p++ ) {
510 passwd.bv_len = strlen( passwd.bv_val );
516 #ifdef HAVE_CYRUS_SASL
517 if( sasl_mech != NULL ) {
518 fprintf( stderr, "%s: -Y previously specified\n", prog );
521 if( version == LDAP_VERSION2 ) {
522 fprintf( stderr, "%s: -Y incompatible with version %d\n",
526 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
527 fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
530 authmethod = LDAP_AUTH_SASL;
531 version = LDAP_VERSION3;
532 sasl_mech = strdup( optarg );
534 fprintf( stderr, "%s: not compiled with SASL support\n",
536 return( EXIT_FAILURE );
540 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
541 fprintf( stderr, "%s: incompatible with previous "
542 "authentication choice\n", prog );
545 authmethod = LDAP_AUTH_SIMPLE;
548 #ifdef HAVE_CYRUS_SASL
549 if( sasl_authz_id != NULL ) {
550 fprintf( stderr, "%s: -X previously specified\n", prog );
553 if( version == LDAP_VERSION2 ) {
554 fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
558 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
559 fprintf( stderr, "%s: -X incompatible with "
560 "authentication choice\n", prog );
563 authmethod = LDAP_AUTH_SASL;
564 version = LDAP_VERSION3;
565 sasl_authz_id = strdup( optarg );
567 fprintf( stderr, "%s: not compiled with SASL support\n",
569 return( EXIT_FAILURE );
574 if( version == LDAP_VERSION2 ) {
575 fprintf( stderr, "%s: -Z incompatible with version %d\n",
579 version = LDAP_VERSION3;
582 fprintf( stderr, "%s: not compiled with TLS support\n",
584 return( EXIT_FAILURE );
590 fprintf( stderr, "%s: unrecognized option -%c\n",
596 if (authmethod == -1) {
597 #ifdef HAVE_CYRUS_SASL
598 authmethod = LDAP_AUTH_SASL;
600 authmethod = LDAP_AUTH_SIMPLE;
604 if( argc - optind > 1 ) {
606 } else if ( argc - optind == 1 ) {
607 user = strdup( argv[optind] );
612 if( want_oldpw && oldpw == NULL ) {
613 /* prompt for old password */
615 oldpw = strdup(getpassphrase("Old password: "));
616 ckoldpw = getpassphrase("Re-enter old password: ");
618 if( oldpw== NULL || ckoldpw == NULL ||
619 strcmp( oldpw, ckoldpw ))
621 fprintf( stderr, "passwords do not match\n" );
626 if( want_newpw && newpw == NULL ) {
627 /* prompt for new password */
629 newpw = strdup(getpassphrase("New password: "));
630 cknewpw = getpassphrase("Re-enter new password: ");
632 if( newpw== NULL || cknewpw == NULL ||
633 strcmp( newpw, cknewpw ))
635 fprintf( stderr, "passwords do not match\n" );
640 if (want_bindpw && passwd.bv_val == NULL ) {
641 /* handle bind password */
642 passwd.bv_val = strdup( getpassphrase("Enter bind password: "));
643 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
647 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
648 fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
650 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
651 fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
656 (void) SIGNAL( SIGPIPE, SIG_IGN );
659 /* connect to server */
660 if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
662 fprintf( stderr, "ldap_init( %s, %d )\n",
663 ldaphost != NULL ? ldaphost : "<DEFAULT>",
667 ld = ldap_init( ldaphost, ldapport );
669 perror("ldapsearch: ldap_init");
675 fprintf( stderr, "ldap_initialize( %s )\n",
676 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
679 rc = ldap_initialize( &ld, ldapuri );
680 if( rc != LDAP_SUCCESS ) {
681 fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
682 rc, ldap_err2string(rc) );
688 if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
689 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
691 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
692 referrals ? "on" : "off" );
697 version = LDAP_VERSION3;
698 rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
700 if(rc != LDAP_OPT_SUCCESS ) {
701 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
705 if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
706 ldap_perror( ld, "ldap_start_tls" );
708 return( EXIT_FAILURE );
712 if ( authmethod == LDAP_AUTH_SASL ) {
713 #ifdef HAVE_CYRUS_SASL
716 if( sasl_secprops != NULL ) {
717 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
718 (void *) sasl_secprops );
720 if( rc != LDAP_OPT_SUCCESS ) {
722 "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
724 return( EXIT_FAILURE );
728 defaults = lutil_sasl_defaults( ld,
735 rc = ldap_sasl_interactive_bind_s( ld, binddn,
736 sasl_mech, NULL, NULL,
737 sasl_flags, lutil_sasl_interact, defaults );
739 if( rc != LDAP_SUCCESS ) {
740 ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
741 return( EXIT_FAILURE );
744 fprintf( stderr, "%s: not compiled with SASL support\n",
746 return( EXIT_FAILURE );
750 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
752 ldap_perror( ld, "ldap_bind" );
753 return( EXIT_FAILURE );
757 if ( authzid || manageDSAit || noop ) {
758 int err, crit=0, i=0;
760 LDAPControl *ctrls[4];
763 c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
764 c[i].ldctl_value.bv_val = authzid;
765 c[i].ldctl_value.bv_len = strlen( authzid );
766 c[i].ldctl_iscritical = 1;
768 if( c[i].ldctl_iscritical ) crit++;
774 c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
775 c[i].ldctl_value.bv_val = NULL;
776 c[i].ldctl_value.bv_len = 0;
777 c[i].ldctl_iscritical = manageDSAit > 1;
779 if( c[i].ldctl_iscritical ) crit++;
785 c[i].ldctl_oid = LDAP_CONTROL_NOOP;
786 c[i].ldctl_value.bv_val = NULL;
787 c[i].ldctl_value.bv_len = 0;
788 c[i].ldctl_iscritical = noop > 1;
790 if( c[i].ldctl_iscritical ) crit++;
795 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
797 if( err != LDAP_OPT_SUCCESS ) {
798 fprintf( stderr, "Could not set %scontrols\n",
799 crit ? "critical " : "" );
806 if( user != NULL || oldpw != NULL || newpw != NULL ) {
807 /* build change password control */
808 BerElement *ber = ber_alloc_t( LBER_USE_DER );
811 perror( "ber_alloc_t" );
816 ber_printf( ber, "{" /*}*/ );
819 ber_printf( ber, "ts",
820 LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user );
824 if( oldpw != NULL ) {
825 ber_printf( ber, "ts",
826 LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, oldpw );
830 if( newpw != NULL ) {
831 ber_printf( ber, "ts",
832 LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, newpw );
836 ber_printf( ber, /*{*/ "N}" );
838 rc = ber_flatten( ber, &bv );
841 perror( "ber_flatten" );
854 rc = ldap_extended_operation( ld,
855 LDAP_EXOP_MODIFY_PASSWD, bv,
860 if( rc != LDAP_SUCCESS ) {
861 ldap_perror( ld, "ldap_extended_operation" );
866 rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
868 ldap_perror( ld, "ldappasswd: ldap_result" );
872 rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 0 );
874 if( rc != LDAP_SUCCESS ) {
875 ldap_perror( ld, "ldap_parse_result" );
879 rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
881 if( rc != LDAP_SUCCESS ) {
882 ldap_perror( ld, "ldap_parse_result" );
886 if( retdata != NULL ) {
889 BerElement *ber = ber_init( retdata );
892 perror( "ber_init" );
897 /* we should check the tag */
898 tag = ber_scanf( ber, "{a}", &s);
900 if( tag == LBER_ERROR ) {
901 perror( "ber_scanf" );
903 printf("New password: %s\n", s);
910 if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
911 printf( "Result: %s (%d)\n", ldap_err2string( code ), code );
913 if( text && *text ) {
914 printf( "Additional info: %s\n", text );
917 if( matcheddn && *matcheddn ) {
918 printf( "Matched DN: %s\n", matcheddn );
923 for( i=0; refs[i]; i++ ) {
924 printf("Referral: %s\n", refs[i] );
930 ber_memfree( matcheddn );
931 ber_memvfree( (void **) refs );
932 ber_memfree( retoid );
933 ber_bvfree( retdata );
936 /* disconnect from server */
939 return code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;