]>
Commit | Line | Data |
---|---|---|
57ba4cac HC |
1 | /* slapcommon.c - common routine for the slap tools */ |
2 | /* $OpenLDAP$ */ | |
3 | /* This work is part of OpenLDAP Software <http://www.openldap.org/>. | |
4 | * | |
efaf9a4a | 5 | * Copyright 1998-2021 The OpenLDAP Foundation. |
57ba4cac HC |
6 | * Portions Copyright 1998-2003 Kurt D. Zeilenga. |
7 | * Portions Copyright 2003 IBM Corporation. | |
8 | * All rights reserved. | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted only as authorized by the OpenLDAP | |
12 | * Public License. | |
13 | * | |
14 | * A copy of this license is available in file LICENSE in the | |
15 | * top-level directory of the distribution or, alternatively, at | |
16 | * <http://www.OpenLDAP.org/license.html>. | |
17 | */ | |
18 | /* ACKNOWLEDGEMENTS: | |
19 | * This work was initially developed by Kurt Zeilenga for inclusion | |
ce2c5173 | 20 | * in OpenLDAP Software. Additional significant contributors include |
57ba4cac HC |
21 | * Jong Hyuk Choi |
22 | * Hallvard B. Furuseth | |
23 | * Howard Chu | |
24 | * Pierangelo Masarati | |
25 | */ | |
26 | ||
27 | #include "portable.h" | |
28 | ||
29 | #include <stdio.h> | |
30 | ||
31 | #include <ac/stdlib.h> | |
32 | #include <ac/ctype.h> | |
33 | #include <ac/string.h> | |
34 | #include <ac/socket.h> | |
35 | #include <ac/unistd.h> | |
36 | ||
37 | #include "slapcommon.h" | |
38 | #include "lutil.h" | |
c225c4af | 39 | #include "ldif.h" |
57ba4cac HC |
40 | |
41 | tool_vars tool_globals; | |
42 | ||
43 | #ifdef CSRIMALLOC | |
44 | static char *leakfilename; | |
45 | static FILE *leakfile; | |
46 | #endif | |
47 | ||
c225c4af HC |
48 | static LDIFFP dummy; |
49 | ||
dfc10014 | 50 | #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) |
cff53d48 PM |
51 | int start_syslog; |
52 | static char **syslog_unknowns; | |
53 | #ifdef LOG_LOCAL4 | |
54 | static int syslogUser = SLAP_DEFAULT_SYSLOG_USER; | |
55 | #endif /* LOG_LOCAL4 */ | |
dfc10014 | 56 | #endif /* LDAP_DEBUG && LDAP_SYSLOG */ |
cff53d48 | 57 | |
57ba4cac HC |
58 | static void |
59 | usage( int tool, const char *progname ) | |
60 | { | |
61 | char *options = NULL; | |
62 | fprintf( stderr, | |
cff53d48 | 63 | "usage: %s [-v] [-d debuglevel] [-f configfile] [-F configdir] [-o <name>[=<value>]]", |
764aa5d9 | 64 | progname ); |
57ba4cac HC |
65 | |
66 | switch( tool ) { | |
0ea4070e | 67 | case SLAPACL: |
e9ab146a | 68 | options = "\n\t[-U authcID | -D authcDN] [-X authzID | -o authzDN=<DN>]" |
cff53d48 | 69 | "\n\t-b DN [-u] [attr[/access][:value]] [...]\n"; |
0ea4070e PM |
70 | break; |
71 | ||
57ba4cac | 72 | case SLAPADD: |
37e58a73 | 73 | options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]\n" |
59ca2d19 | 74 | "\t[-l ldiffile] [-j linenumber] [-q] [-u] [-s] [-w]\n"; |
57ba4cac HC |
75 | break; |
76 | ||
0ea4070e PM |
77 | case SLAPAUTH: |
78 | options = "\n\t[-U authcID] [-X authzID] [-R realm] [-M mech] ID [...]\n"; | |
79 | break; | |
80 | ||
57ba4cac | 81 | case SLAPCAT: |
37e58a73 | 82 | options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" |
0cf52863 | 83 | " [-l ldiffile] [-a filter] [-s subtree] [-H url]\n"; |
764aa5d9 PM |
84 | break; |
85 | ||
86 | case SLAPDN: | |
8e19437d | 87 | options = "\n\t[-N | -P] DN [...]\n"; |
57ba4cac HC |
88 | break; |
89 | ||
90 | case SLAPINDEX: | |
1ed9b5c3 | 91 | options = " [-c]\n\t[-g] [-n databasenumber | -b suffix] [attr ...] [-q] [-t]\n"; |
3ea43689 | 92 | break; |
7b65d46b | 93 | |
6bfdb034 OK |
94 | case SLAPMODIFY: |
95 | options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]\n" | |
96 | "\t[-l ldiffile] [-j linenumber] [-q] [-u] [-s] [-w]\n"; | |
97 | break; | |
98 | ||
0ea4070e | 99 | case SLAPTEST: |
fb790edc | 100 | options = " [-n databasenumber] [-u] [-Q]\n"; |
7b65d46b | 101 | break; |
57e68fa5 PM |
102 | |
103 | case SLAPSCHEMA: | |
104 | options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]" | |
0cf52863 | 105 | " [-l errorfile] [-a filter] [-s subtree] [-H url]\n"; |
57e68fa5 | 106 | break; |
57ba4cac HC |
107 | } |
108 | ||
764aa5d9 | 109 | if ( options != NULL ) { |
57ba4cac HC |
110 | fputs( options, stderr ); |
111 | } | |
112 | exit( EXIT_FAILURE ); | |
113 | } | |
114 | ||
83bb1c93 | 115 | static int |
34f4f38a | 116 | parse_slapopt( int tool, int *mode ) |
83bb1c93 | 117 | { |
cff53d48 | 118 | size_t len = 0; |
83bb1c93 PM |
119 | char *p; |
120 | ||
121 | p = strchr( optarg, '=' ); | |
cff53d48 PM |
122 | if ( p != NULL ) { |
123 | len = p - optarg; | |
124 | p++; | |
83bb1c93 PM |
125 | } |
126 | ||
83bb1c93 PM |
127 | if ( strncasecmp( optarg, "sockurl", len ) == 0 ) { |
128 | if ( !BER_BVISNULL( &listener_url ) ) { | |
129 | ber_memfree( listener_url.bv_val ); | |
130 | } | |
131 | ber_str2bv( p, 0, 1, &listener_url ); | |
132 | ||
133 | } else if ( strncasecmp( optarg, "domain", len ) == 0 ) { | |
134 | if ( !BER_BVISNULL( &peer_domain ) ) { | |
135 | ber_memfree( peer_domain.bv_val ); | |
136 | } | |
137 | ber_str2bv( p, 0, 1, &peer_domain ); | |
138 | ||
139 | } else if ( strncasecmp( optarg, "peername", len ) == 0 ) { | |
140 | if ( !BER_BVISNULL( &peer_name ) ) { | |
141 | ber_memfree( peer_name.bv_val ); | |
142 | } | |
143 | ber_str2bv( p, 0, 1, &peer_name ); | |
144 | ||
145 | } else if ( strncasecmp( optarg, "sockname", len ) == 0 ) { | |
146 | if ( !BER_BVISNULL( &sock_name ) ) { | |
147 | ber_memfree( sock_name.bv_val ); | |
148 | } | |
149 | ber_str2bv( p, 0, 1, &sock_name ); | |
150 | ||
151 | } else if ( strncasecmp( optarg, "ssf", len ) == 0 ) { | |
0fd295a3 | 152 | if ( lutil_atou( &ssf, p ) ) { |
97a310b3 | 153 | Debug( LDAP_DEBUG_ANY, "unable to parse ssf=\"%s\".\n", p ); |
0fd295a3 PM |
154 | return -1; |
155 | } | |
83bb1c93 PM |
156 | |
157 | } else if ( strncasecmp( optarg, "transport_ssf", len ) == 0 ) { | |
0fd295a3 | 158 | if ( lutil_atou( &transport_ssf, p ) ) { |
97a310b3 | 159 | Debug( LDAP_DEBUG_ANY, "unable to parse transport_ssf=\"%s\".\n", p ); |
0fd295a3 PM |
160 | return -1; |
161 | } | |
83bb1c93 PM |
162 | |
163 | } else if ( strncasecmp( optarg, "tls_ssf", len ) == 0 ) { | |
0fd295a3 | 164 | if ( lutil_atou( &tls_ssf, p ) ) { |
97a310b3 | 165 | Debug( LDAP_DEBUG_ANY, "unable to parse tls_ssf=\"%s\".\n", p ); |
0fd295a3 PM |
166 | return -1; |
167 | } | |
83bb1c93 PM |
168 | |
169 | } else if ( strncasecmp( optarg, "sasl_ssf", len ) == 0 ) { | |
0fd295a3 | 170 | if ( lutil_atou( &sasl_ssf, p ) ) { |
97a310b3 | 171 | Debug( LDAP_DEBUG_ANY, "unable to parse sasl_ssf=\"%s\".\n", p ); |
0fd295a3 PM |
172 | return -1; |
173 | } | |
83bb1c93 | 174 | |
e9ab146a PM |
175 | } else if ( strncasecmp( optarg, "authzDN", len ) == 0 ) { |
176 | ber_str2bv( p, 0, 1, &authzDN ); | |
177 | ||
dfc10014 | 178 | #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) |
cff53d48 PM |
179 | } else if ( strncasecmp( optarg, "syslog", len ) == 0 ) { |
180 | if ( parse_debug_level( p, &ldap_syslog, &syslog_unknowns ) ) { | |
181 | return -1; | |
182 | } | |
183 | start_syslog = 1; | |
184 | ||
185 | } else if ( strncasecmp( optarg, "syslog-level", len ) == 0 ) { | |
186 | if ( parse_syslog_level( p, &ldap_syslog_level ) ) { | |
187 | return -1; | |
188 | } | |
189 | start_syslog = 1; | |
190 | ||
191 | #ifdef LOG_LOCAL4 | |
192 | } else if ( strncasecmp( optarg, "syslog-user", len ) == 0 ) { | |
193 | if ( parse_syslog_user( p, &syslogUser ) ) { | |
194 | return -1; | |
195 | } | |
196 | start_syslog = 1; | |
197 | #endif /* LOG_LOCAL4 */ | |
dfc10014 | 198 | #endif /* LDAP_DEBUG && LDAP_SYSLOG */ |
cff53d48 | 199 | |
856f1b40 PM |
200 | } else if ( strncasecmp( optarg, "schema-check", len ) == 0 ) { |
201 | switch ( tool ) { | |
202 | case SLAPADD: | |
203 | if ( strcasecmp( p, "yes" ) == 0 ) { | |
204 | *mode &= ~SLAP_TOOL_NO_SCHEMA_CHECK; | |
205 | } else if ( strcasecmp( p, "no" ) == 0 ) { | |
206 | *mode |= SLAP_TOOL_NO_SCHEMA_CHECK; | |
207 | } else { | |
97a310b3 | 208 | Debug( LDAP_DEBUG_ANY, "unable to parse schema-check=\"%s\".\n", p ); |
856f1b40 PM |
209 | return -1; |
210 | } | |
211 | break; | |
212 | ||
213 | default: | |
97a310b3 | 214 | Debug( LDAP_DEBUG_ANY, "schema-check meaningless for tool.\n" ); |
856f1b40 PM |
215 | break; |
216 | } | |
217 | ||
218 | } else if ( strncasecmp( optarg, "value-check", len ) == 0 ) { | |
219 | switch ( tool ) { | |
220 | case SLAPADD: | |
221 | if ( strcasecmp( p, "yes" ) == 0 ) { | |
222 | *mode |= SLAP_TOOL_VALUE_CHECK; | |
223 | } else if ( strcasecmp( p, "no" ) == 0 ) { | |
224 | *mode &= ~SLAP_TOOL_VALUE_CHECK; | |
225 | } else { | |
97a310b3 | 226 | Debug( LDAP_DEBUG_ANY, "unable to parse value-check=\"%s\".\n", p ); |
856f1b40 PM |
227 | return -1; |
228 | } | |
229 | break; | |
230 | ||
231 | default: | |
97a310b3 | 232 | Debug( LDAP_DEBUG_ANY, "value-check meaningless for tool.\n" ); |
856f1b40 PM |
233 | break; |
234 | } | |
235 | ||
8a259e3d OK |
236 | } else if ( ( strncasecmp( optarg, "ldif_wrap", len ) == 0 ) || |
237 | ( strncasecmp( optarg, "ldif-wrap", len ) == 0 ) ) { | |
dc156d7f PM |
238 | switch ( tool ) { |
239 | case SLAPCAT: | |
240 | if ( strcasecmp( p, "no" ) == 0 ) { | |
241 | ldif_wrap = LDIF_LINE_WIDTH_MAX; | |
242 | ||
351bc07f PM |
243 | } else { |
244 | unsigned int u; | |
245 | if ( lutil_atou( &u, p ) ) { | |
97a310b3 | 246 | Debug( LDAP_DEBUG_ANY, "unable to parse ldif_wrap=\"%s\".\n", p ); |
351bc07f PM |
247 | return -1; |
248 | } | |
249 | ldif_wrap = (ber_len_t)u; | |
dc156d7f PM |
250 | } |
251 | break; | |
252 | ||
253 | default: | |
97a310b3 | 254 | Debug( LDAP_DEBUG_ANY, "ldif-wrap meaningless for tool.\n" ); |
dc156d7f PM |
255 | break; |
256 | } | |
257 | ||
83bb1c93 PM |
258 | } else { |
259 | return -1; | |
260 | } | |
261 | ||
262 | return 0; | |
263 | } | |
57ba4cac HC |
264 | |
265 | /* | |
266 | * slap_tool_init - initialize slap utility, handle program options. | |
267 | * arguments: | |
268 | * name program name | |
269 | * tool tool code | |
270 | * argc, argv command line arguments | |
271 | */ | |
272 | ||
ce3c0245 PM |
273 | static int need_shutdown; |
274 | ||
57ba4cac HC |
275 | void |
276 | slap_tool_init( | |
277 | const char* progname, | |
278 | int tool, | |
279 | int argc, char **argv ) | |
280 | { | |
281 | char *options; | |
cb686a5e HC |
282 | char *conffile = NULL; |
283 | char *confdir = NULL; | |
44725e73 | 284 | struct berval base = BER_BVNULL; |
cdd94c7a | 285 | char *filterstr = NULL; |
57ba4cac HC |
286 | char *subtree = NULL; |
287 | char *ldiffile = NULL; | |
0ef77423 | 288 | char **debug_unknowns = NULL; |
f3014a23 | 289 | int rc, i; |
57ba4cac HC |
290 | int mode = SLAP_TOOL_MODE; |
291 | int truncatemode = 0; | |
37e58a73 | 292 | int use_glue = 1; |
57e68fa5 | 293 | int writer; |
57ba4cac | 294 | |
6315ac9d PM |
295 | #ifdef LDAP_DEBUG |
296 | /* tools default to "none", so that at least LDAP_DEBUG_ANY | |
297 | * messages show up; use -d 0 to reset */ | |
6459cbb7 | 298 | slap_debug = LDAP_DEBUG_NONE; |
4939a382 | 299 | ldif_debug = slap_debug; |
6315ac9d | 300 | #endif |
cff53d48 | 301 | ldap_syslog = 0; |
b24ca759 HC |
302 | /* make sure libldap gets init'd */ |
303 | ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug ); | |
6315ac9d | 304 | |
57ba4cac | 305 | #ifdef CSRIMALLOC |
42dadd57 | 306 | leakfilename = malloc( strlen( progname ) + STRLENOF( ".leak" ) + 1 ); |
57ba4cac HC |
307 | sprintf( leakfilename, "%s.leak", progname ); |
308 | if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) { | |
309 | leakfile = stderr; | |
310 | } | |
311 | free( leakfilename ); | |
b8022be3 | 312 | leakfilename = NULL; |
57ba4cac HC |
313 | #endif |
314 | ||
dc156d7f PM |
315 | ldif_wrap = LDIF_LINE_WIDTH; |
316 | ||
0cf52863 PM |
317 | scope = LDAP_SCOPE_DEFAULT; |
318 | ||
57ba4cac HC |
319 | switch( tool ) { |
320 | case SLAPADD: | |
1ed9b5c3 | 321 | options = "b:cd:f:F:gj:l:n:o:qsS:uvw"; |
57ba4cac HC |
322 | break; |
323 | ||
57ba4cac | 324 | case SLAPCAT: |
0cf52863 | 325 | options = "a:b:cd:f:F:gH:l:n:o:s:v"; |
57ba4cac HC |
326 | mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; |
327 | break; | |
328 | ||
764aa5d9 | 329 | case SLAPDN: |
cff53d48 | 330 | options = "d:f:F:No:Pv"; |
854863f0 | 331 | mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; |
764aa5d9 PM |
332 | break; |
333 | ||
2189d8d4 PM |
334 | case SLAPMODIFY: |
335 | options = "b:cd:f:F:gj:l:n:o:qsS:uvw"; | |
336 | break; | |
337 | ||
57e68fa5 | 338 | case SLAPSCHEMA: |
0cf52863 | 339 | options = "a:b:cd:f:F:gH:l:n:o:s:v"; |
57e68fa5 PM |
340 | mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; |
341 | break; | |
342 | ||
0ea4070e | 343 | case SLAPTEST: |
66570ad5 | 344 | options = "d:f:F:n:o:Quv"; |
0ea4070e PM |
345 | mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; |
346 | break; | |
347 | ||
a54900be | 348 | case SLAPAUTH: |
cff53d48 | 349 | options = "d:f:F:M:o:R:U:vX:"; |
854863f0 | 350 | mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; |
3ea43689 PM |
351 | break; |
352 | ||
764aa5d9 | 353 | case SLAPINDEX: |
1ed9b5c3 | 354 | options = "b:cd:f:F:gn:o:qtv"; |
764aa5d9 PM |
355 | mode |= SLAP_TOOL_READMAIN; |
356 | break; | |
357 | ||
7b65d46b | 358 | case SLAPACL: |
e9ab146a | 359 | options = "b:D:d:f:F:o:uU:vX:"; |
854863f0 | 360 | mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY; |
7b65d46b PM |
361 | break; |
362 | ||
57ba4cac | 363 | default: |
cdd94c7a | 364 | fprintf( stderr, "%s: unknown tool mode (%d)\n", progname, tool ); |
57ba4cac HC |
365 | exit( EXIT_FAILURE ); |
366 | } | |
367 | ||
368 | dbnum = -1; | |
369 | while ( (i = getopt( argc, argv, options )) != EOF ) { | |
370 | switch ( i ) { | |
cdd94c7a | 371 | case 'a': |
a97eed06 | 372 | filterstr = optarg; |
cdd94c7a KZ |
373 | break; |
374 | ||
57ba4cac | 375 | case 'b': |
3ea43689 | 376 | ber_str2bv( optarg, 0, 1, &base ); |
57ba4cac HC |
377 | break; |
378 | ||
379 | case 'c': /* enable continue mode */ | |
380 | continuemode++; | |
381 | break; | |
382 | ||
2422e6aa PM |
383 | case 'd': { /* turn on debugging */ |
384 | int level = 0; | |
385 | ||
0ef77423 | 386 | if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) { |
3517bdf2 PM |
387 | usage( tool, progname ); |
388 | } | |
e725c848 | 389 | #ifdef LDAP_DEBUG |
3517bdf2 PM |
390 | if ( level == 0 ) { |
391 | /* allow to reset log level */ | |
392 | slap_debug = 0; | |
6459cbb7 PM |
393 | |
394 | } else { | |
3517bdf2 | 395 | slap_debug |= level; |
e725c848 PM |
396 | } |
397 | #else | |
3517bdf2 | 398 | if ( level != 0 ) |
e725c848 PM |
399 | fputs( "must compile with LDAP_DEBUG for debugging\n", |
400 | stderr ); | |
401 | #endif | |
2422e6aa | 402 | } break; |
57ba4cac | 403 | |
7b65d46b | 404 | case 'D': |
854863f0 | 405 | ber_str2bv( optarg, 0, 1, &authcDN ); |
7b65d46b PM |
406 | break; |
407 | ||
57ba4cac | 408 | case 'f': /* specify a conf file */ |
a97eed06 | 409 | conffile = optarg; |
57ba4cac HC |
410 | break; |
411 | ||
bc4564ca | 412 | case 'F': /* specify a conf dir */ |
a97eed06 | 413 | confdir = optarg; |
bc4564ca HC |
414 | break; |
415 | ||
37e58a73 HC |
416 | case 'g': /* disable subordinate glue */ |
417 | use_glue = 0; | |
418 | break; | |
419 | ||
0cf52863 PM |
420 | case 'H': { |
421 | LDAPURLDesc *ludp; | |
422 | int rc; | |
423 | ||
424 | rc = ldap_url_parse_ext( optarg, &ludp, | |
425 | LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_NOEMPTY_DN ); | |
426 | if ( rc != LDAP_URL_SUCCESS ) { | |
427 | usage( tool, progname ); | |
428 | } | |
429 | ||
430 | /* don't accept host, port, attrs, extensions */ | |
431 | if ( ldap_pvt_url_scheme2proto( ludp->lud_scheme ) != LDAP_PROTO_TCP ) { | |
432 | usage( tool, progname ); | |
433 | } | |
434 | ||
435 | if ( ludp->lud_host != NULL ) { | |
436 | usage( tool, progname ); | |
437 | } | |
438 | ||
439 | if ( ludp->lud_port != 0 ) { | |
440 | usage( tool, progname ); | |
441 | } | |
442 | ||
443 | if ( ludp->lud_attrs != NULL ) { | |
444 | usage( tool, progname ); | |
445 | } | |
446 | ||
447 | if ( ludp->lud_exts != NULL ) { | |
448 | usage( tool, progname ); | |
449 | } | |
450 | ||
451 | if ( ludp->lud_dn != NULL && ludp->lud_dn[0] != '\0' ) { | |
fccca0ea | 452 | ch_free( subtree ); |
0cf52863 PM |
453 | subtree = ludp->lud_dn; |
454 | ludp->lud_dn = NULL; | |
455 | } | |
456 | ||
457 | if ( ludp->lud_filter != NULL && ludp->lud_filter[0] != '\0' ) { | |
458 | filterstr = ludp->lud_filter; | |
459 | ludp->lud_filter = NULL; | |
460 | } | |
461 | ||
462 | scope = ludp->lud_scope; | |
463 | ||
464 | ldap_free_urldesc( ludp ); | |
465 | } break; | |
466 | ||
59ca2d19 | 467 | case 'j': /* jump to linenumber */ |
461db2de | 468 | if ( lutil_atoul( &jumpline, optarg ) ) { |
59ca2d19 HC |
469 | usage( tool, progname ); |
470 | } | |
471 | break; | |
472 | ||
57ba4cac | 473 | case 'l': /* LDIF file */ |
a97eed06 | 474 | ldiffile = optarg; |
57ba4cac HC |
475 | break; |
476 | ||
cc78fb52 PM |
477 | case 'M': |
478 | ber_str2bv( optarg, 0, 0, &mech ); | |
479 | break; | |
480 | ||
8e19437d PM |
481 | case 'N': |
482 | if ( dn_mode && dn_mode != SLAP_TOOL_LDAPDN_NORMAL ) { | |
483 | usage( tool, progname ); | |
484 | } | |
485 | dn_mode = SLAP_TOOL_LDAPDN_NORMAL; | |
486 | break; | |
487 | ||
57ba4cac | 488 | case 'n': /* which config file db to index */ |
f3014a23 | 489 | if ( lutil_atoi( &dbnum, optarg ) || dbnum < 0 ) { |
0fd295a3 PM |
490 | usage( tool, progname ); |
491 | } | |
57ba4cac HC |
492 | break; |
493 | ||
83bb1c93 | 494 | case 'o': |
34f4f38a | 495 | if ( parse_slapopt( tool, &mode ) ) { |
83bb1c93 PM |
496 | usage( tool, progname ); |
497 | } | |
498 | break; | |
499 | ||
8e19437d PM |
500 | case 'P': |
501 | if ( dn_mode && dn_mode != SLAP_TOOL_LDAPDN_PRETTY ) { | |
502 | usage( tool, progname ); | |
503 | } | |
504 | dn_mode = SLAP_TOOL_LDAPDN_PRETTY; | |
505 | break; | |
506 | ||
9a55fe70 PM |
507 | case 'Q': |
508 | quiet++; | |
509 | slap_debug = 0; | |
510 | break; | |
511 | ||
fe03b5a8 HC |
512 | case 'q': /* turn on quick */ |
513 | mode |= SLAP_TOOL_QUICK; | |
514 | break; | |
515 | ||
cc78fb52 PM |
516 | case 'R': |
517 | realm = optarg; | |
518 | break; | |
519 | ||
a6fd7fa9 | 520 | case 'S': |
aad65553 | 521 | if ( lutil_atou( &csnsid, optarg ) |
a6fd7fa9 PM |
522 | || csnsid > SLAP_SYNC_SID_MAX ) |
523 | { | |
524 | usage( tool, progname ); | |
525 | } | |
526 | break; | |
527 | ||
34f4f38a PM |
528 | case 's': |
529 | switch ( tool ) { | |
530 | case SLAPADD: | |
531 | case SLAPMODIFY: | |
532 | /* no schema check */ | |
c51a71e5 | 533 | mode |= SLAP_TOOL_NO_SCHEMA_CHECK; |
34f4f38a PM |
534 | break; |
535 | ||
536 | case SLAPCAT: | |
537 | case SLAPSCHEMA: | |
538 | /* dump subtree */ | |
59ee9221 | 539 | ch_free( subtree ); |
a97eed06 | 540 | subtree = optarg; |
34f4f38a PM |
541 | break; |
542 | } | |
57ba4cac HC |
543 | break; |
544 | ||
545 | case 't': /* turn on truncate */ | |
546 | truncatemode++; | |
547 | mode |= SLAP_TRUNCATE_MODE; | |
548 | break; | |
549 | ||
3ea43689 PM |
550 | case 'U': |
551 | ber_str2bv( optarg, 0, 0, &authcID ); | |
552 | break; | |
553 | ||
57ba4cac HC |
554 | case 'u': /* dry run */ |
555 | dryrun++; | |
556 | break; | |
557 | ||
558 | case 'v': /* turn on verbose */ | |
559 | verbose++; | |
560 | break; | |
561 | ||
8d0f39bb | 562 | case 'w': /* write context csn at the end */ |
495c3156 | 563 | update_ctxcsn++; |
57ba4cac HC |
564 | break; |
565 | ||
3ea43689 PM |
566 | case 'X': |
567 | ber_str2bv( optarg, 0, 0, &authzID ); | |
568 | break; | |
569 | ||
57ba4cac HC |
570 | default: |
571 | usage( tool, progname ); | |
572 | break; | |
573 | } | |
574 | } | |
575 | ||
dfc10014 | 576 | #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) |
cff53d48 PM |
577 | if ( start_syslog ) { |
578 | char *logName; | |
579 | #ifdef HAVE_EBCDIC | |
580 | logName = ch_strdup( progname ); | |
581 | __atoe( logName ); | |
582 | #else | |
583 | logName = (char *)progname; | |
584 | #endif | |
585 | ||
586 | #ifdef LOG_LOCAL4 | |
587 | openlog( logName, OPENLOG_OPTIONS, syslogUser ); | |
bbc719ca | 588 | #elif defined LOG_DEBUG |
cff53d48 PM |
589 | openlog( logName, OPENLOG_OPTIONS ); |
590 | #endif | |
591 | #ifdef HAVE_EBCDIC | |
592 | free( logName ); | |
b8022be3 | 593 | logName = NULL; |
cff53d48 PM |
594 | #endif |
595 | } | |
dfc10014 | 596 | #endif /* LDAP_DEBUG && LDAP_SYSLOG */ |
cff53d48 | 597 | |
57e68fa5 PM |
598 | switch ( tool ) { |
599 | case SLAPCAT: | |
600 | case SLAPSCHEMA: | |
601 | writer = 1; | |
602 | break; | |
603 | ||
604 | default: | |
605 | writer = 0; | |
606 | break; | |
607 | } | |
608 | ||
764aa5d9 PM |
609 | switch ( tool ) { |
610 | case SLAPADD: | |
611 | case SLAPCAT: | |
2189d8d4 | 612 | case SLAPMODIFY: |
57e68fa5 | 613 | case SLAPSCHEMA: |
764aa5d9 PM |
614 | if ( ( argc != optind ) || (dbnum >= 0 && base.bv_val != NULL ) ) { |
615 | usage( tool, progname ); | |
616 | } | |
617 | ||
764aa5d9 | 618 | break; |
57ba4cac | 619 | |
5d3f3c24 HC |
620 | case SLAPINDEX: |
621 | if ( dbnum >= 0 && base.bv_val != NULL ) { | |
622 | usage( tool, progname ); | |
623 | } | |
624 | ||
625 | break; | |
626 | ||
764aa5d9 PM |
627 | case SLAPDN: |
628 | if ( argc == optind ) { | |
57ba4cac HC |
629 | usage( tool, progname ); |
630 | } | |
764aa5d9 PM |
631 | break; |
632 | ||
a54900be | 633 | case SLAPAUTH: |
3ea43689 PM |
634 | if ( argc == optind && BER_BVISNULL( &authcID ) ) { |
635 | usage( tool, progname ); | |
636 | } | |
637 | break; | |
638 | ||
764aa5d9 PM |
639 | case SLAPTEST: |
640 | if ( argc != optind ) { | |
641 | usage( tool, progname ); | |
642 | } | |
643 | break; | |
644 | ||
7b65d46b PM |
645 | case SLAPACL: |
646 | if ( !BER_BVISNULL( &authcDN ) && !BER_BVISNULL( &authcID ) ) { | |
647 | usage( tool, progname ); | |
648 | } | |
649 | if ( BER_BVISNULL( &base ) ) { | |
650 | usage( tool, progname ); | |
651 | } | |
652 | ber_dupbv( &baseDN, &base ); | |
653 | break; | |
654 | ||
764aa5d9 PM |
655 | default: |
656 | break; | |
57ba4cac HC |
657 | } |
658 | ||
659 | if ( ldiffile == NULL ) { | |
57e68fa5 | 660 | dummy.fp = writer ? stdout : stdin; |
c225c4af | 661 | ldiffp = &dummy; |
57ba4cac | 662 | |
57e68fa5 | 663 | } else if ((ldiffp = ldif_open( ldiffile, writer ? "w" : "r" )) |
57ba4cac HC |
664 | == NULL ) |
665 | { | |
666 | perror( ldiffile ); | |
667 | exit( EXIT_FAILURE ); | |
668 | } | |
669 | ||
670 | /* | |
671 | * initialize stuff and figure out which backend we're dealing with | |
672 | */ | |
673 | ||
8573640f | 674 | rc = slap_init( mode, progname ); |
57ba4cac | 675 | if ( rc != 0 ) { |
8573640f | 676 | fprintf( stderr, "%s: slap_init failed!\n", progname ); |
57ba4cac HC |
677 | exit( EXIT_FAILURE ); |
678 | } | |
679 | ||
bc4564ca | 680 | rc = read_config( conffile, confdir ); |
57ba4cac HC |
681 | |
682 | if ( rc != 0 ) { | |
53921b2c PM |
683 | fprintf( stderr, "%s: bad configuration %s!\n", |
684 | progname, confdir ? "directory" : "file" ); | |
57ba4cac HC |
685 | exit( EXIT_FAILURE ); |
686 | } | |
687 | ||
0ef77423 HC |
688 | if ( debug_unknowns ) { |
689 | rc = parse_debug_unknowns( debug_unknowns, &slap_debug ); | |
690 | ldap_charray_free( debug_unknowns ); | |
691 | debug_unknowns = NULL; | |
692 | if ( rc ) | |
693 | exit( EXIT_FAILURE ); | |
694 | } | |
695 | ||
dfc10014 | 696 | #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG) |
cff53d48 PM |
697 | if ( syslog_unknowns ) { |
698 | rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog ); | |
699 | ldap_charray_free( syslog_unknowns ); | |
700 | syslog_unknowns = NULL; | |
701 | if ( rc ) | |
702 | exit( EXIT_FAILURE ); | |
703 | } | |
3f4e196b | 704 | #endif |
cff53d48 | 705 | |
47e79480 | 706 | at_oc_cache = 1; |
75725a7a | 707 | |
764aa5d9 PM |
708 | switch ( tool ) { |
709 | case SLAPADD: | |
710 | case SLAPCAT: | |
711 | case SLAPINDEX: | |
2189d8d4 | 712 | case SLAPMODIFY: |
57e68fa5 | 713 | case SLAPSCHEMA: |
764aa5d9 PM |
714 | if ( !nbackends ) { |
715 | fprintf( stderr, "No databases found " | |
716 | "in config file\n" ); | |
717 | exit( EXIT_FAILURE ); | |
718 | } | |
719 | break; | |
720 | ||
721 | default: | |
722 | break; | |
57ba4cac HC |
723 | } |
724 | ||
37e58a73 | 725 | if ( use_glue ) { |
1861632d | 726 | rc = glue_sub_attach( 0 ); |
4a1eabf2 | 727 | |
37e58a73 HC |
728 | if ( rc != 0 ) { |
729 | fprintf( stderr, | |
730 | "%s: subordinate configuration error\n", progname ); | |
731 | exit( EXIT_FAILURE ); | |
732 | } | |
4a1eabf2 HC |
733 | } |
734 | ||
57ba4cac HC |
735 | rc = slap_schema_check(); |
736 | ||
737 | if ( rc != 0 ) { | |
738 | fprintf( stderr, "%s: slap_schema_prep failed!\n", progname ); | |
739 | exit( EXIT_FAILURE ); | |
740 | } | |
741 | ||
764aa5d9 | 742 | switch ( tool ) { |
764aa5d9 | 743 | case SLAPTEST: |
66570ad5 HC |
744 | if ( dbnum >= 0 ) |
745 | goto get_db; | |
746 | /* FALLTHRU */ | |
747 | case SLAPDN: | |
a54900be | 748 | case SLAPAUTH: |
3ea43689 PM |
749 | be = NULL; |
750 | goto startup; | |
751 | ||
764aa5d9 PM |
752 | default: |
753 | break; | |
754 | } | |
755 | ||
cdd94c7a KZ |
756 | if( filterstr ) { |
757 | filter = str2filter( filterstr ); | |
758 | ||
759 | if( filter == NULL ) { | |
760 | fprintf( stderr, "Invalid filter '%s'\n", filterstr ); | |
761 | exit( EXIT_FAILURE ); | |
762 | } | |
763 | } | |
764 | ||
57ba4cac HC |
765 | if( subtree ) { |
766 | struct berval val; | |
3ea43689 | 767 | ber_str2bv( subtree, 0, 0, &val ); |
57ba4cac HC |
768 | rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL ); |
769 | if( rc != LDAP_SUCCESS ) { | |
cdd94c7a | 770 | fprintf( stderr, "Invalid subtree DN '%s'\n", subtree ); |
57ba4cac HC |
771 | exit( EXIT_FAILURE ); |
772 | } | |
773 | ||
cdd94c7a | 774 | if ( BER_BVISNULL( &base ) && dbnum == -1 ) { |
57ba4cac | 775 | base = val; |
cdd94c7a | 776 | } else { |
57ba4cac | 777 | free( subtree ); |
b8022be3 | 778 | subtree = NULL; |
cdd94c7a | 779 | } |
57ba4cac HC |
780 | } |
781 | ||
782 | if( base.bv_val != NULL ) { | |
783 | struct berval nbase; | |
784 | ||
785 | rc = dnNormalize( 0, NULL, NULL, &base, &nbase, NULL ); | |
786 | if( rc != LDAP_SUCCESS ) { | |
787 | fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n", | |
788 | progname, base.bv_val ); | |
789 | exit( EXIT_FAILURE ); | |
790 | } | |
791 | ||
88cbe052 | 792 | be = select_backend( &nbase, 0 ); |
57ba4cac | 793 | ber_memfree( nbase.bv_val ); |
b8022be3 | 794 | BER_BVZERO( &nbase ); |
57ba4cac | 795 | |
c84ae5db HC |
796 | if( be == NULL ) { |
797 | fprintf( stderr, "%s: slap_init no backend for \"%s\"\n", | |
798 | progname, base.bv_val ); | |
799 | exit( EXIT_FAILURE ); | |
800 | } | |
854863f0 PM |
801 | switch ( tool ) { |
802 | case SLAPACL: | |
4d3a49b3 | 803 | goto startup; |
854863f0 PM |
804 | |
805 | default: | |
806 | break; | |
4d3a49b3 PM |
807 | } |
808 | ||
21eef84a | 809 | /* If the named base is a glue primary, operate on the |
57ba4cac HC |
810 | * entire context |
811 | */ | |
da69eca7 | 812 | if ( SLAP_GLUE_INSTANCE( be ) ) { |
57ba4cac HC |
813 | nosubordinates = 1; |
814 | } | |
815 | ||
5efa1869 | 816 | ch_free( base.bv_val ); |
b8022be3 | 817 | BER_BVZERO( &base ); |
5efa1869 | 818 | |
57ba4cac | 819 | } else if ( dbnum == -1 ) { |
6c214121 HC |
820 | /* no suffix and no dbnum specified, just default to |
821 | * the first available database | |
822 | */ | |
57ba4cac HC |
823 | if ( nbackends <= 0 ) { |
824 | fprintf( stderr, "No available databases\n" ); | |
825 | exit( EXIT_FAILURE ); | |
826 | } | |
0076b40c HC |
827 | LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { |
828 | dbnum++; | |
6c214121 HC |
829 | |
830 | /* db #0 is cn=config, don't select it as a default */ | |
0076b40c | 831 | if ( dbnum < 1 ) continue; |
57ba4cac | 832 | |
0076b40c HC |
833 | if ( SLAP_MONITOR(be)) |
834 | continue; | |
835 | ||
57ba4cac | 836 | /* If just doing the first by default and it is a |
21eef84a | 837 | * glue subordinate, find the primary. |
57ba4cac | 838 | */ |
0076b40c | 839 | if ( SLAP_GLUE_SUBORDINATE(be) ) { |
57ba4cac | 840 | nosubordinates = 1; |
0076b40c | 841 | continue; |
57ba4cac | 842 | } |
0076b40c | 843 | break; |
57ba4cac HC |
844 | } |
845 | ||
0076b40c | 846 | if ( !be ) { |
57ba4cac HC |
847 | fprintf( stderr, "Available database(s) " |
848 | "do not allow %s\n", progname ); | |
849 | exit( EXIT_FAILURE ); | |
850 | } | |
851 | ||
6c214121 | 852 | if ( nosubordinates == 0 && dbnum > 1 ) { |
57ba4cac | 853 | Debug( LDAP_DEBUG_ANY, |
cdd94c7a KZ |
854 | "The first database does not allow %s;" |
855 | " using the first available one (%d)\n", | |
97a310b3 | 856 | progname, dbnum ); |
57ba4cac HC |
857 | } |
858 | ||
f3014a23 | 859 | } else if ( dbnum >= nbackends ) { |
57ba4cac HC |
860 | fprintf( stderr, |
861 | "Database number selected via -n is out of range\n" | |
6c214121 | 862 | "Must be in the range 0 to %d" |
30066c81 PM |
863 | " (the number of configured databases)\n", |
864 | nbackends - 1 ); | |
57ba4cac HC |
865 | exit( EXIT_FAILURE ); |
866 | ||
867 | } else { | |
66570ad5 | 868 | get_db: |
0076b40c HC |
869 | LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { |
870 | if ( dbnum == 0 ) break; | |
871 | dbnum--; | |
872 | } | |
57ba4cac HC |
873 | } |
874 | ||
0cf52863 PM |
875 | if ( scope != LDAP_SCOPE_DEFAULT && BER_BVISNULL( &sub_ndn ) ) { |
876 | if ( be && be->be_nsuffix ) { | |
877 | ber_dupbv( &sub_ndn, be->be_nsuffix ); | |
878 | ||
879 | } else { | |
880 | fprintf( stderr, | |
881 | "<scope> needs a DN or a valid database\n" ); | |
882 | exit( EXIT_FAILURE ); | |
883 | } | |
884 | } | |
885 | ||
3ea43689 | 886 | startup:; |
f3014a23 PM |
887 | if ( be ) { |
888 | BackendDB *bdtmp; | |
889 | ||
890 | dbnum = 0; | |
891 | LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) { | |
892 | if ( bdtmp == be ) break; | |
893 | dbnum++; | |
894 | } | |
895 | } | |
3ea43689 | 896 | |
57ba4cac HC |
897 | #ifdef CSRIMALLOC |
898 | mal_leaktrace(1); | |
899 | #endif | |
900 | ||
53a4d530 | 901 | |
884ebf91 | 902 | /* slapdn doesn't specify a backend to startup */ |
a9844efa | 903 | if ( !dryrun && tool != SLAPDN ) { |
ce3c0245 PM |
904 | need_shutdown = 1; |
905 | ||
a9844efa HC |
906 | if ( slap_startup( be ) ) { |
907 | switch ( tool ) { | |
908 | case SLAPTEST: | |
909 | fprintf( stderr, "slap_startup failed " | |
910 | "(test would succeed using " | |
911 | "the -u switch)\n" ); | |
912 | break; | |
913 | ||
914 | default: | |
915 | fprintf( stderr, "slap_startup failed\n" ); | |
916 | break; | |
917 | } | |
d5238b91 | 918 | |
a9844efa | 919 | exit( EXIT_FAILURE ); |
d5238b91 | 920 | } |
57ba4cac HC |
921 | } |
922 | } | |
923 | ||
4e22081e | 924 | int slap_tool_destroy( void ) |
57ba4cac | 925 | { |
4e22081e | 926 | int rc = 0; |
4cba10c1 | 927 | if ( !dryrun ) { |
ce3c0245 | 928 | if ( need_shutdown ) { |
4e22081e HC |
929 | if ( slap_shutdown( be )) |
930 | rc = EXIT_FAILURE; | |
ce3c0245 | 931 | } |
4e22081e HC |
932 | if ( slap_destroy()) |
933 | rc = EXIT_FAILURE; | |
47415023 | 934 | } |
57ba4cac HC |
935 | #ifdef SLAPD_MODULES |
936 | if ( slapMode == SLAP_SERVER_MODE ) { | |
937 | /* always false. just pulls in necessary symbol references. */ | |
938 | lutil_uuidstr(NULL, 0); | |
939 | } | |
940 | module_kill(); | |
941 | #endif | |
942 | schema_destroy(); | |
943 | #ifdef HAVE_TLS | |
944 | ldap_pvt_tls_destroy(); | |
945 | #endif | |
946 | config_destroy(); | |
947 | ||
948 | #ifdef CSRIMALLOC | |
949 | mal_dumpleaktrace( leakfile ); | |
950 | #endif | |
854863f0 PM |
951 | |
952 | if ( !BER_BVISNULL( &authcDN ) ) { | |
953 | ch_free( authcDN.bv_val ); | |
b8022be3 | 954 | BER_BVZERO( &authcDN ); |
854863f0 | 955 | } |
8931d68e PM |
956 | |
957 | if ( ldiffp && ldiffp != &dummy ) { | |
958 | ldif_close( ldiffp ); | |
959 | } | |
4e22081e | 960 | return rc; |
57ba4cac | 961 | } |
0cf52863 | 962 | |
15f1e7bd PM |
963 | int |
964 | slap_tool_update_ctxcsn( | |
965 | const char *progname, | |
966 | unsigned long sid, | |
967 | struct berval *bvtext ) | |
968 | { | |
969 | struct berval ctxdn; | |
970 | ID ctxcsn_id; | |
971 | Entry *ctxcsn_e; | |
972 | int rc = EXIT_SUCCESS; | |
973 | ||
974 | if ( !(update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1) ) { | |
975 | return rc; | |
976 | } | |
977 | ||
978 | if ( SLAP_SYNC_SUBENTRY( be )) { | |
979 | build_new_dn( &ctxdn, &be->be_nsuffix[0], | |
980 | (struct berval *)&slap_ldapsync_cn_bv, NULL ); | |
981 | } else { | |
982 | ctxdn = be->be_nsuffix[0]; | |
983 | } | |
984 | ctxcsn_id = be->be_dn2id_get( be, &ctxdn ); | |
985 | if ( ctxcsn_id == NOID ) { | |
986 | if ( SLAP_SYNC_SUBENTRY( be )) { | |
987 | ctxcsn_e = slap_create_context_csn_entry( be, NULL ); | |
988 | for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) { | |
989 | if ( maxcsn[ sid ].bv_len ) { | |
990 | attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN, | |
991 | &maxcsn[ sid ], NULL ); | |
992 | } | |
993 | } | |
994 | ctxcsn_id = be->be_entry_put( be, ctxcsn_e, bvtext ); | |
995 | if ( ctxcsn_id == NOID ) { | |
996 | fprintf( stderr, "%s: couldn't create context entry\n", progname ); | |
997 | rc = EXIT_FAILURE; | |
998 | } | |
c5cc2f24 | 999 | entry_free( ctxcsn_e ); |
15f1e7bd PM |
1000 | } else { |
1001 | fprintf( stderr, "%s: context entry is missing\n", progname ); | |
1002 | rc = EXIT_FAILURE; | |
1003 | } | |
1004 | } else { | |
1005 | ctxcsn_e = be->be_entry_get( be, ctxcsn_id ); | |
1006 | if ( ctxcsn_e != NULL ) { | |
c5cc2f24 | 1007 | Operation op = { 0 }; |
15f1e7bd | 1008 | Entry *e = entry_dup( ctxcsn_e ); |
15f1e7bd | 1009 | Attribute *attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN ); |
c5cc2f24 HC |
1010 | |
1011 | int change; | |
1012 | op.o_bd = be; | |
1013 | be_entry_release_r( &op, ctxcsn_e ); | |
1014 | ||
15f1e7bd PM |
1015 | if ( attr ) { |
1016 | int i; | |
1017 | ||
1018 | change = 0; | |
1019 | ||
1020 | for ( i = 0; !BER_BVISNULL( &attr->a_nvals[ i ] ); i++ ) { | |
1021 | int rc_sid; | |
1022 | int match; | |
1023 | const char *text = NULL; | |
1024 | ||
1025 | rc_sid = slap_parse_csn_sid( &attr->a_nvals[ i ] ); | |
1026 | if ( rc_sid < 0 ) { | |
1027 | Debug( LDAP_DEBUG_ANY, | |
1028 | "%s: unable to extract SID " | |
1029 | "from #%d contextCSN=%s\n", | |
1030 | progname, i, | |
1031 | attr->a_nvals[ i ].bv_val ); | |
1032 | continue; | |
1033 | } | |
1034 | ||
1035 | assert( rc_sid <= SLAP_SYNC_SID_MAX ); | |
1036 | ||
1037 | sid = (unsigned)rc_sid; | |
1038 | ||
1039 | if ( maxcsn[ sid ].bv_len == 0 ) { | |
1040 | match = -1; | |
1041 | ||
1042 | } else { | |
1043 | value_match( &match, slap_schema.si_ad_entryCSN, | |
1044 | slap_schema.si_ad_entryCSN->ad_type->sat_ordering, | |
1045 | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, | |
1046 | &maxcsn[ sid ], &attr->a_nvals[i], &text ); | |
1047 | } | |
1048 | ||
1049 | if ( match > 0 ) { | |
1050 | change = 1; | |
1051 | } else { | |
1052 | AC_MEMCPY( maxcsn[ sid ].bv_val, | |
1053 | attr->a_nvals[ i ].bv_val, | |
1054 | attr->a_nvals[ i ].bv_len ); | |
1055 | maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0'; | |
1056 | maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len; | |
1057 | } | |
1058 | } | |
1059 | ||
1060 | if ( change ) { | |
1061 | if ( attr->a_nvals != attr->a_vals ) { | |
1062 | ber_bvarray_free( attr->a_nvals ); | |
1063 | } | |
1064 | attr->a_nvals = NULL; | |
1065 | ber_bvarray_free( attr->a_vals ); | |
1066 | attr->a_vals = NULL; | |
1067 | attr->a_numvals = 0; | |
1068 | } | |
1069 | } else { | |
1070 | change = 1; | |
1071 | } | |
1072 | ||
1073 | if ( change ) { | |
1074 | for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) { | |
1075 | if ( maxcsn[ sid ].bv_len ) { | |
1076 | attr_merge_one( e, slap_schema.si_ad_contextCSN, | |
1077 | &maxcsn[ sid], NULL ); | |
1078 | } | |
1079 | } | |
1080 | ||
1081 | ctxcsn_id = be->be_entry_modify( be, e, bvtext ); | |
1082 | if( ctxcsn_id == NOID ) { | |
1083 | fprintf( stderr, "%s: could not modify ctxcsn (%s)\n", | |
1084 | progname, bvtext->bv_val ? bvtext->bv_val : "" ); | |
1085 | rc = EXIT_FAILURE; | |
1086 | } else if ( verbose ) { | |
1087 | fprintf( stderr, "modified: \"%s\" (%08lx)\n", | |
1088 | e->e_dn, (long) ctxcsn_id ); | |
1089 | } | |
1090 | } | |
1091 | entry_free( e ); | |
1092 | } | |
1093 | } | |
1094 | ||
1095 | return rc; | |
1096 | } | |
1097 | ||
1098 | /* | |
1099 | * return value: | |
1100 | * -1: update_ctxcsn == 0 | |
1101 | * SLAP_SYNC_SID_MAX + 1: unable to extract SID | |
1102 | * 0 <= SLAP_SYNC_SID_MAX: the SID | |
1103 | */ | |
1104 | unsigned long | |
1105 | slap_tool_update_ctxcsn_check( | |
1106 | const char *progname, | |
1107 | Entry *e ) | |
1108 | { | |
1109 | if ( update_ctxcsn ) { | |
1110 | unsigned long sid = SLAP_SYNC_SID_MAX + 1; | |
1111 | int rc_sid; | |
1112 | Attribute *attr; | |
1113 | ||
1114 | attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN ); | |
1115 | assert( attr != NULL ); | |
1116 | ||
1117 | rc_sid = slap_parse_csn_sid( &attr->a_nvals[ 0 ] ); | |
1118 | if ( rc_sid < 0 ) { | |
1119 | Debug( LDAP_DEBUG_ANY, "%s: could not " | |
1120 | "extract SID from entryCSN=%s, entry dn=\"%s\"\n", | |
1121 | progname, attr->a_nvals[ 0 ].bv_val, e->e_name.bv_val ); | |
1122 | return (unsigned long)(-1); | |
1123 | ||
1124 | } else { | |
1125 | int match; | |
1126 | const char *text = NULL; | |
1127 | ||
1128 | assert( rc_sid <= SLAP_SYNC_SID_MAX ); | |
1129 | ||
1130 | sid = (unsigned)rc_sid; | |
1131 | if ( maxcsn[ sid ].bv_len != 0 ) { | |
1132 | match = 0; | |
1133 | value_match( &match, slap_schema.si_ad_entryCSN, | |
1134 | slap_schema.si_ad_entryCSN->ad_type->sat_ordering, | |
1135 | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, | |
1136 | &maxcsn[ sid ], &attr->a_nvals[0], &text ); | |
1137 | } else { | |
1138 | match = -1; | |
1139 | } | |
1140 | if ( match < 0 ) { | |
1141 | strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val ); | |
1142 | maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len; | |
1143 | } | |
1144 | } | |
1145 | } | |
1146 | ||
1147 | return (unsigned long)(-1); | |
1148 | } | |
1149 | ||
1150 | int | |
1151 | slap_tool_update_ctxcsn_init(void) | |
1152 | { | |
1153 | if ( update_ctxcsn ) { | |
1154 | unsigned long sid; | |
1155 | maxcsn[ 0 ].bv_val = maxcsnbuf; | |
1156 | for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) { | |
1157 | maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_PVT_CSNSTR_BUFSIZE; | |
1158 | maxcsn[ sid ].bv_len = 0; | |
1159 | } | |
1160 | } | |
1161 | ||
1162 | return 0; | |
1163 | } | |
1164 | ||
1165 | int | |
1166 | slap_tool_entry_check( | |
1167 | const char *progname, | |
1168 | Operation *op, | |
1169 | Entry *e, | |
1170 | int lineno, | |
1171 | const char **text, | |
1172 | char *textbuf, | |
1173 | size_t textlen ) | |
1174 | { | |
1175 | /* NOTE: we may want to conditionally enable manage */ | |
1176 | int manage = 0; | |
1177 | ||
1178 | Attribute *oc = attr_find( e->e_attrs, | |
1179 | slap_schema.si_ad_objectClass ); | |
1180 | ||
1181 | if( oc == NULL ) { | |
1182 | fprintf( stderr, "%s: dn=\"%s\" (line=%d): %s\n", | |
1183 | progname, e->e_dn, lineno, | |
1184 | "no objectClass attribute"); | |
1185 | return LDAP_NO_SUCH_ATTRIBUTE; | |
1186 | } | |
1187 | ||
1188 | /* check schema */ | |
1189 | op->o_bd = be; | |
1190 | ||
1191 | if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) { | |
1192 | int rc = entry_schema_check( op, e, NULL, manage, 1, NULL, | |
1193 | text, textbuf, textlen ); | |
1194 | ||
1195 | if( rc != LDAP_SUCCESS ) { | |
1196 | fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n", | |
1197 | progname, e->e_dn, lineno, rc, *text ); | |
1198 | return rc; | |
1199 | } | |
1200 | textbuf[ 0 ] = '\0'; | |
1201 | } | |
1202 | ||
1203 | if ( (slapMode & SLAP_TOOL_VALUE_CHECK) != 0) { | |
1204 | Modifications *ml = NULL; | |
1205 | ||
1206 | int rc = slap_entry2mods( e, &ml, text, textbuf, textlen ); | |
1207 | if ( rc != LDAP_SUCCESS ) { | |
1208 | fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n", | |
1209 | progname, e->e_dn, lineno, rc, *text ); | |
1210 | return rc; | |
1211 | } | |
1212 | textbuf[ 0 ] = '\0'; | |
1213 | ||
1214 | rc = slap_mods_check( op, ml, text, textbuf, textlen, NULL ); | |
1215 | slap_mods_free( ml, 1 ); | |
1216 | if ( rc != LDAP_SUCCESS ) { | |
1217 | fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n", | |
1218 | progname, e->e_dn, lineno, rc, *text ); | |
1219 | return rc; | |
1220 | } | |
1221 | textbuf[ 0 ] = '\0'; | |
1222 | } | |
1223 | ||
1224 | return LDAP_SUCCESS; | |
1225 | } | |
0cf52863 | 1226 |