]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/accesslog.c
Omit logpurge attr if no purge time was configured
[openldap] / servers / slapd / overlays / accesslog.c
index c0454cf20032caf170c73123af0d535b3c1d972c..6284cc364b6f3c39aba14f5e89457c570f57536c 100644 (file)
 #define LOG_OP_ALL             (LOG_OP_READS|LOG_OP_WRITES|LOG_OP_SESSION| \
        LOG_OP_EXTENDED|LOG_OP_UNKNOWN)
 
+typedef struct log_attr {
+       struct log_attr *next;
+       AttributeDescription *attr;
+} log_attr;
+
 typedef struct log_info {
        BackendDB *li_db;
        slap_mask_t li_ops;
@@ -59,8 +64,9 @@ typedef struct log_info {
        struct re_s *li_task;
        Filter *li_oldf;
        Entry *li_old;
+       log_attr *li_oldattrs;
        int li_success;
-       ldap_pvt_thread_mutex_t li_op_mutex;
+       ldap_pvt_thread_rmutex_t li_op_rmutex;
        ldap_pvt_thread_mutex_t li_log_mutex;
 } log_info;
 
@@ -71,7 +77,8 @@ enum {
        LOG_OPS,
        LOG_PURGE,
        LOG_SUCCESS,
-       LOG_OLD
+       LOG_OLD,
+       LOG_OLDATTR
 };
 
 static ConfigTable log_cfats[] = {
@@ -97,6 +104,10 @@ static ConfigTable log_cfats[] = {
                log_cf_gen, "( OLcfgOvAt:4.5 NAME 'olcAccessLogOld' "
                        "DESC 'Log old values when modifying entries matching the filter' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "logoldattr", "attrs", 2, 0, 0, ARG_MAGIC|LOG_OLDATTR,
+               log_cf_gen, "( OLcfgOvAt:4.6 NAME 'olcAccessLogOldAttr' "
+                       "DESC 'Log old values of these attributes even if unmodified' "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { NULL }
 };
 
@@ -107,7 +118,7 @@ static ConfigOCs log_cfocs[] = {
                "SUP olcOverlayConfig "
                "MUST olcAccessLogDB "
                "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ "
-                       "olcAccessLogOld ) )",
+                       "olcAccessLogOld $ olcAccessLogOldAttr ) )",
                        Cft_Overlay, log_cfats },
        { NULL }
 };
@@ -369,7 +380,7 @@ static struct {
                "DESC 'ModRDN operation' "
                "SUP auditWriteObject STRUCTURAL "
                "MUST ( reqNewRDN $ reqDeleteOldRDN ) "
-               "MAY reqNewSuperior )", &log_ocs[LOG_EN_MODRDN] },
+               "MAY ( reqNewSuperior $ reqOld ) )", &log_ocs[LOG_EN_MODRDN] },
        { "( " LOG_SCHEMA_OC ".11 NAME 'auditSearch' "
                "DESC 'Search operation' "
                "SUP auditReadObject STRUCTURAL "
@@ -594,6 +605,14 @@ log_cf_gen(ConfigArgs *c)
        case SLAP_CONFIG_EMIT:
                switch( c->type ) {
                case LOG_DB:
+                       if ( li->li_db == NULL ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "accesslog: \"logdb <suffix>\" must be specified" );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
+                                       c->log, c->msg, c->value_dn.bv_val );
+                               rc = 1;
+                               break;
+                       }
                        value_add( &c->rvalue_vals, li->li_db->be_suffix );
                        value_add( &c->rvalue_nvals, li->li_db->be_nsuffix );
                        break;
@@ -601,6 +620,10 @@ log_cf_gen(ConfigArgs *c)
                        rc = mask_to_verbs( logops, li->li_ops, &c->rvalue_vals );
                        break;
                case LOG_PURGE:
+                       if ( !li->li_age ) {
+                               rc = 1;
+                               break;
+                       }
                        agebv.bv_val = agebuf;
                        log_age_unparse( li->li_age, &agebv );
                        agebv.bv_val[agebv.bv_len] = ' ';
@@ -624,6 +647,16 @@ log_cf_gen(ConfigArgs *c)
                        else
                                rc = 1;
                        break;
+               case LOG_OLDATTR:
+                       if ( li->li_oldattrs ) {
+                               log_attr *la;
+
+                               for ( la = li->li_oldattrs; la; la=la->next )
+                                       value_add_one( &c->rvalue_vals, &la->attr->ad_cname );
+                       }
+                       else
+                               rc = 1;
+                       break;
                }
                break;
        case LDAP_MOD_DELETE:
@@ -660,6 +693,26 @@ log_cf_gen(ConfigArgs *c)
                                li->li_oldf = NULL;
                        }
                        break;
+               case LOG_OLDATTR:
+                       if ( c->valx < 0 ) {
+                               log_attr *la, *ln;
+
+                               for ( la = li->li_oldattrs; la; la = ln ) {
+                                       ln = la->next;
+                                       ch_free( la );
+                               }
+                       } else {
+                               log_attr *la = NULL, **lp;
+                               int i;
+
+                               for ( lp = &li->li_oldattrs, i=0; i < c->valx; i++ ) {
+                                       la = *lp;
+                                       lp = &la->next;
+                               }
+                               *lp = la->next;
+                               ch_free( la );
+                       }
+                       break;
                }
                break;
        default:
