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