s3-lsa: Fix static list of luids in our privileges implementation.
[Samba/ekacnet.git] / source4 / dsdb / samdb / ldb_modules / samba3sam.c
blob42245ce49112a9139f9d44f9bfbc92856899e1ab
1 /*
2 ldb database library - Samba3 SAM compatibility backend
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 */
8 #include "includes.h"
9 #include "ldb_module.h"
10 #include "ldb/ldb_map/ldb_map.h"
11 #include "system/passwd.h"
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 "libcli/security/proto.h"
18 #include "lib/samba3/samba3.h"
21 * sambaSID -> member (dn!)
22 * sambaSIDList -> member (dn!)
23 * sambaDomainName -> name
24 * sambaTrustPassword
25 * sambaUnixIdPool
26 * sambaIdmapEntry
27 * sambaSidEntry
28 * sambaAcctFlags -> systemFlags ?
29 * sambaPasswordHistory -> ntPwdHistory*/
31 /* Not necessary:
32 * sambaConfig
33 * sambaShare
34 * sambaConfigOption
35 * sambaNextGroupRid
36 * sambaNextUserRid
37 * sambaAlgorithmicRidBase
40 /* Not in Samba4:
41 * sambaKickoffTime
42 * sambaPwdCanChange
43 * sambaPwdMustChange
44 * sambaHomePath
45 * sambaHomeDrive
46 * sambaLogonScript
47 * sambaProfilePath
48 * sambaUserWorkstations
49 * sambaMungedDial
50 * sambaLogonHours */
52 /* In Samba4 but not in Samba3:
55 /* From a sambaPrimaryGroupSID, generate a primaryGroupID (integer) attribute */
56 static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *local_attr, const struct ldb_message *remote)
58 struct ldb_message_element *el;
59 const char *sid = ldb_msg_find_attr_as_string(remote, "sambaPrimaryGroupSID", NULL);
60 const char *p;
62 if (!sid)
63 return NULL;
65 p = strrchr(sid, '-');
66 if (!p)
67 return NULL;
69 el = talloc_zero(ctx, struct ldb_message_element);
70 el->name = talloc_strdup(ctx, "primaryGroupID");
71 el->num_values = 1;
72 el->values = talloc_array(ctx, struct ldb_val, 1);
73 el->values[0].data = (uint8_t *)talloc_strdup(el->values, p+1);
74 el->values[0].length = strlen((char *)el->values[0].data);
76 return el;
79 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)
81 const struct ldb_val *sidval;
82 char *sidstring;
83 struct dom_sid *sid;
84 enum ndr_err_code ndr_err;
86 /* We need the domain, so we get it from the objectSid that we hope is here... */
87 sidval = ldb_msg_find_ldb_val(local, "objectSid");
89 if (!sidval)
90 return; /* Sorry, no SID today.. */
92 sid = talloc(remote_mp, struct dom_sid);
93 if (sid == NULL) {
94 return;
97 ndr_err = ndr_pull_struct_blob(sidval, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
98 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
99 talloc_free(sid);
100 return;
103 if (!ldb_msg_find_ldb_val(local, "primaryGroupID"))
104 return; /* Sorry, no SID today.. */
106 sid->num_auths--;
108 sidstring = dom_sid_string(remote_mp, sid);
109 talloc_free(sid);
110 ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_attr_as_uint(local, "primaryGroupID", 0));
111 talloc_free(sidstring);
114 /* Just copy the old value. */
115 static struct ldb_val convert_uid_samaccount(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
117 struct ldb_val out = data_blob(NULL, 0);
118 out = ldb_val_dup(ctx, val);
120 return out;
123 static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
125 struct ldb_context *ldb;
126 struct passwd *pwd;
127 struct ldb_val retval;
129 ldb = ldb_module_get_ctx(module);
131 pwd = getpwnam((char *)val->data);
133 if (!pwd) {
134 ldb_debug(ldb, LDB_DEBUG_WARNING, "Unable to lookup '%s' in passwd", (char *)val->data);
135 return *talloc_zero(ctx, struct ldb_val);
138 retval.data = (uint8_t *)talloc_strdup(ctx, pwd->pw_dir);
139 retval.length = strlen((char *)retval.data);
141 return retval;
144 static struct ldb_val lookup_gid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
146 struct passwd *pwd;
147 struct ldb_val retval;
149 pwd = getpwnam((char *)val->data);
151 if (!pwd) {
152 return *talloc_zero(ctx, struct ldb_val);
155 retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_gid);
156 retval.length = strlen((char *)retval.data);
158 return retval;
161 static struct ldb_val lookup_uid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
163 struct passwd *pwd;
164 struct ldb_val retval;
166 pwd = getpwnam((char *)val->data);
168 if (!pwd) {
169 return *talloc_zero(ctx, struct ldb_val);
172 retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_uid);
173 retval.length = strlen((char *)retval.data);
175 return retval;
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)
181 struct ldb_val out = data_blob(NULL, 0);
182 struct dom_sid *sid;
183 enum ndr_err_code ndr_err;
185 sid = dom_sid_parse_talloc(ctx, (char *)val->data);
186 if (sid == NULL) {
187 return out;
190 ndr_err = ndr_push_struct_blob(&out, ctx,
191 sid, (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;
197 return out;
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)
203 struct ldb_val out = data_blob(NULL, 0);
204 struct dom_sid *sid;
205 enum ndr_err_code ndr_err;
207 sid = talloc(ctx, struct dom_sid);
208 if (sid == NULL) {
209 return out;
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;
218 out.data = (uint8_t *)dom_sid_string(ctx, sid);
219 if (out.data == NULL) {
220 goto done;
222 out.length = strlen((const char *)out.data);
224 done:
225 talloc_free(sid);
226 return out;
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)
232 struct ldb_val out;
233 struct samr_Password pwd;
234 if (val->length != sizeof(pwd.hash)) {
235 return data_blob(NULL, 0);
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);
242 return out;
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)
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);
254 out = data_blob_talloc(ctx, pwd->hash, sizeof(pwd->hash));
255 return out;
258 const struct ldb_map_objectclass samba3_objectclasses[] = {
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 },
267 .local_name = "group",
268 .remote_name = "posixGroup",
269 .base_classes = { "top", NULL },
270 .musts = { "cn", "gidNumber", NULL },
271 .mays = { "userPassword", "memberUid", "description", NULL },
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 },
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 }
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 },
302 { NULL, NULL }
305 const struct ldb_map_attribute samba3_attributes[] =
307 /* sambaNextRid -> nextRid */
309 .local_name = "nextRid",
310 .type = LDB_MAP_RENAME,
311 .u = {
312 .rename = {
313 .remote_name = "sambaNextRid",
318 /* sambaBadPasswordTime -> badPasswordtime*/
320 .local_name = "badPasswordTime",
321 .type = LDB_MAP_RENAME,
322 .u = {
323 .rename = {
324 .remote_name = "sambaBadPasswordTime",
329 /* sambaLMPassword -> lmPwdHash*/
331 .local_name = "dBCSPwd",
332 .type = LDB_MAP_CONVERT,
333 .u = {
334 .convert = {
335 .remote_name = "sambaLMPassword",
336 .convert_local = bin2hex,
337 .convert_remote = hex2bin,
342 /* sambaGroupType -> groupType */
344 .local_name = "groupType",
345 .type = LDB_MAP_RENAME,
346 .u = {
347 .rename = {
348 .remote_name = "sambaGroupType",
353 /* sambaNTPassword -> ntPwdHash*/
355 .local_name = "ntpwdhash",
356 .type = LDB_MAP_CONVERT,
357 .u = {
358 .convert = {
359 .remote_name = "sambaNTPassword",
360 .convert_local = bin2hex,
361 .convert_remote = hex2bin,
366 /* sambaPrimaryGroupSID -> primaryGroupID */
368 .local_name = "primaryGroupID",
369 .type = LDB_MAP_GENERATE,
370 .u = {
371 .generate = {
372 .remote_names = { "sambaPrimaryGroupSID", NULL },
373 .generate_local = generate_primaryGroupID,
374 .generate_remote = generate_sambaPrimaryGroupSID,
379 /* sambaBadPasswordCount -> badPwdCount */
381 .local_name = "badPwdCount",
382 .type = LDB_MAP_RENAME,
383 .u = {
384 .rename = {
385 .remote_name = "sambaBadPasswordCount",
390 /* sambaLogonTime -> lastLogon*/
392 .local_name = "lastLogon",
393 .type = LDB_MAP_RENAME,
394 .u = {
395 .rename = {
396 .remote_name = "sambaLogonTime",
401 /* sambaLogoffTime -> lastLogoff*/
403 .local_name = "lastLogoff",
404 .type = LDB_MAP_RENAME,
405 .u = {
406 .rename = {
407 .remote_name = "sambaLogoffTime",
412 /* uid -> unixName */
414 .local_name = "unixName",
415 .type = LDB_MAP_RENAME,
416 .u = {
417 .rename = {
418 .remote_name = "uid",
423 /* displayName -> name */
425 .local_name = "name",
426 .type = LDB_MAP_RENAME,
427 .u = {
428 .rename = {
429 .remote_name = "displayName",
434 /* cn */
436 .local_name = "cn",
437 .type = LDB_MAP_KEEP,
440 /* sAMAccountName -> cn */
442 .local_name = "sAMAccountName",
443 .type = LDB_MAP_CONVERT,
444 .u = {
445 .convert = {
446 .remote_name = "uid",
447 .convert_remote = convert_uid_samaccount,
452 /* objectCategory */
454 .local_name = "objectCategory",
455 .type = LDB_MAP_IGNORE,
458 /* objectGUID */
460 .local_name = "objectGUID",
461 .type = LDB_MAP_IGNORE,
464 /* objectVersion */
466 .local_name = "objectVersion",
467 .type = LDB_MAP_IGNORE,
470 /* codePage */
472 .local_name = "codePage",
473 .type = LDB_MAP_IGNORE,
476 /* dNSHostName */
478 .local_name = "dNSHostName",
479 .type = LDB_MAP_IGNORE,
483 /* dnsDomain */
485 .local_name = "dnsDomain",
486 .type = LDB_MAP_IGNORE,
489 /* dnsRoot */
491 .local_name = "dnsRoot",
492 .type = LDB_MAP_IGNORE,
495 /* countryCode */
497 .local_name = "countryCode",
498 .type = LDB_MAP_IGNORE,
501 /* nTMixedDomain */
503 .local_name = "nTMixedDomain",
504 .type = LDB_MAP_IGNORE,
507 /* operatingSystem */
509 .local_name = "operatingSystem",
510 .type = LDB_MAP_IGNORE,
513 /* operatingSystemVersion */
515 .local_name = "operatingSystemVersion",
516 .type = LDB_MAP_IGNORE,
520 /* servicePrincipalName */
522 .local_name = "servicePrincipalName",
523 .type = LDB_MAP_IGNORE,
526 /* msDS-Behavior-Version */
528 .local_name = "msDS-Behavior-Version",
529 .type = LDB_MAP_IGNORE,
532 /* msDS-KeyVersionNumber */
534 .local_name = "msDS-KeyVersionNumber",
535 .type = LDB_MAP_IGNORE,
538 /* msDs-masteredBy */
540 .local_name = "msDs-masteredBy",
541 .type = LDB_MAP_IGNORE,
544 /* ou */
546 .local_name = "ou",
547 .type = LDB_MAP_KEEP,
550 /* dc */
552 .local_name = "dc",
553 .type = LDB_MAP_KEEP,
556 /* description */
558 .local_name = "description",
559 .type = LDB_MAP_KEEP,
562 /* sambaSID -> objectSid*/
564 .local_name = "objectSid",
565 .type = LDB_MAP_CONVERT,
566 .u = {
567 .convert = {
568 .remote_name = "sambaSID",
569 .convert_local = decode_sid,
570 .convert_remote = encode_sid,
575 /* sambaPwdLastSet -> pwdLastSet */
577 .local_name = "pwdLastSet",
578 .type = LDB_MAP_RENAME,
579 .u = {
580 .rename = {
581 .remote_name = "sambaPwdLastSet",
586 /* accountExpires */
588 .local_name = "accountExpires",
589 .type = LDB_MAP_IGNORE,
592 /* adminCount */
594 .local_name = "adminCount",
595 .type = LDB_MAP_IGNORE,
598 /* canonicalName */
600 .local_name = "canonicalName",
601 .type = LDB_MAP_IGNORE,
604 /* createTimestamp */
606 .local_name = "createTimestamp",
607 .type = LDB_MAP_IGNORE,
610 /* creationTime */
612 .local_name = "creationTime",
613 .type = LDB_MAP_IGNORE,
616 /* dMDLocation */
618 .local_name = "dMDLocation",
619 .type = LDB_MAP_IGNORE,
622 /* fSMORoleOwner */
624 .local_name = "fSMORoleOwner",
625 .type = LDB_MAP_IGNORE,
628 /* forceLogoff */
630 .local_name = "forceLogoff",
631 .type = LDB_MAP_IGNORE,
634 /* instanceType */
636 .local_name = "instanceType",
637 .type = LDB_MAP_IGNORE,
640 /* invocationId */
642 .local_name = "invocationId",
643 .type = LDB_MAP_IGNORE,
646 /* isCriticalSystemObject */
648 .local_name = "isCriticalSystemObject",
649 .type = LDB_MAP_IGNORE,
652 /* localPolicyFlags */
654 .local_name = "localPolicyFlags",
655 .type = LDB_MAP_IGNORE,
658 /* lockOutObservationWindow */
660 .local_name = "lockOutObservationWindow",
661 .type = LDB_MAP_IGNORE,
664 /* lockoutDuration */
666 .local_name = "lockoutDuration",
667 .type = LDB_MAP_IGNORE,
670 /* lockoutThreshold */
672 .local_name = "lockoutThreshold",
673 .type = LDB_MAP_IGNORE,
676 /* logonCount */
678 .local_name = "logonCount",
679 .type = LDB_MAP_IGNORE,
682 /* masteredBy */
684 .local_name = "masteredBy",
685 .type = LDB_MAP_IGNORE,
688 /* maxPwdAge */
690 .local_name = "maxPwdAge",
691 .type = LDB_MAP_IGNORE,
694 /* member */
696 .local_name = "member",
697 .type = LDB_MAP_IGNORE,
700 /* memberOf */
702 .local_name = "memberOf",
703 .type = LDB_MAP_IGNORE,
706 /* minPwdAge */
708 .local_name = "minPwdAge",
709 .type = LDB_MAP_IGNORE,
712 /* minPwdLength */
714 .local_name = "minPwdLength",
715 .type = LDB_MAP_IGNORE,
718 /* modifiedCount */
720 .local_name = "modifiedCount",
721 .type = LDB_MAP_IGNORE,
724 /* modifiedCountAtLastProm */
726 .local_name = "modifiedCountAtLastProm",
727 .type = LDB_MAP_IGNORE,
730 /* modifyTimestamp */
732 .local_name = "modifyTimestamp",
733 .type = LDB_MAP_IGNORE,
736 /* nCName */
738 .local_name = "nCName",
739 .type = LDB_MAP_IGNORE,
742 /* nETBIOSName */
744 .local_name = "nETBIOSName",
745 .type = LDB_MAP_IGNORE,
748 /* oEMInformation */
750 .local_name = "oEMInformation",
751 .type = LDB_MAP_IGNORE,
754 /* privilege */
756 .local_name = "privilege",
757 .type = LDB_MAP_IGNORE,
760 /* pwdHistoryLength */
762 .local_name = "pwdHistoryLength",
763 .type = LDB_MAP_IGNORE,
766 /* pwdProperties */
768 .local_name = "pwdProperties",
769 .type = LDB_MAP_IGNORE,
772 /* rIDAvailablePool */
774 .local_name = "rIDAvailablePool",
775 .type = LDB_MAP_IGNORE,
778 /* revision */
780 .local_name = "revision",
781 .type = LDB_MAP_IGNORE,
784 /* ridManagerReference */
786 .local_name = "ridManagerReference",
787 .type = LDB_MAP_IGNORE,
790 /* sAMAccountType */
792 .local_name = "sAMAccountType",
793 .type = LDB_MAP_IGNORE,
796 /* sPNMappings */
798 .local_name = "sPNMappings",
799 .type = LDB_MAP_IGNORE,
802 /* serverReference */
804 .local_name = "serverReference",
805 .type = LDB_MAP_IGNORE,
808 /* serverState */
810 .local_name = "serverState",
811 .type = LDB_MAP_IGNORE,
814 /* showInAdvancedViewOnly */
816 .local_name = "showInAdvancedViewOnly",
817 .type = LDB_MAP_IGNORE,
820 /* subRefs */
822 .local_name = "subRefs",
823 .type = LDB_MAP_IGNORE,
826 /* systemFlags */
828 .local_name = "systemFlags",
829 .type = LDB_MAP_IGNORE,
832 /* uASCompat */
834 .local_name = "uASCompat",
835 .type = LDB_MAP_IGNORE,
838 /* uSNChanged */
840 .local_name = "uSNChanged",
841 .type = LDB_MAP_IGNORE,
844 /* uSNCreated */
846 .local_name = "uSNCreated",
847 .type = LDB_MAP_IGNORE,
850 /* userPassword */
852 .local_name = "userPassword",
853 .type = LDB_MAP_IGNORE,
856 /* userAccountControl */
858 .local_name = "userAccountControl",
859 .type = LDB_MAP_IGNORE,
862 /* whenChanged */
864 .local_name = "whenChanged",
865 .type = LDB_MAP_IGNORE,
868 /* whenCreated */
870 .local_name = "whenCreated",
871 .type = LDB_MAP_IGNORE,
874 /* uidNumber */
876 .local_name = "unixName",
877 .type = LDB_MAP_CONVERT,
878 .u = {
879 .convert = {
880 .remote_name = "uidNumber",
881 .convert_local = lookup_uid,
886 /* gidNumber. Perhaps make into generate so we can distinguish between
887 * groups and accounts? */
889 .local_name = "unixName",
890 .type = LDB_MAP_CONVERT,
891 .u = {
892 .convert = {
893 .remote_name = "gidNumber",
894 .convert_local = lookup_gid,
899 /* homeDirectory */
901 .local_name = "unixName",
902 .type = LDB_MAP_CONVERT,
903 .u = {
904 .convert = {
905 .remote_name = "homeDirectory",
906 .convert_local = lookup_homedir,
911 .local_name = NULL,
915 /* the context init function */
916 static int samba3sam_init(struct ldb_module *module)
918 int ret;
920 ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, NULL, "samba3sam");
921 if (ret != LDB_SUCCESS)
922 return ret;
924 return ldb_next_init(module);
927 _PUBLIC_ const struct ldb_module_ops ldb_samba3sam_module_ops = {
928 LDB_MAP_OPS
929 .name = "samba3sam",
930 .init_context = samba3sam_init,