1/*
2 *  odlocales.c
3 */
4
5
6
7#include "portable.h"
8#ifdef SLAPD_OVER_ODLOCALES
9#include "overlayutils.h"
10
11#include <arpa/inet.h>
12#define ODLOCALES_BACK_CONFIG 1
13
14#include <ac/string.h>
15#include <ac/ctype.h>
16#include "slap.h"
17#include "ldif.h"
18#include "config.h"
19
20static const char* defaultLocaleName = "DefaultLocale";
21
22
23static slap_overinst odlocales;
24
25typedef struct odlocales_info {
26	struct odlocales_info *ci_next;
27	struct berval ci_dn;
28	AttributeDescription *ci_ad;
29} odlocales_info;
30
31typedef struct odloc_res_s {
32	struct berval *ndn;
33	char *lname;
34	int count;
35
36} odloc_res;
37
38static int odloc_count_attr_cb(
39							   Operation *op,
40							   SlapReply *rs
41							   )
42{
43	odloc_res *uc;
44	int rc = 0;
45	/* because you never know */
46	if(!op || !rs) return(0);
47
48	/* Only search entries are interesting */
49	if(rs->sr_type != REP_SEARCH) return(0);
50
51	uc = op->o_callback->sc_private;
52	dump_slap_attr(rs->sr_un.sru_search.r_entry->e_attrs);
53	Attribute *someVal = NULL;
54	AttributeDescription	*ad = NULL;
55	const char	*text = NULL;
56	rc = slap_str2ad( "apple-group-realname", &ad, &text );
57	someVal = attr_find(rs->sr_un.sru_search.r_entry->e_attrs, ad);
58    if (someVal != NULL) {
59        uc->lname = someVal->a_vals->bv_val;
60        uc->count++;
61    }
62
63	return(0);
64}
65
66static int odloc_cloud_attr_cb(
67							   Operation *op,
68							   SlapReply *rs
69							   )
70{
71	odloc_res *uc;
72	int rc = 0;
73	/* because you never know */
74	if(!op || !rs) return(0);
75
76	/* Only search entries are interesting */
77	if(rs->sr_type != REP_SEARCH) return(0);
78
79	uc = op->o_callback->sc_private;
80	dump_slap_attr(rs->sr_un.sru_search.r_entry->e_attrs);
81	Attribute *someVal = NULL;
82	AttributeDescription	*ad = NULL;
83	const char	*text = NULL;
84	rc = slap_str2ad( "apple-dns-domain", &ad, &text );
85	someVal = attr_find(rs->sr_un.sru_search.r_entry->e_attrs, ad);
86    if (someVal != NULL) {
87        uc->lname = someVal->a_vals->bv_val;
88        uc->count++;
89    }
90
91	return(0);
92}
93
94
95static char* odlocale_record_search(
96                                    Operation *op,
97                                    char *key,
98                                    struct berval *searchbase
99                                    )
100{
101	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
102	SlapReply nrs = { REP_RESULT };
103	slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */
104	odloc_res uq = { NULL, 0 };
105	int rc;
106    Operation *nop = NULL;
107    OperationBuffer opbuf = {0};
108
109    memset(&opbuf, 0, sizeof(opbuf));
110	nop = (Operation*)&opbuf;
111	nop->o_hdr = &opbuf.ob_hdr;
112	nop->o_controls = opbuf.ob_controls;
113	operation_fake_init(op->o_conn, (Operation*)&opbuf, ldap_pvt_thread_pool_context(), 0);
114	nop = &opbuf.ob_op;
115	nop->o_dn = nop->o_ndn = op->o_bd->be_rootndn;
116
117    nop->ors_filter = str2filter(key);
118	ber_str2bv(key, 0, 0, &nop->ors_filterstr);
119	if (strstr(key, "(cn=locales)")){
120		cb.sc_response	= (slap_response*)odloc_cloud_attr_cb;
121	}else{
122		cb.sc_response	= (slap_response*)odloc_count_attr_cb;
123	}
124	cb.sc_private	= &uq;
125
126	nop->o_callback	= &cb;
127	nop->o_tag	= LDAP_REQ_SEARCH;
128	nop->ors_scope	= LDAP_SCOPE_SUBTREE;
129	nop->ors_deref	= LDAP_DEREF_NEVER;
130	nop->ors_limit	= NULL;
131	nop->ors_slimit	= SLAP_NO_LIMIT;
132	nop->ors_tlimit	= SLAP_NO_LIMIT;
133	nop->ors_attrs	= slap_anlist_all_attributes;
134	nop->ors_attrsonly = 0;
135
136	uq.ndn = &op->o_req_ndn;
137
138	nop->o_req_dn	= *searchbase;
139	nop->o_req_ndn	= *searchbase;
140
141	nop->o_bd = on->on_info->oi_origdb;
142	rc = nop->o_bd->be_search(nop, &nrs);
143	if(nop->ors_filter)
144        filter_free( nop->ors_filter );
145
146	if ((rc == LDAP_SUCCESS) && (uq.count !=0)){
147		return(uq.lname);
148	}else{
149		return NULL;
150	}
151
152
153}
154
155
156
157
158static char* get_locales(Operation *op,
159                         char *myip,
160                         struct berval *searchbase){
161
162	char *mySite = NULL;
163	in_addr_t   y;
164    int         c;
165	char        ipOut[16];
166	char        NetObj[100];
167	char *localeName = NULL;
168
169	in_addr_t x;
170	inet_aton(myip, &x);
171
172	for ( c=32; c > 0 && localeName == NULL; c--){
173
174		const char      *attrs[2];
175		y = (ntohl(x) >> (32-c)) << (32-c);
176
177		unsigned int        tempAddr = htonl( y );
178		unsigned char *X = (unsigned char *)&tempAddr;
179
180		snprintf( ipOut, sizeof(ipOut), "%i.%i.%i.%i", (int)X[0], (int)X[1], (int)X[2], (int)X[3]);
181		snprintf( NetObj, sizeof(NetObj), "(apple-locale-subnets=%s/%i)", ipOut, c );
182
183		localeName = odlocale_record_search(op,NetObj,searchbase);
184	}
185
186	if (localeName != NULL) {
187		Debug( LDAP_DEBUG_TRACE, "found locale %s \n", localeName, 0, 0 );
188		return localeName;
189	} else {
190		return defaultLocaleName;
191	}
192
193}
194
195static int odlocales_response( Operation *op, SlapReply *rs )
196{
197	if ((rs->sr_type != REP_SEARCH) || (op->oq_search.rs_attrs == NULL) ){
198		return SLAP_CB_CONTINUE;
199	}
200	if (strstr(op->oq_search.rs_attrs->an_name.bv_val, "netlogon") == NULL) {
201        return SLAP_CB_CONTINUE;
202	}
203
204	char *theLocale;
205	int rc = 0;
206	Debug( LDAP_DEBUG_TRACE, "OD Locale search called by client %s \n", op->o_hdr->oh_conn->c_peer_name.bv_val, 0, 0 );
207
208	// get the baseDN
209	struct berval searchbase;
210	Attribute *bDN = NULL;
211	AttributeDescription	*ad = NULL;
212	const char	*text = NULL;
213	rc = slap_str2ad( "namingContexts", &ad, &text );
214	bDN = attr_find(rs->sr_un.sru_search.r_entry->e_attrs, ad);
215    if(!bDN || !bDN->a_vals->bv_val) {
216        return SLAP_CB_CONTINUE;
217    }
218
219    char *baseDN = bDN->a_vals->bv_val;
220
221	ber_str2bv( baseDN, 0, 0, &searchbase );
222
223	// Get the locale domain name from locales config record
224	char *theCloud;
225	theCloud = odlocale_record_search(op,"(cn=locales)",&searchbase);
226
227
228	// get the IP of the client to search for
229	char *clientIP = strtok ( op->o_hdr->oh_conn->c_peer_name.bv_val, ":=" );
230	clientIP = strtok ( NULL,":=");
231
232	//Look up the locale.  If no locale is found, it will return "DefaultLocale"
233	theLocale = get_locales(op,clientIP,&searchbase);
234
235	// build the response
236
237	// If the locale is the default locale, just return that.  If it's
238	// something other than the default, return both that locale and the
239	// default locale.
240    char* entry = NULL;
241    if (strncmp(theLocale, defaultLocaleName, strlen(defaultLocaleName)) == 0) {
242        asprintf(&entry, "dn: \nClientSiteName: %s\nDNSDomainName: %s\nDNSForestName: %s\n", theLocale, theCloud,theCloud);
243    }
244    else {
245        asprintf(&entry, "dn: \nClientSiteName: %s\nClientSiteName: %s\nDNSDomainName: %s\nDNSForestName: %s\n", theLocale, defaultLocaleName, theCloud,theCloud);
246    }
247
248    if (entry) {
249        rs->sr_err = LDAP_SUCCESS;
250        rs->sr_un.sru_search.r_entry = str2entry2(entry, 0);
251        free(entry);
252        entry = NULL;
253    }
254
255	//make sure we return all attributes, otherwise, it'll return none!
256	rs->sr_attrs = slap_anlist_all_attributes;
257
258
259	/* Default is to just fall through to the normal processing */
260	return SLAP_CB_CONTINUE;
261}
262
263
264// currently not used
265static int
266odlocales_db_config(
267                    BackendDB	*be,
268                    const char	*fname,
269                    int		lineno,
270                    int		argc,
271                    char		**argv )
272{
273
274	if ( strcasecmp( argv[ 0 ], "odlocales-base" ) == 0 ) {
275        Debug( LDAP_DEBUG_TRACE, "OD Locale search base configured as: %s \n", argv[ 1 ], 0, 0 );
276
277
278		return 0;
279
280	}
281
282}
283
284static ConfigDriver	odlocales_cf;
285
286static ConfigTable localecfg[] = {
287	{ "odlocales", "enabled", 1, 1, 0,
288		ARG_MAGIC, odlocales_cf,
289		"( OLcfgOvAt:700.10 NAME 'olcLocalesEnabled' "
290		"DESC 'Enables LDAP Ping for OD Locales' "
291		"EQUALITY booleanMatch "
292		"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
293	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
294};
295
296
297static ConfigOCs localeocs[] = {
298	{ "( OLcfgOvOc:700.10 "
299		"NAME 'olcODLocale' "
300		"DESC 'OD Locale Overlay configuration' "
301		"SUP olcOverlayConfig "
302		"MAY (olcLocalesEnabled) )",
303		Cft_Overlay, localecfg, NULL, NULL },
304	{ NULL, 0, NULL }
305};
306
307
308static int odlocales_cf( ConfigArgs *c )
309{
310	Debug( LDAP_DEBUG_TRACE, "OD Locales overlay odlocales_cf \n", 0, 0, 0 );
311	slap_overinst *on = (slap_overinst *)c->bi;
312	int rc = 1;
313
314	//Stuff goes here :-)
315
316	return rc;
317}
318
319
320int odlocales_initialize() {
321	int rc = 0;
322	Debug( LDAP_DEBUG_TRACE, "==> OD Locales overlay initialize called \n", 0, 0, 0 );
323	memset( &odlocales, 0, sizeof( slap_overinst ) );
324
325	odlocales.on_bi.bi_type = "odlocales";
326	odlocales.on_response = odlocales_response;
327	//odlocales.on_bi.bi_db_config = odlocales_db_config;
328	odlocales.on_bi.bi_cf_ocs = localeocs;
329
330	rc = config_register_schema( localecfg, localeocs );
331	if ( rc ) {
332		return rc;
333	}
334
335
336	return (overlay_register(&odlocales));
337}
338
339#if SLAPD_OVER_ODLOCALES == SLAPD_MOD_DYNAMIC
340int
341init_module( int argc, char *argv[] )
342{
343	Debug( LDAP_DEBUG_TRACE, "OD Locales overlay init_module \n", 0, 0, 0 );
344	return odlocales_initialize();
345}
346#endif
347#endif /* SLAPD_OVER_ODLOCALES */
348