1 #!/usr/bin/env smbscript
3 (C) Jelmer Vernooij <jelmer@samba.org> 2005
4 (C) Martin Kuehl <mkhl@samba.org> 2006
5 Published under the GNU GPL
6 Sponsored by Google Summer of Code
10 var options = GetOptions(ARGV, "POPT_AUTOHELP", "POPT_COMMON_SAMBA");
11 if (options == undefined) {
12 println("Failed to parse options");
16 libinclude("base.js");
18 if (options.ARGV.length != 2) {
19 println("Usage: samba3sam.js <TESTDIR> <DATADIR>");
23 var prefix = options.ARGV[0];
24 var datadir = options.ARGV[1];
26 function setup_data(obj, ldif)
28 assert(ldif != undefined);
29 ldif = substitute_var(ldif, obj);
30 assert(ldif != undefined);
31 var ok = obj.db.add(ldif);
32 assert(ok.error == 0);
35 function setup_modules(ldb, s3, s4, ldif)
37 assert(ldif != undefined);
38 ldif = substitute_var(ldif, s4);
39 assert(ldif != undefined);
40 var ok = ldb.add(ldif);
41 assert(ok.error == 0);
45 @FROM: " + s4.BASEDN + "
46 @TO: sambaDomainName=TESTS," + s3.BASEDN + "
49 @LIST: rootdse,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,partition
52 partition: " + s4.BASEDN + ":" + s4.url + "
53 partition: " + s3.BASEDN + ":" + s3.url + "
54 replicateEntries: @SUBCLASSES
55 replicateEntries: @ATTRIBUTES
56 replicateEntries: @INDEXLIST
58 var ok = ldb.add(ldif);
59 assert(ok.error == 0);
62 function test_s3sam_search(ldb)
64 println("Looking up by non-mapped attribute");
65 var msg = ldb.search("(cn=Administrator)");
66 assert(msg.error == 0);
67 assert(msg.msgs.length == 1);
68 assert(msg.msgs[0].cn == "Administrator");
70 println("Looking up by mapped attribute");
71 var msg = ldb.search("(name=Backup Operators)");
72 assert(msg.error == 0);
73 assert(msg.msgs.length == 1);
74 assert(msg.msgs[0].name == "Backup Operators");
76 println("Looking up by old name of renamed attribute");
77 var msg = ldb.search("(displayName=Backup Operators)");
78 assert(msg.msgs.length == 0);
80 println("Looking up mapped entry containing SID");
81 var msg = ldb.search("(cn=Replicator)");
82 assert(msg.error == 0);
83 assert(msg.msgs.length == 1);
84 println(msg.msgs[0].dn);
85 assert(msg.msgs[0].dn == "cn=Replicator,ou=Groups,dc=vernstok,dc=nl");
86 assert(msg.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
88 println("Checking mapping of objectClass");
89 var oc = msg.msgs[0].objectClass;
90 assert(oc != undefined);
92 assert(oc[i] == "posixGroup" || oc[i] == "group");
95 println("Looking up by objectClass");
96 var msg = ldb.search("(|(objectClass=user)(cn=Administrator))");
97 assert(msg.error == 0);
98 assert(msg.msgs.length == 2);
99 for (var i = 0; i < msg.msgs.length; i++) {
100 assert((msg.msgs[i].dn == "unixName=Administrator,ou=Users,dc=vernstok,dc=nl") ||
101 (msg.msgs[i].dn == "unixName=nobody,ou=Users,dc=vernstok,dc=nl"));
105 function test_s3sam_modify(ldb, s3)
108 println("Adding a record that will be fallbacked");
114 showInAdvancedViewOnly: TRUE
118 assert(ok.error == 0);
121 println("Checking for existence of record (local)");
122 /* TODO: This record must be searched in the local database, which is currently only supported for base searches
123 * msg = ldb.search("(cn=Foo)", new Array('foo','blah','cn','showInAdvancedViewOnly'));
124 * TODO: Actually, this version should work as well but doesn't...
127 var attrs = new Array('foo','blah','cn','showInAdvancedViewOnly');
128 msg = ldb.search("(cn=Foo)", "cn=Foo", ldb.LDB_SCOPE_BASE, attrs);
129 assert(msg.error == 0);
130 assert(msg.msgs.length == 1);
131 assert(msg.msgs[0].showInAdvancedViewOnly == "TRUE");
132 assert(msg.msgs[0].foo == "bar");
133 assert(msg.msgs[0].blah == "Blie");
135 println("Adding record that will be mapped");
137 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
140 sambaUnicodePwd: geheim
145 assert(ok.error == 0);
147 assert(ok.error == 0);
149 println("Checking for existence of record (remote)");
150 msg = ldb.search("(unixName=bin)", new Array('unixName','cn','dn', 'sambaUnicodePwd'));
151 assert(msg.error == 0);
152 assert(msg.msgs.length == 1);
153 assert(msg.msgs[0].cn == "Niemand");
154 assert(msg.msgs[0].sambaUnicodePwd == "geheim");
156 println("Checking for existence of record (local && remote)");
157 msg = ldb.search("(&(unixName=bin)(sambaUnicodePwd=geheim))", new Array('unixName','cn','dn', 'sambaUnicodePwd'));
158 assert(msg.error == 0);
159 assert(msg.msgs.length == 1); // TODO: should check with more records
160 assert(msg.msgs[0].cn == "Niemand");
161 assert(msg.msgs[0].unixName == "bin");
162 assert(msg.msgs[0].sambaUnicodePwd == "geheim");
164 println("Checking for existence of record (local || remote)");
165 msg = ldb.search("(|(unixName=bin)(sambaUnicodePwd=geheim))", new Array('unixName','cn','dn', 'sambaUnicodePwd'));
166 println("got " + msg.msgs.length + " replies");
167 assert(msg.error == 0);
168 assert(msg.msgs.length == 1); // TODO: should check with more records
169 assert(msg.msgs[0].cn == "Niemand");
170 assert(msg.msgs[0].unixName == "bin" || msg.msgs[0].sambaUnicodePwd == "geheim");
172 println("Checking for data in destination database");
173 msg = s3.db.search("(cn=Niemand)");
174 assert(msg.error == 0);
175 assert(msg.msgs.length >= 1);
176 assert(msg.msgs[0].sambaSID == "S-1-5-21-4231626423-2410014848-2360679739-2001");
177 assert(msg.msgs[0].displayName == "Niemand");
179 println("Adding attribute...");
181 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
188 assert(ok.error == 0);
190 assert(ok.error == 0);
192 println("Checking whether changes are still there...");
193 msg = ldb.search("(cn=Niemand)");
194 assert(msg.error == 0);
195 assert(msg.msgs.length >= 1);
196 assert(msg.msgs[0].cn == "Niemand");
197 assert(msg.msgs[0].description == "Blah");
199 println("Modifying attribute...");
201 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
208 assert(ok.error == 0);
210 assert(ok.error == 0);
212 println("Checking whether changes are still there...");
213 msg = ldb.search("(cn=Niemand)");
214 assert(msg.error == 0);
215 assert(msg.msgs.length >= 1);
216 assert(msg.msgs[0].description == "Blie");
218 println("Deleting attribute...");
220 dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl
226 assert(ok.error == 0);
228 assert(ok.error == 0);
230 println("Checking whether changes are no longer there...");
231 msg = ldb.search("(cn=Niemand)");
232 assert(msg.error == 0);
233 assert(msg.msgs.length >= 1);
234 assert(msg.msgs[0].description == undefined);
236 println("Renaming record...");
237 ok = ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl", "cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
238 assert(ok.error == 0);
240 println("Checking whether DN has changed...");
241 msg = ldb.search("(cn=Niemand2)");
242 assert(msg.error == 0);
243 assert(msg.msgs.length == 1);
244 assert(msg.msgs[0].dn == "cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
246 println("Deleting record...");
247 ok = ldb.del("cn=Niemand2,cn=Users,dc=vernstok,dc=nl");
250 assert(ok.error == 0);
253 println("Checking whether record is gone...");
254 msg = ldb.search("(cn=Niemand2)");
255 assert(msg.error == 0);
256 assert(msg.msgs.length == 0);
259 function test_map_search(ldb, s3, s4)
261 println("Running search tests on mapped data");
266 /* Add a set of split records */
268 dn: " + s4.dn("cn=X") + "
277 objectSid: S-1-5-21-4231626423-2410014848-2360679739-552
278 primaryGroupID: 1-5-21-4231626423-2410014848-2360679739-512
280 dn: " + s4.dn("cn=Y") + "
290 dn: " + s4.dn("cn=Z") + "
300 ldif = substitute_var(ldif, s4);
301 assert(ldif != undefined);
302 var ok = ldb.add(ldif);
305 assert(ok.error == 0);
308 /* Add a set of remote records */
310 dn: " + s3.dn("cn=A") + "
311 objectClass: posixAccount
314 sambaBadPasswordCount: x
317 sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552
318 sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512
320 dn: " + s3.dn("cn=B") + "
324 sambaBadPasswordCount: x
328 dn: " + s3.dn("cn=C") + "
332 sambaBadPasswordCount: y
336 ldif = substitute_var(ldif, s3);
337 assert(ldif != undefined);
338 var ok = s3.db.add(ldif);
339 assert(ok.error == 0);
341 println("Testing search by DN");
343 /* Search remote record by local DN */
345 attrs = new Array("dnsHostName", "lastLogon");
346 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
347 assert(res.error == 0);
348 assert(res.msgs.length == 1);
349 assert(res.msgs[0].dn == dn);
350 assert(res.msgs[0].dnsHostName == undefined);
351 assert(res.msgs[0].lastLogon == "x");
353 /* Search remote record by remote DN */
355 attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime");
356 res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
357 assert(res.error == 0);
358 assert(res.msgs.length == 1);
359 assert(res.msgs[0].dn == dn);
360 assert(res.msgs[0].dnsHostName == undefined);
361 assert(res.msgs[0].lastLogon == undefined);
362 assert(res.msgs[0].sambaLogonTime == "x");
364 /* Search split record by local DN */
366 attrs = new Array("dnsHostName", "lastLogon");
367 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
368 assert(res.error == 0);
369 assert(res.msgs.length == 1);
370 assert(res.msgs[0].dn == dn);
371 assert(res.msgs[0].dnsHostName == "x");
372 assert(res.msgs[0].lastLogon == "x");
374 /* Search split record by remote DN */
376 attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime");
377 res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs);
378 assert(res.error == 0);
379 assert(res.msgs.length == 1);
380 assert(res.msgs[0].dn == dn);
381 assert(res.msgs[0].dnsHostName == undefined);
382 assert(res.msgs[0].lastLogon == undefined);
383 assert(res.msgs[0].sambaLogonTime == "x");
385 println("Testing search by attribute");
387 /* Search by ignored attribute */
388 attrs = new Array("dnsHostName", "lastLogon");
389 res = ldb.search("(revision=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
390 assert(res.error == 0);
391 assert(res.msgs.length == 2);
392 assert(res.msgs[0].dn == s4.dn("cn=Y"));
393 assert(res.msgs[0].dnsHostName == "y");
394 assert(res.msgs[0].lastLogon == "y");
395 assert(res.msgs[1].dn == s4.dn("cn=X"));
396 assert(res.msgs[1].dnsHostName == "x");
397 assert(res.msgs[1].lastLogon == "x");
399 /* Search by kept attribute */
400 attrs = new Array("dnsHostName", "lastLogon");
401 res = ldb.search("(description=y)", NULL, ldb. SCOPE_DEFAULT, attrs);
402 assert(res.error == 0);
403 assert(res.msgs.length == 2);
404 assert(res.msgs[0].dn == s4.dn("cn=Z"));
405 assert(res.msgs[0].dnsHostName == "z");
406 assert(res.msgs[0].lastLogon == "z");
407 assert(res.msgs[1].dn == s4.dn("cn=C"));
408 assert(res.msgs[1].dnsHostName == undefined);
409 assert(res.msgs[1].lastLogon == "z");
411 /* Search by renamed attribute */
412 attrs = new Array("dnsHostName", "lastLogon");
413 res = ldb.search("(badPwdCount=x)", NULL, ldb. SCOPE_DEFAULT, attrs);
414 assert(res.error == 0);
415 assert(res.msgs.length == 2);
416 assert(res.msgs[0].dn == s4.dn("cn=B"));
417 assert(res.msgs[0].dnsHostName == undefined);
418 assert(res.msgs[0].lastLogon == "y");
419 assert(res.msgs[1].dn == s4.dn("cn=A"));
420 assert(res.msgs[1].dnsHostName == undefined);
421 assert(res.msgs[1].lastLogon == "x");
423 /* Search by converted attribute */
424 attrs = new Array("dnsHostName", "lastLogon", "objectSid");
426 Using the SID directly in the parse tree leads to conversion
427 errors, letting the search fail with no results.
428 res = ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", NULL, ldb. SCOPE_DEFAULT, attrs);
430 res = ldb.search("(objectSid=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
431 assert(res.error == 0);
432 assert(res.msgs.length == 2);
433 assert(res.msgs[0].dn == s4.dn("cn=X"));
434 assert(res.msgs[0].dnsHostName == "x");
435 assert(res.msgs[0].lastLogon == "x");
436 assert(res.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
437 assert(res.msgs[1].dn == s4.dn("cn=A"));
438 assert(res.msgs[1].dnsHostName == undefined);
439 assert(res.msgs[1].lastLogon == "x");
440 assert(res.msgs[1].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552");
442 /* Search by generated attribute */
443 /* In most cases, this even works when the mapping is missing
444 * a `convert_operator' by enumerating the remote db. */
445 attrs = new Array("dnsHostName", "lastLogon", "primaryGroupID");
446 res = ldb.search("(primaryGroupID=512)", NULL, ldb. SCOPE_DEFAULT, attrs);
447 assert(res.error == 0);
448 assert(res.msgs.length == 1);
449 assert(res.msgs[0].dn == s4.dn("cn=A"));
450 assert(res.msgs[0].dnsHostName == undefined);
451 assert(res.msgs[0].lastLogon == "x");
452 assert(res.msgs[0].primaryGroupID == "512");
454 /* TODO: There should actually be two results, A and X. The
455 * primaryGroupID of X seems to get corrupted somewhere, and the
456 * objectSid isn't available during the generation of remote (!) data,
457 * which can be observed with the following search. Also note that Xs
458 * objectSid seems to be fine in the previous search for objectSid... */
460 res = ldb.search("(primaryGroupID=*)", NULL, ldb. SCOPE_DEFAULT, attrs);
461 println(res.msgs.length + " results found");
462 for (i=0;i<res.msgs.length;i++) {
463 for (obj in res.msgs[i]) {
464 println(obj + ": " + res.msgs[i][obj]);
470 /* Search by remote name of renamed attribute */
471 attrs = new Array("dnsHostName", "lastLogon");
472 res = ldb.search("(sambaBadPasswordCount=*)", "", ldb. SCOPE_DEFAULT, attrs);
473 assert(res.error == 0);
474 assert(res.msgs.length == 0);
476 /* Search by objectClass */
477 attrs = new Array("dnsHostName", "lastLogon", "objectClass");
478 res = ldb.search("(objectClass=user)", NULL, ldb. SCOPE_DEFAULT, attrs);
479 assert(res.error == 0);
480 assert(res.msgs.length == 2);
481 assert(res.msgs[0].dn == s4.dn("cn=X"));
482 assert(res.msgs[0].dnsHostName == "x");
483 assert(res.msgs[0].lastLogon == "x");
484 assert(res.msgs[0].objectClass != undefined);
485 assert(res.msgs[0].objectClass[0] == "user");
486 assert(res.msgs[1].dn == s4.dn("cn=A"));
487 assert(res.msgs[1].dnsHostName == undefined);
488 assert(res.msgs[1].lastLogon == "x");
489 assert(res.msgs[1].objectClass != undefined);
490 assert(res.msgs[1].objectClass[0] == "user");
492 /* Prove that the objectClass is actually used for the search */
493 res = ldb.search("(|(objectClass=user)(badPwdCount=x))", NULL, ldb. SCOPE_DEFAULT, attrs);
494 assert(res.error == 0);
495 assert(res.msgs.length == 3);
496 assert(res.msgs[0].dn == s4.dn("cn=B"));
497 assert(res.msgs[0].dnsHostName == undefined);
498 assert(res.msgs[0].lastLogon == "y");
499 assert(res.msgs[0].objectClass != undefined);
500 for (i=0;i<res.msgs[0].objectClass.length;i++) {
501 assert(res.msgs[0].objectClass[i] != "user");
503 assert(res.msgs[1].dn == s4.dn("cn=X"));
504 assert(res.msgs[1].dnsHostName == "x");
505 assert(res.msgs[1].lastLogon == "x");
506 assert(res.msgs[1].objectClass != undefined);
507 assert(res.msgs[1].objectClass[0] == "user");
508 assert(res.msgs[2].dn == s4.dn("cn=A"));
509 assert(res.msgs[2].dnsHostName == undefined);
510 assert(res.msgs[2].lastLogon == "x");
511 assert(res.msgs[2].objectClass != undefined);
512 assert(res.msgs[2].objectClass[0] == "user");
514 println("Testing search by parse tree");
516 /* Search by conjunction of local attributes */
517 attrs = new Array("dnsHostName", "lastLogon");
518 res = ldb.search("(&(codePage=x)(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
519 assert(res.error == 0);
520 assert(res.msgs.length == 2);
521 assert(res.msgs[0].dn == s4.dn("cn=Y"));
522 assert(res.msgs[0].dnsHostName == "y");
523 assert(res.msgs[0].lastLogon == "y");
524 assert(res.msgs[1].dn == s4.dn("cn=X"));
525 assert(res.msgs[1].dnsHostName == "x");
526 assert(res.msgs[1].lastLogon == "x");
528 /* Search by conjunction of remote attributes */
529 attrs = new Array("dnsHostName", "lastLogon");
530 res = ldb.search("(&(lastLogon=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
531 assert(res.error == 0);
532 assert(res.msgs.length == 2);
533 assert(res.msgs[0].dn == s4.dn("cn=X"));
534 assert(res.msgs[0].dnsHostName == "x");
535 assert(res.msgs[0].lastLogon == "x");
536 assert(res.msgs[1].dn == s4.dn("cn=A"));
537 assert(res.msgs[1].dnsHostName == undefined);
538 assert(res.msgs[1].lastLogon == "x");
540 /* Search by conjunction of local and remote attribute */
541 attrs = new Array("dnsHostName", "lastLogon");
542 res = ldb.search("(&(codePage=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
543 assert(res.error == 0);
544 assert(res.msgs.length == 2);
545 assert(res.msgs[0].dn == s4.dn("cn=Y"));
546 assert(res.msgs[0].dnsHostName == "y");
547 assert(res.msgs[0].lastLogon == "y");
548 assert(res.msgs[1].dn == s4.dn("cn=X"));
549 assert(res.msgs[1].dnsHostName == "x");
550 assert(res.msgs[1].lastLogon == "x");
552 /* Search by conjunction of local and remote attribute w/o match */
553 attrs = new Array("dnsHostName", "lastLogon");
554 res = ldb.search("(&(codePage=x)(nextRid=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
555 assert(res.error == 0);
556 assert(res.msgs.length == 0);
557 res = ldb.search("(&(revision=x)(lastLogon=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
558 assert(res.error == 0);
559 assert(res.msgs.length == 0);
561 /* Search by disjunction of local attributes */
562 attrs = new Array("dnsHostName", "lastLogon");
563 res = ldb.search("(|(revision=x)(dnsHostName=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
564 assert(res.error == 0);
565 assert(res.msgs.length == 2);
566 assert(res.msgs[0].dn == s4.dn("cn=Y"));
567 assert(res.msgs[0].dnsHostName == "y");
568 assert(res.msgs[0].lastLogon == "y");
569 assert(res.msgs[1].dn == s4.dn("cn=X"));
570 assert(res.msgs[1].dnsHostName == "x");
571 assert(res.msgs[1].lastLogon == "x");
573 /* Search by disjunction of remote attributes */
574 attrs = new Array("dnsHostName", "lastLogon");
575 res = ldb.search("(|(badPwdCount=x)(lastLogon=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
576 assert(res.error == 0);
577 assert(res.msgs.length == 3);
578 assert(res.msgs[0].dn == s4.dn("cn=B"));
579 assert(res.msgs[0].dnsHostName == undefined);
580 assert(res.msgs[0].lastLogon == "y");
581 assert(res.msgs[1].dn == s4.dn("cn=X"));
582 assert(res.msgs[1].dnsHostName == "x");
583 assert(res.msgs[1].lastLogon == "x");
584 assert(res.msgs[2].dn == s4.dn("cn=A"));
585 assert(res.msgs[2].dnsHostName == undefined);
586 assert(res.msgs[2].lastLogon == "x");
588 /* Search by disjunction of local and remote attribute */
589 attrs = new Array("dnsHostName", "lastLogon");
590 res = ldb.search("(|(revision=x)(lastLogon=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
591 assert(res.error == 0);
592 assert(res.msgs.length == 3);
593 assert(res.msgs[0].dn == s4.dn("cn=Y"));
594 assert(res.msgs[0].dnsHostName == "y");
595 assert(res.msgs[0].lastLogon == "y");
596 assert(res.msgs[1].dn == s4.dn("cn=B"));
597 assert(res.msgs[1].dnsHostName == undefined);
598 assert(res.msgs[1].lastLogon == "y");
599 assert(res.msgs[2].dn == s4.dn("cn=X"));
600 assert(res.msgs[2].dnsHostName == "x");
601 assert(res.msgs[2].lastLogon == "x");
603 /* Search by disjunction of local and remote attribute w/o match */
604 attrs = new Array("dnsHostName", "lastLogon");
605 res = ldb.search("(|(codePage=y)(nextRid=z))", NULL, ldb.SCOPE_DEFAULT, attrs);
606 assert(res.error == 0);
607 assert(res.msgs.length == 0);
609 /* Search by negated local attribute */
610 attrs = new Array("dnsHostName", "lastLogon");
611 res = ldb.search("(!(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
612 assert(res.error == 0);
613 assert(res.msgs.length == 4);
614 assert(res.msgs[0].dn == s4.dn("cn=B"));
615 assert(res.msgs[0].dnsHostName == undefined);
616 assert(res.msgs[0].lastLogon == "y");
617 assert(res.msgs[1].dn == s4.dn("cn=A"));
618 assert(res.msgs[1].dnsHostName == undefined);
619 assert(res.msgs[1].lastLogon == "x");
620 assert(res.msgs[2].dn == s4.dn("cn=Z"));
621 assert(res.msgs[2].dnsHostName == "z");
622 assert(res.msgs[2].lastLogon == "z");
623 assert(res.msgs[3].dn == s4.dn("cn=C"));
624 assert(res.msgs[3].dnsHostName == undefined);
625 assert(res.msgs[3].lastLogon == "z");
627 /* Search by negated remote attribute */
628 attrs = new Array("dnsHostName", "lastLogon");
629 res = ldb.search("(!(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs);
630 assert(res.error == 0);
631 assert(res.msgs.length == 2);
632 assert(res.msgs[0].dn == s4.dn("cn=Z"));
633 assert(res.msgs[0].dnsHostName == "z");
634 assert(res.msgs[0].lastLogon == "z");
635 assert(res.msgs[1].dn == s4.dn("cn=C"));
636 assert(res.msgs[1].dnsHostName == undefined);
637 assert(res.msgs[1].lastLogon == "z");
639 /* Search by negated conjunction of local attributes */
640 attrs = new Array("dnsHostName", "lastLogon");
641 res = ldb.search("(!(&(codePage=x)(revision=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
642 assert(res.error == 0);
643 assert(res.msgs.length == 4);
644 assert(res.msgs[0].dn == s4.dn("cn=B"));
645 assert(res.msgs[0].dnsHostName == undefined);
646 assert(res.msgs[0].lastLogon == "y");
647 assert(res.msgs[1].dn == s4.dn("cn=A"));
648 assert(res.msgs[1].dnsHostName == undefined);
649 assert(res.msgs[1].lastLogon == "x");
650 assert(res.msgs[2].dn == s4.dn("cn=Z"));
651 assert(res.msgs[2].dnsHostName == "z");
652 assert(res.msgs[2].lastLogon == "z");
653 assert(res.msgs[3].dn == s4.dn("cn=C"));
654 assert(res.msgs[3].dnsHostName == undefined);
655 assert(res.msgs[3].lastLogon == "z");
657 /* Search by negated conjunction of remote attributes */
658 attrs = new Array("dnsHostName", "lastLogon");
659 res = ldb.search("(!(&(lastLogon=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
660 assert(res.error == 0);
661 assert(res.msgs.length == 4);
662 assert(res.msgs[0].dn == s4.dn("cn=Y"));
663 assert(res.msgs[0].dnsHostName == "y");
664 assert(res.msgs[0].lastLogon == "y");
665 assert(res.msgs[1].dn == s4.dn("cn=B"));
666 assert(res.msgs[1].dnsHostName == undefined);
667 assert(res.msgs[1].lastLogon == "y");
668 assert(res.msgs[2].dn == s4.dn("cn=Z"));
669 assert(res.msgs[2].dnsHostName == "z");
670 assert(res.msgs[2].lastLogon == "z");
671 assert(res.msgs[3].dn == s4.dn("cn=C"));
672 assert(res.msgs[3].dnsHostName == undefined);
673 assert(res.msgs[3].lastLogon == "z");
675 /* Search by negated conjunction of local and remote attribute */
676 attrs = new Array("dnsHostName", "lastLogon");
677 res = ldb.search("(!(&(codePage=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
678 assert(res.error == 0);
679 assert(res.msgs.length == 4);
680 assert(res.msgs[0].dn == s4.dn("cn=B"));
681 assert(res.msgs[0].dnsHostName == undefined);
682 assert(res.msgs[0].lastLogon == "y");
683 assert(res.msgs[1].dn == s4.dn("cn=A"));
684 assert(res.msgs[1].dnsHostName == undefined);
685 assert(res.msgs[1].lastLogon == "x");
686 assert(res.msgs[2].dn == s4.dn("cn=Z"));
687 assert(res.msgs[2].dnsHostName == "z");
688 assert(res.msgs[2].lastLogon == "z");
689 assert(res.msgs[3].dn == s4.dn("cn=C"));
690 assert(res.msgs[3].dnsHostName == undefined);
691 assert(res.msgs[3].lastLogon == "z");
693 /* Search by negated disjunction of local attributes */
694 attrs = new Array("dnsHostName", "lastLogon");
695 res = ldb.search("(!(|(revision=x)(dnsHostName=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
696 assert(res.error == 0);
697 assert(res.msgs[0].dn == s4.dn("cn=B"));
698 assert(res.msgs[0].dnsHostName == undefined);
699 assert(res.msgs[0].lastLogon == "y");
700 assert(res.msgs[1].dn == s4.dn("cn=A"));
701 assert(res.msgs[1].dnsHostName == undefined);
702 assert(res.msgs[1].lastLogon == "x");
703 assert(res.msgs[2].dn == s4.dn("cn=Z"));
704 assert(res.msgs[2].dnsHostName == "z");
705 assert(res.msgs[2].lastLogon == "z");
706 assert(res.msgs[3].dn == s4.dn("cn=C"));
707 assert(res.msgs[3].dnsHostName == undefined);
708 assert(res.msgs[3].lastLogon == "z");
710 /* Search by negated disjunction of remote attributes */
711 attrs = new Array("dnsHostName", "lastLogon");
712 res = ldb.search("(!(|(badPwdCount=x)(lastLogon=x)))", NULL, ldb.SCOPE_DEFAULT, attrs);
713 assert(res.error == 0);
714 assert(res.msgs.length == 3);
715 assert(res.msgs[0].dn == s4.dn("cn=Y"));
716 assert(res.msgs[0].dnsHostName == "y");
717 assert(res.msgs[0].lastLogon == "y");
718 assert(res.msgs[1].dn == s4.dn("cn=Z"));
719 assert(res.msgs[1].dnsHostName == "z");
720 assert(res.msgs[1].lastLogon == "z");
721 assert(res.msgs[2].dn == s4.dn("cn=C"));
722 assert(res.msgs[2].dnsHostName == undefined);
723 assert(res.msgs[2].lastLogon == "z");
725 /* Search by negated disjunction of local and remote attribute */
726 attrs = new Array("dnsHostName", "lastLogon");
727 res = ldb.search("(!(|(revision=x)(lastLogon=y)))", NULL, ldb.SCOPE_DEFAULT, attrs);
728 assert(res.error == 0);
729 assert(res.msgs.length == 3);
730 assert(res.msgs[0].dn == s4.dn("cn=A"));
731 assert(res.msgs[0].dnsHostName == undefined);
732 assert(res.msgs[0].lastLogon == "x");
733 assert(res.msgs[1].dn == s4.dn("cn=Z"));
734 assert(res.msgs[1].dnsHostName == "z");
735 assert(res.msgs[1].lastLogon == "z");
736 assert(res.msgs[2].dn == s4.dn("cn=C"));
737 assert(res.msgs[2].dnsHostName == undefined);
738 assert(res.msgs[2].lastLogon == "z");
740 /* Search by complex parse tree */
741 attrs = new Array("dnsHostName", "lastLogon");
742 res = ldb.search("(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", NULL, ldb.SCOPE_DEFAULT, attrs);
743 assert(res.error == 0);
744 assert(res.msgs.length == 5);
745 assert(res.msgs[0].dn == s4.dn("cn=B"));
746 assert(res.msgs[0].dnsHostName == undefined);
747 assert(res.msgs[0].lastLogon == "y");
748 assert(res.msgs[1].dn == s4.dn("cn=X"));
749 assert(res.msgs[1].dnsHostName == "x");
750 assert(res.msgs[1].lastLogon == "x");
751 assert(res.msgs[2].dn == s4.dn("cn=A"));
752 assert(res.msgs[2].dnsHostName == undefined);
753 assert(res.msgs[2].lastLogon == "x");
754 assert(res.msgs[3].dn == s4.dn("cn=Z"));
755 assert(res.msgs[3].dnsHostName == "z");
756 assert(res.msgs[3].lastLogon == "z");
757 assert(res.msgs[4].dn == s4.dn("cn=C"));
758 assert(res.msgs[4].dnsHostName == undefined);
759 assert(res.msgs[4].lastLogon == "z");
762 var dns = new Array();
763 dns[0] = s4.dn("cn=A");
764 dns[1] = s4.dn("cn=B");
765 dns[2] = s4.dn("cn=C");
766 dns[3] = s4.dn("cn=X");
767 dns[4] = s4.dn("cn=Y");
768 dns[5] = s4.dn("cn=Z");
769 for (i=0;i<dns.length;i++) {
770 var ok = ldb.del(dns[i]);
771 assert(ok.error == 0);
775 function test_map_modify(ldb, s3, s4)
777 println("Running modification tests on mapped data");
785 println("Testing modification of local records");
787 /* Add local record */
788 dn = "cn=test,dc=idealx,dc=org";
797 assert(ok.error == 0);
798 /* Check it's there */
799 attrs = new Array("foo", "revision", "description");
800 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
801 assert(res.error == 0);
802 assert(res.msgs.length == 1);
803 assert(res.msgs[0].dn == dn);
804 assert(res.msgs[0].foo == "bar");
805 assert(res.msgs[0].revision == "1");
806 assert(res.msgs[0].description == "test");
807 /* Check it's not in the local db */
808 res = s4.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs);
809 assert(res.error == 0);
810 assert(res.msgs.length == 0);
811 /* Check it's not in the remote db */
812 res = s3.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs);
813 assert(res.error == 0);
814 assert(res.msgs.length == 0);
816 /* Modify local record */
824 ok = ldb.modify(ldif);
825 assert(ok.error == 0);
826 /* Check in local db */
827 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
828 assert(res.error == 0);
829 assert(res.msgs.length == 1);
830 assert(res.msgs[0].dn == dn);
831 assert(res.msgs[0].foo == "baz");
832 assert(res.msgs[0].revision == "1");
833 assert(res.msgs[0].description == "foo");
835 /* Rename local record */
836 dn2 = "cn=toast,dc=idealx,dc=org";
837 ok = ldb.rename(dn, dn2);
838 assert(ok.error == 0);
839 /* Check in local db */
840 res = ldb.search("", dn2, ldb.SCOPE_BASE, attrs);
841 assert(res.error == 0);
842 assert(res.msgs.length == 1);
843 assert(res.msgs[0].dn == dn2);
844 assert(res.msgs[0].foo == "baz");
845 assert(res.msgs[0].revision == "1");
846 assert(res.msgs[0].description == "foo");
848 /* Delete local record */
850 assert(ok.error == 0);
851 /* Check it's gone */
852 res = ldb.search("", dn2, ldb.SCOPE_BASE);
853 assert(res.error == 0);
854 assert(res.msgs.length == 0);
856 println("Testing modification of remote records");
858 /* Add remote record */
859 dn = s4.dn("cn=test");
860 dn2 = s3.dn("cn=test");
865 sambaBadPasswordCount: 3
868 ok = s3.db.add(ldif);
869 assert(ok.error == 0);
870 /* Check it's there */
871 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
872 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
873 assert(res.error == 0);
874 assert(res.msgs.length == 1);
875 assert(res.msgs[0].dn == dn2);
876 assert(res.msgs[0].description == "foo");
877 assert(res.msgs[0].sambaBadPasswordCount == "3");
878 assert(res.msgs[0].sambaNextRid == "1001");
879 /* Check in mapped db */
880 attrs = new Array("description", "badPwdCount", "nextRid");
881 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
882 assert(res.error == 0);
883 assert(res.msgs.length == 1);
884 assert(res.msgs[0].dn == dn);
885 assert(res.msgs[0].description == "foo");
886 assert(res.msgs[0].badPwdCount == "3");
887 assert(res.msgs[0].nextRid == "1001");
888 /* Check in local db */
889 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
890 assert(res.error == 0);
891 assert(res.msgs.length == 0);
893 /* Modify remote data of remote record */
901 ok = ldb.modify(ldif);
902 /* Check in mapped db */
903 attrs = new Array("description", "badPwdCount", "nextRid");
904 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
905 assert(res.error == 0);
906 assert(res.msgs.length == 1);
907 assert(res.msgs[0].dn == dn);
908 assert(res.msgs[0].description == "test");
909 assert(res.msgs[0].badPwdCount == "4");
910 assert(res.msgs[0].nextRid == "1001");
911 /* Check in remote db */
912 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
913 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
914 assert(res.error == 0);
915 assert(res.msgs.length == 1);
916 assert(res.msgs[0].dn == dn2);
917 assert(res.msgs[0].description == "test");
918 assert(res.msgs[0].sambaBadPasswordCount == "4");
919 assert(res.msgs[0].sambaNextRid == "1001");
921 /* Rename remote record */
922 dn2 = s4.dn("cn=toast");
923 ok = ldb.rename(dn, dn2);
924 assert(ok.error == 0);
925 /* Check in mapped db */
927 attrs = new Array("description", "badPwdCount", "nextRid");
928 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
929 assert(res.error == 0);
930 assert(res.msgs.length == 1);
931 assert(res.msgs[0].dn == dn);
932 assert(res.msgs[0].description == "test");
933 assert(res.msgs[0].badPwdCount == "4");
934 assert(res.msgs[0].nextRid == "1001");
935 /* Check in remote db */
936 dn2 = s3.dn("cn=toast");
937 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid");
938 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
939 assert(res.error == 0);
940 assert(res.msgs.length == 1);
941 assert(res.msgs[0].dn == dn2);
942 assert(res.msgs[0].description == "test");
943 assert(res.msgs[0].sambaBadPasswordCount == "4");
944 assert(res.msgs[0].sambaNextRid == "1001");
946 /* Delete remote record */
948 assert(ok.error == 0);
949 /* Check in mapped db */
950 res = ldb.search("", dn, ldb.SCOPE_BASE);
951 assert(res.error == 0);
952 assert(res.msgs.length == 0);
953 /* Check in remote db */
954 res = s3.db.search("", dn2, ldb.SCOPE_BASE);
955 assert(res.error == 0);
956 assert(res.msgs.length == 0);
958 /* Add remote record (same as before) */
959 dn = s4.dn("cn=test");
960 dn2 = s3.dn("cn=test");
965 sambaBadPasswordCount: 3
968 ok = s3.db.add(ldif);
969 assert(ok.error == 0);
971 /* Modify local data of remote record */
979 ok = ldb.modify(ldif);
980 /* Check in mapped db */
981 attrs = new Array("revision", "description");
982 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
983 assert(res.error == 0);
984 assert(res.msgs.length == 1);
985 assert(res.msgs[0].dn == dn);
986 assert(res.msgs[0].description == "test");
987 assert(res.msgs[0].revision == "1");
988 /* Check in remote db */
989 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
990 assert(res.error == 0);
991 assert(res.msgs.length == 1);
992 assert(res.msgs[0].dn == dn2);
993 assert(res.msgs[0].description == "test");
994 assert(res.msgs[0].revision == undefined);
995 /* Check in local db */
996 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
997 assert(res.error == 0);
998 assert(res.msgs.length == 1);
999 assert(res.msgs[0].dn == dn);
1000 assert(res.msgs[0].description == undefined);
1001 assert(res.msgs[0].revision == "1");
1003 /* Delete (newly) split record */
1005 assert(ok.error == 0);
1007 println("Testing modification of split records");
1009 /* Add split record */
1010 dn = s4.dn("cn=test");
1011 dn2 = s3.dn("cn=test");
1021 assert(ok.error == 0);
1022 /* Check it's there */
1023 attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1024 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1025 assert(res.error == 0);
1026 assert(res.msgs.length == 1);
1027 assert(res.msgs[0].dn == dn);
1028 assert(res.msgs[0].description == "foo");
1029 assert(res.msgs[0].badPwdCount == "3");
1030 assert(res.msgs[0].nextRid == "1001");
1031 assert(res.msgs[0].revision == "1");
1032 /* Check in local db */
1033 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1034 assert(res.error == 0);
1035 assert(res.msgs.length == 1);
1036 assert(res.msgs[0].dn == dn);
1037 assert(res.msgs[0].description == undefined);
1038 assert(res.msgs[0].badPwdCount == undefined);
1039 assert(res.msgs[0].nextRid == undefined);
1040 assert(res.msgs[0].revision == "1");
1041 /* Check in remote db */
1042 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1043 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1044 assert(res.error == 0);
1045 assert(res.msgs.length == 1);
1046 assert(res.msgs[0].dn == dn2);
1047 assert(res.msgs[0].description == "foo");
1048 assert(res.msgs[0].sambaBadPasswordCount == "3");
1049 assert(res.msgs[0].sambaNextRid == "1001");
1050 assert(res.msgs[0].revision == undefined);
1052 /* Modify of split record */
1055 replace: description
1057 replace: badPwdCount
1062 ok = ldb.modify(ldif);
1063 assert(ok.error == 0);
1064 /* Check in mapped db */
1065 attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1066 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1067 assert(res.error == 0);
1068 assert(res.msgs.length == 1);
1069 assert(res.msgs[0].dn == dn);
1070 assert(res.msgs[0].description == "test");
1071 assert(res.msgs[0].badPwdCount == "4");
1072 assert(res.msgs[0].nextRid == "1001");
1073 assert(res.msgs[0].revision == "2");
1074 /* Check in local db */
1075 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1076 assert(res.error == 0);
1077 assert(res.msgs.length == 1);
1078 assert(res.msgs[0].dn == dn);
1079 assert(res.msgs[0].description == undefined);
1080 assert(res.msgs[0].badPwdCount == undefined);
1081 assert(res.msgs[0].nextRid == undefined);
1082 assert(res.msgs[0].revision == "2");
1083 /* Check in remote db */
1084 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1085 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1086 assert(res.error == 0);
1087 assert(res.msgs.length == 1);
1088 assert(res.msgs[0].dn == dn2);
1089 assert(res.msgs[0].description == "test");
1090 assert(res.msgs[0].sambaBadPasswordCount == "4");
1091 assert(res.msgs[0].sambaNextRid == "1001");
1092 assert(res.msgs[0].revision == undefined);
1094 /* Rename split record */
1095 dn2 = s4.dn("cn=toast");
1096 ok = ldb.rename(dn, dn2);
1097 assert(ok.error == 0);
1098 /* Check in mapped db */
1100 attrs = new Array("description", "badPwdCount", "nextRid", "revision");
1101 res = ldb.search("", dn, ldb.SCOPE_BASE, attrs);
1102 assert(res.error == 0);
1103 assert(res.msgs.length == 1);
1104 assert(res.msgs[0].dn == dn);
1105 assert(res.msgs[0].description == "test");
1106 assert(res.msgs[0].badPwdCount == "4");
1107 assert(res.msgs[0].nextRid == "1001");
1108 assert(res.msgs[0].revision == "2");
1109 /* Check in local db */
1110 res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs);
1111 assert(res.error == 0);
1112 assert(res.msgs.length == 1);
1113 assert(res.msgs[0].dn == dn);
1114 assert(res.msgs[0].description == undefined);
1115 assert(res.msgs[0].badPwdCount == undefined);
1116 assert(res.msgs[0].nextRid == undefined);
1117 assert(res.msgs[0].revision == "2");
1118 /* Check in remote db */
1119 dn2 = s3.dn("cn=toast");
1120 attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision");
1121 res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs);
1122 assert(res.error == 0);
1123 assert(res.msgs.length == 1);
1124 assert(res.msgs[0].dn == dn2);
1125 assert(res.msgs[0].description == "test");
1126 assert(res.msgs[0].sambaBadPasswordCount == "4");
1127 assert(res.msgs[0].sambaNextRid == "1001");
1128 assert(res.msgs[0].revision == undefined);
1130 /* Delete split record */
1132 assert(ok.error == 0);
1133 /* Check in mapped db */
1134 res = ldb.search("", dn, ldb.SCOPE_BASE);
1135 assert(res.error == 0);
1136 assert(res.msgs.length == 0);
1137 /* Check in local db */
1138 res = s4.db.search("", dn, ldb.SCOPE_BASE);
1139 assert(res.error == 0);
1140 assert(res.msgs.length == 0);
1141 /* Check in remote db */
1142 res = s3.db.search("", dn2, ldb.SCOPE_BASE);
1143 assert(res.error == 0);
1144 assert(res.msgs.length == 0);
1147 function make_dn(rdn)
1149 return rdn + ",sambaDomainName=TESTS," + this.BASEDN;
1152 function make_s4dn(rdn)
1154 return rdn + "," + this.BASEDN;
1157 var ldb = ldb_init();
1160 var ldbfile = prefix + "/" + "test.ldb";
1161 var ldburl = "tdb://" + ldbfile;
1163 var samba4 = new Object("samba4 partition info");
1164 samba4.file = prefix + "/" + "samba4.ldb";
1165 samba4.url = "tdb://" + samba4.file;
1166 samba4.BASEDN = "dc=vernstok,dc=nl";
1167 samba4.db = ldb_init();
1168 samba4.dn = make_s4dn;
1170 var samba3 = new Object("samba3 partition info");
1171 samba3.file = prefix + "/" + "samba3.ldb";
1172 samba3.url = "tdb://" + samba3.file;
1173 samba3.BASEDN = "cn=Samba3Sam";
1174 samba3.db = ldb_init();
1175 samba3.dn = make_dn;
1177 sys.unlink(ldbfile);
1178 sys.unlink(samba3.file);
1179 sys.unlink(samba4.file);
1181 var ok = ldb.connect(ldburl);
1183 var ok = samba3.db.connect(samba3.url);
1185 var ok = samba4.db.connect(samba4.url);
1188 setup_data(samba3, sys.file_load(datadir + "/" + "samba3.ldif"));
1189 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "/" + "provision_samba3sam.ldif"));
1192 var ok = ldb.connect(ldburl);
1195 test_s3sam_search(ldb);
1196 test_s3sam_modify(ldb, samba3);
1198 sys.unlink(ldbfile);
1199 sys.unlink(samba3.file);
1200 sys.unlink(samba4.file);
1203 var ok = ldb.connect(ldburl);
1205 samba3.db = ldb_init();
1206 var ok = samba3.db.connect(samba3.url);
1208 samba4.db = ldb_init();
1209 var ok = samba4.db.connect(samba4.url);
1212 setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "provision_samba3sam.ldif"));
1215 var ok = ldb.connect(ldburl);
1218 test_map_search(ldb, samba3, samba4);
1219 test_map_modify(ldb, samba3, samba4);
1221 sys.unlink(ldbfile);
1222 sys.unlink(samba3.file);
1223 sys.unlink(samba4.file);