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