odlocales.c   [plain text]


/*
 *  odlocales.c
 */



#include "portable.h"
#ifdef SLAPD_OVER_ODLOCALES
#include "overlayutils.h"

#include <arpa/inet.h>
#define ODLOCALES_BACK_CONFIG 1

#include <ac/string.h>
#include <ac/ctype.h>
#include "slap.h"
#include "ldif.h"
#include "config.h"


static slap_overinst odlocales;

typedef struct odlocales_info {
	struct odlocales_info *ci_next;
	struct berval ci_dn;
	AttributeDescription *ci_ad;
} odlocales_info;

typedef struct odloc_res_s {
	struct berval *ndn;
	char *lname;
	int count;
	
} odloc_res;

static int odloc_count_attr_cb(
							   Operation *op,
							   SlapReply *rs
							   )
{
	odloc_res *uc;
	int rc = 0;
	/* because you never know */
	if(!op || !rs) return(0);
	
	/* Only search entries are interesting */
	if(rs->sr_type != REP_SEARCH) return(0);
	
	uc = op->o_callback->sc_private;
	dump_slap_attr(rs->sr_un.sru_search.r_entry->e_attrs);
	Attribute *someVal = NULL;
	AttributeDescription	*ad = NULL;
	const char	*text = NULL;
	rc = slap_str2ad( "apple-group-realname", &ad, &text );
	someVal = attr_find(rs->sr_un.sru_search.r_entry->e_attrs, ad);
        if (someVal != NULL) {
            uc->lname = someVal->a_vals->bv_val;
            uc->count++;
        }
	
	return(0);
}

static int odloc_cloud_attr_cb(
							   Operation *op,
							   SlapReply *rs
							   )
{
	odloc_res *uc;
	int rc = 0;
	/* because you never know */
	if(!op || !rs) return(0);
	
	/* Only search entries are interesting */
	if(rs->sr_type != REP_SEARCH) return(0);
	
	uc = op->o_callback->sc_private;
	dump_slap_attr(rs->sr_un.sru_search.r_entry->e_attrs);
	Attribute *someVal = NULL;
	AttributeDescription	*ad = NULL;
	const char	*text = NULL;
	rc = slap_str2ad( "apple-dns-domain", &ad, &text );
	someVal = attr_find(rs->sr_un.sru_search.r_entry->e_attrs, ad);
        if (someVal != NULL) {
            uc->lname = someVal->a_vals->bv_val;
            uc->count++;
        }
	
	return(0);
}


static char* odlocale_record_search(
						Operation *op,
						Operation *nop,
						char *key,
						struct berval *searchbase
						)
{
	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
	SlapReply nrs = { REP_RESULT };
	slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */
	odloc_res uq = { NULL, 0 };
	int rc;
	
	nop->ors_filter = str2filter(key);
	ber_str2bv(key, 0, 0, &nop->ors_filterstr);
	if (strstr(key, "(cn=locales)")){
		cb.sc_response	= (slap_response*)odloc_cloud_attr_cb;
	}else{
		cb.sc_response	= (slap_response*)odloc_count_attr_cb;
	}	
	cb.sc_private	= &uq;
	nop->o_callback	= &cb;
	nop->o_tag	= LDAP_REQ_SEARCH;
	nop->ors_scope	= LDAP_SCOPE_SUBTREE;
	nop->ors_deref	= LDAP_DEREF_NEVER;
	nop->ors_limit	= NULL;
	nop->ors_slimit	= SLAP_NO_LIMIT;
	nop->ors_tlimit	= SLAP_NO_LIMIT;
	nop->ors_attrs	= slap_anlist_all_attributes;
	nop->ors_attrsonly = 0;
	
	uq.ndn = &op->o_req_ndn;
	
	nop->o_req_dn	= *searchbase;
	nop->o_req_ndn	= *searchbase;
	nop->o_ndn = op->o_bd->be_rootndn;
	
	nop->o_bd = on->on_info->oi_origdb;
	rc = nop->o_bd->be_search(nop, &nrs);
	

	if ((rc == LDAP_SUCCESS) && (uq.count !=0)){
		return(uq.lname);
	}else{
		return NULL;
	}
	
	
}




static char* get_locales(Operation *op,
					   Operation *nop,
					   char *myip,
					   struct berval *searchbase){

	char *mySite = NULL;
	in_addr_t   y;
		int         c;
	char        ipOut[16];
	char        NetObj[100];
	char *localeName = NULL;
			
	in_addr_t x;
	inet_aton(myip, &x);
		
	for ( c=32; c > 0 && localeName == NULL; c--){
			
		const char      *attrs[2];
		y = (ntohl(x) >> (32-c)) << (32-c);
			
		unsigned int        tempAddr = htonl( y );
		unsigned char *X = (unsigned char *)&tempAddr;
			
		snprintf( ipOut, sizeof(ipOut), "%i.%i.%i.%i", (int)X[0], (int)X[1], (int)X[2], (int)X[3]);
		snprintf( NetObj, sizeof(NetObj), "(apple-locale-subnets=%s/%i)", ipOut, c );
				
		localeName = odlocale_record_search(op,nop,NetObj,searchbase);
		}

	if (localeName != NULL) {
		Debug( LDAP_DEBUG_TRACE, "found locale %s \n", localeName, 0, 0 );
		return localeName;
	}	else {
		return "DefaultLocale";
	}
		
}

