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: joelwreed@gmail.com * 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(); }