1 /* $NetBSD: ldapmodrdn.c,v 1.1.1.4 2014/05/28 09:58:20 tron Exp $ */ 2 3 /* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2014 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 = NULL; 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 tool_bind( ld ); 200 201 tool_server_controls( ld, NULL, 0 ); 202 203 retval = rc = 0; 204 if (havedn) 205 retval = domodrdn( ld, entrydn, rdn, newSuperior, remove_old_RDN ); 206 else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { 207 if ( *buf != '\n' ) { /* blank lines optional, skip */ 208 buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */ 209 210 if ( havedn ) { /* have DN, get RDN */ 211 if (( rdn = strdup( buf )) == NULL ) { 212 perror( "strdup" ); 213 retval = EXIT_FAILURE; 214 goto fail; 215 } 216 rc = domodrdn(ld, entrydn, rdn, newSuperior, remove_old_RDN ); 217 if ( rc != 0 ) 218 retval = rc; 219 havedn = 0; 220 free( rdn ); rdn = NULL; 221 free( entrydn ); entrydn = NULL; 222 } else if ( !havedn ) { /* don't have DN yet */ 223 if (( entrydn = strdup( buf )) == NULL ) { 224 retval = EXIT_FAILURE; 225 goto fail; 226 } 227 ++havedn; 228 } 229 } 230 } 231 232 fail: 233 if ( fp && fp != stdin ) fclose( fp ); 234 if ( entrydn ) free( entrydn ); 235 if ( rdn ) free( rdn ); 236 tool_exit( ld, retval ); 237 } 238 239 static int domodrdn( 240 LDAP *ld, 241 char *dn, 242 char *rdn, 243 char *newSuperior, 244 int remove ) /* flag: remove old RDN */ 245 { 246 int rc, code, id; 247 char *matcheddn=NULL, *text=NULL, **refs=NULL; 248 LDAPControl **ctrls = NULL; 249 LDAPMessage *res; 250 251 if ( verbose ) { 252 printf( _("Renaming \"%s\"\n"), dn ); 253 printf( _("\tnew rdn=\"%s\" (%s old rdn)\n"), 254 rdn, remove ? _("delete") : _("keep") ); 255 if( newSuperior != NULL ) { 256 printf(_("\tnew parent=\"%s\"\n"), newSuperior); 257 } 258 } 259 260 if( dont ) return LDAP_SUCCESS; 261 262 rc = ldap_rename( ld, dn, rdn, newSuperior, remove, 263 NULL, NULL, &id ); 264 265 if ( rc != LDAP_SUCCESS ) { 266 fprintf( stderr, "%s: ldap_rename: %s (%d)\n", 267 prog, ldap_err2string( rc ), rc ); 268 return rc; 269 } 270 271 for ( ; ; ) { 272 struct timeval tv = { 0, 0 }; 273 274 if ( tool_check_abandon( ld, id ) ) { 275 return LDAP_CANCELLED; 276 } 277 278 tv.tv_sec = 0; 279 tv.tv_usec = 100000; 280 281 rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res ); 282 if ( rc < 0 ) { 283 tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); 284 return rc; 285 } 286 287 if ( rc != 0 ) { 288 break; 289 } 290 } 291 292 rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 ); 293 294 if( rc != LDAP_SUCCESS ) { 295 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n", 296 prog, ldap_err2string( rc ), rc ); 297 return rc; 298 } 299 300 if( verbose || code != LDAP_SUCCESS || 301 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) 302 { 303 printf( _("Rename Result: %s (%d)\n"), 304 ldap_err2string( code ), code ); 305 306 if( text && *text ) { 307 printf( _("Additional info: %s\n"), text ); 308 } 309 310 if( matcheddn && *matcheddn ) { 311 printf( _("Matched DN: %s\n"), matcheddn ); 312 } 313 314 if( refs ) { 315 int i; 316 for( i=0; refs[i]; i++ ) { 317 printf(_("Referral: %s\n"), refs[i] ); 318 } 319 } 320 } 321 322 if (ctrls) { 323 tool_print_ctrls( ld, ctrls ); 324 ldap_controls_free( ctrls ); 325 } 326 327 ber_memfree( text ); 328 ber_memfree( matcheddn ); 329 ber_memvfree( (void **) refs ); 330 331 return code; 332 } 333