static int odlocales_response( Operation *op, SlapReply *rs )
{	
	if ((rs->sr_type != REP_SEARCH) || (op->oq_search.rs_attrs == NULL) ){
		return SLAP_CB_CONTINUE;
	}
	if (strstr(op->oq_search.rs_attrs->an_name.bv_val, "netlogon") == NULL) {
			return SLAP_CB_CONTINUE;
	}
	
	char *theLocale;
	int rc = 0;
	Debug( LDAP_DEBUG_TRACE, "OD Locale search called by client %s \n", op->o_hdr->oh_conn->c_peer_name.bv_val, 0, 0 );
	Operation nop = *op;
	
	// get the baseDN
	struct berval searchbase;
	Attribute *bDN = NULL;
	AttributeDescription	*ad = NULL;
	const char	*text = NULL;
	rc = slap_str2ad( "namingContexts", &ad, &text );
	bDN = attr_find(rs->sr_un.sru_search.r_entry->e_attrs, ad);
    if(!bDN || !bDN->a_vals->bv_val)
        return SLAP_CB_CONTINUE;
    char *baseDN = bDN->a_vals->bv_val;
	
	ber_str2bv( baseDN, 0, 0, &searchbase );
	
	// Get the locale domain name from locales config record
	char *theCloud;
	theCloud = odlocale_record_search(op,&nop,"(cn=locales)",&searchbase);

	
	// get the IP of the client to search for
	char *clientIP = strtok ( op->o_hdr->oh_conn->c_peer_name.bv_val, ":=" );
	clientIP = strtok ( NULL,":=");
	
	//Look up the locale.  If no locale is found, it will return "DefaultLocale"
	theLocale = get_locales(op,&nop,clientIP,&searchbase);
	
	// build the response
	char test_entry[512];
	rs->sr_err = LDAP_SUCCESS;
	
	//add new attributes to return here...
	snprintf( test_entry, sizeof(test_entry), "dn: \nClientSiteName: %s\nDNSDomainName: %s\nDNSForestName: %s\n", theLocale, theCloud,theCloud);
	Entry *new = str2entry2( test_entry, 0 );
	rs->sr_un.sru_search.r_entry = new;
	
	//make sure we return all attributes, otherwise, it'll return none!
	rs->sr_attrs = slap_anlist_all_attributes;
	
	
	/* Default is to just fall through to the normal processing */
	return SLAP_CB_CONTINUE;
}


// currently not used
static int
odlocales_db_config(
				BackendDB	*be,
				const char	*fname,
				int		lineno,
				int		argc,
				char		**argv )
{
	
	if ( strcasecmp( argv[ 0 ], "odlocales-base" ) == 0 ) {
	Debug( LDAP_DEBUG_TRACE, "OD Locale search base configured as: %s \n", argv[ 1 ], 0, 0 );

	
		return 0;
		
	}
	
}	

static ConfigDriver	odlocales_cf;

static ConfigTable localecfg[] = {
	{ "odlocales", "enabled", 1, 1, 0,
		ARG_MAGIC, odlocales_cf,
		"( OLcfgOvAt:700.10 NAME 'olcLocalesEnabled' "
		"DESC 'Enables LDAP Ping for OD Locales' "
		"EQUALITY booleanMatch "
		"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};


static ConfigOCs localeocs[] = {
	{ "( OLcfgOvOc:700.10 "
		"NAME 'olcODLocale' "
		"DESC 'OD Locale Overlay configuration' "
		"SUP olcOverlayConfig "
		"MAY (olcLocalesEnabled) )",
		Cft_Overlay, localecfg, NULL, NULL },
	{ NULL, 0, NULL }
};


static int odlocales_cf( ConfigArgs *c )
{
	Debug( LDAP_DEBUG_TRACE, "OD Locales overlay odlocales_cf \n", 0, 0, 0 );
	slap_overinst *on = (slap_overinst *)c->bi;
	int rc = 1;
	
	//Stuff goes here :-)
	
	return rc;
}


int odlocales_initialize() {
	int rc = 0;
	Debug( LDAP_DEBUG_TRACE, "==> OD Locales overlay initialize called \n", 0, 0, 0 );
	memset( &odlocales, 0, sizeof( slap_overinst ) );
	
	odlocales.on_bi.bi_type = "odlocales";
	odlocales.on_response = odlocales_response;
	//odlocales.on_bi.bi_db_config = odlocales_db_config;
	odlocales.on_bi.bi_cf_ocs = localeocs;
	
	rc = config_register_schema( localecfg, localeocs );
	if ( rc ) {
		return rc;
	}
	
	
	return (overlay_register(&odlocales));
}

#if SLAPD_OVER_ODLOCALES == SLAPD_MOD_DYNAMIC
int
init_module( int argc, char *argv[] )
{
	Debug( LDAP_DEBUG_TRACE, "OD Locales overlay init_module \n", 0, 0, 0 );
	return odlocales_initialize();
}
#endif
#endif /* SLAPD_OVER_ODLOCALES */