[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: automatic uidnumber overlay version 0.2
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();
}