slapcommon.c 25.8 KB
Newer Older
1
2
3
4
/* slapcommon.c - common routine for the slap tools */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
5
 * Copyright 1998-2019 The OpenLDAP Foundation.
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * Portions Copyright 1998-2003 Kurt D. Zeilenga.
 * Portions Copyright 2003 IBM Corporation.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by Kurt Zeilenga for inclusion
 * in OpenLDAP Software.  Additional signficant contributors include
 *    Jong Hyuk Choi
 *    Hallvard B. Furuseth
 *    Howard Chu
 *    Pierangelo Masarati
 */

#include "portable.h"

#include <stdio.h>

#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/socket.h>
#include <ac/unistd.h>

#include "slapcommon.h"
#include "lutil.h"
39
#include "ldif.h"
40
41
42
43
44
45
46
47

tool_vars tool_globals;

#ifdef CSRIMALLOC
static char *leakfilename;
static FILE *leakfile;
#endif

48
49
static LDIFFP dummy;

50
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
51
52
53
54
55
int start_syslog;
static char **syslog_unknowns;
#ifdef LOG_LOCAL4
static int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
#endif /* LOG_LOCAL4 */
56
#endif /* LDAP_DEBUG && LDAP_SYSLOG */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
57

58
59
60
61
62
static void
usage( int tool, const char *progname )
{
	char *options = NULL;
	fprintf( stderr,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
63
		"usage: %s [-v] [-d debuglevel] [-f configfile] [-F configdir] [-o <name>[=<value>]]",
64
		progname );
65
66

	switch( tool ) {
67
	case SLAPACL:
68
		options = "\n\t[-U authcID | -D authcDN] [-X authzID | -o authzDN=<DN>]"
Pierangelo Masarati's avatar
Pierangelo Masarati committed
69
			"\n\t-b DN [-u] [attr[/access][:value]] [...]\n";
70
71
		break;

72
	case SLAPADD:
73
		options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]\n"
74
			"\t[-l ldiffile] [-j linenumber] [-q] [-u] [-s] [-w]\n";
75
76
		break;

77
78
79
80
	case SLAPAUTH:
		options = "\n\t[-U authcID] [-X authzID] [-R realm] [-M mech] ID [...]\n";
		break;

81
	case SLAPCAT:
82
		options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]"
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
83
			" [-l ldiffile] [-a filter] [-s subtree] [-H url]\n";
84
85
86
		break;

	case SLAPDN:
87
		options = "\n\t[-N | -P] DN [...]\n";
88
89
90
		break;

	case SLAPINDEX:
91
		options = " [-c]\n\t[-g] [-n databasenumber | -b suffix] [attr ...] [-q] [-t]\n";
92
		break;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
93

94
	case SLAPTEST:
95
		options = " [-n databasenumber] [-u] [-Q]\n";
Pierangelo Masarati's avatar
Pierangelo Masarati committed
96
		break;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
97
98
99

	case SLAPSCHEMA:
		options = " [-c]\n\t[-g] [-n databasenumber | -b suffix]"
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
100
			" [-l errorfile] [-a filter] [-s subtree] [-H url]\n";
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
101
		break;
102
103
	}

104
	if ( options != NULL ) {
105
106
107
108
109
		fputs( options, stderr );
	}
	exit( EXIT_FAILURE );
}

