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