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