ldif.c revision 1.1.1.5 1 1.1.1.2 lukem /* $NetBSD: ldif.c,v 1.1.1.5 2017/02/09 01:47:05 christos 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.5 christos * Copyright 2005-2016 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.5 christos __RCSID("$NetBSD: ldif.c,v 1.1.1.5 2017/02/09 01:47:05 christos 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 int i;
404 1.1.1.4 tron
405 1.1.1.4 tron while (len > 7) {
406 1.1.1.4 tron CRC8;
407 1.1.1.4 tron len -= 8;
408 1.1.1.4 tron }
409 1.1.1.4 tron while (len) {
410 1.1.1.4 tron CRC1;
411 1.1.1.4 tron len--;
412 1.1.1.4 tron }
413 1.1.1.4 tron
414 1.1.1.4 tron return crc ^ 0xffffffff;
415 1.1.1.4 tron }
416 1.1.1.4 tron
417 1.1.1.2 lukem /*
418 1.1.1.2 lukem * Read a file, or stat() it if datap == NULL. Allocate and fill *datap.
419 1.1.1.2 lukem * Return LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT (no such file), or another error.
420 1.1.1.2 lukem */
421 1.1.1.2 lukem static int
422 1.1.1.2 lukem ldif_read_file( const char *path, char **datap )
423 1.1.1.2 lukem {
424 1.1.1.4 tron int rc = LDAP_SUCCESS, fd, len;
425 1.1.1.2 lukem int res = -1; /* 0:success, <0:error, >0:file too big/growing. */
426 1.1 lukem struct stat st;
427 1.1.1.4 tron char *data = NULL, *ptr = NULL;
428 1.1.1.4 tron const char *msg;
429 1.1 lukem
430 1.1.1.2 lukem if ( datap == NULL ) {
431 1.1.1.2 lukem res = stat( path, &st );
432 1.1.1.2 lukem goto done;
433 1.1.1.2 lukem }
434 1.1.1.2 lukem fd = open( path, O_RDONLY );
435 1.1.1.2 lukem if ( fd >= 0 ) {
436 1.1.1.2 lukem if ( fstat( fd, &st ) == 0 ) {
437 1.1.1.2 lukem if ( st.st_size > INT_MAX - 2 ) {
438 1.1.1.2 lukem res = 1;
439 1.1.1.2 lukem } else {
440 1.1.1.2 lukem len = st.st_size + 1; /* +1 detects file size > st.st_size */
441 1.1.1.2 lukem *datap = data = ptr = SLAP_MALLOC( len + 1 );
442 1.1.1.2 lukem if ( ptr != NULL ) {
443 1.1.1.2 lukem while ( len && (res = read( fd, ptr, len )) ) {
444 1.1.1.2 lukem if ( res > 0 ) {
445 1.1.1.2 lukem len -= res;
446 1.1.1.2 lukem ptr += res;
447 1.1.1.2 lukem } else if ( errno != EINTR ) {
448 1.1.1.2 lukem break;
449 1.1.1.2 lukem }
450 1.1.1.2 lukem }
451 1.1.1.2 lukem *ptr = '\0';
452 1.1.1.2 lukem }
453 1.1.1.2 lukem }
454 1.1 lukem }
455 1.1.1.2 lukem if ( close( fd ) < 0 )
456 1.1.1.2 lukem res = -1;
457 1.1.1.2 lukem }
458 1.1.1.2 lukem
459 1.1.1.2 lukem done:
460 1.1.1.2 lukem if ( res == 0 ) {
461 1.1.1.4 tron #ifdef LDAP_DEBUG
462 1.1.1.4 tron msg = "entry file exists";
463 1.1.1.4 tron if ( datap ) {
464 1.1.1.4 tron msg = "read entry file";
465 1.1.1.4 tron len = ptr - data;
466 1.1.1.4 tron ptr = strstr( data, "\n# CRC32" );
467 1.1.1.4 tron if (!ptr) {
468 1.1.1.4 tron msg = "read entry file without checksum";
469 1.1.1.4 tron } else {
470 1.1.1.4 tron unsigned int crc1 = 0, crc2 = 1;
471 1.1.1.4 tron if ( sscanf( ptr + 9, "%08x", &crc1) == 1) {
472 1.1.1.4 tron ptr = strchr(ptr+1, '\n');
473 1.1.1.4 tron if ( ptr ) {
474 1.1.1.4 tron ptr++;
475 1.1.1.4 tron len -= (ptr - data);
476 1.1.1.4 tron crc2 = crc32( ptr, len );
477 1.1.1.4 tron }
478 1.1.1.4 tron }
479 1.1.1.4 tron if ( crc1 != crc2 ) {
480 1.1.1.4 tron Debug( LDAP_DEBUG_ANY, "ldif_read_file: checksum error on \"%s\"\n",
481 1.1.1.4 tron path, 0, 0 );
482 1.1.1.4 tron return rc;
483 1.1.1.4 tron }
484 1.1.1.4 tron }
485 1.1.1.4 tron }
486 1.1.1.4 tron Debug( LDAP_DEBUG_TRACE, "ldif_read_file: %s: \"%s\"\n", msg, path, 0 );
487 1.1.1.4 tron #endif /* LDAP_DEBUG */
488 1.1.1.2 lukem } else {
489 1.1.1.2 lukem if ( res < 0 && errno == ENOENT ) {
490 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_read_file: "
491 1.1.1.2 lukem "no entry file \"%s\"\n", path, 0, 0 );
492 1.1.1.2 lukem rc = LDAP_NO_SUCH_OBJECT;
493 1.1.1.2 lukem } else {
494 1.1.1.4 tron msg = res < 0 ? STRERROR( errno ) : "bad stat() size";
495 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_read_file: %s for \"%s\"\n",
496 1.1.1.2 lukem msg, path, 0 );
497 1.1.1.2 lukem rc = LDAP_OTHER;
498 1.1 lukem }
499 1.1.1.2 lukem if ( data != NULL )
500 1.1.1.2 lukem SLAP_FREE( data );
501 1.1 lukem }
502 1.1.1.2 lukem return rc;
503 1.1 lukem }
504 1.1 lukem
505 1.1 lukem /*
506 1.1 lukem * return nonnegative for success or -1 for error
507 1.1 lukem * do not return numbers less than -1
508 1.1 lukem */
509 1.1.1.2 lukem static int
510 1.1.1.2 lukem spew_file( int fd, const char *spew, int len, int *save_errno )
511 1.1.1.2 lukem {
512 1.1.1.4 tron int writeres;
513 1.1.1.4 tron #define HEADER "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n"
514 1.1.1.4 tron char header[sizeof(HEADER "# CRC32 12345678\n")];
515 1.1.1.2 lukem
516 1.1.1.4 tron sprintf(header, HEADER "# CRC32 %08x\n", crc32(spew, len));
517 1.1.1.4 tron writeres = write_data(fd, header, sizeof(header)-1, save_errno);
518 1.1.1.4 tron return writeres < 0 ? writeres : write_data(fd, spew, len, save_errno);
519 1.1.1.4 tron }
520 1.1.1.4 tron
521 1.1.1.4 tron static int
522 1.1.1.4 tron write_data( int fd, const char *spew, int len, int *save_errno )
523 1.1.1.4 tron {
524 1.1.1.4 tron int writeres = 0;
525 1.1 lukem while(len > 0) {
526 1.1 lukem writeres = write(fd, spew, len);
527 1.1 lukem if(writeres == -1) {
528 1.1.1.2 lukem *save_errno = errno;
529 1.1.1.2 lukem if (*save_errno != EINTR)
530 1.1.1.2 lukem break;
531 1.1 lukem }
532 1.1 lukem else {
533 1.1 lukem spew += writeres;
534 1.1 lukem len -= writeres;
535 1.1 lukem }
536 1.1 lukem }
537 1.1 lukem return writeres;
538 1.1 lukem }
539 1.1 lukem
540 1.1.1.2 lukem /* Write an entry LDIF file. Create parentdir first if non-NULL. */
541 1.1 lukem static int
542 1.1.1.2 lukem ldif_write_entry(
543 1.1.1.2 lukem Operation *op,
544 1.1.1.2 lukem Entry *e,
545 1.1.1.2 lukem const struct berval *path,
546 1.1.1.2 lukem const char *parentdir,
547 1.1.1.2 lukem const char **text )
548 1.1 lukem {
549 1.1.1.2 lukem int rc = LDAP_OTHER, res, save_errno = 0;
550 1.1.1.2 lukem int fd, entry_length;
551 1.1.1.2 lukem char *entry_as_string, *tmpfname;
552 1.1.1.2 lukem
553 1.1.1.2 lukem if ( op->o_abandon )
554 1.1.1.2 lukem return SLAPD_ABANDON;
555 1.1 lukem
556 1.1.1.2 lukem if ( parentdir != NULL && mkdir( parentdir, 0750 ) < 0 ) {
557 1.1 lukem save_errno = errno;
558 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
559 1.1.1.2 lukem "cannot create parent directory",
560 1.1.1.2 lukem parentdir, STRERROR( save_errno ) );
561 1.1.1.2 lukem *text = "internal error (cannot create parent directory)";
562 1.1.1.2 lukem return rc;
563 1.1.1.2 lukem }
564 1.1.1.2 lukem
565 1.1.1.2 lukem tmpfname = ldif_tempname( path );
566 1.1.1.2 lukem fd = tmpfname == NULL ? -1 : mkstemp( tmpfname );
567 1.1.1.2 lukem if ( fd < 0 ) {
568 1.1.1.2 lukem save_errno = errno;
569 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s for \"%s\": %s\n",
570 1.1.1.2 lukem "cannot create file", e->e_dn, STRERROR( save_errno ) );
571 1.1.1.2 lukem *text = "internal error (cannot create file)";
572 1.1 lukem
573 1.1 lukem } else {
574 1.1.1.2 lukem ber_len_t dn_len = e->e_name.bv_len;
575 1.1 lukem struct berval rdn;
576 1.1 lukem
577 1.1 lukem /* Only save the RDN onto disk */
578 1.1 lukem dnRdn( &e->e_name, &rdn );
579 1.1.1.2 lukem if ( rdn.bv_len != dn_len ) {
580 1.1 lukem e->e_name.bv_val[rdn.bv_len] = '\0';
581 1.1 lukem e->e_name.bv_len = rdn.bv_len;
582 1.1 lukem }
583 1.1 lukem
584 1.1.1.2 lukem res = -2;
585 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &entry2str_mutex );
586 1.1.1.2 lukem entry_as_string = entry2str( e, &entry_length );
587 1.1.1.2 lukem if ( entry_as_string != NULL )
588 1.1.1.2 lukem res = spew_file( fd, entry_as_string, entry_length, &save_errno );
589 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
590 1.1 lukem
591 1.1 lukem /* Restore full DN */
592 1.1.1.2 lukem if ( rdn.bv_len != dn_len ) {
593 1.1.1.2 lukem e->e_name.bv_val[rdn.bv_len] = ',';
594 1.1.1.2 lukem e->e_name.bv_len = dn_len;
595 1.1 lukem }
596 1.1 lukem
597 1.1.1.2 lukem if ( close( fd ) < 0 && res >= 0 ) {
598 1.1.1.2 lukem res = -1;
599 1.1.1.2 lukem save_errno = errno;
600 1.1.1.2 lukem }
601 1.1 lukem
602 1.1.1.2 lukem if ( res >= 0 ) {
603 1.1.1.2 lukem if ( move_file( tmpfname, path->bv_val ) == 0 ) {
604 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_write_entry: "
605 1.1.1.2 lukem "wrote entry \"%s\"\n", e->e_name.bv_val, 0, 0 );
606 1.1.1.2 lukem rc = LDAP_SUCCESS;
607 1.1 lukem } else {
608 1.1.1.2 lukem save_errno = errno;
609 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: "
610 1.1.1.2 lukem "could not put entry file for \"%s\" in place: %s\n",
611 1.1.1.2 lukem e->e_name.bv_val, STRERROR( save_errno ), 0 );
612 1.1.1.2 lukem *text = "internal error (could not put entry file in place)";
613 1.1.1.2 lukem }
614 1.1.1.2 lukem } else if ( res == -1 ) {
615 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
616 1.1.1.2 lukem "write error to", tmpfname, STRERROR( save_errno ) );
617 1.1.1.2 lukem *text = "internal error (write error to entry file)";
618 1.1 lukem }
619 1.1 lukem
620 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
621 1.1 lukem unlink( tmpfname );
622 1.1 lukem }
623 1.1 lukem }
624 1.1 lukem
625 1.1.1.2 lukem if ( tmpfname )
626 1.1.1.2 lukem SLAP_FREE( tmpfname );
627 1.1.1.2 lukem return rc;
628 1.1 lukem }
629 1.1 lukem
630 1.1.1.2 lukem /*
631 1.1.1.2 lukem * Read the entry at path, or if entryp==NULL just see if it exists.
632 1.1.1.2 lukem * pdn and pndn are the parent's DN and normalized DN, or both NULL.
633 1.1.1.2 lukem * Return an LDAP result code.
634 1.1.1.2 lukem */
635 1.1.1.2 lukem static int
636 1.1.1.2 lukem ldif_read_entry(
637 1.1.1.2 lukem Operation *op,
638 1.1.1.2 lukem const char *path,
639 1.1 lukem struct berval *pdn,
640 1.1.1.2 lukem struct berval *pndn,
641 1.1.1.2 lukem Entry **entryp,
642 1.1.1.2 lukem const char **text )
643 1.1 lukem {
644 1.1.1.2 lukem int rc;
645 1.1.1.2 lukem Entry *entry;
646 1.1.1.2 lukem char *entry_as_string;
647 1.1.1.2 lukem struct berval rdn;
648 1.1 lukem
649 1.1.1.2 lukem /* TODO: Does slapd prevent Abandon of Bind as per rfc4511?
650 1.1.1.2 lukem * If so we need not check for LDAP_REQ_BIND here.
651 1.1.1.2 lukem */
652 1.1.1.2 lukem if ( op->o_abandon && op->o_tag != LDAP_REQ_BIND )
653 1.1.1.2 lukem return SLAPD_ABANDON;
654 1.1.1.2 lukem
655 1.1.1.2 lukem rc = ldif_read_file( path, entryp ? &entry_as_string : NULL );
656 1.1.1.2 lukem
657 1.1.1.2 lukem switch ( rc ) {
658 1.1.1.2 lukem case LDAP_SUCCESS:
659 1.1.1.2 lukem if ( entryp == NULL )
660 1.1.1.2 lukem break;
661 1.1.1.2 lukem *entryp = entry = str2entry( entry_as_string );
662 1.1.1.2 lukem SLAP_FREE( entry_as_string );
663 1.1.1.2 lukem if ( entry == NULL ) {
664 1.1.1.2 lukem rc = LDAP_OTHER;
665 1.1.1.2 lukem if ( text != NULL )
666 1.1.1.2 lukem *text = "internal error (cannot parse some entry file)";
667 1.1.1.2 lukem break;
668 1.1 lukem }
669 1.1.1.2 lukem if ( pdn == NULL || BER_BVISEMPTY( pdn ) )
670 1.1.1.2 lukem break;
671 1.1.1.2 lukem /* Append parent DN to DN from LDIF file */
672 1.1.1.2 lukem rdn = entry->e_name;
673 1.1.1.2 lukem build_new_dn( &entry->e_name, pdn, &rdn, NULL );
674 1.1.1.2 lukem SLAP_FREE( rdn.bv_val );
675 1.1.1.2 lukem rdn = entry->e_nname;
676 1.1.1.2 lukem build_new_dn( &entry->e_nname, pndn, &rdn, NULL );
677 1.1.1.2 lukem SLAP_FREE( rdn.bv_val );
678 1.1.1.2 lukem break;
679 1.1.1.2 lukem
680 1.1.1.2 lukem case LDAP_OTHER:
681 1.1.1.2 lukem if ( text != NULL )
682 1.1.1.2 lukem *text = entryp
683 1.1.1.2 lukem ? "internal error (cannot read some entry file)"
684 1.1.1.2 lukem : "internal error (cannot stat some entry file)";
685 1.1.1.2 lukem break;
686 1.1 lukem }
687 1.1.1.2 lukem
688 1.1.1.2 lukem return rc;
689 1.1 lukem }
690 1.1 lukem
691 1.1.1.2 lukem /*
692 1.1.1.2 lukem * Read the operation's entry, or if entryp==NULL just see if it exists.
693 1.1.1.2 lukem * Return an LDAP result code. May set *text to a message on failure.
694 1.1.1.2 lukem * If pathp is non-NULL, set it to the entry filename on success.
695 1.1.1.2 lukem */
696 1.1 lukem static int
697 1.1 lukem get_entry(
698 1.1 lukem Operation *op,
699 1.1 lukem Entry **entryp,
700 1.1.1.2 lukem struct berval *pathp,
701 1.1.1.2 lukem const char **text )
702 1.1 lukem {
703 1.1 lukem int rc;
704 1.1 lukem struct berval path, pdn, pndn;
705 1.1 lukem
706 1.1.1.2 lukem dnParent( &op->o_req_dn, &pdn );
707 1.1.1.2 lukem dnParent( &op->o_req_ndn, &pndn );
708 1.1.1.2 lukem rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
709 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
710 1.1.1.2 lukem goto done;
711 1.1 lukem }
712 1.1.1.2 lukem
713 1.1.1.2 lukem rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, entryp, text );
714 1.1 lukem
715 1.1 lukem if ( rc == LDAP_SUCCESS && pathp != NULL ) {
716 1.1 lukem *pathp = path;
717 1.1 lukem } else {
718 1.1.1.2 lukem SLAP_FREE( path.bv_val );
719 1.1 lukem }
720 1.1.1.2 lukem done:
721 1.1 lukem return rc;
722 1.1 lukem }
723 1.1 lukem
724 1.1 lukem
725 1.1.1.2 lukem /*
726 1.1.1.2 lukem * RDN-named directory entry, with special handling of "attr={num}val" RDNs.
727 1.1.1.2 lukem * For sorting, filename "attr=val.ldif" is truncated to "attr="val\0ldif",
728 1.1.1.2 lukem * and filename "attr={num}val.ldif" to "attr={\0um}val.ldif".
729 1.1.1.2 lukem * Does not sort escaped chars correctly, would need to un-escape them.
730 1.1.1.2 lukem */
731 1.1 lukem typedef struct bvlist {
732 1.1 lukem struct bvlist *next;
733 1.1.1.2 lukem char *trunc; /* filename was truncated here */
734 1.1.1.2 lukem int inum; /* num from "attr={num}" in filename, or INT_MIN */
735 1.1.1.2 lukem char savech; /* original char at *trunc */
736 1.1.1.2 lukem /* BVL_NAME(&bvlist) is the filename, allocated after the struct: */
737 1.1.1.2 lukem # define BVL_NAME(bvl) ((char *) ((bvl) + 1))
738 1.1.1.2 lukem # define BVL_SIZE(namelen) (sizeof(bvlist) + (namelen) + 1)
739 1.1 lukem } bvlist;
740 1.1 lukem
741 1.1.1.2 lukem static int
742 1.1.1.2 lukem ldif_send_entry( Operation *op, SlapReply *rs, Entry *e, int scope )
743 1.1 lukem {
744 1.1.1.2 lukem int rc = LDAP_SUCCESS;
745 1.1 lukem
746 1.1.1.2 lukem if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) {
747 1.1.1.2 lukem if ( rs == NULL ) {
748 1.1.1.2 lukem /* Save the entry for tool mode */
749 1.1.1.2 lukem struct ldif_tool *tl =
750 1.1.1.2 lukem &((struct ldif_info *) op->o_bd->be_private)->li_tool;
751 1.1.1.2 lukem
752 1.1.1.2 lukem if ( tl->ecount >= tl->elen ) {
753 1.1.1.2 lukem /* Allocate/grow entries */
754 1.1.1.2 lukem ID elen = tl->elen ? tl->elen * 2 : ENTRY_BUFF_INCREMENT;
755 1.1.1.2 lukem Entry **entries = (Entry **) SLAP_REALLOC( tl->entries,
756 1.1.1.2 lukem sizeof(Entry *) * elen );
757 1.1.1.2 lukem if ( entries == NULL ) {
758 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
759 1.1.1.2 lukem "ldif_send_entry: out of memory\n", 0, 0, 0 );
760 1.1.1.2 lukem rc = LDAP_OTHER;
761 1.1.1.2 lukem goto done;
762 1.1.1.2 lukem }
763 1.1.1.2 lukem tl->elen = elen;
764 1.1.1.2 lukem tl->entries = entries;
765 1.1.1.2 lukem }
766 1.1.1.2 lukem tl->entries[tl->ecount++] = e;
767 1.1.1.2 lukem return rc;
768 1.1 lukem }
769 1.1 lukem
770 1.1.1.2 lukem else if ( !get_manageDSAit( op ) && is_entry_referral( e ) ) {
771 1.1.1.2 lukem /* Send a continuation reference.
772 1.1.1.2 lukem * (ldif_back_referrals() handles baseobject referrals.)
773 1.1.1.2 lukem * Don't check the filter since it's only a candidate.
774 1.1.1.2 lukem */
775 1.1.1.2 lukem BerVarray refs = get_entry_referrals( op, e );
776 1.1.1.2 lukem rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope );
777 1.1.1.2 lukem rs->sr_entry = e;
778 1.1.1.2 lukem rc = send_search_reference( op, rs );
779 1.1.1.2 lukem ber_bvarray_free( rs->sr_ref );
780 1.1.1.2 lukem ber_bvarray_free( refs );
781 1.1.1.2 lukem rs->sr_ref = NULL;
782 1.1.1.2 lukem rs->sr_entry = NULL;
783 1.1 lukem }
784 1.1 lukem
785 1.1.1.2 lukem else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
786 1.1.1.2 lukem rs->sr_entry = e;
787 1.1.1.2 lukem rs->sr_attrs = op->ors_attrs;
788 1.1.1.4 tron /* Could set REP_ENTRY_MUSTBEFREED too for efficiency,
789 1.1.1.4 tron * but refraining lets us test unFREEable MODIFIABLE
790 1.1.1.4 tron * entries. Like entries built on the stack.
791 1.1.1.4 tron */
792 1.1.1.2 lukem rs->sr_flags = REP_ENTRY_MODIFIABLE;
793 1.1.1.2 lukem rc = send_search_entry( op, rs );
794 1.1.1.2 lukem rs->sr_entry = NULL;
795 1.1.1.4 tron rs->sr_attrs = NULL;
796 1.1 lukem }
797 1.1 lukem }
798 1.1 lukem
799 1.1.1.2 lukem done:
800 1.1.1.2 lukem entry_free( e );
801 1.1.1.2 lukem return rc;
802 1.1.1.2 lukem }
803 1.1 lukem
804 1.1.1.2 lukem /* Read LDIF directory <path> into <listp>. Set *fname_maxlenp. */
805 1.1.1.2 lukem static int
806 1.1.1.2 lukem ldif_readdir(
807 1.1.1.2 lukem Operation *op,
808 1.1.1.2 lukem SlapReply *rs,
809 1.1.1.2 lukem const struct berval *path,
810 1.1.1.2 lukem bvlist **listp,
811 1.1.1.2 lukem ber_len_t *fname_maxlenp )
812 1.1.1.2 lukem {
813 1.1.1.2 lukem int rc = LDAP_SUCCESS;
814 1.1.1.2 lukem DIR *dir_of_path;
815 1.1 lukem
816 1.1.1.2 lukem *listp = NULL;
817 1.1.1.2 lukem *fname_maxlenp = 0;
818 1.1.1.2 lukem
819 1.1.1.2 lukem dir_of_path = opendir( path->bv_val );
820 1.1.1.2 lukem if ( dir_of_path == NULL ) {
821 1.1.1.2 lukem int save_errno = errno;
822 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
823 1.1.1.2 lukem int is_rootDSE = (path->bv_len == li->li_base_path.bv_len);
824 1.1.1.2 lukem
825 1.1.1.2 lukem /* Absent directory is OK (leaf entry), except the database dir */
826 1.1.1.2 lukem if ( is_rootDSE || save_errno != ENOENT ) {
827 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
828 1.1.1.2 lukem "=> ldif_search_entry: failed to opendir \"%s\": %s\n",
829 1.1.1.2 lukem path->bv_val, STRERROR( save_errno ), 0 );
830 1.1.1.2 lukem rc = LDAP_OTHER;
831 1.1.1.2 lukem if ( rs != NULL )
832 1.1.1.2 lukem rs->sr_text =
833 1.1.1.2 lukem save_errno != ENOENT ? "internal error (bad directory)"
834 1.1.1.2 lukem : "internal error (database directory does not exist)";
835 1.1 lukem }
836 1.1.1.2 lukem
837 1.1.1.2 lukem } else {
838 1.1.1.2 lukem bvlist *ptr;
839 1.1.1.2 lukem struct dirent *dir;
840 1.1.1.2 lukem int save_errno = 0;
841 1.1.1.2 lukem
842 1.1.1.2 lukem while ( (dir = readdir( dir_of_path )) != NULL ) {
843 1.1.1.2 lukem size_t fname_len;
844 1.1 lukem bvlist *bvl, **prev;
845 1.1.1.2 lukem char *trunc, *idxp, *endp, *endp2;
846 1.1 lukem
847 1.1.1.2 lukem fname_len = strlen( dir->d_name );
848 1.1.1.2 lukem if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */
849 1.1 lukem continue;
850 1.1.1.2 lukem if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF ))
851 1.1 lukem continue;
852 1.1 lukem
853 1.1.1.2 lukem if ( *fname_maxlenp < fname_len )
854 1.1.1.2 lukem *fname_maxlenp = fname_len;
855 1.1.1.2 lukem
856 1.1.1.2 lukem bvl = SLAP_MALLOC( BVL_SIZE( fname_len ) );
857 1.1.1.2 lukem if ( bvl == NULL ) {
858 1.1.1.2 lukem rc = LDAP_OTHER;
859 1.1.1.2 lukem save_errno = errno;
860 1.1.1.2 lukem break;
861 1.1 lukem }
862 1.1.1.2 lukem strcpy( BVL_NAME( bvl ), dir->d_name );
863 1.1 lukem
864 1.1.1.2 lukem /* Make it sortable by ("attr=val" or <preceding {num}, num>) */
865 1.1.1.2 lukem trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF );
866 1.1.1.2 lukem if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL &&
867 1.1.1.2 lukem (endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp &&
868 1.1.1.2 lukem (eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) )
869 1.1.1.2 lukem {
870 1.1.1.2 lukem /* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */
871 1.1.1.2 lukem bvl->inum = strtol( idxp, &endp2, 10 );
872 1.1.1.2 lukem if ( endp2 == endp ) {
873 1.1.1.2 lukem trunc = idxp;
874 1.1.1.2 lukem goto truncate;
875 1.1.1.2 lukem }
876 1.1.1.2 lukem }
877 1.1.1.2 lukem bvl->inum = INT_MIN;
878 1.1.1.2 lukem truncate:
879 1.1.1.2 lukem bvl->trunc = trunc;
880 1.1.1.2 lukem bvl->savech = *trunc;
881 1.1.1.2 lukem *trunc = '\0';
882 1.1.1.2 lukem
883 1.1.1.2 lukem /* Insertion sort */
884 1.1.1.2 lukem for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) {
885 1.1.1.2 lukem int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr ));
886 1.1.1.2 lukem if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) )
887 1.1 lukem break;
888 1.1 lukem }
889 1.1 lukem *prev = bvl;
890 1.1 lukem bvl->next = ptr;
891 1.1 lukem }
892 1.1 lukem
893 1.1.1.2 lukem if ( closedir( dir_of_path ) < 0 ) {
894 1.1.1.2 lukem save_errno = errno;
895 1.1.1.2 lukem rc = LDAP_OTHER;
896 1.1.1.2 lukem if ( rs != NULL )
897 1.1.1.2 lukem rs->sr_text = "internal error (bad directory)";
898 1.1.1.2 lukem }
899 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
900 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_search_entry: %s \"%s\": %s\n",
901 1.1.1.2 lukem "error reading directory", path->bv_val,
902 1.1.1.2 lukem STRERROR( save_errno ) );
903 1.1 lukem }
904 1.1 lukem }
905 1.1.1.2 lukem
906 1.1 lukem return rc;
907 1.1 lukem }
908 1.1 lukem
909 1.1.1.2 lukem /*
910 1.1.1.2 lukem * Send an entry, recursively search its children, and free or save it.
911 1.1.1.2 lukem * Return an LDAP result code. Parameters:
912 1.1.1.2 lukem * op, rs operation and reply. rs == NULL for slap tools.
913 1.1.1.2 lukem * e entry to search, or NULL for rootDSE.
914 1.1.1.2 lukem * scope scope for the part of the search from this entry.
915 1.1.1.2 lukem * path LDIF filename -- bv_len and non-directory part are overwritten.
916 1.1.1.2 lukem */
917 1.1 lukem static int
918 1.1.1.2 lukem ldif_search_entry(
919 1.1.1.2 lukem Operation *op,
920 1.1.1.2 lukem SlapReply *rs,
921 1.1.1.2 lukem Entry *e,
922 1.1.1.2 lukem int scope,
923 1.1.1.2 lukem struct berval *path )
924 1.1 lukem {
925 1.1.1.2 lukem int rc = LDAP_SUCCESS;
926 1.1.1.2 lukem struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" );
927 1.1.1.2 lukem
928 1.1.1.2 lukem if ( scope != LDAP_SCOPE_BASE && e != NULL ) {
929 1.1.1.2 lukem /* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE,
930 1.1.1.2 lukem * which bconfig.c seems to need. (TODO: see config_rename_one.)
931 1.1.1.2 lukem */
932 1.1.1.2 lukem if ( ber_dupbv( &dn, &e->e_name ) == NULL ||
933 1.1.1.2 lukem ber_dupbv( &ndn, &e->e_nname ) == NULL )
934 1.1.1.2 lukem {
935 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
936 1.1.1.2 lukem "ldif_search_entry: out of memory\n", 0, 0, 0 );
937 1.1.1.2 lukem rc = LDAP_OTHER;
938 1.1.1.2 lukem goto done;
939 1.1.1.2 lukem }
940 1.1.1.2 lukem }
941 1.1.1.2 lukem
942 1.1.1.2 lukem /* Send the entry if appropriate, and free or save it */
943 1.1.1.2 lukem if ( e != NULL )
944 1.1.1.2 lukem rc = ldif_send_entry( op, rs, e, scope );
945 1.1.1.2 lukem
946 1.1.1.2 lukem /* Search the children */
947 1.1.1.2 lukem if ( scope != LDAP_SCOPE_BASE && rc == LDAP_SUCCESS ) {
948 1.1.1.2 lukem bvlist *list, *ptr;
949 1.1.1.2 lukem struct berval fpath; /* becomes child pathname */
950 1.1.1.2 lukem char *dir_end; /* will point past dirname in fpath */
951 1.1.1.2 lukem
952 1.1.1.2 lukem ldif2dir_len( *path );
953 1.1.1.2 lukem ldif2dir_name( *path );
954 1.1.1.2 lukem rc = ldif_readdir( op, rs, path, &list, &fpath.bv_len );
955 1.1.1.2 lukem
956 1.1.1.2 lukem if ( list != NULL ) {
957 1.1.1.2 lukem const char **text = rs == NULL ? NULL : &rs->sr_text;
958 1.1.1.2 lukem
959 1.1.1.2 lukem if ( scope == LDAP_SCOPE_ONELEVEL )
960 1.1.1.2 lukem scope = LDAP_SCOPE_BASE;
961 1.1.1.2 lukem else if ( scope == LDAP_SCOPE_SUBORDINATE )
962 1.1.1.2 lukem scope = LDAP_SCOPE_SUBTREE;
963 1.1.1.2 lukem
964 1.1.1.2 lukem /* Allocate fpath and fill in directory part */
965 1.1.1.2 lukem dir_end = fullpath_alloc( &fpath, path, fpath.bv_len );
966 1.1.1.2 lukem if ( dir_end == NULL )
967 1.1.1.2 lukem rc = LDAP_OTHER;
968 1.1.1.2 lukem
969 1.1.1.2 lukem do {
970 1.1.1.2 lukem ptr = list;
971 1.1.1.2 lukem
972 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
973 1.1.1.2 lukem *ptr->trunc = ptr->savech;
974 1.1.1.2 lukem FILL_PATH( &fpath, dir_end, BVL_NAME( ptr ));
975 1.1.1.2 lukem
976 1.1.1.2 lukem rc = ldif_read_entry( op, fpath.bv_val, &dn, &ndn,
977 1.1.1.2 lukem &e, text );
978 1.1.1.2 lukem switch ( rc ) {
979 1.1.1.2 lukem case LDAP_SUCCESS:
980 1.1.1.2 lukem rc = ldif_search_entry( op, rs, e, scope, &fpath );
981 1.1.1.2 lukem break;
982 1.1.1.2 lukem case LDAP_NO_SUCH_OBJECT:
983 1.1.1.2 lukem /* Only the search baseDN may produce noSuchObject. */
984 1.1.1.2 lukem rc = LDAP_OTHER;
985 1.1.1.2 lukem if ( rs != NULL )
986 1.1.1.2 lukem rs->sr_text = "internal error "
987 1.1.1.2 lukem "(did someone just remove an entry file?)";
988 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_search_entry: "
989 1.1.1.2 lukem "file listed in parent directory does not exist: "
990 1.1.1.2 lukem "\"%s\"\n", fpath.bv_val, 0, 0 );
991 1.1.1.2 lukem break;
992 1.1.1.2 lukem }
993 1.1.1.2 lukem }
994 1.1.1.2 lukem
995 1.1.1.2 lukem list = ptr->next;
996 1.1.1.2 lukem SLAP_FREE( ptr );
997 1.1.1.2 lukem } while ( list != NULL );
998 1.1.1.2 lukem
999 1.1.1.2 lukem if ( !BER_BVISNULL( &fpath ) )
1000 1.1.1.2 lukem SLAP_FREE( fpath.bv_val );
1001 1.1.1.2 lukem }
1002 1.1.1.2 lukem }
1003 1.1.1.2 lukem
1004 1.1.1.2 lukem done:
1005 1.1.1.2 lukem if ( !BER_BVISEMPTY( &dn ) )
1006 1.1.1.2 lukem ber_memfree( dn.bv_val );
1007 1.1.1.2 lukem if ( !BER_BVISEMPTY( &ndn ) )
1008 1.1.1.2 lukem ber_memfree( ndn.bv_val );
1009 1.1.1.2 lukem return rc;
1010 1.1.1.2 lukem }
1011 1.1.1.2 lukem
1012 1.1.1.2 lukem static int
1013 1.1.1.2 lukem search_tree( Operation *op, SlapReply *rs )
1014 1.1.1.2 lukem {
1015 1.1.1.2 lukem int rc = LDAP_SUCCESS;
1016 1.1.1.2 lukem Entry *e = NULL;
1017 1.1 lukem struct berval path;
1018 1.1 lukem struct berval pdn, pndn;
1019 1.1 lukem
1020 1.1.1.2 lukem (void) ndn2path( op, &op->o_req_ndn, &path, 1 );
1021 1.1.1.2 lukem if ( !BER_BVISEMPTY( &op->o_req_ndn ) ) {
1022 1.1.1.2 lukem /* Read baseObject */
1023 1.1.1.2 lukem dnParent( &op->o_req_dn, &pdn );
1024 1.1.1.2 lukem dnParent( &op->o_req_ndn, &pndn );
1025 1.1.1.2 lukem rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, &e,
1026 1.1.1.2 lukem rs == NULL ? NULL : &rs->sr_text );
1027 1.1.1.2 lukem }
1028 1.1.1.2 lukem if ( rc == LDAP_SUCCESS )
1029 1.1.1.2 lukem rc = ldif_search_entry( op, rs, e, op->ors_scope, &path );
1030 1.1.1.2 lukem
1031 1.1 lukem ch_free( path.bv_val );
1032 1.1 lukem return rc;
1033 1.1 lukem }
1034 1.1 lukem
1035 1.1 lukem
1036 1.1.1.2 lukem /*
1037 1.1.1.2 lukem * Prepare to create or rename an entry:
1038 1.1.1.2 lukem * Check that the entry does not already exist.
1039 1.1.1.2 lukem * Check that the parent entry exists and can have subordinates,
1040 1.1.1.2 lukem * unless need_dir is NULL or adding the suffix entry.
1041 1.1.1.2 lukem *
1042 1.1.1.2 lukem * Return an LDAP result code. May set *text to a message on failure.
1043 1.1.1.2 lukem * If success, set *dnpath to LDIF entry path and *need_dir to
1044 1.1.1.2 lukem * (directory must be created ? dirname : NULL).
1045 1.1.1.2 lukem */
1046 1.1.1.2 lukem static int
1047 1.1.1.2 lukem ldif_prepare_create(
1048 1.1.1.2 lukem Operation *op,
1049 1.1.1.2 lukem Entry *e,
1050 1.1.1.2 lukem struct berval *dnpath,
1051 1.1.1.2 lukem char **need_dir,
1052 1.1.1.2 lukem const char **text )
1053 1.1 lukem {
1054 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1055 1.1.1.2 lukem struct berval *ndn = &e->e_nname;
1056 1.1.1.2 lukem struct berval ppath = BER_BVNULL;
1057 1.1.1.2 lukem struct stat st;
1058 1.1.1.2 lukem Entry *parent = NULL;
1059 1.1.1.2 lukem int rc;
1060 1.1.1.2 lukem
1061 1.1.1.2 lukem if ( op->o_abandon )
1062 1.1.1.2 lukem return SLAPD_ABANDON;
1063 1.1.1.2 lukem
1064 1.1.1.2 lukem rc = ndn2path( op, ndn, dnpath, 0 );
1065 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1066 1.1.1.2 lukem return rc;
1067 1.1.1.2 lukem }
1068 1.1.1.2 lukem
1069 1.1.1.2 lukem if ( stat( dnpath->bv_val, &st ) == 0 ) { /* entry .ldif file */
1070 1.1.1.2 lukem rc = LDAP_ALREADY_EXISTS;
1071 1.1.1.2 lukem
1072 1.1.1.2 lukem } else if ( errno != ENOENT ) {
1073 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
1074 1.1.1.2 lukem "ldif_prepare_create: cannot stat \"%s\": %s\n",
1075 1.1.1.2 lukem dnpath->bv_val, STRERROR( errno ), 0 );
1076 1.1.1.2 lukem rc = LDAP_OTHER;
1077 1.1.1.2 lukem *text = "internal error (cannot check entry file)";
1078 1.1.1.2 lukem
1079 1.1.1.2 lukem } else if ( need_dir != NULL ) {
1080 1.1.1.2 lukem *need_dir = NULL;
1081 1.1.1.2 lukem rc = get_parent_path( dnpath, &ppath );
1082 1.1.1.2 lukem /* If parent dir exists, so does parent .ldif:
1083 1.1.1.2 lukem * The directory gets created after and removed before the .ldif.
1084 1.1.1.2 lukem * Except with the database directory, which has no matching entry.
1085 1.1.1.2 lukem */
1086 1.1.1.2 lukem if ( rc == LDAP_SUCCESS && stat( ppath.bv_val, &st ) < 0 ) {
1087 1.1.1.2 lukem rc = errno == ENOENT && ppath.bv_len > li->li_base_path.bv_len
1088 1.1.1.2 lukem ? LDAP_NO_SUCH_OBJECT : LDAP_OTHER;
1089 1.1.1.2 lukem }
1090 1.1.1.2 lukem switch ( rc ) {
1091 1.1.1.2 lukem case LDAP_NO_SUCH_OBJECT:
1092 1.1.1.2 lukem /* No parent dir, check parent .ldif */
1093 1.1.1.2 lukem dir2ldif_name( ppath );
1094 1.1.1.2 lukem rc = ldif_read_entry( op, ppath.bv_val, NULL, NULL,
1095 1.1.1.2 lukem (op->o_tag != LDAP_REQ_ADD || get_manageDSAit( op )
1096 1.1.1.2 lukem ? &parent : NULL),
1097 1.1.1.2 lukem text );
1098 1.1.1.2 lukem switch ( rc ) {
1099 1.1.1.2 lukem case LDAP_SUCCESS:
1100 1.1.1.2 lukem /* Check that parent is not a referral, unless
1101 1.1.1.2 lukem * ldif_back_referrals() already checked.
1102 1.1.1.2 lukem */
1103 1.1.1.2 lukem if ( parent != NULL ) {
1104 1.1.1.2 lukem int is_ref = is_entry_referral( parent );
1105 1.1.1.2 lukem entry_free( parent );
1106 1.1.1.2 lukem if ( is_ref ) {
1107 1.1.1.2 lukem rc = LDAP_AFFECTS_MULTIPLE_DSAS;
1108 1.1.1.2 lukem *text = op->o_tag == LDAP_REQ_MODDN
1109 1.1.1.2 lukem ? "newSuperior is a referral object"
1110 1.1.1.2 lukem : "parent is a referral object";
1111 1.1.1.2 lukem break;
1112 1.1.1.2 lukem }
1113 1.1.1.2 lukem }
1114 1.1.1.2 lukem /* Must create parent directory. */
1115 1.1.1.2 lukem ldif2dir_name( ppath );
1116 1.1.1.2 lukem *need_dir = ppath.bv_val;
1117 1.1.1.2 lukem break;
1118 1.1.1.2 lukem case LDAP_NO_SUCH_OBJECT:
1119 1.1.1.2 lukem *text = op->o_tag == LDAP_REQ_MODDN
1120 1.1.1.2 lukem ? "newSuperior object does not exist"
1121 1.1.1.2 lukem : "parent does not exist";
1122 1.1.1.2 lukem break;
1123 1.1.1.2 lukem }
1124 1.1 lukem break;
1125 1.1.1.2 lukem case LDAP_OTHER:
1126 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
1127 1.1.1.2 lukem "ldif_prepare_create: cannot stat \"%s\" parent dir: %s\n",
1128 1.1.1.2 lukem ndn->bv_val, STRERROR( errno ), 0 );
1129 1.1.1.2 lukem *text = "internal error (cannot stat parent dir)";
1130 1.1.1.2 lukem break;
1131 1.1.1.2 lukem }
1132 1.1.1.2 lukem if ( *need_dir == NULL && ppath.bv_val != NULL )
1133 1.1.1.2 lukem SLAP_FREE( ppath.bv_val );
1134 1.1.1.2 lukem }
1135 1.1.1.2 lukem
1136 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1137 1.1.1.2 lukem SLAP_FREE( dnpath->bv_val );
1138 1.1.1.2 lukem BER_BVZERO( dnpath );
1139 1.1.1.2 lukem }
1140 1.1.1.2 lukem return rc;
1141 1.1 lukem }
1142 1.1 lukem
1143 1.1.1.2 lukem static int
1144 1.1.1.2 lukem apply_modify_to_entry(
1145 1.1.1.2 lukem Entry *entry,
1146 1.1.1.2 lukem Modifications *modlist,
1147 1.1.1.2 lukem Operation *op,
1148 1.1.1.4 tron SlapReply *rs,
1149 1.1.1.4 tron char *textbuf )
1150 1.1 lukem {
1151 1.1 lukem int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
1152 1.1 lukem int is_oc = 0;
1153 1.1 lukem Modification *mods;
1154 1.1 lukem
1155 1.1 lukem if (!acl_check_modlist(op, entry, modlist)) {
1156 1.1 lukem return LDAP_INSUFFICIENT_ACCESS;
1157 1.1 lukem }
1158 1.1 lukem
1159 1.1 lukem for (; modlist != NULL; modlist = modlist->sml_next) {
1160 1.1 lukem mods = &modlist->sml_mod;
1161 1.1 lukem
1162 1.1 lukem if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
1163 1.1 lukem is_oc = 1;
1164 1.1 lukem }
1165 1.1 lukem switch (mods->sm_op) {
1166 1.1 lukem case LDAP_MOD_ADD:
1167 1.1 lukem rc = modify_add_values(entry, mods,
1168 1.1 lukem get_permissiveModify(op),
1169 1.1 lukem &rs->sr_text, textbuf,
1170 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1171 1.1 lukem break;
1172 1.1.1.2 lukem
1173 1.1 lukem case LDAP_MOD_DELETE:
1174 1.1 lukem rc = modify_delete_values(entry, mods,
1175 1.1 lukem get_permissiveModify(op),
1176 1.1 lukem &rs->sr_text, textbuf,
1177 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1178 1.1 lukem break;
1179 1.1.1.2 lukem
1180 1.1 lukem case LDAP_MOD_REPLACE:
1181 1.1 lukem rc = modify_replace_values(entry, mods,
1182 1.1 lukem get_permissiveModify(op),
1183 1.1 lukem &rs->sr_text, textbuf,
1184 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1185 1.1 lukem break;
1186 1.1 lukem
1187 1.1 lukem case LDAP_MOD_INCREMENT:
1188 1.1 lukem rc = modify_increment_values( entry,
1189 1.1 lukem mods, get_permissiveModify(op),
1190 1.1 lukem &rs->sr_text, textbuf,
1191 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1192 1.1 lukem break;
1193 1.1 lukem
1194 1.1 lukem case SLAP_MOD_SOFTADD:
1195 1.1 lukem mods->sm_op = LDAP_MOD_ADD;
1196 1.1 lukem rc = modify_add_values(entry, mods,
1197 1.1 lukem get_permissiveModify(op),
1198 1.1 lukem &rs->sr_text, textbuf,
1199 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1200 1.1 lukem mods->sm_op = SLAP_MOD_SOFTADD;
1201 1.1 lukem if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
1202 1.1 lukem rc = LDAP_SUCCESS;
1203 1.1 lukem }
1204 1.1 lukem break;
1205 1.1.1.4 tron
1206 1.1.1.4 tron case SLAP_MOD_SOFTDEL:
1207 1.1.1.4 tron mods->sm_op = LDAP_MOD_DELETE;
1208 1.1.1.4 tron rc = modify_delete_values(entry, mods,
1209 1.1.1.4 tron get_permissiveModify(op),
1210 1.1.1.4 tron &rs->sr_text, textbuf,
1211 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1212 1.1.1.4 tron mods->sm_op = SLAP_MOD_SOFTDEL;
1213 1.1.1.4 tron if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
1214 1.1.1.4 tron rc = LDAP_SUCCESS;
1215 1.1.1.4 tron }
1216 1.1.1.4 tron break;
1217 1.1.1.4 tron
1218 1.1.1.4 tron case SLAP_MOD_ADD_IF_NOT_PRESENT:
1219 1.1.1.4 tron if ( attr_find( entry->e_attrs, mods->sm_desc ) ) {
1220 1.1.1.4 tron rc = LDAP_SUCCESS;
1221 1.1.1.4 tron break;
1222 1.1.1.4 tron }
1223 1.1.1.4 tron mods->sm_op = LDAP_MOD_ADD;
1224 1.1.1.4 tron rc = modify_add_values(entry, mods,
1225 1.1.1.4 tron get_permissiveModify(op),
1226 1.1.1.4 tron &rs->sr_text, textbuf,
1227 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1228 1.1.1.4 tron mods->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
1229 1.1.1.4 tron break;
1230 1.1 lukem }
1231 1.1 lukem if(rc != LDAP_SUCCESS) break;
1232 1.1 lukem }
1233 1.1 lukem
1234 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1235 1.1.1.2 lukem rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */
1236 1.1 lukem if ( is_oc ) {
1237 1.1 lukem entry->e_ocflags = 0;
1238 1.1 lukem }
1239 1.1 lukem /* check that the entry still obeys the schema */
1240 1.1.1.2 lukem rc = entry_schema_check( op, entry, NULL, 0, 0, NULL,
1241 1.1.1.4 tron &rs->sr_text, textbuf, SLAP_TEXT_BUFLEN );
1242 1.1 lukem }
1243 1.1 lukem
1244 1.1 lukem return rc;
1245 1.1 lukem }
1246 1.1 lukem
1247 1.1.1.2 lukem
1248 1.1.1.2 lukem static int
1249 1.1 lukem ldif_back_referrals( Operation *op, SlapReply *rs )
1250 1.1 lukem {
1251 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1252 1.1.1.2 lukem struct berval path, dn = op->o_req_dn, ndn = op->o_req_ndn;
1253 1.1.1.2 lukem ber_len_t min_dnlen;
1254 1.1.1.2 lukem Entry *entry = NULL, **entryp;
1255 1.1.1.2 lukem BerVarray ref;
1256 1.1.1.2 lukem int rc;
1257 1.1 lukem
1258 1.1.1.2 lukem min_dnlen = op->o_bd->be_nsuffix[0].bv_len;
1259 1.1.1.2 lukem if ( min_dnlen == 0 ) {
1260 1.1.1.2 lukem /* Catch root DSE (empty DN), it is not a referral */
1261 1.1.1.2 lukem min_dnlen = 1;
1262 1.1 lukem }
1263 1.1.1.2 lukem if ( ndn2path( op, &ndn, &path, 0 ) != LDAP_SUCCESS ) {
1264 1.1.1.2 lukem return LDAP_SUCCESS; /* Root DSE again */
1265 1.1 lukem }
1266 1.1 lukem
1267 1.1.1.2 lukem entryp = get_manageDSAit( op ) ? NULL : &entry;
1268 1.1 lukem ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
1269 1.1 lukem
1270 1.1.1.2 lukem for (;;) {
1271 1.1.1.2 lukem dnParent( &dn, &dn );
1272 1.1.1.2 lukem dnParent( &ndn, &ndn );
1273 1.1.1.2 lukem rc = ldif_read_entry( op, path.bv_val, &dn, &ndn,
1274 1.1.1.2 lukem entryp, &rs->sr_text );
1275 1.1.1.2 lukem if ( rc != LDAP_NO_SUCH_OBJECT )
1276 1.1.1.2 lukem break;
1277 1.1 lukem
1278 1.1.1.2 lukem rc = LDAP_SUCCESS;
1279 1.1.1.2 lukem if ( ndn.bv_len < min_dnlen )
1280 1.1.1.2 lukem break;
1281 1.1.1.2 lukem (void) get_parent_path( &path, NULL );
1282 1.1.1.2 lukem dir2ldif_name( path );
1283 1.1.1.2 lukem entryp = &entry;
1284 1.1.1.2 lukem }
1285 1.1 lukem
1286 1.1.1.2 lukem ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
1287 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1288 1.1 lukem
1289 1.1.1.2 lukem if ( entry != NULL ) {
1290 1.1.1.2 lukem if ( is_entry_referral( entry ) ) {
1291 1.1 lukem Debug( LDAP_DEBUG_TRACE,
1292 1.1 lukem "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
1293 1.1.1.2 lukem (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_dn );
1294 1.1 lukem
1295 1.1.1.2 lukem ref = get_entry_referrals( op, entry );
1296 1.1.1.2 lukem rs->sr_ref = referral_rewrite( ref, &entry->e_name, &op->o_req_dn,
1297 1.1.1.2 lukem op->o_tag == LDAP_REQ_SEARCH ?
1298 1.1.1.2 lukem op->ors_scope : LDAP_SCOPE_DEFAULT );
1299 1.1.1.2 lukem ber_bvarray_free( ref );
1300 1.1.1.2 lukem
1301 1.1.1.2 lukem if ( rs->sr_ref != NULL ) {
1302 1.1.1.2 lukem /* send referral */
1303 1.1.1.2 lukem rc = rs->sr_err = LDAP_REFERRAL;
1304 1.1.1.2 lukem rs->sr_matched = entry->e_dn;
1305 1.1.1.2 lukem send_ldap_result( op, rs );
1306 1.1.1.2 lukem ber_bvarray_free( rs->sr_ref );
1307 1.1.1.2 lukem rs->sr_ref = NULL;
1308 1.1.1.2 lukem } else {
1309 1.1 lukem rc = LDAP_OTHER;
1310 1.1.1.2 lukem rs->sr_text = "bad referral object";
1311 1.1 lukem }
1312 1.1 lukem rs->sr_matched = NULL;
1313 1.1 lukem }
1314 1.1 lukem
1315 1.1.1.2 lukem entry_free( entry );
1316 1.1 lukem }
1317 1.1 lukem
1318 1.1 lukem return rc;
1319 1.1 lukem }
1320 1.1 lukem
1321 1.1 lukem
1322 1.1 lukem /* LDAP operations */
1323 1.1 lukem
1324 1.1 lukem static int
1325 1.1 lukem ldif_back_bind( Operation *op, SlapReply *rs )
1326 1.1 lukem {
1327 1.1 lukem struct ldif_info *li;
1328 1.1 lukem Attribute *a;
1329 1.1 lukem AttributeDescription *password = slap_schema.si_ad_userPassword;
1330 1.1 lukem int return_val;
1331 1.1.1.2 lukem Entry *entry = NULL;
1332 1.1 lukem
1333 1.1 lukem switch ( be_rootdn_bind( op, rs ) ) {
1334 1.1 lukem case SLAP_CB_CONTINUE:
1335 1.1 lukem break;
1336 1.1 lukem
1337 1.1 lukem default:
1338 1.1 lukem /* in case of success, front end will send result;
1339 1.1 lukem * otherwise, be_rootdn_bind() did */
1340 1.1 lukem return rs->sr_err;
1341 1.1 lukem }
1342 1.1 lukem
1343 1.1 lukem li = (struct ldif_info *) op->o_bd->be_private;
1344 1.1 lukem ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
1345 1.1.1.2 lukem return_val = get_entry(op, &entry, NULL, NULL);
1346 1.1 lukem
1347 1.1 lukem /* no object is found for them */
1348 1.1 lukem if(return_val != LDAP_SUCCESS) {
1349 1.1 lukem rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
1350 1.1 lukem goto return_result;
1351 1.1 lukem }
1352 1.1 lukem
1353 1.1 lukem /* they don't have userpassword */
1354 1.1 lukem if((a = attr_find(entry->e_attrs, password)) == NULL) {
1355 1.1 lukem rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
1356 1.1 lukem return_val = 1;
1357 1.1 lukem goto return_result;
1358 1.1 lukem }
1359 1.1 lukem
1360 1.1 lukem /* authentication actually failed */
1361 1.1 lukem if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred,
1362 1.1 lukem &rs->sr_text) != 0) {
1363 1.1 lukem rs->sr_err = LDAP_INVALID_CREDENTIALS;
1364 1.1 lukem return_val = 1;
1365 1.1 lukem goto return_result;
1366 1.1 lukem }
1367 1.1 lukem
1368 1.1 lukem /* let the front-end send success */
1369 1.1.1.2 lukem return_val = LDAP_SUCCESS;
1370 1.1 lukem
1371 1.1 lukem return_result:
1372 1.1 lukem ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
1373 1.1.1.2 lukem if(return_val != LDAP_SUCCESS)
1374 1.1 lukem send_ldap_result( op, rs );
1375 1.1 lukem if(entry != NULL)
1376 1.1 lukem entry_free(entry);
1377 1.1 lukem return return_val;
1378 1.1 lukem }
1379 1.1 lukem
1380 1.1.1.2 lukem static int
1381 1.1.1.2 lukem ldif_back_search( Operation *op, SlapReply *rs )
1382 1.1 lukem {
1383 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1384 1.1 lukem
1385 1.1 lukem ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
1386 1.1.1.2 lukem rs->sr_err = search_tree( op, rs );
1387 1.1 lukem ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
1388 1.1 lukem send_ldap_result(op, rs);
1389 1.1 lukem
1390 1.1 lukem return rs->sr_err;
1391 1.1 lukem }
1392 1.1 lukem
1393 1.1.1.2 lukem static int
1394 1.1.1.2 lukem ldif_back_add( Operation *op, SlapReply *rs )
1395 1.1.1.2 lukem {
1396 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1397 1.1 lukem Entry * e = op->ora_e;
1398 1.1.1.2 lukem struct berval path;
1399 1.1.1.2 lukem char *parentdir;
1400 1.1 lukem char textbuf[SLAP_TEXT_BUFLEN];
1401 1.1.1.2 lukem int rc;
1402 1.1 lukem
1403 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn, 0, 0 );
1404 1.1 lukem
1405 1.1.1.2 lukem rc = entry_schema_check( op, e, NULL, 0, 1, NULL,
1406 1.1 lukem &rs->sr_text, textbuf, sizeof( textbuf ) );
1407 1.1.1.2 lukem if ( rc != LDAP_SUCCESS )
1408 1.1.1.2 lukem goto send_res;
1409 1.1 lukem
1410 1.1.1.2 lukem rc = slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
1411 1.1.1.2 lukem if ( rc != LDAP_SUCCESS )
1412 1.1.1.2 lukem goto send_res;
1413 1.1.1.2 lukem
1414 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1415 1.1.1.2 lukem
1416 1.1.1.2 lukem rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text );
1417 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1418 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1419 1.1.1.2 lukem rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text );
1420 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1421 1.1.1.2 lukem
1422 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1423 1.1.1.2 lukem if ( parentdir != NULL )
1424 1.1.1.2 lukem SLAP_FREE( parentdir );
1425 1.1 lukem }
1426 1.1 lukem
1427 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1428 1.1 lukem
1429 1.1.1.2 lukem send_res:
1430 1.1.1.2 lukem rs->sr_err = rc;
1431 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n",
1432 1.1.1.2 lukem rc, rs->sr_text ? rs->sr_text : "", 0 );
1433 1.1.1.2 lukem send_ldap_result( op, rs );
1434 1.1 lukem slap_graduate_commit_csn( op );
1435 1.1.1.4 tron rs->sr_text = NULL; /* remove possible pointer to textbuf */
1436 1.1 lukem return rs->sr_err;
1437 1.1 lukem }
1438 1.1 lukem
1439 1.1.1.2 lukem static int
1440 1.1.1.2 lukem ldif_back_modify( Operation *op, SlapReply *rs )
1441 1.1.1.2 lukem {
1442 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1443 1.1 lukem Modifications * modlst = op->orm_modlist;
1444 1.1 lukem struct berval path;
1445 1.1 lukem Entry *entry;
1446 1.1.1.4 tron char textbuf[SLAP_TEXT_BUFLEN];
1447 1.1.1.2 lukem int rc;
1448 1.1 lukem
1449 1.1 lukem slap_mods_opattrs( op, &op->orm_modlist, 1 );
1450 1.1 lukem
1451 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1452 1.1 lukem
1453 1.1.1.2 lukem rc = get_entry( op, &entry, &path, &rs->sr_text );
1454 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1455 1.1.1.4 tron rc = apply_modify_to_entry( entry, modlst, op, rs, textbuf );
1456 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1457 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1458 1.1.1.2 lukem rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text );
1459 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1460 1.1 lukem }
1461 1.1 lukem
1462 1.1 lukem entry_free( entry );
1463 1.1 lukem SLAP_FREE( path.bv_val );
1464 1.1 lukem }
1465 1.1 lukem
1466 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1467 1.1.1.2 lukem
1468 1.1.1.2 lukem rs->sr_err = rc;
1469 1.1.1.2 lukem send_ldap_result( op, rs );
1470 1.1 lukem slap_graduate_commit_csn( op );
1471 1.1.1.4 tron rs->sr_text = NULL; /* remove possible pointer to textbuf */
1472 1.1 lukem return rs->sr_err;
1473 1.1 lukem }
1474 1.1 lukem
1475 1.1.1.2 lukem static int
1476 1.1.1.2 lukem ldif_back_delete( Operation *op, SlapReply *rs )
1477 1.1.1.2 lukem {
1478 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1479 1.1 lukem struct berval path;
1480 1.1.1.2 lukem int rc = LDAP_SUCCESS;
1481 1.1 lukem
1482 1.1 lukem if ( BER_BVISEMPTY( &op->o_csn )) {
1483 1.1 lukem struct berval csn;
1484 1.1.1.3 adam char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];
1485 1.1 lukem
1486 1.1 lukem csn.bv_val = csnbuf;
1487 1.1 lukem csn.bv_len = sizeof( csnbuf );
1488 1.1 lukem slap_get_csn( op, &csn, 1 );
1489 1.1 lukem }
1490 1.1 lukem
1491 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1492 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1493 1.1.1.2 lukem if ( op->o_abandon ) {
1494 1.1.1.2 lukem rc = SLAPD_ABANDON;
1495 1.1.1.2 lukem goto done;
1496 1.1.1.2 lukem }
1497 1.1.1.2 lukem
1498 1.1.1.2 lukem rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
1499 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1500 1.1.1.2 lukem goto done;
1501 1.1.1.2 lukem }
1502 1.1 lukem
1503 1.1.1.2 lukem ldif2dir_len( path );
1504 1.1.1.2 lukem ldif2dir_name( path );
1505 1.1.1.2 lukem if ( rmdir( path.bv_val ) < 0 ) {
1506 1.1 lukem switch ( errno ) {
1507 1.1 lukem case ENOTEMPTY:
1508 1.1.1.2 lukem rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
1509 1.1 lukem break;
1510 1.1 lukem case ENOENT:
1511 1.1 lukem /* is leaf, go on */
1512 1.1 lukem break;
1513 1.1 lukem default:
1514 1.1.1.2 lukem rc = LDAP_OTHER;
1515 1.1.1.2 lukem rs->sr_text = "internal error (cannot delete subtree directory)";
1516 1.1 lukem break;
1517 1.1 lukem }
1518 1.1 lukem }
1519 1.1 lukem
1520 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1521 1.1.1.2 lukem dir2ldif_name( path );
1522 1.1.1.2 lukem if ( unlink( path.bv_val ) < 0 ) {
1523 1.1.1.2 lukem rc = LDAP_NO_SUCH_OBJECT;
1524 1.1.1.2 lukem if ( errno != ENOENT ) {
1525 1.1.1.2 lukem rc = LDAP_OTHER;
1526 1.1.1.2 lukem rs->sr_text = "internal error (cannot delete entry file)";
1527 1.1 lukem }
1528 1.1 lukem }
1529 1.1 lukem }
1530 1.1 lukem
1531 1.1.1.2 lukem if ( rc == LDAP_OTHER ) {
1532 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_back_delete: %s \"%s\": %s\n",
1533 1.1.1.2 lukem "cannot delete", path.bv_val, STRERROR( errno ) );
1534 1.1.1.2 lukem }
1535 1.1.1.2 lukem
1536 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1537 1.1.1.2 lukem done:
1538 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1539 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1540 1.1.1.2 lukem rs->sr_err = rc;
1541 1.1.1.2 lukem send_ldap_result( op, rs );
1542 1.1 lukem slap_graduate_commit_csn( op );
1543 1.1 lukem return rs->sr_err;
1544 1.1 lukem }
1545 1.1 lukem
1546 1.1 lukem
1547 1.1 lukem static int
1548 1.1 lukem ldif_move_entry(
1549 1.1 lukem Operation *op,
1550 1.1 lukem Entry *entry,
1551 1.1.1.2 lukem int same_ndn,
1552 1.1.1.2 lukem struct berval *oldpath,
1553 1.1.1.2 lukem const char **text )
1554 1.1 lukem {
1555 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1556 1.1 lukem struct berval newpath;
1557 1.1.1.2 lukem char *parentdir = NULL, *trash;
1558 1.1.1.2 lukem int rc, rename_res;
1559 1.1 lukem
1560 1.1.1.2 lukem if ( same_ndn ) {
1561 1.1.1.2 lukem rc = LDAP_SUCCESS;
1562 1.1.1.2 lukem newpath = *oldpath;
1563 1.1.1.2 lukem } else {
1564 1.1.1.2 lukem rc = ldif_prepare_create( op, entry, &newpath,
1565 1.1.1.2 lukem op->orr_newSup ? &parentdir : NULL, text );
1566 1.1.1.2 lukem }
1567 1.1 lukem
1568 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1569 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1570 1.1.1.2 lukem
1571 1.1.1.2 lukem rc = ldif_write_entry( op, entry, &newpath, parentdir, text );
1572 1.1.1.2 lukem if ( rc == LDAP_SUCCESS && !same_ndn ) {
1573 1.1.1.2 lukem trash = oldpath->bv_val; /* will be .ldif file to delete */
1574 1.1.1.2 lukem ldif2dir_len( newpath );
1575 1.1.1.2 lukem ldif2dir_len( *oldpath );
1576 1.1.1.2 lukem /* Move subdir before deleting old entry,
1577 1.1.1.2 lukem * so .ldif always exists if subdir does.
1578 1.1.1.2 lukem */
1579 1.1.1.2 lukem ldif2dir_name( newpath );
1580 1.1.1.2 lukem ldif2dir_name( *oldpath );
1581 1.1.1.2 lukem rename_res = move_dir( oldpath->bv_val, newpath.bv_val );
1582 1.1.1.2 lukem if ( rename_res != 0 && errno != ENOENT ) {
1583 1.1.1.2 lukem rc = LDAP_OTHER;
1584 1.1.1.2 lukem *text = "internal error (cannot move this subtree)";
1585 1.1.1.2 lukem trash = newpath.bv_val;
1586 1.1 lukem }
1587 1.1.1.2 lukem
1588 1.1.1.2 lukem /* Delete old entry, or if error undo change */
1589 1.1.1.2 lukem for (;;) {
1590 1.1.1.2 lukem dir2ldif_name( newpath );
1591 1.1.1.2 lukem dir2ldif_name( *oldpath );
1592 1.1.1.2 lukem if ( unlink( trash ) == 0 )
1593 1.1.1.2 lukem break;
1594 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1595 1.1.1.2 lukem /* Prepare to undo change and return failure */
1596 1.1.1.2 lukem rc = LDAP_OTHER;
1597 1.1.1.2 lukem *text = "internal error (cannot move this entry)";
1598 1.1.1.2 lukem trash = newpath.bv_val;
1599 1.1.1.2 lukem if ( rename_res != 0 )
1600 1.1.1.2 lukem continue;
1601 1.1.1.2 lukem /* First move subdirectory back */
1602 1.1.1.2 lukem ldif2dir_name( newpath );
1603 1.1.1.2 lukem ldif2dir_name( *oldpath );
1604 1.1.1.2 lukem if ( move_dir( newpath.bv_val, oldpath->bv_val ) == 0 )
1605 1.1.1.2 lukem continue;
1606 1.1.1.2 lukem }
1607 1.1.1.2 lukem *text = "added new but couldn't delete old entry!";
1608 1.1.1.2 lukem break;
1609 1.1 lukem }
1610 1.1.1.2 lukem
1611 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1612 1.1.1.2 lukem char s[128];
1613 1.1.1.2 lukem snprintf( s, sizeof s, "%s (%s)", *text, STRERROR( errno ));
1614 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
1615 1.1.1.2 lukem "ldif_move_entry: %s: \"%s\" -> \"%s\"\n",
1616 1.1.1.2 lukem s, op->o_req_dn.bv_val, entry->e_dn );
1617 1.1 lukem }
1618 1.1 lukem }
1619 1.1.1.2 lukem
1620 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1621 1.1.1.2 lukem if ( !same_ndn )
1622 1.1.1.2 lukem SLAP_FREE( newpath.bv_val );
1623 1.1.1.2 lukem if ( parentdir != NULL )
1624 1.1.1.2 lukem SLAP_FREE( parentdir );
1625 1.1 lukem }
1626 1.1 lukem
1627 1.1.1.2 lukem return rc;
1628 1.1 lukem }
1629 1.1 lukem
1630 1.1 lukem static int
1631 1.1.1.2 lukem ldif_back_modrdn( Operation *op, SlapReply *rs )
1632 1.1 lukem {
1633 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1634 1.1 lukem struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
1635 1.1 lukem struct berval p_dn, old_path;
1636 1.1 lukem Entry *entry;
1637 1.1.1.4 tron char textbuf[SLAP_TEXT_BUFLEN];
1638 1.1.1.2 lukem int rc, same_ndn;
1639 1.1 lukem
1640 1.1 lukem slap_mods_opattrs( op, &op->orr_modlist, 1 );
1641 1.1 lukem
1642 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1643 1.1 lukem
1644 1.1.1.2 lukem rc = get_entry( op, &entry, &old_path, &rs->sr_text );
1645 1.1 lukem if ( rc == LDAP_SUCCESS ) {
1646 1.1 lukem /* build new dn, and new ndn for the entry */
1647 1.1 lukem if ( op->oq_modrdn.rs_newSup != NULL ) {
1648 1.1 lukem p_dn = *op->oq_modrdn.rs_newSup;
1649 1.1 lukem } else {
1650 1.1 lukem dnParent( &entry->e_name, &p_dn );
1651 1.1 lukem }
1652 1.1.1.2 lukem build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL );
1653 1.1 lukem dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
1654 1.1.1.2 lukem same_ndn = !ber_bvcmp( &entry->e_nname, &new_ndn );
1655 1.1 lukem ber_memfree_x( entry->e_name.bv_val, NULL );
1656 1.1 lukem ber_memfree_x( entry->e_nname.bv_val, NULL );
1657 1.1 lukem entry->e_name = new_dn;
1658 1.1 lukem entry->e_nname = new_ndn;
1659 1.1 lukem
1660 1.1 lukem /* perform the modifications */
1661 1.1.1.4 tron rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs, textbuf );
1662 1.1 lukem if ( rc == LDAP_SUCCESS )
1663 1.1.1.2 lukem rc = ldif_move_entry( op, entry, same_ndn, &old_path,
1664 1.1.1.2 lukem &rs->sr_text );
1665 1.1 lukem
1666 1.1 lukem entry_free( entry );
1667 1.1 lukem SLAP_FREE( old_path.bv_val );
1668 1.1 lukem }
1669 1.1 lukem
1670 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1671 1.1 lukem rs->sr_err = rc;
1672 1.1 lukem send_ldap_result( op, rs );
1673 1.1 lukem slap_graduate_commit_csn( op );
1674 1.1.1.4 tron rs->sr_text = NULL; /* remove possible pointer to textbuf */
1675 1.1 lukem return rs->sr_err;
1676 1.1 lukem }
1677 1.1 lukem
1678 1.1 lukem
1679 1.1 lukem /* Return LDAP_SUCCESS IFF we retrieve the specified entry. */
1680 1.1 lukem static int
1681 1.1 lukem ldif_back_entry_get(
1682 1.1 lukem Operation *op,
1683 1.1 lukem struct berval *ndn,
1684 1.1 lukem ObjectClass *oc,
1685 1.1 lukem AttributeDescription *at,
1686 1.1 lukem int rw,
1687 1.1 lukem Entry **e )
1688 1.1 lukem {
1689 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1690 1.1 lukem struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn;
1691 1.1 lukem int rc;
1692 1.1 lukem
1693 1.1 lukem assert( ndn != NULL );
1694 1.1 lukem assert( !BER_BVISNULL( ndn ) );
1695 1.1 lukem
1696 1.1 lukem ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
1697 1.1 lukem op->o_req_dn = *ndn;
1698 1.1 lukem op->o_req_ndn = *ndn;
1699 1.1.1.2 lukem rc = get_entry( op, e, NULL, NULL );
1700 1.1 lukem op->o_req_dn = op_dn;
1701 1.1 lukem op->o_req_ndn = op_ndn;
1702 1.1 lukem ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
1703 1.1 lukem
1704 1.1 lukem if ( rc == LDAP_SUCCESS && oc && !is_entry_objectclass_or_sub( *e, oc ) ) {
1705 1.1 lukem rc = LDAP_NO_SUCH_ATTRIBUTE;
1706 1.1 lukem entry_free( *e );
1707 1.1 lukem *e = NULL;
1708 1.1 lukem }
1709 1.1 lukem
1710 1.1 lukem return rc;
1711 1.1 lukem }
1712 1.1 lukem
1713 1.1 lukem
1714 1.1 lukem /* Slap tools */
1715 1.1 lukem
1716 1.1.1.2 lukem static int
1717 1.1.1.2 lukem ldif_tool_entry_open( BackendDB *be, int mode )
1718 1.1.1.2 lukem {
1719 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1720 1.1 lukem
1721 1.1.1.2 lukem tl->ecurrent = 0;
1722 1.1.1.2 lukem return 0;
1723 1.1.1.2 lukem }
1724 1.1 lukem
1725 1.1.1.2 lukem static int
1726 1.1.1.2 lukem ldif_tool_entry_close( BackendDB *be )
1727 1.1.1.2 lukem {
1728 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1729 1.1.1.2 lukem Entry **entries = tl->entries;
1730 1.1.1.2 lukem ID i;
1731 1.1.1.2 lukem
1732 1.1.1.2 lukem for ( i = tl->ecount; i--; )
1733 1.1.1.2 lukem if ( entries[i] )
1734 1.1.1.2 lukem entry_free( entries[i] );
1735 1.1.1.2 lukem SLAP_FREE( entries );
1736 1.1.1.2 lukem tl->entries = NULL;
1737 1.1.1.2 lukem tl->ecount = tl->elen = 0;
1738 1.1 lukem return 0;
1739 1.1 lukem }
1740 1.1 lukem
1741 1.1.1.2 lukem static ID
1742 1.1.1.2 lukem ldif_tool_entry_next( BackendDB *be )
1743 1.1 lukem {
1744 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1745 1.1.1.2 lukem
1746 1.1.1.3 adam do {
1747 1.1.1.3 adam Entry *e = tl->entries[ tl->ecurrent ];
1748 1.1.1.3 adam
1749 1.1.1.3 adam if ( tl->ecurrent >= tl->ecount ) {
1750 1.1.1.3 adam return NOID;
1751 1.1.1.3 adam }
1752 1.1.1.3 adam
1753 1.1.1.3 adam ++tl->ecurrent;
1754 1.1.1.3 adam
1755 1.1.1.3 adam if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) {
1756 1.1.1.3 adam continue;
1757 1.1.1.3 adam }
1758 1.1.1.3 adam
1759 1.1.1.3 adam if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter ) != LDAP_COMPARE_TRUE ) {
1760 1.1.1.3 adam continue;
1761 1.1.1.3 adam }
1762 1.1.1.3 adam
1763 1.1.1.3 adam break;
1764 1.1.1.3 adam } while ( 1 );
1765 1.1.1.3 adam
1766 1.1.1.3 adam return tl->ecurrent;
1767 1.1 lukem }
1768 1.1 lukem
1769 1.1 lukem static ID
1770 1.1.1.3 adam ldif_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f )
1771 1.1 lukem {
1772 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1773 1.1 lukem
1774 1.1.1.3 adam tl->tl_base = base;
1775 1.1.1.3 adam tl->tl_scope = scope;
1776 1.1.1.3 adam tl->tl_filter = f;
1777 1.1.1.3 adam
1778 1.1.1.2 lukem if ( tl->entries == NULL ) {
1779 1.1 lukem Operation op = {0};
1780 1.1 lukem
1781 1.1 lukem op.o_bd = be;
1782 1.1 lukem op.o_req_dn = *be->be_suffix;
1783 1.1 lukem op.o_req_ndn = *be->be_nsuffix;
1784 1.1 lukem op.ors_scope = LDAP_SCOPE_SUBTREE;
1785 1.1.1.2 lukem if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) {
1786 1.1.1.2 lukem tl->ecurrent = tl->ecount; /* fail ldif_tool_entry_next() */
1787 1.1.1.4 tron return NOID; /* fail ldif_tool_entry_get() */
1788 1.1.1.2 lukem }
1789 1.1 lukem }
1790 1.1 lukem return ldif_tool_entry_next( be );
1791 1.1 lukem }
1792 1.1 lukem
1793 1.1.1.2 lukem static Entry *
1794 1.1.1.2 lukem ldif_tool_entry_get( BackendDB *be, ID id )
1795 1.1.1.2 lukem {
1796 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1797 1.1.1.2 lukem Entry *e = NULL;
1798 1.1 lukem
1799 1.1.1.2 lukem --id;
1800 1.1.1.2 lukem if ( id < tl->ecount ) {
1801 1.1.1.2 lukem e = tl->entries[id];
1802 1.1.1.2 lukem tl->entries[id] = NULL;
1803 1.1 lukem }
1804 1.1.1.2 lukem return e;
1805 1.1 lukem }
1806 1.1 lukem
1807 1.1.1.2 lukem static ID
1808 1.1.1.2 lukem ldif_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
1809 1.1.1.2 lukem {
1810 1.1.1.2 lukem int rc;
1811 1.1.1.2 lukem const char *errmsg = NULL;
1812 1.1.1.2 lukem struct berval path;
1813 1.1.1.2 lukem char *parentdir;
1814 1.1.1.2 lukem Operation op = {0};
1815 1.1 lukem
1816 1.1.1.2 lukem op.o_bd = be;
1817 1.1.1.2 lukem rc = ldif_prepare_create( &op, e, &path, &parentdir, &errmsg );
1818 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1819 1.1.1.2 lukem rc = ldif_write_entry( &op, e, &path, parentdir, &errmsg );
1820 1.1.1.2 lukem
1821 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1822 1.1.1.2 lukem if ( parentdir != NULL )
1823 1.1.1.2 lukem SLAP_FREE( parentdir );
1824 1.1.1.2 lukem if ( rc == LDAP_SUCCESS )
1825 1.1.1.2 lukem return 1;
1826 1.1 lukem }
1827 1.1.1.2 lukem
1828 1.1.1.2 lukem if ( errmsg == NULL && rc != LDAP_OTHER )
1829 1.1.1.2 lukem errmsg = ldap_err2string( rc );
1830 1.1.1.2 lukem if ( errmsg != NULL )
1831 1.1.1.2 lukem snprintf( text->bv_val, text->bv_len, "%s", errmsg );
1832 1.1.1.2 lukem return NOID;
1833 1.1 lukem }
1834 1.1 lukem
1835 1.1 lukem
1836 1.1 lukem /* Setup */
1837 1.1 lukem
1838 1.1 lukem static int
1839 1.1 lukem ldif_back_db_init( BackendDB *be, ConfigReply *cr )
1840 1.1 lukem {
1841 1.1 lukem struct ldif_info *li;
1842 1.1 lukem
1843 1.1 lukem li = ch_calloc( 1, sizeof(struct ldif_info) );
1844 1.1 lukem be->be_private = li;
1845 1.1 lukem be->be_cf_ocs = ldifocs;
1846 1.1.1.2 lukem ldap_pvt_thread_mutex_init( &li->li_modop_mutex );
1847 1.1.1.2 lukem ldap_pvt_thread_rdwr_init( &li->li_rdwr );
1848 1.1 lukem SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
1849 1.1 lukem return 0;
1850 1.1 lukem }
1851 1.1 lukem
1852 1.1 lukem static int
1853 1.1 lukem ldif_back_db_destroy( Backend *be, ConfigReply *cr )
1854 1.1 lukem {
1855 1.1 lukem struct ldif_info *li = be->be_private;
1856 1.1 lukem
1857 1.1.1.2 lukem ch_free( li->li_base_path.bv_val );
1858 1.1.1.2 lukem ldap_pvt_thread_rdwr_destroy( &li->li_rdwr );
1859 1.1.1.2 lukem ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex );
1860 1.1 lukem free( be->be_private );
1861 1.1 lukem return 0;
1862 1.1 lukem }
1863 1.1 lukem
1864 1.1 lukem static int
1865 1.1.1.2 lukem ldif_back_db_open( Backend *be, ConfigReply *cr )
1866 1.1 lukem {
1867 1.1 lukem struct ldif_info *li = (struct ldif_info *) be->be_private;
1868 1.1 lukem if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
1869 1.1 lukem Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n", 0, 0, 0);
1870 1.1 lukem return 1;
1871 1.1 lukem }
1872 1.1 lukem return 0;
1873 1.1 lukem }
1874 1.1 lukem
1875 1.1 lukem int
1876 1.1.1.2 lukem ldif_back_initialize( BackendInfo *bi )
1877 1.1 lukem {
1878 1.1 lukem static char *controls[] = {
1879 1.1 lukem LDAP_CONTROL_MANAGEDSAIT,
1880 1.1 lukem NULL
1881 1.1 lukem };
1882 1.1 lukem int rc;
1883 1.1 lukem
1884 1.1 lukem bi->bi_flags |=
1885 1.1 lukem SLAP_BFLAG_INCREMENT |
1886 1.1 lukem SLAP_BFLAG_REFERRALS;
1887 1.1 lukem
1888 1.1 lukem bi->bi_controls = controls;
1889 1.1 lukem
1890 1.1 lukem bi->bi_open = 0;
1891 1.1 lukem bi->bi_close = 0;
1892 1.1 lukem bi->bi_config = 0;
1893 1.1 lukem bi->bi_destroy = 0;
1894 1.1 lukem
1895 1.1 lukem bi->bi_db_init = ldif_back_db_init;
1896 1.1 lukem bi->bi_db_config = config_generic_wrapper;
1897 1.1 lukem bi->bi_db_open = ldif_back_db_open;
1898 1.1 lukem bi->bi_db_close = 0;
1899 1.1 lukem bi->bi_db_destroy = ldif_back_db_destroy;
1900 1.1 lukem
1901 1.1 lukem bi->bi_op_bind = ldif_back_bind;
1902 1.1 lukem bi->bi_op_unbind = 0;
1903 1.1 lukem bi->bi_op_search = ldif_back_search;
1904 1.1 lukem bi->bi_op_compare = 0;
1905 1.1 lukem bi->bi_op_modify = ldif_back_modify;
1906 1.1 lukem bi->bi_op_modrdn = ldif_back_modrdn;
1907 1.1 lukem bi->bi_op_add = ldif_back_add;
1908 1.1 lukem bi->bi_op_delete = ldif_back_delete;
1909 1.1 lukem bi->bi_op_abandon = 0;
1910 1.1 lukem
1911 1.1 lukem bi->bi_extended = 0;
1912 1.1 lukem
1913 1.1 lukem bi->bi_chk_referrals = ldif_back_referrals;
1914 1.1 lukem
1915 1.1 lukem bi->bi_connection_init = 0;
1916 1.1 lukem bi->bi_connection_destroy = 0;
1917 1.1 lukem
1918 1.1 lukem bi->bi_entry_get_rw = ldif_back_entry_get;
1919 1.1 lukem
1920 1.1 lukem #if 0 /* NOTE: uncomment to completely disable access control */
1921 1.1 lukem bi->bi_access_allowed = slap_access_always_allowed;
1922 1.1 lukem #endif
1923 1.1 lukem
1924 1.1 lukem bi->bi_tool_entry_open = ldif_tool_entry_open;
1925 1.1 lukem bi->bi_tool_entry_close = ldif_tool_entry_close;
1926 1.1.1.3 adam bi->bi_tool_entry_first = backend_tool_entry_first;
1927 1.1.1.3 adam bi->bi_tool_entry_first_x = ldif_tool_entry_first_x;
1928 1.1 lukem bi->bi_tool_entry_next = ldif_tool_entry_next;
1929 1.1 lukem bi->bi_tool_entry_get = ldif_tool_entry_get;
1930 1.1 lukem bi->bi_tool_entry_put = ldif_tool_entry_put;
1931 1.1 lukem bi->bi_tool_entry_reindex = 0;
1932 1.1 lukem bi->bi_tool_sync = 0;
1933 1.1.1.2 lukem
1934 1.1 lukem bi->bi_tool_dn2id_get = 0;
1935 1.1 lukem bi->bi_tool_entry_modify = 0;
1936 1.1 lukem
1937 1.1 lukem bi->bi_cf_ocs = ldifocs;
1938 1.1 lukem
1939 1.1 lukem rc = config_register_schema( ldifcfg, ldifocs );
1940 1.1 lukem if ( rc ) return rc;
1941 1.1 lukem return 0;
1942 1.1 lukem }
1943