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