joel reed wrote:
Please find attached version 0.2 of the uidnumber overlay I posted previously (http://www.openldap.org/lists/openldap-software/200806/msg00029.html).

Darn it! Forgot to include the file!

jr
/**
 * uidnumber.c 
 *
 * Copyright (C) 2008 Joel W. Reed
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * http://www.OpenLDAP.org/license.html.
 *
 * SEE LICENSE FOR MORE INFORMATION
 *
 * Author:      Joel W. Reed
 * Email:               [EMAIL PROTECTED]
 * Version: 0.2
 * Updated: 06.29.2008
 * 
 * uidnumber
 *
 * This is an OpenLDAP overlay that intercepts ADD requests for posixAccount 
type
 * entries that do not have a uidNumber. When such ADD requests are found, 
 * the overlay adds a uidNumber attribute with the next available uidNumber.
 */

#include "portable.h" 
#include "slap.h"
#include "config.h"

static int uidnumber_search_cb( Operation *op, SlapReply *rs );
static unsigned long uidnumber_next_available( Operation *op );

static slap_overinst uidnumber;
static ObjectClass *oc_posix_account;
static char *uid_attr_name = "uidNumber";

typedef struct uidnumber_data {
        ldap_pvt_thread_mutex_t mutex;
  unsigned long max_uid_number;
} uidnumber_data;

/**
 *      The meat of the overlay. Look for posixAccount adds with no uidNumber, 
and 
 *      add in the next available uidNumber as needed.
 */
static int uidnumber_add( Operation *op, SlapReply *rs )
{
        Entry* to_add = NULL;
        AttributeDescription* ad = NULL;
        Attribute* attr = NULL;
        char uidstr[64];
        struct berval uidbv = BER_BVNULL;
  unsigned long uid;
        const char* text;
        int rc;

        to_add = op->oq_add.rs_e;

        /* if the user doesn't have access, fall through to the normal ADD */
        if(!access_allowed( op, to_add, slap_schema.si_ad_entry,
                                                                                
        NULL, ACL_WRITE, NULL )) {
                return SLAP_CB_CONTINUE;
        }
                
        /* we only care object posixAccount entries */
        if(!is_entry_objectclass( (to_add), oc_posix_account, 0) ) {
                Debug(LDAP_DEBUG_TRACE, "%s: entry %s is not objectclass 
posixAccount\n",
                                        uidnumber.on_bi.bi_type, 
to_add->e_nname.bv_val, 0);
                return SLAP_CB_CONTINUE;
        }

        /* if already has a uidNumber, no further processing required */
        for ( attr = to_add->e_attrs; attr; attr = attr->a_next )
                {
                        if (!strcmp( attr->a_desc->ad_cname.bv_val, 
uid_attr_name )) {
                                Debug(LDAP_DEBUG_TRACE, "%s: entry %s already 
has a uidNumber\n",
                                                        
uidnumber.on_bi.bi_type, to_add->e_nname.bv_val, 0);
                                return SLAP_CB_CONTINUE;
                        }
                }

        uid = uidnumber_next_available(op);

        rc = slap_str2ad( uid_attr_name, &ad, &text );
        if(rc != LDAP_SUCCESS) {
                Debug( LDAP_DEBUG_ANY, "%s: failed to add uidNumber attribute 
to entry\n",
                                         uidnumber.on_bi.bi_type, 0, 0 );
                return SLAP_CB_CONTINUE;
        }

        sprintf( uidstr, "%lu", uid );
        ber_str2bv( uidstr, 0, 0, &uidbv );
        attr_merge_one( to_add, ad, &uidbv, 0 );

        Debug( LDAP_DEBUG_ANY, "%s: added uidNumber %s to entry\n",
                                 uidnumber.on_bi.bi_type, uidstr, 0 );

        return SLAP_CB_CONTINUE;
}

static unsigned long uidnumber_next_available(Operation *op)
{
        slap_overinst* on = (slap_overinst *)op->o_bd->bd_info;
        uidnumber_data* ad = on->on_bi.bi_private;

        Operation nop = *op;
        SlapReply nrs = { REP_RESULT };
        Filter* filter = NULL;
        slap_callback cb = { NULL, uidnumber_search_cb, NULL, ad };
        struct berval fstr = BER_BVNULL;
        struct berval rootstr = BER_BVNULL;
  int rc;

        /* if we already know the max uid, don't bother searching the tree */
        if(ad->max_uid_number == 0) {

                nop.o_callback = &cb;
                op->o_bd->bd_info = (BackendInfo *) on->on_info;
                nop.o_tag = LDAP_REQ_SEARCH;
                nop.o_ctrls = NULL;
                
                filter = str2filter( "(uidNumber=*)" );
                filter2bv( filter, &fstr );

                nop.ors_scope = LDAP_SCOPE_SUBTREE;
                nop.ors_deref = LDAP_DEREF_NEVER;
                nop.ors_slimit = -1;//SLAP_NO_LIMIT;
                nop.ors_tlimit = -1;//SLAP_NO_LIMIT;
                nop.ors_attrsonly = 1;
                nop.ors_attrs = slap_anlist_no_attrs;
                nop.ors_filter = filter;
                nop.ors_filterstr = fstr;

                memset( &nrs, 0, sizeof(nrs) );
                nrs.sr_type = REP_RESULT;
                nrs.sr_err = LDAP_SUCCESS;
                nrs.sr_entry = NULL;
                nrs.sr_flags |= REP_ENTRY_MUSTBEFREED;
                nrs.sr_text = NULL;

                nop.o_req_dn = rootstr;
                nop.o_req_ndn = rootstr;

                if(nop.o_bd->be_search) {
                        rc = nop.o_bd->be_search( &nop, &nrs );
                        Debug( LDAP_DEBUG_TRACE, "%s: searched for entries with 
uidNumber attribute\n",
                                                 uidnumber.on_bi.bi_type,0,0 );
                }
                else {
                        Debug( LDAP_DEBUG_ANY, "%s: backend missing search 
function\n",
                                                 uidnumber.on_bi.bi_type,0,0 );
                }

                if(filter)
                        filter_free( filter );
                if(fstr.bv_val)
                        ch_free( fstr.bv_val );
        }

        return ++(ad->max_uid_number);
}

static int uidnumber_search_cb( Operation *op, SlapReply *rs )
{
        uidnumber_data* ad = op->o_callback->sc_private;
        Entry *entry = NULL;

        if( rs->sr_type != REP_SEARCH ) return 0;
                                
        if( rs->sr_entry ) {
                Debug( LDAP_DEBUG_TRACE, "%s: dn found: %s\n",
                                         uidnumber.on_bi.bi_type, 
rs->sr_entry->e_nname.bv_val, 0 );

                entry = rs->sr_entry;

                Attribute *attr = NULL;
                for (attr = entry->e_attrs; attr; attr = attr->a_next)
                        {
                                if(!strcmp( attr->a_desc->ad_cname.bv_val, 
uid_attr_name ))     {
                                        if(attr->a_numvals > 0 ) {
                                                unsigned long tmp = strtoul( 
attr->a_vals[0].bv_val, 0, 0 );
                                                Debug( LDAP_DEBUG_ANY, "%s: 
uidNumber found: %lu\n",
                                                                         
uidnumber.on_bi.bi_type, tmp, 0 );
                                                if( tmp >= ad->max_uid_number ) 
ad->max_uid_number = tmp;
                                        }
                                }
                        }
        }

        return 0;
}

static int uidnumber_db_init(BackendDB *be,     ConfigReply *cr)
{
        slap_overinst *on = (slap_overinst *)be->bd_info;
        uidnumber_data *ad = ch_calloc(1, sizeof(uidnumber_data));

        on->on_bi.bi_private = ad;
        ldap_pvt_thread_mutex_init( &ad->mutex );
  ad->max_uid_number = 0;

        return 0;
}

static int uidnumber_db_destroy(BackendDB *be, ConfigReply *cr)
{
        slap_overinst *on = (slap_overinst *)be->bd_info;
        uidnumber_data *ad = on->on_bi.bi_private;

        ldap_pvt_thread_mutex_destroy( &ad->mutex );
        free( ad );

        return 0;
}

int uidnumber_init() 
{
        uidnumber.on_bi.bi_type = "uidnumber";
        uidnumber.on_bi.bi_op_add = uidnumber_add;
        uidnumber.on_bi.bi_db_init = uidnumber_db_init;
        uidnumber.on_bi.bi_db_destroy = uidnumber_db_destroy;

        oc_posix_account = oc_find( "posixAccount" );
        if(oc_posix_account == NULL) {
                Debug( LDAP_DEBUG_ANY, "%s: unable to find default ObjectClass 
\"posixAccount\".\n",
                                         uidnumber.on_bi.bi_type, 0, 0 );
                return -1;
        }

        return ( overlay_register(&uidnumber) );
}

int init_module( int argc, char *argv[] ) 
{
        return uidnumber_init();
}

Reply via email to