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_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
28 * sambaAcctFlags -> systemFlags ?
29 * sambaPasswordHistory -> ntPwdHistory*/
37 * sambaAlgorithmicRidBase
48 * sambaUserWorkstations
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
);
65 p
= strrchr(sid
, '-');
69 el
= talloc_zero(ctx
, struct ldb_message_element
);
70 el
->name
= talloc_strdup(ctx
, "primaryGroupID");
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
);
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
;
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");
90 return; /* Sorry, no SID today.. */
92 sid
= talloc(remote_mp
, struct dom_sid
);
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
)) {
103 if (!ldb_msg_find_ldb_val(local
, "primaryGroupID"))
104 return; /* Sorry, no SID today.. */
108 sidstring
= dom_sid_string(remote_mp
, 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
);
123 static struct ldb_val
lookup_homedir(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
125 struct ldb_context
*ldb
;
127 struct ldb_val retval
;
129 ldb
= ldb_module_get_ctx(module
);
131 pwd
= getpwnam((char *)val
->data
);
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
);
144 static struct ldb_val
lookup_gid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
147 struct ldb_val retval
;
149 pwd
= getpwnam((char *)val
->data
);
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
);
161 static struct ldb_val
lookup_uid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
164 struct ldb_val retval
;
166 pwd
= getpwnam((char *)val
->data
);
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
);
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);
183 enum ndr_err_code ndr_err
;
185 sid
= dom_sid_parse_talloc(ctx
, (char *)val
->data
);
190 ndr_err
= ndr_push_struct_blob(&out
, ctx
,
192 sid
, (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
194 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
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);
206 enum ndr_err_code ndr_err
;
208 sid
= talloc(ctx
, struct dom_sid
);
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
)) {
219 out
.data
= (uint8_t *)dom_sid_string(ctx
, sid
);
220 if (out
.data
== NULL
) {
223 out
.length
= strlen((const char *)out
.data
);
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
)
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));
241 return data_blob(NULL
, 0);
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
)
250 struct samr_Password
*pwd
;
251 pwd
= smbpasswd_gethexpwd(ctx
, (const char *)val
->data
);
253 return data_blob(NULL
, 0);
255 out
= data_blob_talloc(ctx
, pwd
->hash
, sizeof(pwd
->hash
));
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
},
306 const struct ldb_map_attribute samba3_attributes
[] =
308 /* sambaNextRid -> nextRid */
310 .local_name
= "nextRid",
311 .type
= LDB_MAP_RENAME
,
314 .remote_name
= "sambaNextRid",
319 /* sambaBadPasswordTime -> badPasswordtime*/
321 .local_name
= "badPasswordTime",
322 .type
= LDB_MAP_RENAME
,
325 .remote_name
= "sambaBadPasswordTime",
330 /* sambaLMPassword -> lmPwdHash*/
332 .local_name
= "dBCSPwd",
333 .type
= LDB_MAP_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
,
349 .remote_name
= "sambaGroupType",
354 /* sambaNTPassword -> ntPwdHash*/
356 .local_name
= "ntpwdhash",
357 .type
= LDB_MAP_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
,
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
,
386 .remote_name
= "sambaBadPasswordCount",
391 /* sambaLogonTime -> lastLogon*/
393 .local_name
= "lastLogon",
394 .type
= LDB_MAP_RENAME
,
397 .remote_name
= "sambaLogonTime",
402 /* sambaLogoffTime -> lastLogoff*/
404 .local_name
= "lastLogoff",
405 .type
= LDB_MAP_RENAME
,
408 .remote_name
= "sambaLogoffTime",
413 /* uid -> unixName */
415 .local_name
= "unixName",
416 .type
= LDB_MAP_RENAME
,
419 .remote_name
= "uid",
424 /* displayName -> name */
426 .local_name
= "name",
427 .type
= LDB_MAP_RENAME
,
430 .remote_name
= "displayName",
438 .type
= LDB_MAP_KEEP
,
441 /* sAMAccountName -> cn */
443 .local_name
= "sAMAccountName",
444 .type
= LDB_MAP_CONVERT
,
447 .remote_name
= "uid",
448 .convert_remote
= convert_uid_samaccount
,
455 .local_name
= "objectCategory",
456 .type
= LDB_MAP_IGNORE
,
461 .local_name
= "objectGUID",
462 .type
= LDB_MAP_IGNORE
,
467 .local_name
= "objectVersion",
468 .type
= LDB_MAP_IGNORE
,
473 .local_name
= "codePage",
474 .type
= LDB_MAP_IGNORE
,
479 .local_name
= "dNSHostName",
480 .type
= LDB_MAP_IGNORE
,
486 .local_name
= "dnsDomain",
487 .type
= LDB_MAP_IGNORE
,
492 .local_name
= "dnsRoot",
493 .type
= LDB_MAP_IGNORE
,
498 .local_name
= "countryCode",
499 .type
= LDB_MAP_IGNORE
,
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
,
548 .type
= LDB_MAP_KEEP
,
554 .type
= LDB_MAP_KEEP
,
559 .local_name
= "description",
560 .type
= LDB_MAP_KEEP
,
563 /* sambaSID -> objectSid*/
565 .local_name
= "objectSid",
566 .type
= LDB_MAP_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
,
582 .remote_name
= "sambaPwdLastSet",
589 .local_name
= "accountExpires",
590 .type
= LDB_MAP_IGNORE
,
595 .local_name
= "adminCount",
596 .type
= LDB_MAP_IGNORE
,
601 .local_name
= "canonicalName",
602 .type
= LDB_MAP_IGNORE
,
605 /* createTimestamp */
607 .local_name
= "createTimestamp",
608 .type
= LDB_MAP_IGNORE
,
613 .local_name
= "creationTime",
614 .type
= LDB_MAP_IGNORE
,
619 .local_name
= "dMDLocation",
620 .type
= LDB_MAP_IGNORE
,
625 .local_name
= "fSMORoleOwner",
626 .type
= LDB_MAP_IGNORE
,
631 .local_name
= "forceLogoff",
632 .type
= LDB_MAP_IGNORE
,
637 .local_name
= "instanceType",
638 .type
= LDB_MAP_IGNORE
,
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
,
679 .local_name
= "logonCount",
680 .type
= LDB_MAP_IGNORE
,
685 .local_name
= "masteredBy",
686 .type
= LDB_MAP_IGNORE
,
691 .local_name
= "maxPwdAge",
692 .type
= LDB_MAP_IGNORE
,
697 .local_name
= "member",
698 .type
= LDB_MAP_IGNORE
,
703 .local_name
= "memberOf",
704 .type
= LDB_MAP_IGNORE
,
709 .local_name
= "minPwdAge",
710 .type
= LDB_MAP_IGNORE
,
715 .local_name
= "minPwdLength",
716 .type
= LDB_MAP_IGNORE
,
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
,
739 .local_name
= "nCName",
740 .type
= LDB_MAP_IGNORE
,
745 .local_name
= "nETBIOSName",
746 .type
= LDB_MAP_IGNORE
,
751 .local_name
= "oEMInformation",
752 .type
= LDB_MAP_IGNORE
,
757 .local_name
= "privilege",
758 .type
= LDB_MAP_IGNORE
,
761 /* pwdHistoryLength */
763 .local_name
= "pwdHistoryLength",
764 .type
= LDB_MAP_IGNORE
,
769 .local_name
= "pwdProperties",
770 .type
= LDB_MAP_IGNORE
,
773 /* rIDAvailablePool */
775 .local_name
= "rIDAvailablePool",
776 .type
= LDB_MAP_IGNORE
,
781 .local_name
= "revision",
782 .type
= LDB_MAP_IGNORE
,
785 /* ridManagerReference */
787 .local_name
= "ridManagerReference",
788 .type
= LDB_MAP_IGNORE
,
793 .local_name
= "sAMAccountType",
794 .type
= LDB_MAP_IGNORE
,
799 .local_name
= "sPNMappings",
800 .type
= LDB_MAP_IGNORE
,
803 /* serverReference */
805 .local_name
= "serverReference",
806 .type
= LDB_MAP_IGNORE
,
811 .local_name
= "serverState",
812 .type
= LDB_MAP_IGNORE
,
815 /* showInAdvancedViewOnly */
817 .local_name
= "showInAdvancedViewOnly",
818 .type
= LDB_MAP_IGNORE
,
823 .local_name
= "subRefs",
824 .type
= LDB_MAP_IGNORE
,
829 .local_name
= "systemFlags",
830 .type
= LDB_MAP_IGNORE
,
835 .local_name
= "uASCompat",
836 .type
= LDB_MAP_IGNORE
,
841 .local_name
= "uSNChanged",
842 .type
= LDB_MAP_IGNORE
,
847 .local_name
= "uSNCreated",
848 .type
= LDB_MAP_IGNORE
,
853 .local_name
= "userPassword",
854 .type
= LDB_MAP_IGNORE
,
857 /* userAccountControl */
859 .local_name
= "userAccountControl",
860 .type
= LDB_MAP_IGNORE
,
865 .local_name
= "whenChanged",
866 .type
= LDB_MAP_IGNORE
,
871 .local_name
= "whenCreated",
872 .type
= LDB_MAP_IGNORE
,
877 .local_name
= "unixName",
878 .type
= LDB_MAP_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
,
894 .remote_name
= "gidNumber",
895 .convert_local
= lookup_gid
,
902 .local_name
= "unixName",
903 .type
= LDB_MAP_CONVERT
,
906 .remote_name
= "homeDirectory",
907 .convert_local
= lookup_homedir
,
916 /* the context init function */
917 static int samba3sam_init(struct ldb_module
*module
)
921 ret
= ldb_map_init(module
, samba3_attributes
, samba3_objectclasses
, NULL
, NULL
, "samba3sam");
922 if (ret
!= LDB_SUCCESS
)
925 return ldb_next_init(module
);
928 _PUBLIC_
const struct ldb_module_ops ldb_samba3sam_module_ops
= {
931 .init_context
= samba3sam_init
,