accesslog.c revision 1.1 1 1.1 lukem /* accesslog.c - log operations for audit/history purposes */
2 1.1 lukem /* $OpenLDAP: pkg/ldap/servers/slapd/overlays/accesslog.c,v 1.37.2.17 2008/05/01 20:37:48 quanah Exp $ */
3 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 1.1 lukem *
5 1.1 lukem * Copyright 2005-2008 The OpenLDAP Foundation.
6 1.1 lukem * Portions copyright 2004-2005 Symas Corporation.
7 1.1 lukem * All rights reserved.
8 1.1 lukem *
9 1.1 lukem * Redistribution and use in source and binary forms, with or without
10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
11 1.1 lukem * Public License.
12 1.1 lukem *
13 1.1 lukem * A copy of this license is available in the file LICENSE in the
14 1.1 lukem * top-level directory of the distribution or, alternatively, at
15 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
16 1.1 lukem */
17 1.1 lukem /* ACKNOWLEDGEMENTS:
18 1.1 lukem * This work was initially developed by Howard Chu for inclusion in
19 1.1 lukem * OpenLDAP Software.
20 1.1 lukem */
21 1.1 lukem
22 1.1 lukem #include "portable.h"
23 1.1 lukem
24 1.1 lukem #ifdef SLAPD_OVER_ACCESSLOG
25 1.1 lukem
26 1.1 lukem #include <stdio.h>
27 1.1 lukem
28 1.1 lukem #include <ac/string.h>
29 1.1 lukem #include <ac/ctype.h>
30 1.1 lukem
31 1.1 lukem #include "slap.h"
32 1.1 lukem #include "config.h"
33 1.1 lukem #include "lutil.h"
34 1.1 lukem #include "ldap_rq.h"
35 1.1 lukem
36 1.1 lukem #define LOG_OP_ADD 0x001
37 1.1 lukem #define LOG_OP_DELETE 0x002
38 1.1 lukem #define LOG_OP_MODIFY 0x004
39 1.1 lukem #define LOG_OP_MODRDN 0x008
40 1.1 lukem #define LOG_OP_COMPARE 0x010
41 1.1 lukem #define LOG_OP_SEARCH 0x020
42 1.1 lukem #define LOG_OP_BIND 0x040
43 1.1 lukem #define LOG_OP_UNBIND 0x080
44 1.1 lukem #define LOG_OP_ABANDON 0x100
45 1.1 lukem #define LOG_OP_EXTENDED 0x200
46 1.1 lukem #define LOG_OP_UNKNOWN 0x400
47 1.1 lukem
48 1.1 lukem #define LOG_OP_WRITES (LOG_OP_ADD|LOG_OP_DELETE|LOG_OP_MODIFY|LOG_OP_MODRDN)
49 1.1 lukem #define LOG_OP_READS (LOG_OP_COMPARE|LOG_OP_SEARCH)
50 1.1 lukem #define LOG_OP_SESSION (LOG_OP_BIND|LOG_OP_UNBIND|LOG_OP_ABANDON)
51 1.1 lukem #define LOG_OP_ALL (LOG_OP_READS|LOG_OP_WRITES|LOG_OP_SESSION| \
52 1.1 lukem LOG_OP_EXTENDED|LOG_OP_UNKNOWN)
53 1.1 lukem
54 1.1 lukem typedef struct log_attr {
55 1.1 lukem struct log_attr *next;
56 1.1 lukem AttributeDescription *attr;
57 1.1 lukem } log_attr;
58 1.1 lukem
59 1.1 lukem typedef struct log_info {
60 1.1 lukem BackendDB *li_db;
61 1.1 lukem struct berval li_db_suffix;
62 1.1 lukem slap_mask_t li_ops;
63 1.1 lukem int li_age;
64 1.1 lukem int li_cycle;
65 1.1 lukem struct re_s *li_task;
66 1.1 lukem Filter *li_oldf;
67 1.1 lukem Entry *li_old;
68 1.1 lukem log_attr *li_oldattrs;
69 1.1 lukem int li_success;
70 1.1 lukem ldap_pvt_thread_rmutex_t li_op_rmutex;
71 1.1 lukem ldap_pvt_thread_mutex_t li_log_mutex;
72 1.1 lukem } log_info;
73 1.1 lukem
74 1.1 lukem static ConfigDriver log_cf_gen;
75 1.1 lukem
76 1.1 lukem enum {
77 1.1 lukem LOG_DB = 1,
78 1.1 lukem LOG_OPS,
79 1.1 lukem LOG_PURGE,
80 1.1 lukem LOG_SUCCESS,
81 1.1 lukem LOG_OLD,
82 1.1 lukem LOG_OLDATTR
83 1.1 lukem };
84 1.1 lukem
85 1.1 lukem static ConfigTable log_cfats[] = {
86 1.1 lukem { "logdb", "suffix", 2, 2, 0, ARG_DN|ARG_MAGIC|LOG_DB,
87 1.1 lukem log_cf_gen, "( OLcfgOvAt:4.1 NAME 'olcAccessLogDB' "
88 1.1 lukem "DESC 'Suffix of database for log content' "
89 1.1 lukem "SUP distinguishedName SINGLE-VALUE )", NULL, NULL },
90 1.1 lukem { "logops", "op|writes|reads|session|all", 2, 0, 0,
91 1.1 lukem ARG_MAGIC|LOG_OPS,
92 1.1 lukem log_cf_gen, "( OLcfgOvAt:4.2 NAME 'olcAccessLogOps' "
93 1.1 lukem "DESC 'Operation types to log' "
94 1.1 lukem "EQUALITY caseIgnoreMatch "
95 1.1 lukem "SYNTAX OMsDirectoryString )", NULL, NULL },
96 1.1 lukem { "logpurge", "age> <interval", 3, 3, 0, ARG_MAGIC|LOG_PURGE,
97 1.1 lukem log_cf_gen, "( OLcfgOvAt:4.3 NAME 'olcAccessLogPurge' "
98 1.1 lukem "DESC 'Log cleanup parameters' "
99 1.1 lukem "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
100 1.1 lukem { "logsuccess", NULL, 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LOG_SUCCESS,
101 1.1 lukem log_cf_gen, "( OLcfgOvAt:4.4 NAME 'olcAccessLogSuccess' "
102 1.1 lukem "DESC 'Log successful ops only' "
103 1.1 lukem "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
104 1.1 lukem { "logold", "filter", 2, 2, 0, ARG_MAGIC|LOG_OLD,
105 1.1 lukem log_cf_gen, "( OLcfgOvAt:4.5 NAME 'olcAccessLogOld' "
106 1.1 lukem "DESC 'Log old values when modifying entries matching the filter' "
107 1.1 lukem "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
108 1.1 lukem { "logoldattr", "attrs", 2, 0, 0, ARG_MAGIC|LOG_OLDATTR,
109 1.1 lukem log_cf_gen, "( OLcfgOvAt:4.6 NAME 'olcAccessLogOldAttr' "
110 1.1 lukem "DESC 'Log old values of these attributes even if unmodified' "
111 1.1 lukem "EQUALITY caseIgnoreMatch "
112 1.1 lukem "SYNTAX OMsDirectoryString )", NULL, NULL },
113 1.1 lukem { NULL }
114 1.1 lukem };
115 1.1 lukem
116 1.1 lukem static ConfigOCs log_cfocs[] = {
117 1.1 lukem { "( OLcfgOvOc:4.1 "
118 1.1 lukem "NAME 'olcAccessLogConfig' "
119 1.1 lukem "DESC 'Access log configuration' "
120 1.1 lukem "SUP olcOverlayConfig "
121 1.1 lukem "MUST olcAccessLogDB "
122 1.1 lukem "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ "
123 1.1 lukem "olcAccessLogOld $ olcAccessLogOldAttr ) )",
124 1.1 lukem Cft_Overlay, log_cfats },
125 1.1 lukem { NULL }
126 1.1 lukem };
127 1.1 lukem
128 1.1 lukem static slap_verbmasks logops[] = {
129 1.1 lukem { BER_BVC("all"), LOG_OP_ALL },
130 1.1 lukem { BER_BVC("writes"), LOG_OP_WRITES },
131 1.1 lukem { BER_BVC("session"), LOG_OP_SESSION },
132 1.1 lukem { BER_BVC("reads"), LOG_OP_READS },
133 1.1 lukem { BER_BVC("add"), LOG_OP_ADD },
134 1.1 lukem { BER_BVC("delete"), LOG_OP_DELETE },
135 1.1 lukem { BER_BVC("modify"), LOG_OP_MODIFY },
136 1.1 lukem { BER_BVC("modrdn"), LOG_OP_MODRDN },
137 1.1 lukem { BER_BVC("compare"), LOG_OP_COMPARE },
138 1.1 lukem { BER_BVC("search"), LOG_OP_SEARCH },
139 1.1 lukem { BER_BVC("bind"), LOG_OP_BIND },
140 1.1 lukem { BER_BVC("unbind"), LOG_OP_UNBIND },
141 1.1 lukem { BER_BVC("abandon"), LOG_OP_ABANDON },
142 1.1 lukem { BER_BVC("extended"), LOG_OP_EXTENDED },
143 1.1 lukem { BER_BVC("unknown"), LOG_OP_UNKNOWN },
144 1.1 lukem { BER_BVNULL, 0 }
145 1.1 lukem };
146 1.1 lukem
147 1.1 lukem /* Start with "add" in logops */
148 1.1 lukem #define EN_OFFSET 4
149 1.1 lukem
150 1.1 lukem enum {
151 1.1 lukem LOG_EN_ADD = 0,
152 1.1 lukem LOG_EN_DELETE,
153 1.1 lukem LOG_EN_MODIFY,
154 1.1 lukem LOG_EN_MODRDN,
155 1.1 lukem LOG_EN_COMPARE,
156 1.1 lukem LOG_EN_SEARCH,
157 1.1 lukem LOG_EN_BIND,
158 1.1 lukem LOG_EN_UNBIND,
159 1.1 lukem LOG_EN_ABANDON,
160 1.1 lukem LOG_EN_EXTENDED,
161 1.1 lukem LOG_EN_UNKNOWN,
162 1.1 lukem LOG_EN__COUNT
163 1.1 lukem };
164 1.1 lukem
165 1.1 lukem static ObjectClass *log_ocs[LOG_EN__COUNT], *log_container,
166 1.1 lukem *log_oc_read, *log_oc_write;
167 1.1 lukem
168 1.1 lukem #define LOG_SCHEMA_ROOT "1.3.6.1.4.1.4203.666.11.5"
169 1.1 lukem
170 1.1 lukem #define LOG_SCHEMA_AT LOG_SCHEMA_ROOT ".1"
171 1.1 lukem #define LOG_SCHEMA_OC LOG_SCHEMA_ROOT ".2"
172 1.1 lukem #define LOG_SCHEMA_SYN LOG_SCHEMA_ROOT ".3"
173 1.1 lukem
174 1.1 lukem static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType,
175 1.1 lukem *ad_reqSession, *ad_reqResult, *ad_reqAuthzID, *ad_reqControls,
176 1.1 lukem *ad_reqRespControls, *ad_reqMethod, *ad_reqAssertion, *ad_reqNewRDN,
177 1.1 lukem *ad_reqNewSuperior, *ad_reqDeleteOldRDN, *ad_reqMod,
178 1.1 lukem *ad_reqScope, *ad_reqFilter, *ad_reqAttr, *ad_reqEntries,
179 1.1 lukem *ad_reqSizeLimit, *ad_reqTimeLimit, *ad_reqAttrsOnly, *ad_reqData,
180 1.1 lukem *ad_reqId, *ad_reqMessage, *ad_reqVersion, *ad_reqDerefAliases,
181 1.1 lukem *ad_reqReferral, *ad_reqOld, *ad_auditContext;
182 1.1 lukem
183 1.1 lukem static int
184 1.1 lukem logSchemaControlValidate(
185 1.1 lukem Syntax *syntax,
186 1.1 lukem struct berval *val );
187 1.1 lukem
188 1.1 lukem char *mrControl[] = {
189 1.1 lukem "objectIdentifierFirstComponentMatch",
190 1.1 lukem NULL
191 1.1 lukem };
192 1.1 lukem
193 1.1 lukem static struct {
194 1.1 lukem char *oid;
195 1.1 lukem slap_syntax_defs_rec syn;
196 1.1 lukem char **mrs;
197 1.1 lukem } lsyntaxes[] = {
198 1.1 lukem { LOG_SCHEMA_SYN ".1" ,
199 1.1 lukem { "( " LOG_SCHEMA_SYN ".1 DESC 'Control' )",
200 1.1 lukem SLAP_SYNTAX_HIDE,
201 1.1 lukem NULL,
202 1.1 lukem logSchemaControlValidate,
203 1.1 lukem NULL },
204 1.1 lukem mrControl },
205 1.1 lukem { NULL }
206 1.1 lukem };
207 1.1 lukem
208 1.1 lukem static struct {
209 1.1 lukem char *at;
210 1.1 lukem AttributeDescription **ad;
211 1.1 lukem } lattrs[] = {
212 1.1 lukem { "( " LOG_SCHEMA_AT ".1 NAME 'reqDN' "
213 1.1 lukem "DESC 'Target DN of request' "
214 1.1 lukem "EQUALITY distinguishedNameMatch "
215 1.1 lukem "SYNTAX OMsDN "
216 1.1 lukem "SINGLE-VALUE )", &ad_reqDN },
217 1.1 lukem { "( " LOG_SCHEMA_AT ".2 NAME 'reqStart' "
218 1.1 lukem "DESC 'Start time of request' "
219 1.1 lukem "EQUALITY generalizedTimeMatch "
220 1.1 lukem "ORDERING generalizedTimeOrderingMatch "
221 1.1 lukem "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
222 1.1 lukem "SINGLE-VALUE )", &ad_reqStart },
223 1.1 lukem { "( " LOG_SCHEMA_AT ".3 NAME 'reqEnd' "
224 1.1 lukem "DESC 'End time of request' "
225 1.1 lukem "EQUALITY generalizedTimeMatch "
226 1.1 lukem "ORDERING generalizedTimeOrderingMatch "
227 1.1 lukem "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
228 1.1 lukem "SINGLE-VALUE )", &ad_reqEnd },
229 1.1 lukem { "( " LOG_SCHEMA_AT ".4 NAME 'reqType' "
230 1.1 lukem "DESC 'Type of request' "
231 1.1 lukem "EQUALITY caseIgnoreMatch "
232 1.1 lukem "SYNTAX OMsDirectoryString "
233 1.1 lukem "SINGLE-VALUE )", &ad_reqType },
234 1.1 lukem { "( " LOG_SCHEMA_AT ".5 NAME 'reqSession' "
235 1.1 lukem "DESC 'Session ID of request' "
236 1.1 lukem "EQUALITY caseIgnoreMatch "
237 1.1 lukem "SYNTAX OMsDirectoryString "
238 1.1 lukem "SINGLE-VALUE )", &ad_reqSession },
239 1.1 lukem { "( " LOG_SCHEMA_AT ".6 NAME 'reqAuthzID' "
240 1.1 lukem "DESC 'Authorization ID of requestor' "
241 1.1 lukem "EQUALITY distinguishedNameMatch "
242 1.1 lukem "SYNTAX OMsDN "
243 1.1 lukem "SINGLE-VALUE )", &ad_reqAuthzID },
244 1.1 lukem { "( " LOG_SCHEMA_AT ".7 NAME 'reqResult' "
245 1.1 lukem "DESC 'Result code of request' "
246 1.1 lukem "EQUALITY integerMatch "
247 1.1 lukem "ORDERING integerOrderingMatch "
248 1.1 lukem "SYNTAX OMsInteger "
249 1.1 lukem "SINGLE-VALUE )", &ad_reqResult },
250 1.1 lukem { "( " LOG_SCHEMA_AT ".8 NAME 'reqMessage' "
251 1.1 lukem "DESC 'Error text of request' "
252 1.1 lukem "EQUALITY caseIgnoreMatch "
253 1.1 lukem "SUBSTR caseIgnoreSubstringsMatch "
254 1.1 lukem "SYNTAX OMsDirectoryString "
255 1.1 lukem "SINGLE-VALUE )", &ad_reqMessage },
256 1.1 lukem { "( " LOG_SCHEMA_AT ".9 NAME 'reqReferral' "
257 1.1 lukem "DESC 'Referrals returned for request' "
258 1.1 lukem "SUP labeledURI )", &ad_reqReferral },
259 1.1 lukem { "( " LOG_SCHEMA_AT ".10 NAME 'reqControls' "
260 1.1 lukem "DESC 'Request controls' "
261 1.1 lukem "EQUALITY objectIdentifierFirstComponentMatch "
262 1.1 lukem "SYNTAX " LOG_SCHEMA_SYN ".1 "
263 1.1 lukem "X-ORDERED 'VALUES' )", &ad_reqControls },
264 1.1 lukem { "( " LOG_SCHEMA_AT ".11 NAME 'reqRespControls' "
265 1.1 lukem "DESC 'Response controls of request' "
266 1.1 lukem "EQUALITY objectIdentifierFirstComponentMatch "
267 1.1 lukem "SYNTAX " LOG_SCHEMA_SYN ".1 "
268 1.1 lukem "X-ORDERED 'VALUES' )", &ad_reqRespControls },
269 1.1 lukem { "( " LOG_SCHEMA_AT ".12 NAME 'reqId' "
270 1.1 lukem "DESC 'ID of Request to Abandon' "
271 1.1 lukem "EQUALITY integerMatch "
272 1.1 lukem "ORDERING integerOrderingMatch "
273 1.1 lukem "SYNTAX OMsInteger "
274 1.1 lukem "SINGLE-VALUE )", &ad_reqId },
275 1.1 lukem { "( " LOG_SCHEMA_AT ".13 NAME 'reqVersion' "
276 1.1 lukem "DESC 'Protocol version of Bind request' "
277 1.1 lukem "EQUALITY integerMatch "
278 1.1 lukem "ORDERING integerOrderingMatch "
279 1.1 lukem "SYNTAX OMsInteger "
280 1.1 lukem "SINGLE-VALUE )", &ad_reqVersion },
281 1.1 lukem { "( " LOG_SCHEMA_AT ".14 NAME 'reqMethod' "
282 1.1 lukem "DESC 'Bind method of request' "
283 1.1 lukem "EQUALITY caseIgnoreMatch "
284 1.1 lukem "SYNTAX OMsDirectoryString "
285 1.1 lukem "SINGLE-VALUE )", &ad_reqMethod },
286 1.1 lukem { "( " LOG_SCHEMA_AT ".15 NAME 'reqAssertion' "
287 1.1 lukem "DESC 'Compare Assertion of request' "
288 1.1 lukem "SYNTAX OMsDirectoryString "
289 1.1 lukem "SINGLE-VALUE )", &ad_reqAssertion },
290 1.1 lukem { "( " LOG_SCHEMA_AT ".16 NAME 'reqMod' "
291 1.1 lukem "DESC 'Modifications of request' "
292 1.1 lukem "EQUALITY octetStringMatch "
293 1.1 lukem "SUBSTR octetStringSubstringsMatch "
294 1.1 lukem "SYNTAX OMsOctetString )", &ad_reqMod },
295 1.1 lukem { "( " LOG_SCHEMA_AT ".17 NAME 'reqOld' "
296 1.1 lukem "DESC 'Old values of entry before request completed' "
297 1.1 lukem "EQUALITY octetStringMatch "
298 1.1 lukem "SUBSTR octetStringSubstringsMatch "
299 1.1 lukem "SYNTAX OMsOctetString )", &ad_reqOld },
300 1.1 lukem { "( " LOG_SCHEMA_AT ".18 NAME 'reqNewRDN' "
301 1.1 lukem "DESC 'New RDN of request' "
302 1.1 lukem "EQUALITY distinguishedNameMatch "
303 1.1 lukem "SYNTAX OMsDN "
304 1.1 lukem "SINGLE-VALUE )", &ad_reqNewRDN },
305 1.1 lukem { "( " LOG_SCHEMA_AT ".19 NAME 'reqDeleteOldRDN' "
306 1.1 lukem "DESC 'Delete old RDN' "
307 1.1 lukem "EQUALITY booleanMatch "
308 1.1 lukem "SYNTAX OMsBoolean "
309 1.1 lukem "SINGLE-VALUE )", &ad_reqDeleteOldRDN },
310 1.1 lukem { "( " LOG_SCHEMA_AT ".20 NAME 'reqNewSuperior' "
311 1.1 lukem "DESC 'New superior DN of request' "
312 1.1 lukem "EQUALITY distinguishedNameMatch "
313 1.1 lukem "SYNTAX OMsDN "
314 1.1 lukem "SINGLE-VALUE )", &ad_reqNewSuperior },
315 1.1 lukem { "( " LOG_SCHEMA_AT ".21 NAME 'reqScope' "
316 1.1 lukem "DESC 'Scope of request' "
317 1.1 lukem "EQUALITY caseIgnoreMatch "
318 1.1 lukem "SYNTAX OMsDirectoryString "
319 1.1 lukem "SINGLE-VALUE )", &ad_reqScope },
320 1.1 lukem { "( " LOG_SCHEMA_AT ".22 NAME 'reqDerefAliases' "
321 1.1 lukem "DESC 'Disposition of Aliases in request' "
322 1.1 lukem "EQUALITY caseIgnoreMatch "
323 1.1 lukem "SYNTAX OMsDirectoryString "
324 1.1 lukem "SINGLE-VALUE )", &ad_reqDerefAliases },
325 1.1 lukem { "( " LOG_SCHEMA_AT ".23 NAME 'reqAttrsOnly' "
326 1.1 lukem "DESC 'Attributes and values of request' "
327 1.1 lukem "EQUALITY booleanMatch "
328 1.1 lukem "SYNTAX OMsBoolean "
329 1.1 lukem "SINGLE-VALUE )", &ad_reqAttrsOnly },
330 1.1 lukem { "( " LOG_SCHEMA_AT ".24 NAME 'reqFilter' "
331 1.1 lukem "DESC 'Filter of request' "
332 1.1 lukem "EQUALITY caseIgnoreMatch "
333 1.1 lukem "SUBSTR caseIgnoreSubstringsMatch "
334 1.1 lukem "SYNTAX OMsDirectoryString "
335 1.1 lukem "SINGLE-VALUE )", &ad_reqFilter },
336 1.1 lukem { "( " LOG_SCHEMA_AT ".25 NAME 'reqAttr' "
337 1.1 lukem "DESC 'Attributes of request' "
338 1.1 lukem "EQUALITY caseIgnoreMatch "
339 1.1 lukem "SYNTAX OMsDirectoryString )", &ad_reqAttr },
340 1.1 lukem { "( " LOG_SCHEMA_AT ".26 NAME 'reqSizeLimit' "
341 1.1 lukem "DESC 'Size limit of request' "
342 1.1 lukem "EQUALITY integerMatch "
343 1.1 lukem "ORDERING integerOrderingMatch "
344 1.1 lukem "SYNTAX OMsInteger "
345 1.1 lukem "SINGLE-VALUE )", &ad_reqSizeLimit },
346 1.1 lukem { "( " LOG_SCHEMA_AT ".27 NAME 'reqTimeLimit' "
347 1.1 lukem "DESC 'Time limit of request' "
348 1.1 lukem "EQUALITY integerMatch "
349 1.1 lukem "ORDERING integerOrderingMatch "
350 1.1 lukem "SYNTAX OMsInteger "
351 1.1 lukem "SINGLE-VALUE )", &ad_reqTimeLimit },
352 1.1 lukem { "( " LOG_SCHEMA_AT ".28 NAME 'reqEntries' "
353 1.1 lukem "DESC 'Number of entries returned' "
354 1.1 lukem "EQUALITY integerMatch "
355 1.1 lukem "ORDERING integerOrderingMatch "
356 1.1 lukem "SYNTAX OMsInteger "
357 1.1 lukem "SINGLE-VALUE )", &ad_reqEntries },
358 1.1 lukem { "( " LOG_SCHEMA_AT ".29 NAME 'reqData' "
359 1.1 lukem "DESC 'Data of extended request' "
360 1.1 lukem "EQUALITY octetStringMatch "
361 1.1 lukem "SUBSTR octetStringSubstringsMatch "
362 1.1 lukem "SYNTAX OMsOctetString "
363 1.1 lukem "SINGLE-VALUE )", &ad_reqData },
364 1.1 lukem
365 1.1 lukem /*
366 1.1 lukem * from <draft-chu-ldap-logschema-01.txt>:
367 1.1 lukem *
368 1.1 lukem
369 1.1 lukem ( LOG_SCHEMA_AT .30 NAME 'auditContext'
370 1.1 lukem DESC 'DN of auditContainer'
371 1.1 lukem EQUALITY distinguishedNameMatch
372 1.1 lukem SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
373 1.1 lukem SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
374 1.1 lukem
375 1.1 lukem * - removed EQUALITY matchingRule
376 1.1 lukem * - changed directoryOperation in dSAOperation
377 1.1 lukem */
378 1.1 lukem { "( " LOG_SCHEMA_AT ".30 NAME 'auditContext' "
379 1.1 lukem "DESC 'DN of auditContainer' "
380 1.1 lukem "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
381 1.1 lukem "SINGLE-VALUE "
382 1.1 lukem "NO-USER-MODIFICATION "
383 1.1 lukem "USAGE dSAOperation )", &ad_auditContext },
384 1.1 lukem { NULL, NULL }
385 1.1 lukem };
386 1.1 lukem
387 1.1 lukem static struct {
388 1.1 lukem char *ot;
389 1.1 lukem ObjectClass **oc;
390 1.1 lukem } locs[] = {
391 1.1 lukem { "( " LOG_SCHEMA_OC ".0 NAME 'auditContainer' "
392 1.1 lukem "DESC 'AuditLog container' "
393 1.1 lukem "SUP top STRUCTURAL "
394 1.1 lukem "MAY ( cn $ reqStart $ reqEnd ) )", &log_container },
395 1.1 lukem { "( " LOG_SCHEMA_OC ".1 NAME 'auditObject' "
396 1.1 lukem "DESC 'OpenLDAP request auditing' "
397 1.1 lukem "SUP top STRUCTURAL "
398 1.1 lukem "MUST ( reqStart $ reqType $ reqSession ) "
399 1.1 lukem "MAY ( reqDN $ reqAuthzID $ reqControls $ reqRespControls $ reqEnd $ "
400 1.1 lukem "reqResult $ reqMessage $ reqReferral ) )",
401 1.1 lukem &log_ocs[LOG_EN_UNBIND] },
402 1.1 lukem { "( " LOG_SCHEMA_OC ".2 NAME 'auditReadObject' "
403 1.1 lukem "DESC 'OpenLDAP read request record' "
404 1.1 lukem "SUP auditObject STRUCTURAL )", &log_oc_read },
405 1.1 lukem { "( " LOG_SCHEMA_OC ".3 NAME 'auditWriteObject' "
406 1.1 lukem "DESC 'OpenLDAP write request record' "
407 1.1 lukem "SUP auditObject STRUCTURAL )", &log_oc_write },
408 1.1 lukem { "( " LOG_SCHEMA_OC ".4 NAME 'auditAbandon' "
409 1.1 lukem "DESC 'Abandon operation' "
410 1.1 lukem "SUP auditObject STRUCTURAL "
411 1.1 lukem "MUST reqId )", &log_ocs[LOG_EN_ABANDON] },
412 1.1 lukem { "( " LOG_SCHEMA_OC ".5 NAME 'auditAdd' "
413 1.1 lukem "DESC 'Add operation' "
414 1.1 lukem "SUP auditWriteObject STRUCTURAL "
415 1.1 lukem "MUST reqMod )", &log_ocs[LOG_EN_ADD] },
416 1.1 lukem { "( " LOG_SCHEMA_OC ".6 NAME 'auditBind' "
417 1.1 lukem "DESC 'Bind operation' "
418 1.1 lukem "SUP auditObject STRUCTURAL "
419 1.1 lukem "MUST ( reqVersion $ reqMethod ) )", &log_ocs[LOG_EN_BIND] },
420 1.1 lukem { "( " LOG_SCHEMA_OC ".7 NAME 'auditCompare' "
421 1.1 lukem "DESC 'Compare operation' "
422 1.1 lukem "SUP auditReadObject STRUCTURAL "
423 1.1 lukem "MUST reqAssertion )", &log_ocs[LOG_EN_COMPARE] },
424 1.1 lukem { "( " LOG_SCHEMA_OC ".8 NAME 'auditDelete' "
425 1.1 lukem "DESC 'Delete operation' "
426 1.1 lukem "SUP auditWriteObject STRUCTURAL "
427 1.1 lukem "MAY reqOld )", &log_ocs[LOG_EN_DELETE] },
428 1.1 lukem { "( " LOG_SCHEMA_OC ".9 NAME 'auditModify' "
429 1.1 lukem "DESC 'Modify operation' "
430 1.1 lukem "SUP auditWriteObject STRUCTURAL "
431 1.1 lukem "MAY reqOld MUST reqMod )", &log_ocs[LOG_EN_MODIFY] },
432 1.1 lukem { "( " LOG_SCHEMA_OC ".10 NAME 'auditModRDN' "
433 1.1 lukem "DESC 'ModRDN operation' "
434 1.1 lukem "SUP auditWriteObject STRUCTURAL "
435 1.1 lukem "MUST ( reqNewRDN $ reqDeleteOldRDN ) "
436 1.1 lukem "MAY ( reqNewSuperior $ reqMod $ reqOld ) )", &log_ocs[LOG_EN_MODRDN] },
437 1.1 lukem { "( " LOG_SCHEMA_OC ".11 NAME 'auditSearch' "
438 1.1 lukem "DESC 'Search operation' "
439 1.1 lukem "SUP auditReadObject STRUCTURAL "
440 1.1 lukem "MUST ( reqScope $ reqDerefAliases $ reqAttrsonly ) "
441 1.1 lukem "MAY ( reqFilter $ reqAttr $ reqEntries $ reqSizeLimit $ "
442 1.1 lukem "reqTimeLimit ) )", &log_ocs[LOG_EN_SEARCH] },
443 1.1 lukem { "( " LOG_SCHEMA_OC ".12 NAME 'auditExtended' "
444 1.1 lukem "DESC 'Extended operation' "
445 1.1 lukem "SUP auditObject STRUCTURAL "
446 1.1 lukem "MAY reqData )", &log_ocs[LOG_EN_EXTENDED] },
447 1.1 lukem { NULL, NULL }
448 1.1 lukem };
449 1.1 lukem
450 1.1 lukem #define RDNEQ "reqStart="
451 1.1 lukem
452 1.1 lukem /* Our time intervals are of the form [ddd+]hh:mm[:ss]
453 1.1 lukem * If a field is present, it must be two digits. (Except for
454 1.1 lukem * days, which can be arbitrary width.)
455 1.1 lukem */
456 1.1 lukem static int
457 1.1 lukem log_age_parse(char *agestr)
458 1.1 lukem {
459 1.1 lukem int t1, t2;
460 1.1 lukem int gotdays = 0;
461 1.1 lukem char *endptr;
462 1.1 lukem
463 1.1 lukem t1 = strtol( agestr, &endptr, 10 );
464 1.1 lukem /* Is there a days delimiter? */
465 1.1 lukem if ( *endptr == '+' ) {
466 1.1 lukem /* 32 bit time only covers about 68 years */
467 1.1 lukem if ( t1 < 0 || t1 > 25000 )
468 1.1 lukem return -1;
469 1.1 lukem t1 *= 24;
470 1.1 lukem gotdays = 1;
471 1.1 lukem agestr = endptr + 1;
472 1.1 lukem } else {
473 1.1 lukem if ( agestr[2] != ':' ) {
474 1.1 lukem /* No valid delimiter found, fail */
475 1.1 lukem return -1;
476 1.1 lukem }
477 1.1 lukem t1 *= 60;
478 1.1 lukem agestr += 3;
479 1.1 lukem }
480 1.1 lukem
481 1.1 lukem t2 = atoi( agestr );
482 1.1 lukem t1 += t2;
483 1.1 lukem
484 1.1 lukem if ( agestr[2] ) {
485 1.1 lukem /* if there's a delimiter, it can only be a colon */
486 1.1 lukem if ( agestr[2] != ':' )
487 1.1 lukem return -1;
488 1.1 lukem } else {
489 1.1 lukem /* If we're at the end of the string, and we started with days,
490 1.1 lukem * fail because we expected to find minutes too.
491 1.1 lukem */
492 1.1 lukem return gotdays ? -1 : t1 * 60;
493 1.1 lukem }
494 1.1 lukem
495 1.1 lukem agestr += 3;
496 1.1 lukem t2 = atoi( agestr );
497 1.1 lukem
498 1.1 lukem /* last field can only be seconds */
499 1.1 lukem if ( agestr[2] && ( agestr[2] != ':' || !gotdays ))
500 1.1 lukem return -1;
501 1.1 lukem t1 *= 60;
502 1.1 lukem t1 += t2;
503 1.1 lukem
504 1.1 lukem if ( agestr[2] ) {
505 1.1 lukem agestr += 3;
506 1.1 lukem if ( agestr[2] )
507 1.1 lukem return -1;
508 1.1 lukem t1 *= 60;
509 1.1 lukem t1 += atoi( agestr );
510 1.1 lukem } else if ( gotdays ) {
511 1.1 lukem /* only got days+hh:mm */
512 1.1 lukem t1 *= 60;
513 1.1 lukem }
514 1.1 lukem return t1;
515 1.1 lukem }
516 1.1 lukem
517 1.1 lukem static void
518 1.1 lukem log_age_unparse( int age, struct berval *agebv, size_t size )
519 1.1 lukem {
520 1.1 lukem int dd, hh, mm, ss, len;
521 1.1 lukem char *ptr;
522 1.1 lukem
523 1.1 lukem assert( size > 0 );
524 1.1 lukem
525 1.1 lukem ss = age % 60;
526 1.1 lukem age /= 60;
527 1.1 lukem mm = age % 60;
528 1.1 lukem age /= 60;
529 1.1 lukem hh = age % 24;
530 1.1 lukem age /= 24;
531 1.1 lukem dd = age;
532 1.1 lukem
533 1.1 lukem ptr = agebv->bv_val;
534 1.1 lukem
535 1.1 lukem if ( dd ) {
536 1.1 lukem len = snprintf( ptr, size, "%d+", dd );
537 1.1 lukem assert( len >= 0 && len < size );
538 1.1 lukem size -= len;
539 1.1 lukem ptr += len;
540 1.1 lukem }
541 1.1 lukem len = snprintf( ptr, size, "%02d:%02d", hh, mm );
542 1.1 lukem assert( len >= 0 && len < size );
543 1.1 lukem size -= len;
544 1.1 lukem ptr += len;
545 1.1 lukem if ( ss ) {
546 1.1 lukem len = snprintf( ptr, size, ":%02d", ss );
547 1.1 lukem assert( len >= 0 && len < size );
548 1.1 lukem size -= len;
549 1.1 lukem ptr += len;
550 1.1 lukem }
551 1.1 lukem
552 1.1 lukem agebv->bv_len = ptr - agebv->bv_val;
553 1.1 lukem }
554 1.1 lukem
555 1.1 lukem static slap_callback nullsc = { NULL, NULL, NULL, NULL };
556 1.1 lukem
557 1.1 lukem #define PURGE_INCREMENT 100
558 1.1 lukem
559 1.1 lukem typedef struct purge_data {
560 1.1 lukem int slots;
561 1.1 lukem int used;
562 1.1 lukem BerVarray dn;
563 1.1 lukem BerVarray ndn;
564 1.1 lukem struct berval csn; /* an arbitrary old CSN */
565 1.1 lukem } purge_data;
566 1.1 lukem
567 1.1 lukem static int
568 1.1 lukem log_old_lookup( Operation *op, SlapReply *rs )
569 1.1 lukem {
570 1.1 lukem purge_data *pd = op->o_callback->sc_private;
571 1.1 lukem
572 1.1 lukem if ( rs->sr_type != REP_SEARCH) return 0;
573 1.1 lukem
574 1.1 lukem if ( slapd_shutdown ) return 0;
575 1.1 lukem
576 1.1 lukem /* Remember old CSN */
577 1.1 lukem if ( pd->csn.bv_val[0] == '\0' ) {
578 1.1 lukem Attribute *a = attr_find( rs->sr_entry->e_attrs,
579 1.1 lukem slap_schema.si_ad_entryCSN );
580 1.1 lukem if ( a ) {
581 1.1 lukem int len = a->a_vals[0].bv_len;
582 1.1 lukem if ( len > pd->csn.bv_len )
583 1.1 lukem len = pd->csn.bv_len;
584 1.1 lukem AC_MEMCPY( pd->csn.bv_val, a->a_vals[0].bv_val, len );
585 1.1 lukem pd->csn.bv_len = len;
586 1.1 lukem }
587 1.1 lukem }
588 1.1 lukem if ( pd->used >= pd->slots ) {
589 1.1 lukem pd->slots += PURGE_INCREMENT;
590 1.1 lukem pd->dn = ch_realloc( pd->dn, pd->slots * sizeof( struct berval ));
591 1.1 lukem pd->ndn = ch_realloc( pd->ndn, pd->slots * sizeof( struct berval ));
592 1.1 lukem }
593 1.1 lukem ber_dupbv( &pd->dn[pd->used], &rs->sr_entry->e_name );
594 1.1 lukem ber_dupbv( &pd->ndn[pd->used], &rs->sr_entry->e_nname );
595 1.1 lukem pd->used++;
596 1.1 lukem return 0;
597 1.1 lukem }
598 1.1 lukem
599 1.1 lukem /* Periodically search for old entries in the log database and delete them */
600 1.1 lukem static void *
601 1.1 lukem accesslog_purge( void *ctx, void *arg )
602 1.1 lukem {
603 1.1 lukem struct re_s *rtask = arg;
604 1.1 lukem struct log_info *li = rtask->arg;
605 1.1 lukem
606 1.1 lukem Connection conn = {0};
607 1.1 lukem OperationBuffer opbuf;
608 1.1 lukem Operation *op;
609 1.1 lukem SlapReply rs = {REP_RESULT};
610 1.1 lukem slap_callback cb = { NULL, log_old_lookup, NULL, NULL };
611 1.1 lukem Filter f;
612 1.1 lukem AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
613 1.1 lukem purge_data pd = {0};
614 1.1 lukem char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
615 1.1 lukem char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
616 1.1 lukem time_t old = slap_get_time();
617 1.1 lukem
618 1.1 lukem connection_fake_init( &conn, &opbuf, ctx );
619 1.1 lukem op = &opbuf.ob_op;
620 1.1 lukem
621 1.1 lukem f.f_choice = LDAP_FILTER_LE;
622 1.1 lukem f.f_ava = &ava;
623 1.1 lukem f.f_next = NULL;
624 1.1 lukem
625 1.1 lukem ava.aa_desc = ad_reqStart;
626 1.1 lukem ava.aa_value.bv_val = timebuf;
627 1.1 lukem ava.aa_value.bv_len = sizeof(timebuf);
628 1.1 lukem
629 1.1 lukem old -= li->li_age;
630 1.1 lukem slap_timestamp( &old, &ava.aa_value );
631 1.1 lukem
632 1.1 lukem op->o_tag = LDAP_REQ_SEARCH;
633 1.1 lukem op->o_bd = li->li_db;
634 1.1 lukem op->o_dn = li->li_db->be_rootdn;
635 1.1 lukem op->o_ndn = li->li_db->be_rootndn;
636 1.1 lukem op->o_req_dn = li->li_db->be_suffix[0];
637 1.1 lukem op->o_req_ndn = li->li_db->be_nsuffix[0];
638 1.1 lukem op->o_callback = &cb;
639 1.1 lukem op->ors_scope = LDAP_SCOPE_ONELEVEL;
640 1.1 lukem op->ors_deref = LDAP_DEREF_NEVER;
641 1.1 lukem op->ors_tlimit = SLAP_NO_LIMIT;
642 1.1 lukem op->ors_slimit = SLAP_NO_LIMIT;
643 1.1 lukem op->ors_filter = &f;
644 1.1 lukem filter2bv_x( op, &f, &op->ors_filterstr );
645 1.1 lukem op->ors_attrs = slap_anlist_no_attrs;
646 1.1 lukem op->ors_attrsonly = 1;
647 1.1 lukem
648 1.1 lukem pd.csn.bv_len = sizeof( csnbuf );
649 1.1 lukem pd.csn.bv_val = csnbuf;
650 1.1 lukem csnbuf[0] = '\0';
651 1.1 lukem cb.sc_private = &pd;
652 1.1 lukem
653 1.1 lukem op->o_bd->be_search( op, &rs );
654 1.1 lukem op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
655 1.1 lukem
656 1.1 lukem if ( pd.used ) {
657 1.1 lukem int i;
658 1.1 lukem
659 1.1 lukem op->o_tag = LDAP_REQ_DELETE;
660 1.1 lukem op->o_callback = &nullsc;
661 1.1 lukem op->o_csn = pd.csn;
662 1.1 lukem
663 1.1 lukem for (i=0; i<pd.used; i++) {
664 1.1 lukem op->o_req_dn = pd.dn[i];
665 1.1 lukem op->o_req_ndn = pd.ndn[i];
666 1.1 lukem if ( !slapd_shutdown )
667 1.1 lukem op->o_bd->be_delete( op, &rs );
668 1.1 lukem ch_free( pd.ndn[i].bv_val );
669 1.1 lukem ch_free( pd.dn[i].bv_val );
670 1.1 lukem }
671 1.1 lukem ch_free( pd.ndn );
672 1.1 lukem ch_free( pd.dn );
673 1.1 lukem }
674 1.1 lukem
675 1.1 lukem ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
676 1.1 lukem ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
677 1.1 lukem ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
678 1.1 lukem
679 1.1 lukem return NULL;
680 1.1 lukem }
681 1.1 lukem
682 1.1 lukem static int
683 1.1 lukem log_cf_gen(ConfigArgs *c)
684 1.1 lukem {
685 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi;
686 1.1 lukem struct log_info *li = on->on_bi.bi_private;
687 1.1 lukem int rc = 0;
688 1.1 lukem slap_mask_t tmask = 0;
689 1.1 lukem char agebuf[2*STRLENOF("ddddd+hh:mm:ss ")];
690 1.1 lukem struct berval agebv, cyclebv;
691 1.1 lukem
692 1.1 lukem switch( c->op ) {
693 1.1 lukem case SLAP_CONFIG_EMIT:
694 1.1 lukem switch( c->type ) {
695 1.1 lukem case LOG_DB:
696 1.1 lukem if ( !BER_BVISEMPTY( &li->li_db_suffix )) {
697 1.1 lukem value_add_one( &c->rvalue_vals, &li->li_db_suffix );
698 1.1 lukem value_add_one( &c->rvalue_nvals, &li->li_db_suffix );
699 1.1 lukem } else if ( li->li_db ) {
700 1.1 lukem value_add_one( &c->rvalue_vals, li->li_db->be_suffix );
701 1.1 lukem value_add_one( &c->rvalue_nvals, li->li_db->be_nsuffix );
702 1.1 lukem } else {
703 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
704 1.1 lukem "accesslog: \"logdb <suffix>\" must be specified" );
705 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
706 1.1 lukem c->log, c->cr_msg, c->value_dn.bv_val );
707 1.1 lukem rc = 1;
708 1.1 lukem break;
709 1.1 lukem }
710 1.1 lukem break;
711 1.1 lukem case LOG_OPS:
712 1.1 lukem rc = mask_to_verbs( logops, li->li_ops, &c->rvalue_vals );
713 1.1 lukem break;
714 1.1 lukem case LOG_PURGE:
715 1.1 lukem if ( !li->li_age ) {
716 1.1 lukem rc = 1;
717 1.1 lukem break;
718 1.1 lukem }
719 1.1 lukem agebv.bv_val = agebuf;
720 1.1 lukem log_age_unparse( li->li_age, &agebv, sizeof( agebuf ) );
721 1.1 lukem agebv.bv_val[agebv.bv_len] = ' ';
722 1.1 lukem agebv.bv_len++;
723 1.1 lukem cyclebv.bv_val = agebv.bv_val + agebv.bv_len;
724 1.1 lukem log_age_unparse( li->li_cycle, &cyclebv, sizeof( agebuf ) - agebv.bv_len );
725 1.1 lukem agebv.bv_len += cyclebv.bv_len;
726 1.1 lukem value_add_one( &c->rvalue_vals, &agebv );
727 1.1 lukem break;
728 1.1 lukem case LOG_SUCCESS:
729 1.1 lukem if ( li->li_success )
730 1.1 lukem c->value_int = li->li_success;
731 1.1 lukem else
732 1.1 lukem rc = 1;
733 1.1 lukem break;
734 1.1 lukem case LOG_OLD:
735 1.1 lukem if ( li->li_oldf ) {
736 1.1 lukem filter2bv( li->li_oldf, &agebv );
737 1.1 lukem ber_bvarray_add( &c->rvalue_vals, &agebv );
738 1.1 lukem }
739 1.1 lukem else
740 1.1 lukem rc = 1;
741 1.1 lukem break;
742 1.1 lukem case LOG_OLDATTR:
743 1.1 lukem if ( li->li_oldattrs ) {
744 1.1 lukem log_attr *la;
745 1.1 lukem
746 1.1 lukem for ( la = li->li_oldattrs; la; la=la->next )
747 1.1 lukem value_add_one( &c->rvalue_vals, &la->attr->ad_cname );
748 1.1 lukem }
749 1.1 lukem else
750 1.1 lukem rc = 1;
751 1.1 lukem break;
752 1.1 lukem }
753 1.1 lukem break;
754 1.1 lukem case LDAP_MOD_DELETE:
755 1.1 lukem switch( c->type ) {
756 1.1 lukem case LOG_DB:
757 1.1 lukem /* noop. this should always be a valid backend. */
758 1.1 lukem break;
759 1.1 lukem case LOG_OPS:
760 1.1 lukem if ( c->valx < 0 ) {
761 1.1 lukem li->li_ops = 0;
762 1.1 lukem } else {
763 1.1 lukem rc = verbs_to_mask( 1, &c->line, logops, &tmask );
764 1.1 lukem if ( rc == 0 )
765 1.1 lukem li->li_ops &= ~tmask;
766 1.1 lukem }
767 1.1 lukem break;
768 1.1 lukem case LOG_PURGE:
769 1.1 lukem if ( li->li_task ) {
770 1.1 lukem struct re_s *re = li->li_task;
771 1.1 lukem li->li_task = NULL;
772 1.1 lukem ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
773 1.1 lukem if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ))
774 1.1 lukem ldap_pvt_runqueue_stoptask( &slapd_rq, re );
775 1.1 lukem ldap_pvt_runqueue_remove( &slapd_rq, re );
776 1.1 lukem ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
777 1.1 lukem }
778 1.1 lukem li->li_age = 0;
779 1.1 lukem li->li_cycle = 0;
780 1.1 lukem break;
781 1.1 lukem case LOG_SUCCESS:
782 1.1 lukem li->li_success = 0;
783 1.1 lukem break;
784 1.1 lukem case LOG_OLD:
785 1.1 lukem if ( li->li_oldf ) {
786 1.1 lukem filter_free( li->li_oldf );
787 1.1 lukem li->li_oldf = NULL;
788 1.1 lukem }
789 1.1 lukem break;
790 1.1 lukem case LOG_OLDATTR:
791 1.1 lukem if ( c->valx < 0 ) {
792 1.1 lukem log_attr *la, *ln;
793 1.1 lukem
794 1.1 lukem for ( la = li->li_oldattrs; la; la = ln ) {
795 1.1 lukem ln = la->next;
796 1.1 lukem ch_free( la );
797 1.1 lukem }
798 1.1 lukem } else {
799 1.1 lukem log_attr *la = NULL, **lp;
800 1.1 lukem int i;
801 1.1 lukem
802 1.1 lukem for ( lp = &li->li_oldattrs, i=0; i < c->valx; i++ ) {
803 1.1 lukem la = *lp;
804 1.1 lukem lp = &la->next;
805 1.1 lukem }
806 1.1 lukem *lp = la->next;
807 1.1 lukem ch_free( la );
808 1.1 lukem }
809 1.1 lukem break;
810 1.1 lukem }
811 1.1 lukem break;
812 1.1 lukem default:
813 1.1 lukem switch( c->type ) {
814 1.1 lukem case LOG_DB:
815 1.1 lukem if ( CONFIG_ONLINE_ADD( c )) {
816 1.1 lukem li->li_db = select_backend( &c->value_ndn, 0 );
817 1.1 lukem if ( !li->li_db ) {
818 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ),
819 1.1 lukem "<%s> no matching backend found for suffix",
820 1.1 lukem c->argv[0] );
821 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
822 1.1 lukem c->log, c->cr_msg, c->value_dn.bv_val );
823 1.1 lukem rc = 1;
824 1.1 lukem }
825 1.1 lukem ch_free( c->value_ndn.bv_val );
826 1.1 lukem } else {
827 1.1 lukem li->li_db_suffix = c->value_ndn;
828 1.1 lukem }
829 1.1 lukem ch_free( c->value_dn.bv_val );
830 1.1 lukem break;
831 1.1 lukem case LOG_OPS:
832 1.1 lukem rc = verbs_to_mask( c->argc, c->argv, logops, &tmask );
833 1.1 lukem if ( rc == 0 )
834 1.1 lukem li->li_ops |= tmask;
835 1.1 lukem break;
836 1.1 lukem case LOG_PURGE:
837 1.1 lukem li->li_age = log_age_parse( c->argv[1] );
838 1.1 lukem if ( li->li_age < 1 ) {
839 1.1 lukem rc = 1;
840 1.1 lukem } else {
841 1.1 lukem li->li_cycle = log_age_parse( c->argv[2] );
842 1.1 lukem if ( li->li_cycle < 1 ) {
843 1.1 lukem rc = 1;
844 1.1 lukem } else if ( slapMode & SLAP_SERVER_MODE ) {
845 1.1 lukem struct re_s *re = li->li_task;
846 1.1 lukem if ( re )
847 1.1 lukem re->interval.tv_sec = li->li_cycle;
848 1.1 lukem else {
849 1.1 lukem ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
850 1.1 lukem li->li_task = ldap_pvt_runqueue_insert( &slapd_rq,
851 1.1 lukem li->li_cycle, accesslog_purge, li,
852 1.1 lukem "accesslog_purge", li->li_db ?
853 1.1 lukem li->li_db->be_suffix[0].bv_val :
854 1.1 lukem c->be->be_suffix[0].bv_val );
855 1.1 lukem ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
856 1.1 lukem }
857 1.1 lukem }
858 1.1 lukem }
859 1.1 lukem break;
860 1.1 lukem case LOG_SUCCESS:
861 1.1 lukem li->li_success = c->value_int;
862 1.1 lukem break;
863 1.1 lukem case LOG_OLD:
864 1.1 lukem li->li_oldf = str2filter( c->argv[1] );
865 1.1 lukem if ( !li->li_oldf ) {
866 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ), "bad filter!" );
867 1.1 lukem rc = 1;
868 1.1 lukem }
869 1.1 lukem break;
870 1.1 lukem case LOG_OLDATTR: {
871 1.1 lukem int i;
872 1.1 lukem AttributeDescription *ad;
873 1.1 lukem const char *text;
874 1.1 lukem
875 1.1 lukem for ( i=1; i< c->argc; i++ ) {
876 1.1 lukem ad = NULL;
877 1.1 lukem if ( slap_str2ad( c->argv[i], &ad, &text ) == LDAP_SUCCESS ) {
878 1.1 lukem log_attr *la = ch_malloc( sizeof( log_attr ));
879 1.1 lukem la->attr = ad;
880 1.1 lukem la->next = li->li_oldattrs;
881 1.1 lukem li->li_oldattrs = la;
882 1.1 lukem } else {
883 1.1 lukem snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s",
884 1.1 lukem c->argv[0], c->argv[i], text );
885 1.1 lukem Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
886 1.1 lukem "%s: %s\n", c->log, c->cr_msg, 0 );
887 1.1 lukem rc = ARG_BAD_CONF;
888 1.1 lukem break;
889 1.1 lukem }
890 1.1 lukem }
891 1.1 lukem }
892 1.1 lukem break;
893 1.1 lukem }
894 1.1 lukem break;
895 1.1 lukem }
896 1.1 lukem return rc;
897 1.1 lukem }
898 1.1 lukem
899 1.1 lukem static int
900 1.1 lukem logSchemaControlValidate(
901 1.1 lukem Syntax *syntax,
902 1.1 lukem struct berval *valp )
903 1.1 lukem {
904 1.1 lukem struct berval val, bv;
905 1.1 lukem int i;
906 1.1 lukem int rc = LDAP_SUCCESS;
907 1.1 lukem
908 1.1 lukem assert( valp != NULL );
909 1.1 lukem
910 1.1 lukem val = *valp;
911 1.1 lukem
912 1.1 lukem /* check minimal size */
913 1.1 lukem if ( val.bv_len < STRLENOF( "{*}" ) ) {
914 1.1 lukem return LDAP_INVALID_SYNTAX;
915 1.1 lukem }
916 1.1 lukem
917 1.1 lukem val.bv_len--;
918 1.1 lukem
919 1.1 lukem /* check SEQUENCE boundaries */
920 1.1 lukem if ( val.bv_val[ 0 ] != '{' /*}*/ ||
921 1.1 lukem val.bv_val[ val.bv_len ] != /*{*/ '}' )
922 1.1 lukem {
923 1.1 lukem return LDAP_INVALID_SYNTAX;
924 1.1 lukem }
925 1.1 lukem
926 1.1 lukem /* extract and check OID */
927 1.1 lukem for ( i = 1; i < val.bv_len; i++ ) {
928 1.1 lukem if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
929 1.1 lukem break;
930 1.1 lukem }
931 1.1 lukem }
932 1.1 lukem
933 1.1 lukem bv.bv_val = &val.bv_val[ i ];
934 1.1 lukem
935 1.1 lukem for ( i++; i < val.bv_len; i++ ) {
936 1.1 lukem if ( ASCII_SPACE( val.bv_val[ i ] ) )
937 1.1 lukem {
938 1.1 lukem break;
939 1.1 lukem }
940 1.1 lukem }
941 1.1 lukem
942 1.1 lukem bv.bv_len = &val.bv_val[ i ] - bv.bv_val;
943 1.1 lukem
944 1.1 lukem rc = numericoidValidate( NULL, &bv );
945 1.1 lukem if ( rc != LDAP_SUCCESS ) {
946 1.1 lukem return rc;
947 1.1 lukem }
948 1.1 lukem
949 1.1 lukem if ( i == val.bv_len ) {
950 1.1 lukem return LDAP_SUCCESS;
951 1.1 lukem }
952 1.1 lukem
953 1.1 lukem if ( val.bv_val[ i ] != ' ' ) {
954 1.1 lukem return LDAP_INVALID_SYNTAX;
955 1.1 lukem }
956 1.1 lukem
957 1.1 lukem for ( i++; i < val.bv_len; i++ ) {
958 1.1 lukem if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
959 1.1 lukem break;
960 1.1 lukem }
961 1.1 lukem }
962 1.1 lukem
963 1.1 lukem if ( i == val.bv_len ) {
964 1.1 lukem return LDAP_SUCCESS;
965 1.1 lukem }
966 1.1 lukem
967 1.1 lukem /* extract and check criticality */
968 1.1 lukem if ( strncasecmp( &val.bv_val[ i ], "criticality ", STRLENOF( "criticality " ) ) == 0 )
969 1.1 lukem {
970 1.1 lukem i += STRLENOF( "criticality " );
971 1.1 lukem for ( ; i < val.bv_len; i++ ) {
972 1.1 lukem if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
973 1.1 lukem break;
974 1.1 lukem }
975 1.1 lukem }
976 1.1 lukem
977 1.1 lukem if ( i == val.bv_len ) {
978 1.1 lukem return LDAP_INVALID_SYNTAX;
979 1.1 lukem }
980 1.1 lukem
981 1.1 lukem bv.bv_val = &val.bv_val[ i ];
982 1.1 lukem
983 1.1 lukem for ( ; i < val.bv_len; i++ ) {
984 1.1 lukem if ( ASCII_SPACE( val.bv_val[ i ] ) ) {
985 1.1 lukem break;
986 1.1 lukem }
987 1.1 lukem }
988 1.1 lukem
989 1.1 lukem bv.bv_len = &val.bv_val[ i ] - bv.bv_val;
990 1.1 lukem
991 1.1 lukem if ( !bvmatch( &bv, &slap_true_bv ) && !bvmatch( &bv, &slap_false_bv ) )
992 1.1 lukem {
993 1.1 lukem return LDAP_INVALID_SYNTAX;
994 1.1 lukem }
995 1.1 lukem
996 1.1 lukem if ( i == val.bv_len ) {
997 1.1 lukem return LDAP_SUCCESS;
998 1.1 lukem }
999 1.1 lukem
1000 1.1 lukem if ( val.bv_val[ i ] != ' ' ) {
1001 1.1 lukem return LDAP_INVALID_SYNTAX;
1002 1.1 lukem }
1003 1.1 lukem
1004 1.1 lukem for ( i++; i < val.bv_len; i++ ) {
1005 1.1 lukem if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
1006 1.1 lukem break;
1007 1.1 lukem }
1008 1.1 lukem }
1009 1.1 lukem
1010 1.1 lukem if ( i == val.bv_len ) {
1011 1.1 lukem return LDAP_SUCCESS;
1012 1.1 lukem }
1013 1.1 lukem }
1014 1.1 lukem
1015 1.1 lukem /* extract and check controlValue */
1016 1.1 lukem if ( strncasecmp( &val.bv_val[ i ], "controlValue ", STRLENOF( "controlValue " ) ) == 0 )
1017 1.1 lukem {
1018 1.1 lukem i += STRLENOF( "controlValue " );
1019 1.1 lukem for ( ; i < val.bv_len; i++ ) {
1020 1.1 lukem if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
1021 1.1 lukem break;
1022 1.1 lukem }
1023 1.1 lukem }
1024 1.1 lukem
1025 1.1 lukem if ( i == val.bv_len ) {
1026 1.1 lukem return LDAP_INVALID_SYNTAX;
1027 1.1 lukem }
1028 1.1 lukem
1029 1.1 lukem if ( val.bv_val[ i ] != '"' ) {
1030 1.1 lukem return LDAP_INVALID_SYNTAX;
1031 1.1 lukem }
1032 1.1 lukem
1033 1.1 lukem for ( ; i < val.bv_len; i++ ) {
1034 1.1 lukem if ( val.bv_val[ i ] == '"' ) {
1035 1.1 lukem break;
1036 1.1 lukem }
1037 1.1 lukem
1038 1.1 lukem if ( !ASCII_HEX( val.bv_val[ i ] ) ) {
1039 1.1 lukem return LDAP_INVALID_SYNTAX;
1040 1.1 lukem }
1041 1.1 lukem }
1042 1.1 lukem
1043 1.1 lukem if ( val.bv_val[ i ] != '"' ) {
1044 1.1 lukem return LDAP_INVALID_SYNTAX;
1045 1.1 lukem }
1046 1.1 lukem
1047 1.1 lukem for ( ; i < val.bv_len; i++ ) {
1048 1.1 lukem if ( !ASCII_SPACE( val.bv_val[ i ] ) ) {
1049 1.1 lukem break;
1050 1.1 lukem }
1051 1.1 lukem }
1052 1.1 lukem
1053 1.1 lukem if ( i == val.bv_len ) {
1054 1.1 lukem return LDAP_SUCCESS;
1055 1.1 lukem }
1056 1.1 lukem }
1057 1.1 lukem
1058 1.1 lukem return LDAP_INVALID_SYNTAX;
1059 1.1 lukem }
1060 1.1 lukem
1061 1.1 lukem static int
1062 1.1 lukem accesslog_ctrls(
1063 1.1 lukem LDAPControl **ctrls,
1064 1.1 lukem BerVarray *valsp,
1065 1.1 lukem BerVarray *nvalsp,
1066 1.1 lukem void *memctx )
1067 1.1 lukem {
1068 1.1 lukem long i, rc = 0;
1069 1.1 lukem
1070 1.1 lukem assert( valsp != NULL );
1071 1.1 lukem assert( ctrls != NULL );
1072 1.1 lukem
1073 1.1 lukem *valsp = NULL;
1074 1.1 lukem *nvalsp = NULL;
1075 1.1 lukem
1076 1.1 lukem for ( i = 0; ctrls[ i ] != NULL; i++ ) {
1077 1.1 lukem struct berval idx,
1078 1.1 lukem oid,
1079 1.1 lukem noid,
1080 1.1 lukem bv;
1081 1.1 lukem char *ptr,
1082 1.1 lukem buf[ 32 ];
1083 1.1 lukem
1084 1.1 lukem if ( ctrls[ i ]->ldctl_oid == NULL ) {
1085 1.1 lukem return LDAP_PROTOCOL_ERROR;
1086 1.1 lukem }
1087 1.1 lukem
1088 1.1 lukem idx.bv_len = snprintf( buf, sizeof( buf ), "{%ld}", i );
1089 1.1 lukem idx.bv_val = buf;
1090 1.1 lukem
1091 1.1 lukem ber_str2bv( ctrls[ i ]->ldctl_oid, 0, 0, &oid );
1092 1.1 lukem noid.bv_len = idx.bv_len + oid.bv_len;
1093 1.1 lukem ptr = noid.bv_val = ber_memalloc_x( noid.bv_len + 1, memctx );
1094 1.1 lukem ptr = lutil_strcopy( ptr, idx.bv_val );
1095 1.1 lukem ptr = lutil_strcopy( ptr, oid.bv_val );
1096 1.1 lukem
1097 1.1 lukem bv.bv_len = idx.bv_len + STRLENOF( "{}" ) + oid.bv_len;
1098 1.1 lukem
1099 1.1 lukem if ( ctrls[ i ]->ldctl_iscritical ) {
1100 1.1 lukem bv.bv_len += STRLENOF( " criticality TRUE" );
1101 1.1 lukem }
1102 1.1 lukem
1103 1.1 lukem if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
1104 1.1 lukem bv.bv_len += STRLENOF( " controlValue \"\"" )
1105 1.1 lukem + 2 * ctrls[ i ]->ldctl_value.bv_len;
1106 1.1 lukem }
1107 1.1 lukem
1108 1.1 lukem ptr = bv.bv_val = ber_memalloc_x( bv.bv_len + 1, memctx );
1109 1.1 lukem if ( ptr == NULL ) {
1110 1.1 lukem ber_bvarray_free( *valsp );
1111 1.1 lukem *valsp = NULL;
1112 1.1 lukem ber_bvarray_free( *nvalsp );
1113 1.1 lukem *nvalsp = NULL;
1114 1.1 lukem return LDAP_OTHER;
1115 1.1 lukem }
1116 1.1 lukem
1117 1.1 lukem ptr = lutil_strcopy( ptr, idx.bv_val );
1118 1.1 lukem
1119 1.1 lukem *ptr++ = '{' /*}*/ ;
1120 1.1 lukem ptr = lutil_strcopy( ptr, oid.bv_val );
1121 1.1 lukem
1122 1.1 lukem if ( ctrls[ i ]->ldctl_iscritical ) {
1123 1.1 lukem ptr = lutil_strcopy( ptr, " criticality TRUE" );
1124 1.1 lukem }
1125 1.1 lukem
1126 1.1 lukem if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) {
1127 1.1 lukem int j;
1128 1.1 lukem
1129 1.1 lukem ptr = lutil_strcopy( ptr, " controlValue \"" );
1130 1.1 lukem for ( j = 0; j < ctrls[ i ]->ldctl_value.bv_len; j++ )
1131 1.1 lukem {
1132 1.1 lukem unsigned char o;
1133 1.1 lukem
1134 1.1 lukem o = ( ( ctrls[ i ]->ldctl_value.bv_val[ j ] >> 4 ) & 0xF );
1135 1.1 lukem if ( o < 10 ) {
1136 1.1 lukem *ptr++ = '0' + o;
1137 1.1 lukem
1138 1.1 lukem } else {
1139 1.1 lukem *ptr++ = 'A' + o;
1140 1.1 lukem }
1141 1.1 lukem
1142 1.1 lukem o = ( ctrls[ i ]->ldctl_value.bv_val[ j ] & 0xF );
1143 1.1 lukem if ( o < 10 ) {
1144 1.1 lukem *ptr++ = '0' + o;
1145 1.1 lukem
1146 1.1 lukem } else {
1147 1.1 lukem *ptr++ = 'A' + o;
1148 1.1 lukem }
1149 1.1 lukem }
1150 1.1 lukem
1151 1.1 lukem *ptr++ = '"';
1152 1.1 lukem }
1153 1.1 lukem
1154 1.1 lukem *ptr++ = '}';
1155 1.1 lukem *ptr = '\0';
1156 1.1 lukem
1157 1.1 lukem ber_bvarray_add_x( valsp, &bv, memctx );
1158 1.1 lukem ber_bvarray_add_x( nvalsp, &noid, memctx );
1159 1.1 lukem }
1160 1.1 lukem
1161 1.1 lukem return rc;
1162 1.1 lukem
1163 1.1 lukem }
1164 1.1 lukem
1165 1.1 lukem static Entry *accesslog_entry( Operation *op, SlapReply *rs, int logop,
1166 1.1 lukem Operation *op2 ) {
1167 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1168 1.1 lukem log_info *li = on->on_bi.bi_private;
1169 1.1 lukem
1170 1.1 lukem char rdnbuf[STRLENOF(RDNEQ)+LDAP_LUTIL_GENTIME_BUFSIZE+8];
1171 1.1 lukem char nrdnbuf[STRLENOF(RDNEQ)+LDAP_LUTIL_GENTIME_BUFSIZE+8];
1172 1.1 lukem
1173 1.1 lukem struct berval rdn, nrdn, timestamp, ntimestamp, bv;
1174 1.1 lukem slap_verbmasks *lo = logops+logop+EN_OFFSET;
1175 1.1 lukem
1176 1.1 lukem Entry *e = entry_alloc();
1177 1.1 lukem
1178 1.1 lukem strcpy( rdnbuf, RDNEQ );
1179 1.1 lukem rdn.bv_val = rdnbuf;
1180 1.1 lukem strcpy( nrdnbuf, RDNEQ );
1181 1.1 lukem nrdn.bv_val = nrdnbuf;
1182 1.1 lukem
1183 1.1 lukem timestamp.bv_val = rdnbuf+STRLENOF(RDNEQ);
1184 1.1 lukem timestamp.bv_len = sizeof(rdnbuf) - STRLENOF(RDNEQ);
1185 1.1 lukem slap_timestamp( &op->o_time, ×tamp );
1186 1.1 lukem snprintf( timestamp.bv_val + timestamp.bv_len-1, sizeof(".123456Z"), ".%06dZ", op->o_tincr );
1187 1.1 lukem timestamp.bv_len += STRLENOF(".123456");
1188 1.1 lukem
1189 1.1 lukem rdn.bv_len = STRLENOF(RDNEQ)+timestamp.bv_len;
1190 1.1 lukem ad_reqStart->ad_type->sat_equality->smr_normalize(
1191 1.1 lukem SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, ad_reqStart->ad_type->sat_syntax,
1192 1.1 lukem ad_reqStart->ad_type->sat_equality, ×tamp, &ntimestamp,
1193 1.1 lukem op->o_tmpmemctx );
1194 1.1 lukem
1195 1.1 lukem strcpy( nrdn.bv_val + STRLENOF(RDNEQ), ntimestamp.bv_val );
1196 1.1 lukem nrdn.bv_len = STRLENOF(RDNEQ)+ntimestamp.bv_len;
1197 1.1 lukem build_new_dn( &e->e_name, li->li_db->be_suffix, &rdn, NULL );
1198 1.1 lukem build_new_dn( &e->e_nname, li->li_db->be_nsuffix, &nrdn, NULL );
1199 1.1 lukem
1200 1.1 lukem attr_merge_one( e, slap_schema.si_ad_objectClass,
1201 1.1 lukem &log_ocs[logop]->soc_cname, NULL );
1202 1.1 lukem attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
1203 1.1 lukem &log_ocs[logop]->soc_cname, NULL );
1204 1.1 lukem attr_merge_one( e, ad_reqStart, ×tamp, &ntimestamp );
1205 1.1 lukem op->o_tmpfree( ntimestamp.bv_val, op->o_tmpmemctx );
1206 1.1 lukem
1207 1.1 lukem slap_op_time( &op2->o_time, &op2->o_tincr );
1208 1.1 lukem
1209 1.1 lukem timestamp.bv_len = sizeof(rdnbuf) - STRLENOF(RDNEQ);
1210 1.1 lukem slap_timestamp( &op2->o_time, ×tamp );
1211 1.1 lukem snprintf( timestamp.bv_val + timestamp.bv_len-1, sizeof(".123456Z"), ".%06dZ", op2->o_tincr );
1212 1.1 lukem timestamp.bv_len += STRLENOF(".123456");
1213 1.1 lukem
1214 1.1 lukem attr_merge_normalize_one( e, ad_reqEnd, ×tamp, op->o_tmpmemctx );
1215 1.1 lukem
1216 1.1 lukem /* Exops have OID appended */
1217 1.1 lukem if ( logop == LOG_EN_EXTENDED ) {
1218 1.1 lukem bv.bv_len = lo->word.bv_len + op->ore_reqoid.bv_len + 2;
1219 1.1 lukem bv.bv_val = ch_malloc( bv.bv_len + 1 );
1220 1.1 lukem AC_MEMCPY( bv.bv_val, lo->word.bv_val, lo->word.bv_len );
1221 1.1 lukem bv.bv_val[lo->word.bv_len] = '{';
1222 1.1 lukem AC_MEMCPY( bv.bv_val+lo->word.bv_len+1, op->ore_reqoid.bv_val,
1223 1.1 lukem op->ore_reqoid.bv_len );
1224 1.1 lukem bv.bv_val[bv.bv_len-1] = '}';
1225 1.1 lukem bv.bv_val[bv.bv_len] = '\0';
1226 1.1 lukem attr_merge_one( e, ad_reqType, &bv, NULL );
1227 1.1 lukem } else {
1228 1.1 lukem attr_merge_one( e, ad_reqType, &lo->word, NULL );
1229 1.1 lukem }
1230 1.1 lukem
1231 1.1 lukem rdn.bv_len = snprintf( rdn.bv_val, sizeof( rdnbuf ), "%lu", op->o_connid );
1232 1.1 lukem if ( rdn.bv_len >= 0 || rdn.bv_len < sizeof( rdnbuf ) ) {
1233 1.1 lukem attr_merge_one( e, ad_reqSession, &rdn, NULL );
1234 1.1 lukem } /* else? */
1235 1.1 lukem
1236 1.1 lukem if ( BER_BVISNULL( &op->o_dn ) ) {
1237 1.1 lukem attr_merge_one( e, ad_reqAuthzID, (struct berval *)&slap_empty_bv,
1238 1.1 lukem (struct berval *)&slap_empty_bv );
1239 1.1 lukem } else {
1240 1.1 lukem attr_merge_one( e, ad_reqAuthzID, &op->o_dn, &op->o_ndn );
1241 1.1 lukem }
1242 1.1 lukem
1243 1.1 lukem /* FIXME: need to add reqControls and reqRespControls */
1244 1.1 lukem if ( op->o_ctrls ) {
1245 1.1 lukem BerVarray vals = NULL,
1246 1.1 lukem nvals = NULL;
1247 1.1 lukem
1248 1.1 lukem if ( accesslog_ctrls( op->o_ctrls, &vals, &nvals,
1249 1.1 lukem op->o_tmpmemctx ) == LDAP_SUCCESS && vals )
1250 1.1 lukem {
1251 1.1 lukem attr_merge( e, ad_reqControls, vals, nvals );
1252 1.1 lukem ber_bvarray_free_x( vals, op->o_tmpmemctx );
1253 1.1 lukem ber_bvarray_free_x( nvals, op->o_tmpmemctx );
1254 1.1 lukem }
1255 1.1 lukem }
1256 1.1 lukem
1257 1.1 lukem if ( rs->sr_ctrls ) {
1258 1.1 lukem BerVarray vals = NULL,
1259 1.1 lukem nvals = NULL;
1260 1.1 lukem
1261 1.1 lukem if ( accesslog_ctrls( rs->sr_ctrls, &vals, &nvals,
1262 1.1 lukem op->o_tmpmemctx ) == LDAP_SUCCESS && vals )
1263 1.1 lukem {
1264 1.1 lukem attr_merge( e, ad_reqRespControls, vals, nvals );
1265 1.1 lukem ber_bvarray_free_x( vals, op->o_tmpmemctx );
1266 1.1 lukem ber_bvarray_free_x( nvals, op->o_tmpmemctx );
1267 1.1 lukem }
1268 1.1 lukem
1269 1.1 lukem }
1270 1.1 lukem
1271 1.1 lukem return e;
1272 1.1 lukem }
1273 1.1 lukem
1274 1.1 lukem static struct berval scopes[] = {
1275 1.1 lukem BER_BVC("base"),
1276 1.1 lukem BER_BVC("one"),
1277 1.1 lukem BER_BVC("sub"),
1278 1.1 lukem BER_BVC("subord")
1279 1.1 lukem };
1280 1.1 lukem
1281 1.1 lukem static struct berval derefs[] = {
1282 1.1 lukem BER_BVC("never"),
1283 1.1 lukem BER_BVC("searching"),
1284 1.1 lukem BER_BVC("finding"),
1285 1.1 lukem BER_BVC("always")
1286 1.1 lukem };
1287 1.1 lukem
1288 1.1 lukem static struct berval simple = BER_BVC("SIMPLE");
1289 1.1 lukem
1290 1.1 lukem static void accesslog_val2val(AttributeDescription *ad, struct berval *val,
1291 1.1 lukem char c_op, struct berval *dst) {
1292 1.1 lukem char *ptr;
1293 1.1 lukem
1294 1.1 lukem dst->bv_len = ad->ad_cname.bv_len + val->bv_len + 2;
1295 1.1 lukem if ( c_op ) dst->bv_len++;
1296 1.1 lukem
1297 1.1 lukem dst->bv_val = ch_malloc( dst->bv_len+1 );
1298 1.1 lukem
1299 1.1 lukem ptr = lutil_strcopy( dst->bv_val, ad->ad_cname.bv_val );
1300 1.1 lukem *ptr++ = ':';
1301 1.1 lukem if ( c_op )
1302 1.1 lukem *ptr++ = c_op;
1303 1.1 lukem *ptr++ = ' ';
1304 1.1 lukem AC_MEMCPY( ptr, val->bv_val, val->bv_len );
1305 1.1 lukem dst->bv_val[dst->bv_len] = '\0';
1306 1.1 lukem }
1307 1.1 lukem
1308 1.1 lukem static int accesslog_response(Operation *op, SlapReply *rs) {
1309 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1310 1.1 lukem log_info *li = on->on_bi.bi_private;
1311 1.1 lukem Attribute *a, *last_attr;
1312 1.1 lukem Modifications *m;
1313 1.1 lukem struct berval *b;
1314 1.1 lukem int i;
1315 1.1 lukem int logop;
1316 1.1 lukem slap_verbmasks *lo;
1317 1.1 lukem Entry *e = NULL, *old = NULL;
1318 1.1 lukem char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8];
1319 1.1 lukem struct berval bv;
1320 1.1 lukem char *ptr;
1321 1.1 lukem BerVarray vals;
1322 1.1 lukem Operation op2 = {0};
1323 1.1 lukem SlapReply rs2 = {REP_RESULT};
1324 1.1 lukem
1325 1.1 lukem if ( rs->sr_type != REP_RESULT && rs->sr_type != REP_EXTENDED )
1326 1.1 lukem return SLAP_CB_CONTINUE;
1327 1.1 lukem
1328 1.1 lukem switch ( op->o_tag ) {
1329 1.1 lukem case LDAP_REQ_ADD: logop = LOG_EN_ADD; break;
1330 1.1 lukem case LDAP_REQ_DELETE: logop = LOG_EN_DELETE; break;
1331 1.1 lukem case LDAP_REQ_MODIFY: logop = LOG_EN_MODIFY; break;
1332 1.1 lukem case LDAP_REQ_MODRDN: logop = LOG_EN_MODRDN; break;
1333 1.1 lukem case LDAP_REQ_COMPARE: logop = LOG_EN_COMPARE; break;
1334 1.1 lukem case LDAP_REQ_SEARCH: logop = LOG_EN_SEARCH; break;
1335 1.1 lukem case LDAP_REQ_BIND: logop = LOG_EN_BIND; break;
1336 1.1 lukem case LDAP_REQ_EXTENDED: logop = LOG_EN_EXTENDED; break;
1337 1.1 lukem default: /* unknown operation type */
1338 1.1 lukem logop = LOG_EN_UNKNOWN; break;
1339 1.1 lukem } /* Unbind and Abandon never reach here */
1340 1.1 lukem
1341 1.1 lukem lo = logops+logop+EN_OFFSET;
1342 1.1 lukem if ( !( li->li_ops & lo->mask ))
1343 1.1 lukem return SLAP_CB_CONTINUE;
1344 1.1 lukem
1345 1.1 lukem if ( lo->mask & LOG_OP_WRITES ) {
1346 1.1 lukem slap_callback *cb;
1347 1.1 lukem ldap_pvt_thread_mutex_lock( &li->li_log_mutex );
1348 1.1 lukem old = li->li_old;
1349 1.1 lukem li->li_old = NULL;
1350 1.1 lukem /* Disarm mod_cleanup */
1351 1.1 lukem for ( cb = op->o_callback; cb; cb = cb->sc_next ) {
1352 1.1 lukem if ( cb->sc_private == (void *)on ) {
1353 1.1 lukem cb->sc_private = NULL;
1354 1.1 lukem break;
1355 1.1 lukem }
1356 1.1 lukem }
1357 1.1 lukem ldap_pvt_thread_rmutex_unlock( &li->li_op_rmutex, op->o_tid );
1358 1.1 lukem }
1359 1.1 lukem
1360 1.1 lukem if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
1361 1.1 lukem goto done;
1362 1.1 lukem
1363 1.1 lukem e = accesslog_entry( op, rs, logop, &op2 );
1364 1.1 lukem
1365 1.1 lukem attr_merge_one( e, ad_reqDN, &op->o_req_dn, &op->o_req_ndn );
1366 1.1 lukem
1367 1.1 lukem if ( rs->sr_text ) {
1368 1.1 lukem ber_str2bv( rs->sr_text, 0, 0, &bv );
1369 1.1 lukem attr_merge_one( e, ad_reqMessage, &bv, NULL );
1370 1.1 lukem }
1371 1.1 lukem bv.bv_len = snprintf( timebuf, sizeof( timebuf ), "%d", rs->sr_err );
1372 1.1 lukem if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) {
1373 1.1 lukem bv.bv_val = timebuf;
1374 1.1 lukem attr_merge_one( e, ad_reqResult, &bv, NULL );
1375 1.1 lukem }
1376 1.1 lukem
1377 1.1 lukem last_attr = attr_find( e->e_attrs, ad_reqResult );
1378 1.1 lukem
1379 1.1 lukem switch( logop ) {
1380 1.1 lukem case LOG_EN_ADD:
1381 1.1 lukem case LOG_EN_DELETE: {
1382 1.1 lukem char c_op;
1383 1.1 lukem Entry *e2;
1384 1.1 lukem
1385 1.1 lukem if ( logop == LOG_EN_ADD ) {
1386 1.1 lukem e2 = op->ora_e;
1387 1.1 lukem c_op = '+';
1388 1.1 lukem } else {
1389 1.1 lukem if ( !old )
1390 1.1 lukem break;
1391 1.1 lukem e2 = old;
1392 1.1 lukem c_op = 0;
1393 1.1 lukem }
1394 1.1 lukem /* count all the vals */
1395 1.1 lukem i = 0;
1396 1.1 lukem for ( a=e2->e_attrs; a; a=a->a_next ) {
1397 1.1 lukem i += a->a_numvals;
1398 1.1 lukem }
1399 1.1 lukem vals = ch_malloc( (i+1) * sizeof( struct berval ));
1400 1.1 lukem i = 0;
1401 1.1 lukem for ( a=e2->e_attrs; a; a=a->a_next ) {
1402 1.1 lukem if ( a->a_vals ) {
1403 1.1 lukem for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
1404 1.1 lukem accesslog_val2val( a->a_desc, b, c_op, &vals[i] );
1405 1.1 lukem }
1406 1.1 lukem }
1407 1.1 lukem }
1408 1.1 lukem vals[i].bv_val = NULL;
1409 1.1 lukem vals[i].bv_len = 0;
1410 1.1 lukem a = attr_alloc( logop == LOG_EN_ADD ? ad_reqMod : ad_reqOld );
1411 1.1 lukem a->a_numvals = i;
1412 1.1 lukem a->a_vals = vals;
1413 1.1 lukem a->a_nvals = vals;
1414 1.1 lukem last_attr->a_next = a;
1415 1.1 lukem break;
1416 1.1 lukem }
1417 1.1 lukem
1418 1.1 lukem case LOG_EN_MODRDN:
1419 1.1 lukem case LOG_EN_MODIFY:
1420 1.1 lukem /* count all the mods */
1421 1.1 lukem i = 0;
1422 1.1 lukem for ( m = op->orm_modlist; m; m = m->sml_next ) {
1423 1.1 lukem if ( m->sml_values ) {
1424 1.1 lukem i += m->sml_numvals;
1425 1.1 lukem } else if ( m->sml_op == LDAP_MOD_DELETE ||
1426 1.1 lukem m->sml_op == LDAP_MOD_REPLACE )
1427 1.1 lukem {
1428 1.1 lukem i++;
1429 1.1 lukem }
1430 1.1 lukem }
1431 1.1 lukem vals = ch_malloc( (i+1) * sizeof( struct berval ));
1432 1.1 lukem i = 0;
1433 1.1 lukem
1434 1.1 lukem /* init flags on old entry */
1435 1.1 lukem if ( old ) {
1436 1.1 lukem for ( a = old->e_attrs; a; a = a->a_next ) {
1437 1.1 lukem log_attr *la;
1438 1.1 lukem a->a_flags = 0;
1439 1.1 lukem
1440 1.1 lukem /* look for attrs that are always logged */
1441 1.1 lukem for ( la = li->li_oldattrs; la; la = la->next ) {
1442 1.1 lukem if ( a->a_desc == la->attr ) {
1443 1.1 lukem a->a_flags = 1;
1444 1.1 lukem }
1445 1.1 lukem }
1446 1.1 lukem }
1447 1.1 lukem }
1448 1.1 lukem
1449 1.1 lukem for ( m = op->orm_modlist; m; m = m->sml_next ) {
1450 1.1 lukem /* Mark this attribute as modified */
1451 1.1 lukem if ( old ) {
1452 1.1 lukem a = attr_find( old->e_attrs, m->sml_desc );
1453 1.1 lukem if ( a ) {
1454 1.1 lukem a->a_flags = 1;
1455 1.1 lukem }
1456 1.1 lukem }
1457 1.1 lukem
1458 1.1 lukem /* don't log the RDN mods; they're explicitly logged later */
1459 1.1 lukem if ( logop == LOG_EN_MODRDN &&
1460 1.1 lukem ( m->sml_op == SLAP_MOD_SOFTADD ||
1461 1.1 lukem m->sml_op == LDAP_MOD_DELETE ) )
1462 1.1 lukem {
1463 1.1 lukem continue;
1464 1.1 lukem }
1465 1.1 lukem
1466 1.1 lukem if ( m->sml_values ) {
1467 1.1 lukem for ( b = m->sml_values; !BER_BVISNULL( b ); b++, i++ ) {
1468 1.1 lukem char c_op;
1469 1.1 lukem
1470 1.1 lukem switch ( m->sml_op ) {
1471 1.1 lukem case LDAP_MOD_ADD: c_op = '+'; break;
1472 1.1 lukem case LDAP_MOD_DELETE: c_op = '-'; break;
1473 1.1 lukem case LDAP_MOD_REPLACE: c_op = '='; break;
1474 1.1 lukem case LDAP_MOD_INCREMENT: c_op = '#'; break;
1475 1.1 lukem
1476 1.1 lukem /* unknown op. there shouldn't be any of these. we
1477 1.1 lukem * don't know what to do with it, but we shouldn't just
1478 1.1 lukem * ignore it.
1479 1.1 lukem */
1480 1.1 lukem default: c_op = '?'; break;
1481 1.1 lukem }
1482 1.1 lukem accesslog_val2val( m->sml_desc, b, c_op, &vals[i] );
1483 1.1 lukem }
1484 1.1 lukem } else if ( m->sml_op == LDAP_MOD_DELETE ||
1485 1.1 lukem m->sml_op == LDAP_MOD_REPLACE )
1486 1.1 lukem {
1487 1.1 lukem vals[i].bv_len = m->sml_desc->ad_cname.bv_len + 2;
1488 1.1 lukem vals[i].bv_val = ch_malloc( vals[i].bv_len + 1 );
1489 1.1 lukem ptr = lutil_strcopy( vals[i].bv_val,
1490 1.1 lukem m->sml_desc->ad_cname.bv_val );
1491 1.1 lukem *ptr++ = ':';
1492 1.1 lukem if ( m->sml_op == LDAP_MOD_DELETE ) {
1493 1.1 lukem *ptr++ = '-';
1494 1.1 lukem } else {
1495 1.1 lukem *ptr++ = '=';
1496 1.1 lukem }
1497 1.1 lukem *ptr = '\0';
1498 1.1 lukem i++;
1499 1.1 lukem }
1500 1.1 lukem }
1501 1.1 lukem
1502 1.1 lukem if ( i > 0 ) {
1503 1.1 lukem BER_BVZERO( &vals[i] );
1504 1.1 lukem a = attr_alloc( ad_reqMod );
1505 1.1 lukem a->a_numvals = i;
1506 1.1 lukem a->a_vals = vals;
1507 1.1 lukem a->a_nvals = vals;
1508 1.1 lukem last_attr->a_next = a;
1509 1.1 lukem last_attr = a;
1510 1.1 lukem
1511 1.1 lukem } else {
1512 1.1 lukem ch_free( vals );
1513 1.1 lukem }
1514 1.1 lukem
1515 1.1 lukem if ( old ) {
1516 1.1 lukem /* count all the vals */
1517 1.1 lukem i = 0;
1518 1.1 lukem for ( a = old->e_attrs; a != NULL; a = a->a_next ) {
1519 1.1 lukem if ( a->a_vals && a->a_flags ) {
1520 1.1 lukem i += a->a_numvals;
1521 1.1 lukem }
1522 1.1 lukem }
1523 1.1 lukem vals = ch_malloc( (i + 1) * sizeof( struct berval ) );
1524 1.1 lukem i = 0;
1525 1.1 lukem for ( a=old->e_attrs; a; a=a->a_next ) {
1526 1.1 lukem if ( a->a_vals && a->a_flags ) {
1527 1.1 lukem for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
1528 1.1 lukem accesslog_val2val( a->a_desc, b, 0, &vals[i] );
1529 1.1 lukem }
1530 1.1 lukem }
1531 1.1 lukem }
1532 1.1 lukem vals[i].bv_val = NULL;
1533 1.1 lukem vals[i].bv_len = 0;
1534 1.1 lukem a = attr_alloc( ad_reqOld );
1535 1.1 lukem a->a_numvals = i;
1536 1.1 lukem a->a_vals = vals;
1537 1.1 lukem a->a_nvals = vals;
1538 1.1 lukem last_attr->a_next = a;
1539 1.1 lukem }
1540 1.1 lukem if ( logop == LOG_EN_MODIFY ) {
1541 1.1 lukem break;
1542 1.1 lukem }
1543 1.1 lukem
1544 1.1 lukem /* Now log the actual modRDN info */
1545 1.1 lukem attr_merge_one( e, ad_reqNewRDN, &op->orr_newrdn, &op->orr_nnewrdn );
1546 1.1 lukem attr_merge_one( e, ad_reqDeleteOldRDN, op->orr_deleteoldrdn ?
1547 1.1 lukem (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv,
1548 1.1 lukem NULL );
1549 1.1 lukem if ( op->orr_newSup ) {
1550 1.1 lukem attr_merge_one( e, ad_reqNewSuperior, op->orr_newSup, op->orr_nnewSup );
1551 1.1 lukem }
1552 1.1 lukem break;
1553 1.1 lukem
1554 1.1 lukem case LOG_EN_COMPARE:
1555 1.1 lukem bv.bv_len = op->orc_ava->aa_desc->ad_cname.bv_len + 1 +
1556 1.1 lukem op->orc_ava->aa_value.bv_len;
1557 1.1 lukem bv.bv_val = op->o_tmpalloc( bv.bv_len+1, op->o_tmpmemctx );
1558 1.1 lukem ptr = lutil_strcopy( bv.bv_val, op->orc_ava->aa_desc->ad_cname.bv_val );
1559 1.1 lukem *ptr++ = '=';
1560 1.1 lukem AC_MEMCPY( ptr, op->orc_ava->aa_value.bv_val, op->orc_ava->aa_value.bv_len );
1561 1.1 lukem bv.bv_val[bv.bv_len] = '\0';
1562 1.1 lukem attr_merge_one( e, ad_reqAssertion, &bv, NULL );
1563 1.1 lukem op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
1564 1.1 lukem break;
1565 1.1 lukem
1566 1.1 lukem case LOG_EN_SEARCH:
1567 1.1 lukem attr_merge_one( e, ad_reqScope, &scopes[op->ors_scope], NULL );
1568 1.1 lukem attr_merge_one( e, ad_reqDerefAliases, &derefs[op->ors_deref], NULL );
1569 1.1 lukem attr_merge_one( e, ad_reqAttrsOnly, op->ors_attrsonly ?
1570 1.1 lukem (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv,
1571 1.1 lukem NULL );
1572 1.1 lukem if ( !BER_BVISEMPTY( &op->ors_filterstr ))
1573 1.1 lukem attr_merge_one( e, ad_reqFilter, &op->ors_filterstr, NULL );
1574 1.1 lukem if ( op->ors_attrs ) {
1575 1.1 lukem /* count them */
1576 1.1 lukem for (i=0; !BER_BVISNULL(&op->ors_attrs[i].an_name );i++)
1577 1.1 lukem ;
1578 1.1 lukem vals = op->o_tmpalloc( (i+1) * sizeof(struct berval),
1579 1.1 lukem op->o_tmpmemctx );
1580 1.1 lukem for (i=0; !BER_BVISNULL(&op->ors_attrs[i].an_name );i++)
1581 1.1 lukem vals[i] = op->ors_attrs[i].an_name;
1582 1.1 lukem vals[i].bv_val = NULL;
1583 1.1 lukem vals[i].bv_len = 0;
1584 1.1 lukem attr_merge( e, ad_reqAttr, vals, NULL );
1585 1.1 lukem op->o_tmpfree( vals, op->o_tmpmemctx );
1586 1.1 lukem }
1587 1.1 lukem bv.bv_val = timebuf;
1588 1.1 lukem bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", rs->sr_nentries );
1589 1.1 lukem if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) {
1590 1.1 lukem attr_merge_one( e, ad_reqEntries, &bv, NULL );
1591 1.1 lukem } /* else? */
1592 1.1 lukem
1593 1.1 lukem bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", op->ors_tlimit );
1594 1.1 lukem if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) {
1595 1.1 lukem attr_merge_one( e, ad_reqTimeLimit, &bv, NULL );
1596 1.1 lukem } /* else? */
1597 1.1 lukem
1598 1.1 lukem bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", op->ors_slimit );
1599 1.1 lukem if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) {
1600 1.1 lukem attr_merge_one( e, ad_reqSizeLimit, &bv, NULL );
1601 1.1 lukem } /* else? */
1602 1.1 lukem break;
1603 1.1 lukem
1604 1.1 lukem case LOG_EN_BIND:
1605 1.1 lukem bv.bv_val = timebuf;
1606 1.1 lukem bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", op->o_protocol );
1607 1.1 lukem if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) {
1608 1.1 lukem attr_merge_one( e, ad_reqVersion, &bv, NULL );
1609 1.1 lukem } /* else? */
1610 1.1 lukem if ( op->orb_method == LDAP_AUTH_SIMPLE ) {
1611 1.1 lukem attr_merge_one( e, ad_reqMethod, &simple, NULL );
1612 1.1 lukem } else {
1613 1.1 lukem bv.bv_len = STRLENOF("SASL()") + op->orb_mech.bv_len;
1614 1.1 lukem bv.bv_val = op->o_tmpalloc( bv.bv_len + 1, op->o_tmpmemctx );
1615 1.1 lukem ptr = lutil_strcopy( bv.bv_val, "SASL(" );
1616 1.1 lukem ptr = lutil_strcopy( ptr, op->orb_mech.bv_val );
1617 1.1 lukem *ptr++ = ')';
1618 1.1 lukem *ptr = '\0';
1619 1.1 lukem attr_merge_one( e, ad_reqMethod, &bv, NULL );
1620 1.1 lukem op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
1621 1.1 lukem }
1622 1.1 lukem
1623 1.1 lukem break;
1624 1.1 lukem
1625 1.1 lukem case LOG_EN_EXTENDED:
1626 1.1 lukem if ( op->ore_reqdata ) {
1627 1.1 lukem attr_merge_one( e, ad_reqData, op->ore_reqdata, NULL );
1628 1.1 lukem }
1629 1.1 lukem break;
1630 1.1 lukem
1631 1.1 lukem case LOG_EN_UNKNOWN:
1632 1.1 lukem /* we don't know its parameters, don't add any */
1633 1.1 lukem break;
1634 1.1 lukem }
1635 1.1 lukem
1636 1.1 lukem op2.o_hdr = op->o_hdr;
1637 1.1 lukem op2.o_tag = LDAP_REQ_ADD;
1638 1.1 lukem op2.o_bd = li->li_db;
1639 1.1 lukem op2.o_dn = li->li_db->be_rootdn;
1640 1.1 lukem op2.o_ndn = li->li_db->be_rootndn;
1641 1.1 lukem op2.o_req_dn = e->e_name;
1642 1.1 lukem op2.o_req_ndn = e->e_nname;
1643 1.1 lukem op2.ora_e = e;
1644 1.1 lukem op2.o_callback = &nullsc;
1645 1.1 lukem
1646 1.1 lukem if (( lo->mask & LOG_OP_WRITES ) && !BER_BVISEMPTY( &op->o_csn )) {
1647 1.1 lukem slap_queue_csn( &op2, &op->o_csn );
1648 1.1 lukem }
1649 1.1 lukem
1650 1.1 lukem op2.o_bd->be_add( &op2, &rs2 );
1651 1.1 lukem if ( e == op2.ora_e ) entry_free( e );
1652 1.1 lukem e = NULL;
1653 1.1 lukem
1654 1.1 lukem done:
1655 1.1 lukem if ( lo->mask & LOG_OP_WRITES )
1656 1.1 lukem ldap_pvt_thread_mutex_unlock( &li->li_log_mutex );
1657 1.1 lukem if ( old ) entry_free( old );
1658 1.1 lukem return SLAP_CB_CONTINUE;
1659 1.1 lukem }
1660 1.1 lukem
1661 1.1 lukem /* Since Bind success is sent by the frontend, it won't normally enter
1662 1.1 lukem * the overlay response callback. Add another callback to make sure it
1663 1.1 lukem * gets here.
1664 1.1 lukem */
1665 1.1 lukem static int
1666 1.1 lukem accesslog_bind_resp( Operation *op, SlapReply *rs )
1667 1.1 lukem {
1668 1.1 lukem BackendDB *be, db;
1669 1.1 lukem int rc;
1670 1.1 lukem slap_callback *sc;
1671 1.1 lukem
1672 1.1 lukem be = op->o_bd;
1673 1.1 lukem db = *be;
1674 1.1 lukem op->o_bd = &db;
1675 1.1 lukem db.bd_info = op->o_callback->sc_private;
1676 1.1 lukem rc = accesslog_response( op, rs );
1677 1.1 lukem op->o_bd = be;
1678 1.1 lukem sc = op->o_callback;
1679 1.1 lukem op->o_callback = sc->sc_next;
1680 1.1 lukem op->o_tmpfree( sc, op->o_tmpmemctx );
1681 1.1 lukem return rc;
1682 1.1 lukem }
1683 1.1 lukem
1684 1.1 lukem static int
1685 1.1 lukem accesslog_op_bind( Operation *op, SlapReply *rs )
1686 1.1 lukem {
1687 1.1 lukem slap_callback *sc;
1688 1.1 lukem
1689 1.1 lukem sc = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
1690 1.1 lukem sc->sc_response = accesslog_bind_resp;
1691 1.1 lukem sc->sc_private = op->o_bd->bd_info;
1692 1.1 lukem
1693 1.1 lukem if ( op->o_callback ) {
1694 1.1 lukem sc->sc_next = op->o_callback->sc_next;
1695 1.1 lukem op->o_callback->sc_next = sc;
1696 1.1 lukem } else {
1697 1.1 lukem op->o_callback = sc;
1698 1.1 lukem }
1699 1.1 lukem return SLAP_CB_CONTINUE;
1700 1.1 lukem }
1701 1.1 lukem
1702 1.1 lukem static int
1703 1.1 lukem accesslog_mod_cleanup( Operation *op, SlapReply *rs )
1704 1.1 lukem {
1705 1.1 lukem slap_callback *sc = op->o_callback;
1706 1.1 lukem slap_overinst *on = sc->sc_private;
1707 1.1 lukem op->o_callback = sc->sc_next;
1708 1.1 lukem
1709 1.1 lukem op->o_tmpfree( sc, op->o_tmpmemctx );
1710 1.1 lukem
1711 1.1 lukem if ( on ) {
1712 1.1 lukem BackendInfo *bi = op->o_bd->bd_info;
1713 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on;
1714 1.1 lukem accesslog_response( op, rs );
1715 1.1 lukem op->o_bd->bd_info = bi;
1716 1.1 lukem }
1717 1.1 lukem return 0;
1718 1.1 lukem }
1719 1.1 lukem
1720 1.1 lukem static int
1721 1.1 lukem accesslog_op_mod( Operation *op, SlapReply *rs )
1722 1.1 lukem {
1723 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1724 1.1 lukem log_info *li = on->on_bi.bi_private;
1725 1.1 lukem
1726 1.1 lukem if ( li->li_ops & LOG_OP_WRITES ) {
1727 1.1 lukem slap_callback *cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ), *cb2;
1728 1.1 lukem cb->sc_cleanup = accesslog_mod_cleanup;
1729 1.1 lukem cb->sc_response = NULL;
1730 1.1 lukem cb->sc_private = on;
1731 1.1 lukem cb->sc_next = NULL;
1732 1.1 lukem for ( cb2 = op->o_callback; cb2->sc_next; cb2 = cb2->sc_next );
1733 1.1 lukem cb2->sc_next = cb;
1734 1.1 lukem
1735 1.1 lukem ldap_pvt_thread_rmutex_lock( &li->li_op_rmutex, op->o_tid );
1736 1.1 lukem if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE ||
1737 1.1 lukem op->o_tag == LDAP_REQ_MODIFY ||
1738 1.1 lukem ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) {
1739 1.1 lukem int rc;
1740 1.1 lukem Entry *e;
1741 1.1 lukem
1742 1.1 lukem op->o_bd->bd_info = on->on_info->oi_orig;
1743 1.1 lukem rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
1744 1.1 lukem if ( e ) {
1745 1.1 lukem if ( test_filter( op, e, li->li_oldf ) == LDAP_COMPARE_TRUE )
1746 1.1 lukem li->li_old = entry_dup( e );
1747 1.1 lukem be_entry_release_rw( op, e, 0 );
1748 1.1 lukem }
1749 1.1 lukem op->o_bd->bd_info = (BackendInfo *)on;
1750 1.1 lukem }
1751 1.1 lukem }
1752 1.1 lukem return SLAP_CB_CONTINUE;
1753 1.1 lukem }
1754 1.1 lukem
1755 1.1 lukem /* unbinds are broadcast to all backends; we only log it if this
1756 1.1 lukem * backend was used for the original bind.
1757 1.1 lukem */
1758 1.1 lukem static int
1759 1.1 lukem accesslog_unbind( Operation *op, SlapReply *rs )
1760 1.1 lukem {
1761 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1762 1.1 lukem if ( op->o_conn->c_authz_backend == on->on_info->oi_origdb ) {
1763 1.1 lukem log_info *li = on->on_bi.bi_private;
1764 1.1 lukem Operation op2 = {0};
1765 1.1 lukem void *cids[SLAP_MAX_CIDS];
1766 1.1 lukem SlapReply rs2 = {REP_RESULT};
1767 1.1 lukem Entry *e;
1768 1.1 lukem
1769 1.1 lukem if ( !( li->li_ops & LOG_OP_UNBIND ))
1770 1.1 lukem return SLAP_CB_CONTINUE;
1771 1.1 lukem
1772 1.1 lukem e = accesslog_entry( op, rs, LOG_EN_UNBIND, &op2 );
1773 1.1 lukem op2.o_hdr = op->o_hdr;
1774 1.1 lukem op2.o_tag = LDAP_REQ_ADD;
1775 1.1 lukem op2.o_bd = li->li_db;
1776 1.1 lukem op2.o_dn = li->li_db->be_rootdn;
1777 1.1 lukem op2.o_ndn = li->li_db->be_rootndn;
1778 1.1 lukem op2.o_req_dn = e->e_name;
1779 1.1 lukem op2.o_req_ndn = e->e_nname;
1780 1.1 lukem op2.ora_e = e;
1781 1.1 lukem op2.o_callback = &nullsc;
1782 1.1 lukem op2.o_controls = cids;
1783 1.1 lukem memset(cids, 0, sizeof( cids ));
1784 1.1 lukem
1785 1.1 lukem op2.o_bd->be_add( &op2, &rs2 );
1786 1.1 lukem if ( e == op2.ora_e )
1787 1.1 lukem entry_free( e );
1788 1.1 lukem }
1789 1.1 lukem return SLAP_CB_CONTINUE;
1790 1.1 lukem }
1791 1.1 lukem
1792 1.1 lukem static int
1793 1.1 lukem accesslog_abandon( Operation *op, SlapReply *rs )
1794 1.1 lukem {
1795 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1796 1.1 lukem log_info *li = on->on_bi.bi_private;
1797 1.1 lukem Operation op2 = {0};
1798 1.1 lukem void *cids[SLAP_MAX_CIDS];
1799 1.1 lukem SlapReply rs2 = {REP_RESULT};
1800 1.1 lukem Entry *e;
1801 1.1 lukem char buf[64];
1802 1.1 lukem struct berval bv;
1803 1.1 lukem
1804 1.1 lukem if ( !op->o_time || !( li->li_ops & LOG_OP_ABANDON ))
1805 1.1 lukem return SLAP_CB_CONTINUE;
1806 1.1 lukem
1807 1.1 lukem e = accesslog_entry( op, rs, LOG_EN_ABANDON, &op2 );
1808 1.1 lukem bv.bv_val = buf;
1809 1.1 lukem bv.bv_len = snprintf( buf, sizeof( buf ), "%d", op->orn_msgid );
1810 1.1 lukem if ( bv.bv_len >= 0 && bv.bv_len < sizeof( buf ) ) {
1811 1.1 lukem attr_merge_one( e, ad_reqId, &bv, NULL );
1812 1.1 lukem } /* else? */
1813 1.1 lukem
1814 1.1 lukem op2.o_hdr = op->o_hdr;
1815 1.1 lukem op2.o_tag = LDAP_REQ_ADD;
1816 1.1 lukem op2.o_bd = li->li_db;
1817 1.1 lukem op2.o_dn = li->li_db->be_rootdn;
1818 1.1 lukem op2.o_ndn = li->li_db->be_rootndn;
1819 1.1 lukem op2.o_req_dn = e->e_name;
1820 1.1 lukem op2.o_req_ndn = e->e_nname;
1821 1.1 lukem op2.ora_e = e;
1822 1.1 lukem op2.o_callback = &nullsc;
1823 1.1 lukem op2.o_controls = cids;
1824 1.1 lukem memset(cids, 0, sizeof( cids ));
1825 1.1 lukem
1826 1.1 lukem op2.o_bd->be_add( &op2, &rs2 );
1827 1.1 lukem if ( e == op2.ora_e )
1828 1.1 lukem entry_free( e );
1829 1.1 lukem
1830 1.1 lukem return SLAP_CB_CONTINUE;
1831 1.1 lukem }
1832 1.1 lukem
1833 1.1 lukem static int
1834 1.1 lukem accesslog_operational( Operation *op, SlapReply *rs )
1835 1.1 lukem {
1836 1.1 lukem slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1837 1.1 lukem log_info *li = on->on_bi.bi_private;
1838 1.1 lukem
1839 1.1 lukem if ( op->o_sync != SLAP_CONTROL_NONE )
1840 1.1 lukem return SLAP_CB_CONTINUE;
1841 1.1 lukem
1842 1.1 lukem if ( rs->sr_entry != NULL
1843 1.1 lukem && dn_match( &op->o_bd->be_nsuffix[0], &rs->sr_entry->e_nname ) )
1844 1.1 lukem {
1845 1.1 lukem Attribute **ap;
1846 1.1 lukem
1847 1.1 lukem for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
1848 1.1 lukem /* just count */ ;
1849 1.1 lukem
1850 1.1 lukem if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
1851 1.1 lukem ad_inlist( ad_auditContext, rs->sr_attrs ) )
1852 1.1 lukem {
1853 1.1 lukem *ap = attr_alloc( ad_auditContext );
1854 1.1 lukem attr_valadd( *ap,
1855 1.1 lukem &li->li_db->be_suffix[0],
1856 1.1 lukem &li->li_db->be_nsuffix[0], 1 );
1857 1.1 lukem }
1858 1.1 lukem }
1859 1.1 lukem
1860 1.1 lukem return SLAP_CB_CONTINUE;
1861 1.1 lukem }
1862 1.1 lukem
1863 1.1 lukem static slap_overinst accesslog;
1864 1.1 lukem
1865 1.1 lukem static int
1866 1.1 lukem accesslog_db_init(
1867 1.1 lukem BackendDB *be,
1868 1.1 lukem ConfigReply *cr
1869 1.1 lukem )
1870 1.1 lukem {
1871 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
1872 1.1 lukem log_info *li = ch_calloc(1, sizeof(log_info));
1873 1.1 lukem
1874 1.1 lukem on->on_bi.bi_private = li;
1875 1.1 lukem ldap_pvt_thread_rmutex_init( &li->li_op_rmutex );
1876 1.1 lukem ldap_pvt_thread_mutex_init( &li->li_log_mutex );
1877 1.1 lukem return 0;
1878 1.1 lukem }
1879 1.1 lukem
1880 1.1 lukem static int
1881 1.1 lukem accesslog_db_destroy(
1882 1.1 lukem BackendDB *be,
1883 1.1 lukem ConfigReply *cr
1884 1.1 lukem )
1885 1.1 lukem {
1886 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
1887 1.1 lukem log_info *li = on->on_bi.bi_private;
1888 1.1 lukem log_attr *la;
1889 1.1 lukem
1890 1.1 lukem if ( li->li_oldf )
1891 1.1 lukem filter_free( li->li_oldf );
1892 1.1 lukem for ( la=li->li_oldattrs; la; la=li->li_oldattrs ) {
1893 1.1 lukem li->li_oldattrs = la->next;
1894 1.1 lukem ch_free( la );
1895 1.1 lukem }
1896 1.1 lukem ldap_pvt_thread_mutex_destroy( &li->li_log_mutex );
1897 1.1 lukem ldap_pvt_thread_rmutex_destroy( &li->li_op_rmutex );
1898 1.1 lukem free( li );
1899 1.1 lukem return LDAP_SUCCESS;
1900 1.1 lukem }
1901 1.1 lukem
1902 1.1 lukem /* Create the logdb's root entry if it's missing */
1903 1.1 lukem static void *
1904 1.1 lukem accesslog_db_root(
1905 1.1 lukem void *ctx,
1906 1.1 lukem void *arg )
1907 1.1 lukem {
1908 1.1 lukem struct re_s *rtask = arg;
1909 1.1 lukem slap_overinst *on = rtask->arg;
1910 1.1 lukem log_info *li = on->on_bi.bi_private;
1911 1.1 lukem
1912 1.1 lukem Connection conn = {0};
1913 1.1 lukem OperationBuffer opbuf;
1914 1.1 lukem Operation *op;
1915 1.1 lukem
1916 1.1 lukem Entry *e;
1917 1.1 lukem int rc;
1918 1.1 lukem
1919 1.1 lukem connection_fake_init( &conn, &opbuf, ctx );
1920 1.1 lukem op = &opbuf.ob_op;
1921 1.1 lukem op->o_bd = li->li_db;
1922 1.1 lukem op->o_dn = li->li_db->be_rootdn;
1923 1.1 lukem op->o_ndn = li->li_db->be_rootndn;
1924 1.1 lukem rc = be_entry_get_rw( op, li->li_db->be_nsuffix, NULL, NULL, 0, &e );
1925 1.1 lukem
1926 1.1 lukem if ( e ) {
1927 1.1 lukem be_entry_release_rw( op, e, 0 );
1928 1.1 lukem
1929 1.1 lukem } else {
1930 1.1 lukem SlapReply rs = {REP_RESULT};
1931 1.1 lukem struct berval rdn, nrdn, attr;
1932 1.1 lukem char *ptr;
1933 1.1 lukem AttributeDescription *ad = NULL;
1934 1.1 lukem const char *text = NULL;
1935 1.1 lukem Entry *e_ctx;
1936 1.1 lukem
1937 1.1 lukem e = entry_alloc();
1938 1.1 lukem ber_dupbv( &e->e_name, li->li_db->be_suffix );
1939 1.1 lukem ber_dupbv( &e->e_nname, li->li_db->be_nsuffix );
1940 1.1 lukem
1941 1.1 lukem attr_merge_one( e, slap_schema.si_ad_objectClass,
1942 1.1 lukem &log_container->soc_cname, NULL );
1943 1.1 lukem
1944 1.1 lukem dnRdn( &e->e_name, &rdn );
1945 1.1 lukem dnRdn( &e->e_nname, &nrdn );
1946 1.1 lukem ptr = ber_bvchr( &rdn, '=' );
1947 1.1 lukem
1948 1.1 lukem assert( ptr != NULL );
1949 1.1 lukem
1950 1.1 lukem attr.bv_val = rdn.bv_val;
1951 1.1 lukem attr.bv_len = ptr - rdn.bv_val;
1952 1.1 lukem
1953 1.1 lukem slap_bv2ad( &attr, &ad, &text );
1954 1.1 lukem
1955 1.1 lukem rdn.bv_val = ptr+1;
1956 1.1 lukem rdn.bv_len -= attr.bv_len + 1;
1957 1.1 lukem ptr = ber_bvchr( &nrdn, '=' );
1958 1.1 lukem nrdn.bv_len -= ptr - nrdn.bv_val + 1;
1959 1.1 lukem nrdn.bv_val = ptr+1;
1960 1.1 lukem attr_merge_one( e, ad, &rdn, &nrdn );
1961 1.1 lukem
1962 1.1 lukem /* Get contextCSN from main DB */
1963 1.1 lukem op->o_bd = on->on_info->oi_origdb;
1964 1.1 lukem rc = be_entry_get_rw( op, op->o_bd->be_nsuffix, NULL,
1965 1.1 lukem slap_schema.si_ad_contextCSN, 0, &e_ctx );
1966 1.1 lukem
1967 1.1 lukem if ( e_ctx ) {
1968 1.1 lukem Attribute *a;
1969 1.1 lukem
1970 1.1 lukem a = attr_find( e_ctx->e_attrs, slap_schema.si_ad_contextCSN );
1971 1.1 lukem if ( a ) {
1972 1.1 lukem /* FIXME: contextCSN could have multiple values!
1973 1.1 lukem * should select the one with the server's SID */
1974 1.1 lukem attr_merge_one( e, slap_schema.si_ad_entryCSN,
1975 1.1 lukem &a->a_vals[0], &a->a_nvals[0] );
1976 1.1 lukem attr_merge( e, a->a_desc, a->a_vals, a->a_nvals );
1977 1.1 lukem }
1978 1.1 lukem be_entry_release_rw( op, e_ctx, 0 );
1979 1.1 lukem }
1980 1.1 lukem op->o_bd = li->li_db;
1981 1.1 lukem
1982 1.1 lukem op->ora_e = e;
1983 1.1 lukem op->o_req_dn = e->e_name;
1984 1.1 lukem op->o_req_ndn = e->e_nname;
1985 1.1 lukem op->o_callback = &nullsc;
1986 1.1 lukem SLAP_DBFLAGS( op->o_bd ) |= SLAP_DBFLAG_NOLASTMOD;
1987 1.1 lukem rc = op->o_bd->be_add( op, &rs );
1988 1.1 lukem SLAP_DBFLAGS( op->o_bd ) ^= SLAP_DBFLAG_NOLASTMOD;
1989 1.1 lukem if ( e == op->ora_e )
1990 1.1 lukem entry_free( e );
1991 1.1 lukem }
1992 1.1 lukem ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
1993 1.1 lukem ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
1994 1.1 lukem ldap_pvt_runqueue_remove( &slapd_rq, rtask );
1995 1.1 lukem ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
1996 1.1 lukem
1997 1.1 lukem return NULL;
1998 1.1 lukem }
1999 1.1 lukem
2000 1.1 lukem static int
2001 1.1 lukem accesslog_db_open(
2002 1.1 lukem BackendDB *be,
2003 1.1 lukem ConfigReply *cr
2004 1.1 lukem )
2005 1.1 lukem {
2006 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info;
2007 1.1 lukem log_info *li = on->on_bi.bi_private;
2008 1.1 lukem
2009 1.1 lukem
2010 1.1 lukem if ( !BER_BVISEMPTY( &li->li_db_suffix )) {
2011 1.1 lukem li->li_db = select_backend( &li->li_db_suffix, 0 );
2012 1.1 lukem ch_free( li->li_db_suffix.bv_val );
2013 1.1 lukem BER_BVZERO( &li->li_db_suffix );
2014 1.1 lukem }
2015 1.1 lukem if ( li->li_db == NULL ) {
2016 1.1 lukem Debug( LDAP_DEBUG_ANY,
2017 1.1 lukem "accesslog: \"logdb <suffix>\" missing or invalid.\n",
2018 1.1 lukem 0, 0, 0 );
2019 1.1 lukem return 1;
2020 1.1 lukem }
2021 1.1 lukem
2022 1.1 lukem if ( slapMode & SLAP_TOOL_MODE )
2023 1.1 lukem return 0;
2024 1.1 lukem
2025 1.1 lukem if ( BER_BVISEMPTY( &li->li_db->be_rootndn )) {
2026 1.1 lukem ber_dupbv( &li->li_db->be_rootdn, li->li_db->be_suffix );
2027 1.1 lukem ber_dupbv( &li->li_db->be_rootndn, li->li_db->be_nsuffix );
2028 1.1 lukem }
2029 1.1 lukem
2030 1.1 lukem ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
2031 1.1 lukem ldap_pvt_runqueue_insert( &slapd_rq, 3600, accesslog_db_root, on,
2032 1.1 lukem "accesslog_db_root", li->li_db->be_suffix[0].bv_val );
2033 1.1 lukem ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
2034 1.1 lukem
2035 1.1 lukem return 0;
2036 1.1 lukem }
2037 1.1 lukem
2038 1.1 lukem int accesslog_initialize()
2039 1.1 lukem {
2040 1.1 lukem int i, rc;
2041 1.1 lukem
2042 1.1 lukem accesslog.on_bi.bi_type = "accesslog";
2043 1.1 lukem accesslog.on_bi.bi_db_init = accesslog_db_init;
2044 1.1 lukem accesslog.on_bi.bi_db_destroy = accesslog_db_destroy;
2045 1.1 lukem accesslog.on_bi.bi_db_open = accesslog_db_open;
2046 1.1 lukem
2047 1.1 lukem accesslog.on_bi.bi_op_add = accesslog_op_mod;
2048 1.1 lukem accesslog.on_bi.bi_op_bind = accesslog_op_bind;
2049 1.1 lukem accesslog.on_bi.bi_op_delete = accesslog_op_mod;
2050 1.1 lukem accesslog.on_bi.bi_op_modify = accesslog_op_mod;
2051 1.1 lukem accesslog.on_bi.bi_op_modrdn = accesslog_op_mod;
2052 1.1 lukem accesslog.on_bi.bi_op_unbind = accesslog_unbind;
2053 1.1 lukem accesslog.on_bi.bi_op_abandon = accesslog_abandon;
2054 1.1 lukem accesslog.on_bi.bi_operational = accesslog_operational;
2055 1.1 lukem accesslog.on_response = accesslog_response;
2056 1.1 lukem
2057 1.1 lukem accesslog.on_bi.bi_cf_ocs = log_cfocs;
2058 1.1 lukem
2059 1.1 lukem nullsc.sc_response = slap_null_cb;
2060 1.1 lukem
2061 1.1 lukem rc = config_register_schema( log_cfats, log_cfocs );
2062 1.1 lukem if ( rc ) return rc;
2063 1.1 lukem
2064 1.1 lukem /* log schema integration */
2065 1.1 lukem for ( i=0; lsyntaxes[i].oid; i++ ) {
2066 1.1 lukem int code;
2067 1.1 lukem
2068 1.1 lukem code = register_syntax( &lsyntaxes[ i ].syn );
2069 1.1 lukem if ( code != 0 ) {
2070 1.1 lukem Debug( LDAP_DEBUG_ANY,
2071 1.1 lukem "accesslog_init: register_syntax failed\n",
2072 1.1 lukem 0, 0, 0 );
2073 1.1 lukem return code;
2074 1.1 lukem }
2075 1.1 lukem
2076 1.1 lukem if ( lsyntaxes[i].mrs != NULL ) {
2077 1.1 lukem code = mr_make_syntax_compat_with_mrs(
2078 1.1 lukem lsyntaxes[i].oid, lsyntaxes[i].mrs );
2079 1.1 lukem if ( code < 0 ) {
2080 1.1 lukem Debug( LDAP_DEBUG_ANY,
2081 1.1 lukem "accesslog_init: "
2082 1.1 lukem "mr_make_syntax_compat_with_mrs "
2083 1.1 lukem "failed\n",
2084 1.1 lukem 0, 0, 0 );
2085 1.1 lukem return code;
2086 1.1 lukem }
2087 1.1 lukem }
2088 1.1 lukem }
2089 1.1 lukem
2090 1.1 lukem for ( i=0; lattrs[i].at; i++ ) {
2091 1.1 lukem int code;
2092 1.1 lukem
2093 1.1 lukem code = register_at( lattrs[i].at, lattrs[i].ad, 0 );
2094 1.1 lukem if ( code ) {
2095 1.1 lukem Debug( LDAP_DEBUG_ANY,
2096 1.1 lukem "accesslog_init: register_at failed\n",
2097 1.1 lukem 0, 0, 0 );
2098 1.1 lukem return -1;
2099 1.1 lukem }
2100 1.1 lukem #ifndef LDAP_DEVEL
2101 1.1 lukem (*lattrs[i].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
2102 1.1 lukem #endif
2103 1.1 lukem }
2104 1.1 lukem
2105 1.1 lukem for ( i=0; locs[i].ot; i++ ) {
2106 1.1 lukem int code;
2107 1.1 lukem
2108 1.1 lukem code = register_oc( locs[i].ot, locs[i].oc, 0 );
2109 1.1 lukem if ( code ) {
2110 1.1 lukem Debug( LDAP_DEBUG_ANY,
2111 1.1 lukem "accesslog_init: register_oc failed\n",
2112 1.1 lukem 0, 0, 0 );
2113 1.1 lukem return -1;
2114 1.1 lukem }
2115 1.1 lukem #ifndef LDAP_DEVEL
2116 1.1 lukem (*locs[i].oc)->soc_flags |= SLAP_OC_HIDE;
2117 1.1 lukem #endif
2118 1.1 lukem }
2119 1.1 lukem
2120 1.1 lukem return overlay_register(&accesslog);
2121 1.1 lukem }
2122 1.1 lukem
2123 1.1 lukem #if SLAPD_OVER_ACCESSLOG == SLAPD_MOD_DYNAMIC
2124 1.1 lukem int
2125 1.1 lukem init_module( int argc, char *argv[] )
2126 1.1 lukem {
2127 1.1 lukem return accesslog_initialize();
2128 1.1 lukem }
2129 1.1 lukem #endif
2130 1.1 lukem
2131 1.1 lukem #endif /* SLAPD_OVER_ACCESSLOG */
2132