r12719: Rename unicodePwd -> sambaPassword.
[samba.git] / source4 / dsdb / samdb / ldb_modules / samba3sam.c
1 /* 
2    ldb database library - Samba3 SAM compatibility backend
3
4    Copyright (C) Jelmer Vernooij 2005
5 */
6
7 #include "includes.h"
8 #include "ldb/modules/ldb_map.h"
9 #include "ldb/include/ldb.h"
10 #include "ldb/include/ldb_private.h"
11 #include "system/passwd.h"
12
13 /* 
14  * sambaSID -> member  (dn!)
15  * sambaSIDList -> member (dn!) 
16  * sambaDomainName -> name 
17  * sambaTrustPassword 
18  * sambaUnixIdPool 
19  * sambaIdmapEntry 
20  * sambaAccountPolicy 
21  * sambaSidEntry 
22  * sambaAcctFlags -> systemFlags ?
23  * sambaPasswordHistory  -> ntPwdHistory*/
24
25 /* Not necessary:
26  * sambaConfig
27  * sambaShare
28  * sambaConfigOption 
29  * sambaNextGroupRid
30  * sambaNextUserRid
31  * sambaAlgorithmicRidBase
32  */
33
34 /* Not in Samba4: 
35  * sambaKickoffTime
36  * sambaPwdCanChange
37  * sambaPwdMustChange
38  * sambaHomePath
39  * sambaHomeDrive
40  * sambaLogonScript
41  * sambaProfilePath
42  * sambaUserWorkstations
43  * sambaMungedDial
44  * sambaLogonHours */
45
46 /* In Samba4 but not in Samba3:
47 */
48
49 static void generate_hashes (struct ldb_module *module, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote_mp, struct ldb_message *remote_fb)
50 {
51         const char *upwd = ldb_msg_find_string(local, local_attr, NULL);
52         struct ldb_val val;
53
54         if (!upwd)
55                 return;
56
57         ldb_msg_add_string(remote_fb, local_attr, upwd);
58
59         val.length = 16;
60         val.data = talloc_zero_size(module, val.length);
61
62         E_md4hash(upwd, val.data);
63         ldb_msg_add_value(remote_mp, "sambaNTPassword", &val);
64                         
65         val.data = talloc_zero_size(module, val.length);
66         E_deshash(upwd, val.data);
67         ldb_msg_add_value(remote_mp, "sambaLMPassword", &val);
68 }
69
70
71 static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *attr, const struct ldb_message *remote)
72 {
73         struct ldb_message_element *el;
74         const char *sid = ldb_msg_find_string(remote, attr, NULL);
75
76         if (!sid)
77                 return NULL;
78
79         if (strchr(sid, '-') == NULL)
80                 return NULL;
81
82         el = talloc_zero(ctx, struct ldb_message_element);
83         el->name = talloc_strdup(ctx, "primaryGroupID");
84         el->num_values = 1;
85         el->values = talloc_array(ctx, struct ldb_val, 1);
86         el->values[0].data = (uint8_t *)talloc_strdup(ctx, strchr(sid, '-')+1);
87         el->values[0].length = strlen((char *)el->values[0].data);
88
89         return el;
90 }
91
92 static void generate_sambaPrimaryGroupSID(struct ldb_module *module, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote_mp, struct ldb_message *remote_fb)
93 {
94         const struct ldb_val *sidval;
95         char *sidstring;
96         struct dom_sid *sid;
97         NTSTATUS status;
98
99         sidval = ldb_msg_find_ldb_val(local, "objectSid");
100
101         if (!sidval) 
102                 return; /* Sorry, no SID today.. */
103
104         sid = talloc(remote_mp, struct dom_sid);
105         if (sid == NULL) {
106                 return;
107         }
108         status = ndr_pull_struct_blob(sidval, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
109         if (!NT_STATUS_IS_OK(status)) {
110                 talloc_free(sid);
111                 return;
112         }
113
114         if (!ldb_msg_find_ldb_val(local, "primaryGroupID"))
115                 return; /* Sorry, no SID today.. */
116
117         sid->num_auths--;
118
119         sidstring = dom_sid_string(remote_mp, sid);
120         talloc_free(sid);
121         ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_uint(local, "primaryGroupID", 0));
122         talloc_free(sidstring);
123 }
124
125 static struct ldb_val convert_uid_samaccount(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
126 {
127         return ldb_val_dup(ctx, val);
128 }
129
130 static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
131 {
132         struct passwd *pwd; 
133         struct ldb_val retval;
134         
135         pwd = getpwnam((char *)val->data);
136
137         if (!pwd) {
138                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to lookup '%s' in passwd", (char *)val->data);
139                 return *talloc_zero(ctx, struct ldb_val);
140         }
141
142         retval.data = (uint8_t *)talloc_strdup(ctx, pwd->pw_dir);
143         retval.length = strlen((char *)retval.data);
144
145         return retval;
146 }
147
148 static struct ldb_val lookup_gid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
149 {
150         struct passwd *pwd; 
151         struct ldb_val retval;
152         
153         pwd = getpwnam((char *)val->data);
154
155         if (!pwd) {
156                 return *talloc_zero(ctx, struct ldb_val);
157         }
158
159         retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_gid);
160         retval.length = strlen((char *)retval.data);
161
162         return retval;
163 }
164
165 static struct ldb_val lookup_uid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
166 {
167         struct passwd *pwd; 
168         struct ldb_val retval;
169         
170         pwd = getpwnam((char *)val->data);
171
172         if (!pwd) {
173                 return *talloc_zero(ctx, struct ldb_val);
174         }
175
176         retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_uid);
177         retval.length = strlen((char *)retval.data);
178
179         return retval;
180 }
181
182 static struct ldb_val encode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
183 {
184         struct dom_sid *sid = dom_sid_parse_talloc(ctx, (char *)val->data);
185         struct ldb_val *out = talloc_zero(ctx, struct ldb_val);
186         NTSTATUS status;
187
188         if (sid == NULL) {
189                 return *out;
190         }
191         status = ndr_push_struct_blob(out, ctx, sid, 
192                                       (ndr_push_flags_fn_t)ndr_push_dom_sid);
193         talloc_free(sid);
194         if (!NT_STATUS_IS_OK(status)) {
195                 return *out;
196         }
197
198         return *out;
199 }
200
201 static struct ldb_val decode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
202 {
203         struct dom_sid *sid;
204         NTSTATUS status;
205         struct ldb_val *out = talloc_zero(ctx, struct ldb_val);
206         
207         sid = talloc(ctx, struct dom_sid);
208         if (sid == NULL) {
209                 return *out;
210         }
211         status = ndr_pull_struct_blob(val, sid, sid, 
212                                       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
213         if (!NT_STATUS_IS_OK(status)) {
214                 talloc_free(sid);
215                 return *out;
216         }
217         out->data = (uint8_t *)dom_sid_string(ctx, sid);
218         talloc_free(sid);
219         if (out->data == NULL) {
220                 return *out;
221         }
222         out->length = strlen((const char *)out->data);
223
224         return *out;
225 }
226
227 const struct ldb_map_objectclass samba3_objectclasses[] = {
228         {
229                 .local_name = "user",
230                 .remote_name = "posixAccount",
231                 .base_classes = { "top", NULL },
232                 .musts = { "cn", "uid", "uidNumber", "gidNumber", "homeDirectory", NULL },
233                 .mays = { "userPassword", "loginShell", "gecos", "description", NULL },
234         },
235         {
236                 .local_name = "group",
237                 .remote_name = "posixGroup",
238                 .base_classes = { "top", NULL },
239                 .musts = { "cn", "gidNumber", NULL },
240                 .mays = { "userPassword", "memberUid", "description", NULL },
241         },
242         { 
243                 .local_name = "group", 
244                 .remote_name = "sambaGroupMapping",
245                 .base_classes = { "top", "posixGroup", NULL },
246                 .musts = { "gidNumber", "sambaSID", "sambaGroupType", NULL },
247                 .mays = { "displayName", "description", "sambaSIDList", NULL },
248         },
249         { 
250                 .local_name = "user", 
251                 .remote_name = "sambaSAMAccount",
252                 .base_classes = { "top", "posixAccount", NULL },
253                 .musts = { "uid", "sambaSID", NULL },
254                 .mays = { "cn", "sambaLMPassword", "sambaNTPassword",
255                         "sambaPwdLastSet", "sambaLogonTime", "sambaLogoffTime",
256                         "sambaKickoffTime", "sambaPwdCanChange", "sambaPwdMustChange",
257                         "sambaAcctFlags", "displayName", "sambaHomePath", "sambaHomeDrive",
258                         "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
259                         "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
260                         "sambaBadPasswordCount", "sambaBadPasswordTime",
261                 "sambaPasswordHistory", "sambaLogonHours", NULL }
262         
263         },
264         { 
265                 .local_name = "domain", 
266                 .remote_name = "sambaDomain",
267                 .base_classes = { "top", NULL },
268                 .musts = { "sambaDomainName", "sambaSID", NULL },
269                 .mays = { "sambaNextRid", "sambaNextGroupRid", "sambaNextUserRid", "sambaAlgorithmicRidBase", NULL },
270         },
271                 { NULL, NULL }
272 };
273
274 const struct ldb_map_attribute samba3_attributes[] = 
275 {
276         /* sambaNextRid -> nextRid */
277         {
278                 .local_name = "nextRid",
279                 .type = MAP_RENAME,
280                 .u = {
281                         .rename = {
282                                 .remote_name = "sambaNextRid",
283                         },
284                 },
285         },
286
287         /* sambaBadPasswordTime -> badPasswordtime*/
288         {
289                 .local_name = "badPasswordTime",
290                 .type = MAP_RENAME,
291                 .u = {
292                         .rename = {
293                                 .remote_name = "sambaBadPasswordTime",
294                         },
295                 },
296         },
297
298         /* sambaLMPassword -> lmPwdHash*/
299         {
300                 .local_name = "lmPwdHash",
301                 .type = MAP_RENAME,
302                 .u = {
303                         .rename = {
304                                 .remote_name = "sambaLMPassword",
305                         },
306                 },
307         },
308
309         /* sambaGroupType -> groupType */
310         {
311                 .local_name = "groupType",
312                 .type = MAP_RENAME,
313                 .u = {
314                         .rename = {
315                                 .remote_name = "sambaGroupType",
316                         },
317                 },
318         },
319
320         /* sambaNTPassword -> ntPwdHash*/
321         {
322                 .local_name = "ntPwdHash",
323                 .type = MAP_RENAME,
324                 .u = {
325                         .rename = {
326                                 .remote_name = "sambaNTPassword",
327                         },
328                 },
329         },
330
331         /* sambaPrimaryGroupSID -> primaryGroupID */
332         {
333                 .local_name = "primaryGroupID",
334                 .type = MAP_GENERATE,
335                 .u = {
336                         .generate = {
337                                 .remote_names = { "sambaPrimaryGroupSID", NULL },
338                                 .generate_local = generate_primaryGroupID,
339                                 .generate_remote = generate_sambaPrimaryGroupSID, 
340                         },
341                 },
342         },
343
344         /* sambaBadPasswordCount -> badPwdCount */
345         {
346                 .local_name = "badPwdCount",
347                 .type = MAP_RENAME,
348                 .u = {
349                         .rename = {
350                                 .remote_name = "sambaBadPasswordCount",
351                         },
352                 },
353         },
354
355         /* sambaLogonTime -> lastLogon*/
356         {
357                 .local_name = "lastLogon",
358                 .type = MAP_RENAME,
359                 .u = {
360                         .rename = {
361                                 .remote_name = "sambaLogonTime",
362                         },
363                 },
364         },
365
366         /* sambaLogoffTime -> lastLogoff*/
367         {
368                 .local_name = "lastLogoff",
369                 .type = MAP_RENAME,
370                 .u = {
371                         .rename = {
372                                 .remote_name = "sambaLogoffTime",
373                         },
374                 },
375         },
376
377         /* uid -> unixName */
378         {
379                 .local_name = "unixName",
380                 .type = MAP_RENAME,
381                 .u = {
382                         .rename = {
383                                 .remote_name = "uid",
384                         },
385                 },
386         },
387
388         /* displayName -> name */
389         {
390                 .local_name = "name",
391                 .type = MAP_RENAME,
392                 .u = {
393                         .rename = {
394                                 .remote_name = "displayName",
395                         },
396                 },
397         },
398
399         /* cn */
400         {
401                 .local_name = "cn",
402                 .type = MAP_KEEP,
403         },
404
405         /* sAMAccountName -> cn */
406         {
407                 .local_name = "sAMAccountName",
408                 .type = MAP_CONVERT,
409                 .u = {
410                         .convert = {
411                                 .remote_name = "uid",
412                                 .convert_remote = convert_uid_samaccount,
413                         },
414                 },
415         },
416
417         /* objectCategory */
418         {
419                 .local_name = "objectCategory",
420                 .type = MAP_IGNORE,
421         },
422
423         /* objectGUID */
424         {
425                 .local_name = "objectGUID",
426                 .type = MAP_IGNORE,
427         },
428
429         /* objectVersion */
430         {
431                 .local_name = "objectVersion",
432                 .type = MAP_IGNORE,
433         },
434
435         /* codePage */
436         { 
437                 .local_name = "codePage",
438                 .type = MAP_IGNORE,
439         },
440
441         /* dNSHostName */
442         {
443                 .local_name = "dNSHostName",
444                 .type = MAP_IGNORE,
445         },
446
447
448         /* dnsDomain */
449         {
450                 .local_name = "dnsDomain",
451                 .type = MAP_IGNORE,
452         },
453
454         /* dnsRoot */
455         {
456                 .local_name = "dnsRoot",
457                 .type = MAP_IGNORE,
458         },
459
460         /* countryCode */
461         {
462                 .local_name = "countryCode",
463                 .type = MAP_IGNORE,
464         },
465
466         /* nTMixedDomain */
467         { 
468                 .local_name = "nTMixedDomain",
469                 .type = MAP_IGNORE,
470         },
471
472         /* operatingSystem */
473         { 
474                 .local_name = "operatingSystem",
475                 .type = MAP_IGNORE,
476         },
477
478         /* operatingSystemVersion */
479         {
480                 .local_name = "operatingSystemVersion",
481                 .type = MAP_IGNORE,
482         },
483
484
485         /* servicePrincipalName */
486         {
487                 .local_name = "servicePrincipalName",
488                 .type = MAP_IGNORE,
489         },
490
491         /* msDS-Behavior-Version */
492         {
493                 .local_name = "msDS-Behavior-Version",
494                 .type = MAP_IGNORE,
495         },
496
497         /* msDS-KeyVersionNumber */
498         {
499                 .local_name = "msDS-KeyVersionNumber",
500                 .type = MAP_IGNORE,
501         },
502
503         /* msDs-masteredBy */
504         {
505                 .local_name = "msDs-masteredBy",
506                 .type = MAP_IGNORE,
507         },
508
509         /* ou */
510         {
511                 .local_name = "ou",
512                 .type = MAP_KEEP,
513         },
514
515         /* dc */
516         {
517                 .local_name = "dc",
518                 .type = MAP_KEEP,
519         },
520
521         /* description */
522         {
523                 .local_name = "description",
524                 .type = MAP_KEEP,
525         },
526
527         /* sambaSID -> objectSid*/
528         {
529                 .local_name = "objectSid",
530                 .type = MAP_CONVERT,
531                 .u = {
532                         .convert = {
533                                 .remote_name = "sambaSID", 
534                                 .convert_local = decode_sid,
535                                 .convert_remote = encode_sid,
536                         },
537                 },
538         },
539
540         /* sambaPwdLastSet -> pwdLastSet */
541         {
542                 .local_name = "pwdLastSet",
543                 .type = MAP_RENAME,
544                 .u = {
545                         .rename = {
546                                 .remote_name = "sambaPwdLastSet",
547                         },
548                 },
549         },      
550
551         /* accountExpires */
552         {
553                 .local_name = "accountExpires", 
554                 .type = MAP_IGNORE,
555         },
556
557         /* adminCount */
558         {
559                 .local_name = "adminCount",
560                 .type = MAP_IGNORE,
561         },
562
563         /* canonicalName */
564         {
565                 .local_name = "canonicalName",
566                 .type = MAP_IGNORE,
567         },
568
569         /* createTimestamp */
570         {
571                 .local_name = "createTimestamp",
572                 .type = MAP_IGNORE,
573         },
574         
575         /* creationTime */
576         {
577                 .local_name = "creationTime",
578                 .type = MAP_IGNORE,
579         },
580         
581         /* dMDLocation */
582         {
583                 .local_name = "dMDLocation",
584                 .type = MAP_IGNORE,
585         },
586         
587         /* fSMORoleOwner */
588         {
589                 .local_name = "fSMORoleOwner",
590                 .type = MAP_IGNORE,
591         },
592         
593         /* forceLogoff */
594         {
595                 .local_name = "forceLogoff",
596                 .type = MAP_IGNORE,
597         },
598         
599         /* instanceType */
600         {
601                 .local_name = "instanceType",
602                 .type = MAP_IGNORE,
603         },
604         
605         /* invocationId */
606         {
607                 .local_name = "invocationId",
608                 .type = MAP_IGNORE,
609         },
610         
611         /* isCriticalSystemObject */
612         {
613                 .local_name = "isCriticalSystemObject",
614                 .type = MAP_IGNORE,
615         },
616         
617         /* localPolicyFlags */
618         {
619                 .local_name = "localPolicyFlags",
620                 .type = MAP_IGNORE,
621         },
622         
623         /* lockOutObservationWindow */
624         {
625                 .local_name = "lockOutObservationWindow",
626                 .type = MAP_IGNORE,
627         },
628
629         /* lockoutDuration */
630         {
631                 .local_name = "lockoutDuration",
632                 .type = MAP_IGNORE,
633         },
634
635         /* lockoutThreshold */
636         {
637                 .local_name = "lockoutThreshold",
638                 .type = MAP_IGNORE,
639         },
640
641         /* logonCount */
642         {
643                 .local_name = "logonCount",
644                 .type = MAP_IGNORE,
645         },
646
647         /* masteredBy */
648         {
649                 .local_name = "masteredBy",
650                 .type = MAP_IGNORE,
651         },
652
653         /* maxPwdAge */
654         {
655                 .local_name = "maxPwdAge",
656                 .type = MAP_IGNORE,
657         },
658
659         /* member */
660         {
661                 .local_name = "member",
662                 .type = MAP_IGNORE,
663         },
664
665         /* memberOf */
666         {
667                 .local_name = "memberOf",
668                 .type = MAP_IGNORE,
669         },
670
671         /* minPwdAge */
672         {
673                 .local_name = "minPwdAge",
674                 .type = MAP_IGNORE,
675         },
676
677         /* minPwdLength */
678         {
679                 .local_name = "minPwdLength",
680                 .type = MAP_IGNORE,
681         },
682
683         /* modifiedCount */
684         {
685                 .local_name = "modifiedCount",
686                 .type = MAP_IGNORE,
687         },
688
689         /* modifiedCountAtLastProm */
690         {
691                 .local_name = "modifiedCountAtLastProm",
692                 .type = MAP_IGNORE,
693         },
694
695         /* modifyTimestamp */
696         {
697                 .local_name = "modifyTimestamp",
698                 .type = MAP_IGNORE,
699         },
700
701         /* nCName */
702         {
703                 .local_name = "nCName",
704                 .type = MAP_IGNORE,
705         },
706
707         /* nETBIOSName */
708         {
709                 .local_name = "nETBIOSName",
710                 .type = MAP_IGNORE,
711         },
712
713         /* oEMInformation */
714         {
715                 .local_name = "oEMInformation",
716                 .type = MAP_IGNORE,
717         },
718
719         /* privilege */
720         {
721                 .local_name = "privilege",
722                 .type = MAP_IGNORE,
723         },
724
725         /* pwdHistoryLength */
726         {
727                 .local_name = "pwdHistoryLength",
728                 .type = MAP_IGNORE,
729         },
730
731         /* pwdProperties */
732         {
733                 .local_name = "pwdProperties",
734                 .type = MAP_IGNORE,
735         },
736
737         /* rIDAvailablePool */
738         {
739                 .local_name = "rIDAvailablePool",
740                 .type = MAP_IGNORE,
741         },
742
743         /* revision */
744         {
745                 .local_name = "revision",
746                 .type = MAP_IGNORE,
747         },
748
749         /* ridManagerReference */
750         {
751                 .local_name = "ridManagerReference",
752                 .type = MAP_IGNORE,
753         },
754
755         /* sAMAccountType */
756         {
757                 .local_name = "sAMAccountType",
758                 .type = MAP_IGNORE,
759         },
760
761         /* sPNMappings */
762         {
763                 .local_name = "sPNMappings",
764                 .type = MAP_IGNORE,
765         },
766
767         /* serverReference */
768         {
769                 .local_name = "serverReference",
770                 .type = MAP_IGNORE,
771         },
772
773         /* serverState */
774         {
775                 .local_name = "serverState",
776                 .type = MAP_IGNORE,
777         },
778
779         /* showInAdvancedViewOnly */
780         {
781                 .local_name = "showInAdvancedViewOnly",
782                 .type = MAP_IGNORE,
783         },
784
785         /* subRefs */
786         {
787                 .local_name = "subRefs",
788                 .type = MAP_IGNORE,
789         },
790
791         /* systemFlags */
792         {
793                 .local_name = "systemFlags",
794                 .type = MAP_IGNORE,
795         },
796
797         /* uASCompat */
798         {
799                 .local_name = "uASCompat",
800                 .type = MAP_IGNORE,
801         },
802
803         /* uSNChanged */
804         {
805                 .local_name = "uSNChanged",
806                 .type = MAP_IGNORE,
807         },
808
809         /* uSNCreated */
810         {
811                 .local_name = "uSNCreated",
812                 .type = MAP_IGNORE,
813         },
814
815         /* sambaPassword */
816         {
817                 .local_name = "sambaPassword",
818                 .type = MAP_IGNORE,
819         },
820
821         /* userAccountControl */
822         {
823                 .local_name = "userAccountControl",
824                 .type = MAP_IGNORE,
825         },
826
827         /* whenChanged */
828         {
829                 .local_name = "whenChanged",
830                 .type = MAP_IGNORE,
831         },
832
833         /* whenCreated */
834         {
835                 .local_name = "whenCreated",
836                 .type = MAP_IGNORE,
837         },
838
839         /* uidNumber */
840         {
841                 .local_name = "unixName",
842                 .type = MAP_CONVERT,
843                 .u = {
844                         .convert = {
845                                 .remote_name = "uidNumber",
846                                 .convert_local = lookup_uid,
847                         },
848                 },
849         },
850
851         /* gidNumber. Perhaps make into generate so we can distinguish between 
852          * groups and accounts? */
853         {
854                 .local_name = "unixName",
855                 .type = MAP_CONVERT,
856                 .u = {
857                         .convert = {
858                                 .remote_name = "gidNumber",
859                                 .convert_local = lookup_gid,
860                         },
861                 },
862         },
863
864         /* homeDirectory */
865         {
866                 .local_name = "unixName",
867                 .type = MAP_CONVERT,
868                 .u = {
869                         .convert = {
870                                 .remote_name = "homeDirectory",
871                                 .convert_local = lookup_homedir,
872                         },
873                 },
874         },
875         {
876                 .local_name = NULL,
877         }
878 };
879
880         /* the init function */
881 struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[])
882 {
883         return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, "samba3sam");
884 }