slapcommon.c 25.7 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/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 1998-2014 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
248
249
250
251
	} 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:
			Debug( LDAP_DEBUG_ANY, "value-check meaningless for tool.\n", 0, 0, 0 );
			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
440
441
442
443
444
445
446
447
448
449
450
451
452
453
		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' ) {
				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;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

555
556
557
558
559
560
		default:
			usage( tool, progname );
			break;
		}
	}

561
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
562
563
564
565
566
567
568
569
570
571
572
	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 );
573
#elif defined LOG_DEBUG
Pierangelo Masarati's avatar
Pierangelo Masarati committed
574
575
576
577
		openlog( logName, OPENLOG_OPTIONS );
#endif
#ifdef HAVE_EBCDIC
		free( logName );
578
		logName = NULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
579
580
#endif
	}
581
#endif /* LDAP_DEBUG && LDAP_SYSLOG */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
582

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

	default:
		writer = 0;
		break;
	}

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

		break;
603

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

		break;

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

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

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

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

639
640
	default:
		break;
641
642
643
	}

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

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

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

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

664
	rc = read_config( conffile, confdir );
665
666

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

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

680
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
681
682
683
684
685
686
687
	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
688
#endif
Pierangelo Masarati's avatar
Pierangelo Masarati committed
689

Howard Chu's avatar
Howard Chu committed
690
	at_oc_cache = 1;
Howard Chu's avatar
Howard Chu committed
691

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

	default:
		break;
706
707
	}

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

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

718
719
720
721
722
723
724
	rc = slap_schema_check();

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

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

735
736
737
738
	default:
		break;
	}

739
740
741
742
743
744
745
	if( filterstr ) {
		filter = str2filter( filterstr );

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

		ch_free( filterstr );
		filterstr = NULL;
749
750
	}

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

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

	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 );
		}

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

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

		default:
			break;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
793
794
		}

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

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

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

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

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

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

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

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

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
861
862
863
864
865
866
867
868
869
870
871
	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 );
		}
	}

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

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

883
884
885
886
#ifdef CSRIMALLOC
	mal_leaktrace(1);
#endif

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

892
893
894
895
896
	if ( confdir != NULL ) {
		ch_free( confdir );
		confdir = NULL;
	}

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

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

906
907
908
909
910
911
912
913
914
915
916
917
		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;
			}
918

919
			exit( EXIT_FAILURE );
920
		}
921
922
923
	}
}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
924
int slap_tool_destroy( void )
925
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
926
	int rc = 0;
927
	if ( !dryrun ) {
928
		if ( need_shutdown ) {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
929
930
			if ( slap_shutdown( be ))
				rc = EXIT_FAILURE;
931
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
932
933
		if ( slap_destroy())
			rc = EXIT_FAILURE;
934
	}
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
#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
951
952
953

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

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

963
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;
			}
		} else {
			fprintf( stderr, "%s: context entry is missing\n", progname );
For faster browsing, not all history is shown. View entire blame