110
static int
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
111
parse_slapopt( int tool, int *mode )
112
{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
113
	size_t	len = 0;
114
115
116
	char	*p;

	p = strchr( optarg, '=' );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
117
118
119
	if ( p != NULL ) {
		len = p - optarg;
		p++;
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
	}

	if ( strncasecmp( optarg, "sockurl", len ) == 0 ) {
		if ( !BER_BVISNULL( &listener_url ) ) {
			ber_memfree( listener_url.bv_val );
		}
		ber_str2bv( p, 0, 1, &listener_url );

	} else if ( strncasecmp( optarg, "domain", len ) == 0 ) {
		if ( !BER_BVISNULL( &peer_domain ) ) {
			ber_memfree( peer_domain.bv_val );
		}
		ber_str2bv( p, 0, 1, &peer_domain );

	} else if ( strncasecmp( optarg, "peername", len ) == 0 ) {
		if ( !BER_BVISNULL( &peer_name ) ) {
			ber_memfree( peer_name.bv_val );
		}
		ber_str2bv( p, 0, 1, &peer_name );

	} else if ( strncasecmp( optarg, "sockname", len ) == 0 ) {
		if ( !BER_BVISNULL( &sock_name ) ) {
			ber_memfree( sock_name.bv_val );
		}
		ber_str2bv( p, 0, 1, &sock_name );

	} else if ( strncasecmp( optarg, "ssf", len ) == 0 ) {
147
148
149
150
		if ( lutil_atou( &ssf, p ) ) {
			Debug( LDAP_DEBUG_ANY, "unable to parse ssf=\"%s\".\n", p, 0, 0 );
			return -1;
		}
151
152

	} else if ( strncasecmp( optarg, "transport_ssf", len ) == 0 ) {
153
154
155
156
		if ( lutil_atou( &transport_ssf, p ) ) {
			Debug( LDAP_DEBUG_ANY, "unable to parse transport_ssf=\"%s\".\n", p, 0, 0 );
			return -1;
		}
157
158

	} else if ( strncasecmp( optarg, "tls_ssf", len ) == 0 ) {
159
160
161
162
		if ( lutil_atou( &tls_ssf, p ) ) {
			Debug( LDAP_DEBUG_ANY, "unable to parse tls_ssf=\"%s\".\n", p, 0, 0 );
			return -1;
		}
163
164

	} else if ( strncasecmp( optarg, "sasl_ssf", len ) == 0 ) {
165
166
167
168
		if ( lutil_atou( &sasl_ssf, p ) ) {
			Debug( LDAP_DEBUG_ANY, "unable to parse sasl_ssf=\"%s\".\n", p, 0, 0 );
			return -1;
		}
169

170
171
172
	} else if ( strncasecmp( optarg, "authzDN", len ) == 0 ) {
		ber_str2bv( p, 0, 1, &authzDN );

173
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	} else if ( strncasecmp( optarg, "syslog", len ) == 0 ) {
		if ( parse_debug_level( p, &ldap_syslog, &syslog_unknowns ) ) {
			return -1;
		}
		start_syslog = 1;

	} else if ( strncasecmp( optarg, "syslog-level", len ) == 0 ) {
		if ( parse_syslog_level( p, &ldap_syslog_level ) ) {
			return -1;
		}
		start_syslog = 1;

#ifdef LOG_LOCAL4
	} else if ( strncasecmp( optarg, "syslog-user", len ) == 0 ) {
		if ( parse_syslog_user( p, &syslogUser ) ) {
			return -1;
		}
		start_syslog = 1;
#endif /* LOG_LOCAL4 */
193
#endif /* LDAP_DEBUG && LDAP_SYSLOG */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
194

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
	} else if ( strncasecmp( optarg, "schema-check", len ) == 0 ) {
		switch ( tool ) {
		case SLAPADD:
			if ( strcasecmp( p, "yes" ) == 0 ) {
				*mode &= ~SLAP_TOOL_NO_SCHEMA_CHECK;
			} else if ( strcasecmp( p, "no" ) == 0 ) {
				*mode |= SLAP_TOOL_NO_SCHEMA_CHECK;
			} else {
				Debug( LDAP_DEBUG_ANY, "unable to parse schema-check=\"%s\".\n", p, 0, 0 );
				return -1;
			}
			break;

		default:
			Debug( LDAP_DEBUG_ANY, "schema-check meaningless for tool.\n", 0, 0, 0 );
			break;
		}

	} else if ( strncasecmp( optarg, "value-check", len ) == 0 ) {
		switch ( tool ) {
		case SLAPADD:
			if ( strcasecmp( p, "yes" ) == 0 ) {
				*mode |= SLAP_TOOL_VALUE_CHECK;
			} else if ( strcasecmp( p, "no" ) == 0 ) {
				*mode &= ~SLAP_TOOL_VALUE_CHECK;
			} else {
				Debug( LDAP_DEBUG_ANY, "unable to parse value-check=\"%s\".\n", p, 0, 0 );
				return -1;
			}
			break;

		default:
			Debug( LDAP_DEBUG_ANY, "value-check meaningless for tool.\n", 0, 0, 0 );
			break;
		}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
	} else if ( strncasecmp( optarg, "ldif-wrap", len ) == 0 ) {
		switch ( tool ) {
		case SLAPCAT:
			if ( strcasecmp( p, "no" ) == 0 ) {
				ldif_wrap = LDIF_LINE_WIDTH_MAX;

			} else {
				unsigned int u;
				if ( lutil_atou( &u, p ) ) {
					Debug( LDAP_DEBUG_ANY, "unable to parse ldif-wrap=\"%s\".\n", p, 0, 0 );
					return -1;
				}
				ldif_wrap = (ber_len_t)u;
			}
			break;

		default:
Howard Chu's avatar
Howard Chu committed
248
			Debug( LDAP_DEBUG_ANY, "ldif-wrap meaningless for tool.\n", 0, 0, 0 );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
249
250
251
			break;
		}

252
253
254
255
256
257
	} else {
		return -1;
	}

	return 0;
}
258
259
260
261
262
263
264
265
266

