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