2 ldb database library - Samba3 SAM compatibility backend
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
9 #include "ldb/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
29 * sambaAcctFlags -> systemFlags ?
30 * sambaPasswordHistory -> ntPwdHistory*/
38 * sambaAlgorithmicRidBase
49 * sambaUserWorkstations
53 /* In Samba4 but not in Samba3:
56 /* From a sambaPrimaryGroupSID, generate a primaryGroupID (integer) attribute */
57 static struct ldb_message_element *generate_primaryGroupID(struct ldb_module *module, TALLOC_CTX *ctx, const char *local_attr, const struct ldb_message *remote)
59 struct ldb_message_element *el;
60 const char *sid = ldb_msg_find_attr_as_string(remote, "sambaPrimaryGroupSID", NULL);
66 p = strrchr(sid, '-');
70 el = talloc_zero(ctx, struct ldb_message_element);
71 el->name = talloc_strdup(ctx, "primaryGroupID");
73 el->values = talloc_array(ctx, struct ldb_val, 1);
74 el->values[0].data = (uint8_t *)talloc_strdup(el->values, p+1);
75 el->values[0].length = strlen((char *)el->values[0].data);
80 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)
82 const struct ldb_val *sidval;
85 enum ndr_err_code ndr_err;
87 /* We need the domain, so we get it from the objectSid that we hope is here... */
88 sidval = ldb_msg_find_ldb_val(local, "objectSid");
91 return; /* Sorry, no SID today.. */
93 sid = talloc(remote_mp, struct dom_sid);
98 ndr_err = ndr_pull_struct_blob(sidval, sid, NULL, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
99 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
104 if (!ldb_msg_find_ldb_val(local, "primaryGroupID"))
105 return; /* Sorry, no SID today.. */
109 sidstring = dom_sid_string(remote_mp, sid);
111 ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_attr_as_uint(local, "primaryGroupID", 0));
112 talloc_free(sidstring);
115 /* Just copy the old value. */
116 static struct ldb_val convert_uid_samaccount(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
118 struct ldb_val out = data_blob(NULL, 0);
119 out = ldb_val_dup(ctx, val);
124 static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
126 struct ldb_context *ldb;
128 struct ldb_val retval;
130 ldb = ldb_module_get_ctx(module);
132 pwd = getpwnam((char *)val->data);
135 ldb_debug(ldb, LDB_DEBUG_WARNING, "Unable to lookup '%s' in passwd", (char *)val->data);
136 return *talloc_zero(ctx, struct ldb_val);
139 retval.data = (uint8_t *)talloc_strdup(ctx, pwd->pw_dir);
140 retval.length = strlen((char *)retval.data);
145 static struct ldb_val lookup_gid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
148 struct ldb_val retval;
150 pwd = getpwnam((char *)val->data);
153 return *talloc_zero(ctx, struct ldb_val);
156 retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_gid);
157 retval.length = strlen((char *)retval.data);
162 static struct ldb_val lookup_uid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
165 struct ldb_val retval;
167 pwd = getpwnam((char *)val->data);
170 return *talloc_zero(ctx, struct ldb_val);
173 retval.data = (uint8_t *)talloc_asprintf(ctx, "%ld", (unsigned long)pwd->pw_uid);
174 retval.length = strlen((char *)retval.data);
179 /* Encode a sambaSID to an objectSid. */
180 static struct ldb_val encode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
182 struct ldb_val out = data_blob(NULL, 0);
184 enum ndr_err_code ndr_err;
186 sid = dom_sid_parse_talloc(ctx, (char *)val->data);
191 ndr_err = ndr_push_struct_blob(&out, ctx,
193 sid, (ndr_push_flags_fn_t)ndr_push_dom_sid);
195 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
202 /* Decode an objectSid to a sambaSID. */
203 static struct ldb_val decode_sid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
205 struct ldb_val out = data_blob(NULL, 0);
207 enum ndr_err_code ndr_err;
209 sid = talloc(ctx, struct dom_sid);
214 ndr_err = ndr_pull_struct_blob(val, sid, NULL, sid,
215 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
216 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
220 out.data = (uint8_t *)dom_sid_string(ctx, sid);
221 if (out.data == NULL) {
224 out.length = strlen((const char *)out.data);
231 /* Convert 16 bytes to 32 hex digits. */
232 static struct ldb_val bin2hex(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
235 struct samr_Password pwd;
236 if (val->length != sizeof(pwd.hash)) {
237 return data_blob(NULL, 0);
239 memcpy(pwd.hash, val->data, sizeof(pwd.hash));
240 out = data_blob_string_const(smbpasswd_sethexpwd(ctx, &pwd, 0));
242 return data_blob(NULL, 0);
247 /* Convert 32 hex digits to 16 bytes. */
248 static struct ldb_val hex2bin(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
251 struct samr_Password *pwd;
252 pwd = smbpasswd_gethexpwd(ctx, (const char *)val->data);
254 return data_blob(NULL, 0);
256 out = data_blob_talloc(ctx, pwd->hash, sizeof(pwd->hash));
260 const struct ldb_map_objectclass samba3_objectclasses[] = {
262 .local_name = "user",
263 .remote_name = "posixAccount",
264 .base_classes = { "top", NULL },
265 .musts = { "cn", "uid", "uidNumber", "gidNumber", "homeDirectory", NULL },
266 .mays = { "userPassword", "loginShell", "gecos", "description", NULL },
269 .local_name = "group",
270 .remote_name = "posixGroup",
271 .base_classes = { "top", NULL },
272 .musts = { "cn", "gidNumber", NULL },
273 .mays = { "userPassword", "memberUid", "description", NULL },
276 .local_name = "group",
277 .remote_name = "sambaGroupMapping",
278 .base_classes = { "top", "posixGroup", NULL },
279 .musts = { "gidNumber", "sambaSID", "sambaGroupType", NULL },
280 .mays = { "displayName", "description", "sambaSIDList", NULL },
283 .local_name = "user",
284 .remote_name = "sambaSAMAccount",
285 .base_classes = { "top", "posixAccount", NULL },
286 .musts = { "uid", "sambaSID", NULL },
287 .mays = { "cn", "sambaLMPassword", "sambaNTPassword",
288 "sambaPwdLastSet", "sambaLogonTime", "sambaLogoffTime",
289 "sambaKickoffTime", "sambaPwdCanChange", "sambaPwdMustChange",
290 "sambaAcctFlags", "displayName", "sambaHomePath", "sambaHomeDrive",
291 "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
292 "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
293 "sambaBadPasswordCount", "sambaBadPasswordTime",
294 "sambaPasswordHistory", "sambaLogonHours", NULL }
298 .local_name = "domain",
299 .remote_name = "sambaDomain",
300 .base_classes = { "top", NULL },
301 .musts = { "sambaDomainName", "sambaSID", NULL },
302 .mays = { "sambaNextRid", "sambaNextGroupRid", "sambaNextUserRid", "sambaAlgorithmicRidBase", NULL },
307 const struct ldb_map_attribute samba3_attributes[] =
309 /* sambaNextRid -> nextRid */
311 .local_name = "nextRid",
315 .remote_name = "sambaNextRid",
320 /* sambaBadPasswordTime -> badPasswordtime*/
322 .local_name = "badPasswordTime",
326 .remote_name = "sambaBadPasswordTime",
331 /* sambaLMPassword -> lmPwdHash*/
333 .local_name = "dBCSPwd",
337 .remote_name = "sambaLMPassword",
338 .convert_local = bin2hex,
339 .convert_remote = hex2bin,
344 /* sambaGroupType -> groupType */
346 .local_name = "groupType",
350 .remote_name = "sambaGroupType",
355 /* sambaNTPassword -> ntPwdHash*/
357 .local_name = "ntpwdhash",
361 .remote_name = "sambaNTPassword",
362 .convert_local = bin2hex,
363 .convert_remote = hex2bin,
368 /* sambaPrimaryGroupSID -> primaryGroupID */
370 .local_name = "primaryGroupID",
371 .type = MAP_GENERATE,
374 .remote_names = { "sambaPrimaryGroupSID", NULL },
375 .generate_local = generate_primaryGroupID,
376 .generate_remote = generate_sambaPrimaryGroupSID,
381 /* sambaBadPasswordCount -> badPwdCount */
383 .local_name = "badPwdCount",
387 .remote_name = "sambaBadPasswordCount",
392 /* sambaLogonTime -> lastLogon*/
394 .local_name = "lastLogon",
398 .remote_name = "sambaLogonTime",
403 /* sambaLogoffTime -> lastLogoff*/
405 .local_name = "lastLogoff",
409 .remote_name = "sambaLogoffTime",
414 /* uid -> unixName */
416 .local_name = "unixName",
420 .remote_name = "uid",
425 /* displayName -> name */
427 .local_name = "name",
431 .remote_name = "displayName",
442 /* sAMAccountName -> cn */
444 .local_name = "sAMAccountName",
448 .remote_name = "uid",
449 .convert_remote = convert_uid_samaccount,
456 .local_name = "objectCategory",
462 .local_name = "objectGUID",
468 .local_name = "objectVersion",
474 .local_name = "codePage",
480 .local_name = "dNSHostName",
487 .local_name = "dnsDomain",
493 .local_name = "dnsRoot",
499 .local_name = "countryCode",
505 .local_name = "nTMixedDomain",
509 /* operatingSystem */
511 .local_name = "operatingSystem",
515 /* operatingSystemVersion */
517 .local_name = "operatingSystemVersion",
522 /* servicePrincipalName */
524 .local_name = "servicePrincipalName",
528 /* msDS-Behavior-Version */
530 .local_name = "msDS-Behavior-Version",
534 /* msDS-KeyVersionNumber */
536 .local_name = "msDS-KeyVersionNumber",
540 /* msDs-masteredBy */
542 .local_name = "msDs-masteredBy",
560 .local_name = "description",
564 /* sambaSID -> objectSid*/
566 .local_name = "objectSid",
570 .remote_name = "sambaSID",
571 .convert_local = decode_sid,
572 .convert_remote = encode_sid,
577 /* sambaPwdLastSet -> pwdLastSet */
579 .local_name = "pwdLastSet",
583 .remote_name = "sambaPwdLastSet",
590 .local_name = "accountExpires",
596 .local_name = "adminCount",
602 .local_name = "canonicalName",
606 /* createTimestamp */
608 .local_name = "createTimestamp",
614 .local_name = "creationTime",
620 .local_name = "dMDLocation",
626 .local_name = "fSMORoleOwner",
632 .local_name = "forceLogoff",
638 .local_name = "instanceType",
644 .local_name = "invocationId",
648 /* isCriticalSystemObject */
650 .local_name = "isCriticalSystemObject",
654 /* localPolicyFlags */
656 .local_name = "localPolicyFlags",
660 /* lockOutObservationWindow */
662 .local_name = "lockOutObservationWindow",
666 /* lockoutDuration */
668 .local_name = "lockoutDuration",
672 /* lockoutThreshold */
674 .local_name = "lockoutThreshold",
680 .local_name = "logonCount",
686 .local_name = "masteredBy",
692 .local_name = "maxPwdAge",
698 .local_name = "member",
704 .local_name = "memberOf",
710 .local_name = "minPwdAge",
716 .local_name = "minPwdLength",
722 .local_name = "modifiedCount",
726 /* modifiedCountAtLastProm */
728 .local_name = "modifiedCountAtLastProm",
732 /* modifyTimestamp */
734 .local_name = "modifyTimestamp",
740 .local_name = "nCName",
746 .local_name = "nETBIOSName",
752 .local_name = "oEMInformation",
758 .local_name = "privilege",
762 /* pwdHistoryLength */
764 .local_name = "pwdHistoryLength",
770 .local_name = "pwdProperties",
774 /* rIDAvailablePool */
776 .local_name = "rIDAvailablePool",
782 .local_name = "revision",
786 /* ridManagerReference */
788 .local_name = "ridManagerReference",
794 .local_name = "sAMAccountType",
800 .local_name = "sPNMappings",
804 /* serverReference */
806 .local_name = "serverReference",
812 .local_name = "serverState",
816 /* showInAdvancedViewOnly */
818 .local_name = "showInAdvancedViewOnly",
824 .local_name = "subRefs",
830 .local_name = "systemFlags",
836 .local_name = "uASCompat",
842 .local_name = "uSNChanged",
848 .local_name = "uSNCreated",
854 .local_name = "userPassword",
858 /* userAccountControl */
860 .local_name = "userAccountControl",
866 .local_name = "whenChanged",
872 .local_name = "whenCreated",
878 .local_name = "unixName",
882 .remote_name = "uidNumber",
883 .convert_local = lookup_uid,
888 /* gidNumber. Perhaps make into generate so we can distinguish between
889 * groups and accounts? */
891 .local_name = "unixName",
895 .remote_name = "gidNumber",
896 .convert_local = lookup_gid,
903 .local_name = "unixName",
907 .remote_name = "homeDirectory",
908 .convert_local = lookup_homedir,
917 /* the context init function */
918 static int samba3sam_init(struct ldb_module *module)
922 ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, NULL, "samba3sam");
923 if (ret != LDB_SUCCESS)
926 return ldb_next_init(module);
929 _PUBLIC_ const struct ldb_module_ops ldb_samba3sam_module_ops = {
932 .init_context = samba3sam_init,