/*
 * slap_tool_init - initialize slap utility, handle program options.
 * arguments:
 *	name		program name
 *	tool		tool code
 *	argc, argv	command line arguments
 */

267
268
static int need_shutdown;

269
270
271
272
273
274
275
void
slap_tool_init(
	const char* progname,
	int tool,
	int argc, char **argv )
{
	char *options;
Howard Chu's avatar
Howard Chu committed
276
277
	char *conffile = NULL;
	char *confdir = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
278
	struct berval base = BER_BVNULL;
279
	char *filterstr = NULL;
280
281
	char *subtree = NULL;
	char *ldiffile	= NULL;
282
	char **debug_unknowns = NULL;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
283
	int rc, i;
284
285
	int mode = SLAP_TOOL_MODE;
	int truncatemode = 0;
286
	int use_glue = 1;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
287
	int writer;
288

289
290
291
#ifdef LDAP_DEBUG
	/* tools default to "none", so that at least LDAP_DEBUG_ANY 
	 * messages show up; use -d 0 to reset */
292
	slap_debug = LDAP_DEBUG_NONE;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
293
	ldif_debug = slap_debug;
294
#endif
Pierangelo Masarati's avatar
Pierangelo Masarati committed
295
	ldap_syslog = 0;
296

297
#ifdef CSRIMALLOC
Pierangelo Masarati's avatar
typo    
Pierangelo Masarati committed
298
	leakfilename = malloc( strlen( progname ) + STRLENOF( ".leak" ) + 1 );
299
300
301
302
303
	sprintf( leakfilename, "%s.leak", progname );
	if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) {
		leakfile = stderr;
	}
	free( leakfilename );
304
	leakfilename = NULL;
305
306
#endif

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
307
308
	ldif_wrap = LDIF_LINE_WIDTH;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
309
310
	scope = LDAP_SCOPE_DEFAULT;

