1 /* auditlog.c - log modifications for audit/history purposes */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/overlays/auditlog.c,v 1.7.2.7 2008/04/14 21:18:48 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2005-2008 The OpenLDAP Foundation.
6 * Portions copyright 2004-2005 Symas Corporation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by Symas Corp. for inclusion in
19 * OpenLDAP Software. This work was sponsored by Hewlett-Packard.
24 #ifdef SLAPD_OVER_AUDITLOG
28 #include <ac/string.h>
35 typedef struct auditlog_data
{
36 ldap_pvt_thread_mutex_t ad_mutex
;
40 static ConfigTable auditlogcfg
[] = {
41 { "auditlog", "filename", 2, 2, 0,
42 ARG_STRING
|ARG_OFFSET
,
43 (void *)offsetof(auditlog_data
, ad_logfile
),
44 "( OLcfgOvAt:15.1 NAME 'olcAuditlogFile' "
45 "DESC 'Filename for auditlogging' "
46 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
47 { NULL
, NULL
, 0, 0, 0, ARG_IGNORED
}
50 static ConfigOCs auditlogocs
[] = {
52 "NAME 'olcAuditlogConfig' "
53 "DESC 'Auditlog configuration' "
54 "SUP olcOverlayConfig "
55 "MAY ( olcAuditlogFile ) )",
56 Cft_Overlay
, auditlogcfg
},
60 static int fprint_ldif(FILE *f
, char *name
, char *val
, ber_len_t len
) {
62 if((s
= ldif_put(LDIF_PUT_VALUE
, name
, val
, len
)) == NULL
)
69 static int auditlog_response(Operation
*op
, SlapReply
*rs
) {
70 slap_overinst
*on
= (slap_overinst
*)op
->o_bd
->bd_info
;
71 auditlog_data
*ad
= on
->on_bi
.bi_private
;
75 struct berval
*b
, *who
= NULL
;
80 if ( rs
->sr_err
!= LDAP_SUCCESS
) return SLAP_CB_CONTINUE
;
82 if ( !ad
->ad_logfile
) return SLAP_CB_CONTINUE
;
85 ** add or modify: use modifiersName if present
89 case LDAP_REQ_MODRDN
: what
= "modrdn"; break;
90 case LDAP_REQ_DELETE
: what
= "delete"; break;
93 for(a
= op
->ora_e
->e_attrs
; a
; a
= a
->a_next
)
94 if( a
->a_desc
== slap_schema
.si_ad_modifiersName
) {
101 for(m
= op
->orm_modlist
; m
; m
= m
->sml_next
)
102 if( m
->sml_desc
== slap_schema
.si_ad_modifiersName
&&
103 ( m
->sml_op
== LDAP_MOD_ADD
||
104 m
->sml_op
== LDAP_MOD_REPLACE
)) {
105 who
= &m
->sml_values
[0];
110 return SLAP_CB_CONTINUE
;
113 suffix
= op
->o_bd
->be_suffix
[0].bv_len
? op
->o_bd
->be_suffix
[0].bv_val
:
117 ** note: this means requestor's dn when modifiersName is null
122 ldap_pvt_thread_mutex_lock(&ad
->ad_mutex
);
123 if((f
= fopen(ad
->ad_logfile
, "a")) == NULL
) {
124 ldap_pvt_thread_mutex_unlock(&ad
->ad_mutex
);
125 return SLAP_CB_CONTINUE
;
128 stamp
= slap_get_time();
129 fprintf(f
, "# %s %ld %s%s%s\n",
130 what
, (long)stamp
, suffix
, who
? " " : "", who
? who
->bv_val
: "");
132 if ( !BER_BVISEMPTY( &op
->o_conn
->c_dn
) &&
133 (!who
|| !dn_match( who
, &op
->o_conn
->c_dn
)))
134 fprintf(f
, "# realdn: %s\n", op
->o_conn
->c_dn
.bv_val
);
136 fprintf(f
, "dn: %s\nchangetype: %s\n",
137 op
->o_req_dn
.bv_val
, what
);
141 for(a
= op
->ora_e
->e_attrs
; a
; a
= a
->a_next
)
142 if((b
= a
->a_vals
) != NULL
)
143 for(i
= 0; b
[i
].bv_val
; i
++)
144 fprint_ldif(f
, a
->a_desc
->ad_cname
.bv_val
, b
[i
].bv_val
, b
[i
].bv_len
);
147 case LDAP_REQ_MODIFY
:
148 for(m
= op
->orm_modlist
; m
; m
= m
->sml_next
) {
149 switch(m
->sml_op
& LDAP_MOD_OP
) {
150 case LDAP_MOD_ADD
: what
= "add"; break;
151 case LDAP_MOD_REPLACE
: what
= "replace"; break;
152 case LDAP_MOD_DELETE
: what
= "delete"; break;
153 case LDAP_MOD_INCREMENT
: what
= "increment"; break;
155 fprintf(f
, "# MOD_TYPE_UNKNOWN:%02x\n", m
->sml_op
& LDAP_MOD_OP
);
158 fprintf(f
, "%s: %s\n", what
, m
->sml_desc
->ad_cname
.bv_val
);
159 if((b
= m
->sml_values
) != NULL
)
160 for(i
= 0; b
[i
].bv_val
; i
++)
161 fprint_ldif(f
, m
->sml_desc
->ad_cname
.bv_val
, b
[i
].bv_val
, b
[i
].bv_len
);
166 case LDAP_REQ_MODRDN
:
167 fprintf(f
, "newrdn: %s\ndeleteoldrdn: %s\n",
168 op
->orr_newrdn
.bv_val
, op
->orr_deleteoldrdn
? "1" : "0");
169 if(op
->orr_newSup
) fprintf(f
, "newsuperior: %s\n", op
->orr_newSup
->bv_val
);
172 case LDAP_REQ_DELETE
:
173 /* nothing else needed */
177 fprintf(f
, "# end %s %ld\n\n", what
, (long)stamp
);
180 ldap_pvt_thread_mutex_unlock(&ad
->ad_mutex
);
181 return SLAP_CB_CONTINUE
;
184 static slap_overinst auditlog
;
192 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
193 auditlog_data
*ad
= ch_calloc(1, sizeof(auditlog_data
));
195 on
->on_bi
.bi_private
= ad
;
196 ldap_pvt_thread_mutex_init( &ad
->ad_mutex
);
206 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
207 auditlog_data
*ad
= on
->on_bi
.bi_private
;
209 free( ad
->ad_logfile
);
210 ad
->ad_logfile
= NULL
;
220 slap_overinst
*on
= (slap_overinst
*)be
->bd_info
;
221 auditlog_data
*ad
= on
->on_bi
.bi_private
;
223 ldap_pvt_thread_mutex_destroy( &ad
->ad_mutex
);
228 int auditlog_initialize() {
231 auditlog
.on_bi
.bi_type
= "auditlog";
232 auditlog
.on_bi
.bi_db_init
= auditlog_db_init
;
233 auditlog
.on_bi
.bi_db_close
= auditlog_db_close
;
234 auditlog
.on_bi
.bi_db_destroy
= auditlog_db_destroy
;
235 auditlog
.on_response
= auditlog_response
;
237 auditlog
.on_bi
.bi_cf_ocs
= auditlogocs
;
238 rc
= config_register_schema( auditlogcfg
, auditlogocs
);
241 return overlay_register(&auditlog
);
244 #if SLAPD_OVER_AUDITLOG == SLAPD_MOD_DYNAMIC && defined(PIC)
246 init_module( int argc
, char *argv
[] )
248 return auditlog_initialize();
252 #endif /* SLAPD_OVER_AUDITLOG */