Back to index

openldap  2.4.31
auditlog.c
Go to the documentation of this file.
00001 /* auditlog.c - log modifications for audit/history purposes */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2005-2012 The OpenLDAP Foundation.
00006  * Portions copyright 2004-2005 Symas Corporation.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Symas Corp. for inclusion in
00019  * OpenLDAP Software.  This work was sponsored by Hewlett-Packard.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #ifdef SLAPD_OVER_AUDITLOG
00025 
00026 #include <stdio.h>
00027 
00028 #include <ac/string.h>
00029 #include <ac/ctype.h>
00030 
00031 #include "slap.h"
00032 #include "config.h"
00033 #include "ldif.h"
00034 
00035 typedef struct auditlog_data {
00036        ldap_pvt_thread_mutex_t ad_mutex;
00037        char *ad_logfile;
00038 } auditlog_data;
00039 
00040 static ConfigTable auditlogcfg[] = {
00041        { "auditlog", "filename", 2, 2, 0,
00042          ARG_STRING|ARG_OFFSET,
00043          (void *)offsetof(auditlog_data, ad_logfile),
00044          "( OLcfgOvAt:15.1 NAME 'olcAuditlogFile' "
00045          "DESC 'Filename for auditlogging' "
00046          "SYNTAX OMsDirectoryString )", NULL, NULL },
00047        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
00048 };
00049 
00050 static ConfigOCs auditlogocs[] = {
00051        { "( OLcfgOvOc:15.1 "
00052          "NAME 'olcAuditlogConfig' "
00053          "DESC 'Auditlog configuration' "
00054          "SUP olcOverlayConfig "
00055          "MAY ( olcAuditlogFile ) )",
00056          Cft_Overlay, auditlogcfg },
00057        { NULL, 0, NULL }
00058 };
00059 
00060 static int fprint_ldif(FILE *f, char *name, char *val, ber_len_t len) {
00061        char *s;
00062        if((s = ldif_put(LDIF_PUT_VALUE, name, val, len)) == NULL)
00063               return(-1);
00064        fputs(s, f);
00065        ber_memfree(s);
00066        return(0);
00067 }
00068 
00069 static int auditlog_response(Operation *op, SlapReply *rs) {
00070        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
00071        auditlog_data *ad = on->on_bi.bi_private;
00072        FILE *f;
00073        Attribute *a;
00074        Modifications *m;
00075        struct berval *b, *who = NULL, peername;
00076        char *what, *whatm, *suffix;
00077        time_t stamp;
00078        int i;
00079 
00080        if ( rs->sr_err != LDAP_SUCCESS ) return SLAP_CB_CONTINUE;
00081 
00082        if ( !ad->ad_logfile ) return SLAP_CB_CONTINUE;
00083 
00084 /*
00085 ** add or modify: use modifiersName if present
00086 **
00087 */
00088        switch(op->o_tag) {
00089               case LDAP_REQ_MODRDN:       what = "modrdn";     break;
00090               case LDAP_REQ_DELETE:       what = "delete";     break;
00091               case LDAP_REQ_ADD:
00092                      what = "add";
00093                      for(a = op->ora_e->e_attrs; a; a = a->a_next)
00094                             if( a->a_desc == slap_schema.si_ad_modifiersName ) {
00095                                    who = &a->a_vals[0];
00096                                    break;
00097                             }
00098                      break;
00099               case LDAP_REQ_MODIFY:
00100                      what = "modify";
00101                      for(m = op->orm_modlist; m; m = m->sml_next)
00102                             if( m->sml_desc == slap_schema.si_ad_modifiersName &&
00103                                    ( m->sml_op == LDAP_MOD_ADD ||
00104                                    m->sml_op == LDAP_MOD_REPLACE )) {
00105                                    who = &m->sml_values[0];
00106                                    break;
00107                             }
00108                      break;
00109               default:
00110                      return SLAP_CB_CONTINUE;
00111        }
00112 
00113        suffix = op->o_bd->be_suffix[0].bv_len ? op->o_bd->be_suffix[0].bv_val :
00114               "global";
00115 
00116 /*
00117 ** note: this means requestor's dn when modifiersName is null
00118 */
00119        if ( !who )
00120               who = &op->o_dn;
00121 
00122        peername = op->o_conn->c_peer_name;
00123        ldap_pvt_thread_mutex_lock(&ad->ad_mutex);
00124        if((f = fopen(ad->ad_logfile, "a")) == NULL) {
00125               ldap_pvt_thread_mutex_unlock(&ad->ad_mutex);
00126               return SLAP_CB_CONTINUE;
00127        }
00128 
00129        stamp = slap_get_time();
00130        fprintf(f, "# %s %ld %s%s%s %s conn=%ld\n",
00131               what, (long)stamp, suffix, who ? " " : "", who ? who->bv_val : "",
00132               peername.bv_val ? peername.bv_val: "", op->o_conn->c_connid);
00133 
00134        if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) &&
00135               (!who || !dn_match( who, &op->o_conn->c_dn )))
00136               fprintf(f, "# realdn: %s\n", op->o_conn->c_dn.bv_val );
00137 
00138        fprintf(f, "dn: %s\nchangetype: %s\n",
00139               op->o_req_dn.bv_val, what);
00140 
00141        switch(op->o_tag) {
00142          case LDAP_REQ_ADD:
00143               for(a = op->ora_e->e_attrs; a; a = a->a_next)
00144                 if((b = a->a_vals) != NULL)
00145                      for(i = 0; b[i].bv_val; i++)
00146                             fprint_ldif(f, a->a_desc->ad_cname.bv_val, b[i].bv_val, b[i].bv_len);
00147               break;
00148 
00149          case LDAP_REQ_MODIFY:
00150               for(m = op->orm_modlist; m; m = m->sml_next) {
00151                      switch(m->sml_op & LDAP_MOD_OP) {
00152                             case LDAP_MOD_ADD:    whatm = "add";             break;
00153                             case LDAP_MOD_REPLACE:       whatm = "replace";  break;
00154                             case LDAP_MOD_DELETE:        whatm = "delete";   break;
00155                             case LDAP_MOD_INCREMENT: whatm = "increment";    break;
00156                             default:
00157                                    fprintf(f, "# MOD_TYPE_UNKNOWN:%02x\n", m->sml_op & LDAP_MOD_OP);
00158                                    continue;
00159                      }
00160                      fprintf(f, "%s: %s\n", whatm, m->sml_desc->ad_cname.bv_val);
00161                      if((b = m->sml_values) != NULL)
00162                        for(i = 0; b[i].bv_val; i++)
00163                             fprint_ldif(f, m->sml_desc->ad_cname.bv_val, b[i].bv_val, b[i].bv_len);
00164                      fprintf(f, "-\n");
00165               }
00166               break;
00167 
00168          case LDAP_REQ_MODRDN:
00169               fprintf(f, "newrdn: %s\ndeleteoldrdn: %s\n",
00170                      op->orr_newrdn.bv_val, op->orr_deleteoldrdn ? "1" : "0");
00171               if(op->orr_newSup) fprintf(f, "newsuperior: %s\n", op->orr_newSup->bv_val);
00172               break;
00173 
00174          case LDAP_REQ_DELETE:
00175               /* nothing else needed */
00176               break;
00177        }
00178 
00179        fprintf(f, "# end %s %ld\n\n", what, (long)stamp);
00180 
00181        fclose(f);
00182        ldap_pvt_thread_mutex_unlock(&ad->ad_mutex);
00183        return SLAP_CB_CONTINUE;
00184 }
00185 
00186 static slap_overinst auditlog;
00187 
00188 static int
00189 auditlog_db_init(
00190        BackendDB *be,
00191        ConfigReply *cr
00192 )
00193 {
00194        slap_overinst *on = (slap_overinst *)be->bd_info;
00195        auditlog_data *ad = ch_calloc(1, sizeof(auditlog_data));
00196 
00197        on->on_bi.bi_private = ad;
00198        ldap_pvt_thread_mutex_init( &ad->ad_mutex );
00199        return 0;
00200 }
00201 
00202 static int
00203 auditlog_db_close(
00204        BackendDB *be,
00205        ConfigReply *cr
00206 )
00207 {
00208        slap_overinst *on = (slap_overinst *)be->bd_info;
00209        auditlog_data *ad = on->on_bi.bi_private;
00210 
00211        free( ad->ad_logfile );
00212        ad->ad_logfile = NULL;
00213        return 0;
00214 }
00215 
00216 static int
00217 auditlog_db_destroy(
00218        BackendDB *be,
00219        ConfigReply *cr
00220 )
00221 {
00222        slap_overinst *on = (slap_overinst *)be->bd_info;
00223        auditlog_data *ad = on->on_bi.bi_private;
00224 
00225        ldap_pvt_thread_mutex_destroy( &ad->ad_mutex );
00226        free( ad );
00227        return 0;
00228 }
00229 
00230 int auditlog_initialize() {
00231        int rc;
00232 
00233        auditlog.on_bi.bi_type = "auditlog";
00234        auditlog.on_bi.bi_db_init = auditlog_db_init;
00235        auditlog.on_bi.bi_db_close = auditlog_db_close;
00236        auditlog.on_bi.bi_db_destroy = auditlog_db_destroy;
00237        auditlog.on_response = auditlog_response;
00238 
00239        auditlog.on_bi.bi_cf_ocs = auditlogocs;
00240        rc = config_register_schema( auditlogcfg, auditlogocs );
00241        if ( rc ) return rc;
00242 
00243        return overlay_register(&auditlog);
00244 }
00245 
00246 #if SLAPD_OVER_AUDITLOG == SLAPD_MOD_DYNAMIC && defined(PIC)
00247 int
00248 init_module( int argc, char *argv[] )
00249 {
00250        return auditlog_initialize();
00251 }
00252 #endif
00253 
00254 #endif /* SLAPD_OVER_AUDITLOG */