2 ldb database library - Samba3 SAM compatibility backend
4 Copyright (C) Jelmer Vernooij 2005
8 #include "ldb/modules/ldb_map.h"
9 #include "ldb/include/ldb.h"
10 #include "ldb/include/ldb_private.h"
11 #include "librpc/gen_ndr/ndr_security.h"
12 #include "system/passwd.h"
15 * sambaSID -> member (dn!)
16 * sambaSIDList -> member (dn!)
17 * sambaDomainName -> name
23 * sambaAcctFlags -> systemFlags ?
24 * sambaPasswordHistory -> ntPwdHistory*/
32 * sambaAlgorithmicRidBase
43 * sambaUserWorkstations
47 /* In Samba4 but not in Samba3:
50 static void generate_hashes (struct ldb_module *module, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote_mp, struct ldb_message *remote_fb)
52 const char *upwd = ldb_msg_find_string(local, local_attr, NULL);
58 ldb_msg_add_string(remote_fb, local_attr, upwd);
61 val.data = talloc_zero_size(module, val.length);
63 E_md4hash(upwd, val.data);
64 ldb_msg_add_value(remote_mp, "sambaNTPassword", &val);
66 val.data = talloc_zero_size(module, val.length);
67 E_deshash(upwd, val.data);
68 ldb_msg_add_value(remote_mp, "sambaLMPassword", &val);
72 static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *attr, const struct ldb_message *remote)
74 struct ldb_message_element *el;
75 const char *sid = ldb_msg_find_string(remote, attr, NULL);
80 if (strchr(sid, '-') == NULL)
83 el = talloc_zero(ctx, struct ldb_message_element);
84 el->name = talloc_strdup(ctx, "primaryGroupID");
86 el->values = talloc_array(ctx, struct ldb_val, 1);
87 el->values[0].data = (uint8_t *)talloc_strdup(ctx, strchr(sid, '-')+1);
88 el->values[0].length = strlen((char *)el->values[0].data);
93 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)
95 const struct ldb_val *sidval;
100 sidval = ldb_msg_find_ldb_val(local, "objectSid");
103 return; /* Sorry, no SID today.. */
105 sid = talloc(remote_mp, struct dom_sid);
109 status = ndr_pull_struct_blob(sidval, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
110 if (!NT_STATUS_IS_OK(status)) {
115 if (!ldb_msg_find_ldb_val(local, "primaryGroupID"))
116 return; /* Sorry, no SID today.. */
120 sidstring = dom_sid_string(remote_mp, sid);
122 ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_uint(local, "primaryGroupID", 0));
123 talloc_free(sidstring);
126 static struct ldb_val convert_uid_samaccount(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
128 return ldb_val_dup(ctx, val);
131 static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
134 struct ldb_val retval;
136 pwd = getpwnam((char *)val->data);
139 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to lookup '%s' in passwd", (char *)val->data);
140 return *talloc_zero(ctx, struct ldb_val);
143 retval.data = (uint8_t *)talloc_strdup(ctx, pwd->pw_dir);
144 retval.length = strlen((char *)retval.data);
149 static struct ldb_val lookup_gid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
152 struct ldb_val retval;
154 pwd = getpwnam((char *)val->data);
157 return *talloc_zero(ctx, struct ldb_val);
160 retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_gid);
161 retval.length = strlen((char *)retval.data);
166 static struct ldb_val lookup_uid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
169 struct ldb_val retval;
171 pwd = getpwnam((char *)val->data);
174 return *talloc_zero(ctx, struct ldb_val);
177 retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_uid);
178 retval.length = strlen((char *)retval.data);
183 static struct ldb_val encode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
185 struct dom_sid *sid = dom_sid_parse_talloc(ctx, (char *)val->data);
186 struct ldb_val *out = talloc_zero(ctx, struct ldb_val);
192 status = ndr_push_struct_blob(out, ctx, sid,
193 (ndr_push_flags_fn_t)ndr_push_dom_sid);
195 if (!NT_STATUS_IS_OK(status)) {
202 static struct ldb_val decode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
206 struct ldb_val *out = talloc_zero(ctx, struct ldb_val);
208 sid = talloc(ctx, struct dom_sid);
212 status = ndr_pull_struct_blob(val, sid, sid,
213 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
214 if (!NT_STATUS_IS_OK(status)) {
218 out->data = (uint8_t *)dom_sid_string(ctx, sid);
220 if (out->data == NULL) {
223 out->length = strlen((const char *)out->data);
228 const struct ldb_map_objectclass samba3_objectclasses[] = {
230 .local_name = "user",
231 .remote_name = "posixAccount",
232 .base_classes = { "top", NULL },
233 .musts = { "cn", "uid", "uidNumber", "gidNumber", "homeDirectory", NULL },
234 .mays = { "userPassword", "loginShell", "gecos", "description", NULL },
237 .local_name = "group",
238 .remote_name = "posixGroup",
239 .base_classes = { "top", NULL },
240 .musts = { "cn", "gidNumber", NULL },
241 .mays = { "userPassword", "memberUid", "description", NULL },
244 .local_name = "group",
245 .remote_name = "sambaGroupMapping",
246 .base_classes = { "top", "posixGroup", NULL },
247 .musts = { "gidNumber", "sambaSID", "sambaGroupType", NULL },
248 .mays = { "displayName", "description", "sambaSIDList", NULL },
251 .local_name = "user",
252 .remote_name = "sambaSAMAccount",
253 .base_classes = { "top", "posixAccount", NULL },
254 .musts = { "uid", "sambaSID", NULL },
255 .mays = { "cn", "sambaLMPassword", "sambaNTPassword",
256 "sambaPwdLastSet", "sambaLogonTime", "sambaLogoffTime",
257 "sambaKickoffTime", "sambaPwdCanChange", "sambaPwdMustChange",
258 "sambaAcctFlags", "displayName", "sambaHomePath", "sambaHomeDrive",
259 "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
260 "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
261 "sambaBadPasswordCount", "sambaBadPasswordTime",
262 "sambaPasswordHistory", "sambaLogonHours", NULL }
266 .local_name = "domain",
267 .remote_name = "sambaDomain",
268 .base_classes = { "top", NULL },
269 .musts = { "sambaDomainName", "sambaSID", NULL },
270 .mays = { "sambaNextRid", "sambaNextGroupRid", "sambaNextUserRid", "sambaAlgorithmicRidBase", NULL },
275 const struct ldb_map_attribute samba3_attributes[] =
277 /* sambaNextRid -> nextRid */
279 .local_name = "nextRid",
283 .remote_name = "sambaNextRid",
288 /* sambaBadPasswordTime -> badPasswordtime*/
290 .local_name = "badPasswordTime",
294 .remote_name = "sambaBadPasswordTime",
299 /* sambaLMPassword -> lmPwdHash*/
301 .local_name = "lmPwdHash",
305 .remote_name = "sambaLMPassword",
310 /* sambaGroupType -> groupType */
312 .local_name = "groupType",
316 .remote_name = "sambaGroupType",
321 /* sambaNTPassword -> ntPwdHash*/
323 .local_name = "ntPwdHash",
327 .remote_name = "sambaNTPassword",
332 /* sambaPrimaryGroupSID -> primaryGroupID */
334 .local_name = "primaryGroupID",
335 .type = MAP_GENERATE,
338 .remote_names = { "sambaPrimaryGroupSID", NULL },
339 .generate_local = generate_primaryGroupID,
340 .generate_remote = generate_sambaPrimaryGroupSID,
345 /* sambaBadPasswordCount -> badPwdCount */
347 .local_name = "badPwdCount",
351 .remote_name = "sambaBadPasswordCount",
356 /* sambaLogonTime -> lastLogon*/
358 .local_name = "lastLogon",
362 .remote_name = "sambaLogonTime",
367 /* sambaLogoffTime -> lastLogoff*/
369 .local_name = "lastLogoff",
373 .remote_name = "sambaLogoffTime",
378 /* uid -> unixName */
380 .local_name = "unixName",
384 .remote_name = "uid",
389 /* displayName -> name */
391 .local_name = "name",
395 .remote_name = "displayName",
406 /* sAMAccountName -> cn */
408 .local_name = "sAMAccountName",
412 .remote_name = "uid",
413 .convert_remote = convert_uid_samaccount,
420 .local_name = "objectCategory",
426 .local_name = "objectGUID",
432 .local_name = "objectVersion",
438 .local_name = "codePage",
444 .local_name = "dNSHostName",
451 .local_name = "dnsDomain",
457 .local_name = "dnsRoot",
463 .local_name = "countryCode",
469 .local_name = "nTMixedDomain",
473 /* operatingSystem */
475 .local_name = "operatingSystem",
479 /* operatingSystemVersion */
481 .local_name = "operatingSystemVersion",
486 /* servicePrincipalName */
488 .local_name = "servicePrincipalName",
492 /* msDS-Behavior-Version */
494 .local_name = "msDS-Behavior-Version",
498 /* msDS-KeyVersionNumber */
500 .local_name = "msDS-KeyVersionNumber",
504 /* msDs-masteredBy */
506 .local_name = "msDs-masteredBy",
524 .local_name = "description",
528 /* sambaSID -> objectSid*/
530 .local_name = "objectSid",
534 .remote_name = "sambaSID",
535 .convert_local = decode_sid,
536 .convert_remote = encode_sid,
541 /* sambaPwdLastSet -> pwdLastSet */
543 .local_name = "pwdLastSet",
547 .remote_name = "sambaPwdLastSet",
554 .local_name = "accountExpires",
560 .local_name = "adminCount",
566 .local_name = "canonicalName",
570 /* createTimestamp */
572 .local_name = "createTimestamp",
578 .local_name = "creationTime",
584 .local_name = "dMDLocation",
590 .local_name = "fSMORoleOwner",
596 .local_name = "forceLogoff",
602 .local_name = "instanceType",
608 .local_name = "invocationId",
612 /* isCriticalSystemObject */
614 .local_name = "isCriticalSystemObject",
618 /* localPolicyFlags */
620 .local_name = "localPolicyFlags",
624 /* lockOutObservationWindow */
626 .local_name = "lockOutObservationWindow",
630 /* lockoutDuration */
632 .local_name = "lockoutDuration",
636 /* lockoutThreshold */
638 .local_name = "lockoutThreshold",
644 .local_name = "logonCount",
650 .local_name = "masteredBy",
656 .local_name = "maxPwdAge",
662 .local_name = "member",
668 .local_name = "memberOf",
674 .local_name = "minPwdAge",
680 .local_name = "minPwdLength",
686 .local_name = "modifiedCount",
690 /* modifiedCountAtLastProm */
692 .local_name = "modifiedCountAtLastProm",
696 /* modifyTimestamp */
698 .local_name = "modifyTimestamp",
704 .local_name = "nCName",
710 .local_name = "nETBIOSName",
716 .local_name = "oEMInformation",
722 .local_name = "privilege",
726 /* pwdHistoryLength */
728 .local_name = "pwdHistoryLength",
734 .local_name = "pwdProperties",
738 /* rIDAvailablePool */
740 .local_name = "rIDAvailablePool",
746 .local_name = "revision",
750 /* ridManagerReference */
752 .local_name = "ridManagerReference",
758 .local_name = "sAMAccountType",
764 .local_name = "sPNMappings",
768 /* serverReference */
770 .local_name = "serverReference",
776 .local_name = "serverState",
780 /* showInAdvancedViewOnly */
782 .local_name = "showInAdvancedViewOnly",
788 .local_name = "subRefs",
794 .local_name = "systemFlags",
800 .local_name = "uASCompat",
806 .local_name = "uSNChanged",
812 .local_name = "uSNCreated",
818 .local_name = "unicodePwd",
822 /* userAccountControl */
824 .local_name = "userAccountControl",
830 .local_name = "whenChanged",
836 .local_name = "whenCreated",
842 .local_name = "unixName",
846 .remote_name = "uidNumber",
847 .convert_local = lookup_uid,
852 /* gidNumber. Perhaps make into generate so we can distinguish between
853 * groups and accounts? */
855 .local_name = "unixName",
859 .remote_name = "gidNumber",
860 .convert_local = lookup_gid,
867 .local_name = "unixName",
871 .remote_name = "homeDirectory",
872 .convert_local = lookup_homedir,
879 .local_name = "unicodePwd",
880 .type = MAP_GENERATE,
883 .remote_names = { "sambaNTPassword", "sambaLMPassword", NULL },
884 .generate_local = NULL,
885 .generate_remote = generate_hashes
894 /* the init function */
895 #ifdef HAVE_DLOPEN_DISABLED
896 struct ldb_module *init_module(struct ldb_context *ldb, const char *options[])
898 struct ldb_module *ldb_samba3sam_module_init(struct ldb_context *ldb, const char *options[])
901 return ldb_map_init(ldb, samba3_attributes, samba3_objectclasses, "samba3sam");