r20460: Simplfy the handling of password hashes in the samba3sam module.
[Samba/ekacnet.git] / source4 / dsdb / samdb / ldb_modules / samba3sam.c
blobc66dbee360d6eb0d8c93f758d510536795616255
1 /*
2 ldb database library - Samba3 SAM compatibility backend
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 */
8 #include "includes.h"
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
26 * sambaTrustPassword
27 * sambaUnixIdPool
28 * sambaIdmapEntry
29 * sambaAccountPolicy
30 * sambaSidEntry
31 * sambaAcctFlags -> systemFlags ?
32 * sambaPasswordHistory -> ntPwdHistory*/
34 /* Not necessary:
35 * sambaConfig
36 * sambaShare
37 * sambaConfigOption
38 * sambaNextGroupRid
39 * sambaNextUserRid
40 * sambaAlgorithmicRidBase
43 /* Not in Samba4:
44 * sambaKickoffTime
45 * sambaPwdCanChange
46 * sambaPwdMustChange
47 * sambaHomePath
48 * sambaHomeDrive
49 * sambaLogonScript
50 * sambaProfilePath
51 * sambaUserWorkstations
52 * sambaMungedDial
53 * sambaLogonHours */
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);
63 const char *p;
65 if (!sid)
66 return NULL;
68 p = strrchr(sid, '-');
69 if (!p)
70 return NULL;
72 el = talloc_zero(ctx, struct ldb_message_element);
73 el->name = talloc_strdup(ctx, "primaryGroupID");
74 el->num_values = 1;
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);
79 return el;
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;
85 char *sidstring;
86 struct dom_sid *sid;
87 NTSTATUS status;
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");
92 if (!sidval)
93 return; /* Sorry, no SID today.. */
95 sid = talloc(remote_mp, struct dom_sid);
96 if (sid == NULL) {
97 return;
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)) {
101 talloc_free(sid);
102 return;
105 if (!ldb_msg_find_ldb_val(local, "primaryGroupID"))
106 return; /* Sorry, no SID today.. */
108 sid->num_auths--;
110 sidstring = dom_sid_string(remote_mp, sid);
111 talloc_free(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);
122 return out;
125 static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
127 struct passwd *pwd;
128 struct ldb_val retval;
130 pwd = getpwnam((char *)val->data);
132 if (!pwd) {
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);
140 return retval;
143 static struct ldb_val lookup_gid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
145 struct passwd *pwd;
146 struct ldb_val retval;
148 pwd = getpwnam((char *)val->data);
150 if (!pwd) {
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);
157 return retval;
160 static struct ldb_val lookup_uid(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
162 struct passwd *pwd;
163 struct ldb_val retval;
165 pwd = getpwnam((char *)val->data);
167 if (!pwd) {
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);
174 return retval;
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);
181 struct dom_sid *sid;
182 NTSTATUS status;
184 sid = dom_sid_parse_talloc(ctx, (char *)val->data);
185 if (sid == NULL) {
186 return out;
189 status = ndr_push_struct_blob(&out, ctx, sid,
190 (ndr_push_flags_fn_t)ndr_push_dom_sid);
191 talloc_free(sid);
192 if (!NT_STATUS_IS_OK(status)) {
193 return out;
196 return out;
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);
203 struct dom_sid *sid;
204 NTSTATUS status;
206 sid = talloc(ctx, struct dom_sid);
207 if (sid == NULL) {
208 return out;
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)) {
214 goto done;
217 out.data = (uint8_t *)dom_sid_string(ctx, sid);
218 if (out.data == NULL) {
219 goto done;
221 out.length = strlen((const char *)out.data);
223 done:
224 talloc_free(sid);
225 return out;
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)
231 struct ldb_val out;
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));
238 if (!out.data) {
239 return data_blob(NULL, 0);
241 return out;
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)
247 struct ldb_val out;
248 struct samr_Password *pwd;
249 pwd = smbpasswd_gethexpwd(ctx, (const char *)val->data);
250 if (!pwd) {
251 return data_blob(NULL, 0);
253 out = data_blob_talloc(ctx, pwd->hash, sizeof(pwd->hash));
254 return out;
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 },
301 { NULL, NULL }
304 const struct ldb_map_attribute samba3_attributes[] =
306 /* sambaNextRid -> nextRid */
308 .local_name = "nextRid",
309 .type = MAP_RENAME,
310 .u = {
311 .rename = {
312 .remote_name = "sambaNextRid",
317 /* sambaBadPasswordTime -> badPasswordtime*/
319 .local_name = "badPasswordTime",
320 .type = MAP_RENAME,
321 .u = {
322 .rename = {
323 .remote_name = "sambaBadPasswordTime",
328 /* sambaLMPassword -> lmPwdHash*/
330 .local_name = "lmPwdHash",
331 .type = MAP_CONVERT,
332 .u = {
333 .convert = {
334 .remote_name = "sambaLMPassword",
335 .convert_local = bin2hex,
336 .convert_remote = hex2bin,
341 /* sambaGroupType -> groupType */
343 .local_name = "groupType",
344 .type = MAP_RENAME,
345 .u = {
346 .rename = {
347 .remote_name = "sambaGroupType",
352 /* sambaNTPassword -> ntPwdHash*/
354 .local_name = "ntpwdhash",
355 .type = MAP_CONVERT,
356 .u = {
357 .convert = {
358 .remote_name = "sambaNTPassword",
359 .convert_local = bin2hex,
360 .convert_remote = hex2bin,
365 /* sambaPrimaryGroupSID -> primaryGroupID */
367 .local_name = "primaryGroupID",
368 .type = MAP_GENERATE,
369 .u = {
370 .generate = {
371 .remote_names = { "sambaPrimaryGroupSID", NULL },
372 .generate_local = generate_primaryGroupID,
373 .generate_remote = generate_sambaPrimaryGroupSID,
378 /* sambaBadPasswordCount -> badPwdCount */
380 .local_name = "badPwdCount",
381 .type = MAP_RENAME,
382 .u = {
383 .rename = {
384 .remote_name = "sambaBadPasswordCount",
389 /* sambaLogonTime -> lastLogon*/
391 .local_name = "lastLogon",
392 .type = MAP_RENAME,
393 .u = {
394 .rename = {
395 .remote_name = "sambaLogonTime",
400 /* sambaLogoffTime -> lastLogoff*/
402 .local_name = "lastLogoff",
403 .type = MAP_RENAME,
404 .u = {
405 .rename = {
406 .remote_name = "sambaLogoffTime",
411 /* uid -> unixName */
413 .local_name = "unixName",
414 .type = MAP_RENAME,
415 .u = {
416 .rename = {
417 .remote_name = "uid",
422 /* displayName -> name */
424 .local_name = "name",
425 .type = MAP_RENAME,
426 .u = {
427 .rename = {
428 .remote_name = "displayName",
433 /* cn */
435 .local_name = "cn",
436 .type = MAP_KEEP,
439 /* sAMAccountName -> cn */
441 .local_name = "sAMAccountName",
442 .type = MAP_CONVERT,
443 .u = {
444 .convert = {
445 .remote_name = "uid",
446 .convert_remote = convert_uid_samaccount,
451 /* objectCategory */
453 .local_name = "objectCategory",
454 .type = MAP_IGNORE,
457 /* objectGUID */
459 .local_name = "objectGUID",
460 .type = MAP_IGNORE,
463 /* objectVersion */
465 .local_name = "objectVersion",
466 .type = MAP_IGNORE,
469 /* codePage */
471 .local_name = "codePage",
472 .type = MAP_IGNORE,
475 /* dNSHostName */
477 .local_name = "dNSHostName",
478 .type = MAP_IGNORE,
482 /* dnsDomain */
484 .local_name = "dnsDomain",
485 .type = MAP_IGNORE,
488 /* dnsRoot */
490 .local_name = "dnsRoot",
491 .type = MAP_IGNORE,
494 /* countryCode */
496 .local_name = "countryCode",
497 .type = MAP_IGNORE,
500 /* nTMixedDomain */
502 .local_name = "nTMixedDomain",
503 .type = MAP_IGNORE,
506 /* operatingSystem */
508 .local_name = "operatingSystem",
509 .type = MAP_IGNORE,
512 /* operatingSystemVersion */
514 .local_name = "operatingSystemVersion",
515 .type = MAP_IGNORE,
519 /* servicePrincipalName */
521 .local_name = "servicePrincipalName",
522 .type = MAP_IGNORE,
525 /* msDS-Behavior-Version */
527 .local_name = "msDS-Behavior-Version",
528 .type = MAP_IGNORE,
531 /* msDS-KeyVersionNumber */
533 .local_name = "msDS-KeyVersionNumber",
534 .type = MAP_IGNORE,
537 /* msDs-masteredBy */
539 .local_name = "msDs-masteredBy",
540 .type = MAP_IGNORE,
543 /* ou */
545 .local_name = "ou",
546 .type = MAP_KEEP,
549 /* dc */
551 .local_name = "dc",
552 .type = MAP_KEEP,
555 /* description */
557 .local_name = "description",
558 .type = MAP_KEEP,
561 /* sambaSID -> objectSid*/
563 .local_name = "objectSid",
564 .type = MAP_CONVERT,
565 .u = {
566 .convert = {
567 .remote_name = "sambaSID",
568 .convert_local = decode_sid,
569 .convert_remote = encode_sid,
574 /* sambaPwdLastSet -> pwdLastSet */
576 .local_name = "pwdLastSet",
577 .type = MAP_RENAME,
578 .u = {
579 .rename = {
580 .remote_name = "sambaPwdLastSet",
585 /* accountExpires */
587 .local_name = "accountExpires",
588 .type = MAP_IGNORE,
591 /* adminCount */
593 .local_name = "adminCount",
594 .type = MAP_IGNORE,
597 /* canonicalName */
599 .local_name = "canonicalName",
600 .type = MAP_IGNORE,
603 /* createTimestamp */
605 .local_name = "createTimestamp",
606 .type = MAP_IGNORE,
609 /* creationTime */
611 .local_name = "creationTime",
612 .type = MAP_IGNORE,
615 /* dMDLocation */
617 .local_name = "dMDLocation",
618 .type = MAP_IGNORE,
621 /* fSMORoleOwner */
623 .local_name = "fSMORoleOwner",
624 .type = MAP_IGNORE,
627 /* forceLogoff */
629 .local_name = "forceLogoff",
630 .type = MAP_IGNORE,
633 /* instanceType */
635 .local_name = "instanceType",
636 .type = MAP_IGNORE,
639 /* invocationId */
641 .local_name = "invocationId",
642 .type = MAP_IGNORE,
645 /* isCriticalSystemObject */
647 .local_name = "isCriticalSystemObject",
648 .type = MAP_IGNORE,
651 /* localPolicyFlags */
653 .local_name = "localPolicyFlags",
654 .type = MAP_IGNORE,
657 /* lockOutObservationWindow */
659 .local_name = "lockOutObservationWindow",
660 .type = MAP_IGNORE,
663 /* lockoutDuration */
665 .local_name = "lockoutDuration",
666 .type = MAP_IGNORE,
669 /* lockoutThreshold */
671 .local_name = "lockoutThreshold",
672 .type = MAP_IGNORE,
675 /* logonCount */
677 .local_name = "logonCount",
678 .type = MAP_IGNORE,
681 /* masteredBy */
683 .local_name = "masteredBy",
684 .type = MAP_IGNORE,
687 /* maxPwdAge */
689 .local_name = "maxPwdAge",
690 .type = MAP_IGNORE,
693 /* member */
695 .local_name = "member",
696 .type = MAP_IGNORE,
699 /* memberOf */
701 .local_name = "memberOf",
702 .type = MAP_IGNORE,
705 /* minPwdAge */
707 .local_name = "minPwdAge",
708 .type = MAP_IGNORE,
711 /* minPwdLength */
713 .local_name = "minPwdLength",
714 .type = MAP_IGNORE,
717 /* modifiedCount */
719 .local_name = "modifiedCount",
720 .type = MAP_IGNORE,
723 /* modifiedCountAtLastProm */
725 .local_name = "modifiedCountAtLastProm",
726 .type = MAP_IGNORE,
729 /* modifyTimestamp */
731 .local_name = "modifyTimestamp",
732 .type = MAP_IGNORE,
735 /* nCName */
737 .local_name = "nCName",
738 .type = MAP_IGNORE,
741 /* nETBIOSName */
743 .local_name = "nETBIOSName",
744 .type = MAP_IGNORE,
747 /* oEMInformation */
749 .local_name = "oEMInformation",
750 .type = MAP_IGNORE,
753 /* privilege */
755 .local_name = "privilege",
756 .type = MAP_IGNORE,
759 /* pwdHistoryLength */
761 .local_name = "pwdHistoryLength",
762 .type = MAP_IGNORE,
765 /* pwdProperties */
767 .local_name = "pwdProperties",
768 .type = MAP_IGNORE,
771 /* rIDAvailablePool */
773 .local_name = "rIDAvailablePool",
774 .type = MAP_IGNORE,
777 /* revision */
779 .local_name = "revision",
780 .type = MAP_IGNORE,
783 /* ridManagerReference */
785 .local_name = "ridManagerReference",
786 .type = MAP_IGNORE,
789 /* sAMAccountType */
791 .local_name = "sAMAccountType",
792 .type = MAP_IGNORE,
795 /* sPNMappings */
797 .local_name = "sPNMappings",
798 .type = MAP_IGNORE,
801 /* serverReference */
803 .local_name = "serverReference",
804 .type = MAP_IGNORE,
807 /* serverState */
809 .local_name = "serverState",
810 .type = MAP_IGNORE,
813 /* showInAdvancedViewOnly */
815 .local_name = "showInAdvancedViewOnly",
816 .type = MAP_IGNORE,
819 /* subRefs */
821 .local_name = "subRefs",
822 .type = MAP_IGNORE,
825 /* systemFlags */
827 .local_name = "systemFlags",
828 .type = MAP_IGNORE,
831 /* uASCompat */
833 .local_name = "uASCompat",
834 .type = MAP_IGNORE,
837 /* uSNChanged */
839 .local_name = "uSNChanged",
840 .type = MAP_IGNORE,
843 /* uSNCreated */
845 .local_name = "uSNCreated",
846 .type = MAP_IGNORE,
849 /* sambaPassword */
851 .local_name = "sambaPassword",
852 .type = MAP_IGNORE,
855 /* userAccountControl */
857 .local_name = "userAccountControl",
858 .type = MAP_IGNORE,
861 /* whenChanged */
863 .local_name = "whenChanged",
864 .type = MAP_IGNORE,
867 /* whenCreated */
869 .local_name = "whenCreated",
870 .type = MAP_IGNORE,
873 /* uidNumber */
875 .local_name = "unixName",
876 .type = MAP_CONVERT,
877 .u = {
878 .convert = {
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",
889 .type = MAP_CONVERT,
890 .u = {
891 .convert = {
892 .remote_name = "gidNumber",
893 .convert_local = lookup_gid,
898 /* homeDirectory */
900 .local_name = "unixName",
901 .type = MAP_CONVERT,
902 .u = {
903 .convert = {
904 .remote_name = "homeDirectory",
905 .convert_local = lookup_homedir,
910 .local_name = NULL,
914 /* the context init function */
915 static int samba3sam_init(struct ldb_module *module)
917 int ret;
919 ret = ldb_map_init(module, samba3_attributes, samba3_objectclasses, NULL, "samba3sam");
920 if (ret != LDB_SUCCESS)
921 return ret;
923 return ldb_next_init(module);
926 static struct ldb_module_ops samba3sam_ops = {
927 .name = "samba3sam",
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);