311
312
	switch( tool ) {
	case SLAPADD:
313
		options = "b:cd:f:F:gj:l:n:o:qsS:uvw";
314
315
316
		break;

	case SLAPCAT:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
317
		options = "a:b:cd:f:F:gH:l:n:o:s:v";
318
319
320
		mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
		break;

321
	case SLAPDN:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
322
		options = "d:f:F:No:Pv";
323
		mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
324
325
		break;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
326
	case SLAPSCHEMA:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
327
		options = "a:b:cd:f:F:gH:l:n:o:s:v";
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
328
329
330
		mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
		break;

331
	case SLAPTEST:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
332
		options = "d:f:F:n:o:Quv";
333
334
335
		mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
		break;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
336
	case SLAPAUTH:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
337
		options = "d:f:F:M:o:R:U:vX:";
338
		mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
339
340
		break;

341
	case SLAPINDEX:
342
		options = "b:cd:f:F:gn:o:qtv";
343
344
345
		mode |= SLAP_TOOL_READMAIN;
		break;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
346
	case SLAPACL:
347
		options = "b:D:d:f:F:o:uU:vX:";
348
		mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
349
350
		break;

351
	default:
352
		fprintf( stderr, "%s: unknown tool mode (%d)\n", progname, tool );
353
354
355
356
357
358
		exit( EXIT_FAILURE );
	}

	dbnum = -1;
	while ( (i = getopt( argc, argv, options )) != EOF ) {
		switch ( i ) {
359
		case 'a':
Howard Chu's avatar
Howard Chu committed
360
			filterstr = ch_strdup( optarg );
361
362
			break;

363
		case 'b':
364
			ber_str2bv( optarg, 0, 1, &base );
365
366
367
368
369
370
			break;

		case 'c':	/* enable continue mode */
			continuemode++;
			break;

371
372
373
		case 'd': {	/* turn on debugging */
			int	level = 0;

374
			if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) {
375
376
				usage( tool, progname );
			}
377
#ifdef LDAP_DEBUG
378
379
380
			if ( level == 0 ) {
				/* allow to reset log level */
				slap_debug = 0;
381
382

			} else {
383
				slap_debug |= level;
384
385
			}
#else
386
			if ( level != 0 )
387
388
389
				fputs( "must compile with LDAP_DEBUG for debugging\n",
				       stderr );
#endif
390
			} break;
391

Pierangelo Masarati's avatar
Pierangelo Masarati committed
392
		case 'D':
393
			ber_str2bv( optarg, 0, 1, &authcDN );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
394
395
			break;

396
		case 'f':	/* specify a conf file */
Howard Chu's avatar
Howard Chu committed
397
			conffile = ch_strdup( optarg );
398
399
			break;

400
		case 'F':	/* specify a conf dir */
Howard Chu's avatar
Howard Chu committed
401
			confdir = ch_strdup( optarg );
402
403
			break;

404
405
406
407
		case 'g':	/* disable subordinate glue */
			use_glue = 0;
			break;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
		case 'H': {
			LDAPURLDesc *ludp;
			int rc;

			rc = ldap_url_parse_ext( optarg, &ludp,
				LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_NOEMPTY_DN );
			if ( rc != LDAP_URL_SUCCESS ) {
				usage( tool, progname );
			}

			/* don't accept host, port, attrs, extensions */
			if ( ldap_pvt_url_scheme2proto( ludp->lud_scheme ) != LDAP_PROTO_TCP ) {
				usage( tool, progname );
			}

			if ( ludp->lud_host != NULL ) {
				usage( tool, progname );
			}

			if ( ludp->lud_port != 0 ) {
				usage( tool, progname );
			}

			if ( ludp->lud_attrs != NULL ) {
				usage( tool, progname );
			}

			if ( ludp->lud_exts != NULL ) {
				usage( tool, progname );
			}

			if ( ludp->lud_dn != NULL && ludp->lud_dn[0] != '\0' ) {
Howard Chu's avatar
Howard Chu committed
440
				ch_free( subtree );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
441
442
443
444
445
446
447
448
449
450
451
452
453
454
				subtree = ludp->lud_dn;
				ludp->lud_dn = NULL;
			}

			if ( ludp->lud_filter != NULL && ludp->lud_filter[0] != '\0' ) {
				filterstr = ludp->lud_filter;
				ludp->lud_filter = NULL;
			}

			scope = ludp->lud_scope;

			ldap_free_urldesc( ludp );
			} break;

455
		case 'j':	/* jump to linenumber */
456
			if ( lutil_atoul( &jumpline, optarg ) ) {
457
458
459
460
				usage( tool, progname );
			}
			break;

461
		case 'l':	/* LDIF file */
Howard Chu's avatar
Howard Chu committed
462
			ldiffile = ch_strdup( optarg );
463
464
			break;

465
466
467
468
		case 'M':
			ber_str2bv( optarg, 0, 0, &mech );
			break;

469
470
471
472
473
474
475
		case 'N':
			if ( dn_mode && dn_mode != SLAP_TOOL_LDAPDN_NORMAL ) {
				usage( tool, progname );
			}
			dn_mode = SLAP_TOOL_LDAPDN_NORMAL;
			break;

476
		case 'n':	/* which config file db to index */
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
477
			if ( lutil_atoi( &dbnum, optarg ) || dbnum < 0 ) {
478
479
				usage( tool, progname );
			}
480
481
			break;

482
		case 'o':
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
483
			if ( parse_slapopt( tool, &mode ) ) {
484
485
486
487
				usage( tool, progname );
			}
			break;

488
489
490
491
492
493
494
		case 'P':
			if ( dn_mode && dn_mode != SLAP_TOOL_LDAPDN_PRETTY ) {
				usage( tool, progname );
			}
			dn_mode = SLAP_TOOL_LDAPDN_PRETTY;
			break;

495
496
497
498
499
		case 'Q':
			quiet++;
			slap_debug = 0;
			break;

500
501
502
503
		case 'q':	/* turn on quick */
			mode |= SLAP_TOOL_QUICK;
			break;

504
505
506
507
		case 'R':
			realm = optarg;
			break;

508
		case 'S':
509
			if ( lutil_atou( &csnsid, optarg )
510
511
512
513
514
515
				|| csnsid > SLAP_SYNC_SID_MAX )
			{
				usage( tool, progname );
			}
			break;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
516
517
518
519
		case 's':
			switch ( tool ) {
			case SLAPADD:
				/* no schema check */
520
				mode |= SLAP_TOOL_NO_SCHEMA_CHECK;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
521
522
523
524
525
				break;

			case SLAPCAT:
			case SLAPSCHEMA:
				/* dump subtree */
Howard Chu's avatar
Howard Chu committed
526
				ch_free( subtree );
Howard Chu's avatar
Howard Chu committed
527
				subtree = ch_strdup( optarg );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
528
529
				break;
			}
530
531
532
533
534
535
536
			break;

		case 't':	/* turn on truncate */
			truncatemode++;
			mode |= SLAP_TRUNCATE_MODE;
			break;

537
538
539
540
		case 'U':
			ber_str2bv( optarg, 0, 0, &authcID );
			break;

541
542
543
544
545
546
547
548
		case 'u':	/* dry run */
			dryrun++;
			break;

		case 'v':	/* turn on verbose */
			verbose++;
			break;

Howard Chu's avatar
Howard Chu committed
549
		case 'w':	/* write context csn at the end */
550
			update_ctxcsn++;
551
552
			break;

553
554
555
556
		case 'X':
			ber_str2bv( optarg, 0, 0, &authzID );
			break;

557
558
559
560
561
562
		default:
			usage( tool, progname );
			break;
		}
	}

