1 /* $NetBSD: ldapmodrdn.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */ 4 /* OpenLDAP: pkg/ldap/clients/tools/ldapmodrdn.c,v 1.116.2.8 2009/08/13 00:55:07 quanah Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2009 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 1999, Juan C. Gomez, All rights reserved. 22 * This software is not subject to any license of Silicon Graphics 23 * Inc. or Purdue University. 24 * 25 * Redistribution and use in source and binary forms are permitted 26 * without restriction or fee of any kind as long as this notice 27 * is preserved. 28 */ 29 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms are permitted 33 * provided that this notice is preserved and that due credit is given 34 * to the University of Michigan at Ann Arbor. The name of the 35 * University may not be used to endorse or promote products derived 36 * from this software without specific prior written permission. This 37 * software is provided ``as is'' without express or implied warranty. 38 */ 39 /* ACKNOWLEDGEMENTS: 40 * This work was originally developed by the University of Michigan 41 * (as part of U-MICH LDAP). Additional significant contributors 42 * include: 43 * Kurt D. Zeilenga 44 * Juan C Gomez 45 */ 46 47 48 #include "portable.h" 49 50 #include <stdio.h> 51 52 #include <ac/stdlib.h> 53 54 #include <ac/ctype.h> 55 #include <ac/string.h> 56 #include <ac/unistd.h> 57 #include <ac/socket.h> 58 #include <ac/time.h> 59 60 #include <ldap.h> 61 #include "lutil.h" 62 #include "lutil_ldap.h" 63 #include "ldap_defaults.h" 64 65 #include "common.h" 66 67 68 static char *newSuperior = NULL; 69 static int remove_old_RDN = 0; 70 71 72 static int domodrdn( 73 LDAP *ld, 74 char *dn, 75 char *rdn, 76 char *newSuperior, 77 int remove ); /* flag: remove old RDN */ 78 79 void 80 usage( void ) 81 { 82 fprintf( stderr, _("Rename LDAP entries\n\n")); 83 fprintf( stderr, _("usage: %s [options] [dn rdn]\n"), prog); 84 fprintf( stderr, _(" dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n")); 85 fprintf( stderr, _(" If not given, the list of modifications is read from stdin or\n")); 86 fprintf( stderr, _(" from the file specified by \"-f file\" (see man page).\n")); 87 fprintf( stderr, _("Rename options:\n")); 88 fprintf( stderr, _(" -c continuous operation mode (do not stop on errors)\n")); 89 fprintf( stderr, _(" -f file read operations from `file'\n")); 90 fprintf( stderr, _(" -M enable Manage DSA IT control (-MM to make critical)\n")); 91 fprintf( stderr, _(" -P version protocol version (default: 3)\n")); 92 fprintf( stderr, _(" -r remove old RDN\n")); 93 fprintf( stderr, _(" -s newsup new superior entry\n")); 94 tool_common_usage(); 95 exit( EXIT_FAILURE ); 96 } 97 98 99 const char options[] = "rs:" 100 "cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z"; 101 102 int 103 handle_private_option( int i ) 104 { 105 switch ( i ) { 106 #if 0 107 int crit; 108 char *control, *cvalue; 109 case 'E': /* modrdn extensions */ 110 if( protocol == LDAP_VERSION2 ) { 111 fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"), 112 prog, version ); 113 exit( EXIT_FAILURE ); 114 } 115 116 /* should be extended to support comma separated list of 117 * [!]key[=value] parameters, e.g. -E !foo,bar=567 118 */ 119 120 crit = 0; 121 cvalue = NULL; 122 if( optarg[0] == '!' ) { 123 crit = 1; 124 optarg++; 125 } 126 127 control = strdup( optarg ); 128 if ( (cvalue = strchr( control, '=' )) != NULL ) { 129 *cvalue++ = '\0'; 130 } 131 fprintf( stderr, _("Invalid modrdn extension name: %s\n"), control ); 132 usage(); 133 #endif 134 135 case 'r': /* remove old RDN */ 136 remove_old_RDN++; 137 break; 138 139 case 's': /* newSuperior */ 140 if( protocol == LDAP_VERSION2 ) { 141 fprintf( stderr, _("%s: -X incompatible with LDAPv%d\n"), 142 prog, protocol ); 143 exit( EXIT_FAILURE ); 144 } 145 newSuperior = strdup( optarg ); 146 protocol = LDAP_VERSION3; 147 break; 148 149 default: 150 return 0; 151 } 152 return 1; 153 } 154 155 156 int 157 main(int argc, char **argv) 158 { 159 char *entrydn = NULL, *rdn = NULL, buf[ 4096 ]; 160 FILE *fp = NULL; 161 LDAP *ld; 162 int rc, retval, havedn; 163 164 tool_init( TOOL_MODRDN ); 165 prog = lutil_progname( "ldapmodrdn", argc, argv ); 166 167 tool_args( argc, argv ); 168 169 havedn = 0; 170 if (argc - optind == 2) { 171 if (( rdn = strdup( argv[argc - 1] )) == NULL ) { 172 perror( "strdup" ); 173 retval = EXIT_FAILURE; 174 goto fail; 175 } 176 if (( entrydn = strdup( argv[argc - 2] )) == NULL ) { 177 perror( "strdup" ); 178 retval = EXIT_FAILURE; 179 goto fail; 180 } 181 ++havedn; 182 } else if ( argc - optind != 0 ) { 183 fprintf( stderr, _("%s: invalid number of arguments (%d), only two allowed\n"), prog, argc-optind ); 184 usage(); 185 } 186 187 if ( infile != NULL ) { 188 if (( fp = fopen( infile, "r" )) == NULL ) { 189 perror( infile ); 190 retval = EXIT_FAILURE; 191 goto fail; 192 } 193 } else { 194 fp = stdin; 195 } 196 197 ld = tool_conn_setup( 0, 0 ); 198 199 if ( pw_file || want_bindpw ) { 200 if ( pw_file ) { 201 rc = lutil_get_filed_password( pw_file, &passwd ); 202 if( rc ) { 203 retval = EXIT_FAILURE; 204 goto fail; 205 } 206 } else { 207 passwd.bv_val = getpassphrase( _("Enter LDAP Password: ") ); 208 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0; 209 } 210 } 211 212 tool_bind( ld ); 213 214 tool_server_controls( ld, NULL, 0 ); 215 216 retval = rc = 0; 217 if (havedn) 218 retval = domodrdn( ld, entrydn, rdn, newSuperior, remove_old_RDN ); 219 else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { 220 if ( *buf != '\n' ) { /* blank lines optional, skip */ 221 buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */ 222 223 if ( havedn ) { /* have DN, get RDN */ 224 if (( rdn = strdup( buf )) == NULL ) { 225 perror( "strdup" ); 226 retval = EXIT_FAILURE; 227 goto fail; 228 } 229 rc = domodrdn(ld, entrydn, rdn, newSuperior, remove_old_RDN ); 230 if ( rc != 0 ) 231 retval = rc; 232 havedn = 0; 233 free( rdn ); rdn = NULL; 234 free( entrydn ); entrydn = NULL; 235 } else if ( !havedn ) { /* don't have DN yet */ 236 if (( entrydn = strdup( buf )) == NULL ) { 237 retval = EXIT_FAILURE; 238 goto fail; 239 } 240 ++havedn; 241 } 242 } 243 } 244 245 tool_unbind( ld ); 246 tool_destroy(); 247 fail: 248 if ( fp && fp != stdin ) fclose( fp ); 249 if ( entrydn ) free( entrydn ); 250 if ( rdn ) free( rdn ); 251 return( retval ); 252 } 253 254 static int domodrdn( 255 LDAP *ld, 256 char *dn, 257 char *rdn, 258 char *newSuperior, 259 int remove ) /* flag: remove old RDN */ 260 { 261 int rc, code, id; 262 char *matcheddn=NULL, *text=NULL, **refs=NULL; 263 LDAPControl **ctrls = NULL; 264 LDAPMessage *res; 265 266 if ( verbose ) { 267 printf( _("Renaming \"%s\"\n"), dn ); 268 printf( _("\tnew rdn=\"%s\" (%s old rdn)\n"), 269 rdn, remove ? _("delete") : _("keep") ); 270 if( newSuperior != NULL ) { 271 printf(_("\tnew parent=\"%s\"\n"), newSuperior); 272 } 273 } 274 275 if( dont ) return LDAP_SUCCESS; 276 277 rc = ldap_rename( ld, dn, rdn, newSuperior, remove, 278 NULL, NULL, &id ); 279 280 if ( rc != LDAP_SUCCESS ) { 281 fprintf( stderr, "%s: ldap_rename: %s (%d)\n", 282 prog, ldap_err2string( rc ), rc ); 283 return rc; 284 } 285 286 for ( ; ; ) { 287 struct timeval tv = { 0, 0 }; 288 289 if ( tool_check_abandon( ld, id ) ) { 290 return LDAP_CANCELLED; 291 } 292 293 tv.tv_sec = 0; 294 tv.tv_usec = 100000; 295 296 rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res ); 297 if ( rc < 0 ) { 298 tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); 299 return rc; 300 } 301 302 if ( rc != 0 ) { 303 break; 304 } 305 } 306 307 rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 ); 308 309 if( rc != LDAP_SUCCESS ) { 310 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n", 311 prog, ldap_err2string( rc ), rc ); 312 return rc; 313 } 314 315 if( verbose || code != LDAP_SUCCESS || 316 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) 317 { 318 printf( _("Rename Result: %s (%d)\n"), 319 ldap_err2string( code ), code ); 320 321 if( text && *text ) { 322 printf( _("Additional info: %s\n"), text ); 323 } 324 325 if( matcheddn && *matcheddn ) { 326 printf( _("Matched DN: %s\n"), matcheddn ); 327 } 328 329 if( refs ) { 330 int i; 331 for( i=0; refs[i]; i++ ) { 332 printf(_("Referral: %s\n"), refs[i] ); 333 } 334 } 335 } 336 337 if (ctrls) { 338 tool_print_ctrls( ld, ctrls ); 339 ldap_controls_free( ctrls ); 340 } 341 342 ber_memfree( text ); 343 ber_memfree( matcheddn ); 344 ber_memvfree( (void **) refs ); 345 346 return code; 347 } 348