1 /* $NetBSD: ldif.c,v 1.1.1.4 2014/05/28 09:58:49 tron Exp $ */ 2 3 /* ldif.c - the ldif backend */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2005-2014 The OpenLDAP Foundation. 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 the 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 originally developed by Eric Stokes for inclusion 20 * in OpenLDAP Software. 21 */ 22 23 #include "portable.h" 24 #include <stdio.h> 25 #include <ac/string.h> 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <ac/dirent.h> 29 #include <fcntl.h> 30 #include <ac/errno.h> 31 #include <ac/unistd.h> 32 #include "slap.h" 33 #include "lutil.h" 34 #include "config.h" 35 36 struct ldif_tool { 37 Entry **entries; /* collected by bi_tool_entry_first() */ 38 ID elen; /* length of entries[] array */ 39 ID ecount; /* number of entries */ 40 ID ecurrent; /* bi_tool_entry_next() position */ 41 # define ENTRY_BUFF_INCREMENT 500 /* initial entries[] length */ 42 struct berval *tl_base; 43 int tl_scope; 44 Filter *tl_filter; 45 }; 46 47 /* Per-database data */ 48 struct ldif_info { 49 struct berval li_base_path; /* database directory */ 50 struct ldif_tool li_tool; /* for slap tools */ 51 /* 52 * Read-only LDAP requests readlock li_rdwr for filesystem input. 53 * Update requests first lock li_modop_mutex for filesystem I/O, 54 * and then writelock li_rdwr as well for filesystem output. 55 * This allows update requests to do callbacks that acquire 56 * read locks, e.g. access controls that inspect entries. 57 * (An alternative would be recursive read/write locks.) 58 */ 59 ldap_pvt_thread_mutex_t li_modop_mutex; /* serialize update requests */ 60 ldap_pvt_thread_rdwr_t li_rdwr; /* no other I/O when writing */ 61 }; 62 63 static int write_data( int fd, const char *spew, int len, int *save_errno ); 64 65 #ifdef _WIN32 66 #define mkdir(a,b) mkdir(a) 67 #define move_file(from, to) (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)) 68 #else 69 #define move_file(from, to) rename(from, to) 70 #endif 71 #define move_dir(from, to) rename(from, to) 72 73 74 #define LDIF ".ldif" 75 #define LDIF_FILETYPE_SEP '.' /* LDIF[0] */ 76 77 /* 78 * Unsafe/translated characters in the filesystem. 79 * 80 * LDIF_UNSAFE_CHAR(c) returns true if the character c is not to be used 81 * in relative filenames, except it should accept '\\', '{' and '}' even 82 * if unsafe. The value should be a constant expression. 83 * 84 * If '\\' is unsafe, #define LDIF_ESCAPE_CHAR as a safe character. 85 * If '{' and '}' are unsafe, #define IX_FSL/IX_FSR as safe characters. 86 * (Not digits, '-' or '+'. IX_FSL == IX_FSR is allowed.) 87 * 88 * Characters are escaped as LDIF_ESCAPE_CHAR followed by two hex digits, 89 * except '\\' is replaced with LDIF_ESCAPE_CHAR and {} with IX_FS[LR]. 90 * Also some LDIF special chars are hex-escaped. 91 * 92 * Thus an LDIF filename is a valid normalized RDN (or suffix DN) 93 * followed by ".ldif", except with '\\' replaced with LDIF_ESCAPE_CHAR. 94 */ 95 96 #ifndef _WIN32 97 98 /* 99 * Unix/MacOSX version. ':' vs '/' can cause confusion on MacOSX so we 100 * escape both. We escape them on Unix so both OS variants get the same 101 * filenames. 102 */ 103 #define LDIF_ESCAPE_CHAR '\\' 104 #define LDIF_UNSAFE_CHAR(c) ((c) == '/' || (c) == ':') 105 106 #else /* _WIN32 */ 107 108 /* Windows version - Microsoft's list of unsafe characters, except '\\' */ 109 #define LDIF_ESCAPE_CHAR '^' /* Not '\\' (unsafe on Windows) */ 110 #define LDIF_UNSAFE_CHAR(c) \ 111 ((c) == '/' || (c) == ':' || \ 112 (c) == '<' || (c) == '>' || (c) == '"' || \ 113 (c) == '|' || (c) == '?' || (c) == '*') 114 115 #endif /* !_WIN32 */ 116 117 /* 118 * Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}bdb"). 119 * IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames. 120 */ 121 #define IX_DNL '{' 122 #define IX_DNR '}' 123 #ifndef IX_FSL 124 #define IX_FSL IX_DNL 125 #define IX_FSR IX_DNR 126 #endif 127 128 /* 129 * Test for unsafe chars, as well as chars handled specially by back-ldif: 130 * - If the escape char is not '\\', it must itself be escaped. Otherwise 131 * '\\' and the escape char would map to the same character. 132 * - Escape the '.' in ".ldif", so the directory for an RDN that actually 133 * ends with ".ldif" can not conflict with a file of the same name. And 134 * since some OSes/programs choke on multiple '.'s, escape all of them. 135 * - If '{' and '}' are translated to some other characters, those 136 * characters must in turn be escaped when they occur in an RDN. 137 */ 138 #ifndef LDIF_NEED_ESCAPE 139 #define LDIF_NEED_ESCAPE(c) \ 140 ((LDIF_UNSAFE_CHAR(c)) || \ 141 LDIF_MAYBE_UNSAFE(c, LDIF_ESCAPE_CHAR) || \ 142 LDIF_MAYBE_UNSAFE(c, LDIF_FILETYPE_SEP) || \ 143 LDIF_MAYBE_UNSAFE(c, IX_FSL) || \ 144 (IX_FSR != IX_FSL && LDIF_MAYBE_UNSAFE(c, IX_FSR))) 145 #endif 146 /* 147 * Helper macro for LDIF_NEED_ESCAPE(): Treat character x as unsafe if 148 * back-ldif does not already treat is specially. 149 */ 150 #define LDIF_MAYBE_UNSAFE(c, x) \ 151 (!(LDIF_UNSAFE_CHAR(x) || (x) == '\\' || (x) == IX_DNL || (x) == IX_DNR) \ 152 && (c) == (x)) 153 154 /* Collect other "safe char" tests here, until someone needs a fix. */ 155 enum { 156 eq_unsafe = LDIF_UNSAFE_CHAR('='), 157 safe_filenames = STRLENOF("" LDAP_DIRSEP "") == 1 && !( 158 LDIF_UNSAFE_CHAR('-') || /* for "{-1}frontend" in bconfig.c */ 159 LDIF_UNSAFE_CHAR(LDIF_ESCAPE_CHAR) || 160 LDIF_UNSAFE_CHAR(IX_FSL) || LDIF_UNSAFE_CHAR(IX_FSR)) 161 }; 162 /* Sanity check: Try to force a compilation error if !safe_filenames */ 163 typedef struct { 164 int assert_safe_filenames : safe_filenames ? 2 : -2; 165 } assert_safe_filenames[safe_filenames ? 2 : -2]; 166 167 168 static ConfigTable ldifcfg[] = { 169 { "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET, 170 (void *)offsetof(struct ldif_info, li_base_path), 171 "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' " 172 "DESC 'Directory for database content' " 173 "EQUALITY caseIgnoreMatch " 174 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 175 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 176 NULL, NULL, NULL, NULL } 177 }; 178 179 static ConfigOCs ldifocs[] = { 180 { "( OLcfgDbOc:2.1 " 181 "NAME 'olcLdifConfig' " 182 "DESC 'LDIF backend configuration' " 183 "SUP olcDatabaseConfig " 184 "MUST ( olcDbDirectory ) )", Cft_Database, ldifcfg }, 185 { NULL, 0, NULL } 186 }; 187 188 189 /* 190 * Handle file/directory names. 191 */ 192 193 /* Set *res = LDIF filename path for the normalized DN */ 194 static int 195 ndn2path( Operation *op, struct berval *dn, struct berval *res, int empty_ok ) 196 { 197 BackendDB *be = op->o_bd; 198 struct ldif_info *li = (struct ldif_info *) be->be_private; 199 struct berval *suffixdn = &be->be_nsuffix[0]; 200 const char *start, *end, *next, *p; 201 char ch, *ptr; 202 ber_len_t len; 203 static const char hex[] = "0123456789ABCDEF"; 204 205 assert( dn != NULL ); 206 assert( !BER_BVISNULL( dn ) ); 207 assert( suffixdn != NULL ); 208 assert( !BER_BVISNULL( suffixdn ) ); 209 assert( dnIsSuffix( dn, suffixdn ) ); 210 211 if ( dn->bv_len == 0 && !empty_ok ) { 212 return LDAP_UNWILLING_TO_PERFORM; 213 } 214 215 start = dn->bv_val; 216 end = start + dn->bv_len; 217 218 /* Room for dir, dirsep, dn, LDIF, "\hexpair"-escaping of unsafe chars */ 219 len = li->li_base_path.bv_len + dn->bv_len + (1 + STRLENOF( LDIF )); 220 for ( p = start; p < end; ) { 221 ch = *p++; 222 if ( LDIF_NEED_ESCAPE( ch ) ) 223 len += 2; 224 } 225 res->bv_val = ch_malloc( len + 1 ); 226 227 ptr = lutil_strcopy( res->bv_val, li->li_base_path.bv_val ); 228 for ( next = end - suffixdn->bv_len; end > start; end = next ) { 229 /* Set p = start of DN component, next = &',' or start of DN */ 230 while ( (p = next) > start ) { 231 --next; 232 if ( DN_SEPARATOR( *next ) ) 233 break; 234 } 235 /* Append <dirsep> <p..end-1: RDN or database-suffix> */ 236 for ( *ptr++ = LDAP_DIRSEP[0]; p < end; *ptr++ = ch ) { 237 ch = *p++; 238 if ( LDIF_ESCAPE_CHAR != '\\' && ch == '\\' ) { 239 ch = LDIF_ESCAPE_CHAR; 240 } else if ( IX_FSL != IX_DNL && ch == IX_DNL ) { 241 ch = IX_FSL; 242 } else if ( IX_FSR != IX_DNR && ch == IX_DNR ) { 243 ch = IX_FSR; 244 } else if ( LDIF_NEED_ESCAPE( ch ) ) { 245 *ptr++ = LDIF_ESCAPE_CHAR; 246 *ptr++ = hex[(ch & 0xFFU) >> 4]; 247 ch = hex[ch & 0x0FU]; 248 } 249 } 250 } 251 ptr = lutil_strcopy( ptr, LDIF ); 252 res->bv_len = ptr - res->bv_val; 253 254 assert( res->bv_len <= len ); 255 256 return LDAP_SUCCESS; 257 } 258 259 /* 260 * *dest = dupbv(<dir + LDAP_DIRSEP>), plus room for <more>-sized filename. 261 * Return pointer past the dirname. 262 */ 263 static char * 264 fullpath_alloc( struct berval *dest, const struct berval *dir, ber_len_t more ) 265 { 266 char *s = SLAP_MALLOC( dir->bv_len + more + 2 ); 267 268 dest->bv_val = s; 269 if ( s == NULL ) { 270 dest->bv_len = 0; 271 Debug( LDAP_DEBUG_ANY, "back-ldif: out of memory\n", 0, 0, 0 ); 272 } else { 273 s = lutil_strcopy( dest->bv_val, dir->bv_val ); 274 *s++ = LDAP_DIRSEP[0]; 275 *s = '\0'; 276 dest->bv_len = s - dest->bv_val; 277 } 278 return s; 279 } 280 281 /* 282 * Append filename to fullpath_alloc() dirname or replace previous filename. 283 * dir_end = fullpath_alloc() return value. 284 */ 285 #define FILL_PATH(fpath, dir_end, filename) \ 286 ((fpath)->bv_len = lutil_strcopy(dir_end, filename) - (fpath)->bv_val) 287 288 289 /* .ldif entry filename length <-> subtree dirname length. */ 290 #define ldif2dir_len(bv) ((bv).bv_len -= STRLENOF(LDIF)) 291 #define dir2ldif_len(bv) ((bv).bv_len += STRLENOF(LDIF)) 292 /* .ldif entry filename <-> subtree dirname, both with dirname length. */ 293 #define ldif2dir_name(bv) ((bv).bv_val[(bv).bv_len] = '\0') 294 #define dir2ldif_name(bv) ((bv).bv_val[(bv).bv_len] = LDIF_FILETYPE_SEP) 295 296 /* Get the parent directory path, plus the LDIF suffix overwritten by a \0. */ 297 static int 298 get_parent_path( struct berval *dnpath, struct berval *res ) 299 { 300 ber_len_t i = dnpath->bv_len; 301 302 while ( i > 0 && dnpath->bv_val[ --i ] != LDAP_DIRSEP[0] ) ; 303 if ( res == NULL ) { 304 res = dnpath; 305 } else { 306 res->bv_val = SLAP_MALLOC( i + 1 + STRLENOF(LDIF) ); 307 if ( res->bv_val == NULL ) 308 return LDAP_OTHER; 309 AC_MEMCPY( res->bv_val, dnpath->bv_val, i ); 310 } 311 res->bv_len = i; 312 strcpy( res->bv_val + i, LDIF ); 313 res->bv_val[i] = '\0'; 314 return LDAP_SUCCESS; 315 } 316 317 /* Make temporary filename pattern for mkstemp() based on dnpath. */ 318 static char * 319 ldif_tempname( const struct berval *dnpath ) 320 { 321 static const char suffix[] = ".XXXXXX"; 322 ber_len_t len = dnpath->bv_len - STRLENOF( LDIF ); 323 char *name = SLAP_MALLOC( len + sizeof( suffix ) ); 324 325 if ( name != NULL ) { 326 AC_MEMCPY( name, dnpath->bv_val, len ); 327 strcpy( name + len, suffix ); 328 } 329 return name; 330 } 331 332 /* CRC-32 table for the polynomial: 333 * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. 334 * 335 * As used by zlib 336 */ 337 338 static const ber_uint_t crctab[256] = { 339 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 340 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 341 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 342 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 343 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 344 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 345 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 346 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 347 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 348 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 349 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 350 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 351 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 352 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 353 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 354 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 355 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 356 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 357 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 358 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 359 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 360 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 361 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 362 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 363 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 364 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 365 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 366 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 367 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 368 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 369 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 370 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 371 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 372 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 373 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 374 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 375 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 376 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 377 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 378 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 379 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 380 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 381 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 382 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 383 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 384 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 385 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 386 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 387 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 388 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 389 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 390 0x2d02ef8dL 391 }; 392 393 #define CRC1 crc = crctab[(crc ^ *buf++) & 0xff] ^ (crc >> 8) 394 #define CRC8 CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1 395 unsigned int 396 crc32(const void *vbuf, int len) 397 { 398 const unsigned char *buf = vbuf; 399 ber_uint_t crc = 0xffffffff; 400 int i; 401 402 while (len > 7) { 403 CRC8; 404 len -= 8; 405 } 406 while (len) { 407 CRC1; 408 len--; 409 } 410 411 return crc ^ 0xffffffff; 412 } 413 414 /* 415 * Read a file, or stat() it if datap == NULL. Allocate and fill *datap. 416 * Return LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT (no such file), or another error. 417 */ 418 static int 419 ldif_read_file( const char *path, char **datap ) 420 { 421 int rc = LDAP_SUCCESS, fd, len; 422 int res = -1; /* 0:success, <0:error, >0:file too big/growing. */ 423 struct stat st; 424 char *data = NULL, *ptr = NULL; 425 const char *msg; 426 427 if ( datap == NULL ) { 428 res = stat( path, &st ); 429 goto done; 430 } 431 fd = open( path, O_RDONLY ); 432 if ( fd >= 0 ) { 433 if ( fstat( fd, &st ) == 0 ) { 434 if ( st.st_size > INT_MAX - 2 ) { 435 res = 1; 436 } else { 437 len = st.st_size + 1; /* +1 detects file size > st.st_size */ 438 *datap = data = ptr = SLAP_MALLOC( len + 1 ); 439 if ( ptr != NULL ) { 440 while ( len && (res = read( fd, ptr, len )) ) { 441 if ( res > 0 ) { 442 len -= res; 443 ptr += res; 444 } else if ( errno != EINTR ) { 445 break; 446 } 447 } 448 *ptr = '\0'; 449 } 450 } 451 } 452 if ( close( fd ) < 0 ) 453 res = -1; 454 } 455 456 done: 457 if ( res == 0 ) { 458 #ifdef LDAP_DEBUG 459 msg = "entry file exists"; 460 if ( datap ) { 461 msg = "read entry file"; 462 len = ptr - data; 463 ptr = strstr( data, "\n# CRC32" ); 464 if (!ptr) { 465 msg = "read entry file without checksum"; 466 } else { 467 unsigned int crc1 = 0, crc2 = 1; 468 if ( sscanf( ptr + 9, "%08x", &crc1) == 1) { 469 ptr = strchr(ptr+1, '\n'); 470 if ( ptr ) { 471 ptr++; 472 len -= (ptr - data); 473 crc2 = crc32( ptr, len ); 474 } 475 } 476 if ( crc1 != crc2 ) { 477 Debug( LDAP_DEBUG_ANY, "ldif_read_file: checksum error on \"%s\"\n", 478 path, 0, 0 ); 479 return rc; 480 } 481 } 482 } 483 Debug( LDAP_DEBUG_TRACE, "ldif_read_file: %s: \"%s\"\n", msg, path, 0 ); 484 #endif /* LDAP_DEBUG */ 485 } else { 486 if ( res < 0 && errno == ENOENT ) { 487 Debug( LDAP_DEBUG_TRACE, "ldif_read_file: " 488 "no entry file \"%s\"\n", path, 0, 0 ); 489 rc = LDAP_NO_SUCH_OBJECT; 490 } else { 491 msg = res < 0 ? STRERROR( errno ) : "bad stat() size"; 492 Debug( LDAP_DEBUG_ANY, "ldif_read_file: %s for \"%s\"\n", 493 msg, path, 0 ); 494 rc = LDAP_OTHER; 495 } 496 if ( data != NULL ) 497 SLAP_FREE( data ); 498 } 499 return rc; 500 } 501 502 /* 503 * return nonnegative for success or -1 for error 504 * do not return numbers less than -1 505 */ 506 static int 507 spew_file( int fd, const char *spew, int len, int *save_errno ) 508 { 509 int writeres; 510 #define HEADER "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n" 511 char header[sizeof(HEADER "# CRC32 12345678\n")]; 512 513 sprintf(header, HEADER "# CRC32 %08x\n", crc32(spew, len)); 514 writeres = write_data(fd, header, sizeof(header)-1, save_errno); 515 return writeres < 0 ? writeres : write_data(fd, spew, len, save_errno); 516 } 517 518 static int 519 write_data( int fd, const char *spew, int len, int *save_errno ) 520 { 521 int writeres = 0; 522 while(len > 0) { 523 writeres = write(fd, spew, len); 524 if(writeres == -1) { 525 *save_errno = errno; 526 if (*save_errno != EINTR) 527 break; 528 } 529 else { 530 spew += writeres; 531 len -= writeres; 532 } 533 } 534 return writeres; 535 } 536 537 /* Write an entry LDIF file. Create parentdir first if non-NULL. */ 538 static int 539 ldif_write_entry( 540 Operation *op, 541 Entry *e, 542 const struct berval *path, 543 const char *parentdir, 544 const char **text ) 545 { 546 int rc = LDAP_OTHER, res, save_errno = 0; 547 int fd, entry_length; 548 char *entry_as_string, *tmpfname; 549 550 if ( op->o_abandon ) 551 return SLAPD_ABANDON; 552 553 if ( parentdir != NULL && mkdir( parentdir, 0750 ) < 0 ) { 554 save_errno = errno; 555 Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n", 556 "cannot create parent directory", 557 parentdir, STRERROR( save_errno ) ); 558 *text = "internal error (cannot create parent directory)"; 559 return rc; 560 } 561 562 tmpfname = ldif_tempname( path ); 563 fd = tmpfname == NULL ? -1 : mkstemp( tmpfname ); 564 if ( fd < 0 ) { 565 save_errno = errno; 566 Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s for \"%s\": %s\n", 567 "cannot create file", e->e_dn, STRERROR( save_errno ) ); 568 *text = "internal error (cannot create file)"; 569 570 } else { 571 ber_len_t dn_len = e->e_name.bv_len; 572 struct berval rdn; 573 574 /* Only save the RDN onto disk */ 575 dnRdn( &e->e_name, &rdn ); 576 if ( rdn.bv_len != dn_len ) { 577 e->e_name.bv_val[rdn.bv_len] = '\0'; 578 e->e_name.bv_len = rdn.bv_len; 579 } 580 581 res = -2; 582 ldap_pvt_thread_mutex_lock( &entry2str_mutex ); 583 entry_as_string = entry2str( e, &entry_length ); 584 if ( entry_as_string != NULL ) 585 res = spew_file( fd, entry_as_string, entry_length, &save_errno ); 586 ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); 587 588 /* Restore full DN */ 589 if ( rdn.bv_len != dn_len ) { 590 e->e_name.bv_val[rdn.bv_len] = ','; 591 e->e_name.bv_len = dn_len; 592 } 593 594 if ( close( fd ) < 0 && res >= 0 ) { 595 res = -1; 596 save_errno = errno; 597 } 598 599 if ( res >= 0 ) { 600 if ( move_file( tmpfname, path->bv_val ) == 0 ) { 601 Debug( LDAP_DEBUG_TRACE, "ldif_write_entry: " 602 "wrote entry \"%s\"\n", e->e_name.bv_val, 0, 0 ); 603 rc = LDAP_SUCCESS; 604 } else { 605 save_errno = errno; 606 Debug( LDAP_DEBUG_ANY, "ldif_write_entry: " 607 "could not put entry file for \"%s\" in place: %s\n", 608 e->e_name.bv_val, STRERROR( save_errno ), 0 ); 609 *text = "internal error (could not put entry file in place)"; 610 } 611 } else if ( res == -1 ) { 612 Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n", 613 "write error to", tmpfname, STRERROR( save_errno ) ); 614 *text = "internal error (write error to entry file)"; 615 } 616 617 if ( rc != LDAP_SUCCESS ) { 618 unlink( tmpfname ); 619 } 620 } 621 622 if ( tmpfname ) 623 SLAP_FREE( tmpfname ); 624 return rc; 625 } 626 627 /* 628 * Read the entry at path, or if entryp==NULL just see if it exists. 629 * pdn and pndn are the parent's DN and normalized DN, or both NULL. 630 * Return an LDAP result code. 631 */ 632 static int 633 ldif_read_entry( 634 Operation *op, 635 const char *path, 636 struct berval *pdn, 637 struct berval *pndn, 638 Entry **entryp, 639 const char **text ) 640 { 641 int rc; 642 Entry *entry; 643 char *entry_as_string; 644 struct berval rdn; 645 646 /* TODO: Does slapd prevent Abandon of Bind as per rfc4511? 647 * If so we need not check for LDAP_REQ_BIND here. 648 */ 649 if ( op->o_abandon && op->o_tag != LDAP_REQ_BIND ) 650 return SLAPD_ABANDON; 651 652 rc = ldif_read_file( path, entryp ? &entry_as_string : NULL ); 653 654 switch ( rc ) { 655 case LDAP_SUCCESS: 656 if ( entryp == NULL ) 657 break; 658 *entryp = entry = str2entry( entry_as_string ); 659 SLAP_FREE( entry_as_string ); 660 if ( entry == NULL ) { 661 rc = LDAP_OTHER; 662 if ( text != NULL ) 663 *text = "internal error (cannot parse some entry file)"; 664 break; 665 } 666 if ( pdn == NULL || BER_BVISEMPTY( pdn ) ) 667 break; 668 /* Append parent DN to DN from LDIF file */ 669 rdn = entry->e_name; 670 build_new_dn( &entry->e_name, pdn, &rdn, NULL ); 671 SLAP_FREE( rdn.bv_val ); 672 rdn = entry->e_nname; 673 build_new_dn( &entry->e_nname, pndn, &rdn, NULL ); 674 SLAP_FREE( rdn.bv_val ); 675 break; 676 677 case LDAP_OTHER: 678 if ( text != NULL ) 679 *text = entryp 680 ? "internal error (cannot read some entry file)" 681 : "internal error (cannot stat some entry file)"; 682 break; 683 } 684 685 return rc; 686 } 687 688 /* 689 * Read the operation's entry, or if entryp==NULL just see if it exists. 690 * Return an LDAP result code. May set *text to a message on failure. 691 * If pathp is non-NULL, set it to the entry filename on success. 692 */ 693 static int 694 get_entry( 695 Operation *op, 696 Entry **entryp, 697 struct berval *pathp, 698 const char **text ) 699 { 700 int rc; 701 struct berval path, pdn, pndn; 702 703 dnParent( &op->o_req_dn, &pdn ); 704 dnParent( &op->o_req_ndn, &pndn ); 705 rc = ndn2path( op, &op->o_req_ndn, &path, 0 ); 706 if ( rc != LDAP_SUCCESS ) { 707 goto done; 708 } 709 710 rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, entryp, text ); 711 712 if ( rc == LDAP_SUCCESS && pathp != NULL ) { 713 *pathp = path; 714 } else { 715 SLAP_FREE( path.bv_val ); 716 } 717 done: 718 return rc; 719 } 720 721 722 /* 723 * RDN-named directory entry, with special handling of "attr={num}val" RDNs. 724 * For sorting, filename "attr=val.ldif" is truncated to "attr="val\0ldif", 725 * and filename "attr={num}val.ldif" to "attr={\0um}val.ldif". 726 * Does not sort escaped chars correctly, would need to un-escape them. 727 */ 728 typedef struct bvlist { 729 struct bvlist *next; 730 char *trunc; /* filename was truncated here */ 731 int inum; /* num from "attr={num}" in filename, or INT_MIN */ 732 char savech; /* original char at *trunc */ 733 /* BVL_NAME(&bvlist) is the filename, allocated after the struct: */ 734 # define BVL_NAME(bvl) ((char *) ((bvl) + 1)) 735 # define BVL_SIZE(namelen) (sizeof(bvlist) + (namelen) + 1) 736 } bvlist; 737 738 static int 739 ldif_send_entry( Operation *op, SlapReply *rs, Entry *e, int scope ) 740 { 741 int rc = LDAP_SUCCESS; 742 743 if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) { 744 if ( rs == NULL ) { 745 /* Save the entry for tool mode */ 746 struct ldif_tool *tl = 747 &((struct ldif_info *) op->o_bd->be_private)->li_tool; 748 749 if ( tl->ecount >= tl->elen ) { 750 /* Allocate/grow entries */ 751 ID elen = tl->elen ? tl->elen * 2 : ENTRY_BUFF_INCREMENT; 752 Entry **entries = (Entry **) SLAP_REALLOC( tl->entries, 753 sizeof(Entry *) * elen ); 754 if ( entries == NULL ) { 755 Debug( LDAP_DEBUG_ANY, 756 "ldif_send_entry: out of memory\n", 0, 0, 0 ); 757 rc = LDAP_OTHER; 758 goto done; 759 } 760 tl->elen = elen; 761 tl->entries = entries; 762 } 763 tl->entries[tl->ecount++] = e; 764 return rc; 765 } 766 767 else if ( !get_manageDSAit( op ) && is_entry_referral( e ) ) { 768 /* Send a continuation reference. 769 * (ldif_back_referrals() handles baseobject referrals.) 770 * Don't check the filter since it's only a candidate. 771 */ 772 BerVarray refs = get_entry_referrals( op, e ); 773 rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope ); 774 rs->sr_entry = e; 775 rc = send_search_reference( op, rs ); 776 ber_bvarray_free( rs->sr_ref ); 777 ber_bvarray_free( refs ); 778 rs->sr_ref = NULL; 779 rs->sr_entry = NULL; 780 } 781 782 else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { 783 rs->sr_entry = e; 784 rs->sr_attrs = op->ors_attrs; 785 /* Could set REP_ENTRY_MUSTBEFREED too for efficiency, 786 * but refraining lets us test unFREEable MODIFIABLE 787 * entries. Like entries built on the stack. 788 */ 789 rs->sr_flags = REP_ENTRY_MODIFIABLE; 790 rc = send_search_entry( op, rs ); 791 rs->sr_entry = NULL; 792 rs->sr_attrs = NULL; 793 } 794 } 795 796 done: 797 entry_free( e ); 798 return rc; 799 } 800 801 /* Read LDIF directory <path> into <listp>. Set *fname_maxlenp. */ 802 static int 803 ldif_readdir( 804 Operation *op, 805 SlapReply *rs, 806 const struct berval *path, 807 bvlist **listp, 808 ber_len_t *fname_maxlenp ) 809 { 810 int rc = LDAP_SUCCESS; 811 DIR *dir_of_path; 812 813 *listp = NULL; 814 *fname_maxlenp = 0; 815 816 dir_of_path = opendir( path->bv_val ); 817 if ( dir_of_path == NULL ) { 818 int save_errno = errno; 819 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 820 int is_rootDSE = (path->bv_len == li->li_base_path.bv_len); 821 822 /* Absent directory is OK (leaf entry), except the database dir */ 823 if ( is_rootDSE || save_errno != ENOENT ) { 824 Debug( LDAP_DEBUG_ANY, 825 "=> ldif_search_entry: failed to opendir \"%s\": %s\n", 826 path->bv_val, STRERROR( save_errno ), 0 ); 827 rc = LDAP_OTHER; 828 if ( rs != NULL ) 829 rs->sr_text = 830 save_errno != ENOENT ? "internal error (bad directory)" 831 : !is_rootDSE ? "internal error (missing directory)" 832 : "internal error (database directory does not exist)"; 833 } 834 835 } else { 836 bvlist *ptr; 837 struct dirent *dir; 838 int save_errno = 0; 839 840 while ( (dir = readdir( dir_of_path )) != NULL ) { 841 size_t fname_len; 842 bvlist *bvl, **prev; 843 char *trunc, *idxp, *endp, *endp2; 844 845 fname_len = strlen( dir->d_name ); 846 if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */ 847 continue; 848 if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF )) 849 continue; 850 851 if ( *fname_maxlenp < fname_len ) 852 *fname_maxlenp = fname_len; 853 854 bvl = SLAP_MALLOC( BVL_SIZE( fname_len ) ); 855 if ( bvl == NULL ) { 856 rc = LDAP_OTHER; 857 save_errno = errno; 858 break; 859 } 860 strcpy( BVL_NAME( bvl ), dir->d_name ); 861 862 /* Make it sortable by ("attr=val" or <preceding {num}, num>) */ 863 trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF ); 864 if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL && 865 (endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp && 866 (eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) ) 867 { 868 /* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */ 869 bvl->inum = strtol( idxp, &endp2, 10 ); 870 if ( endp2 == endp ) { 871 trunc = idxp; 872 goto truncate; 873 } 874 } 875 bvl->inum = INT_MIN; 876 truncate: 877 bvl->trunc = trunc; 878 bvl->savech = *trunc; 879 *trunc = '\0'; 880 881 /* Insertion sort */ 882 for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) { 883 int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr )); 884 if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) ) 885 break; 886 } 887 *prev = bvl; 888 bvl->next = ptr; 889 } 890 891 if ( closedir( dir_of_path ) < 0 ) { 892 save_errno = errno; 893 rc = LDAP_OTHER; 894 if ( rs != NULL ) 895 rs->sr_text = "internal error (bad directory)"; 896 } 897 if ( rc != LDAP_SUCCESS ) { 898 Debug( LDAP_DEBUG_ANY, "ldif_search_entry: %s \"%s\": %s\n", 899 "error reading directory", path->bv_val, 900 STRERROR( save_errno ) ); 901 } 902 } 903 904 return rc; 905 } 906 907 /* 908 * Send an entry, recursively search its children, and free or save it. 909 * Return an LDAP result code. Parameters: 910 * op, rs operation and reply. rs == NULL for slap tools. 911 * e entry to search, or NULL for rootDSE. 912 * scope scope for the part of the search from this entry. 913 * path LDIF filename -- bv_len and non-directory part are overwritten. 914 */ 915 static int 916 ldif_search_entry( 917 Operation *op, 918 SlapReply *rs, 919 Entry *e, 920 int scope, 921 struct berval *path ) 922 { 923 int rc = LDAP_SUCCESS; 924 struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" ); 925 926 if ( scope != LDAP_SCOPE_BASE && e != NULL ) { 927 /* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE, 928 * which bconfig.c seems to need. (TODO: see config_rename_one.) 929 */ 930 if ( ber_dupbv( &dn, &e->e_name ) == NULL || 931 ber_dupbv( &ndn, &e->e_nname ) == NULL ) 932 { 933 Debug( LDAP_DEBUG_ANY, 934 "ldif_search_entry: out of memory\n", 0, 0, 0 ); 935 rc = LDAP_OTHER; 936 goto done; 937 } 938 } 939 940 /* Send the entry if appropriate, and free or save it */ 941 if ( e != NULL ) 942 rc = ldif_send_entry( op, rs, e, scope ); 943 944 /* Search the children */ 945 if ( scope != LDAP_SCOPE_BASE && rc == LDAP_SUCCESS ) { 946 bvlist *list, *ptr; 947 struct berval fpath; /* becomes child pathname */ 948 char *dir_end; /* will point past dirname in fpath */ 949 950 ldif2dir_len( *path ); 951 ldif2dir_name( *path ); 952 rc = ldif_readdir( op, rs, path, &list, &fpath.bv_len ); 953 954 if ( list != NULL ) { 955 const char **text = rs == NULL ? NULL : &rs->sr_text; 956 957 if ( scope == LDAP_SCOPE_ONELEVEL ) 958 scope = LDAP_SCOPE_BASE; 959 else if ( scope == LDAP_SCOPE_SUBORDINATE ) 960 scope = LDAP_SCOPE_SUBTREE; 961 962 /* Allocate fpath and fill in directory part */ 963 dir_end = fullpath_alloc( &fpath, path, fpath.bv_len ); 964 if ( dir_end == NULL ) 965 rc = LDAP_OTHER; 966 967 do { 968 ptr = list; 969 970 if ( rc == LDAP_SUCCESS ) { 971 *ptr->trunc = ptr->savech; 972 FILL_PATH( &fpath, dir_end, BVL_NAME( ptr )); 973 974 rc = ldif_read_entry( op, fpath.bv_val, &dn, &ndn, 975 &e, text ); 976 switch ( rc ) { 977 case LDAP_SUCCESS: 978 rc = ldif_search_entry( op, rs, e, scope, &fpath ); 979 break; 980 case LDAP_NO_SUCH_OBJECT: 981 /* Only the search baseDN may produce noSuchObject. */ 982 rc = LDAP_OTHER; 983 if ( rs != NULL ) 984 rs->sr_text = "internal error " 985 "(did someone just remove an entry file?)"; 986 Debug( LDAP_DEBUG_ANY, "ldif_search_entry: " 987 "file listed in parent directory does not exist: " 988 "\"%s\"\n", fpath.bv_val, 0, 0 ); 989 break; 990 } 991 } 992 993 list = ptr->next; 994 SLAP_FREE( ptr ); 995 } while ( list != NULL ); 996 997 if ( !BER_BVISNULL( &fpath ) ) 998 SLAP_FREE( fpath.bv_val ); 999 } 1000 } 1001 1002 done: 1003 if ( !BER_BVISEMPTY( &dn ) ) 1004 ber_memfree( dn.bv_val ); 1005 if ( !BER_BVISEMPTY( &ndn ) ) 1006 ber_memfree( ndn.bv_val ); 1007 return rc; 1008 } 1009 1010 static int 1011 search_tree( Operation *op, SlapReply *rs ) 1012 { 1013 int rc = LDAP_SUCCESS; 1014 Entry *e = NULL; 1015 struct berval path; 1016 struct berval pdn, pndn; 1017 1018 (void) ndn2path( op, &op->o_req_ndn, &path, 1 ); 1019 if ( !BER_BVISEMPTY( &op->o_req_ndn ) ) { 1020 /* Read baseObject */ 1021 dnParent( &op->o_req_dn, &pdn ); 1022 dnParent( &op->o_req_ndn, &pndn ); 1023 rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, &e, 1024 rs == NULL ? NULL : &rs->sr_text ); 1025 } 1026 if ( rc == LDAP_SUCCESS ) 1027 rc = ldif_search_entry( op, rs, e, op->ors_scope, &path ); 1028 1029 ch_free( path.bv_val ); 1030 return rc; 1031 } 1032 1033 1034 /* 1035 * Prepare to create or rename an entry: 1036 * Check that the entry does not already exist. 1037 * Check that the parent entry exists and can have subordinates, 1038 * unless need_dir is NULL or adding the suffix entry. 1039 * 1040 * Return an LDAP result code. May set *text to a message on failure. 1041 * If success, set *dnpath to LDIF entry path and *need_dir to 1042 * (directory must be created ? dirname : NULL). 1043 */ 1044 static int 1045 ldif_prepare_create( 1046 Operation *op, 1047 Entry *e, 1048 struct berval *dnpath, 1049 char **need_dir, 1050 const char **text ) 1051 { 1052 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1053 struct berval *ndn = &e->e_nname; 1054 struct berval ppath = BER_BVNULL; 1055 struct stat st; 1056 Entry *parent = NULL; 1057 int rc; 1058 1059 if ( op->o_abandon ) 1060 return SLAPD_ABANDON; 1061 1062 rc = ndn2path( op, ndn, dnpath, 0 ); 1063 if ( rc != LDAP_SUCCESS ) { 1064 return rc; 1065 } 1066 1067 if ( stat( dnpath->bv_val, &st ) == 0 ) { /* entry .ldif file */ 1068 rc = LDAP_ALREADY_EXISTS; 1069 1070 } else if ( errno != ENOENT ) { 1071 Debug( LDAP_DEBUG_ANY, 1072 "ldif_prepare_create: cannot stat \"%s\": %s\n", 1073 dnpath->bv_val, STRERROR( errno ), 0 ); 1074 rc = LDAP_OTHER; 1075 *text = "internal error (cannot check entry file)"; 1076 1077 } else if ( need_dir != NULL ) { 1078 *need_dir = NULL; 1079 rc = get_parent_path( dnpath, &ppath ); 1080 /* If parent dir exists, so does parent .ldif: 1081 * The directory gets created after and removed before the .ldif. 1082 * Except with the database directory, which has no matching entry. 1083 */ 1084 if ( rc == LDAP_SUCCESS && stat( ppath.bv_val, &st ) < 0 ) { 1085 rc = errno == ENOENT && ppath.bv_len > li->li_base_path.bv_len 1086 ? LDAP_NO_SUCH_OBJECT : LDAP_OTHER; 1087 } 1088 switch ( rc ) { 1089 case LDAP_NO_SUCH_OBJECT: 1090 /* No parent dir, check parent .ldif */ 1091 dir2ldif_name( ppath ); 1092 rc = ldif_read_entry( op, ppath.bv_val, NULL, NULL, 1093 (op->o_tag != LDAP_REQ_ADD || get_manageDSAit( op ) 1094 ? &parent : NULL), 1095 text ); 1096 switch ( rc ) { 1097 case LDAP_SUCCESS: 1098 /* Check that parent is not a referral, unless 1099 * ldif_back_referrals() already checked. 1100 */ 1101 if ( parent != NULL ) { 1102 int is_ref = is_entry_referral( parent ); 1103 entry_free( parent ); 1104 if ( is_ref ) { 1105 rc = LDAP_AFFECTS_MULTIPLE_DSAS; 1106 *text = op->o_tag == LDAP_REQ_MODDN 1107 ? "newSuperior is a referral object" 1108 : "parent is a referral object"; 1109 break; 1110 } 1111 } 1112 /* Must create parent directory. */ 1113 ldif2dir_name( ppath ); 1114 *need_dir = ppath.bv_val; 1115 break; 1116 case LDAP_NO_SUCH_OBJECT: 1117 *text = op->o_tag == LDAP_REQ_MODDN 1118 ? "newSuperior object does not exist" 1119 : "parent does not exist"; 1120 break; 1121 } 1122 break; 1123 case LDAP_OTHER: 1124 Debug( LDAP_DEBUG_ANY, 1125 "ldif_prepare_create: cannot stat \"%s\" parent dir: %s\n", 1126 ndn->bv_val, STRERROR( errno ), 0 ); 1127 *text = "internal error (cannot stat parent dir)"; 1128 break; 1129 } 1130 if ( *need_dir == NULL && ppath.bv_val != NULL ) 1131 SLAP_FREE( ppath.bv_val ); 1132 } 1133 1134 if ( rc != LDAP_SUCCESS ) { 1135 SLAP_FREE( dnpath->bv_val ); 1136 BER_BVZERO( dnpath ); 1137 } 1138 return rc; 1139 } 1140 1141 static int 1142 apply_modify_to_entry( 1143 Entry *entry, 1144 Modifications *modlist, 1145 Operation *op, 1146 SlapReply *rs, 1147 char *textbuf ) 1148 { 1149 int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS; 1150 int is_oc = 0; 1151 Modification *mods; 1152 1153 if (!acl_check_modlist(op, entry, modlist)) { 1154 return LDAP_INSUFFICIENT_ACCESS; 1155 } 1156 1157 for (; modlist != NULL; modlist = modlist->sml_next) { 1158 mods = &modlist->sml_mod; 1159 1160 if ( mods->sm_desc == slap_schema.si_ad_objectClass ) { 1161 is_oc = 1; 1162 } 1163 switch (mods->sm_op) { 1164 case LDAP_MOD_ADD: 1165 rc = modify_add_values(entry, mods, 1166 get_permissiveModify(op), 1167 &rs->sr_text, textbuf, 1168 SLAP_TEXT_BUFLEN ); 1169 break; 1170 1171 case LDAP_MOD_DELETE: 1172 rc = modify_delete_values(entry, mods, 1173 get_permissiveModify(op), 1174 &rs->sr_text, textbuf, 1175 SLAP_TEXT_BUFLEN ); 1176 break; 1177 1178 case LDAP_MOD_REPLACE: 1179 rc = modify_replace_values(entry, mods, 1180 get_permissiveModify(op), 1181 &rs->sr_text, textbuf, 1182 SLAP_TEXT_BUFLEN ); 1183 break; 1184 1185 case LDAP_MOD_INCREMENT: 1186 rc = modify_increment_values( entry, 1187 mods, get_permissiveModify(op), 1188 &rs->sr_text, textbuf, 1189 SLAP_TEXT_BUFLEN ); 1190 break; 1191 1192 case SLAP_MOD_SOFTADD: 1193 mods->sm_op = LDAP_MOD_ADD; 1194 rc = modify_add_values(entry, mods, 1195 get_permissiveModify(op), 1196 &rs->sr_text, textbuf, 1197 SLAP_TEXT_BUFLEN ); 1198 mods->sm_op = SLAP_MOD_SOFTADD; 1199 if (rc == LDAP_TYPE_OR_VALUE_EXISTS) { 1200 rc = LDAP_SUCCESS; 1201 } 1202 break; 1203 1204 case SLAP_MOD_SOFTDEL: 1205 mods->sm_op = LDAP_MOD_DELETE; 1206 rc = modify_delete_values(entry, mods, 1207 get_permissiveModify(op), 1208 &rs->sr_text, textbuf, 1209 SLAP_TEXT_BUFLEN ); 1210 mods->sm_op = SLAP_MOD_SOFTDEL; 1211 if (rc == LDAP_NO_SUCH_ATTRIBUTE) { 1212 rc = LDAP_SUCCESS; 1213 } 1214 break; 1215 1216 case SLAP_MOD_ADD_IF_NOT_PRESENT: 1217 if ( attr_find( entry->e_attrs, mods->sm_desc ) ) { 1218 rc = LDAP_SUCCESS; 1219 break; 1220 } 1221 mods->sm_op = LDAP_MOD_ADD; 1222 rc = modify_add_values(entry, mods, 1223 get_permissiveModify(op), 1224 &rs->sr_text, textbuf, 1225 SLAP_TEXT_BUFLEN ); 1226 mods->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT; 1227 break; 1228 } 1229 if(rc != LDAP_SUCCESS) break; 1230 } 1231 1232 if ( rc == LDAP_SUCCESS ) { 1233 rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */ 1234 if ( is_oc ) { 1235 entry->e_ocflags = 0; 1236 } 1237 /* check that the entry still obeys the schema */ 1238 rc = entry_schema_check( op, entry, NULL, 0, 0, NULL, 1239 &rs->sr_text, textbuf, SLAP_TEXT_BUFLEN ); 1240 } 1241 1242 return rc; 1243 } 1244 1245 1246 static int 1247 ldif_back_referrals( Operation *op, SlapReply *rs ) 1248 { 1249 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1250 struct berval path, dn = op->o_req_dn, ndn = op->o_req_ndn; 1251 ber_len_t min_dnlen; 1252 Entry *entry = NULL, **entryp; 1253 BerVarray ref; 1254 int rc; 1255 1256 min_dnlen = op->o_bd->be_nsuffix[0].bv_len; 1257 if ( min_dnlen == 0 ) { 1258 /* Catch root DSE (empty DN), it is not a referral */ 1259 min_dnlen = 1; 1260 } 1261 if ( ndn2path( op, &ndn, &path, 0 ) != LDAP_SUCCESS ) { 1262 return LDAP_SUCCESS; /* Root DSE again */ 1263 } 1264 1265 entryp = get_manageDSAit( op ) ? NULL : &entry; 1266 ldap_pvt_thread_rdwr_rlock( &li->li_rdwr ); 1267 1268 for (;;) { 1269 dnParent( &dn, &dn ); 1270 dnParent( &ndn, &ndn ); 1271 rc = ldif_read_entry( op, path.bv_val, &dn, &ndn, 1272 entryp, &rs->sr_text ); 1273 if ( rc != LDAP_NO_SUCH_OBJECT ) 1274 break; 1275 1276 rc = LDAP_SUCCESS; 1277 if ( ndn.bv_len < min_dnlen ) 1278 break; 1279 (void) get_parent_path( &path, NULL ); 1280 dir2ldif_name( path ); 1281 entryp = &entry; 1282 } 1283 1284 ldap_pvt_thread_rdwr_runlock( &li->li_rdwr ); 1285 SLAP_FREE( path.bv_val ); 1286 1287 if ( entry != NULL ) { 1288 if ( is_entry_referral( entry ) ) { 1289 Debug( LDAP_DEBUG_TRACE, 1290 "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n", 1291 (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_dn ); 1292 1293 ref = get_entry_referrals( op, entry ); 1294 rs->sr_ref = referral_rewrite( ref, &entry->e_name, &op->o_req_dn, 1295 op->o_tag == LDAP_REQ_SEARCH ? 1296 op->ors_scope : LDAP_SCOPE_DEFAULT ); 1297 ber_bvarray_free( ref ); 1298 1299 if ( rs->sr_ref != NULL ) { 1300 /* send referral */ 1301 rc = rs->sr_err = LDAP_REFERRAL; 1302 rs->sr_matched = entry->e_dn; 1303 send_ldap_result( op, rs ); 1304 ber_bvarray_free( rs->sr_ref ); 1305 rs->sr_ref = NULL; 1306 } else { 1307 rc = LDAP_OTHER; 1308 rs->sr_text = "bad referral object"; 1309 } 1310 rs->sr_matched = NULL; 1311 } 1312 1313 entry_free( entry ); 1314 } 1315 1316 return rc; 1317 } 1318 1319 1320 /* LDAP operations */ 1321 1322 static int 1323 ldif_back_bind( Operation *op, SlapReply *rs ) 1324 { 1325 struct ldif_info *li; 1326 Attribute *a; 1327 AttributeDescription *password = slap_schema.si_ad_userPassword; 1328 int return_val; 1329 Entry *entry = NULL; 1330 1331 switch ( be_rootdn_bind( op, rs ) ) { 1332 case SLAP_CB_CONTINUE: 1333 break; 1334 1335 default: 1336 /* in case of success, front end will send result; 1337 * otherwise, be_rootdn_bind() did */ 1338 return rs->sr_err; 1339 } 1340 1341 li = (struct ldif_info *) op->o_bd->be_private; 1342 ldap_pvt_thread_rdwr_rlock(&li->li_rdwr); 1343 return_val = get_entry(op, &entry, NULL, NULL); 1344 1345 /* no object is found for them */ 1346 if(return_val != LDAP_SUCCESS) { 1347 rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS; 1348 goto return_result; 1349 } 1350 1351 /* they don't have userpassword */ 1352 if((a = attr_find(entry->e_attrs, password)) == NULL) { 1353 rs->sr_err = LDAP_INAPPROPRIATE_AUTH; 1354 return_val = 1; 1355 goto return_result; 1356 } 1357 1358 /* authentication actually failed */ 1359 if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred, 1360 &rs->sr_text) != 0) { 1361 rs->sr_err = LDAP_INVALID_CREDENTIALS; 1362 return_val = 1; 1363 goto return_result; 1364 } 1365 1366 /* let the front-end send success */ 1367 return_val = LDAP_SUCCESS; 1368 1369 return_result: 1370 ldap_pvt_thread_rdwr_runlock(&li->li_rdwr); 1371 if(return_val != LDAP_SUCCESS) 1372 send_ldap_result( op, rs ); 1373 if(entry != NULL) 1374 entry_free(entry); 1375 return return_val; 1376 } 1377 1378 static int 1379 ldif_back_search( Operation *op, SlapReply *rs ) 1380 { 1381 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1382 1383 ldap_pvt_thread_rdwr_rlock(&li->li_rdwr); 1384 rs->sr_err = search_tree( op, rs ); 1385 ldap_pvt_thread_rdwr_runlock(&li->li_rdwr); 1386 send_ldap_result(op, rs); 1387 1388 return rs->sr_err; 1389 } 1390 1391 static int 1392 ldif_back_add( Operation *op, SlapReply *rs ) 1393 { 1394 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1395 Entry * e = op->ora_e; 1396 struct berval path; 1397 char *parentdir; 1398 char textbuf[SLAP_TEXT_BUFLEN]; 1399 int rc; 1400 1401 Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn, 0, 0 ); 1402 1403 rc = entry_schema_check( op, e, NULL, 0, 1, NULL, 1404 &rs->sr_text, textbuf, sizeof( textbuf ) ); 1405 if ( rc != LDAP_SUCCESS ) 1406 goto send_res; 1407 1408 rc = slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), 1 ); 1409 if ( rc != LDAP_SUCCESS ) 1410 goto send_res; 1411 1412 ldap_pvt_thread_mutex_lock( &li->li_modop_mutex ); 1413 1414 rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text ); 1415 if ( rc == LDAP_SUCCESS ) { 1416 ldap_pvt_thread_rdwr_wlock( &li->li_rdwr ); 1417 rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text ); 1418 ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr ); 1419 1420 SLAP_FREE( path.bv_val ); 1421 if ( parentdir != NULL ) 1422 SLAP_FREE( parentdir ); 1423 } 1424 1425 ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex ); 1426 1427 send_res: 1428 rs->sr_err = rc; 1429 Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n", 1430 rc, rs->sr_text ? rs->sr_text : "", 0 ); 1431 send_ldap_result( op, rs ); 1432 slap_graduate_commit_csn( op ); 1433 rs->sr_text = NULL; /* remove possible pointer to textbuf */ 1434 return rs->sr_err; 1435 } 1436 1437 static int 1438 ldif_back_modify( Operation *op, SlapReply *rs ) 1439 { 1440 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1441 Modifications * modlst = op->orm_modlist; 1442 struct berval path; 1443 Entry *entry; 1444 char textbuf[SLAP_TEXT_BUFLEN]; 1445 int rc; 1446 1447 slap_mods_opattrs( op, &op->orm_modlist, 1 ); 1448 1449 ldap_pvt_thread_mutex_lock( &li->li_modop_mutex ); 1450 1451 rc = get_entry( op, &entry, &path, &rs->sr_text ); 1452 if ( rc == LDAP_SUCCESS ) { 1453 rc = apply_modify_to_entry( entry, modlst, op, rs, textbuf ); 1454 if ( rc == LDAP_SUCCESS ) { 1455 ldap_pvt_thread_rdwr_wlock( &li->li_rdwr ); 1456 rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text ); 1457 ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr ); 1458 } 1459 1460 entry_free( entry ); 1461 SLAP_FREE( path.bv_val ); 1462 } 1463 1464 ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex ); 1465 1466 rs->sr_err = rc; 1467 send_ldap_result( op, rs ); 1468 slap_graduate_commit_csn( op ); 1469 rs->sr_text = NULL; /* remove possible pointer to textbuf */ 1470 return rs->sr_err; 1471 } 1472 1473 static int 1474 ldif_back_delete( Operation *op, SlapReply *rs ) 1475 { 1476 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1477 struct berval path; 1478 int rc = LDAP_SUCCESS; 1479 1480 if ( BER_BVISEMPTY( &op->o_csn )) { 1481 struct berval csn; 1482 char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE]; 1483 1484 csn.bv_val = csnbuf; 1485 csn.bv_len = sizeof( csnbuf ); 1486 slap_get_csn( op, &csn, 1 ); 1487 } 1488 1489 ldap_pvt_thread_mutex_lock( &li->li_modop_mutex ); 1490 ldap_pvt_thread_rdwr_wlock( &li->li_rdwr ); 1491 if ( op->o_abandon ) { 1492 rc = SLAPD_ABANDON; 1493 goto done; 1494 } 1495 1496 rc = ndn2path( op, &op->o_req_ndn, &path, 0 ); 1497 if ( rc != LDAP_SUCCESS ) { 1498 goto done; 1499 } 1500 1501 ldif2dir_len( path ); 1502 ldif2dir_name( path ); 1503 if ( rmdir( path.bv_val ) < 0 ) { 1504 switch ( errno ) { 1505 case ENOTEMPTY: 1506 rc = LDAP_NOT_ALLOWED_ON_NONLEAF; 1507 break; 1508 case ENOENT: 1509 /* is leaf, go on */ 1510 break; 1511 default: 1512 rc = LDAP_OTHER; 1513 rs->sr_text = "internal error (cannot delete subtree directory)"; 1514 break; 1515 } 1516 } 1517 1518 if ( rc == LDAP_SUCCESS ) { 1519 dir2ldif_name( path ); 1520 if ( unlink( path.bv_val ) < 0 ) { 1521 rc = LDAP_NO_SUCH_OBJECT; 1522 if ( errno != ENOENT ) { 1523 rc = LDAP_OTHER; 1524 rs->sr_text = "internal error (cannot delete entry file)"; 1525 } 1526 } 1527 } 1528 1529 if ( rc == LDAP_OTHER ) { 1530 Debug( LDAP_DEBUG_ANY, "ldif_back_delete: %s \"%s\": %s\n", 1531 "cannot delete", path.bv_val, STRERROR( errno ) ); 1532 } 1533 1534 SLAP_FREE( path.bv_val ); 1535 done: 1536 ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr ); 1537 ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex ); 1538 rs->sr_err = rc; 1539 send_ldap_result( op, rs ); 1540 slap_graduate_commit_csn( op ); 1541 return rs->sr_err; 1542 } 1543 1544 1545 static int 1546 ldif_move_entry( 1547 Operation *op, 1548 Entry *entry, 1549 int same_ndn, 1550 struct berval *oldpath, 1551 const char **text ) 1552 { 1553 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1554 struct berval newpath; 1555 char *parentdir = NULL, *trash; 1556 int rc, rename_res; 1557 1558 if ( same_ndn ) { 1559 rc = LDAP_SUCCESS; 1560 newpath = *oldpath; 1561 } else { 1562 rc = ldif_prepare_create( op, entry, &newpath, 1563 op->orr_newSup ? &parentdir : NULL, text ); 1564 } 1565 1566 if ( rc == LDAP_SUCCESS ) { 1567 ldap_pvt_thread_rdwr_wlock( &li->li_rdwr ); 1568 1569 rc = ldif_write_entry( op, entry, &newpath, parentdir, text ); 1570 if ( rc == LDAP_SUCCESS && !same_ndn ) { 1571 trash = oldpath->bv_val; /* will be .ldif file to delete */ 1572 ldif2dir_len( newpath ); 1573 ldif2dir_len( *oldpath ); 1574 /* Move subdir before deleting old entry, 1575 * so .ldif always exists if subdir does. 1576 */ 1577 ldif2dir_name( newpath ); 1578 ldif2dir_name( *oldpath ); 1579 rename_res = move_dir( oldpath->bv_val, newpath.bv_val ); 1580 if ( rename_res != 0 && errno != ENOENT ) { 1581 rc = LDAP_OTHER; 1582 *text = "internal error (cannot move this subtree)"; 1583 trash = newpath.bv_val; 1584 } 1585 1586 /* Delete old entry, or if error undo change */ 1587 for (;;) { 1588 dir2ldif_name( newpath ); 1589 dir2ldif_name( *oldpath ); 1590 if ( unlink( trash ) == 0 ) 1591 break; 1592 if ( rc == LDAP_SUCCESS ) { 1593 /* Prepare to undo change and return failure */ 1594 rc = LDAP_OTHER; 1595 *text = "internal error (cannot move this entry)"; 1596 trash = newpath.bv_val; 1597 if ( rename_res != 0 ) 1598 continue; 1599 /* First move subdirectory back */ 1600 ldif2dir_name( newpath ); 1601 ldif2dir_name( *oldpath ); 1602 if ( move_dir( newpath.bv_val, oldpath->bv_val ) == 0 ) 1603 continue; 1604 } 1605 *text = "added new but couldn't delete old entry!"; 1606 break; 1607 } 1608 1609 if ( rc != LDAP_SUCCESS ) { 1610 char s[128]; 1611 snprintf( s, sizeof s, "%s (%s)", *text, STRERROR( errno )); 1612 Debug( LDAP_DEBUG_ANY, 1613 "ldif_move_entry: %s: \"%s\" -> \"%s\"\n", 1614 s, op->o_req_dn.bv_val, entry->e_dn ); 1615 } 1616 } 1617 1618 ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr ); 1619 if ( !same_ndn ) 1620 SLAP_FREE( newpath.bv_val ); 1621 if ( parentdir != NULL ) 1622 SLAP_FREE( parentdir ); 1623 } 1624 1625 return rc; 1626 } 1627 1628 static int 1629 ldif_back_modrdn( Operation *op, SlapReply *rs ) 1630 { 1631 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1632 struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL; 1633 struct berval p_dn, old_path; 1634 Entry *entry; 1635 char textbuf[SLAP_TEXT_BUFLEN]; 1636 int rc, same_ndn; 1637 1638 slap_mods_opattrs( op, &op->orr_modlist, 1 ); 1639 1640 ldap_pvt_thread_mutex_lock( &li->li_modop_mutex ); 1641 1642 rc = get_entry( op, &entry, &old_path, &rs->sr_text ); 1643 if ( rc == LDAP_SUCCESS ) { 1644 /* build new dn, and new ndn for the entry */ 1645 if ( op->oq_modrdn.rs_newSup != NULL ) { 1646 p_dn = *op->oq_modrdn.rs_newSup; 1647 } else { 1648 dnParent( &entry->e_name, &p_dn ); 1649 } 1650 build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL ); 1651 dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL ); 1652 same_ndn = !ber_bvcmp( &entry->e_nname, &new_ndn ); 1653 ber_memfree_x( entry->e_name.bv_val, NULL ); 1654 ber_memfree_x( entry->e_nname.bv_val, NULL ); 1655 entry->e_name = new_dn; 1656 entry->e_nname = new_ndn; 1657 1658 /* perform the modifications */ 1659 rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs, textbuf ); 1660 if ( rc == LDAP_SUCCESS ) 1661 rc = ldif_move_entry( op, entry, same_ndn, &old_path, 1662 &rs->sr_text ); 1663 1664 entry_free( entry ); 1665 SLAP_FREE( old_path.bv_val ); 1666 } 1667 1668 ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex ); 1669 rs->sr_err = rc; 1670 send_ldap_result( op, rs ); 1671 slap_graduate_commit_csn( op ); 1672 rs->sr_text = NULL; /* remove possible pointer to textbuf */ 1673 return rs->sr_err; 1674 } 1675 1676 1677 /* Return LDAP_SUCCESS IFF we retrieve the specified entry. */ 1678 static int 1679 ldif_back_entry_get( 1680 Operation *op, 1681 struct berval *ndn, 1682 ObjectClass *oc, 1683 AttributeDescription *at, 1684 int rw, 1685 Entry **e ) 1686 { 1687 struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; 1688 struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn; 1689 int rc; 1690 1691 assert( ndn != NULL ); 1692 assert( !BER_BVISNULL( ndn ) ); 1693 1694 ldap_pvt_thread_rdwr_rlock( &li->li_rdwr ); 1695 op->o_req_dn = *ndn; 1696 op->o_req_ndn = *ndn; 1697 rc = get_entry( op, e, NULL, NULL ); 1698 op->o_req_dn = op_dn; 1699 op->o_req_ndn = op_ndn; 1700 ldap_pvt_thread_rdwr_runlock( &li->li_rdwr ); 1701 1702 if ( rc == LDAP_SUCCESS && oc && !is_entry_objectclass_or_sub( *e, oc ) ) { 1703 rc = LDAP_NO_SUCH_ATTRIBUTE; 1704 entry_free( *e ); 1705 *e = NULL; 1706 } 1707 1708 return rc; 1709 } 1710 1711 1712 /* Slap tools */ 1713 1714 static int 1715 ldif_tool_entry_open( BackendDB *be, int mode ) 1716 { 1717 struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; 1718 1719 tl->ecurrent = 0; 1720 return 0; 1721 } 1722 1723 static int 1724 ldif_tool_entry_close( BackendDB *be ) 1725 { 1726 struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; 1727 Entry **entries = tl->entries; 1728 ID i; 1729 1730 for ( i = tl->ecount; i--; ) 1731 if ( entries[i] ) 1732 entry_free( entries[i] ); 1733 SLAP_FREE( entries ); 1734 tl->entries = NULL; 1735 tl->ecount = tl->elen = 0; 1736 return 0; 1737 } 1738 1739 static ID 1740 ldif_tool_entry_next( BackendDB *be ) 1741 { 1742 struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; 1743 1744 do { 1745 Entry *e = tl->entries[ tl->ecurrent ]; 1746 1747 if ( tl->ecurrent >= tl->ecount ) { 1748 return NOID; 1749 } 1750 1751 ++tl->ecurrent; 1752 1753 if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) { 1754 continue; 1755 } 1756 1757 if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter ) != LDAP_COMPARE_TRUE ) { 1758 continue; 1759 } 1760 1761 break; 1762 } while ( 1 ); 1763 1764 return tl->ecurrent; 1765 } 1766 1767 static ID 1768 ldif_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f ) 1769 { 1770 struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; 1771 1772 tl->tl_base = base; 1773 tl->tl_scope = scope; 1774 tl->tl_filter = f; 1775 1776 if ( tl->entries == NULL ) { 1777 Operation op = {0}; 1778 1779 op.o_bd = be; 1780 op.o_req_dn = *be->be_suffix; 1781 op.o_req_ndn = *be->be_nsuffix; 1782 op.ors_scope = LDAP_SCOPE_SUBTREE; 1783 if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) { 1784 tl->ecurrent = tl->ecount; /* fail ldif_tool_entry_next() */ 1785 return NOID; /* fail ldif_tool_entry_get() */ 1786 } 1787 } 1788 return ldif_tool_entry_next( be ); 1789 } 1790 1791 static Entry * 1792 ldif_tool_entry_get( BackendDB *be, ID id ) 1793 { 1794 struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool; 1795 Entry *e = NULL; 1796 1797 --id; 1798 if ( id < tl->ecount ) { 1799 e = tl->entries[id]; 1800 tl->entries[id] = NULL; 1801 } 1802 return e; 1803 } 1804 1805 static ID 1806 ldif_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) 1807 { 1808 int rc; 1809 const char *errmsg = NULL; 1810 struct berval path; 1811 char *parentdir; 1812 Operation op = {0}; 1813 1814 op.o_bd = be; 1815 rc = ldif_prepare_create( &op, e, &path, &parentdir, &errmsg ); 1816 if ( rc == LDAP_SUCCESS ) { 1817 rc = ldif_write_entry( &op, e, &path, parentdir, &errmsg ); 1818 1819 SLAP_FREE( path.bv_val ); 1820 if ( parentdir != NULL ) 1821 SLAP_FREE( parentdir ); 1822 if ( rc == LDAP_SUCCESS ) 1823 return 1; 1824 } 1825 1826 if ( errmsg == NULL && rc != LDAP_OTHER ) 1827 errmsg = ldap_err2string( rc ); 1828 if ( errmsg != NULL ) 1829 snprintf( text->bv_val, text->bv_len, "%s", errmsg ); 1830 return NOID; 1831 } 1832 1833 1834 /* Setup */ 1835 1836 static int 1837 ldif_back_db_init( BackendDB *be, ConfigReply *cr ) 1838 { 1839 struct ldif_info *li; 1840 1841 li = ch_calloc( 1, sizeof(struct ldif_info) ); 1842 be->be_private = li; 1843 be->be_cf_ocs = ldifocs; 1844 ldap_pvt_thread_mutex_init( &li->li_modop_mutex ); 1845 ldap_pvt_thread_rdwr_init( &li->li_rdwr ); 1846 SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX; 1847 return 0; 1848 } 1849 1850 static int 1851 ldif_back_db_destroy( Backend *be, ConfigReply *cr ) 1852 { 1853 struct ldif_info *li = be->be_private; 1854 1855 ch_free( li->li_base_path.bv_val ); 1856 ldap_pvt_thread_rdwr_destroy( &li->li_rdwr ); 1857 ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex ); 1858 free( be->be_private ); 1859 return 0; 1860 } 1861 1862 static int 1863 ldif_back_db_open( Backend *be, ConfigReply *cr ) 1864 { 1865 struct ldif_info *li = (struct ldif_info *) be->be_private; 1866 if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */ 1867 Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n", 0, 0, 0); 1868 return 1; 1869 } 1870 return 0; 1871 } 1872 1873 int 1874 ldif_back_initialize( BackendInfo *bi ) 1875 { 1876 static char *controls[] = { 1877 LDAP_CONTROL_MANAGEDSAIT, 1878 NULL 1879 }; 1880 int rc; 1881 1882 bi->bi_flags |= 1883 SLAP_BFLAG_INCREMENT | 1884 SLAP_BFLAG_REFERRALS; 1885 1886 bi->bi_controls = controls; 1887 1888 bi->bi_open = 0; 1889 bi->bi_close = 0; 1890 bi->bi_config = 0; 1891 bi->bi_destroy = 0; 1892 1893 bi->bi_db_init = ldif_back_db_init; 1894 bi->bi_db_config = config_generic_wrapper; 1895 bi->bi_db_open = ldif_back_db_open; 1896 bi->bi_db_close = 0; 1897 bi->bi_db_destroy = ldif_back_db_destroy; 1898 1899 bi->bi_op_bind = ldif_back_bind; 1900 bi->bi_op_unbind = 0; 1901 bi->bi_op_search = ldif_back_search; 1902 bi->bi_op_compare = 0; 1903 bi->bi_op_modify = ldif_back_modify; 1904 bi->bi_op_modrdn = ldif_back_modrdn; 1905 bi->bi_op_add = ldif_back_add; 1906 bi->bi_op_delete = ldif_back_delete; 1907 bi->bi_op_abandon = 0; 1908 1909 bi->bi_extended = 0; 1910 1911 bi->bi_chk_referrals = ldif_back_referrals; 1912 1913 bi->bi_connection_init = 0; 1914 bi->bi_connection_destroy = 0; 1915 1916 bi->bi_entry_get_rw = ldif_back_entry_get; 1917 1918 #if 0 /* NOTE: uncomment to completely disable access control */ 1919 bi->bi_access_allowed = slap_access_always_allowed; 1920 #endif 1921 1922 bi->bi_tool_entry_open = ldif_tool_entry_open; 1923 bi->bi_tool_entry_close = ldif_tool_entry_close; 1924 bi->bi_tool_entry_first = backend_tool_entry_first; 1925 bi->bi_tool_entry_first_x = ldif_tool_entry_first_x; 1926 bi->bi_tool_entry_next = ldif_tool_entry_next; 1927 bi->bi_tool_entry_get = ldif_tool_entry_get; 1928 bi->bi_tool_entry_put = ldif_tool_entry_put; 1929 bi->bi_tool_entry_reindex = 0; 1930 bi->bi_tool_sync = 0; 1931 1932 bi->bi_tool_dn2id_get = 0; 1933 bi->bi_tool_entry_modify = 0; 1934 1935 bi->bi_cf_ocs = ldifocs; 1936 1937 rc = config_register_schema( ldifcfg, ldifocs ); 1938 if ( rc ) return rc; 1939 return 0; 1940 } 1941