563
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
564
565
566
567
568
569
570
571
572
573
574
	if ( start_syslog ) {
		char *logName;
#ifdef HAVE_EBCDIC
		logName = ch_strdup( progname );
		__atoe( logName );
#else
		logName = (char *)progname;
#endif

#ifdef LOG_LOCAL4
		openlog( logName, OPENLOG_OPTIONS, syslogUser );
575
#elif defined LOG_DEBUG
Pierangelo Masarati's avatar
Pierangelo Masarati committed
576
577
578
579
		openlog( logName, OPENLOG_OPTIONS );
#endif
#ifdef HAVE_EBCDIC
		free( logName );
580
		logName = NULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
581
582
#endif
	}
583
#endif /* LDAP_DEBUG && LDAP_SYSLOG */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
584

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
585
586
587
588
589
590
591
592
593
594
595
	switch ( tool ) {
	case SLAPCAT:
	case SLAPSCHEMA:
		writer = 1;
		break;

	default:
		writer = 0;
		break;
	}

596
597
598
	switch ( tool ) {
	case SLAPADD:
	case SLAPCAT:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
599
	case SLAPSCHEMA:
600
601
602
603
604
		if ( ( argc != optind ) || (dbnum >= 0 && base.bv_val != NULL ) ) {
			usage( tool, progname );
		}

		break;
605

606
607
608
609
610
611
612
	case SLAPINDEX:
		if ( dbnum >= 0 && base.bv_val != NULL ) {
			usage( tool, progname );
		}

		break;

613
614
	case SLAPDN:
		if ( argc == optind ) {
615
616
			usage( tool, progname );
		}
617
618
		break;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
619
	case SLAPAUTH:
620
621
622
623
624
		if ( argc == optind && BER_BVISNULL( &authcID ) ) {
			usage( tool, progname );
		}
		break;

625
626
627
628
629
630
	case SLAPTEST:
		if ( argc != optind ) {
			usage( tool, progname );
		}
		break;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
631
632
633
634
635
636
637
638
639
640
	case SLAPACL:
		if ( !BER_BVISNULL( &authcDN ) && !BER_BVISNULL( &authcID ) ) {
			usage( tool, progname );
		}
		if ( BER_BVISNULL( &base ) ) {
			usage( tool, progname );
		}
		ber_dupbv( &baseDN, &base );
		break;

641
642
	default:
		break;
643
644
645
	}

	if ( ldiffile == NULL ) {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
646
		dummy.fp = writer ? stdout : stdin;
647
		ldiffp = &dummy;
648

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
649
	} else if ((ldiffp = ldif_open( ldiffile, writer ? "w" : "r" ))
650
651
652
653
654
655
656
657
658
659
		== NULL )
	{
		perror( ldiffile );
		exit( EXIT_FAILURE );
	}

	/*
	 * initialize stuff and figure out which backend we're dealing with
	 */

