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