s4:resolve_oids LDB module - not really a change but a nicer method to call "talloc_r...
[Samba/nascimento.git] / source4 / dsdb / samdb / ldb_modules / samba3sam.c
blob61013d133e8c386e71ac4caf951f6bf8035cdc0b
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, NULL, 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 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;
198 return out;
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)
204 struct ldb_val out = data_blob(NULL, 0);
205 struct dom_sid *sid;
206 enum ndr_err_code ndr_err;
208 sid = talloc(ctx, struct dom_sid);
209 if (sid == NULL) {
210 return out;
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;
219 out.data = (uint8_t *)dom_sid_string(ctx, sid);
220 if (out.data == NULL) {
221 goto done;
223 out.length = strlen((const char *)out.data);
225 done:
226 talloc_free(sid);
227 return out;
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)
233 struct ldb_val out;
234 struct samr_Password pwd;
235 if (val->length != sizeof(pwd.hash)) {
236 return data_blob(NULL, 0);
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);
243 return out;
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)
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);
255 out = data_blob_talloc(ctx, pwd->hash, sizeof(pwd->hash));
256 return out;
259 const struct ldb_map_objectclass samba3_objectclasses[] = {
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 },
268 .local_name = "group",
269 .remote_name = "posixGroup",
270 .base_classes = { "top", NULL },
271 .musts = { "cn", "gidNumber", NULL },
272 .mays = { "userPassword", "memberUid", "description", NULL },
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 },
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 }
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 },
303 { NULL, NULL }
306 const struct ldb_map_attribute samba3_attributes[] =
308 /* sambaNextRid -> nextRid */
310 .local_name = "nextRid",
311 .type = LDB_MAP_RENAME,
312 .u = {
313 .rename = {
314 .remote_name = "sambaNextRid",
319 /* sambaBadPasswordTime -> badPasswordtime*/
321 .local_name = "badPasswordTime",
322 .type = LDB_MAP_RENAME,
323 .u = {
324 .rename = {
325 .remote_name = "sambaBadPasswordTime",
330 /* sambaLMPassword -> lmPwdHash*/
332 .local_name = "dBCSPwd",
333 .type = LDB_MAP_CONVERT,
334 .u = {
335 .convert = {
336 .remote_name = "sambaLMPassword",
337 .convert_local = bin2hex,
338 .convert_remote = hex2bin,
343 /* sambaGroupType -> groupType */
345 .local_name = "groupType",
346 .type = LDB_MAP_RENAME,
347 .u = {
348 .rename = {
349 .remote_name = "sambaGroupType",
354 /* sambaNTPassword -> ntPwdHash*/
356 .local_name = "ntpwdhash",
357 .type = LDB_MAP_CONVERT,
358 .u = {
359 .convert = {
360 .remote_name = "sambaNTPassword",
361 .convert_local = bin2hex,
362 .convert_remote = hex2bin,
367 /* sambaPrimaryGroupSID -> primaryGroupID */
369 .local_name = "primaryGroupID",
370 .type = LDB_MAP_GENERATE,
371 .u = {
372 .generate = {
373 .remote_names = { "sambaPrimaryGroupSID", NULL },
374 .generate_local = generate_primaryGroupID,
375 .generate_remote = generate_sambaPrimaryGroupSID,
380 /* sambaBadPasswordCount -> badPwdCount */
382 .local_name = "badPwdCount",
383 .type = LDB_MAP_RENAME,
384 .u = {
385 .rename = {
386 .remote_name = "sambaBadPasswordCount",
391 /* sambaLogonTime -> lastLogon*/
393 .local_name = "lastLogon",
394 .type = LDB_MAP_RENAME,
395 .u = {
396 .rename = {
397 .remote_name = "sambaLogonTime",
402 /* sambaLogoffTime -> lastLogoff*/
404 .local_name = "lastLogoff",
405 .type = LDB_MAP_RENAME,
406 .u = {
407 .rename = {
408 .remote_name = "sambaLogoffTime",
413 /* uid -> unixName */
415 .local_name = "unixName",
416 .type = LDB_MAP_RENAME,
417 .u = {
418 .rename = {
419 .remote_name = "uid",
424 /* displayName -> name */
426 .local_name = "name",
427 .type = LDB_MAP_RENAME,
428 .u = {
429 .rename = {
430 .remote_name = "displayName",
435 /* cn */
437 .local_name = "cn",
438 .type = LDB_MAP_KEEP,
441 /* sAMAccountName -> cn */
443 .local_name = "sAMAccountName",
444 .type = LDB_MAP_CONVERT,
445 .u = {
446 .convert = {
447 .remote_name = "uid",
448 .convert_remote = convert_uid_samaccount,
453 /* objectCategory */
455 .local_name = "objectCategory",
456 .type = LDB_MAP_IGNORE,
459 /* objectGUID */
461 .local_name = "objectGUID",
462 .type = LDB_MAP_IGNORE,
465 /* objectVersion */
467 .local_name = "objectVersion",
468 .type = LDB_MAP_IGNORE,
471 /* codePage */
473 .local_name = "codePage",
474 .type = LDB_MAP_IGNORE,
477 /* dNSHostName */
479 .local_name = "dNSHostName",
480 .type = LDB_MAP_IGNORE,
484 /* dnsDomain */
486 .local_name = "dnsDomain",
487 .type = LDB_MAP_IGNORE,
490 /* dnsRoot */
492 .local_name = "dnsRoot",
493 .type = LDB_MAP_IGNORE,
496 /* countryCode */
498 .local_name = "countryCode",
499 .type = LDB_MAP_IGNORE,
502 /* nTMixedDomain */
504 .local_name = "nTMixedDomain",
505 .type = LDB_MAP_IGNORE,
508 /* operatingSystem */
510 .local_name = "operatingSystem",
511 .type = LDB_MAP_IGNORE,
514 /* operatingSystemVersion */
516 .local_name = "operatingSystemVersion",
517 .type = LDB_MAP_IGNORE,
521 /* servicePrincipalName */
523 .local_name = "servicePrincipalName",
524 .type = LDB_MAP_IGNORE,
527 /* msDS-Behavior-Version */
529 .local_name = "msDS-Behavior-Version",
530 .type = LDB_MAP_IGNORE,
533 /* msDS-KeyVersionNumber */
535 .local_name = "msDS-KeyVersionNumber",
536 .type = LDB_MAP_IGNORE,
539 /* msDs-masteredBy */
541 .local_name = "msDs-masteredBy",
542 .type = LDB_MAP_IGNORE,
545 /* ou */
547 .local_name = "ou",
548 .type = LDB_MAP_KEEP,
551 /* dc */
553 .local_name = "dc",
554 .type = LDB_MAP_KEEP,
557 /* description */
559 .local_name = "description",
560 .type = LDB_MAP_KEEP,
563 /* sambaSID -> objectSid*/
565 .local_name = "objectSid",
566 .type = LDB_MAP_CONVERT,
567 .u = {
568 .convert = {
569 .remote_name = "sambaSID",
570 .convert_local = decode_sid,
571 .convert_remote = encode_sid,
576 /* sambaPwdLastSet -> pwdLastSet */
578 .local_name = "pwdLastSet",
579 .type = LDB_MAP_RENAME,
580 .u = {
581 .rename = {
582 .remote_name = "sambaPwdLastSet",
587 /* accountExpires */
589 .local_name = "accountExpires",
590 .type = LDB_MAP_IGNORE,
593 /* adminCount */
595 .local_name = "adminCount",
596 .type = LDB_MAP_IGNORE,
599 /* canonicalName */
601 .local_name = "canonicalName",
602 .type = LDB_MAP_IGNORE,
605 /* createTimestamp */
607 .local_name = "createTimestamp",
608 .type = LDB_MAP_IGNORE,
611 /* creationTime */
613 .local_name = "creationTime",
614 .type = LDB_MAP_IGNORE,
617 /* dMDLocation */
619 .local_name = "dMDLocation",
620 .type = LDB_MAP_IGNORE,
623 /* fSMORoleOwner */
625 .local_name = "fSMORoleOwner",
626 .type = LDB_MAP_IGNORE,
629 /* forceLogoff */
631 .local_name = "forceLogoff",
632 .type = LDB_MAP_IGNORE,
635 /* instanceType */
637 .local_name = "instanceType",
638 .type = LDB_MAP_IGNORE,
641 /* invocationId */
643 .local_name = "invocationId",
644 .type = LDB_MAP_IGNORE,
647 /* isCriticalSystemObject */
649 .local_name = "isCriticalSystemObject",
650 .type = LDB_MAP_IGNORE,
653 /* localPolicyFlags */
655 .local_name = "localPolicyFlags",
656 .type = LDB_MAP_IGNORE,
659 /* lockOutObservationWindow */
661 .local_name = "lockOutObservationWindow",
662 .type = LDB_MAP_IGNORE,
665 /* lockoutDuration */
667 .local_name = "lockoutDuration",
668 .type = LDB_MAP_IGNORE,
671 /* lockoutThreshold */
673 .local_name = "lockoutThreshold",
674 .type = LDB_MAP_IGNORE,
677 /* logonCount */
679 .local_name = "logonCount",
680 .type = LDB_MAP_IGNORE,
683 /* masteredBy */
685 .local_name = "masteredBy",
686 .type = LDB_MAP_IGNORE,
689 /* maxPwdAge */
691 .local_name = "maxPwdAge",
692 .type = LDB_MAP_IGNORE,
695 /* member */
697 .local_name = "member",
698 .type = LDB_MAP_IGNORE,
701 /* memberOf */
703 .local_name = "memberOf",
704 .type = LDB_MAP_IGNORE,
707 /* minPwdAge */
709 .local_name = "minPwdAge",
710 .type = LDB_MAP_IGNORE,
713 /* minPwdLength */
715 .local_name = "minPwdLength",
716 .type = LDB_MAP_IGNORE,
719 /* modifiedCount */
721 .local_name = "modifiedCount",
722 .type = LDB_MAP_IGNORE,
725 /* modifiedCountAtLastProm */
727 .local_name = "modifiedCountAtLastProm",
728 .type = LDB_MAP_IGNORE,
731 /* modifyTimestamp */
733 .local_name = "modifyTimestamp",
734 .type = LDB_MAP_IGNORE,
737 /* nCName */
739 .local_name = "nCName",
740 .type = LDB_MAP_IGNORE,
743 /* nETBIOSName */
745 .local_name = "nETBIOSName",
746 .type = LDB_MAP_IGNORE,
749 /* oEMInformation */
751 .local_name = "oEMInformation",
752 .type = LDB_MAP_IGNORE,
755 /* privilege */
757 .local_name = "privilege",
758 .type = LDB_MAP_IGNORE,
761 /* pwdHistoryLength */
763 .local_name = "pwdHistoryLength",
764 .type = LDB_MAP_IGNORE,
767 /* pwdProperties */
769 .local_name = "pwdProperties",
770 .type = LDB_MAP_IGNORE,
773 /* rIDAvailablePool */
775 .local_name = "rIDAvailablePool",
776 .type = LDB_MAP_IGNORE,
779 /* revision */
781 .local_name = "revision",
782 .type = LDB_MAP_IGNORE,
785 /* ridManagerReference */
787 .local_name = "ridManagerReference",
788 .type = LDB_MAP_IGNORE,
791 /* sAMAccountType */
793 .local_name = "sAMAccountType",
794 .type = LDB_MAP_IGNORE,
797 /* sPNMappings */
799 .local_name = "sPNMappings",
800 .type = LDB_MAP_IGNORE,
803 /* serverReference */
805 .local_name = "serverReference",
806 .type = LDB_MAP_IGNORE,
809 /* serverState */
811 .local_name = "serverState",
812 .type = LDB_MAP_IGNORE,
815 /* showInAdvancedViewOnly */
817 .local_name = "showInAdvancedViewOnly",
818 .type = LDB_MAP_IGNORE,
821 /* subRefs */
823 .local_name = "subRefs",
824 .type = LDB_MAP_IGNORE,
827 /* systemFlags */
829 .local_name = "systemFlags",
830 .type = LDB_MAP_IGNORE,
833 /* uASCompat */
835 .local_name = "uASCompat",
836 .type = LDB_MAP_IGNORE,
839 /* uSNChanged */
841 .local_name = "uSNChanged",
842 .type = LDB_MAP_IGNORE,
845 /* uSNCreated */
847 .local_name = "uSNCreated",
848 .type = LDB_MAP_IGNORE,
851 /* userPassword */
853 .local_name = "userPassword",
854 .type = LDB_MAP_IGNORE,
857 /* userAccountControl */
859 .local_name = "userAccountControl",
860 .type = LDB_MAP_IGNORE,
863 /* whenChanged */
865 .local_name = "whenChanged",
866 .type = LDB_MAP_IGNORE,
869 /* whenCreated */
871 .local_name = "whenCreated",
872 .type = LDB_MAP_IGNORE,
875 /* uidNumber */
877 .local_name = "unixName",
878 .type = LDB_MAP_CONVERT,
879 .u = {
880 .convert = {
881 .remote_name = "uidNumber",
882 .convert_local = lookup_uid,
887 /* gidNumber. Perhaps make into generate so we can distinguish between
888 * groups and accounts? */
890 .local_name = "unixName",
891 .type = LDB_MAP_CONVERT,
892 .u = {
893 .convert = {
894 .remote_name = "gidNumber",
895 .convert_local = lookup_gid,
900 /* homeDirectory */
902 .local_name = "unixName",
903 .type = LDB_MAP_CONVERT,
904 .u = {
905 .convert = {
906 .remote_name = "homeDirectory",
907 .convert_local = lookup_homedir,
912 .local_name = NULL,
916 /* the context init function */
917 static int samba3sam_init(struct ldb_module *module)
919 int ret;
921 ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, NULL, "samba3sam");
922 if (ret != LDB_SUCCESS)
923 return ret;
925 return ldb_next_init(module);
928 _PUBLIC_ const struct ldb_module_ops ldb_samba3sam_module_ops = {
929 LDB_MAP_OPS
930 .name = "samba3sam",
931 .init_context = samba3sam_init,