Howard Chu's avatar
Howard Chu committed
660
	rc = slap_init( mode, progname );
661
	if ( rc != 0 ) {
Howard Chu's avatar
Howard Chu committed
662
		fprintf( stderr, "%s: slap_init failed!\n", progname );
663
664
665
		exit( EXIT_FAILURE );
	}

666
	rc = read_config( conffile, confdir );
667
668

	if ( rc != 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
669
670
		fprintf( stderr, "%s: bad configuration %s!\n",
			progname, confdir ? "directory" : "file" );
671
672
673
		exit( EXIT_FAILURE );
	}

674
675
676
677
678
679
680
681
	if ( debug_unknowns ) {
		rc = parse_debug_unknowns( debug_unknowns, &slap_debug );
		ldap_charray_free( debug_unknowns );
		debug_unknowns = NULL;
		if ( rc )
			exit( EXIT_FAILURE );
	}

682
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
683
684
685
686
687
688
689
	if ( syslog_unknowns ) {
		rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog );
		ldap_charray_free( syslog_unknowns );
		syslog_unknowns = NULL;
		if ( rc )
			exit( EXIT_FAILURE );
	}
Howard Chu's avatar
Howard Chu committed
690
#endif
Pierangelo Masarati's avatar
Pierangelo Masarati committed
691

Howard Chu's avatar
Howard Chu committed
692
	at_oc_cache = 1;
Howard Chu's avatar
Howard Chu committed
693

694
695
696
697
	switch ( tool ) {
	case SLAPADD:
	case SLAPCAT:
	case SLAPINDEX:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
698
	case SLAPSCHEMA:
699
700
701
702
703
704
705
706
707
		if ( !nbackends ) {
			fprintf( stderr, "No databases found "
					"in config file\n" );
			exit( EXIT_FAILURE );
		}
		break;

	default:
		break;
708
709
	}

710
	if ( use_glue ) {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
711
		rc = glue_sub_attach( 0 );
712

713
714
715
716
717
		if ( rc != 0 ) {
			fprintf( stderr,
				"%s: subordinate configuration error\n", progname );
			exit( EXIT_FAILURE );
		}
718
719
	}

720
721
722
723
724
725
726
	rc = slap_schema_check();

	if ( rc != 0 ) {
		fprintf( stderr, "%s: slap_schema_prep failed!\n", progname );
		exit( EXIT_FAILURE );
	}

727
728
	switch ( tool ) {
	case SLAPTEST:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
729
730
731
732
		if ( dbnum >= 0 )
			goto get_db;
		/* FALLTHRU */
	case SLAPDN:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
733
	case SLAPAUTH:
734
735
736
		be = NULL;
		goto startup;

737
738
739
740
	default:
		break;
	}

741
742
743
744
745
746
747
	if( filterstr ) {
		filter = str2filter( filterstr );

		if( filter == NULL ) {
			fprintf( stderr, "Invalid filter '%s'\n", filterstr );
			exit( EXIT_FAILURE );
		}
748
749
750

		ch_free( filterstr );
		filterstr = NULL;
751
752
	}