@@ -667,7 +720,16 @@ log_cf_gen(ConfigArgs *c)
                case LOG_DB:
                        li->li_db = select_backend( &c->value_ndn, 0, 0 );
                        if ( !li->li_db ) {
-                               sprintf( c->msg, "<%s> no matching backend found for suffix",
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "<%s> no matching backend found for suffix",
+                                       c->argv[0] );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
+                                       c->log, c->msg, c->value_dn.bv_val );
+                               rc = 1;
+                       }
+                       if ( BER_BVISEMPTY( &li->li_db->be_rootdn )) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "<%s> no rootDN was configured for suffix",
                                        c->argv[0] );
                                Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
                                        c->log, c->msg, c->value_dn.bv_val );
@@ -711,6 +773,27 @@ log_cf_gen(ConfigArgs *c)
                                sprintf( c->msg, "bad filter!" );
                                rc = 1;
                        }
+                       break;
+               case LOG_OLDATTR: {
+                       int i;
+                       AttributeDescription *ad;
+                       const char *text;
+
+                       for ( i=1; i< c->argc; i++ ) {
+                               ad = NULL;
+                               if ( slap_str2ad( c->argv[i], &ad, &text ) == LDAP_SUCCESS ) {
+                                       log_attr *la = ch_malloc( sizeof( log_attr ));
+                                       la->attr = ad;
+                                       la->next = li->li_oldattrs;
+                                       li->li_oldattrs = la;
+                               } else {
+                                       sprintf( c->msg, "%s: %s", c->argv[i], text );
+                                       rc = ARG_BAD_CONF;
+                                       break;
+                               }
+                       }
+                       }
+                       break;
                }
                break;
        }
@@ -872,7 +955,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                ldap_pvt_thread_mutex_lock( &li->li_log_mutex );
                old = li->li_old;
                li->li_old = NULL;
-               ldap_pvt_thread_mutex_unlock( &li->li_op_mutex );
+               ldap_pvt_thread_rmutex_unlock( &li->li_op_rmutex, op->o_tid );
        }
 
        if ( li->li_success && rs->sr_err != LDAP_SUCCESS )
@@ -950,10 +1033,17 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                vals = ch_malloc( (i+1) * sizeof( struct berval ));
                i = 0;
 
-               /* Zero flags on old entry */
+               /* init flags on old entry */
                if ( old ) {
-                       for ( a=old->e_attrs; a; a=a->a_next )
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               log_attr *la;
                                a->a_flags = 0;
+
+                               /* look for attrs that are always logged */
+                               for ( la=li->li_oldattrs; la; la=la->next )
+                                       if ( a->a_desc == la->attr )
+                                               a->a_flags = 1;
+                       }
                }
 
                for ( m=op->orm_modlist; m; m=m->sml_next ) {
@@ -1029,6 +1119,40 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                break;
 
        case LOG_EN_MODRDN:
+               if ( old ) {
+                       /* count all the vals */
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               log_attr *la;
+
+                               /* look for attrs that are always logged */
+                               for ( la=li->li_oldattrs; la; la=la->next ) {
+                                       if ( a->a_desc == la->attr ) {
+                                               for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
+                                                       i++;
+                                               }
+                                       }
+                               }
+                       }
+                       vals = ch_malloc( (i+1) * sizeof( struct berval ));
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               log_attr *la;
+                               for ( la=li->li_oldattrs; la; la=la->next ) {
+                                       if ( a->a_desc == la->attr ) {
+                                               for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
+                                                       accesslog_val2val( a->a_desc, b, 0, &vals[i] );
+                                               }
+                                       }
+                               }
+                       }
+                       vals[i].bv_val = NULL;
+                       vals[i].bv_len = 0;
+                       a = attr_alloc( ad_reqOld );
+                       a->a_vals = vals;
+                       a->a_nvals = vals;
+                       last_attr->a_next = a;
+               }
                attr_merge_one( e, ad_reqNewRDN, &op->orr_newrdn, &op->orr_nnewrdn );
                attr_merge_one( e, ad_reqDeleteOldRDN, op->orr_deleteoldrdn ?
                        (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv,
@@ -1184,12 +1308,10 @@ accesslog_op_mod( Operation *op, SlapReply *rs )
        log_info *li = on->on_bi.bi_private;
 
        if ( li->li_ops & LOG_OP_WRITES ) {
-               /* FIXME: this needs to be a recursive mutex to allow
-                * overlays like refint to keep working.
-                */
-               ldap_pvt_thread_mutex_lock( &li->li_op_mutex );
+               ldap_pvt_thread_rmutex_lock( &li->li_op_rmutex, op->o_tid );
                if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE ||
-                       op->o_tag == LDAP_REQ_MODIFY )) {
+                       op->o_tag == LDAP_REQ_MODIFY ||
+                       ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) {
                        int rc;
                        Entry *e;
 
@@ -1291,7 +1413,7 @@ accesslog_db_init(
        log_info *li = ch_calloc(1, sizeof(log_info));
 
        on->on_bi.bi_private = li;
-       ldap_pvt_thread_mutex_init( &li->li_op_mutex );
+       ldap_pvt_thread_rmutex_init( &li->li_op_rmutex );
        ldap_pvt_thread_mutex_init( &li->li_log_mutex );
        return 0;
 }
@@ -1305,7 +1427,7 @@ accesslog_db_destroy(
        log_info *li = on->on_bi.bi_private;
 
        ldap_pvt_thread_mutex_destroy( &li->li_log_mutex );
-       ldap_pvt_thread_mutex_destroy( &li->li_op_mutex );
+       ldap_pvt_thread_rmutex_destroy( &li->li_op_rmutex );
        free( li );
        return LDAP_SUCCESS;
 }
@@ -1325,6 +1447,13 @@ accesslog_db_open(
        int rc;
        void *thrctx;
 
+       if ( li->li_db == NULL ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "accesslog: \"logdb <suffix>\" must be specified.\n",
+                       0, 0, 0 );
+               return 1;
+       }
+
        if ( slapMode & SLAP_TOOL_MODE )
                return 0;