1 /* $NetBSD: ldapmodrdn.c,v 1.1.1.5 2017/02/09 01:46:43 christos 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-2016 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 <sys/cdefs.h> 49 __RCSID("$NetBSD: ldapmodrdn.c,v 1.1.1.5 2017/02/09 01:46:43 christos Exp $"); 50 51 #include "portable.h" 52 53 #include <stdio.h> 54 55 #include <ac/stdlib.h> 56 57 #include <ac/ctype.h> 58 #include <ac/string.h> 59 #include <ac/unistd.h> 60 #include <ac/socket.h> 61 #include <ac/time.h> 62 63 #include <ldap.h> 64 #include "lutil.h" 65 #include "lutil_ldap.h" 66 #include "ldap_defaults.h" 67 68 #include "common.h" 69 70 71 static char *newSuperior = NULL; 72 static int remove_old_RDN = 0; 73 74 75 static int domodrdn( 76 LDAP *ld, 77 char *dn, 78 char *rdn, 79 char *newSuperior, 80 int remove ); /* flag: remove old RDN */ 81 82 void 83 usage( void ) 84 { 85 fprintf( stderr, _("Rename LDAP entries\n\n")); 86 fprintf( stderr, _("usage: %s [options] [dn rdn]\n"), prog); 87 fprintf( stderr, _(" dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n")); 88 fprintf( stderr, _(" If not given, the list of modifications is read from stdin or\n")); 89 fprintf( stderr, _(" from the file specified by \"-f file\" (see man page).\n")); 90 fprintf( stderr, _("Rename options:\n")); 91 fprintf( stderr, _(" -c continuous operation mode (do not stop on errors)\n")); 92 fprintf( stderr, _(" -f file read operations from `file'\n")); 93 fprintf( stderr, _(" -M enable Manage DSA IT control (-MM to make critical)\n")); 94 fprintf( stderr, _(" -P version protocol version (default: 3)\n")); 95 fprintf( stderr, _(" -r remove old RDN\n")); 96 fprintf( stderr, _(" -s newsup new superior entry\n")); 97 tool_common_usage(); 98 exit( EXIT_FAILURE ); 99 } 100 101 102 const char options[] = "rs:" 103 "cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z"; 104 105 int 106 handle_private_option( int i ) 107 { 108 switch ( i ) { 109 #if 0 110 int crit; 111 char *control, *cvalue; 112 case 'E': /* modrdn extensions */ 113 if( protocol == LDAP_VERSION2 ) { 114 fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"), 115 prog, version ); 116 exit( EXIT_FAILURE ); 117 } 118 119 /* should be extended to support comma separated list of 120 * [!]key[=value] parameters, e.g. -E !foo,bar=567 121 */ 122 123 crit = 0; 124 cvalue = NULL; 125 if( optarg[0] == '!' ) { 126 crit = 1; 127 optarg++; 128 } 129 130 control = strdup( optarg ); 131 if ( (cvalue = strchr( control, '=' )) != NULL ) { 132 *cvalue++ = '\0'; 133 } 134 fprintf( stderr, _("Invalid modrdn extension name: %s\n"), control ); 135 usage(); 136 #endif 137 138 case 'r': /* remove old RDN */ 139 remove_old_RDN++; 140 break; 141 142 case 's': /* newSuperior */ 143 if( protocol == LDAP_VERSION2 ) { 144 fprintf( stderr, _("%s: -X incompatible with LDAPv%d\n"), 145 prog, protocol ); 146 exit( EXIT_FAILURE ); 147 } 148 newSuperior = strdup( optarg ); 149 protocol = LDAP_VERSION3; 150 break; 151 152 default: 153 return 0; 154 } 155 return 1; 156 } 157 158 159 int 160 main(int argc, char **argv) 161 { 162 char *entrydn = NULL, *rdn = NULL, buf[ 4096 ]; 163 FILE *fp = NULL; 164 LDAP *ld = NULL; 165 int rc, retval, havedn; 166 167 tool_init( TOOL_MODRDN ); 168 prog = lutil_progname( "ldapmodrdn", argc, argv ); 169 170 tool_args( argc, argv ); 171 172 havedn = 0; 173 if (argc - optind == 2) { 174 if (( rdn = strdup( argv[argc - 1] )) == NULL ) { 175 perror( "strdup" ); 176 retval = EXIT_FAILURE; 177 goto fail; 178 } 179 if (( entrydn = strdup( argv[argc - 2] )) == NULL ) { 180 perror( "strdup" ); 181 retval = EXIT_FAILURE; 182 goto fail; 183 } 184 ++havedn; 185 } else if ( argc - optind != 0 ) { 186 fprintf( stderr, _("%s: invalid number of arguments (%d), only two allowed\n"), prog, argc-optind ); 187 usage(); 188 } 189 190 if ( infile != NULL ) { 191 if (( fp = fopen( infile, "r" )) == NULL ) { 192 perror( infile ); 193 retval = EXIT_FAILURE; 194 goto fail; 195 } 196 } else { 197 fp = stdin; 198 } 199 200 ld = tool_conn_setup( 0, 0 ); 201 202 tool_bind( ld ); 203 204 tool_server_controls( ld, NULL, 0 ); 205 206 retval = rc = 0; 207 if (havedn) 208 retval = domodrdn( ld, entrydn, rdn, newSuperior, remove_old_RDN ); 209 else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) { 210 if ( *buf != '\n' ) { /* blank lines optional, skip */ 211 buf[ strlen( buf ) - 1 ] = '\0'; /* remove nl */ 212 213 if ( havedn ) { /* have DN, get RDN */ 214 if (( rdn = strdup( buf )) == NULL ) { 215 perror( "strdup" ); 216 retval = EXIT_FAILURE; 217 goto fail; 218 } 219 rc = domodrdn(ld, entrydn, rdn, newSuperior, remove_old_RDN ); 220 if ( rc != 0 ) 221 retval = rc; 222 havedn = 0; 223 free( rdn ); rdn = NULL; 224 free( entrydn ); entrydn = NULL; 225 } else if ( !havedn ) { /* don't have DN yet */ 226 if (( entrydn = strdup( buf )) == NULL ) { 227 retval = EXIT_FAILURE; 228 goto fail; 229 } 230 ++havedn; 231 } 232 } 233 } 234 235 fail: 236 if ( fp && fp != stdin ) fclose( fp ); 237 if ( entrydn ) free( entrydn ); 238 if ( rdn ) free( rdn ); 239 tool_exit( ld, retval ); 240 } 241 242 static int domodrdn( 243 LDAP *ld, 244 char *dn, 245 char *rdn, 246 char *newSuperior, 247 int remove ) /* flag: remove old RDN */ 248 { 249 int rc, code, id; 250 char *matcheddn=NULL, *text=NULL, **refs=NULL; 251 LDAPControl **ctrls = NULL; 252 LDAPMessage *res; 253 254 if ( verbose ) { 255 printf( _("Renaming \"%s\"\n"), dn ); 256 printf( _("\tnew rdn=\"%s\" (%s old rdn)\n"), 257 rdn, remove ? _("delete") : _("keep") ); 258 if( newSuperior != NULL ) { 259 printf(_("\tnew parent=\"%s\"\n"), newSuperior); 260 } 261 } 262 263 if( dont ) return LDAP_SUCCESS; 264 265 rc = ldap_rename( ld, dn, rdn, newSuperior, remove, 266 NULL, NULL, &id ); 267 268 if ( rc != LDAP_SUCCESS ) { 269 fprintf( stderr, "%s: ldap_rename: %s (%d)\n", 270 prog, ldap_err2string( rc ), rc ); 271 return rc; 272 } 273 274 for ( ; ; ) { 275 struct timeval tv = { 0, 0 }; 276 277 if ( tool_check_abandon( ld, id ) ) { 278 return LDAP_CANCELLED; 279 } 280 281 tv.tv_sec = 0; 282 tv.tv_usec = 100000; 283 284 rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res ); 285 if ( rc < 0 ) { 286 tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); 287 return rc; 288 } 289 290 if ( rc != 0 ) { 291 break; 292 } 293 } 294 295 rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, &ctrls, 1 ); 296 297 if( rc != LDAP_SUCCESS ) { 298 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n", 299 prog, ldap_err2string( rc ), rc ); 300 return rc; 301 } 302 303 if( verbose || code != LDAP_SUCCESS || 304 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) 305 { 306 printf( _("Rename Result: %s (%d)\n"), 307 ldap_err2string( code ), code ); 308 309 if( text && *text ) { 310 printf( _("Additional info: %s\n"), text ); 311 } 312 313 if( matcheddn && *matcheddn ) { 314 printf( _("Matched DN: %s\n"), matcheddn ); 315 } 316 317 if( refs ) { 318 int i; 319 for( i=0; refs[i]; i++ ) { 320 printf(_("Referral: %s\n"), refs[i] ); 321 } 322 } 323 } 324 325 if (ctrls) { 326 tool_print_ctrls( ld, ctrls ); 327 ldap_controls_free( ctrls ); 328 } 329 330 ber_memfree( text ); 331 ber_memfree( matcheddn ); 332 ber_memvfree( (void **) refs ); 333 334 return code; 335 } 336