Back to index

openldap  2.4.31
ldappasswd.c
Go to the documentation of this file.
00001 /* ldappasswd -- a tool for change LDAP passwords */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
00007  * Portions Copyright 1998-2001 Net Boolean Incorporated.
00008  * Portions Copyright 2001-2003 IBM Corporation.
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted only as authorized by the OpenLDAP
00013  * Public License.
00014  *
00015  * A copy of this license is available in the file LICENSE in the
00016  * top-level directory of the distribution or, alternatively, at
00017  * <http://www.OpenLDAP.org/license.html>.
00018  */
00019 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
00020  * All rights reserved.
00021  *
00022  * Redistribution and use in source and binary forms are permitted
00023  * provided that this notice is preserved and that due credit is given
00024  * to the University of Michigan at Ann Arbor.  The name of the
00025  * University may not be used to endorse or promote products derived
00026  * from this software without specific prior written permission.  This
00027  * software is provided ``as is'' without express or implied warranty.
00028  */
00029 /* ACKNOWLEDGEMENTS:
00030  * The original ldappasswd(1) tool was developed by Dave Storey (F5
00031  * Network), based on other OpenLDAP client tools (which are, of
00032  * course, based on U-MICH LDAP).  This version was rewritten
00033  * by Kurt D. Zeilenga (based on other OpenLDAP client tools).
00034  */
00035 
00036 #include "portable.h"
00037 
00038 #include <stdio.h>
00039 
00040 #include <ac/stdlib.h>
00041 
00042 #include <ac/ctype.h>
00043 #include <ac/socket.h>
00044 #include <ac/string.h>
00045 #include <ac/time.h>
00046 #include <ac/unistd.h>
00047 
00048 #include <ldap.h>
00049 #include "lutil.h"
00050 #include "lutil_ldap.h"
00051 #include "ldap_defaults.h"
00052 
00053 #include "common.h"
00054 
00055 
00056 static struct berval newpw = { 0, NULL };
00057 static struct berval oldpw = { 0, NULL };
00058 
00059 static int   want_newpw = 0;
00060 static int   want_oldpw = 0;
00061 
00062 static char *oldpwfile = NULL;
00063 static char *newpwfile = NULL;
00064 
00065 void
00066 usage( void )
00067 {
00068        fprintf( stderr, _("Change password of an LDAP user\n\n"));
00069        fprintf( stderr,_("usage: %s [options] [user]\n"), prog);
00070        fprintf( stderr, _("  user: the authentication identity, commonly a DN\n"));
00071        fprintf( stderr, _("Password change options:\n"));
00072        fprintf( stderr, _("  -a secret  old password\n"));
00073        fprintf( stderr, _("  -A         prompt for old password\n"));
00074        fprintf( stderr, _("  -t file    read file for old password\n"));
00075        fprintf( stderr, _("  -s secret  new password\n"));
00076        fprintf( stderr, _("  -S         prompt for new password\n"));
00077        fprintf( stderr, _("  -T file    read file for new password\n"));
00078        tool_common_usage();
00079        exit( EXIT_FAILURE );
00080 }
00081 
00082 
00083 const char options[] = "a:As:St:T:"
00084        "d:D:e:h:H:InNO:o:p:QR:U:vVw:WxX:y:Y:Z";
00085 
00086 int
00087 handle_private_option( int i )
00088 {
00089        switch ( i ) {
00090 #if 0
00091        case 'E': /* passwd extensions */ {
00092               int           crit;
00093               char   *control, *cvalue;
00094               if( protocol == LDAP_VERSION2 ) {
00095                      fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
00096                               prog, protocol );
00097                      exit( EXIT_FAILURE );
00098               }
00099 
00100               /* should be extended to support comma separated list of
00101                *     [!]key[=value] parameters, e.g.  -E !foo,bar=567
00102                */
00103 
00104               crit = 0;
00105               cvalue = NULL;
00106               if( optarg[0] == '!' ) {
00107                      crit = 1;
00108                      optarg++;
00109               }
00110 
00111               control = strdup( optarg );
00112               if ( (cvalue = strchr( control, '=' )) != NULL ) {
00113                      *cvalue++ = '\0';
00114               }
00115               fprintf( stderr, _("Invalid passwd extension name: %s\n"), control );
00116               usage();
00117               }
00118 #endif
00119 
00120        case 'a':     /* old password (secret) */
00121               oldpw.bv_val = strdup( optarg );
00122               {
00123                      char* p;
00124                      for( p = optarg; *p != '\0'; p++ ) {
00125                             *p = '\0';
00126                      }
00127               }
00128               oldpw.bv_len = strlen( oldpw.bv_val );
00129               break;
00130 
00131        case 'A':     /* prompt for old password */
00132               want_oldpw++;
00133               break;
00134 
00135        case 's':     /* new password (secret) */
00136               newpw.bv_val = strdup (optarg);
00137               {
00138                      char* p;
00139                      for( p = optarg; *p != '\0'; p++ ) {
00140                             *p = '\0';
00141                      }
00142               }
00143               newpw.bv_len = strlen( newpw.bv_val );
00144               break;
00145 
00146        case 'S':     /* prompt for user password */
00147               want_newpw++;
00148               break;
00149 
00150        case 't':
00151               oldpwfile = optarg;
00152               break;
00153 
00154        case 'T':
00155               newpwfile = optarg;
00156               break;
00157 
00158        default:
00159               return 0;
00160        }
00161        return 1;
00162 }
00163 
00164 
00165 int
00166 main( int argc, char *argv[] )
00167 {
00168        int rc;
00169        char   *user = NULL;
00170 
00171        LDAP          *ld = NULL;
00172        struct berval bv = {0, NULL};
00173        BerElement  *ber = NULL;
00174 
00175        int id, code = LDAP_OTHER;
00176        LDAPMessage *res;
00177        char *matcheddn = NULL, *text = NULL, **refs = NULL;
00178        char   *retoid = NULL;
00179        struct berval *retdata = NULL;
00180        LDAPControl **ctrls = NULL;
00181 
00182     tool_init( TOOL_PASSWD );
00183        prog = lutil_progname( "ldappasswd", argc, argv );
00184 
00185        /* LDAPv3 only */
00186        protocol = LDAP_VERSION3;
00187 
00188        tool_args( argc, argv );
00189 
00190        if( argc - optind > 1 ) {
00191               usage();
00192        } else if ( argc - optind == 1 ) {
00193               user = strdup( argv[optind] );
00194        } else {
00195               user = NULL;
00196        }
00197 
00198        if( oldpwfile ) {
00199               rc = lutil_get_filed_password( oldpwfile, &oldpw );
00200               if( rc ) {
00201                      rc = EXIT_FAILURE;
00202                      goto done;
00203               }
00204        }
00205 
00206        if( want_oldpw && oldpw.bv_val == NULL ) {
00207               /* prompt for old password */
00208               char *ckoldpw;
00209               oldpw.bv_val = strdup(getpassphrase(_("Old password: ")));
00210               ckoldpw = getpassphrase(_("Re-enter old password: "));
00211 
00212               if( oldpw.bv_val == NULL || ckoldpw == NULL ||
00213                      strcmp( oldpw.bv_val, ckoldpw ))
00214               {
00215                      fprintf( stderr, _("passwords do not match\n") );
00216                      rc = EXIT_FAILURE;
00217                      goto done;
00218               }
00219 
00220               oldpw.bv_len = strlen( oldpw.bv_val );
00221        }
00222 
00223        if( newpwfile ) {
00224               rc = lutil_get_filed_password( newpwfile, &newpw );
00225               if( rc ) {
00226                      rc = EXIT_FAILURE;
00227                      goto done;
00228               }
00229        }
00230 
00231        if( want_newpw && newpw.bv_val == NULL ) {
00232               /* prompt for new password */
00233               char *cknewpw;
00234               newpw.bv_val = strdup(getpassphrase(_("New password: ")));
00235               cknewpw = getpassphrase(_("Re-enter new password: "));
00236 
00237               if( newpw.bv_val == NULL || cknewpw == NULL ||
00238                      strcmp( newpw.bv_val, cknewpw ))
00239               {
00240                      fprintf( stderr, _("passwords do not match\n") );
00241                      rc = EXIT_FAILURE;
00242                      goto done;
00243               }
00244 
00245               newpw.bv_len = strlen( newpw.bv_val );
00246        }
00247 
00248        ld = tool_conn_setup( 0, 0 );
00249 
00250        tool_bind( ld );
00251 
00252        if( user != NULL || oldpw.bv_val != NULL || newpw.bv_val != NULL ) {
00253               /* build the password modify request data */
00254               ber = ber_alloc_t( LBER_USE_DER );
00255 
00256               if( ber == NULL ) {
00257                      perror( "ber_alloc_t" );
00258                      rc = EXIT_FAILURE;
00259                      goto done;
00260               }
00261 
00262               ber_printf( ber, "{" /*}*/ );
00263 
00264               if( user != NULL ) {
00265                      ber_printf( ber, "ts",
00266                             LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user );
00267                      free(user);
00268               }
00269 
00270               if( oldpw.bv_val != NULL ) {
00271                      ber_printf( ber, "tO",
00272                             LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &oldpw );
00273                      free(oldpw.bv_val);
00274               }
00275 
00276               if( newpw.bv_val != NULL ) {
00277                      ber_printf( ber, "tO",
00278                             LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw );
00279                      free(newpw.bv_val);
00280               }
00281 
00282               ber_printf( ber, /*{*/ "N}" );
00283 
00284               rc = ber_flatten2( ber, &bv, 0 );
00285 
00286               if( rc < 0 ) {
00287                      perror( "ber_flatten2" );
00288                      rc = EXIT_FAILURE;
00289                      goto done;
00290               }
00291        }
00292 
00293        if ( dont ) {
00294               rc = LDAP_SUCCESS;
00295               goto done;
00296        }
00297 
00298        tool_server_controls( ld, NULL, 0);
00299 
00300        rc = ldap_extended_operation( ld,
00301               LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL, 
00302               NULL, NULL, &id );
00303 
00304        ber_free( ber, 1 );
00305 
00306        if( rc != LDAP_SUCCESS ) {
00307               tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL );
00308               rc = EXIT_FAILURE;
00309               goto done;
00310        }
00311 
00312        for ( ; ; ) {
00313               struct timeval       tv;
00314 
00315               if ( tool_check_abandon( ld, id ) ) {
00316                      tool_exit( ld, LDAP_CANCELLED );
00317               }
00318 
00319               tv.tv_sec = 0;
00320               tv.tv_usec = 100000;
00321 
00322               rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res );
00323               if ( rc < 0 ) {
00324                      tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
00325                      tool_exit( ld, rc );
00326               }
00327 
00328               if ( rc != 0 ) {
00329                      break;
00330               }
00331        }
00332 
00333        rc = ldap_parse_result( ld, res,
00334               &code, &matcheddn, &text, &refs, &ctrls, 0 );
00335        if( rc != LDAP_SUCCESS ) {
00336               tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
00337               rc = EXIT_FAILURE;
00338               goto done;
00339        }
00340 
00341        rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
00342        if( rc != LDAP_SUCCESS ) {
00343               tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
00344               rc = EXIT_FAILURE;
00345               goto done;
00346        }
00347 
00348        if( retdata != NULL ) {
00349               ber_tag_t tag;
00350               char *s;
00351               ber = ber_init( retdata );
00352 
00353               if( ber == NULL ) {
00354                      perror( "ber_init" );
00355                      rc = EXIT_FAILURE;
00356                      goto done;
00357               }
00358 
00359               /* we should check the tag */
00360               tag = ber_scanf( ber, "{a}", &s);
00361 
00362               if( tag == LBER_ERROR ) {
00363                      perror( "ber_scanf" );
00364               } else {
00365                      printf(_("New password: %s\n"), s);
00366                      ber_memfree( s );
00367               }
00368 
00369               ber_free( ber, 1 );
00370 
00371        } else if ( code == LDAP_SUCCESS && newpw.bv_val == NULL ) {
00372               tool_perror( "ldap_parse_extended_result", LDAP_DECODING_ERROR,
00373                      " new password expected", NULL, NULL, NULL );
00374        }
00375 
00376        if( verbose || code != LDAP_SUCCESS ||
00377               ( matcheddn && *matcheddn ) || ( text && *text ) || refs || ctrls )
00378        {
00379               printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
00380 
00381               if( text && *text ) {
00382                      printf( _("Additional info: %s\n"), text );
00383               }
00384 
00385               if( matcheddn && *matcheddn ) {
00386                      printf( _("Matched DN: %s\n"), matcheddn );
00387               }
00388 
00389               if( refs ) {
00390                      int i;
00391                      for( i=0; refs[i]; i++ ) {
00392                             printf(_("Referral: %s\n"), refs[i] );
00393                      }
00394               }
00395 
00396               if( ctrls ) {
00397                      tool_print_ctrls( ld, ctrls );
00398                      ldap_controls_free( ctrls );
00399               }
00400        }
00401 
00402        ber_memfree( text );
00403        ber_memfree( matcheddn );
00404        ber_memvfree( (void **) refs );
00405        ber_memfree( retoid );
00406        ber_bvfree( retdata );
00407 
00408        rc = ( code == LDAP_SUCCESS ) ? EXIT_SUCCESS : EXIT_FAILURE;
00409 
00410 done:
00411        /* disconnect from server */
00412        tool_exit( ld, rc ); 
00413 }