1 /* ldapmodify.c - generic program to modify or add entries using LDAP */
2 /* $OpenLDAP: pkg/ldap/clients/tools/ldapmodify.c,v 1.186.2.7 2008/02/11 23:26:38 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2006 Howard Chu.
7 * Portions Copyright 1998-2003 Kurt D. Zeilenga.
8 * Portions Copyright 1998-2001 Net Boolean Incorporated.
9 * Portions Copyright 2001-2003 IBM Corporation.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted only as authorized by the OpenLDAP
16 * A copy of this license is available in the file LICENSE in the
17 * top-level directory of the distribution or, alternatively, at
18 * <http://www.OpenLDAP.org/license.html>.
20 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
21 * All rights reserved.
23 * Redistribution and use in source and binary forms are permitted
24 * provided that this notice is preserved and that due credit is given
25 * to the University of Michigan at Ann Arbor. The name of the
26 * University may not be used to endorse or promote products derived
27 * from this software without specific prior written permission. This
28 * software is provided ``as is'' without express or implied warranty.
31 * This work was originally developed by the University of Michigan
32 * (as part of U-MICH LDAP). Additional significant contributors
43 #include <ac/stdlib.h>
45 #include <ac/string.h>
46 #include <ac/unistd.h>
47 #include <ac/socket.h>
50 #ifdef HAVE_SYS_STAT_H
54 #ifdef HAVE_SYS_FILE_H
64 #include "lutil_ldap.h"
66 #include "ldap_defaults.h"
74 static char *rejfile
= NULL
;
75 static LDAP
*ld
= NULL
;
79 /* strings found in LDIF entries */
80 static struct berval BV_VERSION
= BER_BVC("version");
81 static struct berval BV_DN
= BER_BVC("dn");
82 static struct berval BV_CONTROL
= BER_BVC("control");
83 static struct berval BV_CHANGETYPE
= BER_BVC("changetype");
84 static struct berval BV_ADDCT
= BER_BVC("add");
85 static struct berval BV_MODIFYCT
= BER_BVC("modify");
86 static struct berval BV_DELETECT
= BER_BVC("delete");
87 static struct berval BV_MODRDNCT
= BER_BVC("modrdn");
88 static struct berval BV_MODDNCT
= BER_BVC("moddn");
89 static struct berval BV_RENAMECT
= BER_BVC("rename");
90 static struct berval BV_MODOPADD
= BER_BVC("add");
91 static struct berval BV_MODOPREPLACE
= BER_BVC("replace");
92 static struct berval BV_MODOPDELETE
= BER_BVC("delete");
93 static struct berval BV_MODOPINCREMENT
= BER_BVC("increment");
94 static struct berval BV_NEWRDN
= BER_BVC("newrdn");
95 static struct berval BV_DELETEOLDRDN
= BER_BVC("deleteoldrdn");
96 static struct berval BV_NEWSUP
= BER_BVC("newsuperior");
98 #define BVICMP(a,b) ((a)->bv_len != (b)->bv_len ? \
99 (a)->bv_len - (b)->bv_len : strcasecmp((a)->bv_val, (b)->bv_val))
101 static int process_ldif_rec
LDAP_P(( char *rbuf
, int lineno
));
102 static int parse_ldif_control
LDAP_P(( struct berval
*val
, LDAPControl
***pctrls
));
103 static int domodify
LDAP_P((
106 LDAPControl
**pctrls
,
108 static int dodelete
LDAP_P((
110 LDAPControl
**pctrls
));
111 static int dorename
LDAP_P((
116 LDAPControl
**pctrls
));
117 static int process_response(
125 static int txnabort
= 0;
126 struct berval
*txn_id
= NULL
;
132 fprintf( stderr
, _("Add or modify entries from an LDAP server\n\n"));
133 fprintf( stderr
, _("usage: %s [options]\n"), prog
);
134 fprintf( stderr
, _(" The list of desired operations are read from stdin"
135 " or from the file\n"));
136 fprintf( stderr
, _(" specified by \"-f file\".\n"));
137 fprintf( stderr
, _("Add or modify options:\n"));
138 fprintf( stderr
, _(" -a add values (%s)\n"),
139 (ldapadd
? _("default") : _("default is to replace")));
140 fprintf( stderr
, _(" -E [!]ext=extparam modify extensions"
141 " (! indicate s criticality)\n"));
144 _(" [!]txn=<commit|abort> (transaction)\n"));
146 fprintf( stderr
, _(" -S file write skipped modifications to `file'\n"));
149 exit( EXIT_FAILURE
);
153 const char options
[] = "aE:rS:"
154 "cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
157 handle_private_option( int i
)
159 char *control
, *cvalue
;
163 case 'E': /* modify extensions */
164 if( protocol
== LDAP_VERSION2
) {
165 fprintf( stderr
, _("%s: -E incompatible with LDAPv%d\n"),
167 exit( EXIT_FAILURE
);
170 /* should be extended to support comma separated list of
171 * [!]key[=value] parameters, e.g. -E !foo,bar=567
176 if( optarg
[0] == '!' ) {
181 control
= ber_strdup( optarg
);
182 if ( (cvalue
= strchr( control
, '=' )) != NULL
) {
187 if( strcasecmp( control
, "txn" ) == 0 ) {
191 _("txn control previously specified\n"));
192 exit( EXIT_FAILURE
);
194 if( cvalue
!= NULL
) {
195 if( strcasecmp( cvalue
, "abort" ) == 0 ) {
197 } else if( strcasecmp( cvalue
, "commit" ) != 0 ) {
198 fprintf( stderr
, _("Invalid value for txn control, %s\n"),
200 exit( EXIT_FAILURE
);
208 fprintf( stderr
, _("Invalid modify extension name: %s\n"),
218 case 'r': /* replace (obsolete) */
221 case 'S': /* skipped modifications to file */
222 if( rejfile
!= NULL
) {
223 fprintf( stderr
, _("%s: -S previously specified\n"), prog
);
224 exit( EXIT_FAILURE
);
226 rejfile
= ber_strdup( optarg
);
237 main( int argc
, char **argv
)
239 char *rbuf
= NULL
, *rejbuf
= NULL
;
241 struct LDIFFP
*ldiffp
, ldifdummy
= {0};
242 char *matched_msg
, *error_msg
;
246 int lineno
, nextline
= 0, lmax
= 0;
249 prog
= lutil_progname( "ldapmodify", argc
, argv
);
251 /* strncmp instead of strcmp since NT binaries carry .exe extension */
252 ldapadd
= ( strncasecmp( prog
, "ldapadd", sizeof("ldapadd")-1 ) == 0 );
254 tool_init( ldapadd
? TOOL_ADD
: TOOL_MODIFY
);
256 tool_args( argc
, argv
);
258 if ( argc
!= optind
) usage();
260 if ( rejfile
!= NULL
) {
261 if (( rejfp
= fopen( rejfile
, "w" )) == NULL
) {
263 return( EXIT_FAILURE
);
269 if ( infile
!= NULL
) {
270 if (( ldiffp
= ldif_open( infile
, "r" )) == NULL
) {
272 return( EXIT_FAILURE
);
275 ldifdummy
.fp
= stdin
;
279 if ( debug
) ldif_debug
= debug
;
281 ld
= tool_conn_setup( dont
, 0 );
284 if ( pw_file
|| want_bindpw
) {
286 rc
= lutil_get_filed_password( pw_file
, &passwd
);
287 if( rc
) return EXIT_FAILURE
;
289 passwd
.bv_val
= getpassphrase( _("Enter LDAP Password: ") );
290 passwd
.bv_len
= passwd
.bv_val
? strlen( passwd
.bv_val
) : 0;
298 /* start transaction */
299 rc
= ldap_txn_start_s( ld
, NULL
, NULL
, &txn_id
);
300 if( rc
!= LDAP_SUCCESS
) {
301 tool_perror( "ldap_txn_start_s", rc
, NULL
, NULL
, NULL
, NULL
);
302 if( txn
> 1 ) return EXIT_FAILURE
;
316 c
[i
].ldctl_oid
= LDAP_CONTROL_X_TXN_SPEC
;
317 c
[i
].ldctl_value
= *txn_id
;
318 c
[i
].ldctl_iscritical
= 1;
324 tool_server_controls( ld
, c
, i
);
329 while (( rc
== 0 || contoper
) && ldif_read_record( ldiffp
, &nextline
,
333 len
= strlen( rbuf
);
334 if (( rejbuf
= (char *)ber_memalloc( len
+1 )) == NULL
) {
336 exit( EXIT_FAILURE
);
338 memcpy( rejbuf
, rbuf
, len
+1 );
341 rc
= process_ldif_rec( rbuf
, lineno
);
344 if ( rc
) retval
= rc
;
346 fprintf(rejfp
, _("# Error: %s (%d)"), ldap_err2string(rc
), rc
);
349 ldap_get_option(ld
, LDAP_OPT_MATCHED_DN
, &matched_msg
);
350 if ( matched_msg
!= NULL
) {
351 if ( *matched_msg
!= '\0' ) {
352 fprintf( rejfp
, _(", matched DN: %s"), matched_msg
);
354 ldap_memfree( matched_msg
);
358 ldap_get_option(ld
, LDAP_OPT_DIAGNOSTIC_MESSAGE
, &error_msg
);
359 if ( error_msg
!= NULL
) {
360 if ( *error_msg
!= '\0' ) {
361 fprintf( rejfp
, _(", additional info: %s"), error_msg
);
363 ldap_memfree( error_msg
);
365 fprintf( rejfp
, "\n%s\n", rejbuf
);
368 if (rejfp
) ber_memfree( rejbuf
);
373 if( retval
== 0 && txn
) {
374 rc
= ldap_set_option( ld
, LDAP_OPT_SERVER_CONTROLS
, NULL
);
375 if ( rc
!= LDAP_OPT_SUCCESS
) {
376 fprintf( stderr
, "Could not unset controls for ldap_txn_end\n");
379 /* create transaction */
380 rc
= ldap_txn_end_s( ld
, !txnabort
, txn_id
, NULL
, NULL
, NULL
);
381 if( rc
!= LDAP_SUCCESS
) {
382 tool_perror( "ldap_txn_end_s", rc
, NULL
, NULL
, NULL
, NULL
);
392 if ( rejfp
!= NULL
) {
402 process_ldif_rec( char *rbuf
, int linenum
)
404 char *line
, *dn
, *newrdn
, *newsup
;
406 int expect_modop
, expect_sep
;
408 int new_entry
, delete_entry
, got_all
;
409 LDAPMod
**pmods
, *lm
= NULL
;
411 LDAPControl
**pctrls
;
412 int i
, j
, k
, lines
, idn
, nmods
;
413 struct berval
*btype
, *vals
, **bvl
, bv
;
415 unsigned char *mops
= NULL
;
419 rc
= got_all
= delete_entry
= modop
= expect_modop
= 0;
425 dn
= newrdn
= newsup
= NULL
;
427 lines
= ldif_countlines( rbuf
);
428 btype
= ber_memcalloc( 1, (lines
+1)*2*sizeof(struct berval
)+lines
);
430 return LDAP_NO_MEMORY
;
432 vals
= btype
+lines
+1;
433 freeval
= (char *)(vals
+lines
+1);
436 while ( rc
== 0 && ( line
= ldif_getline( &rbuf
)) != NULL
) {
439 if ( *line
== '\n' || *line
== '\0' ) {
445 if ( line
[0] == '-' && !line
[1] ) {
446 BER_BVZERO( btype
+i
);
451 if ( ( rc
= ldif_parse_line2( line
, btype
+i
, vals
+i
, &freev
) ) < 0 ) {
452 fprintf( stderr
, _("%s: invalid format (line %d) entry: \"%s\"\n"),
453 prog
, linenum
+i
, dn
== NULL
? "" : dn
);
454 rc
= LDAP_PARAM_ERROR
;
460 if ( linenum
+i
== 1 && !BVICMP( btype
+i
, &BV_VERSION
)) {
462 if( vals
[i
].bv_len
== 0 || lutil_atoi( &v
, vals
[i
].bv_val
) != 0 || v
!= 1 ) {
464 _("%s: invalid version %s, line %d (ignored)\n"),
465 prog
, vals
[i
].bv_val
, linenum
);
469 } else if ( !BVICMP( btype
+i
, &BV_DN
)) {
473 /* skip all lines until we see "dn:" */
477 /* check to make sure there was a dn: line */
490 if( version
&& lines
== 1 ) {
496 /* Check for "control" tag after dn and before changetype. */
497 if (!BVICMP( btype
+i
, &BV_CONTROL
)) {
498 /* Parse and add it to the list of controls */
499 rc
= parse_ldif_control( vals
+i
, &pctrls
);
502 _("%s: Error processing %s line, line %d: %s\n"),
503 prog
, BV_CONTROL
.bv_val
, linenum
+i
, ldap_err2string(rc
) );
509 _("%s: Expecting more input after %s line, line %d\n"),
510 prog
, btype
[i
-1].bv_val
, linenum
+i
);
512 rc
= LDAP_PARAM_ERROR
;
517 /* Check for changetype */
518 if ( !BVICMP( btype
+i
, &BV_CHANGETYPE
)) {
519 #ifdef LIBERAL_CHANGETYPE_MODOP
520 /* trim trailing spaces (and log warning ...) */
522 for ( icnt
= vals
[i
].bv_len
; --icnt
> 0; ) {
523 if ( !isspace( (unsigned char) vals
[i
].bv_val
[icnt
] ) ) {
528 if ( ++icnt
!= vals
[i
].bv_len
) {
529 fprintf( stderr
, _("%s: illegal trailing space after"
530 " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
531 prog
, BV_CHANGETYPE
.bv_val
, vals
[i
].bv_val
, linenum
+i
, dn
);
532 vals
[i
].bv_val
[icnt
] = '\0';
534 #endif /* LIBERAL_CHANGETYPE_MODOP */
536 if ( BVICMP( vals
+i
, &BV_MODIFYCT
) == 0 ) {
539 } else if ( BVICMP( vals
+i
, &BV_ADDCT
) == 0 ) {
541 modop
= LDAP_MOD_ADD
;
542 } else if ( BVICMP( vals
+i
, &BV_MODRDNCT
) == 0
543 || BVICMP( vals
+i
, &BV_MODDNCT
) == 0
544 || BVICMP( vals
+i
, &BV_RENAMECT
) == 0)
549 if ( BVICMP( btype
+i
, &BV_NEWRDN
)) {
550 fprintf( stderr
, _("%s: expecting \"%s:\" but saw"
551 " \"%s:\" (line %d, entry \"%s\")\n"),
552 prog
, BV_NEWRDN
.bv_val
, btype
[i
].bv_val
, linenum
+i
, dn
);
553 rc
= LDAP_PARAM_ERROR
;
556 newrdn
= vals
[i
].bv_val
;
560 if ( BVICMP( btype
+i
, &BV_DELETEOLDRDN
)) {
561 fprintf( stderr
, _("%s: expecting \"%s:\" but saw"
562 " \"%s:\" (line %d, entry \"%s\")\n"),
563 prog
, BV_DELETEOLDRDN
.bv_val
, btype
[i
].bv_val
, linenum
+i
, dn
);
564 rc
= LDAP_PARAM_ERROR
;
567 deleteoldrdn
= ( vals
[i
].bv_val
[0] == '0' ) ? 0 : 1;
570 if ( BVICMP( btype
+i
, &BV_NEWSUP
)) {
571 fprintf( stderr
, _("%s: expecting \"%s:\" but saw"
572 " \"%s:\" (line %d, entry \"%s\")\n"),
573 prog
, BV_NEWSUP
.bv_val
, btype
[i
].bv_val
, linenum
+i
, dn
);
574 rc
= LDAP_PARAM_ERROR
;
577 newsup
= vals
[i
].bv_val
;
581 } else if ( BVICMP( vals
+i
, &BV_DELETECT
) == 0 ) {
582 got_all
= delete_entry
= 1;
585 _("%s: unknown %s \"%s\" (line %d, entry \"%s\")\n"),
586 prog
, BV_CHANGETYPE
.bv_val
, vals
[i
].bv_val
, linenum
+i
, dn
);
587 rc
= LDAP_PARAM_ERROR
;
591 } else if ( ldapadd
) { /* missing changetype => add */
593 modop
= LDAP_MOD_ADD
;
595 expect_modop
= 1; /* missing changetype => modify */
601 _("%s: extra lines at end (line %d, entry \"%s\")\n"),
602 prog
, linenum
+i
, dn
);
603 rc
= LDAP_PARAM_ERROR
;
615 /* Make sure all attributes with multiple values are contiguous */
616 for (; i
<lines
; i
++) {
617 for (j
=i
+1; j
<lines
; j
++) {
618 if ( !BVICMP( btype
+i
, btype
+j
)) {
620 /* out of order, move intervening attributes down */
624 for (k
=j
; k
>i
; k
--) {
625 btype
[k
] = btype
[k
-1];
627 freeval
[k
] = freeval
[k
-1];
638 /* Allocate space for array of mods, array of pointers to mods,
639 * and array of pointers to values, allowing for NULL terminators
640 * for the pointer arrays...
642 lm
= ber_memalloc( nmods
* sizeof(LDAPMod
) +
643 (nmods
+1) * sizeof(LDAPMod
*) +
644 (lines
+ nmods
- idn
) * sizeof(struct berval
*));
645 pmods
= (LDAPMod
**)(lm
+nmods
);
646 bvl
= (struct berval
**)(pmods
+nmods
+1);
651 for (i
=idn
; i
<lines
; i
++) {
652 if ( !BVICMP( btype
+i
, &BV_DN
)) {
653 fprintf( stderr
, _("%s: attributeDescription \"%s\":"
654 " (possible missing newline"
655 " after line %d, entry \"%s\"?)\n"),
656 prog
, btype
[i
].bv_val
, linenum
+i
- 1, dn
);
658 if ( BVICMP(btype
+i
,&bv
)) {
661 lm
[j
].mod_op
= LDAP_MOD_ADD
| LDAP_MOD_BVALUES
;
662 lm
[j
].mod_type
= bv
.bv_val
;
663 lm
[j
].mod_bvalues
= bvl
+k
;
674 mops
= ber_memalloc( lines
+1 );
678 for ( ; i
<lines
; i
++ ) {
679 if ( expect_modop
) {
680 #ifdef LIBERAL_CHANGETYPE_MODOP
681 /* trim trailing spaces (and log warning ...) */
683 for ( icnt
= vals
[i
].bv_len
; --icnt
> 0; ) {
684 if ( !isspace( (unsigned char) vals
[i
].bv_val
[icnt
] ) ) break;
687 if ( ++icnt
!= vals
[i
].bv_len
) {
688 fprintf( stderr
, _("%s: illegal trailing space after"
689 " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
690 prog
, type
, vals
[i
].bv_val
, linenum
+i
, dn
);
691 vals
[i
].bv_val
[icnt
] = '\0';
693 #endif /* LIBERAL_CHANGETYPE_MODOP */
697 if ( BVICMP( btype
+i
, &BV_MODOPADD
) == 0 ) {
698 modop
= LDAP_MOD_ADD
;
701 } else if ( BVICMP( btype
+i
, &BV_MODOPREPLACE
) == 0 ) {
702 /* defer handling these since they might have no values.
703 * Use the BVALUES flag to signal that these were
704 * deferred. If values are provided later, this
705 * flag will be switched off.
707 modop
= LDAP_MOD_REPLACE
;
708 mops
[i
] = modop
| LDAP_MOD_BVALUES
;
710 } else if ( BVICMP( btype
+i
, &BV_MODOPDELETE
) == 0 ) {
711 modop
= LDAP_MOD_DELETE
;
712 mops
[i
] = modop
| LDAP_MOD_BVALUES
;
714 } else if ( BVICMP( btype
+i
, &BV_MODOPINCREMENT
) == 0 ) {
715 modop
= LDAP_MOD_INCREMENT
;
718 } else { /* no modify op: invalid LDIF */
719 fprintf( stderr
, _("%s: modify operation type is missing at"
720 " line %d, entry \"%s\"\n"),
721 prog
, linenum
+i
, dn
);
722 rc
= LDAP_PARAM_ERROR
;
726 } else if ( expect_sep
&& BER_BVISEMPTY( btype
+i
)) {
732 if ( BVICMP( btype
+i
, &bv
)) {
733 fprintf( stderr
, _("%s: wrong attributeType at"
734 " line %d, entry \"%s\"\n"),
735 prog
, linenum
+i
, dn
);
736 rc
= LDAP_PARAM_ERROR
;
740 /* If prev op was deferred and matches this type,
743 if ( (mops
[i
-1]&LDAP_MOD_BVALUES
) && !BVICMP(btype
+i
,
751 #if 0 /* we should faithfully encode the LDIF, not combine */
752 /* Make sure all modops with multiple values are contiguous */
753 for (i
=idn
; i
<lines
; i
++) {
754 if ( mops
[i
] == M_SEP
)
756 for (j
=i
+1; j
<lines
; j
++) {
757 if ( mops
[j
] == M_SEP
|| mops
[i
] != mops
[j
] )
759 if ( !BVICMP( btype
+i
, btype
+j
)) {
761 /* out of order, move intervening attributes down */
770 for (k
=j
; k
>i
; k
--) {
771 btype
[k
] = btype
[k
-1];
773 freeval
[k
] = freeval
[k
-1];
788 /* Allocate space for array of mods, array of pointers to mods,
789 * and array of pointers to values, allowing for NULL terminators
790 * for the pointer arrays...
792 lm
= ber_memalloc( nmods
* sizeof(LDAPMod
) +
793 (nmods
+1) * sizeof(LDAPMod
*) +
794 (lines
+ nmods
- idn
) * sizeof(struct berval
*));
795 pmods
= (LDAPMod
**)(lm
+nmods
);
796 bvl
= (struct berval
**)(pmods
+nmods
+1);
802 for (i
=idn
; i
<lines
; i
++) {
803 if ( mops
[i
] == M_SEP
)
805 if ( mops
[i
] != mops
[i
-1] || BVICMP(btype
+i
,&bv
)) {
808 lm
[j
].mod_op
= mops
[i
] | LDAP_MOD_BVALUES
;
809 lm
[j
].mod_type
= bv
.bv_val
;
810 if ( mops
[i
] & LDAP_MOD_BVALUES
) {
811 lm
[j
].mod_bvalues
= NULL
;
813 lm
[j
].mod_bvalues
= bvl
+k
;
824 /* If default controls are set (as with -M option) and controls are
825 specified in the LDIF file, we must add the default controls to
826 the list of controls sent with the ldap operation.
830 LDAPControl
**defctrls
= NULL
; /* Default server controls */
831 LDAPControl
**newctrls
= NULL
;
832 ldap_get_option(ld
, LDAP_OPT_SERVER_CONTROLS
, &defctrls
);
834 int npc
=0; /* Num of LDIF controls */
835 int ndefc
=0; /* Num of default controls */
836 while (pctrls
[npc
]) npc
++; /* Count LDIF controls */
837 while (defctrls
[ndefc
]) ndefc
++; /* Count default controls */
838 newctrls
= ber_memrealloc(pctrls
,
839 (npc
+ndefc
+1)*sizeof(LDAPControl
*));
841 if (newctrls
== NULL
) {
846 for (i
=npc
; i
<npc
+ndefc
; i
++) {
847 pctrls
[i
] = ldap_control_dup(defctrls
[i
-npc
]);
848 if (pctrls
[i
] == NULL
) {
853 pctrls
[npc
+ndefc
] = NULL
;
855 ldap_controls_free(defctrls
); /* Must be freed by library */
861 if ( delete_entry
) {
862 rc
= dodelete( dn
, pctrls
);
863 } else if ( newrdn
!= NULL
) {
864 rc
= dorename( dn
, newrdn
, newsup
, deleteoldrdn
, pctrls
);
866 rc
= domodify( dn
, pmods
, pctrls
, new_entry
);
869 if ( rc
== LDAP_SUCCESS
) {
875 if (pctrls
!= NULL
) {
876 ldap_controls_free( pctrls
);
881 if ( mops
!= NULL
) {
884 for (i
=lines
-1; i
>=0; i
--)
885 if ( freeval
[i
] ) ber_memfree( vals
[i
].bv_val
);
886 ber_memfree( btype
);
891 /* Parse an LDIF control line of the form
892 control: oid [true/false] [: value] or
893 control: oid [true/false] [:: base64-value] or
894 control: oid [true/false] [:< url]
895 The control is added to the list of controls in *ppctrls.
900 LDAPControl
***ppctrls
)
903 int criticality
= 0; /* Default is false if not present */
906 LDAPControl
*newctrl
= NULL
;
907 LDAPControl
**pctrls
= NULL
;
908 struct berval type
, bv
;
911 if (ppctrls
) pctrls
= *ppctrls
;
912 /* OID should come first. Validate and extract it. */
914 if (*s
== 0) return ( LDAP_PARAM_ERROR
);
916 while (isdigit((unsigned char)*s
) || *s
== '.') {
917 s
++; /* OID should be digits or . */
920 return ( LDAP_PARAM_ERROR
); /* OID was not present */
922 if (*s
) { /* End of OID should be space or NULL */
923 if (!isspace((unsigned char)*s
)) {
924 return ( LDAP_PARAM_ERROR
); /* else OID contained invalid chars */
926 *s
++ = 0; /* Replace space with null to terminate */
929 oid
= ber_strdup(oidStart
);
930 if (oid
== NULL
) return ( LDAP_NO_MEMORY
);
932 /* Optional Criticality field is next. */
933 while (*s
&& isspace((unsigned char)*s
)) {
934 s
++; /* Skip white space before criticality */
936 if (strncasecmp(s
, "true", 4) == 0) {
940 else if (strncasecmp(s
, "false", 5) == 0) {
945 /* Optional value field is next */
946 while (*s
&& isspace((unsigned char)*s
)) {
947 s
++; /* Skip white space before value */
950 if (*s
!= ':') { /* If value is present, must start with : */
951 rc
= LDAP_PARAM_ERROR
;
955 /* Back up so value is in the form
959 Then we can use ldif_parse_line2 to extract and decode the value
964 rc
= ldif_parse_line2(s
, &type
, &bv
, &freeval
);
966 rc
= LDAP_PARAM_ERROR
;
971 /* Create a new LDAPControl structure. */
972 newctrl
= (LDAPControl
*)ber_memalloc(sizeof(LDAPControl
));
973 if ( newctrl
== NULL
) {
977 newctrl
->ldctl_oid
= oid
;
979 newctrl
->ldctl_iscritical
= criticality
;
981 newctrl
->ldctl_value
= bv
;
983 ber_dupbv( &newctrl
->ldctl_value
, &bv
);
985 /* Add the new control to the passed-in list of controls. */
988 while ( pctrls
[i
] ) { /* Count the # of controls passed in */
992 /* Allocate 1 more slot for the new control and 1 for the NULL. */
993 pctrls
= (LDAPControl
**) ber_memrealloc(pctrls
,
994 (i
+2)*(sizeof(LDAPControl
*)));
995 if (pctrls
== NULL
) {
1006 if (newctrl
->ldctl_oid
) ber_memfree(newctrl
->ldctl_oid
);
1007 if (newctrl
->ldctl_value
.bv_val
) {
1008 ber_memfree(newctrl
->ldctl_value
.bv_val
);
1010 ber_memfree(newctrl
);
1012 if (oid
) ber_memfree(oid
);
1022 LDAPControl
**pctrls
,
1025 int rc
, i
, j
, k
, notascii
, op
;
1029 fprintf( stderr
, _("%s: no DN specified\n"), prog
);
1030 return( LDAP_PARAM_ERROR
);
1033 if ( pmods
== NULL
) {
1034 /* implement "touch" (empty sequence)
1035 * modify operation (note that there
1036 * is no symmetry with the UNIX command,
1037 * since \"touch\" on a non-existent entry
1039 printf( "warning: no attributes to %sadd (entry=\"%s\")\n",
1040 newentry
? "" : "change or ", dn
);
1043 for ( i
= 0; pmods
[ i
] != NULL
; ++i
) {
1044 op
= pmods
[ i
]->mod_op
& ~LDAP_MOD_BVALUES
;
1045 if( op
== LDAP_MOD_ADD
&& ( pmods
[i
]->mod_bvalues
== NULL
)) {
1047 _("%s: attribute \"%s\" has no values (entry=\"%s\")\n"),
1048 prog
, pmods
[i
]->mod_type
, dn
);
1049 return LDAP_PARAM_ERROR
;
1054 for ( i
= 0; pmods
[ i
] != NULL
; ++i
) {
1055 op
= pmods
[ i
]->mod_op
& ~LDAP_MOD_BVALUES
;
1057 op
== LDAP_MOD_REPLACE
? _("replace") :
1058 op
== LDAP_MOD_ADD
? _("add") :
1059 op
== LDAP_MOD_INCREMENT
? _("increment") :
1060 op
== LDAP_MOD_DELETE
? _("delete") :
1062 pmods
[ i
]->mod_type
);
1064 if ( pmods
[ i
]->mod_bvalues
!= NULL
) {
1065 for ( j
= 0; pmods
[ i
]->mod_bvalues
[ j
] != NULL
; ++j
) {
1066 bvp
= pmods
[ i
]->mod_bvalues
[ j
];
1068 for ( k
= 0; (unsigned long) k
< bvp
->bv_len
; ++k
) {
1069 if ( !isascii( bvp
->bv_val
[ k
] )) {
1075 printf( _("\tNOT ASCII (%ld bytes)\n"), bvp
->bv_len
);
1077 printf( "\t%s\n", bvp
->bv_val
);
1086 printf( "%sadding new entry \"%s\"\n", dont
? "!" : "", dn
);
1088 printf( "%smodifying entry \"%s\"\n", dont
? "!" : "", dn
);
1094 rc
= ldap_add_ext( ld
, dn
, pmods
, pctrls
, NULL
, &msgid
);
1096 rc
= ldap_modify_ext( ld
, dn
, pmods
, pctrls
, NULL
, &msgid
);
1099 if ( rc
!= LDAP_SUCCESS
) {
1100 /* print error message about failed update including DN */
1101 fprintf( stderr
, _("%s: update failed: %s\n"), prog
, dn
);
1102 tool_perror( newentry
? "ldap_add" : "ldap_modify",
1103 rc
, NULL
, NULL
, NULL
, NULL
);
1106 rc
= process_response( ld
, msgid
,
1107 newentry
? LDAP_RES_ADD
: LDAP_RES_MODIFY
, dn
);
1109 if ( verbose
&& rc
== LDAP_SUCCESS
) {
1110 printf( _("modify complete\n") );
1126 LDAPControl
**pctrls
)
1131 printf( _("%sdeleting entry \"%s\"\n"), dont
? "!" : "", dn
);
1133 rc
= ldap_delete_ext( ld
, dn
, pctrls
, NULL
, &msgid
);
1134 if ( rc
!= LDAP_SUCCESS
) {
1135 fprintf( stderr
, _("%s: delete failed: %s\n"), prog
, dn
);
1136 tool_perror( "ldap_delete", rc
, NULL
, NULL
, NULL
, NULL
);
1139 rc
= process_response( ld
, msgid
, LDAP_RES_DELETE
, dn
);
1141 if ( verbose
&& rc
== LDAP_SUCCESS
) {
1142 printf( _("delete complete\n") );
1160 LDAPControl
**pctrls
)
1165 printf( _("%smodifying rdn of entry \"%s\"\n"), dont
? "!" : "", dn
);
1167 printf( _("\tnew RDN: \"%s\" (%skeep existing values)\n"),
1168 newrdn
, deleteoldrdn
? _("do not ") : "" );
1171 rc
= ldap_rename( ld
, dn
, newrdn
, newsup
, deleteoldrdn
,
1172 pctrls
, NULL
, &msgid
);
1173 if ( rc
!= LDAP_SUCCESS
) {
1174 fprintf( stderr
, _("%s: rename failed: %s\n"), prog
, dn
);
1175 tool_perror( "ldap_rename", rc
, NULL
, NULL
, NULL
, NULL
);
1178 rc
= process_response( ld
, msgid
, LDAP_RES_RENAME
, dn
);
1180 if ( verbose
&& rc
== LDAP_SUCCESS
) {
1181 printf( _("rename complete\n") );
1193 res2str( int res
) {
1197 case LDAP_RES_DELETE
:
1198 return "ldap_delete";
1199 case LDAP_RES_MODIFY
:
1200 return "ldap_modify";
1201 case LDAP_RES_MODRDN
:
1202 return "ldap_rename";
1207 return "ldap_unknown";
1210 static int process_response(
1217 int rc
= LDAP_OTHER
, msgtype
;
1218 struct timeval tv
= { 0, 0 };
1220 char *text
= NULL
, *matched
= NULL
, **refs
= NULL
;
1221 LDAPControl
**ctrls
= NULL
;
1225 tv
.tv_usec
= 100000;
1227 rc
= ldap_result( ld
, msgid
, LDAP_MSG_ALL
, &tv
, &res
);
1228 if ( tool_check_abandon( ld
, msgid
) ) {
1229 return LDAP_CANCELLED
;
1233 ldap_get_option( ld
, LDAP_OPT_RESULT_CODE
, &rc
);
1234 tool_perror( "ldap_result", rc
, NULL
, NULL
, NULL
, NULL
);
1243 msgtype
= ldap_msgtype( res
);
1245 rc
= ldap_parse_result( ld
, res
, &err
, &matched
, &text
, &refs
, &ctrls
, 1 );
1246 if ( rc
== LDAP_SUCCESS
) rc
= err
;
1249 if ( rc
== LDAP_X_TXN_SPECIFY_OKAY
) {
1253 if ( rc
!= LDAP_SUCCESS
) {
1254 tool_perror( res2str( op
), rc
, NULL
, matched
, text
, refs
);
1255 } else if ( msgtype
!= op
) {
1256 fprintf( stderr
, "%s: msgtype: expected %d got %d\n",
1257 res2str( op
), op
, msgtype
);
1261 if ( text
) ldap_memfree( text
);
1262 if ( matched
) ldap_memfree( matched
);
1263 if ( text
) ber_memvfree( (void **)refs
);
1266 tool_print_ctrls( ld
, ctrls
);
1267 ldap_controls_free( ctrls
);