0bfc9a3dae98543e7d9c8b2c17d621ddcb1ff8b6
[ira/wip.git] / source / 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, NULL, 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, 
191                                        NULL,
192                                        sid, (ndr_push_flags_fn_t)ndr_push_dom_sid);
193         talloc_free(sid);
194         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
195                 return out;
196         }
197
198         return out;
199 }
200
201 /* Decode an objectSid to a sambaSID. */
202 static struct ldb_val decode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
203 {
204         struct ldb_val out = data_blob(NULL, 0);
205         struct dom_sid *sid;
206         enum ndr_err_code ndr_err;
207
208         sid = talloc(ctx, struct dom_sid);
209         if (sid == NULL) {
210                 return out;
211         }
212
213         ndr_err = ndr_pull_struct_blob(val, sid, NULL, sid,
214                                        (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
215         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
216                 goto done;
217         }
218
219         out.data = (uint8_t *)dom_sid_string(ctx, sid);
220         if (out.data == NULL) {
221                 goto done;
222         }
223         out.length = strlen((const char *)out.data);
224
225 done:
226         talloc_free(sid);
227         return out;
228 }
229
230 /* Convert 16 bytes to 32 hex digits. */
231 static struct ldb_val bin2hex(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
232 {
233         struct ldb_val out;
234         struct samr_Password pwd;
235         if (val->length != sizeof(pwd.hash)) {
236                 return data_blob(NULL, 0);
237         }
238         memcpy(pwd.hash, val->data, sizeof(pwd.hash));
239         out = data_blob_string_const(smbpasswd_sethexpwd(ctx, &pwd, 0));
240         if (!out.data) {
241                 return data_blob(NULL, 0);
242         }
243         return out;
244 }
245
246 /* Convert 32 hex digits to 16 bytes. */
247 static struct ldb_val hex2bin(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
248 {
249         struct ldb_val out;
250         struct samr_Password *pwd;
251         pwd = smbpasswd_gethexpwd(ctx, (const char *)val->data);
252         if (!pwd) {
253                 return data_blob(NULL, 0);
254         }
255         out = data_blob_talloc(ctx, pwd->hash, sizeof(pwd->hash));
256         return out;
257 }
258
259 const struct ldb_map_objectclass samba3_objectclasses[] = {
260         {
261                 .local_name = "user",
262                 .remote_name = "posixAccount",
263                 .base_classes = { "top", NULL },
264                 .musts = { "cn", "uid", "uidNumber", "gidNumber", "homeDirectory", NULL },
265                 .mays = { "userPassword", "loginShell", "gecos", "description", NULL },
266         },
267         {
268                 .local_name = "group",
269                 .remote_name = "posixGroup",
270                 .base_classes = { "top", NULL },
271                 .musts = { "cn", "gidNumber", NULL },
272                 .mays = { "userPassword", "memberUid", "description", NULL },
273         },
274         {
275                 .local_name = "group",
276                 .remote_name = "sambaGroupMapping",
277                 .base_classes = { "top", "posixGroup", NULL },
278                 .musts = { "gidNumber", "sambaSID", "sambaGroupType", NULL },
279                 .mays = { "displayName", "description", "sambaSIDList", NULL },
280         },
281         {
282                 .local_name = "user",
283                 .remote_name = "sambaSAMAccount",
284                 .base_classes = { "top", "posixAccount", NULL },
285                 .musts = { "uid", "sambaSID", NULL },
286                 .mays = { "cn", "sambaLMPassword", "sambaNTPassword",
287                         "sambaPwdLastSet", "sambaLogonTime", "sambaLogoffTime",
288                         "sambaKickoffTime", "sambaPwdCanChange", "sambaPwdMustChange",
289                         "sambaAcctFlags", "displayName", "sambaHomePath", "sambaHomeDrive",
290                         "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
291                         "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
292                         "sambaBadPasswordCount", "sambaBadPasswordTime",
293                 "sambaPasswordHistory", "sambaLogonHours", NULL }
294
295         },
296         {
297                 .local_name = "domain",
298                 .remote_name = "sambaDomain",
299                 .base_classes = { "top", NULL },
300                 .musts = { "sambaDomainName", "sambaSID", NULL },
301                 .mays = { "sambaNextRid", "sambaNextGroupRid", "sambaNextUserRid", "sambaAlgorithmicRidBase", NULL },
302         },
303                 { NULL, NULL }
304 };
305
306 const struct ldb_map_attribute samba3_attributes[] =
307 {
308         /* sambaNextRid -> nextRid */
309         {
310                 .local_name = "nextRid",
311                 .type = MAP_RENAME,
312                 .u = {
313                         .rename = {
314                                 .remote_name = "sambaNextRid",
315                         },
316                 },
317         },
318
319         /* sambaBadPasswordTime -> badPasswordtime*/
320         {
321                 .local_name = "badPasswordTime",
322                 .type = MAP_RENAME,
323                 .u = {
324                         .rename = {
325                                 .remote_name = "sambaBadPasswordTime",
326                         },
327                 },
328         },
329
330         /* sambaLMPassword -> lmPwdHash*/
331         {
332                 .local_name = "dBCSPwd",
333                 .type = MAP_CONVERT,
334                 .u = {
335                         .convert = {
336                                 .remote_name = "sambaLMPassword",
337                                 .convert_local = bin2hex,
338                                 .convert_remote = hex2bin,
339                         },
340                 },
341         },
342
343         /* sambaGroupType -> groupType */
344         {
345                 .local_name = "groupType",
346                 .type = MAP_RENAME,
347                 .u = {
348                         .rename = {
349                                 .remote_name = "sambaGroupType",
350                         },
351                 },
352         },
353
354         /* sambaNTPassword -> ntPwdHash*/
355         {
356                 .local_name = "ntpwdhash",
357                 .type = MAP_CONVERT,
358                 .u = {
359                         .convert = {
360                                 .remote_name = "sambaNTPassword",
361                                 .convert_local = bin2hex,
362                                 .convert_remote = hex2bin,
363                         },
364                 },
365         },
366
367         /* sambaPrimaryGroupSID -> primaryGroupID */
368         {
369                 .local_name = "primaryGroupID",
370                 .type = MAP_GENERATE,
371                 .u = {
372                         .generate = {
373                                 .remote_names = { "sambaPrimaryGroupSID", NULL },
374                                 .generate_local = generate_primaryGroupID,
375                                 .generate_remote = generate_sambaPrimaryGroupSID,
376                         },
377                 },
378         },
379
380         /* sambaBadPasswordCount -> badPwdCount */
381         {
382                 .local_name = "badPwdCount",
383                 .type = MAP_RENAME,
384                 .u = {
385                         .rename = {
386                                 .remote_name = "sambaBadPasswordCount",
387                         },
388                 },
389         },
390
391         /* sambaLogonTime -> lastLogon*/
392         {
393                 .local_name = "lastLogon",
394                 .type = MAP_RENAME,
395                 .u = {
396                         .rename = {
397                                 .remote_name = "sambaLogonTime",
398                         },
399                 },
400         },
401
402         /* sambaLogoffTime -> lastLogoff*/
403         {
404                 .local_name = "lastLogoff",
405                 .type = MAP_RENAME,
406                 .u = {
407                         .rename = {
408                                 .remote_name = "sambaLogoffTime",
409                         },
410                 },
411         },
412
413         /* uid -> unixName */
414         {
415                 .local_name = "unixName",
416                 .type = MAP_RENAME,
417                 .u = {
418                         .rename = {
419                                 .remote_name = "uid",
420                         },
421                 },
422         },
423
424         /* displayName -> name */
425         {
426                 .local_name = "name",
427                 .type = MAP_RENAME,
428                 .u = {
429                         .rename = {
430                                 .remote_name = "displayName",
431                         },
432                 },
433         },
434
435         /* cn */
436         {
437                 .local_name = "cn",
438                 .type = MAP_KEEP,
439         },
440
441         /* sAMAccountName -> cn */
442         {
443                 .local_name = "sAMAccountName",
444                 .type = MAP_CONVERT,
445                 .u = {
446                         .convert = {
447                                 .remote_name = "uid",
448                                 .convert_remote = convert_uid_samaccount,
449                         },
450                 },
451         },
452
453         /* objectCategory */
454         {
455                 .local_name = "objectCategory",
456                 .type = MAP_IGNORE,
457         },
458
459         /* objectGUID */
460         {
461                 .local_name = "objectGUID",
462                 .type = MAP_IGNORE,
463         },
464
465         /* objectVersion */
466         {
467                 .local_name = "objectVersion",
468                 .type = MAP_IGNORE,
469         },
470
471         /* codePage */
472         {
473                 .local_name = "codePage",
474                 .type = MAP_IGNORE,
475         },
476
477         /* dNSHostName */
478         {
479                 .local_name = "dNSHostName",
480                 .type = MAP_IGNORE,
481         },
482
483
484         /* dnsDomain */
485         {
486                 .local_name = "dnsDomain",
487                 .type = MAP_IGNORE,
488         },
489
490         /* dnsRoot */
491         {
492                 .local_name = "dnsRoot",
493                 .type = MAP_IGNORE,
494         },
495
496         /* countryCode */
497         {
498                 .local_name = "countryCode",
499                 .type = MAP_IGNORE,
500         },
501
502         /* nTMixedDomain */
503         {
504                 .local_name = "nTMixedDomain",
505                 .type = MAP_IGNORE,
506         },
507
508         /* operatingSystem */
509         {
510                 .local_name = "operatingSystem",
511                 .type = MAP_IGNORE,
512         },
513
514         /* operatingSystemVersion */
515         {
516                 .local_name = "operatingSystemVersion",
517                 .type = MAP_IGNORE,
518         },
519
520
521         /* servicePrincipalName */
522         {
523                 .local_name = "servicePrincipalName",
524                 .type = MAP_IGNORE,
525         },
526
527         /* msDS-Behavior-Version */
528         {
529                 .local_name = "msDS-Behavior-Version",
530                 .type = MAP_IGNORE,
531         },
532
533         /* msDS-KeyVersionNumber */
534         {
535                 .local_name = "msDS-KeyVersionNumber",
536                 .type = MAP_IGNORE,
537         },
538
539         /* msDs-masteredBy */
540         {
541                 .local_name = "msDs-masteredBy",
542                 .type = MAP_IGNORE,
543         },
544
545         /* ou */
546         {
547                 .local_name = "ou",
548                 .type = MAP_KEEP,
549         },
550
551         /* dc */
552         {
553                 .local_name = "dc",
554                 .type = MAP_KEEP,
555         },
556
557         /* description */
558         {
559                 .local_name = "description",
560                 .type = MAP_KEEP,
561         },
562
563         /* sambaSID -> objectSid*/
564         {
565                 .local_name = "objectSid",
566                 .type = MAP_CONVERT,
567                 .u = {
568                         .convert = {
569                                 .remote_name = "sambaSID",
570                                 .convert_local = decode_sid,
571                                 .convert_remote = encode_sid,
572                         },
573                 },
574         },
575
576         /* sambaPwdLastSet -> pwdLastSet */
577         {
578                 .local_name = "pwdLastSet",
579                 .type = MAP_RENAME,
580                 .u = {
581                         .rename = {
582                                 .remote_name = "sambaPwdLastSet",
583                         },
584                 },
585         },
586
587         /* accountExpires */
588         {
589                 .local_name = "accountExpires",
590                 .type = MAP_IGNORE,
591         },
592
593         /* adminCount */
594         {
595                 .local_name = "adminCount",
596                 .type = MAP_IGNORE,
597         },
598
599         /* canonicalName */
600         {
601                 .local_name = "canonicalName",
602                 .type = MAP_IGNORE,
603         },
604
605         /* createTimestamp */
606         {
607                 .local_name = "createTimestamp",
608                 .type = MAP_IGNORE,
609         },
610
611         /* creationTime */
612         {
613                 .local_name = "creationTime",
614                 .type = MAP_IGNORE,
615         },
616
617         /* dMDLocation */
618         {
619                 .local_name = "dMDLocation",
620                 .type = MAP_IGNORE,
621         },
622
623         /* fSMORoleOwner */
624         {
625                 .local_name = "fSMORoleOwner",
626                 .type = MAP_IGNORE,
627         },
628
629         /* forceLogoff */
630         {
631                 .local_name = "forceLogoff",
632                 .type = MAP_IGNORE,
633         },
634
635         /* instanceType */
636         {
637                 .local_name = "instanceType",
638                 .type = MAP_IGNORE,
639         },
640
641         /* invocationId */
642         {
643                 .local_name = "invocationId",
644                 .type = MAP_IGNORE,
645         },
646
647         /* isCriticalSystemObject */
648         {
649                 .local_name = "isCriticalSystemObject",
650                 .type = MAP_IGNORE,
651         },
652
653         /* localPolicyFlags */
654         {
655                 .local_name = "localPolicyFlags",
656                 .type = MAP_IGNORE,
657         },
658
659         /* lockOutObservationWindow */
660         {
661                 .local_name = "lockOutObservationWindow",
662                 .type = MAP_IGNORE,
663         },
664
665         /* lockoutDuration */
666         {
667                 .local_name = "lockoutDuration",
668                 .type = MAP_IGNORE,
669         },
670
671         /* lockoutThreshold */
672         {
673                 .local_name = "lockoutThreshold",
674                 .type = MAP_IGNORE,
675         },
676
677         /* logonCount */
678         {
679                 .local_name = "logonCount",
680                 .type = MAP_IGNORE,
681         },
682
683         /* masteredBy */
684         {
685                 .local_name = "masteredBy",
686                 .type = MAP_IGNORE,
687         },
688
689         /* maxPwdAge */
690         {
691                 .local_name = "maxPwdAge",
692                 .type = MAP_IGNORE,
693         },
694
695         /* member */
696         {
697                 .local_name = "member",
698                 .type = MAP_IGNORE,
699         },
700
701         /* memberOf */
702         {
703                 .local_name = "memberOf",
704                 .type = MAP_IGNORE,
705         },
706
707         /* minPwdAge */
708         {
709                 .local_name = "minPwdAge",
710                 .type = MAP_IGNORE,
711         },
712
713         /* minPwdLength */
714         {
715                 .local_name = "minPwdLength",
716                 .type = MAP_IGNORE,
717         },
718
719         /* modifiedCount */
720         {
721                 .local_name = "modifiedCount",
722                 .type = MAP_IGNORE,
723         },
724
725         /* modifiedCountAtLastProm */
726         {
727                 .local_name = "modifiedCountAtLastProm",
728                 .type = MAP_IGNORE,
729         },
730
731         /* modifyTimestamp */
732         {
733                 .local_name = "modifyTimestamp",
734                 .type = MAP_IGNORE,
735         },
736
737         /* nCName */
738         {
739                 .local_name = "nCName",
740                 .type = MAP_IGNORE,
741         },
742
743         /* nETBIOSName */
744         {
745                 .local_name = "nETBIOSName",
746                 .type = MAP_IGNORE,
747         },
748
749         /* oEMInformation */
750         {
751                 .local_name = "oEMInformation",
752                 .type = MAP_IGNORE,
753         },
754
755         /* privilege */
756         {
757                 .local_name = "privilege",
758                 .type = MAP_IGNORE,
759         },
760
761         /* pwdHistoryLength */
762         {
763                 .local_name = "pwdHistoryLength",
764                 .type = MAP_IGNORE,
765         },
766
767         /* pwdProperties */
768         {
769                 .local_name = "pwdProperties",
770                 .type = MAP_IGNORE,
771         },
772
773         /* rIDAvailablePool */
774         {
775                 .local_name = "rIDAvailablePool",
776                 .type = MAP_IGNORE,
777         },
778
779         /* revision */
780         {
781                 .local_name = "revision",
782                 .type = MAP_IGNORE,
783         },
784
785         /* ridManagerReference */
786         {
787                 .local_name = "ridManagerReference",
788                 .type = MAP_IGNORE,
789         },
790
791         /* sAMAccountType */
792         {
793                 .local_name = "sAMAccountType",
794                 .type = MAP_IGNORE,
795         },
796
797         /* sPNMappings */
798         {
799                 .local_name = "sPNMappings",
800                 .type = MAP_IGNORE,
801         },
802
803         /* serverReference */
804         {
805                 .local_name = "serverReference",
806                 .type = MAP_IGNORE,
807         },
808
809         /* serverState */
810         {
811                 .local_name = "serverState",
812                 .type = MAP_IGNORE,
813         },
814
815         /* showInAdvancedViewOnly */
816         {
817                 .local_name = "showInAdvancedViewOnly",
818                 .type = MAP_IGNORE,
819         },
820
821         /* subRefs */
822         {
823                 .local_name = "subRefs",
824                 .type = MAP_IGNORE,
825         },
826
827         /* systemFlags */
828         {
829                 .local_name = "systemFlags",
830                 .type = MAP_IGNORE,
831         },
832
833         /* uASCompat */
834         {
835                 .local_name = "uASCompat",
836                 .type = MAP_IGNORE,
837         },
838
839         /* uSNChanged */
840         {
841                 .local_name = "uSNChanged",
842                 .type = MAP_IGNORE,
843         },
844
845         /* uSNCreated */
846         {
847                 .local_name = "uSNCreated",
848                 .type = MAP_IGNORE,
849         },
850
851         /* sambaPassword */
852         {
853                 .local_name = "sambaPassword",
854                 .type = MAP_IGNORE,
855         },
856
857         /* userAccountControl */
858         {
859                 .local_name = "userAccountControl",
860                 .type = MAP_IGNORE,
861         },
862
863         /* whenChanged */
864         {
865                 .local_name = "whenChanged",
866                 .type = MAP_IGNORE,
867         },
868
869         /* whenCreated */
870         {
871                 .local_name = "whenCreated",
872                 .type = MAP_IGNORE,
873         },
874
875         /* uidNumber */
876         {
877                 .local_name = "unixName",
878                 .type = MAP_CONVERT,
879                 .u = {
880                         .convert = {
881                                 .remote_name = "uidNumber",
882                                 .convert_local = lookup_uid,
883                         },
884                 },
885         },
886
887         /* gidNumber. Perhaps make into generate so we can distinguish between 
888          * groups and accounts? */
889         {
890                 .local_name = "unixName",
891                 .type = MAP_CONVERT,
892                 .u = {
893                         .convert = {
894                                 .remote_name = "gidNumber",
895                                 .convert_local = lookup_gid,
896                         },
897                 },
898         },
899
900         /* homeDirectory */
901         {
902                 .local_name = "unixName",
903                 .type = MAP_CONVERT,
904                 .u = {
905                         .convert = {
906                                 .remote_name = "homeDirectory",
907                                 .convert_local = lookup_homedir,
908                         },
909                 },
910         },
911         {
912                 .local_name = NULL,
913         }
914 };
915
916 /* the context init function */
917 static int samba3sam_init(struct ldb_module *module)
918 {
919         int ret;
920
921         ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, "samba3sam");
922         if (ret != LDB_SUCCESS)
923                 return ret;
924
925         return ldb_next_init(module);
926 }
927
928 static struct ldb_module_ops samba3sam_ops = {
929         .name              = "samba3sam",
930         .init_context      = samba3sam_init,
931 };
932
933 /* the init function */
934 int ldb_samba3sam_module_init(void)
935 {
936         struct ldb_module_ops ops = ldb_map_get_ops();
937         samba3sam_ops.add       = ops.add;
938         samba3sam_ops.modify    = ops.modify;
939         samba3sam_ops.del       = ops.del;
940         samba3sam_ops.rename    = ops.rename;
941         samba3sam_ops.search    = ops.search;
942         samba3sam_ops.wait      = ops.wait;
943
944         return ldb_register_module(&samba3sam_ops);
945 }