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.h"
10 #include "ldb/include/ldb_private.h"
11 #include "ldb/include/ldb_errors.h"
12 #include "ldb/modules/ldb_map.h"
13 #include "system/passwd.h"
15 #include "librpc/gen_ndr/ndr_security.h"
16 #include "librpc/gen_ndr/ndr_samr.h"
17 #include "librpc/ndr/libndr.h"
18 #include "libcli/security/security.h"
19 #include "libcli/security/proto.h"
20 #include "lib/samba3/samba3.h"
23 * sambaSID -> member (dn!)
24 * sambaSIDList -> member (dn!)
25 * sambaDomainName -> name
31 * sambaAcctFlags -> systemFlags ?
32 * sambaPasswordHistory -> ntPwdHistory*/
40 * sambaAlgorithmicRidBase
51 * sambaUserWorkstations
55 /* In Samba4 but not in Samba3:
58 /* From a sambaPrimaryGroupSID, generate a primaryGroupID (integer) attribute */
59 static struct ldb_message_element
*generate_primaryGroupID(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const char *local_attr
, const struct ldb_message
*remote
)
61 struct ldb_message_element
*el
;
62 const char *sid
= ldb_msg_find_attr_as_string(remote
, "sambaPrimaryGroupSID", NULL
);
68 p
= strrchr(sid
, '-');
72 el
= talloc_zero(ctx
, struct ldb_message_element
);
73 el
->name
= talloc_strdup(ctx
, "primaryGroupID");
75 el
->values
= talloc_array(ctx
, struct ldb_val
, 1);
76 el
->values
[0].data
= (uint8_t *)talloc_strdup(el
->values
, p
+1);
77 el
->values
[0].length
= strlen((char *)el
->values
[0].data
);
82 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
)
84 const struct ldb_val
*sidval
;
89 /* We need the domain, so we get it from the objectSid that we hope is here... */
90 sidval
= ldb_msg_find_ldb_val(local
, "objectSid");
93 return; /* Sorry, no SID today.. */
95 sid
= talloc(remote_mp
, struct dom_sid
);
99 status
= ndr_pull_struct_blob(sidval
, sid
, sid
, (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
100 if (!NT_STATUS_IS_OK(status
)) {
105 if (!ldb_msg_find_ldb_val(local
, "primaryGroupID"))
106 return; /* Sorry, no SID today.. */
110 sidstring
= dom_sid_string(remote_mp
, sid
);
112 ldb_msg_add_fmt(remote_mp
, "sambaPrimaryGroupSID", "%s-%d", sidstring
, ldb_msg_find_attr_as_uint(local
, "primaryGroupID", 0));
113 talloc_free(sidstring
);
116 /* Just copy the old value. */
117 static struct ldb_val
convert_uid_samaccount(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
119 struct ldb_val out
= data_blob(NULL
, 0);
120 ldb_handler_copy(module
->ldb
, ctx
, val
, &out
);
125 static struct ldb_val
lookup_homedir(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
128 struct ldb_val retval
;
130 pwd
= getpwnam((char *)val
->data
);
133 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
, "Unable to lookup '%s' in passwd", (char *)val
->data
);
134 return *talloc_zero(ctx
, struct ldb_val
);
137 retval
.data
= (uint8_t *)talloc_strdup(ctx
, pwd
->pw_dir
);
138 retval
.length
= strlen((char *)retval
.data
);
143 static struct ldb_val
lookup_gid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
146 struct ldb_val retval
;
148 pwd
= getpwnam((char *)val
->data
);
151 return *talloc_zero(ctx
, struct ldb_val
);
154 retval
.data
= (uint8_t *)talloc_asprintf(ctx
, "%ld", (unsigned long)pwd
->pw_gid
);
155 retval
.length
= strlen((char *)retval
.data
);
160 static struct ldb_val
lookup_uid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
163 struct ldb_val retval
;
165 pwd
= getpwnam((char *)val
->data
);
168 return *talloc_zero(ctx
, struct ldb_val
);
171 retval
.data
= (uint8_t *)talloc_asprintf(ctx
, "%ld", (unsigned long)pwd
->pw_uid
);
172 retval
.length
= strlen((char *)retval
.data
);
177 /* Encode a sambaSID to an objectSid. */
178 static struct ldb_val
encode_sid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
180 struct ldb_val out
= data_blob(NULL
, 0);
184 sid
= dom_sid_parse_talloc(ctx
, (char *)val
->data
);
189 status
= ndr_push_struct_blob(&out
, ctx
, sid
,
190 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
192 if (!NT_STATUS_IS_OK(status
)) {
199 /* Decode an objectSid to a sambaSID. */
200 static struct ldb_val
decode_sid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
202 struct ldb_val out
= data_blob(NULL
, 0);
206 sid
= talloc(ctx
, struct dom_sid
);
211 status
= ndr_pull_struct_blob(val
, sid
, sid
,
212 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
213 if (!NT_STATUS_IS_OK(status
)) {
217 out
.data
= (uint8_t *)dom_sid_string(ctx
, sid
);
218 if (out
.data
== NULL
) {
221 out
.length
= strlen((const char *)out
.data
);
228 /* Convert 16 bytes to 32 hex digits. */
229 static struct ldb_val
bin2hex(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
232 struct samr_Password pwd
;
233 if (val
->length
!= sizeof(pwd
.hash
)) {
234 return data_blob(NULL
, 0);
236 memcpy(pwd
.hash
, val
->data
, sizeof(pwd
.hash
));
237 out
= data_blob_string_const(smbpasswd_sethexpwd(ctx
, &pwd
, 0));
239 return data_blob(NULL
, 0);
244 /* Convert 32 hex digits to 16 bytes. */
245 static struct ldb_val
hex2bin(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
248 struct samr_Password
*pwd
;
249 pwd
= smbpasswd_gethexpwd(ctx
, (const char *)val
->data
);
251 return data_blob(NULL
, 0);
253 out
= data_blob_talloc(ctx
, pwd
->hash
, sizeof(pwd
->hash
));
257 const struct ldb_map_objectclass samba3_objectclasses
[] = {
259 .local_name
= "user",
260 .remote_name
= "posixAccount",
261 .base_classes
= { "top", NULL
},
262 .musts
= { "cn", "uid", "uidNumber", "gidNumber", "homeDirectory", NULL
},
263 .mays
= { "userPassword", "loginShell", "gecos", "description", NULL
},
266 .local_name
= "group",
267 .remote_name
= "posixGroup",
268 .base_classes
= { "top", NULL
},
269 .musts
= { "cn", "gidNumber", NULL
},
270 .mays
= { "userPassword", "memberUid", "description", NULL
},
273 .local_name
= "group",
274 .remote_name
= "sambaGroupMapping",
275 .base_classes
= { "top", "posixGroup", NULL
},
276 .musts
= { "gidNumber", "sambaSID", "sambaGroupType", NULL
},
277 .mays
= { "displayName", "description", "sambaSIDList", NULL
},
280 .local_name
= "user",
281 .remote_name
= "sambaSAMAccount",
282 .base_classes
= { "top", "posixAccount", NULL
},
283 .musts
= { "uid", "sambaSID", NULL
},
284 .mays
= { "cn", "sambaLMPassword", "sambaNTPassword",
285 "sambaPwdLastSet", "sambaLogonTime", "sambaLogoffTime",
286 "sambaKickoffTime", "sambaPwdCanChange", "sambaPwdMustChange",
287 "sambaAcctFlags", "displayName", "sambaHomePath", "sambaHomeDrive",
288 "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
289 "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
290 "sambaBadPasswordCount", "sambaBadPasswordTime",
291 "sambaPasswordHistory", "sambaLogonHours", NULL
}
295 .local_name
= "domain",
296 .remote_name
= "sambaDomain",
297 .base_classes
= { "top", NULL
},
298 .musts
= { "sambaDomainName", "sambaSID", NULL
},
299 .mays
= { "sambaNextRid", "sambaNextGroupRid", "sambaNextUserRid", "sambaAlgorithmicRidBase", NULL
},
304 const struct ldb_map_attribute samba3_attributes
[] =
306 /* sambaNextRid -> nextRid */
308 .local_name
= "nextRid",
312 .remote_name
= "sambaNextRid",
317 /* sambaBadPasswordTime -> badPasswordtime*/
319 .local_name
= "badPasswordTime",
323 .remote_name
= "sambaBadPasswordTime",
328 /* sambaLMPassword -> lmPwdHash*/
330 .local_name
= "dBCSPwd",
334 .remote_name
= "sambaLMPassword",
335 .convert_local
= bin2hex
,
336 .convert_remote
= hex2bin
,
341 /* sambaGroupType -> groupType */
343 .local_name
= "groupType",
347 .remote_name
= "sambaGroupType",
352 /* sambaNTPassword -> ntPwdHash*/
354 .local_name
= "ntpwdhash",
358 .remote_name
= "sambaNTPassword",
359 .convert_local
= bin2hex
,
360 .convert_remote
= hex2bin
,
365 /* sambaPrimaryGroupSID -> primaryGroupID */
367 .local_name
= "primaryGroupID",
368 .type
= MAP_GENERATE
,
371 .remote_names
= { "sambaPrimaryGroupSID", NULL
},
372 .generate_local
= generate_primaryGroupID
,
373 .generate_remote
= generate_sambaPrimaryGroupSID
,
378 /* sambaBadPasswordCount -> badPwdCount */
380 .local_name
= "badPwdCount",
384 .remote_name
= "sambaBadPasswordCount",
389 /* sambaLogonTime -> lastLogon*/
391 .local_name
= "lastLogon",
395 .remote_name
= "sambaLogonTime",
400 /* sambaLogoffTime -> lastLogoff*/
402 .local_name
= "lastLogoff",
406 .remote_name
= "sambaLogoffTime",
411 /* uid -> unixName */
413 .local_name
= "unixName",
417 .remote_name
= "uid",
422 /* displayName -> name */
424 .local_name
= "name",
428 .remote_name
= "displayName",
439 /* sAMAccountName -> cn */
441 .local_name
= "sAMAccountName",
445 .remote_name
= "uid",
446 .convert_remote
= convert_uid_samaccount
,
453 .local_name
= "objectCategory",
459 .local_name
= "objectGUID",
465 .local_name
= "objectVersion",
471 .local_name
= "codePage",
477 .local_name
= "dNSHostName",
484 .local_name
= "dnsDomain",
490 .local_name
= "dnsRoot",
496 .local_name
= "countryCode",
502 .local_name
= "nTMixedDomain",
506 /* operatingSystem */
508 .local_name
= "operatingSystem",
512 /* operatingSystemVersion */
514 .local_name
= "operatingSystemVersion",
519 /* servicePrincipalName */
521 .local_name
= "servicePrincipalName",
525 /* msDS-Behavior-Version */
527 .local_name
= "msDS-Behavior-Version",
531 /* msDS-KeyVersionNumber */
533 .local_name
= "msDS-KeyVersionNumber",
537 /* msDs-masteredBy */
539 .local_name
= "msDs-masteredBy",
557 .local_name
= "description",
561 /* sambaSID -> objectSid*/
563 .local_name
= "objectSid",
567 .remote_name
= "sambaSID",
568 .convert_local
= decode_sid
,
569 .convert_remote
= encode_sid
,
574 /* sambaPwdLastSet -> pwdLastSet */
576 .local_name
= "pwdLastSet",
580 .remote_name
= "sambaPwdLastSet",
587 .local_name
= "accountExpires",
593 .local_name
= "adminCount",
599 .local_name
= "canonicalName",
603 /* createTimestamp */
605 .local_name
= "createTimestamp",
611 .local_name
= "creationTime",
617 .local_name
= "dMDLocation",
623 .local_name
= "fSMORoleOwner",
629 .local_name
= "forceLogoff",
635 .local_name
= "instanceType",
641 .local_name
= "invocationId",
645 /* isCriticalSystemObject */
647 .local_name
= "isCriticalSystemObject",
651 /* localPolicyFlags */
653 .local_name
= "localPolicyFlags",
657 /* lockOutObservationWindow */
659 .local_name
= "lockOutObservationWindow",
663 /* lockoutDuration */
665 .local_name
= "lockoutDuration",
669 /* lockoutThreshold */
671 .local_name
= "lockoutThreshold",
677 .local_name
= "logonCount",
683 .local_name
= "masteredBy",
689 .local_name
= "maxPwdAge",
695 .local_name
= "member",
701 .local_name
= "memberOf",
707 .local_name
= "minPwdAge",
713 .local_name
= "minPwdLength",
719 .local_name
= "modifiedCount",
723 /* modifiedCountAtLastProm */
725 .local_name
= "modifiedCountAtLastProm",
729 /* modifyTimestamp */
731 .local_name
= "modifyTimestamp",
737 .local_name
= "nCName",
743 .local_name
= "nETBIOSName",
749 .local_name
= "oEMInformation",
755 .local_name
= "privilege",
759 /* pwdHistoryLength */
761 .local_name
= "pwdHistoryLength",
767 .local_name
= "pwdProperties",
771 /* rIDAvailablePool */
773 .local_name
= "rIDAvailablePool",
779 .local_name
= "revision",
783 /* ridManagerReference */
785 .local_name
= "ridManagerReference",
791 .local_name
= "sAMAccountType",
797 .local_name
= "sPNMappings",
801 /* serverReference */
803 .local_name
= "serverReference",
809 .local_name
= "serverState",
813 /* showInAdvancedViewOnly */
815 .local_name
= "showInAdvancedViewOnly",
821 .local_name
= "subRefs",
827 .local_name
= "systemFlags",
833 .local_name
= "uASCompat",
839 .local_name
= "uSNChanged",
845 .local_name
= "uSNCreated",
851 .local_name
= "sambaPassword",
855 /* userAccountControl */
857 .local_name
= "userAccountControl",
863 .local_name
= "whenChanged",
869 .local_name
= "whenCreated",
875 .local_name
= "unixName",
879 .remote_name
= "uidNumber",
880 .convert_local
= lookup_uid
,
885 /* gidNumber. Perhaps make into generate so we can distinguish between
886 * groups and accounts? */
888 .local_name
= "unixName",
892 .remote_name
= "gidNumber",
893 .convert_local
= lookup_gid
,
900 .local_name
= "unixName",
904 .remote_name
= "homeDirectory",
905 .convert_local
= lookup_homedir
,
914 /* the context init function */
915 static int samba3sam_init(struct ldb_module
*module
)
919 ret
= ldb_map_init(module
, samba3_attributes
, samba3_objectclasses
, NULL
, "samba3sam");
920 if (ret
!= LDB_SUCCESS
)
923 return ldb_next_init(module
);
926 static struct ldb_module_ops samba3sam_ops
= {
928 .init_context
= samba3sam_init
,
931 /* the init function */
932 int ldb_samba3sam_module_init(void)
934 struct ldb_module_ops ops
= ldb_map_get_ops();
935 samba3sam_ops
.add
= ops
.add
;
936 samba3sam_ops
.modify
= ops
.modify
;
937 samba3sam_ops
.del
= ops
.del
;
938 samba3sam_ops
.rename
= ops
.rename
;
939 samba3sam_ops
.search
= ops
.search
;
940 samba3sam_ops
.wait
= ops
.wait
;
942 return ldb_register_module(&samba3sam_ops
);