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