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 "lib/samba3/samba3.h"
20 * sambaSID -> member (dn!)
21 * sambaSIDList -> member (dn!)
22 * sambaDomainName -> name
27 * sambaAcctFlags -> systemFlags ?
28 * sambaPasswordHistory -> ntPwdHistory*/
36 * sambaAlgorithmicRidBase
47 * sambaUserWorkstations
51 /* In Samba4 but not in Samba3:
54 /* From a sambaPrimaryGroupSID, generate a primaryGroupID (integer) attribute */
55 static struct ldb_message_element
*generate_primaryGroupID(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const char *local_attr
, const struct ldb_message
*remote
)
57 struct ldb_message_element
*el
;
58 const char *sid
= ldb_msg_find_attr_as_string(remote
, "sambaPrimaryGroupSID", NULL
);
64 p
= strrchr(sid
, '-');
68 el
= talloc_zero(ctx
, struct ldb_message_element
);
69 el
->name
= talloc_strdup(ctx
, "primaryGroupID");
71 el
->values
= talloc_array(ctx
, struct ldb_val
, 1);
72 el
->values
[0].data
= (uint8_t *)talloc_strdup(el
->values
, p
+1);
73 el
->values
[0].length
= strlen((char *)el
->values
[0].data
);
78 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
)
80 const struct ldb_val
*sidval
;
83 enum ndr_err_code ndr_err
;
85 /* We need the domain, so we get it from the objectSid that we hope is here... */
86 sidval
= ldb_msg_find_ldb_val(local
, "objectSid");
89 return; /* Sorry, no SID today.. */
91 sid
= talloc(remote_mp
, struct dom_sid
);
96 ndr_err
= ndr_pull_struct_blob(sidval
, sid
, sid
, (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
97 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
102 if (!ldb_msg_find_ldb_val(local
, "primaryGroupID"))
103 return; /* Sorry, no SID today.. */
107 sidstring
= dom_sid_string(remote_mp
, sid
);
109 ldb_msg_add_fmt(remote_mp
, "sambaPrimaryGroupSID", "%s-%u", sidstring
,
110 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 /* "pw_gid" is per POSIX definition "unsigned".
156 * But write it out as "signed" for LDAP compliance. */
157 retval
.data
= (uint8_t *)talloc_asprintf(ctx
, "%d", (int) pwd
->pw_gid
);
158 retval
.length
= strlen((char *)retval
.data
);
163 static struct ldb_val
lookup_uid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
166 struct ldb_val retval
;
168 pwd
= getpwnam((char *)val
->data
);
171 return *talloc_zero(ctx
, struct ldb_val
);
174 /* "pw_uid" is per POSIX definition "unsigned".
175 * But write it out as "signed" for LDAP compliance. */
176 retval
.data
= (uint8_t *)talloc_asprintf(ctx
, "%d", (int) pwd
->pw_uid
);
177 retval
.length
= strlen((char *)retval
.data
);
182 /* Encode a sambaSID to an objectSid. */
183 static struct ldb_val
encode_sid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
185 struct ldb_val out
= data_blob(NULL
, 0);
187 enum ndr_err_code ndr_err
;
189 sid
= dom_sid_parse_talloc(ctx
, (char *)val
->data
);
194 ndr_err
= ndr_push_struct_blob(&out
, ctx
,
195 sid
, (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
197 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
204 /* Decode an objectSid to a sambaSID. */
205 static struct ldb_val
decode_sid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
207 struct ldb_val out
= data_blob(NULL
, 0);
209 enum ndr_err_code ndr_err
;
211 sid
= talloc(ctx
, struct dom_sid
);
216 ndr_err
= ndr_pull_struct_blob(val
, sid
, sid
,
217 (ndr_pull_flags_fn_t
)ndr_pull_dom_sid
);
218 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
222 out
.data
= (uint8_t *)dom_sid_string(ctx
, sid
);
223 if (out
.data
== NULL
) {
226 out
.length
= strlen((const char *)out
.data
);
233 /* Convert 16 bytes to 32 hex digits. */
234 static struct ldb_val
bin2hex(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
237 struct samr_Password pwd
;
238 if (val
->length
!= sizeof(pwd
.hash
)) {
239 return data_blob(NULL
, 0);
241 memcpy(pwd
.hash
, val
->data
, sizeof(pwd
.hash
));
242 out
= data_blob_string_const(smbpasswd_sethexpwd(ctx
, &pwd
, 0));
244 return data_blob(NULL
, 0);
249 /* Convert 32 hex digits to 16 bytes. */
250 static struct ldb_val
hex2bin(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
253 struct samr_Password
*pwd
;
254 pwd
= smbpasswd_gethexpwd(ctx
, (const char *)val
->data
);
256 return data_blob(NULL
, 0);
258 out
= data_blob_talloc(ctx
, pwd
->hash
, sizeof(pwd
->hash
));
262 const struct ldb_map_objectclass samba3_objectclasses
[] = {
264 .local_name
= "user",
265 .remote_name
= "posixAccount",
266 .base_classes
= { "top", NULL
},
267 .musts
= { "cn", "uid", "uidNumber", "gidNumber", "homeDirectory", NULL
},
268 .mays
= { "userPassword", "loginShell", "gecos", "description", NULL
},
271 .local_name
= "group",
272 .remote_name
= "posixGroup",
273 .base_classes
= { "top", NULL
},
274 .musts
= { "cn", "gidNumber", NULL
},
275 .mays
= { "userPassword", "memberUid", "description", NULL
},
278 .local_name
= "group",
279 .remote_name
= "sambaGroupMapping",
280 .base_classes
= { "top", "posixGroup", NULL
},
281 .musts
= { "gidNumber", "sambaSID", "sambaGroupType", NULL
},
282 .mays
= { "displayName", "description", "sambaSIDList", NULL
},
285 .local_name
= "user",
286 .remote_name
= "sambaSAMAccount",
287 .base_classes
= { "top", "posixAccount", NULL
},
288 .musts
= { "uid", "sambaSID", NULL
},
289 .mays
= { "cn", "sambaLMPassword", "sambaNTPassword",
290 "sambaPwdLastSet", "sambaLogonTime", "sambaLogoffTime",
291 "sambaKickoffTime", "sambaPwdCanChange", "sambaPwdMustChange",
292 "sambaAcctFlags", "displayName", "sambaHomePath", "sambaHomeDrive",
293 "sambaLogonScript", "sambaProfilePath", "description", "sambaUserWorkstations",
294 "sambaPrimaryGroupSID", "sambaDomainName", "sambaMungedDial",
295 "sambaBadPasswordCount", "sambaBadPasswordTime",
296 "sambaPasswordHistory", "sambaLogonHours", NULL
}
300 .local_name
= "domain",
301 .remote_name
= "sambaDomain",
302 .base_classes
= { "top", NULL
},
303 .musts
= { "sambaDomainName", "sambaSID", NULL
},
304 .mays
= { "sambaNextRid", "sambaNextGroupRid", "sambaNextUserRid", "sambaAlgorithmicRidBase", NULL
},
309 const struct ldb_map_attribute samba3_attributes
[] =
311 /* sambaNextRid -> nextRid */
313 .local_name
= "nextRid",
314 .type
= LDB_MAP_RENAME
,
317 .remote_name
= "sambaNextRid",
322 /* sambaBadPasswordTime -> badPasswordtime*/
324 .local_name
= "badPasswordTime",
325 .type
= LDB_MAP_RENAME
,
328 .remote_name
= "sambaBadPasswordTime",
333 /* sambaLMPassword -> lmPwdHash*/
335 .local_name
= "dBCSPwd",
336 .type
= LDB_MAP_CONVERT
,
339 .remote_name
= "sambaLMPassword",
340 .convert_local
= bin2hex
,
341 .convert_remote
= hex2bin
,
346 /* sambaGroupType -> groupType */
348 .local_name
= "groupType",
349 .type
= LDB_MAP_RENAME
,
352 .remote_name
= "sambaGroupType",
357 /* sambaNTPassword -> ntPwdHash*/
359 .local_name
= "ntpwdhash",
360 .type
= LDB_MAP_CONVERT
,
363 .remote_name
= "sambaNTPassword",
364 .convert_local
= bin2hex
,
365 .convert_remote
= hex2bin
,
370 /* sambaPrimaryGroupSID -> primaryGroupID */
372 .local_name
= "primaryGroupID",
373 .type
= LDB_MAP_GENERATE
,
376 .remote_names
= { "sambaPrimaryGroupSID", NULL
},
377 .generate_local
= generate_primaryGroupID
,
378 .generate_remote
= generate_sambaPrimaryGroupSID
,
383 /* sambaBadPasswordCount -> badPwdCount */
385 .local_name
= "badPwdCount",
386 .type
= LDB_MAP_RENAME
,
389 .remote_name
= "sambaBadPasswordCount",
394 /* sambaLogonTime -> lastLogon*/
396 .local_name
= "lastLogon",
397 .type
= LDB_MAP_RENAME
,
400 .remote_name
= "sambaLogonTime",
405 /* sambaLogoffTime -> lastLogoff*/
407 .local_name
= "lastLogoff",
408 .type
= LDB_MAP_RENAME
,
411 .remote_name
= "sambaLogoffTime",
416 /* uid -> unixName */
418 .local_name
= "unixName",
419 .type
= LDB_MAP_RENAME
,
422 .remote_name
= "uid",
427 /* displayName -> name */
429 .local_name
= "name",
430 .type
= LDB_MAP_RENAME
,
433 .remote_name
= "displayName",
441 .type
= LDB_MAP_KEEP
,
444 /* sAMAccountName -> cn */
446 .local_name
= "sAMAccountName",
447 .type
= LDB_MAP_CONVERT
,
450 .remote_name
= "uid",
451 .convert_remote
= convert_uid_samaccount
,
458 .local_name
= "objectCategory",
459 .type
= LDB_MAP_IGNORE
,
464 .local_name
= "objectGUID",
465 .type
= LDB_MAP_IGNORE
,
470 .local_name
= "objectVersion",
471 .type
= LDB_MAP_IGNORE
,
476 .local_name
= "codePage",
477 .type
= LDB_MAP_IGNORE
,
482 .local_name
= "dNSHostName",
483 .type
= LDB_MAP_IGNORE
,
489 .local_name
= "dnsDomain",
490 .type
= LDB_MAP_IGNORE
,
495 .local_name
= "dnsRoot",
496 .type
= LDB_MAP_IGNORE
,
501 .local_name
= "countryCode",
502 .type
= LDB_MAP_IGNORE
,
507 .local_name
= "nTMixedDomain",
508 .type
= LDB_MAP_IGNORE
,
511 /* operatingSystem */
513 .local_name
= "operatingSystem",
514 .type
= LDB_MAP_IGNORE
,
517 /* operatingSystemVersion */
519 .local_name
= "operatingSystemVersion",
520 .type
= LDB_MAP_IGNORE
,
524 /* servicePrincipalName */
526 .local_name
= "servicePrincipalName",
527 .type
= LDB_MAP_IGNORE
,
530 /* msDS-Behavior-Version */
532 .local_name
= "msDS-Behavior-Version",
533 .type
= LDB_MAP_IGNORE
,
536 /* msDS-KeyVersionNumber */
538 .local_name
= "msDS-KeyVersionNumber",
539 .type
= LDB_MAP_IGNORE
,
542 /* msDs-masteredBy */
544 .local_name
= "msDs-masteredBy",
545 .type
= LDB_MAP_IGNORE
,
551 .type
= LDB_MAP_KEEP
,
557 .type
= LDB_MAP_KEEP
,
562 .local_name
= "description",
563 .type
= LDB_MAP_KEEP
,
566 /* sambaSID -> objectSid*/
568 .local_name
= "objectSid",
569 .type
= LDB_MAP_CONVERT
,
572 .remote_name
= "sambaSID",
573 .convert_local
= decode_sid
,
574 .convert_remote
= encode_sid
,
579 /* sambaPwdLastSet -> pwdLastSet */
581 .local_name
= "pwdLastSet",
582 .type
= LDB_MAP_RENAME
,
585 .remote_name
= "sambaPwdLastSet",
592 .local_name
= "accountExpires",
593 .type
= LDB_MAP_IGNORE
,
598 .local_name
= "adminCount",
599 .type
= LDB_MAP_IGNORE
,
604 .local_name
= "canonicalName",
605 .type
= LDB_MAP_IGNORE
,
608 /* createTimestamp */
610 .local_name
= "createTimestamp",
611 .type
= LDB_MAP_IGNORE
,
616 .local_name
= "creationTime",
617 .type
= LDB_MAP_IGNORE
,
622 .local_name
= "dMDLocation",
623 .type
= LDB_MAP_IGNORE
,
628 .local_name
= "fSMORoleOwner",
629 .type
= LDB_MAP_IGNORE
,
634 .local_name
= "forceLogoff",
635 .type
= LDB_MAP_IGNORE
,
640 .local_name
= "instanceType",
641 .type
= LDB_MAP_IGNORE
,
646 .local_name
= "invocationId",
647 .type
= LDB_MAP_IGNORE
,
650 /* isCriticalSystemObject */
652 .local_name
= "isCriticalSystemObject",
653 .type
= LDB_MAP_IGNORE
,
656 /* localPolicyFlags */
658 .local_name
= "localPolicyFlags",
659 .type
= LDB_MAP_IGNORE
,
662 /* lockOutObservationWindow */
664 .local_name
= "lockOutObservationWindow",
665 .type
= LDB_MAP_IGNORE
,
668 /* lockoutDuration */
670 .local_name
= "lockoutDuration",
671 .type
= LDB_MAP_IGNORE
,
674 /* lockoutThreshold */
676 .local_name
= "lockoutThreshold",
677 .type
= LDB_MAP_IGNORE
,
682 .local_name
= "logonCount",
683 .type
= LDB_MAP_IGNORE
,
688 .local_name
= "masteredBy",
689 .type
= LDB_MAP_IGNORE
,
694 .local_name
= "maxPwdAge",
695 .type
= LDB_MAP_IGNORE
,
700 .local_name
= "member",
701 .type
= LDB_MAP_IGNORE
,
706 .local_name
= "memberOf",
707 .type
= LDB_MAP_IGNORE
,
712 .local_name
= "minPwdAge",
713 .type
= LDB_MAP_IGNORE
,
718 .local_name
= "minPwdLength",
719 .type
= LDB_MAP_IGNORE
,
724 .local_name
= "modifiedCount",
725 .type
= LDB_MAP_IGNORE
,
728 /* modifiedCountAtLastProm */
730 .local_name
= "modifiedCountAtLastProm",
731 .type
= LDB_MAP_IGNORE
,
734 /* modifyTimestamp */
736 .local_name
= "modifyTimestamp",
737 .type
= LDB_MAP_IGNORE
,
742 .local_name
= "nCName",
743 .type
= LDB_MAP_IGNORE
,
748 .local_name
= "nETBIOSName",
749 .type
= LDB_MAP_IGNORE
,
754 .local_name
= "oEMInformation",
755 .type
= LDB_MAP_IGNORE
,
760 .local_name
= "privilege",
761 .type
= LDB_MAP_IGNORE
,
764 /* pwdHistoryLength */
766 .local_name
= "pwdHistoryLength",
767 .type
= LDB_MAP_IGNORE
,
772 .local_name
= "pwdProperties",
773 .type
= LDB_MAP_IGNORE
,
776 /* rIDAvailablePool */
778 .local_name
= "rIDAvailablePool",
779 .type
= LDB_MAP_IGNORE
,
784 .local_name
= "revision",
785 .type
= LDB_MAP_IGNORE
,
788 /* ridManagerReference */
790 .local_name
= "ridManagerReference",
791 .type
= LDB_MAP_IGNORE
,
796 .local_name
= "sAMAccountType",
797 .type
= LDB_MAP_IGNORE
,
802 .local_name
= "sPNMappings",
803 .type
= LDB_MAP_IGNORE
,
806 /* serverReference */
808 .local_name
= "serverReference",
809 .type
= LDB_MAP_IGNORE
,
814 .local_name
= "serverState",
815 .type
= LDB_MAP_IGNORE
,
818 /* showInAdvancedViewOnly */
820 .local_name
= "showInAdvancedViewOnly",
821 .type
= LDB_MAP_IGNORE
,
826 .local_name
= "subRefs",
827 .type
= LDB_MAP_IGNORE
,
832 .local_name
= "systemFlags",
833 .type
= LDB_MAP_IGNORE
,
838 .local_name
= "uASCompat",
839 .type
= LDB_MAP_IGNORE
,
844 .local_name
= "uSNChanged",
845 .type
= LDB_MAP_IGNORE
,
850 .local_name
= "uSNCreated",
851 .type
= LDB_MAP_IGNORE
,
856 .local_name
= "userPassword",
857 .type
= LDB_MAP_IGNORE
,
860 /* userAccountControl */
862 .local_name
= "userAccountControl",
863 .type
= LDB_MAP_IGNORE
,
868 .local_name
= "whenChanged",
869 .type
= LDB_MAP_IGNORE
,
874 .local_name
= "whenCreated",
875 .type
= LDB_MAP_IGNORE
,
880 .local_name
= "unixName",
881 .type
= LDB_MAP_CONVERT
,
884 .remote_name
= "uidNumber",
885 .convert_local
= lookup_uid
,
890 /* gidNumber. Perhaps make into generate so we can distinguish between
891 * groups and accounts? */
893 .local_name
= "unixName",
894 .type
= LDB_MAP_CONVERT
,
897 .remote_name
= "gidNumber",
898 .convert_local
= lookup_gid
,
905 .local_name
= "unixName",
906 .type
= LDB_MAP_CONVERT
,
909 .remote_name
= "homeDirectory",
910 .convert_local
= lookup_homedir
,
919 /* the context init function */
920 static int samba3sam_init(struct ldb_module
*module
)
924 ret
= ldb_map_init(module
, samba3_attributes
, samba3_objectclasses
, NULL
, NULL
, "samba3sam");
925 if (ret
!= LDB_SUCCESS
)
928 return ldb_next_init(module
);
931 static const struct ldb_module_ops ldb_samba3sam_module_ops
= {
934 .init_context
= samba3sam_init
,
937 int ldb_samba3sam_module_init(const char *version
)
939 LDB_MODULE_CHECK_VERSION(version
);
940 return ldb_register_module(&ldb_samba3sam_module_ops
);