753
754
	if( subtree ) {
		struct berval val;
755
		ber_str2bv( subtree, 0, 0, &val );
756
757
		rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL );
		if( rc != LDAP_SUCCESS ) {
758
			fprintf( stderr, "Invalid subtree DN '%s'\n", subtree );
759
760
761
			exit( EXIT_FAILURE );
		}

762
		if ( BER_BVISNULL( &base ) && dbnum == -1 ) {
763
			base = val;
764
		} else {
765
			free( subtree );
766
			subtree = NULL;
767
		}
768
769
770
771
772
773
774
775
776
777
778
779
	}

	if( base.bv_val != NULL ) {
		struct berval nbase;

		rc = dnNormalize( 0, NULL, NULL, &base, &nbase, NULL );
		if( rc != LDAP_SUCCESS ) {
			fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n",
				progname, base.bv_val );
			exit( EXIT_FAILURE );
		}

780
		be = select_backend( &nbase, 0 );
781
		ber_memfree( nbase.bv_val );
782
		BER_BVZERO( &nbase );
783

784
785
786
787
788
		if( be == NULL ) {
			fprintf( stderr, "%s: slap_init no backend for \"%s\"\n",
				progname, base.bv_val );
			exit( EXIT_FAILURE );
		}
789
790
		switch ( tool ) {
		case SLAPACL:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
791
			goto startup;
792
793
794

		default:
			break;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
795
796
		}

797
798
799
		/* If the named base is a glue master, operate on the
		 * entire context
		 */
800
		if ( SLAP_GLUE_INSTANCE( be ) ) {
801
802
803
			nosubordinates = 1;
		}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
804
		ch_free( base.bv_val );
805
		BER_BVZERO( &base );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
806

807
	} else if ( dbnum == -1 ) {
Howard Chu's avatar
Howard Chu committed
808
809
810
		/* no suffix and no dbnum specified, just default to
		 * the first available database
		 */
811
812
813
814
		if ( nbackends <= 0 ) {
			fprintf( stderr, "No available databases\n" );
			exit( EXIT_FAILURE );
		}
815
816
		LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
			dbnum++;
Howard Chu's avatar
Howard Chu committed
817
818

			/* db #0 is cn=config, don't select it as a default */
819
			if ( dbnum < 1 ) continue;
820
		
821
822
823
		 	if ( SLAP_MONITOR(be))
				continue;

824
825
826
		/* If just doing the first by default and it is a
		 * glue subordinate, find the master.
		 */
827
			if ( SLAP_GLUE_SUBORDINATE(be) ) {
828
				nosubordinates = 1;
829
				continue;
830
			}
831
			break;
832
833
		}

834
		if ( !be ) {
835
836
837
838
839
			fprintf( stderr, "Available database(s) "
					"do not allow %s\n", progname );
			exit( EXIT_FAILURE );
		}
		
Howard Chu's avatar
Howard Chu committed
840
		if ( nosubordinates == 0 && dbnum > 1 ) {
841
			Debug( LDAP_DEBUG_ANY,
842
843
				"The first database does not allow %s;"
				" using the first available one (%d)\n",
Howard Chu's avatar
Howard Chu committed
844
				progname, dbnum, 0 );
845
846
		}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
847
	} else if ( dbnum >= nbackends ) {
848
849
		fprintf( stderr,
			"Database number selected via -n is out of range\n"
Howard Chu's avatar
Howard Chu committed
850
			"Must be in the range 0 to %d"
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
851
852
			" (the number of configured databases)\n",
			nbackends - 1 );
853
854
855
		exit( EXIT_FAILURE );

	} else {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
856
get_db:
857
858
859
860
		LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
			if ( dbnum == 0 ) break;
			dbnum--;
		}
861
862
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
863
864
865
866
867
868
869
870
871
872
873
	if ( scope != LDAP_SCOPE_DEFAULT && BER_BVISNULL( &sub_ndn ) ) {
		if ( be && be->be_nsuffix ) {
			ber_dupbv( &sub_ndn, be->be_nsuffix );

		} else {
			fprintf( stderr,
				"<scope> needs a DN or a valid database\n" );
			exit( EXIT_FAILURE );
		}
	}

