1#include "portable.h" 2#ifdef SLAPD_OVER_ODUSERS 3#include "overlayutils.h" 4 5#include <arpa/inet.h> 6#define ODUSERS_BACK_CONFIG 1 7 8#include <ac/string.h> 9#include <ac/ctype.h> 10#include <uuid/uuid.h> 11#include "slap.h" 12#include "ldif.h" 13#include "config.h" 14#define __COREFOUNDATION_CFFILESECURITY__ 15#include <CoreFoundation/CoreFoundation.h> 16#include "applehelpers.h" 17 18extern AttributeDescription *policyAD; 19extern AttributeDescription *passwordRequiredDateAD; 20 21static AttributeDescription *uidAD = NULL; 22static AttributeDescription *krbAD = NULL; 23static AttributeDescription *draftkrbAD = NULL; 24static AttributeDescription *draftkrbAliasesAD = NULL; 25static AttributeDescription *aaAD = NULL; 26static AttributeDescription *altsecAD = NULL; 27 28static slap_overinst odusers; 29static ConfigDriver odusers_cf; 30static int odusers_add_authdata(Operation *op, SlapReply *rs, uuid_t newuuid); 31 32#define kDirservConfigName "cn=dirserv,cn=config" 33#define ODUSERS_EXTRA_KEY "odusers_key" 34 35typedef struct OpExtraOD { 36 OpExtra oe; 37 uuid_t uuid; 38} OpExtraOD; 39 40static ConfigTable odcfg[] = { 41 { "odusers", "enabled", 1, 1, 0, 42 ARG_MAGIC, odusers_cf, 43 "( OLcfgOvAt:700.11 NAME 'olcODUsersEnabled' " 44 "DESC 'Enable OD Users overlay' " 45 "EQUALITY booleanMatch " 46 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 47 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 48}; 49 50static ConfigOCs odocs[] = { 51 { "( OLcfgOvOc:700.11 " 52 "NAME 'olcODUsers' " 53 "DESC 'OD Users Overlay configuration' " 54 "SUP olcOverlayConfig " 55 "MAY (olcODUsersEnabled) )", 56 Cft_Overlay, odcfg, NULL, NULL }, 57 { NULL, 0, NULL } 58}; 59 60#undef calloc 61#undef malloc 62#undef free 63 64 65static int odusers_cf(ConfigArgs *c) { 66 slap_overinst *on = (slap_overinst *)c->bi; 67 return 1; 68} 69 70static bool odusers_isaccount(Operation *op) { 71 bool ret = false; 72 73 if(strnstr(op->o_req_ndn.bv_val, "cn=users", op->o_req_ndn.bv_len) != NULL) ret = 1; 74 if(strnstr(op->o_req_ndn.bv_val, "cn=computers", op->o_req_ndn.bv_len) != NULL) ret = 1; 75 76 return ret; 77} 78 79static int odusers_delete(Operation *op, SlapReply *rs) { 80 OperationBuffer opbuf; 81 Operation *fakeop; 82 Entry *e = NULL; 83 Entry *p = NULL; 84 char guidstr[37]; 85 struct berval *dn = &op->o_req_ndn; 86 87 if(op->o_req_ndn.bv_len < 14 || !(strnstr(op->o_req_ndn.bv_val, "cn=users,", op->o_req_ndn.bv_len)!=NULL || strnstr(op->o_req_ndn.bv_val, "cn=computers,", op->o_req_ndn.bv_len)!=NULL) || strnstr(op->o_req_ndn.bv_val, "cn=authdata", op->o_req_ndn.bv_len)!=NULL) { 88 goto out; 89 } 90 91 // Fake up a new Operation, but use the current Connection structure 92 memset(&opbuf, 0, sizeof(opbuf)); 93 fakeop = (Operation*)&opbuf; 94 fakeop->o_hdr = &opbuf.ob_hdr; 95 fakeop->o_controls = opbuf.ob_controls; 96 operation_fake_init(op->o_conn, (Operation*)&opbuf, ldap_pvt_thread_pool_context(), 0); 97 fakeop = &opbuf.ob_op; 98 fakeop->o_dn = fakeop->o_ndn = op->o_ndn; 99 100 dnParent(&op->o_req_ndn, &fakeop->o_req_ndn); 101 if(fakeop->o_req_ndn.bv_len < 1) { 102 goto out; 103 } 104 105 fakeop->o_req_dn = fakeop->o_req_ndn; 106 p = odusers_copy_entry(fakeop); 107 if(!p) { 108 goto out; 109 } 110 111 // First check for delete access to children of the parent 112 if(!access_allowed(fakeop, p, slap_schema.si_ad_children, NULL, ACL_WDEL, NULL)) { 113 Debug(LDAP_DEBUG_ANY, "%s: access denied: %s attempted to delete child of %s", __PRETTY_FUNCTION__, fakeop->o_ndn.bv_val, p->e_dn); 114 goto out; 115 } 116 117 // Find the entry we're trying to delete 118 fakeop->o_req_dn = fakeop->o_req_ndn = *dn; 119 e = odusers_copy_entry(fakeop); 120 if(!e) { 121 Debug(LDAP_DEBUG_ANY, "%s: No entry associated with %s\n", __PRETTY_FUNCTION__, dn->bv_val, 0); 122 goto out; 123 } 124 125 // Check for delete access of the specific entry 126 if(!access_allowed(fakeop, e, slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL)) { 127 Debug(LDAP_DEBUG_ANY, "%s: access denied: %s attempted to delete %s", __PRETTY_FUNCTION__, fakeop->o_ndn.bv_val, fakeop->o_req_ndn.bv_val); 128 goto out; 129 } 130 131 if( odusers_get_authguid(e, guidstr) ) { 132 goto out; 133 } 134 135 // Perform the removal 136 if( odusers_remove_authdata(guidstr) != 0 ) { 137 goto out; 138 } 139 140out: 141 if(e) entry_free(e); 142 if(p) entry_free(p); 143 return SLAP_CB_CONTINUE; 144} 145 146/* bridges an authdata attribute to a user container request */ 147static int odusers_search_bridge_authdata(Operation *op, SlapReply *rs, const char *reqattr) { 148 OperationBuffer opbuf; 149 Operation *fakeop; 150 Connection conn = {0}; 151 Entry *e = NULL; 152 Attribute *a = NULL; 153 Entry *retentry = NULL; 154 char guidstr[37]; 155 156 dnNormalize( 0, NULL, NULL, &op->o_req_dn, &op->o_req_ndn, NULL ); 157 e = odusers_copy_authdata(&op->o_req_ndn); 158 if(!e) { 159 Debug(LDAP_DEBUG_ANY, "%s: No entry associated with %s\n", __func__, op->o_req_ndn.bv_val, 0); 160 goto out; 161 } 162 163 for(a = e->e_attrs; a; a = a->a_next) { 164 if(strncmp(a->a_desc->ad_cname.bv_val, reqattr, a->a_desc->ad_cname.bv_len) == 0) { 165 retentry = entry_alloc(); 166 if(!retentry) goto out; 167 168 retentry->e_id = NOID; 169 retentry->e_name = op->o_req_dn; 170 retentry->e_nname = op->o_req_ndn; 171 172 retentry->e_attrs = attr_dup(a); 173 if(!retentry->e_attrs) { 174 Debug(LDAP_DEBUG_ANY, "%s: could not duplicate entry: %s", __func__, retentry->e_name.bv_val, 0); 175 goto out; 176 } 177 178 op->ors_slimit = -1; 179 rs->sr_entry = retentry; 180 rs->sr_nentries = 0; 181 rs->sr_flags = 0; 182 rs->sr_ctrls = NULL; 183 rs->sr_operational_attrs = NULL; 184 rs->sr_attrs = op->ors_attrs; 185 rs->sr_err = LDAP_SUCCESS; 186 rs->sr_err = send_search_entry(op, rs); 187 if(rs->sr_err == LDAP_SIZELIMIT_EXCEEDED) { 188 Debug(LDAP_DEBUG_ANY, "%s: size limit exceeded on entry: %s", __func__, retentry->e_name.bv_val, 0); 189 } 190 rs->sr_entry = NULL; 191 send_ldap_result(op, rs); 192 if(e) entry_free(e); 193 return rs->sr_err; 194 } 195 } 196 197out: 198 if(e) entry_free(e); 199// if (retentry) entry_free(retentry); 200 return SLAP_CB_CONTINUE; 201} 202 203static int odusers_search_accountpolicy_proxy(Operation *op, SlapReply *rs, char *attr_str) { 204 Entry *retentry = NULL; 205 Attribute *attr = NULL; 206 Filter *filter = NULL; 207 AttributeAssertion *ava = NULL; 208 char *tmpstr = NULL; 209 struct berval dn; 210 211 CFDictionaryRef userpolicyinfodict = NULL; 212 __block CFDictionaryRef policyData = NULL; 213 CFStringRef globalaccountpolicyGUID = NULL; 214 CFErrorRef cferr = NULL; 215 int64_t policyresult = 0; 216 int64_t willExpireIn = 0; 217 bool override = false; 218 219 bool isaccount = odusers_isaccount(op); 220 221 dn = op->o_req_ndn; 222 223 if(!BER_BVISEMPTY(&dn)) { 224 if (op->ors_filter) { 225 ava = op->ors_filter->f_ava; 226 filter = op->ors_filter; 227 } 228 229 if (isaccount) { 230 userpolicyinfodict = odusers_copy_accountpolicyinfo(&dn); 231 override = odusers_accountpolicy_override(&dn); 232 } else if (strncmp(op->o_req_ndn.bv_val, kDirservConfigName, strlen(kDirservConfigName)) == 0) { 233 userpolicyinfodict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 234 /* kAPAttributeGlobalPoliciesGUID */ 235 globalaccountpolicyGUID = odusers_copy_globalaccountpolicyGUID(); 236 if (globalaccountpolicyGUID) { 237 CFDictionarySetValue(userpolicyinfodict, kAPAttributeGlobalPoliciesGUID, globalaccountpolicyGUID); 238 } 239 } 240 241 if (userpolicyinfodict) { 242 if (override) { /* bypass AccountPolicy evaluation and return 'pass by default' */ 243 if ( strcmp(attr_str, "apple-authenticationAllowed") == 0 || strcmp(attr_str, "apple-passwordChangeAllowed") == 0 ) { 244 policyresult = 1; 245 } else if ( strcmp(attr_str, "apple-willPasswordExpire") == 0 || strcmp(attr_str, "apple-willAuthenticationsExpire") == 0 ) { 246 policyresult = 0; 247 } else if (strcmp(attr_str, "apple-secondsUntilPasswordExpires") == 0 || strcmp(attr_str, "apple-secondsUntilAuthenticationsExpire") == 0) { 248 policyresult = -1; 249 } 250 } else if (strcmp(attr_str, "apple-authenticationAllowed") == 0) { 251 policyresult = APAuthenticationAllowed(userpolicyinfodict, true, &cferr, ^(CFArrayRef keys){ return odusers_accountpolicy_retrievedata(&policyData, keys, &dn); }, NULL) ? (int64_t) 1 : (int64_t) CFErrorGetCode(cferr); 252 } else if (strcmp(attr_str, "apple-passwordChangeAllowed") == 0) { 253 Filter *flist = NULL; 254 if (filter ) { 255 if ( filter->f_choice == LDAP_FILTER_AND ) { /* "(&(uid=user1)(userPassword=abcd))" */ 256 flist = filter->f_and; 257 } else if ( filter->f_choice == LDAP_FILTER_EQUALITY ) { /* "(userPassword=abcd)" */ 258 flist = filter; 259 } 260 if (flist && flist->f_choice == LDAP_FILTER_EQUALITY) { /* (attr=value) */ 261 CFStringRef passcfstr = NULL; 262 CFStringRef uidcfstr = NULL; 263 for ( ; flist ; flist = flist->f_next) { 264 if (flist->f_av_desc == slap_schema.si_ad_userPassword && flist->f_av_value.bv_val) { 265 passcfstr = CFStringCreateWithBytes(kCFAllocatorDefault, flist->f_av_value.bv_val, flist->f_av_value.bv_len, kCFStringEncodingUTF8, false); 266 CFDictionarySetValue(userpolicyinfodict, kAPAttributePassword, passcfstr); 267 } else if (flist->f_av_desc == slap_schema.si_ad_uid && flist->f_av_value.bv_val) { 268 uidcfstr = CFStringCreateWithBytes(kCFAllocatorDefault, flist->f_av_value.bv_val, flist->f_av_value.bv_len, kCFStringEncodingUTF8, false); 269 CFDictionarySetValue(userpolicyinfodict, kAPAttributeRecordName, uidcfstr); 270 } 271 } 272 if (passcfstr) { 273 policyresult = (int64_t) APPasswordChangeAllowed(userpolicyinfodict, &cferr, ^(CFArrayRef keys){ return odusers_accountpolicy_retrievedata(&policyData, keys, &dn); }, NULL); 274 } else { 275 Debug(LDAP_DEBUG_ANY, "%s: APPasswordChangeAllowed - parameter error\n", __func__, 0, 0); 276 } 277 if (passcfstr) CFRelease(passcfstr); 278 if (uidcfstr) CFRelease(uidcfstr); 279 } 280 } 281 } else if (strcmp(attr_str, "apple-willPasswordExpire") == 0) { 282 if (ava && ava->aa_value.bv_val) { 283 willExpireIn = strtoll(ava->aa_value.bv_val, NULL, 10); 284 policyresult = (int64_t) APWillPasswordExpire(willExpireIn, userpolicyinfodict, ^(CFArrayRef keys){ return odusers_accountpolicy_retrievedata(&policyData, keys, &dn); }); 285 Debug(LDAP_DEBUG_ANY, "%s: APWillPasswordExpire %lld \n", __func__, willExpireIn, 0); 286 } 287 } else if (strcmp(attr_str, "apple-willAuthenticationsExpire") == 0) { 288 if (ava && ava->aa_value.bv_val) { 289 willExpireIn = strtoll(ava->aa_value.bv_val, NULL, 10); 290 policyresult = (int64_t) APWillAuthenticationsExpire(willExpireIn, userpolicyinfodict, ^(CFArrayRef keys){ return odusers_accountpolicy_retrievedata(&policyData, keys, &dn); }); 291 Debug(LDAP_DEBUG_ANY, "%s: APWillAuthenticationsExpire %lld \n", __func__, willExpireIn, 0); 292 } 293 } else if (strcmp(attr_str, "apple-secondsUntilPasswordExpires") == 0) { 294 policyresult = APSecondsUntilPasswordExpiration(userpolicyinfodict, ^(CFArrayRef keys){ return odusers_accountpolicy_retrievedata(&policyData, keys, &dn); }); 295 } else if (strcmp(attr_str, "apple-secondsUntilAuthenticationsExpire") == 0) { 296 policyresult = APSecondsUntilAuthenticationExpiration(userpolicyinfodict, ^(CFArrayRef keys){ return odusers_accountpolicy_retrievedata(&policyData, keys, &dn); }); 297 } 298 299 AttributeDescription *attrDesc = NULL; 300 const char *text = NULL; 301 if(slap_str2ad(attr_str, &attrDesc, &text) != 0) { 302 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for %s", __PRETTY_FUNCTION__, attr_str, 0); 303 goto out; 304 } 305 306 asprintf(&tmpstr, "%lld", policyresult); 307 attr = attr_alloc(attrDesc); 308 attr->a_flags |= SLAP_ATTR_DONT_FREE_DATA; 309 attr->a_vals = ch_malloc(2 * sizeof(struct berval)); 310 attr->a_vals[0].bv_val = tmpstr; 311 attr->a_vals[0].bv_len = strlen(tmpstr); 312 attr->a_vals[1].bv_len = 0; 313 attr->a_vals[1].bv_val = NULL; 314 attr->a_nvals = attr->a_vals; 315 316 } else { 317 goto out; 318 } 319 } else { 320 goto out; 321 } 322 323 retentry = entry_alloc(); 324 if(!retentry) goto out; 325 326 retentry->e_id = NOID; 327 ber_dupbv(&retentry->e_name, &op->o_req_dn); 328 ber_dupbv(&retentry->e_nname, &op->o_req_ndn); 329 330 if (attr) { 331 retentry->e_attrs = attr; 332 } else { 333 retentry->e_attrs = NULL; 334 } 335 336 op->ors_slimit = -1; 337 rs->sr_entry = retentry; 338 rs->sr_nentries = 0; 339 rs->sr_flags = 0; 340 rs->sr_ctrls = NULL; 341 rs->sr_operational_attrs = NULL; 342 rs->sr_attrs = op->ors_attrs; 343 rs->sr_err = LDAP_SUCCESS; 344 rs->sr_err = send_search_entry(op, rs); 345 if(rs->sr_err == LDAP_SIZELIMIT_EXCEEDED) { 346 Debug(LDAP_DEBUG_ANY, "%s: size limit exceeded on entry: %s", __func__, retentry->e_name.bv_val, 0); 347 } 348 rs->sr_entry = NULL; 349 send_ldap_result(op, rs); 350 if(retentry) entry_free(retentry); 351 if (userpolicyinfodict) CFRelease(userpolicyinfodict); 352 if (policyData) CFRelease(policyData); 353 if (globalaccountpolicyGUID) CFRelease(globalaccountpolicyGUID); 354 if (cferr) CFRelease(cferr); 355 free(tmpstr); 356 return rs->sr_err; 357 358 359out: 360 if(retentry) entry_free(retentry); 361 if (userpolicyinfodict) CFRelease(userpolicyinfodict); 362 if (policyData) CFRelease(policyData); 363 if (globalaccountpolicyGUID) CFRelease(globalaccountpolicyGUID); 364 if (cferr) CFRelease(cferr); 365 return SLAP_CB_CONTINUE; 366} 367 368static int odusers_search_bridge_accountpolicy(Operation *op, SlapReply *rs) { 369 OperationBuffer opbuf; 370 Operation *fakeop; 371 Connection conn = {0}; 372 Entry *e = NULL; 373 Attribute *a = NULL; 374 Entry *retentry = NULL; 375 char guidstr[37]; 376 Attribute *pwsPolicyAttr = NULL; 377 378 dnNormalize( 0, NULL, NULL, &op->o_req_dn, &op->o_req_ndn, NULL ); 379 e = odusers_copy_authdata(&op->o_req_ndn); 380 if(!e) { 381 Debug(LDAP_DEBUG_ANY, "%s: No entry associated with %s\n", __func__, op->o_req_ndn.bv_val, 0); 382 goto out; 383 } 384 385 /* translate PasswordServer 'apple-user-passwordpolicy' queries from new 'apple-accountpolicy' format */ 386 CFDictionaryRef accountpolicy = odusers_copy_accountpolicy_fromentry(e); 387 if (accountpolicy) { 388 CFDictionaryRef pwsPolicy = APLegacyPoliciesWithPolicySet(accountpolicy); 389 if (pwsPolicy) { 390 AttributeDescription *pwsPolicydesc = NULL; 391 const char *text = NULL; 392 if(slap_str2ad("apple-user-passwordpolicy", &pwsPolicydesc, &text) != 0) { 393 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for global policy", __PRETTY_FUNCTION__, 0, 0); 394 goto out; 395 } 396 397 struct berval *bv = odusers_copy_dict2bv(pwsPolicy); 398 CFRelease(pwsPolicy); 399 400 pwsPolicyAttr = attr_alloc(pwsPolicydesc); 401 pwsPolicyAttr->a_vals = ch_malloc(2 * sizeof(struct berval)); 402 pwsPolicyAttr->a_vals[0] = *bv; 403 pwsPolicyAttr->a_vals[1].bv_len = 0; 404 pwsPolicyAttr->a_vals[1].bv_val = NULL; 405 pwsPolicyAttr->a_nvals = pwsPolicyAttr->a_vals; 406 } 407 CFRelease(accountpolicy); 408 } 409 410 retentry = entry_alloc(); 411 if(!retentry) goto out; 412 413 retentry->e_id = NOID; 414 retentry->e_name = op->o_req_dn; 415 retentry->e_nname = op->o_req_ndn; 416 417 if (pwsPolicyAttr) { 418 retentry->e_attrs = pwsPolicyAttr; 419 } else { 420 retentry->e_attrs = NULL; 421 } 422 423 op->ors_slimit = -1; 424 rs->sr_entry = retentry; 425 rs->sr_nentries = 0; 426 rs->sr_flags = 0; 427 rs->sr_ctrls = NULL; 428 rs->sr_operational_attrs = NULL; 429 rs->sr_attrs = op->ors_attrs; 430 rs->sr_err = LDAP_SUCCESS; 431 rs->sr_err = send_search_entry(op, rs); 432 if(rs->sr_err == LDAP_SIZELIMIT_EXCEEDED) { 433 Debug(LDAP_DEBUG_ANY, "%s: size limit exceeded on entry: %s", __func__, retentry->e_name.bv_val, 0); 434 } 435 rs->sr_entry = NULL; 436 send_ldap_result(op, rs); 437 if(e) entry_free(e); 438 return rs->sr_err; 439 440 441out: 442 if(e) entry_free(e); 443 return SLAP_CB_CONTINUE; 444 445} 446 447static int odusers_search_effective_userpolicy(Operation *op, SlapReply *rs) { 448 Attribute *effective = NULL; 449 const char *text = NULL; 450 CFDictionaryRef effectivedict = odusers_copy_effectiveuserpoldict(&op->o_req_ndn); 451 if(!effectivedict) { 452 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve effective policy for %s\n", __func__, op->o_req_ndn.bv_val, 0); 453 goto out; 454 } 455 456 Entry *retentry = entry_alloc(); 457 if(!retentry) goto out; 458 459 retentry->e_id = NOID; 460 retentry->e_name = op->o_req_dn; 461 retentry->e_nname = op->o_req_ndn; 462 463 struct berval *bv = odusers_copy_dict2bv(effectivedict); 464 CFRelease(effectivedict); 465 if(!bv) { 466 Debug(LDAP_DEBUG_ANY, "%s: Unable to convert effective policy to berval", __PRETTY_FUNCTION__, 0, 0); 467 goto out; 468 } 469 470 AttributeDescription *effectivedesc = NULL; 471 if(slap_str2ad("apple-user-passwordpolicy-effective", &effectivedesc, &text) != 0) { 472 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for effective policy", __PRETTY_FUNCTION__, 0, 0); 473 goto out; 474 } 475 476 effective = attr_alloc(effectivedesc); 477 effective->a_vals = ch_malloc(2 * sizeof(struct berval)); 478 effective->a_vals[0] = *bv; 479 ch_free(bv); 480 effective->a_vals[1].bv_len = 0; 481 effective->a_vals[1].bv_val = NULL; 482 effective->a_nvals = effective->a_vals; 483 484 retentry->e_attrs = effective; 485 486 op->ors_slimit = -1; 487 rs->sr_entry = retentry; 488 rs->sr_nentries = 0; 489 rs->sr_flags = 0; 490 rs->sr_ctrls = NULL; 491 rs->sr_operational_attrs = NULL; 492 rs->sr_attrs = op->ors_attrs; 493 rs->sr_err = LDAP_SUCCESS; 494 rs->sr_err = send_search_entry(op, rs); 495 if(rs->sr_err == LDAP_SIZELIMIT_EXCEEDED) { 496 Debug(LDAP_DEBUG_ANY, "%s: size limit exceeded on entry: %s", __PRETTY_FUNCTION__, retentry->e_name.bv_val, 0); 497 } 498 rs->sr_entry = NULL; 499 send_ldap_result(op, rs); 500 return rs->sr_err; 501 502out: 503// if (retentry) entry_free(retentry); 504 return SLAP_CB_CONTINUE; 505} 506static int odusers_search_global_accountpolicy(Operation *op, SlapReply *rs) { 507 Attribute *attr = odusers_copy_attr("cn=access,cn=authdata", "apple-accountpolicy"); 508 509 Entry *retentry = entry_alloc(); 510 if(!retentry) goto out; 511 512 retentry->e_id = NOID; 513 retentry->e_name = op->o_req_dn; 514 retentry->e_nname = op->o_req_ndn; 515 retentry->e_attrs = attr; 516 517 op->ors_slimit = -1; 518 rs->sr_entry = retentry; 519 rs->sr_nentries = 0; 520 rs->sr_flags = 0; 521 rs->sr_ctrls = NULL; 522 rs->sr_operational_attrs = NULL; 523 rs->sr_attrs = op->ors_attrs; 524 rs->sr_err = LDAP_SUCCESS; 525 rs->sr_err = send_search_entry(op, rs); 526 if(rs->sr_err == LDAP_SIZELIMIT_EXCEEDED) { 527 Debug(LDAP_DEBUG_ANY, "%s: size limit exceeded on entry: %s", __PRETTY_FUNCTION__, retentry->e_name.bv_val, 0); 528 } 529 rs->sr_entry = NULL; 530 send_ldap_result(op, rs); 531 return rs->sr_err; 532 533out: 534 if(attr) attr_free(attr); 535 return SLAP_CB_CONTINUE; 536} 537 538static int odusers_search_globalpolicy(Operation *op, SlapReply *rs) { 539 Attribute *global = odusers_copy_globalpolicy(); 540 if(!global) { 541 CFDictionaryRef globaldict = odusers_copy_defaultglobalpolicy(); 542 struct berval *bv = odusers_copy_dict2bv(globaldict); 543 CFRelease(globaldict); 544 545 AttributeDescription *globaldesc = NULL; 546 const char *text = NULL; 547 if(slap_str2ad("apple-user-passwordpolicy", &globaldesc, &text) != 0) { 548 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for global policy", __PRETTY_FUNCTION__, 0, 0); 549 goto out; 550 } 551 552 global = attr_alloc(globaldesc); 553 global->a_vals = ch_malloc(2 * sizeof(struct berval)); 554 global->a_vals[0] = *bv; 555 global->a_vals[1].bv_len = 0; 556 global->a_vals[1].bv_val = NULL; 557 global->a_nvals = global->a_vals; 558 } 559 560 Entry *retentry = entry_alloc(); 561 if(!retentry) goto out; 562 563 retentry->e_id = NOID; 564 retentry->e_name = op->o_req_dn; 565 retentry->e_nname = op->o_req_ndn; 566 retentry->e_attrs = global; 567 568 op->ors_slimit = -1; 569 rs->sr_entry = retentry; 570 rs->sr_nentries = 0; 571 rs->sr_flags = 0; 572 rs->sr_ctrls = NULL; 573 rs->sr_operational_attrs = NULL; 574 rs->sr_attrs = op->ors_attrs; 575 rs->sr_err = LDAP_SUCCESS; 576 rs->sr_err = send_search_entry(op, rs); 577 if(rs->sr_err == LDAP_SIZELIMIT_EXCEEDED) { 578 Debug(LDAP_DEBUG_ANY, "%s: size limit exceeded on entry: %s", __PRETTY_FUNCTION__, retentry->e_name.bv_val, 0); 579 } 580 rs->sr_entry = NULL; 581 send_ldap_result(op, rs); 582 return rs->sr_err; 583 584out: 585 if(global) attr_free(global); 586 return SLAP_CB_CONTINUE; 587} 588 589static int odusers_search_pwsprefs(Operation *op, SlapReply *rs) { 590 OperationBuffer opbuf; 591 Operation *fakeop; 592 Connection conn = {0}; 593 Entry *e = NULL; 594 Attribute *a; 595 char *saslrealm = NULL; 596 int ret = 0; 597 598 CFMutableDictionaryRef prefs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 599 int zeroint = 0; 600 CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zeroint); 601 CFDictionaryAddValue(prefs, CFSTR("BadTrialDelay"), zero); 602 CFRelease(zero); 603 604 CFDictionaryAddValue(prefs, CFSTR("ExternalCommand"), CFSTR("Disabled")); 605 606 CFMutableArrayRef listeners = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 607 CFArrayAppendValue(listeners, CFSTR("Ethernet")); 608 CFArrayAppendValue(listeners, CFSTR("Local")); 609 CFArrayAppendValue(listeners, CFSTR("UNIX Domain Socket")); 610 CFDictionaryAddValue(prefs, CFSTR("ListenerInterfaces"), listeners); 611 CFRelease(listeners); 612 613 CFMutableArrayRef ports = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 614 int oneohsixint = 106; 615 CFNumberRef oneohsix = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &oneohsixint); 616 CFArrayAppendValue(ports, oneohsix); 617 CFRelease(oneohsix); 618 int threesixfivenineint = 3659; 619 CFNumberRef threesixfivenine = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &threesixfivenineint); 620 CFArrayAppendValue(ports, threesixfivenine); 621 CFRelease(threesixfivenine); 622 CFDictionaryAddValue(prefs, CFSTR("ListenerPorts"), ports); 623 CFRelease(ports); 624 625 int threeint = 3; 626 CFNumberRef three = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &threeint); 627 CFDictionaryAddValue(prefs, CFSTR("Preference File Version"), three); 628 CFRelease(three); 629 630 char *suffix = op->o_req_ndn.bv_val + strlen("cn=passwordserver,cn=config,"); 631 CFArrayRef mechs = odusers_copy_enabledmechs(suffix); 632 if(mechs) { 633 int i; 634 CFMutableDictionaryRef pluginstates = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 635 for(i = 0; i < CFArrayGetCount(mechs); i++) { 636 CFStringRef mech = CFArrayGetValueAtIndex(mechs, i); 637 CFDictionaryAddValue(pluginstates, mech, CFSTR("ON")); 638 } 639 CFDictionaryAddValue(prefs, CFSTR("SASLPluginStates"), pluginstates); 640 CFRelease(mechs); 641 CFRelease(pluginstates); 642 } 643 644 CFDictionaryAddValue(prefs, CFSTR("SyncSASLPlugInList"), kCFBooleanTrue); 645 646 saslrealm = odusers_copy_saslrealm(); 647 if(!saslrealm) { 648 Debug(LDAP_DEBUG_ANY, "%s: unable to find sasl realm\n", __func__, 0, 0); 649 goto out; 650 } 651 652 CFStringRef cfsaslrealm = CFStringCreateWithCString(kCFAllocatorDefault, saslrealm, kCFStringEncodingUTF8); 653 CFDictionaryAddValue(prefs, CFSTR("SASLRealm"), cfsaslrealm); 654 CFRelease(cfsaslrealm); 655 ch_free(saslrealm); 656 657 e = entry_alloc(); 658 e->e_id = NOID; 659 e->e_name = op->o_req_dn; 660 e->e_nname = op->o_req_ndn; 661 AttributeDescription *desc = NULL; 662 const char *text; 663 if(slap_str2ad("apple-xmlplist", &desc, &text) != 0) { 664 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for apple-xmlplist\n", __func__, 0, 0); 665 goto out; 666 } 667 struct berval *bv = odusers_copy_dict2bv(prefs); 668 if(!bv) { 669 Debug(LDAP_DEBUG_ANY, "%s: Unable to convert prefs to berval\n", __func__, 0, 0); 670 goto out; 671 } 672 e->e_attrs = attr_alloc(desc); 673 e->e_attrs->a_vals = ch_malloc(2 * sizeof(struct berval)); 674 e->e_attrs->a_vals[0] = *bv; 675 e->e_attrs->a_vals[1].bv_len = 0; 676 e->e_attrs->a_vals[1].bv_val = 0; 677 e->e_attrs->a_nvals = e->e_attrs->a_vals; 678 e->e_attrs->a_numvals = 1; 679 ch_free(bv); 680 681 op->ors_slimit = -1; 682 rs->sr_entry = e; 683 rs->sr_nentries = 1; 684 rs->sr_flags = 0; 685 rs->sr_ctrls = 0; 686 rs->sr_operational_attrs = NULL; 687 rs->sr_attrs = op->ors_attrs; 688 rs->sr_err = LDAP_SUCCESS; 689 rs->sr_err = send_search_entry(op, rs); 690 rs->sr_entry = NULL; 691 send_ldap_result(op, rs); 692 ret = rs->sr_err; 693 694out: 695 if(prefs) CFRelease(prefs); 696 return 0; 697} 698 699static int odusers_search(Operation *op, SlapReply *rs) { 700 bool isaccount; 701 702 if(!op || op->o_req_ndn.bv_len == 0) return SLAP_CB_CONTINUE; 703 if(!op->ors_attrs) return SLAP_CB_CONTINUE; 704 if(strnstr(op->o_req_ndn.bv_val, "cn=authdata", op->o_req_ndn.bv_len) != NULL) return SLAP_CB_CONTINUE; 705 706 isaccount = odusers_isaccount(op); 707 708 if(isaccount && strncmp(op->ors_attrs[0].an_name.bv_val, "apple-user-passwordpolicy", op->ors_attrs[0].an_name.bv_len) == 0) { 709 return odusers_search_bridge_accountpolicy(op, rs); 710 } else if(strncmp(op->ors_attrs[0].an_name.bv_val, "apple-authenticationAllowed", op->ors_attrs[0].an_name.bv_len) == 0 || 711 strncmp(op->ors_attrs[0].an_name.bv_val, "apple-passwordChangeAllowed", op->ors_attrs[0].an_name.bv_len) == 0 || 712 strncmp(op->ors_attrs[0].an_name.bv_val, "apple-willPasswordExpire", op->ors_attrs[0].an_name.bv_len) == 0 || 713 strncmp(op->ors_attrs[0].an_name.bv_val, "apple-willAuthenticationsExpire", op->ors_attrs[0].an_name.bv_len) == 0 || 714 strncmp(op->ors_attrs[0].an_name.bv_val, "apple-secondsUntilPasswordExpires", op->ors_attrs[0].an_name.bv_len) == 0 || 715 strncmp(op->ors_attrs[0].an_name.bv_val, "apple-secondsUntilAuthenticationsExpire", op->ors_attrs[0].an_name.bv_len) == 0 ) { 716 return odusers_search_accountpolicy_proxy(op, rs, op->ors_attrs[0].an_name.bv_val); 717 } else if(isaccount && strncmp(op->ors_attrs[0].an_name.bv_val, "apple-user-passwordpolicy-effective", op->ors_attrs[0].an_name.bv_len) == 0) { 718 return odusers_search_effective_userpolicy(op, rs); 719 } else if(isaccount && strncmp(op->ors_attrs[0].an_name.bv_val, "draft-krbPrincipalAliases", op->ors_attrs[0].an_name.bv_len) == 0) { 720 return odusers_search_bridge_authdata(op, rs, "draft-krbPrincipalAliases"); 721 } else if(isaccount && strncmp(op->ors_attrs[0].an_name.bv_val, "apple-accountpolicy", op->ors_attrs[0].an_name.bv_len) == 0) { 722 return odusers_search_bridge_authdata(op, rs, "apple-accountpolicy"); 723 } else if(!isaccount && (strncmp(op->o_req_ndn.bv_val, kDirservConfigName, strlen(kDirservConfigName)) == 0) && strncmp(op->ors_attrs[0].an_name.bv_val, "apple-accountpolicy", op->ors_attrs[0].an_name.bv_len) == 0) { 724 odusers_search_global_accountpolicy(op, rs); 725 } else if(!isaccount && (strncmp(op->o_req_ndn.bv_val, kDirservConfigName, strlen(kDirservConfigName)) == 0) && strncmp(op->ors_attrs[0].an_name.bv_val, "apple-user-passwordpolicy", op->ors_attrs[0].an_name.bv_len) == 0) { 726 return odusers_search_globalpolicy(op, rs); 727 } else if(!isaccount && (strncmp(op->o_req_ndn.bv_val, "cn=passwordserver,cn=config", strlen(kDirservConfigName)) == 0) && strncmp(op->ors_attrs[0].an_name.bv_val, "apple-xmlplist", op->ors_attrs[0].an_name.bv_len) == 0) { 728 return odusers_search_pwsprefs(op, rs); 729 } 730 731 return SLAP_CB_CONTINUE; 732} 733 734static int odusers_insert_vendorName(SlapReply *rs) { 735 Attribute *a = NULL; 736 // Make sure attribute doesn't exist 737 for(a = rs->sr_un.sru_search.r_entry->e_attrs; a; a = a->a_next) { 738 if(strncmp(a->a_desc->ad_cname.bv_val, "vendorName", a->a_desc->ad_cname.bv_len) == 0) { 739 goto out; 740 } 741 } 742 743 AttributeDescription *namedesc = NULL; 744 const char *text = NULL; 745 if(slap_str2ad("vendorName", &namedesc, &text) != 0) { 746 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for vendorName", __PRETTY_FUNCTION__, 0, 0); 747 goto out; 748 } 749 750 a = attr_alloc(namedesc); 751 a->a_vals = ch_malloc(2 * sizeof(struct berval)); 752 a->a_vals[0].bv_val = ch_strdup("Apple") ; 753 a->a_vals[0].bv_len = strlen(a->a_vals[0].bv_val); 754 a->a_vals[1].bv_len = 0; 755 a->a_vals[1].bv_val = NULL; 756 a->a_nvals = a->a_vals; 757 758 a->a_next = rs->sr_un.sru_search.r_entry->e_attrs; 759 rs->sr_un.sru_search.r_entry->e_attrs = a; 760out: 761 return 0; 762} 763 764static int odusers_insert_vendorVersion(SlapReply *rs) { 765 Attribute *a = NULL; 766 // Make sure attribute doesn't exist 767 for(a = rs->sr_un.sru_search.r_entry->e_attrs; a; a = a->a_next) { 768 if(strncmp(a->a_desc->ad_cname.bv_val, "vendorVersion", a->a_desc->ad_cname.bv_len) == 0) { 769 goto out; 770 } 771 } 772 773 AttributeDescription *namedesc = NULL; 774 const char *text = NULL; 775 if(slap_str2ad("vendorVersion", &namedesc, &text) != 0) { 776 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for vendorVersion", __PRETTY_FUNCTION__, 0, 0); 777 goto out; 778 } 779 780 a = attr_alloc(namedesc); 781 a->a_vals = ch_malloc(2 * sizeof(struct berval)); 782 a->a_vals[0].bv_val = ch_strdup(PROJVERSION); 783 a->a_vals[0].bv_len = strlen(a->a_vals[0].bv_val); 784 a->a_vals[1].bv_len = 0; 785 a->a_vals[1].bv_val = NULL; 786 a->a_nvals = a->a_vals; 787 788 a->a_next = rs->sr_un.sru_search.r_entry->e_attrs; 789 rs->sr_un.sru_search.r_entry->e_attrs = a; 790out: 791 return 0; 792} 793 794static int odusers_insert_operatingSystemVersion(SlapReply *rs) { 795 const char* attrName = "operatingSystemVersion"; 796 Attribute *a = NULL; 797 // Make sure attribute doesn't exist 798 for(a = rs->sr_un.sru_search.r_entry->e_attrs; a; a = a->a_next) { 799 if(strncmp(a->a_desc->ad_cname.bv_val, attrName, a->a_desc->ad_cname.bv_len) == 0) { 800 goto out; 801 } 802 } 803 804 AttributeDescription *namedesc = NULL; 805 const char *text = NULL; 806 if(slap_str2ad(attrName, &namedesc, &text) != 0) { 807 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for %s", __PRETTY_FUNCTION__, attrName, 0); 808 goto out; 809 } 810 811 a = attr_alloc(namedesc); 812 a->a_vals = ch_malloc(2 * sizeof(struct berval)); 813 a->a_vals[0].bv_val = ch_strdup(TGT_OS_VERSION); 814 a->a_vals[0].bv_len = strlen(a->a_vals[0].bv_val); 815 a->a_vals[1].bv_len = 0; 816 a->a_vals[1].bv_val = NULL; 817 a->a_nvals = a->a_vals; 818 819 a->a_next = rs->sr_un.sru_search.r_entry->e_attrs; 820 rs->sr_un.sru_search.r_entry->e_attrs = a; 821out: 822 return 0; 823} 824 825static int odusers_response(Operation *op, SlapReply *rs) { 826 static char *version = NULL; 827 AttributeName *an = NULL; 828 829 /* If this is a result to an ADD that is a user/computer account */ 830 if(op->o_tag == LDAP_REQ_ADD && (strnstr(op->o_req_ndn.bv_val, "cn=authdata", op->o_req_ndn.bv_len) == NULL) && odusers_isaccount(op)) { 831 Debug(LDAP_DEBUG_ANY, "%s: processing response to add of %s\n", __func__, op->o_req_dn.bv_val, 0); 832 833 Attribute *a = NULL; 834 OpExtraOD *oe = NULL; 835 OpExtra *oex = NULL; 836 a = attr_find( op->ora_e->e_attrs, slap_schema.si_ad_entryUUID ); 837 if(!a) { 838 Debug(LDAP_DEBUG_ANY, "%s: Could not find entryUUID\n", __func__, 0, 0); 839 } else { 840 Debug(LDAP_DEBUG_ANY, "%s: entryUUID %s\n", __func__, a->a_vals[0].bv_val, 0); 841 } 842 843 LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) { 844 if(oex->oe_key == ODUSERS_EXTRA_KEY) { 845 char uuidstr[37]; 846 oe = (OpExtraOD*)oex; 847 848 uuidstr[sizeof(uuidstr)-1] = '\0'; 849 uuid_unparse_lower(oe->uuid, uuidstr); 850 Debug(LDAP_DEBUG_ANY, "%s: Found uuid: %s\n", __func__, uuidstr, 0); 851 if (rs->sr_err == LDAP_SUCCESS && rs->sr_type == REP_RESULT) { // add authdata on successful creation 852 odusers_add_authdata(op, rs, oe->uuid); 853 } 854 LDAP_SLIST_REMOVE(&op->o_extra, &oe->oe, OpExtra, oe_next); 855 free(oe); 856 break; 857 } 858 } 859 860 return SLAP_CB_CONTINUE; 861 } 862 863 if ((rs->sr_type != REP_SEARCH) || (op->oq_search.rs_attrs == NULL) ) { 864 return SLAP_CB_CONTINUE; 865 } 866 867 if(!op->ors_attrs) return SLAP_CB_CONTINUE; 868 869 // Only interested in the rootDSE 870 if(op->o_req_ndn.bv_len != 0) return SLAP_CB_CONTINUE; 871 872 int i; 873 for(i = 0; op->ors_attrs[i].an_name.bv_len > 0; i++) { 874 if(op->ors_attrs[i].an_name.bv_val == NULL) break; 875 if(strncmp(op->ors_attrs[i].an_name.bv_val, "vendorName", op->ors_attrs[i].an_name.bv_len) == 0) { 876 odusers_insert_vendorName(rs); 877 } else if(strncmp(op->ors_attrs[i].an_name.bv_val, "vendorVersion", op->ors_attrs[i].an_name.bv_len) == 0) { 878 odusers_insert_vendorVersion(rs); 879 } else if(strncmp(op->ors_attrs[i].an_name.bv_val, "operatingSystemVersion", op->ors_attrs[i].an_name.bv_len) == 0) { 880 odusers_insert_operatingSystemVersion(rs); 881 } else if(strncmp(op->ors_attrs[i].an_name.bv_val, "+", op->ors_attrs[i].an_name.bv_len) == 0) { 882 odusers_insert_vendorName(rs); 883 odusers_insert_vendorVersion(rs); 884 odusers_insert_operatingSystemVersion(rs); 885 } 886 } 887 888out: 889 return SLAP_CB_CONTINUE; 890} 891 892static int odusers_modify_bridge_authdata(Operation *op, SlapReply *rs) { 893 OperationBuffer opbuf = {0}; 894 Operation *fakeop; 895 Connection conn = {0}; 896 Entry *e; 897 898 e = odusers_copy_authdata(&op->o_req_ndn); 899 if(!e) { 900 Debug(LDAP_DEBUG_ANY, "%s: No entry associated with %s\n", __PRETTY_FUNCTION__, op->o_req_ndn.bv_val, 0); 901 goto out; 902 } 903 904 connection_fake_init2(&conn, &opbuf, ldap_pvt_thread_pool_context(), 0); 905 fakeop = &opbuf.ob_op; 906 fakeop->o_dn = op->o_dn; 907 fakeop->o_ndn = op->o_ndn; 908 fakeop->o_req_dn = e->e_name; 909 fakeop->o_req_ndn = e->e_nname; 910 fakeop->o_tag = op->o_tag; 911 fakeop->orm_modlist = op->orm_modlist; 912 fakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 913 fakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 914 915 // Use the frontend DB for the modification so we go through the syncrepl 916 // overlay and our change gets replicated. 917 fakeop->o_bd = frontendDB; 918 919 slap_op_time(&op->o_time, &op->o_tincr); 920 921 fakeop->o_bd->be_modify(fakeop, rs); 922 if(rs->sr_err != LDAP_SUCCESS) { 923 Debug(LDAP_DEBUG_ANY, "%s: Unable to modify authdata attribute: %s (%d)\n", __PRETTY_FUNCTION__, fakeop->o_req_ndn.bv_val, rs->sr_err); 924 goto out; 925 } 926 927 send_ldap_result(op, rs); 928 return rs->sr_err; 929 930out: 931 return SLAP_CB_CONTINUE; 932} 933 934static int odusers_modify_userpolicy(Operation *op, SlapReply *rs) { 935 OperationBuffer opbuf = {0}; 936 Operation *fakeop; 937 Connection conn = {0}; 938 Entry *e; 939 Modifications *m = op->orm_modlist; 940 CFDictionaryRef userdict = NULL; 941 CFDictionaryRef accountPolicyDict = NULL; 942 943 e = odusers_copy_authdata(&op->o_req_ndn); 944 if(!e) { 945 Debug(LDAP_DEBUG_ANY, "%s: No entry associated with %s\n", __func__, op->o_req_ndn.bv_val, 0); 946 goto out; 947 } 948 949 connection_fake_init2(&conn, &opbuf, ldap_pvt_thread_pool_context(), 0); 950 fakeop = &opbuf.ob_op; 951 fakeop->o_dn = op->o_dn; 952 fakeop->o_ndn = op->o_ndn; 953 fakeop->o_req_dn = e->e_name; 954 fakeop->o_req_ndn = e->e_nname; 955 fakeop->o_tag = op->o_tag; 956 fakeop->orm_modlist = op->orm_modlist; 957 fakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 958 fakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 959 960 if(m && m->sml_numvals) { 961 userdict = CopyPolicyToDict(m->sml_values[0].bv_val, m->sml_values[0].bv_len); 962 if(!userdict) { 963 Debug(LDAP_DEBUG_ANY, "%s: Could not convert user policy to dict", __func__, 0, 0); 964 } else { 965 CFNumberRef isAdminUser = CFDictionaryGetValue(userdict, CFSTR("isAdminUser")); 966 unsigned int tmpint = 0; 967 if(isAdminUser) { 968 CFNumberGetValue(isAdminUser, kCFNumberIntType, &tmpint); 969 if(tmpint) { 970 odusers_joingroup("admin", &op->o_req_dn, 0); 971 } else { 972 odusers_joingroup("admin", &op->o_req_dn, 1); 973 } 974 } 975 976 CFNumberRef isSessionKeyAgent = CFDictionaryGetValue(userdict, CFSTR("isSessionKeyAgent")); 977 tmpint = 0; 978 if(isSessionKeyAgent) { 979 CFNumberGetValue(isSessionKeyAgent, kCFNumberIntType, &tmpint); 980 if(tmpint) { 981 odusers_joingroup("com.apple.access_sessionkey", &op->o_req_dn, 0); 982 } else { 983 odusers_joingroup("com.apple.access_sessionkey", &op->o_req_dn, 1); 984 } 985 } 986 987 CFNumberRef isDisabled = CFDictionaryGetValue(userdict, CFSTR("isDisabled")); 988 tmpint = 0; 989 if(isDisabled) { 990 CFNumberGetValue(isDisabled, kCFNumberIntType, &tmpint); 991 if(tmpint) { 992 odusers_joingroup("com.apple.access_disabled", &op->o_req_dn, 0); 993 } else { 994 odusers_joingroup("com.apple.access_disabled", &op->o_req_dn, 1); 995 } 996 } 997 998 accountPolicyDict = APPolicySetWithLegacyPolicies(userdict); 999 if (accountPolicyDict) { 1000 Debug(LDAP_DEBUG_ANY, "%s: APPolicySetWithLegacyPolicies", __func__, 0, 0); 1001 odusers_accountpolicy_set(&op->o_req_ndn, e, accountPolicyDict); 1002 CFRelease(accountPolicyDict); 1003 } 1004 CFRelease(userdict); 1005 } 1006 } 1007 1008 // Use the frontend DB for the modification so we go through the syncrepl 1009 // overlay and our change gets replicated. 1010 fakeop->o_bd = frontendDB; 1011 1012 slap_op_time(&op->o_time, &op->o_tincr); 1013 1014 fakeop->o_bd->be_modify(fakeop, rs); 1015 if(rs->sr_err != LDAP_SUCCESS) { 1016 Debug(LDAP_DEBUG_ANY, "%s: Unable to modify authdata attribute: %s (%d)\n", __PRETTY_FUNCTION__, fakeop->o_req_ndn.bv_val, rs->sr_err); 1017 goto out; 1018 } 1019 1020 send_ldap_result(op, rs); 1021 return rs->sr_err; 1022 1023out: 1024 return SLAP_CB_CONTINUE; 1025} 1026 1027static int odusers_modify_globalpolicy(Operation *op, SlapReply *rs) { 1028 OperationBuffer opbuf = {0}; 1029 Operation *fakeop; 1030 Connection conn = {0}; 1031 Entry *e; 1032 Modifications *m = op->orm_modlist; 1033 CFDictionaryRef globaldict = NULL; 1034 1035 connection_fake_init2(&conn, &opbuf, ldap_pvt_thread_pool_context(), 0); 1036 fakeop = &opbuf.ob_op; 1037 fakeop->o_dn = op->o_dn; 1038 fakeop->o_ndn = op->o_ndn; 1039 fakeop->o_req_dn.bv_val = "cn=access,cn=authdata"; 1040 fakeop->o_req_dn.bv_len = strlen(fakeop->o_req_dn.bv_val); 1041 fakeop->o_req_ndn = fakeop->o_req_dn; 1042 fakeop->o_tag = op->o_tag; 1043 fakeop->orm_modlist = op->orm_modlist; 1044 fakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 1045 fakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 1046 1047 if(m && m->sml_numvals) { 1048 globaldict = CopyPolicyToDict(m->sml_values[0].bv_val, m->sml_values[0].bv_len); 1049 if(!globaldict) { 1050 Debug(LDAP_DEBUG_ANY, "%s: Could not convert global policy to dict", __func__, 0, 0); 1051 } else { 1052 /* translate apple-user-passwordpolicy to apple-accountpolicy */ 1053 if (strncmp(m->sml_desc->ad_cname.bv_val, "apple-user-passwordpolicy", m->sml_desc->ad_cname.bv_len) == 0) { 1054 CFDictionaryRef accountPolicyDict = NULL; 1055 accountPolicyDict = APPolicySetWithLegacyPolicies(globaldict); 1056 if (accountPolicyDict) { 1057 Debug(LDAP_DEBUG_ANY, "%s: APPolicySetWithLegacyPolicies - global", __func__, 0, 0); 1058 AttributeDescription *appleAccountPolicyAD = NULL; 1059 const char *text = NULL; 1060 struct berval *policy_bv = NULL; 1061 1062 if(slap_str2ad("apple-accountpolicy", &appleAccountPolicyAD, &text) != 0) { 1063 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of apple-accountpolicy attribute", __PRETTY_FUNCTION__, 0, 0); 1064 goto out; 1065 } 1066 1067 m = (Modifications *) ch_malloc(sizeof(Modifications)); 1068 1069 policy_bv = odusers_copy_dict2bv(accountPolicyDict); 1070 1071 m->sml_op = LDAP_MOD_REPLACE; 1072 m->sml_flags = 0; 1073 m->sml_type = appleAccountPolicyAD->ad_cname; 1074 m->sml_values = (struct berval*) ch_malloc(2 * sizeof(struct berval)); 1075 m->sml_values[0].bv_val = policy_bv->bv_val; 1076 m->sml_values[0].bv_len = policy_bv->bv_len; 1077 m->sml_values[1].bv_val = NULL; 1078 m->sml_values[1].bv_len = 0; 1079 m->sml_nvalues = NULL; 1080 m->sml_numvals = 1; 1081 m->sml_desc = appleAccountPolicyAD; 1082 m->sml_next = fakeop->orm_modlist; 1083 fakeop->orm_modlist = m; 1084 1085 CFRelease(accountPolicyDict); 1086 } 1087 } 1088 1089 CFNumberRef newPasswordRequired = CFDictionaryGetValue(globaldict, CFSTR("newPasswordRequired")); 1090 if(newPasswordRequired) { 1091 const char *text = NULL; 1092 time_t tmptime; 1093 struct tm tmptm; 1094 tmptime = time(NULL); 1095 gmtime_r(&tmptime, &tmptm); 1096 1097 if(!passwordRequiredDateAD && (slap_str2ad("passwordRequiredDate", &passwordRequiredDateAD, &text) != 0)) { 1098 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of uid attribute", __PRETTY_FUNCTION__, 0, 0); 1099 goto out; 1100 } 1101 m = ch_calloc(1, sizeof(Modifications)); 1102 m->sml_op = LDAP_MOD_REPLACE; 1103 m->sml_flags = 0; 1104 m->sml_type = passwordRequiredDateAD->ad_cname; 1105 m->sml_values = (struct berval*) ch_malloc(2 * sizeof(struct berval)); 1106 m->sml_values[0].bv_val = ch_calloc(1, 256); 1107 m->sml_values[0].bv_len = strftime(m->sml_values[0].bv_val, 256, "%Y%m%d%H%M%SZ", &tmptm); 1108 m->sml_values[1].bv_val = NULL; 1109 m->sml_values[1].bv_len = 0; 1110 m->sml_nvalues = NULL; 1111 m->sml_numvals = 1; 1112 m->sml_desc = passwordRequiredDateAD; 1113 m->sml_next = fakeop->orm_modlist; 1114 fakeop->orm_modlist = m; 1115 } 1116 CFRelease(globaldict); 1117 } 1118 } 1119 1120 // Use the frontend DB for the modification so we go through the syncrepl 1121 // overlay and our change gets replicated. 1122 fakeop->o_bd = frontendDB; 1123 1124 slap_op_time(&op->o_time, &op->o_tincr); 1125 1126 fakeop->o_bd->be_modify(fakeop, rs); 1127 if(rs->sr_err != LDAP_SUCCESS) { 1128 Debug(LDAP_DEBUG_ANY, "%s: Unable to modify user policy: %s (%d)\n", __PRETTY_FUNCTION__, fakeop->o_req_ndn.bv_val, rs->sr_err); 1129 goto out; 1130 } 1131 1132 APInvalidateCacheForPolicySet(NULL); 1133 1134 send_ldap_result(op, rs); 1135 return rs->sr_err; 1136 1137out: 1138 return SLAP_CB_CONTINUE; 1139} 1140 1141static int odusers_enforce_admin(Operation *op) { 1142 CFDictionaryRef policy = NULL; 1143 int ret = -1; 1144 1145 if((op->o_conn->c_listener->sl_url.bv_len == strlen("ldapi://%2Fvar%2Frun%2Fldapi")) && (strncmp(op->o_conn->c_listener->sl_url.bv_val, "ldapi://%2Fvar%2Frun%2Fldapi", op->o_conn->c_listener->sl_url.bv_len) == 0)) { 1146 ret = 0; 1147 goto out; 1148 } 1149 1150 policy = odusers_copy_effectiveuserpoldict(&op->o_conn->c_dn); 1151 if(!policy) { 1152 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve effective policy for %s\n", __func__, op->o_conn->c_dn.bv_val, 0); 1153 return SLAP_CB_CONTINUE; 1154 } 1155 if(odusers_isdisabled(policy)) { 1156 Debug(LDAP_DEBUG_ANY, "%s: disabled user tried to set policy", __PRETTY_FUNCTION__, 0, 0); 1157 goto out; 1158 } 1159 if(!odusers_isadmin(policy)) { 1160 Debug(LDAP_DEBUG_ANY, "%s: non-admin user tried to set policy", __PRETTY_FUNCTION__, 0, 0); 1161 goto out; 1162 } 1163 1164 ret = 0; 1165out: 1166 if(policy) CFRelease(policy); 1167 return ret; 1168} 1169 1170static int odusers_rename(Operation *op, SlapReply *rs) { 1171 bool isaccount; 1172 1173 if(!op || op->o_req_ndn.bv_len == 0) return SLAP_CB_CONTINUE; 1174 1175 if(strnstr(op->o_req_ndn.bv_val, "cn=authdata", op->o_req_ndn.bv_len) != NULL) return SLAP_CB_CONTINUE; 1176 1177 isaccount = odusers_isaccount(op); 1178 if(!isaccount) { 1179 return SLAP_CB_CONTINUE; 1180 } 1181 1182 OperationBuffer opbuf = {0}; 1183 Operation *fakeop = NULL; 1184 Connection conn = {0}; 1185 Entry *e = NULL; 1186 const char *text = NULL; 1187 SlapReply rs2 = {REP_RESULT}; 1188 Modifications *m = NULL; 1189 char *newname = NULL; 1190 char *newnameminusdollar = NULL; 1191 char *oldname = NULL; 1192 char *princname = NULL; 1193 char *oldprincname = NULL; 1194 char *realmname = NULL; 1195 1196 OperationBuffer useropbuf = {0}; 1197 Operation *userfakeop = NULL; 1198 Connection userconn = {0}; 1199 Entry *usere = NULL; 1200 SlapReply userrs = {REP_RESULT}; 1201 Modifications *userm = NULL; 1202 Attribute *aas = NULL; 1203 Attribute *altsec = NULL; 1204 Attribute *aliases = NULL; 1205 int i; 1206 Entry *authe = NULL; 1207 AccessControlState acl_state = ACL_STATE_INIT; 1208 1209 realmname = odusers_copy_krbrealm(op); 1210 if(!realmname) { 1211 Debug(LDAP_DEBUG_ANY, "%s: Can't locate kerberos realm", __func__, 0, 0); 1212 goto out; 1213 } 1214 1215 newname = strchr(op->orr_newrdn.bv_val, '='); 1216 if(!newname) { 1217 Debug(LDAP_DEBUG_ANY, "%s: Could not determine new name from %s\n", __func__, op->orr_newrdn.bv_val, 0); 1218 goto out; 1219 } 1220 newname++; 1221 1222 e = odusers_copy_authdata(&op->o_req_ndn); 1223 if(!e) { 1224 Debug(LDAP_DEBUG_ANY, "%s: No entry associated with %s\n", __PRETTY_FUNCTION__, op->o_req_ndn.bv_val, 0); 1225 goto out; 1226 } 1227 1228 oldname = odusers_copy_recname(op); 1229 if(!oldname) { 1230 Debug(LDAP_DEBUG_ANY, "%s: could not find recname of %s\n", __PRETTY_FUNCTION__, op->o_req_ndn.bv_val, 0); 1231 goto out; 1232 } 1233 1234 asprintf(&princname, "%s@%s", newname, realmname); 1235 asprintf(&oldprincname, "%s@%s", oldname, realmname); 1236 1237 if(!uidAD && slap_str2ad("uid", &uidAD, &text) != 0) { 1238 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of uid attribute", __PRETTY_FUNCTION__, 0, 0); 1239 goto out; 1240 } 1241 if(!krbAD && slap_str2ad("KerberosPrincName", &krbAD, &text) != 0) { 1242 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of KerberosPrincName attribute", __PRETTY_FUNCTION__, 0, 0); 1243 goto out; 1244 } 1245 if(!draftkrbAD && slap_str2ad("draft-krbPrincipalName", &draftkrbAD, &text) != 0) { 1246 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of draft-PrincipalName attribute", __PRETTY_FUNCTION__, 0, 0); 1247 goto out; 1248 } 1249 if(!draftkrbAliasesAD && slap_str2ad("draft-krbPrincipalAliases", &draftkrbAliasesAD, &text) != 0) { 1250 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of draft-krbPrincipalAliases attribute", __PRETTY_FUNCTION__, 0, 0); 1251 goto out; 1252 } 1253 if(!aaAD && slap_str2ad("authAuthority", &aaAD, &text) != 0) { 1254 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of authAuthority attribute", __PRETTY_FUNCTION__, 0, 0); 1255 goto out; 1256 } 1257 if(!altsecAD && slap_str2ad("altSecurityIdentities", &altsecAD, &text) != 0) { 1258 Debug(LDAP_DEBUG_ANY, "%s: Unable to retrieve description of altSecurityIdentities attribute", __PRETTY_FUNCTION__, 0, 0); 1259 goto out; 1260 } 1261 1262 connection_fake_init2(&conn, &opbuf, ldap_pvt_thread_pool_context(), 0); 1263 fakeop = &opbuf.ob_op; 1264 fakeop->o_dn = op->o_dn; 1265 fakeop->o_ndn = op->o_ndn; 1266 fakeop->o_req_dn = e->e_name; 1267 fakeop->o_req_ndn = e->e_nname; 1268 fakeop->o_tag = LDAP_REQ_MODIFY; 1269 fakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 1270 fakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 1271 fakeop->o_bd = frontendDB; 1272 fakeop->orm_modlist = m = (Modifications *) ch_malloc(sizeof(Modifications)); 1273 m->sml_op = LDAP_MOD_REPLACE; 1274 m->sml_flags = 0; 1275 m->sml_type = uidAD->ad_cname; 1276 m->sml_values = (struct berval*) ch_malloc(2 * sizeof(struct berval)); 1277 m->sml_values[0].bv_val = ch_strdup(newname); 1278 m->sml_values[0].bv_len = strlen(newname); 1279 m->sml_values[1].bv_val = NULL; 1280 m->sml_values[1].bv_len = 0; 1281 m->sml_numvals = 1; 1282 m->sml_nvalues = NULL; 1283 m->sml_desc = uidAD; 1284 1285 m->sml_next = (Modifications *) ch_malloc(sizeof(Modifications)); 1286 m = m->sml_next; 1287 1288 m->sml_op = LDAP_MOD_REPLACE; 1289 m->sml_flags = 0; 1290 m->sml_type = krbAD->ad_cname; 1291 m->sml_values = (struct berval*) ch_malloc(2 * sizeof(struct berval)); 1292 m->sml_values[0].bv_val = ch_strdup(newname); 1293 m->sml_values[0].bv_len = strlen(newname); 1294 m->sml_values[1].bv_val = NULL; 1295 m->sml_values[1].bv_len = 0; 1296 m->sml_numvals = 1; 1297 m->sml_nvalues = NULL; 1298 m->sml_desc = krbAD; 1299 m->sml_next = (Modifications *) ch_malloc(sizeof(Modifications)); 1300 m = m->sml_next; 1301 1302 m->sml_op = LDAP_MOD_REPLACE; 1303 m->sml_flags = 0; 1304 m->sml_type = draftkrbAD->ad_cname; 1305 m->sml_values = (struct berval*) ch_malloc(2 * sizeof(struct berval)); 1306 m->sml_values[0].bv_val = ch_strdup(princname); 1307 m->sml_values[0].bv_len = strlen(princname); 1308 m->sml_values[1].bv_val = NULL; 1309 m->sml_values[1].bv_len = 0; 1310 m->sml_numvals = 1; 1311 m->sml_nvalues = NULL; 1312 m->sml_desc = draftkrbAD; 1313 m->sml_next = NULL; 1314 1315 1316 // Update user record now 1317 connection_fake_init2(&userconn, &useropbuf, ldap_pvt_thread_pool_context(), 0); 1318 userfakeop = &useropbuf.ob_op; 1319 userfakeop->o_dn = op->o_dn; 1320 userfakeop->o_ndn = op->o_ndn; 1321 userfakeop->o_req_dn = op->o_dn; 1322 userfakeop->o_req_ndn = op->o_ndn; 1323 authe = odusers_copy_entry(userfakeop); 1324 userfakeop->o_req_dn = op->o_req_dn; 1325 userfakeop->o_req_ndn = op->o_req_ndn; 1326 usere = odusers_copy_entry(userfakeop); 1327 if(!usere) { 1328 Debug(LDAP_DEBUG_ANY, "%s: No user entry associated with %s\n", __PRETTY_FUNCTION__, userfakeop->o_req_ndn.bv_val, 0); 1329 goto out; 1330 } 1331 userfakeop->o_bd = frontendDB; 1332 userfakeop->o_tag = LDAP_REQ_MODIFY; 1333 userfakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 1334 userfakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 1335 1336 userfakeop->orm_modlist = userm = (Modifications *) ch_malloc(sizeof(Modifications)); 1337 aas = attrs_find(usere->e_attrs, aaAD); 1338 if(!aas) { 1339 Debug(LDAP_DEBUG_ANY, "%s: User has no authauthorities: %s\n", __func__, userfakeop->o_req_dn.bv_val, 0); 1340 ch_free(userm); 1341 userm = NULL; 1342 goto out; 1343 } 1344 userm->sml_op = LDAP_MOD_REPLACE; 1345 userm->sml_flags = 0; 1346 userm->sml_type = aaAD->ad_cname; 1347 userm->sml_values = (struct berval*) ch_malloc((aas->a_numvals+1) * sizeof(struct berval)); 1348 for(i = 0; i < aas->a_numvals; i++) { 1349 if(strnstr(aas->a_vals[i].bv_val, ";Kerberosv5;", aas->a_vals[i].bv_len) != NULL) { 1350 userm->sml_values[i].bv_len = asprintf(&userm->sml_values[i].bv_val, ";Kerberosv5;;%s@%s;%s;", newname, realmname, realmname); 1351 } else { 1352 ber_dupbv(&userm->sml_values[i], &aas->a_vals[i]); 1353 } 1354 } 1355 userm->sml_values[i].bv_val = NULL; 1356 userm->sml_values[i].bv_len = 0; 1357 userm->sml_numvals = i; 1358 userm->sml_nvalues = NULL; 1359 userm->sml_desc = aaAD; 1360 userm->sml_next = NULL; 1361 1362 altsec = attrs_find(usere->e_attrs, altsecAD); 1363 if(altsec) { 1364 userm->sml_next = (Modifications *) ch_malloc(sizeof(Modifications)); 1365 userm = userm->sml_next; 1366 userm->sml_op = LDAP_MOD_REPLACE; 1367 userm->sml_flags = 0; 1368 userm->sml_type = altsecAD->ad_cname; 1369 userm->sml_values = (struct berval*) ch_malloc((altsec->a_numvals+1) * sizeof(struct berval)); 1370 for(i = 0; i < altsec->a_numvals; i++) { 1371 if(strnstr(altsec->a_vals[i].bv_val, oldprincname, altsec->a_vals[i].bv_len) != NULL) { 1372 userm->sml_values[i].bv_len = asprintf(&userm->sml_values[i].bv_val, "Kerberos:%s", princname); 1373 } else { 1374 ber_dupbv(&userm->sml_values[i], &altsec->a_vals[i]); 1375 } 1376 } 1377 userm->sml_values[i].bv_val = NULL; 1378 userm->sml_values[i].bv_len = 0; 1379 userm->sml_numvals = i; 1380 userm->sml_nvalues = NULL; 1381 userm->sml_desc = altsecAD; 1382 userm->sml_next = NULL; 1383 } 1384 1385 aliases = attrs_find(e->e_attrs, draftkrbAliasesAD); 1386 if(aliases) { 1387 m->sml_next = (Modifications *) ch_malloc(sizeof(Modifications)); 1388 m = m->sml_next; 1389 m->sml_op = LDAP_MOD_DELETE; 1390 m->sml_flags = 0; 1391 m->sml_type = draftkrbAliasesAD->ad_cname; 1392 m->sml_values = (struct berval*) ch_malloc((aliases->a_numvals+1) * sizeof(struct berval)); 1393 for(i = 0; i < aliases->a_numvals; i++) { 1394 ber_dupbv(&m->sml_values[i], &aliases->a_vals[i]); 1395 } 1396 m->sml_values[i].bv_val = NULL; 1397 m->sml_values[i].bv_len = 0; 1398 m->sml_numvals = i; 1399 m->sml_nvalues = NULL; 1400 m->sml_desc = draftkrbAliasesAD; 1401 m->sml_next = NULL; 1402 1403 newnameminusdollar = ch_strdup(newname); 1404 newnameminusdollar[strlen(newnameminusdollar)-1] = '\0'; 1405 1406 m->sml_next = (Modifications *) ch_malloc(sizeof(Modifications)); 1407 m = m->sml_next; 1408 m->sml_op = LDAP_MOD_ADD; 1409 m->sml_flags = 0; 1410 m->sml_type = draftkrbAliasesAD->ad_cname; 1411 m->sml_values = (struct berval*) ch_malloc((aliases->a_numvals+1) * sizeof(struct berval)); 1412 for(i = 0; i < aliases->a_numvals; i++) { 1413 if(strnstr(aliases->a_vals[i].bv_val, "/", aliases->a_vals[i].bv_len) != NULL) { 1414 char *tmpstr = ch_calloc(1, aliases->a_vals[i].bv_len+1); 1415 memcpy(tmpstr, aliases->a_vals[i].bv_val, aliases->a_vals[i].bv_len); 1416 char *freeme = strsep(&tmpstr, "/"); 1417 m->sml_values[i].bv_len = asprintf(&m->sml_values[i].bv_val, "%s/%s@%s", freeme, newnameminusdollar, realmname); 1418 ch_free(freeme); 1419 } else { 1420 ber_dupbv(&m->sml_values[i], &aliases->a_vals[i]); 1421 } 1422 } 1423 ch_free(newnameminusdollar); 1424 m->sml_values[i].bv_val = NULL; 1425 m->sml_values[i].bv_len = 0; 1426 m->sml_numvals = i; 1427 m->sml_nvalues = NULL; 1428 m->sml_desc = draftkrbAliasesAD; 1429 m->sml_next = NULL; 1430 } 1431 1432 bool isldapi = false; 1433 if((op->o_conn->c_listener->sl_url.bv_len == strlen("ldapi://%2Fvar%2Frun%2Fldapi")) && (strncmp(op->o_conn->c_listener->sl_url.bv_val, "ldapi://%2Fvar%2Frun%2Fldapi", op->o_conn->c_listener->sl_url.bv_len) == 0)) { 1434 isldapi = true; 1435 } 1436 1437 if(!isldapi) { 1438 if(!authe) { 1439 Debug(LDAP_DEBUG_ANY, "%s: rename of %s attempted by unauthed user", __func__, userfakeop->o_req_ndn.bv_val, 0); 1440 goto out; 1441 } 1442 1443 BackendDB *tmpbd = op->o_bd; 1444 op->o_bd = select_backend(&op->o_req_ndn, 1); 1445 userrs.sr_err = access_allowed(op, authe, slap_schema.si_ad_entry, &op->o_req_ndn, ACL_WRITE, &acl_state); 1446 op->o_bd = tmpbd; 1447 if(!userrs.sr_err) { 1448 Debug(LDAP_DEBUG_ANY, "%s: access denied renaming %s: %d\n", __func__, userfakeop->o_req_ndn.bv_val, userrs.sr_err); 1449 goto out; 1450 } 1451 } 1452 1453 // Actually do the updates 1454 userfakeop->o_bd->be_modify(userfakeop, &userrs); 1455 if(userrs.sr_err != LDAP_SUCCESS) { 1456 Debug(LDAP_DEBUG_ANY, "Unable to rename userdata for user %s: %d %s\n", userfakeop->o_req_ndn.bv_val, userrs.sr_err, userrs.sr_text); 1457 goto out; 1458 } 1459 1460 fakeop->o_bd->be_modify(fakeop, &rs2); 1461 if(rs2.sr_err != LDAP_SUCCESS) { 1462 Debug(LDAP_DEBUG_ANY, "Unable to rename authdata for user %s: %d %s\n", fakeop->o_req_ndn.bv_val, rs2.sr_err, rs2.sr_text); 1463 goto out; 1464 } 1465 1466out: 1467 if(e) entry_free(e); 1468 if(usere) entry_free(usere); 1469// if(authe) entry_free(authe); 1470 if(m) slap_mods_free(fakeop->orm_modlist, 1); 1471 if(userm) slap_mods_free(userfakeop->orm_modlist, 1); 1472 ch_free(realmname); 1473 free(princname); 1474 free(oldprincname); 1475 ch_free(oldname); 1476 1477 return SLAP_CB_CONTINUE; 1478} 1479 1480static int odusers_modify(Operation *op, SlapReply *rs) { 1481 bool isaccount; 1482 Modifications *m; 1483 1484 if(!op || op->o_req_ndn.bv_len == 0) return SLAP_CB_CONTINUE; 1485 1486 if(strnstr(op->o_req_ndn.bv_val, "cn=authdata", op->o_req_ndn.bv_len) != NULL) return SLAP_CB_CONTINUE; 1487 1488 m = op->orm_modlist; 1489 if(!m) return SLAP_CB_CONTINUE; 1490 1491 isaccount = odusers_isaccount(op); 1492 1493 // setpolicy will only work on a replacement basis, if we support 1494 // non-setpolicy modifys this needs to become policy specific. 1495 if((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE) return SLAP_CB_CONTINUE; 1496 1497 if(isaccount && strncmp(m->sml_desc->ad_cname.bv_val, "apple-user-passwordpolicy", m->sml_desc->ad_cname.bv_len) == 0) { 1498 if(odusers_enforce_admin(op) != 0) { 1499 Debug(LDAP_DEBUG_ANY, "%s: no admin privs while attempting policy modification for %s\n", __func__, op->o_req_ndn.bv_val, 0); 1500 send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS, "policy modification not permitted"); 1501 return rs->sr_err; 1502 } 1503 1504 return odusers_modify_userpolicy(op, rs); 1505 } else if(isaccount && (strncmp(m->sml_desc->ad_cname.bv_val, "draft-krbPrincipalAliases", m->sml_desc->ad_cname.bv_len) == 0 || 1506 strncmp(m->sml_desc->ad_cname.bv_val, "apple-accountpolicy", m->sml_desc->ad_cname.bv_len) == 0)) { 1507 if((odusers_enforce_admin(op) != 0) && (ber_bvcmp(&op->o_ndn, &op->o_req_ndn) != 0)) { 1508 send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS, "No access"); 1509 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 1510 return rs->sr_err; 1511 } 1512 1513 return odusers_modify_bridge_authdata(op, rs); 1514 } else if(!isaccount && (strncmp(op->o_req_ndn.bv_val, kDirservConfigName, strlen(kDirservConfigName)) == 0) 1515 && (strncmp(m->sml_desc->ad_cname.bv_val, "apple-user-passwordpolicy", m->sml_desc->ad_cname.bv_len) == 0 || 1516 strncmp(m->sml_desc->ad_cname.bv_val, "apple-accountpolicy", m->sml_desc->ad_cname.bv_len) == 0)) { 1517 if(odusers_enforce_admin(op) != 0) { 1518 Debug(LDAP_DEBUG_ANY, "%s: no admin privs while attempting global policy modification\n", __func__, 0, 0); 1519 send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS, "global policy modification not permitted"); 1520 return rs->sr_err; 1521 } 1522 1523 return odusers_modify_globalpolicy(op, rs); 1524 } 1525 1526 return SLAP_CB_CONTINUE; 1527} 1528 1529/* Returns a newly allocated copy of the pws pubkey attribute. 1530 * Caller is responsible for free()'ing the returned result. 1531 */ 1532static char *odusers_copy_pwspubkey(Operation *op) { 1533 OperationBuffer opbuf = {0}; 1534 Operation *fakeop = NULL; 1535 Connection conn = {0}; 1536 Entry *e = NULL; 1537 Attribute *a = NULL; 1538 AttributeDescription *pubkeyAD = NULL; 1539 const char *text = NULL; 1540 static char *savedkey = NULL; 1541 char *ret = NULL; 1542 1543 if(savedkey) { 1544 return ch_strdup(savedkey); 1545 } 1546 1547 connection_fake_init2(&conn, &opbuf, ldap_pvt_thread_pool_context(), 0); 1548 fakeop = &opbuf.ob_op; 1549 fakeop->o_dn = op->o_dn; 1550 fakeop->o_ndn = op->o_ndn; 1551 fakeop->o_req_dn.bv_len = strlen("cn=authdata"); 1552 fakeop->o_req_dn.bv_val = "cn=authdata"; 1553 fakeop->o_req_ndn = fakeop->o_req_dn; 1554 fakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 1555 fakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 1556 1557 e = odusers_copy_entry(fakeop); 1558 if(!e) { 1559 Debug(LDAP_DEBUG_TRACE, "%s: No entry associated with cn=authdata\n", __func__, 0, 0); 1560 goto out; 1561 } 1562 1563 if(slap_str2ad("PWSPublicKey", &pubkeyAD, &text) != 0) { 1564 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for authGUID", __func__, 0, 0); 1565 goto out; 1566 } 1567 1568 a = attr_find(e->e_attrs, pubkeyAD); 1569 if(!a) { 1570 Debug(LDAP_DEBUG_ANY, "%s: Could not locate PWSPublicKey attribute", __func__, 0, 0); 1571 goto out; 1572 } 1573 1574 ret = ch_calloc(1, a->a_vals[0].bv_len + 1); 1575 if(!ret) goto out; 1576 memcpy(ret, a->a_vals[0].bv_val, a->a_vals[0].bv_len); 1577 savedkey = ch_strdup(ret); 1578 1579out: 1580 if(e) entry_free(e); 1581 return ret; 1582} 1583 1584/* takes a uuid and converts it to PWS slot representation of 1585 * 0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 1586 * appending a NUL byte. 1587 * Caller is responsible for allocation of string. 1588 */ 1589static void odusers_uuid_to_pwsslot(uuid_t uuid, char *string) { 1590 char uuidstr[37]; 1591 int i, n; 1592 1593 uuidstr[sizeof(uuidstr)-1] = '\0'; 1594 uuid_unparse_lower(uuid, uuidstr); 1595 string[0] = '0'; 1596 string[1] = 'x'; 1597 for(i = 0, n = 2; n < 34 && i < 36; i++) { 1598 if( uuidstr[i] != '-' ) { 1599 string[n] = uuidstr[i]; 1600 n++; 1601 } 1602 } 1603 string[n] = '\0'; 1604 return; 1605} 1606 1607static int odusers_add_authdata(Operation *op, SlapReply *rs, uuid_t newuuid) { 1608 OperationBuffer opbuf = {0}; 1609 Operation *fakeop = NULL; 1610 Connection conn = {0}; 1611 Entry *e = NULL; 1612 Attribute *a = NULL; 1613 Attribute *attriter = NULL; 1614 Attribute *entryUUID = NULL; 1615 AttributeDescription *authGUIDAD = NULL; 1616 AttributeDescription *objectClassAD = NULL; 1617 const char *text = NULL; 1618 uuid_string_t uuidstr; 1619 SlapReply rs2 = {REP_RESULT}; 1620 char *authauthority = NULL; 1621 char slotid[37]; 1622 char *recname = NULL; 1623 char *realm = NULL; 1624 bool iscomputer = false; 1625 1626 uuid_unparse_lower(newuuid, uuidstr); 1627 1628 recname = odusers_copy_recname(op); 1629 if(!recname) { 1630 Debug(LDAP_DEBUG_ANY, "%s: Could not determine record name", __func__, 0, 0); 1631 goto out; 1632 } 1633 1634 if(strnstr(op->o_req_dn.bv_val, "cn=computer", op->o_req_dn.bv_len) != NULL) { 1635 iscomputer = true; 1636 } 1637 1638 realm = odusers_copy_krbrealm(op); 1639 1640 connection_fake_init2(&conn, &opbuf, ldap_pvt_thread_pool_context(), 0); 1641 fakeop = &opbuf.ob_op; 1642 fakeop->o_dn = op->o_dn; 1643 fakeop->o_ndn = op->o_ndn; 1644 fakeop->o_req_dn.bv_len = asprintf(&fakeop->o_req_dn.bv_val, "authGUID=%s,cn=users,cn=authdata", uuidstr); 1645 fakeop->o_req_ndn = fakeop->o_req_dn; 1646 fakeop->o_tag = LDAP_REQ_ADD; 1647 fakeop->o_conn->c_listener->sl_url.bv_val = "ldapi://%2Fvar%2Frun%2Fldapi"; 1648 fakeop->o_conn->c_listener->sl_url.bv_len = strlen("ldapi://%2Fvar%2Frun%2Fldapi"); 1649 1650 if(slap_str2ad("authGUID", &authGUIDAD, &text) != 0) { 1651 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for authGUID", __func__, 0, 0); 1652 goto out; 1653 } 1654 if(slap_str2ad("objectClass", &objectClassAD, &text) != 0) { 1655 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for objectClass", __func__, 0, 0); 1656 goto out; 1657 } 1658 1659 a = attr_alloc(authGUIDAD); 1660 if(!a) goto out; 1661 a->a_vals = ch_calloc(2, sizeof(struct berval)); 1662 if(!a->a_vals) goto out; 1663 a->a_vals[0].bv_len = strlen(uuidstr); 1664 a->a_vals[0].bv_val = ch_calloc(1, a->a_vals[0].bv_len+1); 1665 strncpy(a->a_vals[0].bv_val, uuidstr, a->a_vals[0].bv_len); 1666 a->a_nvals = a->a_vals; 1667 a->a_numvals = 1; 1668 1669 a->a_next = attr_alloc(objectClassAD); 1670 if(!a->a_next) goto out; 1671 attriter = a->a_next; 1672 attriter->a_vals = ch_calloc(2, sizeof(struct berval)); 1673 if(!attriter->a_vals) goto out; 1674 attriter->a_vals[0].bv_len = strlen("pwsAuthdata"); 1675 attriter->a_vals[0].bv_val = ch_strdup("pwsAuthdata"); 1676 attriter->a_nvals = attriter->a_vals; 1677 attriter->a_numvals = 1; 1678 1679 if(recname) { 1680 AttributeDescription *uidAD = NULL; 1681 if(slap_str2ad("uid", &uidAD, &text) != 0) { 1682 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for uid", __func__, 0, 0); 1683 goto out; 1684 } 1685 attriter->a_next = attr_alloc(uidAD); 1686 if(!attriter->a_next) goto out; 1687 attriter = attriter->a_next; 1688 attriter->a_vals = ch_calloc(2, sizeof(struct berval)); 1689 if(!attriter->a_vals) goto out; 1690 attriter->a_vals[0].bv_len = strlen(recname); 1691 attriter->a_vals[0].bv_val = ch_strdup(recname); 1692 attriter->a_nvals = attriter->a_vals; 1693 attriter->a_numvals = 1; 1694 1695 AttributeDescription *princnameAD = NULL; 1696 if(slap_str2ad("KerberosPrincName", &princnameAD, &text) != 0) { 1697 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for KerberosPrincName", __func__, 0, 0); 1698 goto out; 1699 } 1700 attriter->a_next = attr_alloc(princnameAD); 1701 if(!attriter->a_next) goto out; 1702 attriter = attriter->a_next; 1703 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1704 if(!attriter->a_vals) goto out; 1705 attriter->a_vals[0].bv_len = strlen(recname); 1706 attriter->a_vals[0].bv_val = ch_strdup(recname); 1707 attriter->a_vals[1].bv_len = 0; 1708 attriter->a_vals[1].bv_val = NULL; 1709 attriter->a_nvals = attriter->a_vals; 1710 attriter->a_numvals = 1; 1711 attriter->a_flags = 0; 1712 } 1713 1714 AttributeDescription *creationDateAD = NULL; 1715 struct tm tmtime; 1716 time_t now; 1717 if(slap_str2ad("creationDate", &creationDateAD, &text) != 0) { 1718 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for creationDate", __func__, 0, 0); 1719 goto out; 1720 } 1721 now = time(NULL); 1722 gmtime_r(&now, &tmtime); 1723 attriter->a_next = attr_alloc(creationDateAD); 1724 if(!attriter->a_next) goto out; 1725 attriter = attriter->a_next; 1726 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1727 if(!attriter->a_vals) goto out; 1728 attriter->a_vals[0].bv_val = ch_calloc(1, 256); 1729 attriter->a_vals[0].bv_len = strftime(attriter->a_vals[0].bv_val, 256, "%Y%m%d%H%M%SZ", &tmtime); 1730 attriter->a_vals[1].bv_len = 0; 1731 attriter->a_vals[1].bv_val = NULL; 1732 attriter->a_nvals = attriter->a_vals; 1733 attriter->a_numvals = 1; 1734 attriter->a_flags = 0; 1735 1736 AttributeDescription *disablereasonAD = NULL; 1737 if(slap_str2ad("disableReason", &disablereasonAD, &text) != 0) { 1738 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for disableReason", __func__, 0, 0); 1739 goto out; 1740 } 1741 attriter->a_next = attr_alloc(disablereasonAD); 1742 if(!attriter->a_next) goto out; 1743 attriter = attriter->a_next; 1744 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1745 if(!attriter->a_vals) goto out; 1746 attriter->a_vals[0].bv_len = strlen("none"); 1747 attriter->a_vals[0].bv_val = ch_strdup("none"); 1748 attriter->a_vals[1].bv_len = 0; 1749 attriter->a_vals[1].bv_val = NULL; 1750 attriter->a_nvals = attriter->a_vals; 1751 attriter->a_numvals = 1; 1752 attriter->a_flags = 0; 1753 1754 AttributeDescription *adminGroupsAD = NULL; 1755 if(slap_str2ad("adminGroups", &adminGroupsAD, &text) != 0) { 1756 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for adminGroups", __func__, 0, 0); 1757 goto out; 1758 } 1759 attriter->a_next = attr_alloc(adminGroupsAD); 1760 if(!attriter->a_next) goto out; 1761 attriter = attriter->a_next; 1762 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1763 if(!attriter->a_vals) goto out; 1764 attriter->a_vals[0].bv_len = strlen("unrestricted"); 1765 attriter->a_vals[0].bv_val = ch_strdup("unrestricted"); 1766 attriter->a_vals[1].bv_len = 0; 1767 attriter->a_vals[1].bv_val = NULL; 1768 attriter->a_nvals = attriter->a_vals; 1769 attriter->a_numvals = 1; 1770 attriter->a_flags = 0; 1771 1772 AttributeDescription *failedLoginAD = NULL; 1773 if(slap_str2ad("loginFailedAttempts", &failedLoginAD, &text) != 0) { 1774 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for loginFailedAttempts", __func__, 0, 0); 1775 goto out; 1776 } 1777 attriter->a_next = attr_alloc(failedLoginAD); 1778 if(!attriter->a_next) goto out; 1779 attriter = attriter->a_next; 1780 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1781 if(!attriter->a_vals) goto out; 1782 attriter->a_vals[0].bv_len = strlen("0"); 1783 attriter->a_vals[0].bv_val = ch_strdup("0"); 1784 attriter->a_vals[1].bv_len = 0; 1785 attriter->a_vals[1].bv_val = NULL; 1786 attriter->a_nvals = attriter->a_vals; 1787 attriter->a_numvals = 1; 1788 attriter->a_flags = 0; 1789 1790 entryUUID = attr_find( op->ora_e->e_attrs, slap_schema.si_ad_entryUUID ); 1791 if(!entryUUID) { 1792 Debug(LDAP_DEBUG_ANY, "%s: couldn't find entryUUID attribute in copy of %s", __func__, op->o_req_ndn.bv_val, 0); 1793 goto out; 1794 } 1795 1796 AttributeDescription *userLinkAD = NULL; 1797 if(slap_str2ad("userLinkage", &userLinkAD, &text) != 0) { 1798 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for userLinkage", __func__, 0, 0); 1799 goto out; 1800 } 1801 attriter->a_next = attr_alloc(userLinkAD); 1802 if(!attriter->a_next) goto out; 1803 attriter = attriter->a_next; 1804 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1805 if(!attriter->a_vals) goto out; 1806 attriter->a_vals[0].bv_len = entryUUID->a_vals[0].bv_len; 1807 attriter->a_vals[0].bv_val = ch_malloc(entryUUID->a_vals[0].bv_len+1); 1808 memcpy(attriter->a_vals[0].bv_val, entryUUID->a_vals[0].bv_val, entryUUID->a_vals[0].bv_len); 1809 attriter->a_vals[0].bv_val[entryUUID->a_vals[0].bv_len] = '\0'; 1810 attriter->a_vals[1].bv_len = 0; 1811 attriter->a_vals[1].bv_val = NULL; 1812 attriter->a_nvals = attriter->a_vals; 1813 attriter->a_numvals = 1; 1814 attriter->a_flags = 0; 1815 1816 if(realm) { 1817 AttributeDescription *draftNameAD = NULL; 1818 if(slap_str2ad("draft-krbPrincipalName", &draftNameAD, &text) != 0) { 1819 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for draft-krbPrincipalName", __func__, 0, 0); 1820 goto out; 1821 } 1822 attriter->a_next = attr_alloc(draftNameAD); 1823 if(!attriter->a_next) goto out; 1824 attriter = attriter->a_next; 1825 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1826 if(!attriter->a_vals) goto out; 1827 char *principalName = NULL; 1828 asprintf(&principalName, "%s@%s", recname, realm); 1829 ber_str2bv(principalName, strlen(principalName), 1, &attriter->a_vals[0]); 1830 free(principalName); 1831 attriter->a_vals[1].bv_len = 0; 1832 attriter->a_vals[1].bv_val = NULL; 1833 attriter->a_nvals = attriter->a_vals; 1834 attriter->a_numvals = 1; 1835 attriter->a_flags = 0; 1836 1837 AttributeDescription *draftPolicyAD = NULL; 1838 if(slap_str2ad("draft-krbTicketPolicy", &draftPolicyAD, &text) != 0) { 1839 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for draft-krbTicketPolicy", __func__, 0, 0); 1840 goto out; 1841 } 1842 attriter->a_next = attr_alloc(draftPolicyAD); 1843 if(!attriter->a_next) goto out; 1844 attriter = attriter->a_next; 1845 attriter->a_vals = ch_malloc(2 * sizeof(struct berval)); 1846 if(!attriter->a_vals) goto out; 1847 if(iscomputer) { 1848 attriter->a_vals[0].bv_len = strlen("358"); 1849 attriter->a_vals[0].bv_val = ch_strdup("358"); 1850 } else { 1851 attriter->a_vals[0].bv_len = strlen("326"); 1852 attriter->a_vals[0].bv_val = ch_strdup("326"); 1853 } 1854 attriter->a_vals[1].bv_len = 0; 1855 attriter->a_vals[1].bv_val = NULL; 1856 attriter->a_nvals = attriter->a_vals; 1857 attriter->a_numvals = 1; 1858 attriter->a_flags = 0; 1859 } 1860 attriter->a_next = NULL; 1861 1862 e = entry_alloc(); 1863 e->e_id = NOID; 1864 ber_dupbv(&e->e_name, &fakeop->o_req_dn); 1865 ber_dupbv(&e->e_nname, &fakeop->o_req_ndn); 1866 e->e_attrs = a; 1867 1868 fakeop->ora_e = e; 1869 fakeop->o_bd = select_backend(&fakeop->o_req_ndn, 1); 1870 if(!fakeop->o_bd) { 1871 Debug(LDAP_DEBUG_ANY, "%s: could not locate backend for %s", __func__, fakeop->o_req_ndn.bv_val, 0); 1872 goto out; 1873 } 1874 1875 fakeop->o_bd->be_add(fakeop, &rs2); 1876 1877out: 1878// if (e) entry_free(e); 1879 if(fakeop && fakeop->o_req_dn.bv_val) free(fakeop->o_req_dn.bv_val); 1880 ch_free(realm); 1881 ch_free(recname); 1882 1883 return 0; 1884} 1885 1886/* Add auth authorities and altsecurityidentities to a new user record request*/ 1887static int odusers_add_aa(Operation *op, SlapReply *rs, uuid_t newuuid) { 1888 Attribute *attriter = NULL; 1889 Attribute *newAA = NULL; 1890 AttributeDescription *authAuthorityAD = NULL; 1891 const char *text = NULL; 1892 uuid_string_t uuidstr; 1893 char *pubkey = NULL; 1894 char *authauthority = NULL; 1895 char slotid[37]; 1896 char *recname = NULL; 1897 char *realm = NULL; 1898 char *primary_master_ip = NULL; 1899 bool iscomputer = false; 1900 1901 recname = odusers_copy_recname(op); 1902 if(!recname) { 1903 Debug(LDAP_DEBUG_ANY, "%s: Could not determine record name", __func__, 0, 0); 1904 goto out; 1905 } 1906 1907 if(strnstr(op->o_req_dn.bv_val, "cn=computer", op->o_req_dn.bv_len) != NULL) { 1908 iscomputer = true; 1909 } 1910 1911 realm = odusers_copy_krbrealm(op); 1912 1913 pubkey = odusers_copy_pwspubkey(op); 1914 if(!pubkey) { 1915 Debug(LDAP_DEBUG_ANY, "%s: could not locate PWS public key", __func__, 0, 0); 1916 goto out; 1917 } 1918 1919 primary_master_ip = odusers_copy_primarymasterip(op); 1920 if(!primary_master_ip) { 1921 Debug(LDAP_DEBUG_ANY, "%s: could not locate Primary Master's IP address; trying System Configuration", __func__, 0, 0); 1922 primary_master_ip = CopyPrimaryIPv4Address(); 1923 if (!primary_master_ip) { 1924 Debug(LDAP_DEBUG_ANY, "%s: could not locate IP address in System Configuration; using 127.0.0.1 in the auth authority", __func__, 0, 0); 1925 primary_master_ip = ch_strdup("127.0.0.1"); 1926 } 1927 } 1928 1929 odusers_uuid_to_pwsslot(newuuid, slotid); 1930 1931 authAuthorityAD = slap_schema.si_ad_authAuthority; 1932 newAA = attr_alloc(authAuthorityAD); 1933 if(!newAA) goto out; 1934 attriter = newAA; 1935 attriter->a_vals = ch_malloc(3 *sizeof(struct berval)); 1936 if(!attriter->a_vals) goto out; 1937 if(pubkey[strlen(pubkey)-1] == '\n') { 1938 pubkey[strlen(pubkey)-1] = '\0'; // strip of trailing newline 1939 } 1940 char *pws_authAuthority = NULL; 1941 char *krb5_authAuthority = NULL; 1942 asprintf(&pws_authAuthority, ";ApplePasswordServer;%s,%s:%s", slotid, pubkey, primary_master_ip); 1943 ber_str2bv(pws_authAuthority, strlen(pws_authAuthority), 1, &attriter->a_vals[0]); 1944 free(pws_authAuthority); 1945 asprintf(&krb5_authAuthority, ";Kerberosv5;;%s@%s;%s;", recname, realm, realm); 1946 ber_str2bv(krb5_authAuthority, strlen(krb5_authAuthority), 1, &attriter->a_vals[1]); 1947 free(krb5_authAuthority); 1948 1949 attriter->a_vals[2].bv_len = 0; 1950 attriter->a_vals[2].bv_val = NULL; 1951 attriter->a_nvals = attriter->a_vals; 1952 attriter->a_numvals = 2; 1953 attriter->a_flags = 0; 1954 1955 if(!iscomputer) { 1956 AttributeDescription *altSecAD = NULL; 1957 if(slap_str2ad("altSecurityIdentities", &altSecAD, &text) != 0) { 1958 Debug(LDAP_DEBUG_ANY, "%s: slap_str2ad failed for altSecurityIdentities", __func__, 0, 0); 1959 goto out; 1960 } 1961 attriter->a_next = attr_alloc(altSecAD); 1962 attriter = attriter->a_next; 1963 if(!attriter) goto out; 1964 attriter->a_vals = ch_malloc(2 *sizeof(struct berval)); 1965 if(!attriter->a_vals) goto out; 1966 char * altSecurityIdentities = NULL; 1967 asprintf(&altSecurityIdentities, "Kerberos:%s@%s", recname, realm); 1968 ber_str2bv(altSecurityIdentities, strlen(altSecurityIdentities), 1, &attriter->a_vals[0]); 1969 free(altSecurityIdentities); 1970 attriter->a_vals[1].bv_len = 0; 1971 attriter->a_vals[1].bv_val = NULL; 1972 attriter->a_nvals = attriter->a_vals; 1973 attriter->a_numvals = 1; 1974 attriter->a_flags = 0; 1975 } 1976 attriter->a_next = NULL; 1977 1978 for(attriter = op->ora_e->e_attrs; attriter->a_next; attriter = attriter->a_next); 1979 attriter->a_next = newAA; 1980 1981out: 1982 ch_free(realm); 1983 ch_free(recname); 1984 ch_free(pubkey); 1985 ch_free(primary_master_ip); 1986 1987 return 0; 1988} 1989 1990static int odusers_add(Operation *op, SlapReply *rs) { 1991 bool isaccount; 1992 Modifications *m; 1993 1994 if(!op || op->o_req_ndn.bv_len == 0) return SLAP_CB_CONTINUE; 1995 if(strnstr(op->o_req_ndn.bv_val, "cn=authdata", op->o_req_ndn.bv_len) != NULL) return SLAP_CB_CONTINUE; 1996 1997 m = op->orm_modlist; 1998 if(!m) return SLAP_CB_CONTINUE; 1999 2000 isaccount = odusers_isaccount(op); 2001 2002 if(isaccount) { 2003 OpExtraOD *oe = NULL; 2004 2005 oe = calloc(1, sizeof(OpExtraOD)); 2006 if(!oe) return SLAP_CB_CONTINUE; 2007 oe->oe.oe_key = ODUSERS_EXTRA_KEY; 2008 uuid_generate_time(oe->uuid); 2009 LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oe->oe, oe_next); 2010 2011 odusers_add_aa(op, rs, oe->uuid); 2012 } 2013 2014 return SLAP_CB_CONTINUE; 2015} 2016 2017int odusers_initialize() { 2018 int rc = 0; 2019 2020 memset(&odusers, 0, sizeof(slap_overinst)); 2021 2022 odusers.on_bi.bi_type = "odusers"; 2023 odusers.on_bi.bi_cf_ocs = odocs; 2024 odusers.on_bi.bi_op_delete = odusers_delete; 2025 odusers.on_bi.bi_op_search = odusers_search; 2026 odusers.on_bi.bi_op_modify = odusers_modify; 2027 odusers.on_bi.bi_op_add = odusers_add; 2028 odusers.on_bi.bi_op_modrdn = odusers_rename; 2029 odusers.on_response = odusers_response; 2030 2031 rc = config_register_schema(odcfg, odocs); 2032 if(rc) return rc; 2033 2034 return overlay_register(&odusers); 2035} 2036 2037#if SLAPD_OVER_ODUSERS == SLAPD_MOD_DYNAMIC 2038int 2039init_module( int argc, char *argv[] ) 2040{ 2041 return odusers_initialize(); 2042} 2043#endif 2044 2045#endif /* SLAPD_OVER_ODUSERS */ 2046