]> git.sur5r.net Git - openldap/blob - clients/tools/ldapmodrdn.c
1927cbd850162cc99f355efbd570c1579f4d1126
[openldap] / clients / tools / ldapmodrdn.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 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
33 static char     *binddn = NULL;
34 static struct berval passwd = { 0, NULL};
35 static char     *ldaphost = NULL;
36 static int      ldapport = 0;
37 #ifdef HAVE_CYRUS_SASL
38 static char     *sasl_authc_id = NULL;
39 static char     *sasl_authz_id = NULL;
40 static char     *sasl_mech = NULL;
41 static int      sasl_integrity = 0;
42 static int      sasl_privacy = 0;
43 #endif
44 static int      use_tls = 0;
45 static int      not, verbose, contoper;
46 static LDAP     *ld;
47
48 static int domodrdn(
49     LDAP        *ld,
50     char        *dn,
51     char        *rdn,
52     char        *newSuperior,
53     int         remove );       /* flag: remove old RDN */
54
55 static void
56 usage( const char *s )
57 {
58         fprintf( stderr,
59 "Rename LDAP entries\n\n"
60 "usage: %s [options] [dn rdn]\n"
61 "       dn rdn: If given, rdn will replace the RDN of the entry specified by DN\n"
62 "               If not given, the list of modifications is read from stdin or\n"
63 "               from the file specified by \"-f file\" (see man page).\n"
64 "options:\n"
65 "       -c\t\tcontinuous operation mode (do not stop on errors)\n"
66 "       -C\t\tchase referrals\n"
67 "       -d level\tset LDAP debugging level to `level'\n"
68 "       -D binddn\tbind DN\n"
69 "       -E\t\trequest SASL privacy (-EE to make it critical)\n"
70 "       -f file\t\tdo renames listed in `file'\n"
71 "       -h host\t\tLDAP server\n"
72 "       -I\t\trequest SASL integrity checking (-II to make it\n"
73 "               \tcritical)\n"
74 "       -k\t\tuse Kerberos authentication\n"
75 "       -K\t\tlike -k, but do only step 1 of the Kerberos bind\n"
76 "       -M\t\tenable Manage DSA IT control (-MM to make it critical)\n"
77 "       -n\t\tshow what would be done but don't actually do it\n"
78 "       -p port\t\tport on LDAP server\n"
79 "       -P version\tprocotol version (default: 3)\n"
80 "       -r\t\tremove old RDN\n"
81 "       -s newsuperior\tnew superior entry\n"
82 "       -U user\t\tSASL authentication identity (username)\n"
83 "       -v\t\trun in verbose mode (diagnostics to standard output)\n"
84 "       -w passwd\tbind passwd (for simple authentication)\n"
85 "       -W\t\tprompt for bind passwd\n"
86 "       -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
87 "       -Y mech\t\tSASL mechanism\n"
88 "       -Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
89 ,               s );
90
91         exit( EXIT_FAILURE );
92 }
93
94 int
95 main(int argc, char **argv)
96 {
97     char                *myname,*infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
98     FILE                *fp;
99         int             rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit;
100         int             referrals;
101     char        *newSuperior=NULL;
102
103     infile = NULL;
104     not = contoper = verbose = remove = want_bindpw =
105                 debug = manageDSAit = referrals = 0;
106     authmethod = LDAP_AUTH_SIMPLE;
107         version = -1;
108
109     myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname;
110
111     while (( i = getopt( argc, argv, "cCD:d:Ef:h:IKkMnP:p:rs:U:vWw:X:Y:Z" )) != EOF ) {
112         switch( i ) {
113         case 'k':       /* kerberos bind */
114 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
115                 authmethod = LDAP_AUTH_KRBV4;
116 #else
117                 fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
118                 return( EXIT_FAILURE );
119 #endif
120                 break;
121         case 'K':       /* kerberos bind, part one only */
122 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
123                 authmethod = LDAP_AUTH_KRBV41;
124 #else
125                 fprintf( stderr, "%s was not compiled with Kerberos support\n", argv[0] );
126                 return( EXIT_FAILURE );
127 #endif
128                 break;
129         case 'c':       /* continuous operation mode */
130             ++contoper;
131             break;
132         case 'C':
133                 referrals++;
134                 break;
135         case 'h':       /* ldap host */
136             ldaphost = strdup( optarg );
137             break;
138         case 'D':       /* bind DN */
139             binddn = strdup( optarg );
140             break;
141         case 's':       /* newSuperior */
142             newSuperior = strdup( optarg );
143             version = LDAP_VERSION3;    /* This option => force V3 */
144             break;
145         case 'w':       /* password */
146             passwd.bv_val = strdup( optarg );
147                 {
148                         char* p;
149
150                         for( p = optarg; *p == '\0'; p++ ) {
151                                 *p = '*';
152                         }
153                 }
154                 passwd.bv_len = strlen( passwd.bv_val );
155             break;
156         case 'd':
157             debug |= atoi( optarg );
158             break;
159         case 'f':       /* read from file */
160             infile = strdup( optarg );
161             break;
162         case 'p':
163             ldapport = atoi( optarg );
164             break;
165         case 'n':       /* print adds, don't actually do them */
166             ++not;
167             break;
168         case 'v':       /* verbose mode */
169             verbose++;
170             break;
171         case 'r':       /* remove old RDN */
172             remove++;
173             break;
174         case 'M':
175                 /* enable Manage DSA IT */
176                 manageDSAit++;
177                 break;
178         case 'W':
179                 want_bindpw++;
180                 break;
181         case 'P':
182                 switch( atoi(optarg) )
183                 {
184                 case 2:
185                         version = LDAP_VERSION2;
186                         break;
187                 case 3:
188                         version = LDAP_VERSION3;
189                         break;
190                 default:
191                         fprintf( stderr, "protocol version should be 2 or 3\n" );
192                         usage( argv[0] );
193                         return( EXIT_FAILURE );
194                 }
195                 break;
196         case 'I':
197 #ifdef HAVE_CYRUS_SASL
198                 sasl_integrity++;
199                 authmethod = LDAP_AUTH_SASL;
200 #else
201                 fprintf( stderr, "%s was not compiled with SASL support\n",
202                         argv[0] );
203                 return( EXIT_FAILURE );
204 #endif
205                 break;
206         case 'E':
207 #ifdef HAVE_CYRUS_SASL
208                 sasl_privacy++;
209                 authmethod = LDAP_AUTH_SASL;
210 #else
211                 fprintf( stderr, "%s was not compiled with SASL support\n",
212                         argv[0] );
213                 return( EXIT_FAILURE );
214 #endif
215                 break;
216         case 'Y':
217 #ifdef HAVE_CYRUS_SASL
218                 if ( strcasecmp( optarg, "any" ) && strcmp( optarg, "*" ) ) {
219                         sasl_mech = strdup( optarg );
220                 }
221                 authmethod = LDAP_AUTH_SASL;
222 #else
223                 fprintf( stderr, "%s was not compiled with SASL support\n",
224                         argv[0] );
225                 return( EXIT_FAILURE );
226 #endif
227                 break;
228         case 'U':
229 #ifdef HAVE_CYRUS_SASL
230                 sasl_authc_id = strdup( optarg );
231                 authmethod = LDAP_AUTH_SASL;
232 #else
233                 fprintf( stderr, "%s was not compiled with SASL support\n",
234                         argv[0] );
235                 return( EXIT_FAILURE );
236 #endif
237                 break;
238         case 'X':
239 #ifdef HAVE_CYRUS_SASL
240                 sasl_authz_id = strdup( optarg );
241                 authmethod = LDAP_AUTH_SASL;
242 #else
243                 fprintf( stderr, "%s was not compiled with SASL support\n",
244                         argv[0] );
245                 return( EXIT_FAILURE );
246 #endif
247                 break;
248         case 'Z':
249 #ifdef HAVE_TLS
250                 use_tls++;
251 #else
252                 fprintf( stderr, "%s was not compiled with TLS support\n",
253                         argv[0] );
254                 return( EXIT_FAILURE );
255 #endif
256                 break;
257         default:
258             usage( argv[0] );
259             return( EXIT_FAILURE );
260         }
261     }
262
263         if ( ( authmethod == LDAP_AUTH_KRBV4 ) || ( authmethod ==
264                         LDAP_AUTH_KRBV41 ) ) {
265                 if( version > LDAP_VERSION2 ) {
266                         fprintf( stderr, "Kerberos requires LDAPv2\n" );
267                         return( EXIT_FAILURE );
268                 }
269                 version = LDAP_VERSION2;
270         }
271         else if ( authmethod == LDAP_AUTH_SASL ) {
272                 if( version != -1 && version != LDAP_VERSION3 ) {
273                         fprintf( stderr, "SASL requires LDAPv3\n" );
274                         return( EXIT_FAILURE );
275                 }
276                 version = LDAP_VERSION3;
277         }
278
279         if( manageDSAit ) {
280                 if( version != -1 && version != LDAP_VERSION3 ) {
281                         fprintf(stderr, "manage DSA control requires LDAPv3\n");
282                         return EXIT_FAILURE;
283                 }
284                 version = LDAP_VERSION3;
285         }
286
287         if( use_tls ) {
288                 if( version != -1 && version != LDAP_VERSION3 ) {
289                         fprintf(stderr, "Start TLS requires LDAPv3\n");
290                         return EXIT_FAILURE;
291                 }
292                 version = LDAP_VERSION3;
293         }
294
295     if (newSuperior != NULL) {
296                 if (version == LDAP_VERSION2) {
297                         fprintf( stderr,
298                                 "%s: version conflict!, -s newSuperior requires LDAPv3\n",
299                                 myname);
300                         usage( argv[0] );
301                         return( EXIT_FAILURE );
302                 }
303                 version = LDAP_VERSION3;
304     }
305     
306     havedn = 0;
307     if (argc - optind == 2) {
308         if (( rdn = strdup( argv[argc - 1] )) == NULL ) {
309             perror( "strdup" );
310             return( EXIT_FAILURE );
311         }
312         if (( entrydn = strdup( argv[argc - 2] )) == NULL ) {
313             perror( "strdup" );
314             return( EXIT_FAILURE );
315         }
316         ++havedn;
317     } else if ( argc - optind != 0 ) {
318         fprintf( stderr, "%s: invalid number of arguments, only two allowed\n", myname);
319         usage( argv[0] );
320         return( EXIT_FAILURE );
321     }
322
323     if ( infile != NULL ) {
324         if (( fp = fopen( infile, "r" )) == NULL ) {
325             perror( infile );
326             return( EXIT_FAILURE );
327         }
328     } else {
329         fp = stdin;
330     }
331
332         if ( debug ) {
333                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
334                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
335                 }
336                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
337                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
338                 }
339         }
340
341 #ifdef SIGPIPE
342         (void) SIGNAL( SIGPIPE, SIG_IGN );
343 #endif
344
345     if (( ld = ldap_init( ldaphost, ldapport )) == NULL ) {
346         perror( "ldap_init" );
347         return( EXIT_FAILURE );
348     }
349
350         /* referrals */
351         if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
352                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
353         {
354                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
355                         referrals ? "on" : "off" );
356                 return EXIT_FAILURE;
357         }
358
359         if (version == -1 ) {
360                 version = 3;
361         }
362
363         if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
364                 != LDAP_OPT_SUCCESS )
365         {
366                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
367                         version );
368         }
369
370         if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
371                 if ( use_tls > 1 ) {
372                         ldap_perror( ld, "ldap_start_tls" );
373                         return( EXIT_FAILURE );
374                 }
375                 fprintf( stderr, "WARNING: could not start TLS\n" );
376         }
377
378         if (want_bindpw) {
379                 passwd.bv_val = getpassphrase("Enter LDAP Password: ");
380                 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
381         }
382
383         if ( authmethod == LDAP_AUTH_SASL ) {
384 #ifdef HAVE_CYRUS_SASL
385                 int     minssf = 0, maxssf = 0;
386
387                 if ( sasl_integrity > 0 )
388                         maxssf = 1;
389                 if ( sasl_integrity > 1 )
390                         minssf = 1;
391                 if ( sasl_privacy > 0 )
392                         maxssf = 100000; /* Something big value */
393                 if ( sasl_privacy > 1 )
394                         minssf = 56;
395                 
396                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
397                         (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
398                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
399                                 "%d\n", minssf);
400                         return( EXIT_FAILURE );
401                 }
402                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
403                         (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
404                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
405                                 "%d\n", maxssf);
406                         return( EXIT_FAILURE );
407                 }
408                 
409                 rc = ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
410                                 sasl_authz_id, sasl_mech,
411                                 passwd.bv_len ? &passwd : NULL,
412                                 NULL, NULL );
413
414                 if( rc != LDAP_SUCCESS ) {
415                         ldap_perror( ld, "ldap_negotiated_sasl_bind_s" );
416                         return( EXIT_FAILURE );
417                 }
418 #else
419                 fprintf( stderr, "%s was not compiled with SASL support\n",
420                         argv[0] );
421                 return( EXIT_FAILURE );
422 #endif
423         }
424         else {
425                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
426                                 != LDAP_SUCCESS ) {
427                         ldap_perror( ld, "ldap_bind" );
428                         return( EXIT_FAILURE );
429                 }
430         }
431
432         if ( manageDSAit ) {
433                 int err;
434                 LDAPControl c;
435                 LDAPControl *ctrls[2];
436                 ctrls[0] = &c;
437                 ctrls[1] = NULL;
438
439                 c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
440                 c.ldctl_value.bv_val = NULL;
441                 c.ldctl_value.bv_len = 0;
442                 c.ldctl_iscritical = manageDSAit > 1;
443
444                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
445
446                 if( err != LDAP_OPT_SUCCESS ) {
447                         fprintf( stderr, "Could not set ManageDSAit %scontrol\n",
448                                 c.ldctl_iscritical ? "critical " : "" );
449                         if( c.ldctl_iscritical ) {
450                                 exit( EXIT_FAILURE );
451                         }
452                 }
453         }
454
455     rc = 0;
456     if (havedn)
457         rc = domodrdn( ld, entrydn, rdn, newSuperior, remove );
458     else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
459         if ( *buf != '\0' ) {   /* blank lines optional, skip */
460             buf[ strlen( buf ) - 1 ] = '\0';    /* remove nl */
461
462             if ( havedn ) {     /* have DN, get RDN */
463                 if (( rdn = strdup( buf )) == NULL ) {
464                     perror( "strdup" );
465                     return( EXIT_FAILURE );
466                 }
467                 rc = domodrdn(ld, entrydn, rdn, newSuperior, remove );
468                 havedn = 0;
469             } else if ( !havedn ) {     /* don't have DN yet */
470                 if (( entrydn = strdup( buf )) == NULL ) {
471                     perror( "strdup" );
472                     return( EXIT_FAILURE );
473                 }
474                 ++havedn;
475             }
476         }
477     }
478
479     ldap_unbind( ld );
480
481         /* UNREACHABLE */
482         return( rc );
483 }
484
485 static int domodrdn(
486     LDAP        *ld,
487     char        *dn,
488     char        *rdn,
489     char        *newSuperior,
490     int         remove ) /* flag: remove old RDN */
491 {
492     int i;
493
494     if ( verbose ) {
495                 printf( "Renaming \"%s\"\n", dn );
496                 printf( "\tnew rdn=\"%s\" (%s old rdn)\n",
497                         rdn, remove ? "delete" : "keep" );
498                 if( newSuperior != NULL ) {
499                         printf("\tnew parent=\"%s\"\n", newSuperior);
500                 }
501         }
502
503     if ( !not ) {
504         i = ldap_rename2_s( ld, dn, rdn, newSuperior, remove );
505         if ( i != LDAP_SUCCESS ) {
506             ldap_perror( ld, "ldap_rename2_s" );
507         } else if ( verbose ) {
508             printf( "modrdn complete\n" );
509         }
510     } else {
511         i = LDAP_SUCCESS;
512     }
513
514     return( i );
515 }