874
startup:;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
875
876
877
878
879
880
881
882
883
	if ( be ) {
		BackendDB *bdtmp;

		dbnum = 0;
		LDAP_STAILQ_FOREACH( bdtmp, &backendDB, be_next ) {
			if ( bdtmp == be ) break;
			dbnum++;
		}
	}
884

885
886
887
888
#ifdef CSRIMALLOC
	mal_leaktrace(1);
#endif

Pierangelo Masarati's avatar
Pierangelo Masarati committed
889
890
	if ( conffile != NULL ) {
		ch_free( conffile );
891
		conffile = NULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
892
893
	}

894
895
896
897
898
	if ( confdir != NULL ) {
		ch_free( confdir );
		confdir = NULL;
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
899
900
	if ( ldiffile != NULL ) {
		ch_free( ldiffile );
901
		ldiffile = NULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
902
903
	}

904
	/* slapdn doesn't specify a backend to startup */
905
	if ( !dryrun && tool != SLAPDN ) {
906
907
		need_shutdown = 1;

908
909
910
911
912
913
914
915
916
917
918
919
		if ( slap_startup( be ) ) {
			switch ( tool ) {
			case SLAPTEST:
				fprintf( stderr, "slap_startup failed "
						"(test would succeed using "
						"the -u switch)\n" );
				break;

			default:
				fprintf( stderr, "slap_startup failed\n" );
				break;
			}
920

921
			exit( EXIT_FAILURE );
922
		}
923
924
925
	}
}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
926
int slap_tool_destroy( void )
927
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
928
	int rc = 0;
929
	if ( !dryrun ) {
930
		if ( need_shutdown ) {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
931
932
			if ( slap_shutdown( be ))
				rc = EXIT_FAILURE;
933
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
934
935
		if ( slap_destroy())
			rc = EXIT_FAILURE;
936
	}
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
#ifdef SLAPD_MODULES
	if ( slapMode == SLAP_SERVER_MODE ) {
	/* always false. just pulls in necessary symbol references. */
		lutil_uuidstr(NULL, 0);
	}
	module_kill();
#endif
	schema_destroy();
#ifdef HAVE_TLS
	ldap_pvt_tls_destroy();
#endif
	config_destroy();

#ifdef CSRIMALLOC
	mal_dumpleaktrace( leakfile );
#endif
953
954
955

	if ( !BER_BVISNULL( &authcDN ) ) {
		ch_free( authcDN.bv_val );
956
		BER_BVZERO( &authcDN );
957
	}
958
959
960
961

	if ( ldiffp && ldiffp != &dummy ) {
		ldif_close( ldiffp );
	}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
962
	return rc;
963
}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
int
slap_tool_update_ctxcsn(
	const char *progname,
	unsigned long sid,
	struct berval *bvtext )
{
	struct berval ctxdn;
	ID ctxcsn_id;
	Entry *ctxcsn_e;
	int rc = EXIT_SUCCESS;

	if ( !(update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1) ) {
		return rc;
	}

	if ( SLAP_SYNC_SUBENTRY( be )) {
		build_new_dn( &ctxdn, &be->be_nsuffix[0],
			(struct berval *)&slap_ldapsync_cn_bv, NULL );
	} else {
		ctxdn = be->be_nsuffix[0];
	}
	ctxcsn_id = be->be_dn2id_get( be, &ctxdn );
	if ( ctxcsn_id == NOID ) {
		if ( SLAP_SYNC_SUBENTRY( be )) {
			ctxcsn_e = slap_create_context_csn_entry( be, NULL );
			for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
				if ( maxcsn[ sid ].bv_len ) {
					attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN,
						&maxcsn[ sid ], NULL );
				}
			}
			ctxcsn_id = be->be_entry_put( be, ctxcsn_e, bvtext );
			if ( ctxcsn_id == NOID ) {
				fprintf( stderr, "%s: couldn't create context entry\n", progname );
				rc = EXIT_FAILURE;
			}
For faster browsing, not all history is shown. View entire blame