1 /* ldappasswd -- a tool for change LDAP passwords */ 2 /* $OpenLDAP: pkg/ldap/clients/tools/ldappasswd.c,v 1.136.2.4 2008/02/11 23:26:38 kurt Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * Portions Copyright 1998-2003 Kurt D. Zeilenga. 7 * Portions Copyright 1998-2001 Net Boolean Incorporated. 8 * Portions Copyright 2001-2003 IBM Corporation. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms are permitted 23 * provided that this notice is preserved and that due credit is given 24 * to the University of Michigan at Ann Arbor. The name of the 25 * University may not be used to endorse or promote products derived 26 * from this software without specific prior written permission. This 27 * software is provided ``as is'' without express or implied warranty. 28 */ 29 /* ACKNOWLEDGEMENTS: 30 * The original ldappasswd(1) tool was developed by Dave Storey (F5 31 * Network), based on other OpenLDAP client tools (which are, of 32 * course, based on U-MICH LDAP). This version was rewritten 33 * by Kurt D. Zeilenga (based on other OpenLDAP client tools). 34 */ 35 36 #include "portable.h" 37 38 #include <stdio.h> 39 40 #include <ac/stdlib.h> 41 42 #include <ac/ctype.h> 43 #include <ac/socket.h> 44 #include <ac/string.h> 45 #include <ac/time.h> 46 #include <ac/unistd.h> 47 48 #include <ldap.h> 49 #include "lutil.h" 50 #include "lutil_ldap.h" 51 #include "ldap_defaults.h" 52 53 #include "common.h" 54 55 56 static struct berval newpw = { 0, NULL }; 57 static struct berval oldpw = { 0, NULL }; 58 59 static int want_newpw = 0; 60 static int want_oldpw = 0; 61 62 static char *oldpwfile = NULL; 63 static char *newpwfile = NULL; 64 65 void 66 usage( void ) 67 { 68 fprintf( stderr, _("Change password of an LDAP user\n\n")); 69 fprintf( stderr,_("usage: %s [options] [user]\n"), prog); 70 fprintf( stderr, _(" user: the authentication identity, commonly a DN\n")); 71 fprintf( stderr, _("Password change options:\n")); 72 fprintf( stderr, _(" -a secret old password\n")); 73 fprintf( stderr, _(" -A prompt for old password\n")); 74 fprintf( stderr, _(" -t file read file for old password\n")); 75 fprintf( stderr, _(" -s secret new password\n")); 76 fprintf( stderr, _(" -S prompt for new password\n")); 77 fprintf( stderr, _(" -T file read file for new password\n")); 78 tool_common_usage(); 79 exit( EXIT_FAILURE ); 80 } 81 82 83 const char options[] = "a:As:St:T:" 84 "d:D:e:h:H:InO:o:p:QR:U:vVw:WxX:y:Y:Z"; 85 86 int 87 handle_private_option( int i ) 88 { 89 switch ( i ) { 90 #if 0 91 case 'E': /* passwd extensions */ { 92 int crit; 93 char *control, *cvalue; 94 if( protocol == LDAP_VERSION2 ) { 95 fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"), 96 prog, protocol ); 97 exit( EXIT_FAILURE ); 98 } 99 100 /* should be extended to support comma separated list of 101 * [!]key[=value] parameters, e.g. -E !foo,bar=567 102 */ 103 104 crit = 0; 105 cvalue = NULL; 106 if( optarg[0] == '!' ) { 107 crit = 1; 108 optarg++; 109 } 110 111 control = strdup( optarg ); 112 if ( (cvalue = strchr( control, '=' )) != NULL ) { 113 *cvalue++ = '\0'; 114 } 115 fprintf( stderr, _("Invalid passwd extension name: %s\n"), control ); 116 usage(); 117 } 118 #endif 119 120 case 'a': /* old password (secret) */ 121 oldpw.bv_val = strdup( optarg ); 122 { 123 char* p; 124 for( p = optarg; *p != '\0'; p++ ) { 125 *p = '\0'; 126 } 127 } 128 oldpw.bv_len = strlen( oldpw.bv_val ); 129 break; 130 131 case 'A': /* prompt for old password */ 132 want_oldpw++; 133 break; 134 135 case 's': /* new password (secret) */ 136 newpw.bv_val = strdup (optarg); 137 { 138 char* p; 139 for( p = optarg; *p != '\0'; p++ ) { 140 *p = '\0'; 141 } 142 } 143 newpw.bv_len = strlen( newpw.bv_val ); 144 break; 145 146 case 'S': /* prompt for user password */ 147 want_newpw++; 148 break; 149 150 case 't': 151 oldpwfile = optarg; 152 break; 153 154 case 'T': 155 newpwfile = optarg; 156 break; 157 158 default: 159 return 0; 160 } 161 return 1; 162 } 163 164 165 int 166 main( int argc, char *argv[] ) 167 { 168 int rc; 169 char *user = NULL; 170 171 LDAP *ld = NULL; 172 struct berval bv = {0, NULL}; 173 BerElement *ber = NULL; 174 175 int id, code = LDAP_OTHER; 176 LDAPMessage *res; 177 char *matcheddn = NULL, *text = NULL, **refs = NULL; 178 char *retoid = NULL; 179 struct berval *retdata = NULL; 180 LDAPControl **ctrls = NULL; 181 182 tool_init( TOOL_PASSWD ); 183 prog = lutil_progname( "ldappasswd", argc, argv ); 184 185 /* LDAPv3 only */ 186 protocol = LDAP_VERSION3; 187 188 tool_args( argc, argv ); 189 190 if( argc - optind > 1 ) { 191 usage(); 192 } else if ( argc - optind == 1 ) { 193 user = strdup( argv[optind] ); 194 } else { 195 user = NULL; 196 } 197 198 if( oldpwfile ) { 199 rc = lutil_get_filed_password( oldpwfile, &oldpw ); 200 if( rc ) { 201 rc = EXIT_FAILURE; 202 goto done; 203 } 204 } 205 206 if( want_oldpw && oldpw.bv_val == NULL ) { 207 /* prompt for old password */ 208 char *ckoldpw; 209 oldpw.bv_val = strdup(getpassphrase(_("Old password: "))); 210 ckoldpw = getpassphrase(_("Re-enter old password: ")); 211 212 if( oldpw.bv_val == NULL || ckoldpw == NULL || 213 strcmp( oldpw.bv_val, ckoldpw )) 214 { 215 fprintf( stderr, _("passwords do not match\n") ); 216 rc = EXIT_FAILURE; 217 goto done; 218 } 219 220 oldpw.bv_len = strlen( oldpw.bv_val ); 221 } 222 223 if( newpwfile ) { 224 rc = lutil_get_filed_password( newpwfile, &newpw ); 225 if( rc ) { 226 rc = EXIT_FAILURE; 227 goto done; 228 } 229 } 230 231 if( want_newpw && newpw.bv_val == NULL ) { 232 /* prompt for new password */ 233 char *cknewpw; 234 newpw.bv_val = strdup(getpassphrase(_("New password: "))); 235 cknewpw = getpassphrase(_("Re-enter new password: ")); 236 237 if( newpw.bv_val == NULL || cknewpw == NULL || 238 strcmp( newpw.bv_val, cknewpw )) 239 { 240 fprintf( stderr, _("passwords do not match\n") ); 241 rc = EXIT_FAILURE; 242 goto done; 243 } 244 245 newpw.bv_len = strlen( newpw.bv_val ); 246 } 247 248 if ( pw_file ) { 249 rc = lutil_get_filed_password( pw_file, &passwd ); 250 if( rc ) { 251 rc = EXIT_FAILURE; 252 goto done; 253 } 254 255 } else if ( want_bindpw ) { 256 passwd.bv_val = getpassphrase( _("Enter LDAP Password: ") ); 257 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0; 258 } 259 260 ld = tool_conn_setup( 0, 0 ); 261 262 tool_bind( ld ); 263 264 if ( assertion || authzid || manageDSAit || noop ) { 265 tool_server_controls( ld, NULL, 0 ); 266 } 267 268 if( user != NULL || oldpw.bv_val != NULL || newpw.bv_val != NULL ) { 269 /* build the password modify request data */ 270 ber = ber_alloc_t( LBER_USE_DER ); 271 272 if( ber == NULL ) { 273 perror( "ber_alloc_t" ); 274 rc = EXIT_FAILURE; 275 goto done; 276 } 277 278 ber_printf( ber, "{" /*}*/ ); 279 280 if( user != NULL ) { 281 ber_printf( ber, "ts", 282 LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user ); 283 free(user); 284 } 285 286 if( oldpw.bv_val != NULL ) { 287 ber_printf( ber, "tO", 288 LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &oldpw ); 289 free(oldpw.bv_val); 290 } 291 292 if( newpw.bv_val != NULL ) { 293 ber_printf( ber, "tO", 294 LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw ); 295 free(newpw.bv_val); 296 } 297 298 ber_printf( ber, /*{*/ "N}" ); 299 300 rc = ber_flatten2( ber, &bv, 0 ); 301 302 if( rc < 0 ) { 303 perror( "ber_flatten2" ); 304 rc = EXIT_FAILURE; 305 goto done; 306 } 307 } 308 309 if ( dont ) { 310 rc = LDAP_SUCCESS; 311 goto done; 312 } 313 314 tool_server_controls( ld, NULL, 0); 315 316 rc = ldap_extended_operation( ld, 317 LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL, 318 NULL, NULL, &id ); 319 320 ber_free( ber, 1 ); 321 322 if( rc != LDAP_SUCCESS ) { 323 tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL ); 324 rc = EXIT_FAILURE; 325 goto done; 326 } 327 328 for ( ; ; ) { 329 struct timeval tv; 330 331 if ( tool_check_abandon( ld, id ) ) { 332 return LDAP_CANCELLED; 333 } 334 335 tv.tv_sec = 0; 336 tv.tv_usec = 100000; 337 338 rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res ); 339 if ( rc < 0 ) { 340 tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); 341 return rc; 342 } 343 344 if ( rc != 0 ) { 345 break; 346 } 347 } 348 349 rc = ldap_parse_result( ld, res, 350 &code, &matcheddn, &text, &refs, &ctrls, 0 ); 351 if( rc != LDAP_SUCCESS ) { 352 tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL ); 353 rc = EXIT_FAILURE; 354 goto done; 355 } 356 357 rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 ); 358 if( rc != LDAP_SUCCESS ) { 359 tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL ); 360 rc = EXIT_FAILURE; 361 goto done; 362 } 363 364 if( retdata != NULL ) { 365 ber_tag_t tag; 366 char *s; 367 ber = ber_init( retdata ); 368 369 if( ber == NULL ) { 370 perror( "ber_init" ); 371 rc = EXIT_FAILURE; 372 goto done; 373 } 374 375 /* we should check the tag */ 376 tag = ber_scanf( ber, "{a}", &s); 377 378 if( tag == LBER_ERROR ) { 379 perror( "ber_scanf" ); 380 } else { 381 printf(_("New password: %s\n"), s); 382 free( s ); 383 } 384 385 ber_free( ber, 1 ); 386 387 } else if ( code == LDAP_SUCCESS && newpw.bv_val == NULL ) { 388 tool_perror( "ldap_parse_extended_result", LDAP_DECODING_ERROR, 389 " new password expected", NULL, NULL, NULL ); 390 } 391 392 skip: 393 if( verbose || code != LDAP_SUCCESS || 394 matcheddn || text || refs || ctrls ) 395 { 396 printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code ); 397 398 if( text && *text ) { 399 printf( _("Additional info: %s\n"), text ); 400 } 401 402 if( matcheddn && *matcheddn ) { 403 printf( _("Matched DN: %s\n"), matcheddn ); 404 } 405 406 if( refs ) { 407 int i; 408 for( i=0; refs[i]; i++ ) { 409 printf(_("Referral: %s\n"), refs[i] ); 410 } 411 } 412 413 if( ctrls ) { 414 tool_print_ctrls( ld, ctrls ); 415 ldap_controls_free( ctrls ); 416 } 417 } 418 419 ber_memfree( text ); 420 ber_memfree( matcheddn ); 421 ber_memvfree( (void **) refs ); 422 ber_memfree( retoid ); 423 ber_bvfree( retdata ); 424 425 rc = ( code == LDAP_SUCCESS ) ? EXIT_SUCCESS : EXIT_FAILURE; 426 427 done: 428 /* disconnect from server */ 429 if ( ld ) 430 tool_unbind( ld ); 431 tool_destroy(); 432 return rc; 433 } 434