]> git.sur5r.net Git - openldap/blob - clients/tools/ldapmodrdn.c
eeedfee48aef98f9b08cf4377bf1c38d150730a4
[openldap] / clients / tools / ldapmodrdn.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* ldapmodrdn.c - generic program to modify an entry's RDN using LDAP.
7  *
8  * Support for MODIFYDN REQUEST V3 (newSuperior) by:
9  * 
10  * Copyright 1999, Juan C. Gomez, All rights reserved.
11  * This software is not subject to any license of Silicon Graphics 
12  * Inc. or Purdue University.
13  *
14  * Redistribution and use in source and binary forms are permitted
15  * without restriction or fee of any kind as long as this notice
16  * is preserved.
17  *
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdlib.h>
25
26 #include <ac/ctype.h>
27 #include <ac/signal.h>
28 #include <ac/string.h>
29 #include <ac/unistd.h>
30
31 #include <ldap.h>
32 #include "lutil.h"
33 #include "lutil_ldap.h"
34 #include "ldap_defaults.h"
35
36 static char *prog = NULL;
37 static char     *binddn = NULL;
38 static struct berval passwd = { 0, NULL };
39 static char     *ldapuri = NULL;
40 static char     *ldaphost = NULL;
41 static int      ldapport = 0;
42 #ifdef HAVE_CYRUS_SASL
43 static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
44 static char *sasl_realm = NULL;
45 static char     *sasl_authc_id = NULL;
46 static char     *sasl_authz_id = NULL;
47 static char     *sasl_mech = NULL;
48 static char     *sasl_secprops = NULL;
49 #endif
50 static int      use_tls = 0;
51 static int      not, verbose, contoper;
52 static LDAP     *ld = NULL;
53
54 static int domodrdn(
55     LDAP        *ld,
56     char        *dn,
57     char        *rdn,
58     char        *newSuperior,
59     int         remove );       /* flag: remove old RDN */
60
61 static void
62 usage( const char *s )
63 {
64         fprintf( stderr,
65 "Rename LDAP entries\n\n"
66 "usage: %s [options] [dn rdn]\n"
67 "       dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n"
68 "               If not given, the list of modifications is read from stdin or\n"
69 "               from the file specified by \"-f file\" (see man page).\n"
70 "Rename options:\n"
71 "  -c         continuous operation mode (do not stop on errors)\n"
72 "  -f file    read operations from `file'\n"
73 "  -r         remove old RDN\n"
74 "  -s newsup  new superior entry\n"
75
76 "Common options:\n"
77 "  -d level   set LDAP debugging level to `level'\n"
78 "  -D binddn  bind DN\n"
79 "  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
80 "             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
81 "             [!]manageDSAit   (alternate form, see -M)\n"
82 "             [!]noop\n"
83 "  -f file    read operations from `file'\n"
84 "  -h host    LDAP server\n"
85 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
86 "  -I         use SASL Interactive mode\n"
87 "  -k         use Kerberos authentication\n"
88 "  -K         like -k, but do only step 1 of the Kerberos bind\n"
89 "  -M         enable Manage DSA IT control (-MM to make critical)\n"
90 "  -n         show what would be done but don't actually update\n"
91 "  -O props   SASL security properties\n"
92 "  -p port    port on LDAP server\n"
93 "  -P version procotol version (default: 3)\n"
94 "  -Q         use SASL Quiet mode\n"
95 "  -R realm   SASL realm\n"
96 "  -U authzid SASL authentication identity\n"
97 "  -v         run in verbose mode (diagnostics to standard output)\n"
98 "  -w passwd  bind passwd (for simple authentication)\n"
99 "  -W         prompt for bind passwd\n"
100 "  -x         Simple authentication\n"
101 "  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
102 "  -y file    Read passwd from file\n"
103 "  -Y mech    SASL mechanism\n"
104 "  -Z         Start TLS request (-ZZ to require successful response)\n"
105 ,               s );
106
107         exit( EXIT_FAILURE );
108 }
109
110 int
111 main(int argc, char **argv)
112 {
113     char                *infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
114     FILE                *fp;
115         int             rc, retval, i, remove, havedn, authmethod, version;
116         int             want_bindpw, debug, manageDSAit, noop, crit;
117         int             referrals;
118     char        *newSuperior=NULL;
119         char    *pw_file = NULL;
120         char    *control, *cvalue;
121         char    *authzid = NULL;
122
123     infile = NULL;
124     not = contoper = verbose = remove = want_bindpw =
125                 debug = manageDSAit = noop = referrals = 0;
126     authmethod = -1;
127         version = -1;
128
129     prog = lutil_progname( "ldapmodrdn", argc, argv );
130
131     while (( i = getopt( argc, argv, "cf:rs:"
132                 "Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
133         {
134         switch( i ) {
135         /* Modrdn Options */
136         case 'c':
137                 contoper++;
138                 break;
139         case 'E': /* modrdn controls */
140                 if( version == LDAP_VERSION2 ) {
141                         fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
142                                 prog, version );
143                         return EXIT_FAILURE;
144                 }
145
146                 /* should be extended to support comma separated list of
147                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
148                  */
149
150                 crit = 0;
151                 cvalue = NULL;
152                 if( optarg[0] == '!' ) {
153                         crit = 1;
154                         optarg++;
155                 }
156
157                 control = strdup( optarg );
158                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
159                         *cvalue++ = '\0';
160                 }
161                 fprintf( stderr, "Invalid modrdn control name: %s\n", control );
162                 usage(prog);
163                 return EXIT_FAILURE;
164         case 'f':       /* read from file */
165                 if( infile != NULL ) {
166                         fprintf( stderr, "%s: -f previously specified\n", prog );
167                         return EXIT_FAILURE;
168                 }
169             infile = strdup( optarg );
170             break;
171         case 'r':       /* remove old RDN */
172             remove++;
173             break;
174         case 's':       /* newSuperior */
175                 if( version == LDAP_VERSION2 ) {
176                         fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
177                                 prog, version );
178                         return EXIT_FAILURE;
179                 }
180             newSuperior = strdup( optarg );
181             version = LDAP_VERSION3;
182             break;
183
184         /* Common Options */
185         case 'C':
186                 referrals++;
187                 break;
188         case 'd':
189             debug |= atoi( optarg );
190             break;
191         case 'D':       /* bind DN */
192                 if( binddn != NULL ) {
193                         fprintf( stderr, "%s: -D previously specified\n", prog );
194                         return EXIT_FAILURE;
195                 }
196             binddn = strdup( optarg );
197             break;
198         case 'e': /* general controls */
199                 if( version == LDAP_VERSION2 ) {
200                         fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
201                                 prog, version );
202                         return EXIT_FAILURE;
203                 }
204
205                 /* should be extended to support comma separated list of
206                  *      [!]key[=value] parameters, e.g.  -e !foo,bar=567
207                  */
208
209                 crit = 0;
210                 cvalue = NULL;
211                 if( optarg[0] == '!' ) {
212                         crit = 1;
213                         optarg++;
214                 }
215
216                 control = strdup( optarg );
217                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
218                         *cvalue++ = '\0';
219                 }
220
221                 if ( strcasecmp( control, "authzid" ) == 0 ) {
222                         if( authzid != NULL ) {
223                                 fprintf( stderr, "authzid control previously specified\n");
224                                 return EXIT_FAILURE;
225                         }
226                         if( cvalue == NULL ) {
227                                 fprintf( stderr, "authzid: control value expected\n" );
228                                 usage(prog);
229                                 return EXIT_FAILURE;
230                         }
231                         if( !crit ) {
232                                 fprintf( stderr, "authzid: must be marked critical\n" );
233                                 usage(prog);
234                                 return EXIT_FAILURE;
235                         }
236
237                         assert( authzid == NULL );
238                         authzid = cvalue;
239
240                 } else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
241                         if( manageDSAit ) {
242                                 fprintf( stderr, "manageDSAit control previously specified\n");
243                                 return EXIT_FAILURE;
244                         }
245                         if( cvalue != NULL ) {
246                                 fprintf( stderr, "manageDSAit: no control value expected\n" );
247                                 usage(prog);
248                                 return EXIT_FAILURE;
249                         }
250
251                         manageDSAit = 1 + crit;
252
253                 } else if ( strcasecmp( control, "noop" ) == 0 ) {
254                         if( noop ) {
255                                 fprintf( stderr, "noop control previously specified\n");
256                                 return EXIT_FAILURE;
257                         }
258                         if( cvalue != NULL ) {
259                                 fprintf( stderr, "noop: no control value expected\n" );
260                                 usage(prog);
261                                 return EXIT_FAILURE;
262                         }
263
264                         noop = 1 + crit;
265
266                 } else {
267                         fprintf( stderr, "Invalid general control name: %s\n", control );
268                         usage(prog);
269                         return EXIT_FAILURE;
270                 }
271                 break;
272         case 'h':       /* ldap host */
273                 if( ldapuri != NULL ) {
274                         fprintf( stderr, "%s: -h incompatible with -H\n", prog );
275                         return EXIT_FAILURE;
276                 }
277                 if( ldaphost != NULL ) {
278                         fprintf( stderr, "%s: -h previously specified\n", prog );
279                         return EXIT_FAILURE;
280                 }
281             ldaphost = strdup( optarg );
282             break;
283         case 'H':       /* ldap URI */
284                 if( ldaphost != NULL ) {
285                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
286                         return EXIT_FAILURE;
287                 }
288                 if( ldapport ) {
289                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
290                         return EXIT_FAILURE;
291                 }
292                 if( ldapuri != NULL ) {
293                         fprintf( stderr, "%s: -H previously specified\n", prog );
294                         return EXIT_FAILURE;
295                 }
296             ldapuri = strdup( optarg );
297             break;
298         case 'I':
299 #ifdef HAVE_CYRUS_SASL
300                 if( version == LDAP_VERSION2 ) {
301                         fprintf( stderr, "%s: -I incompatible with version %d\n",
302                                 prog, version );
303                         return EXIT_FAILURE;
304                 }
305                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
306                         fprintf( stderr, "%s: incompatible previous "
307                                 "authentication choice\n",
308                                 prog );
309                         return EXIT_FAILURE;
310                 }
311                 authmethod = LDAP_AUTH_SASL;
312                 version = LDAP_VERSION3;
313                 sasl_flags = LDAP_SASL_INTERACTIVE;
314                 break;
315 #else
316                 fprintf( stderr, "%s: was not compiled with SASL support\n",
317                         prog );
318                 return( EXIT_FAILURE );
319 #endif
320         case 'k':       /* kerberos bind */
321 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
322                 if( version > LDAP_VERSION2 ) {
323                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
324                                 prog, version );
325                         return EXIT_FAILURE;
326                 }
327
328                 if( authmethod != -1 ) {
329                         fprintf( stderr, "%s: -k incompatible with previous "
330                                 "authentication choice\n", prog );
331                         return EXIT_FAILURE;
332                 }
333                         
334                 authmethod = LDAP_AUTH_KRBV4;
335 #else
336                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
337                 return EXIT_FAILURE;
338 #endif
339             break;
340         case 'K':       /* kerberos bind, part one only */
341 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
342                 if( version > LDAP_VERSION2 ) {
343                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
344                                 prog, version );
345                         return EXIT_FAILURE;
346                 }
347                 if( authmethod != -1 ) {
348                         fprintf( stderr, "%s: incompatible with previous "
349                                 "authentication choice\n", prog );
350                         return EXIT_FAILURE;
351                 }
352
353                 authmethod = LDAP_AUTH_KRBV41;
354 #else
355                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
356                 return( EXIT_FAILURE );
357 #endif
358             break;
359         case 'M':
360                 /* enable Manage DSA IT */
361                 if( version == LDAP_VERSION2 ) {
362                         fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
363                                 prog, version );
364                         return EXIT_FAILURE;
365                 }
366                 manageDSAit++;
367                 version = LDAP_VERSION3;
368                 break;
369         case 'n':       /* print deletes, don't actually do them */
370             ++not;
371             break;
372         case 'O':
373 #ifdef HAVE_CYRUS_SASL
374                 if( sasl_secprops != NULL ) {
375                         fprintf( stderr, "%s: -O previously specified\n", prog );
376                         return EXIT_FAILURE;
377                 }
378                 if( version == LDAP_VERSION2 ) {
379                         fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
380                                 prog, version );
381                         return EXIT_FAILURE;
382                 }
383                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
384                         fprintf( stderr, "%s: incompatible previous "
385                                 "authentication choice\n", prog );
386                         return EXIT_FAILURE;
387                 }
388                 authmethod = LDAP_AUTH_SASL;
389                 version = LDAP_VERSION3;
390                 sasl_secprops = strdup( optarg );
391 #else
392                 fprintf( stderr, "%s: not compiled with SASL support\n",
393                         prog );
394                 return( EXIT_FAILURE );
395 #endif
396                 break;
397         case 'p':
398                 if( ldapport ) {
399                         fprintf( stderr, "%s: -p previously specified\n", prog );
400                         return EXIT_FAILURE;
401                 }
402             ldapport = atoi( optarg );
403             break;
404         case 'P':
405                 switch( atoi(optarg) ) {
406                 case 2:
407                         if( version == LDAP_VERSION3 ) {
408                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
409                                         prog, version );
410                                 return EXIT_FAILURE;
411                         }
412                         version = LDAP_VERSION2;
413                         break;
414                 case 3:
415                         if( version == LDAP_VERSION2 ) {
416                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
417                                         prog, version );
418                                 return EXIT_FAILURE;
419                         }
420                         version = LDAP_VERSION3;
421                         break;
422                 default:
423                         fprintf( stderr, "%s: protocol version should be 2 or 3\n",
424                                 prog );
425                         usage( prog );
426                         return( EXIT_FAILURE );
427                 }
428                 break;
429         case 'Q':
430 #ifdef HAVE_CYRUS_SASL
431                 if( version == LDAP_VERSION2 ) {
432                         fprintf( stderr, "%s: -Q incompatible with version %d\n",
433                                 prog, version );
434                         return EXIT_FAILURE;
435                 }
436                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
437                         fprintf( stderr, "%s: incompatible previous "
438                                 "authentication choice\n",
439                                 prog );
440                         return EXIT_FAILURE;
441                 }
442                 authmethod = LDAP_AUTH_SASL;
443                 version = LDAP_VERSION3;
444                 sasl_flags = LDAP_SASL_QUIET;
445                 break;
446 #else
447                 fprintf( stderr, "%s: not compiled with SASL support\n",
448                         prog );
449                 return( EXIT_FAILURE );
450 #endif
451         case 'R':
452 #ifdef HAVE_CYRUS_SASL
453                 if( sasl_realm != NULL ) {
454                         fprintf( stderr, "%s: -R previously specified\n", prog );
455                         return EXIT_FAILURE;
456                 }
457                 if( version == LDAP_VERSION2 ) {
458                         fprintf( stderr, "%s: -R incompatible with version %d\n",
459                                 prog, version );
460                         return EXIT_FAILURE;
461                 }
462                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
463                         fprintf( stderr, "%s: incompatible previous "
464                                 "authentication choice\n",
465                                 prog );
466                         return EXIT_FAILURE;
467                 }
468                 authmethod = LDAP_AUTH_SASL;
469                 version = LDAP_VERSION3;
470                 sasl_realm = strdup( optarg );
471 #else
472                 fprintf( stderr, "%s: not compiled with SASL support\n",
473                         prog );
474                 return( EXIT_FAILURE );
475 #endif
476                 break;
477         case 'U':
478 #ifdef HAVE_CYRUS_SASL
479                 if( sasl_authc_id != NULL ) {
480                         fprintf( stderr, "%s: -U previously specified\n", prog );
481                         return EXIT_FAILURE;
482                 }
483                 if( version == LDAP_VERSION2 ) {
484                         fprintf( stderr, "%s: -U incompatible with version %d\n",
485                                 prog, version );
486                         return EXIT_FAILURE;
487                 }
488                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
489                         fprintf( stderr, "%s: incompatible previous "
490                                 "authentication choice\n",
491                                 prog );
492                         return EXIT_FAILURE;
493                 }
494                 authmethod = LDAP_AUTH_SASL;
495                 version = LDAP_VERSION3;
496                 sasl_authc_id = strdup( optarg );
497 #else
498                 fprintf( stderr, "%s: not compiled with SASL support\n",
499                         prog );
500                 return( EXIT_FAILURE );
501 #endif
502                 break;
503         case 'v':       /* verbose mode */
504             verbose++;
505             break;
506         case 'w':       /* password */
507             passwd.bv_val = strdup( optarg );
508                 {
509                         char* p;
510
511                         for( p = optarg; *p != '\0'; p++ ) {
512                                 *p = '\0';
513                         }
514                 }
515                 passwd.bv_len = strlen( passwd.bv_val );
516             break;
517         case 'W':
518                 want_bindpw++;
519                 break;
520         case 'y':
521                 pw_file = optarg;
522                 break;
523         case 'Y':
524 #ifdef HAVE_CYRUS_SASL
525                 if( sasl_mech != NULL ) {
526                         fprintf( stderr, "%s: -Y previously specified\n", prog );
527                         return EXIT_FAILURE;
528                 }
529                 if( version == LDAP_VERSION2 ) {
530                         fprintf( stderr, "%s: -Y incompatible with version %d\n",
531                                 prog, version );
532                         return EXIT_FAILURE;
533                 }
534                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
535                         fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
536                         return EXIT_FAILURE;
537                 }
538                 authmethod = LDAP_AUTH_SASL;
539                 version = LDAP_VERSION3;
540                 sasl_mech = strdup( optarg );
541 #else
542                 fprintf( stderr, "%s: not compiled with SASL support\n",
543                         prog );
544                 return( EXIT_FAILURE );
545 #endif
546                 break;
547         case 'x':
548                 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
549                         fprintf( stderr, "%s: incompatible with previous "
550                                 "authentication choice\n", prog );
551                         return EXIT_FAILURE;
552                 }
553                 authmethod = LDAP_AUTH_SIMPLE;
554                 break;
555         case 'X':
556 #ifdef HAVE_CYRUS_SASL
557                 if( sasl_authz_id != NULL ) {
558                         fprintf( stderr, "%s: -X previously specified\n", prog );
559                         return EXIT_FAILURE;
560                 }
561                 if( version == LDAP_VERSION2 ) {
562                         fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
563                                 prog, version );
564                         return EXIT_FAILURE;
565                 }
566                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
567                         fprintf( stderr, "%s: -X incompatible with "
568                                 "authentication choice\n", prog );
569                         return EXIT_FAILURE;
570                 }
571                 authmethod = LDAP_AUTH_SASL;
572                 version = LDAP_VERSION3;
573                 sasl_authz_id = strdup( optarg );
574 #else
575                 fprintf( stderr, "%s: not compiled with SASL support\n",
576                         prog );
577                 return( EXIT_FAILURE );
578 #endif
579                 break;
580         case 'Z':
581 #ifdef HAVE_TLS
582                 if( version == LDAP_VERSION2 ) {
583                         fprintf( stderr, "%s: -Z incompatible with version %d\n",
584                                 prog, version );
585                         return EXIT_FAILURE;
586                 }
587                 version = LDAP_VERSION3;
588                 use_tls++;
589 #else
590                 fprintf( stderr, "%s: not compiled with TLS support\n",
591                         prog );
592                 return( EXIT_FAILURE );
593 #endif
594                 break;
595         default:
596                 fprintf( stderr, "%s: unrecognized option -%c\n",
597                         prog, optopt );
598             usage( prog );
599             return( EXIT_FAILURE );
600         }
601     }
602
603         if (version == -1) {
604                 version = LDAP_VERSION3;
605         }
606         if (authmethod == -1 && version > LDAP_VERSION2) {
607 #ifdef HAVE_CYRUS_SASL
608                 authmethod = LDAP_AUTH_SASL;
609 #else
610                 authmethod = LDAP_AUTH_SIMPLE;
611 #endif
612         }
613
614     havedn = 0;
615     if (argc - optind == 2) {
616         if (( rdn = strdup( argv[argc - 1] )) == NULL ) {
617             perror( "strdup" );
618             return( EXIT_FAILURE );
619         }
620         if (( entrydn = strdup( argv[argc - 2] )) == NULL ) {
621             perror( "strdup" );
622             return( EXIT_FAILURE );
623         }
624         ++havedn;
625     } else if ( argc - optind != 0 ) {
626         fprintf( stderr, "%s: invalid number of arguments (%d), "
627                 "only two allowed\n", prog, argc-optind );
628         usage( prog );
629         return( EXIT_FAILURE );
630     }
631
632     if ( infile != NULL ) {
633         if (( fp = fopen( infile, "r" )) == NULL ) {
634             perror( infile );
635             return( EXIT_FAILURE );
636         }
637     } else {
638         fp = stdin;
639     }
640
641         if ( debug ) {
642                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
643                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
644                 }
645                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
646                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
647                 }
648         }
649
650 #ifdef SIGPIPE
651         (void) SIGNAL( SIGPIPE, SIG_IGN );
652 #endif
653
654         if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
655                 if ( verbose ) {
656                         fprintf( stderr, "ldap_init( %s, %d )\n",
657                                 ldaphost != NULL ? ldaphost : "<DEFAULT>",
658                                 ldapport );
659                 }
660
661                 ld = ldap_init( ldaphost, ldapport );
662                 if( ld == NULL ) {
663                         perror("ldapmodify: ldap_init");
664                         return EXIT_FAILURE;
665                 }
666
667         } else {
668                 if ( verbose ) {
669                         fprintf( stderr, "ldap_initialize( %s )\n",
670                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
671                 }
672
673                 rc = ldap_initialize( &ld, ldapuri );
674                 if( rc != LDAP_SUCCESS ) {
675                         fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
676                                 rc, ldap_err2string(rc) );
677                         return EXIT_FAILURE;
678                 }
679         }
680
681         /* referrals */
682         if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
683                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
684         {
685                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
686                         referrals ? "on" : "off" );
687                 return EXIT_FAILURE;
688         }
689
690         if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
691                 != LDAP_OPT_SUCCESS )
692         {
693                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
694                         version );
695                 return EXIT_FAILURE;
696         }
697
698         if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
699                 ldap_perror( ld, "ldap_start_tls" );
700                 if ( use_tls > 1 ) {
701                         return( EXIT_FAILURE );
702                 }
703         }
704
705         if ( pw_file || want_bindpw ) {
706                 if ( pw_file ) {
707                         rc = lutil_get_filed_password( pw_file, &passwd );
708                         if( rc ) return EXIT_FAILURE;
709                 } else {
710                         passwd.bv_val = getpassphrase( "Enter LDAP Password: " );
711                         passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
712                 }
713         }
714
715         if ( authmethod == LDAP_AUTH_SASL ) {
716 #ifdef HAVE_CYRUS_SASL
717                 void *defaults;
718
719                 if( sasl_secprops != NULL ) {
720                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
721                                 (void *) sasl_secprops );
722                         
723                         if( rc != LDAP_OPT_SUCCESS ) {
724                                 fprintf( stderr,
725                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
726                                         sasl_secprops );
727                                 return( EXIT_FAILURE );
728                         }
729                 }
730                 
731                 defaults = lutil_sasl_defaults( ld,
732                         sasl_mech,
733                         sasl_realm,
734                         sasl_authc_id,
735                         passwd.bv_val,
736                         sasl_authz_id );
737
738                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
739                         sasl_mech, NULL, NULL,
740                         sasl_flags, lutil_sasl_interact, defaults );
741
742                 if( rc != LDAP_SUCCESS ) {
743                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
744                         return( EXIT_FAILURE );
745                 }
746 #else
747                 fprintf( stderr, "%s: not compiled with SASL support\n",
748                         prog );
749                 return( EXIT_FAILURE );
750 #endif
751         }
752         else {
753                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
754                                 != LDAP_SUCCESS ) {
755                         ldap_perror( ld, "ldap_bind" );
756                         return( EXIT_FAILURE );
757                 }
758         }
759
760         if ( authzid || manageDSAit || noop ) {
761                 int err, crit=0, i=0;
762                 LDAPControl c[3];
763                 LDAPControl *ctrls[4];
764
765                 if ( authzid ) {
766                         c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
767                         c[i].ldctl_value.bv_val = authzid;
768                         c[i].ldctl_value.bv_len = strlen( authzid );
769                         c[i].ldctl_iscritical = 1;
770
771                         if( c[i].ldctl_iscritical ) crit++;
772                         ctrls[i] = &c[i];
773                         ctrls[++i] = NULL;
774                 }
775
776                 if ( manageDSAit ) {
777                         c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
778                         c[i].ldctl_value.bv_val = NULL;
779                         c[i].ldctl_value.bv_len = 0;
780                         c[i].ldctl_iscritical = manageDSAit > 1;
781
782                         if( c[i].ldctl_iscritical ) crit++;
783                         ctrls[i] = &c[i];
784                         ctrls[++i] = NULL;
785                 }
786
787                 if ( noop ) {
788                         c[i].ldctl_oid = LDAP_CONTROL_NOOP;
789                         c[i].ldctl_value.bv_val = NULL;
790                         c[i].ldctl_value.bv_len = 0;
791                         c[i].ldctl_iscritical = noop > 1;
792
793                         if( c[i].ldctl_iscritical ) crit++;
794                         ctrls[i] = &c[i];
795                         ctrls[++i] = NULL;
796                 }
797         
798                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
799
800                 if( err != LDAP_OPT_SUCCESS ) {
801                         fprintf( stderr, "Could not set %scontrols\n",
802                                 crit ? "critical " : "" );
803                         if ( crit ) {
804                                 return EXIT_FAILURE;
805                         }
806                 }
807         }
808
809     retval = rc = 0;
810     if (havedn)
811         retval = domodrdn( ld, entrydn, rdn, newSuperior, remove );
812     else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
813         if ( *buf != '\0' ) {   /* blank lines optional, skip */
814             buf[ strlen( buf ) - 1 ] = '\0';    /* remove nl */
815
816             if ( havedn ) {     /* have DN, get RDN */
817                 if (( rdn = strdup( buf )) == NULL ) {
818                     perror( "strdup" );
819                     return( EXIT_FAILURE );
820                 }
821                 rc = domodrdn(ld, entrydn, rdn, newSuperior, remove );
822                 if ( rc != 0 )
823                         retval = rc;
824                 havedn = 0;
825             } else if ( !havedn ) {     /* don't have DN yet */
826                 if (( entrydn = strdup( buf )) == NULL ) {
827                     perror( "strdup" );
828                     return( EXIT_FAILURE );
829                 }
830                 ++havedn;
831             }
832         }
833     }
834
835     ldap_unbind( ld );
836
837     return( retval );
838 }
839
840 static int domodrdn(
841     LDAP        *ld,
842     char        *dn,
843     char        *rdn,
844     char        *newSuperior,
845     int         remove ) /* flag: remove old RDN */
846 {
847         int rc, code, id;
848         char *matcheddn=NULL, *text=NULL, **refs=NULL;
849         LDAPMessage *res;
850
851     if ( verbose ) {
852                 printf( "Renaming \"%s\"\n", dn );
853                 printf( "\tnew rdn=\"%s\" (%s old rdn)\n",
854                         rdn, remove ? "delete" : "keep" );
855                 if( newSuperior != NULL ) {
856                         printf("\tnew parent=\"%s\"\n", newSuperior);
857                 }
858         }
859
860         if( not ) return LDAP_SUCCESS;
861
862         rc = ldap_rename( ld, dn, rdn, newSuperior, remove,
863                 NULL, NULL, &id );
864
865         if ( rc != LDAP_SUCCESS ) {
866                 fprintf( stderr, "%s: ldap_rename: %s (%d)\n",
867                         prog, ldap_err2string( rc ), rc );
868                 return rc;
869         }
870
871         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
872         if ( rc < 0 ) {
873                 ldap_perror( ld, "ldapmodrdn: ldap_result" );
874                 return rc;
875         }
876
877         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
878
879         if( rc != LDAP_SUCCESS ) {
880                 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
881                         prog, ldap_err2string( rc ), rc );
882                 return rc;
883         }
884
885         if( verbose || code != LDAP_SUCCESS ||
886                 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
887         {
888                 printf( "Rename Result: %s (%d)\n",
889                         ldap_err2string( code ), code );
890
891                 if( text && *text ) {
892                         printf( "Additional info: %s\n", text );
893                 }
894
895                 if( matcheddn && *matcheddn ) {
896                         printf( "Matched DN: %s\n", matcheddn );
897                 }
898
899                 if( refs ) {
900                         int i;
901                         for( i=0; refs[i]; i++ ) {
902                                 printf("Referral: %s\n", refs[i] );
903                         }
904                 }
905         }
906
907         ber_memfree( text );
908         ber_memfree( matcheddn );
909         ber_memvfree( (void **) refs );
910
911         return code;
912 }