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