2 Unix SMB/CIFS implementation.
4 Copyright (C) Guenther Deschner <gd@samba.org> 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/passwd.h"
22 #include "libnet/libnet_dssync.h"
23 #include "../libcli/security/security.h"
24 #include "../libds/common/flags.h"
25 #include "../librpc/gen_ndr/ndr_drsuapi.h"
27 #include "dbwrap/dbwrap.h"
28 #include "dbwrap/dbwrap_rbt.h"
29 #include "../libds/common/flag_mapping.h"
31 #include "lib/util/base64.h"
33 /****************************************************************
34 ****************************************************************/
36 struct dssync_passdb
{
37 struct pdb_methods
*methods
;
38 struct db_context
*all
;
39 struct db_context
*aliases
;
40 struct db_context
*groups
;
43 struct dssync_passdb_obj
{
44 struct dssync_passdb_obj
*self
;
46 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
49 struct db_context
*members
;
52 struct dssync_passdb_mem
{
53 struct dssync_passdb_mem
*self
;
55 struct drsuapi_DsReplicaObjectIdentifier3
*cur
;
56 struct dssync_passdb_obj
*obj
;
61 static NTSTATUS
dssync_insert_obj(struct dssync_passdb
*pctx
,
62 struct db_context
*db
,
63 struct dssync_passdb_obj
*obj
)
66 struct db_record
*rec
;
69 rec
= dbwrap_fetch_locked(db
, talloc_tos(), obj
->key
);
71 return NT_STATUS_NO_MEMORY
;
74 value
= dbwrap_record_get_value(rec
);
75 if (value
.dsize
!= 0) {
79 status
= dbwrap_record_store(rec
, obj
->data
, TDB_INSERT
);
80 if (!NT_STATUS_IS_OK(status
)) {
88 static struct dssync_passdb_obj
*dssync_parse_obj(const TDB_DATA data
)
90 struct dssync_passdb_obj
*obj
;
92 if (data
.dsize
!= sizeof(obj
)) {
97 * we need to copy the pointer to avoid alignment problems
100 memcpy(&obj
, data
.dptr
, sizeof(obj
));
102 return talloc_get_type_abort(obj
, struct dssync_passdb_obj
);
105 static struct dssync_passdb_obj
*dssync_search_obj_by_guid(struct dssync_passdb
*pctx
,
106 struct db_context
*db
,
107 const struct GUID
*guid
)
109 struct dssync_passdb_obj
*obj
;
114 key
= make_tdb_data((const uint8_t *)(const void *)guid
,
117 status
= dbwrap_fetch(db
, talloc_tos(), key
, &data
);
118 if (!NT_STATUS_IS_OK(status
)) {
122 obj
= dssync_parse_obj(data
);
126 static NTSTATUS
dssync_create_obj(struct dssync_passdb
*pctx
,
127 struct db_context
*db
,
129 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
130 struct dssync_passdb_obj
**_obj
)
133 struct dssync_passdb_obj
*obj
;
135 obj
= talloc_zero(pctx
, struct dssync_passdb_obj
);
137 return NT_STATUS_NO_MEMORY
;
142 obj
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->object
.identifier
->guid
,
143 sizeof(cur
->object
.identifier
->guid
));
144 obj
->data
= make_tdb_data((const uint8_t *)(void *)&obj
->self
,
147 obj
->members
= db_open_rbt(obj
);
148 if (obj
->members
== NULL
) {
149 return NT_STATUS_NO_MEMORY
;
152 status
= dssync_insert_obj(pctx
, db
, obj
);
153 if (!NT_STATUS_IS_OK(status
)) {
161 static NTSTATUS
dssync_insert_mem(struct dssync_passdb
*pctx
,
162 struct dssync_passdb_obj
*obj
,
163 struct dssync_passdb_mem
*mem
)
166 struct db_record
*rec
;
169 rec
= dbwrap_fetch_locked(obj
->members
, talloc_tos(), mem
->key
);
171 return NT_STATUS_NO_MEMORY
;
174 value
= dbwrap_record_get_value(rec
);
175 if (value
.dsize
!= 0) {
179 status
= dbwrap_record_store(rec
, mem
->data
, TDB_INSERT
);
180 if (!NT_STATUS_IS_OK(status
)) {
188 static NTSTATUS
dssync_create_mem(struct dssync_passdb
*pctx
,
189 struct dssync_passdb_obj
*obj
,
191 struct drsuapi_DsReplicaObjectIdentifier3
*cur
,
192 struct dssync_passdb_mem
**_mem
)
195 struct dssync_passdb_mem
*mem
;
197 mem
= talloc_zero(pctx
, struct dssync_passdb_mem
);
199 return NT_STATUS_NO_MEMORY
;
203 mem
->active
= active
;
205 mem
->key
= make_tdb_data((const uint8_t *)(void *)&cur
->guid
,
207 mem
->data
= make_tdb_data((const uint8_t *)(void *)&mem
->self
,
210 status
= dssync_insert_mem(pctx
, obj
, mem
);
211 if (!NT_STATUS_IS_OK(status
)) {
219 static struct dssync_passdb_mem
*dssync_parse_mem(const TDB_DATA data
)
221 struct dssync_passdb_mem
*mem
;
223 if (data
.dsize
!= sizeof(mem
)) {
228 * we need to copy the pointer to avoid alignment problems
231 memcpy(&mem
, data
.dptr
, sizeof(mem
));
233 return talloc_get_type_abort(mem
, struct dssync_passdb_mem
);
236 static NTSTATUS
passdb_startup(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
237 struct replUpToDateVectorBlob
**pold_utdv
)
240 struct dssync_passdb
*pctx
;
242 pctx
= talloc_zero(mem_ctx
, struct dssync_passdb
);
244 return NT_STATUS_NO_MEMORY
;
247 if (ctx
->output_filename
) {
248 status
= make_pdb_method_name(&pctx
->methods
, ctx
->output_filename
);
250 status
= make_pdb_method_name(&pctx
->methods
, lp_passdb_backend());
253 if (!NT_STATUS_IS_OK(status
)) {
257 pctx
->all
= db_open_rbt(pctx
);
258 if (pctx
->all
== NULL
) {
259 return NT_STATUS_NO_MEMORY
;
261 pctx
->aliases
= db_open_rbt(pctx
);
262 if (pctx
->aliases
== NULL
) {
263 return NT_STATUS_NO_MEMORY
;
265 pctx
->groups
= db_open_rbt(pctx
);
266 if (pctx
->groups
== NULL
) {
267 return NT_STATUS_NO_MEMORY
;
270 ctx
->private_data
= pctx
;
275 /****************************************************************
276 ****************************************************************/
278 struct dssync_passdb_traverse_amembers
{
279 struct dssync_context
*ctx
;
280 struct dssync_passdb_obj
*obj
;
285 struct dssync_passdb_traverse_aliases
{
286 struct dssync_context
*ctx
;
291 static int dssync_passdb_traverse_amembers(struct db_record
*rec
,
294 struct dssync_passdb_traverse_amembers
*state
=
295 (struct dssync_passdb_traverse_amembers
*)private_data
;
296 struct dssync_passdb
*pctx
=
297 talloc_get_type_abort(state
->ctx
->private_data
,
298 struct dssync_passdb
);
299 struct dssync_passdb_mem
*mem
;
301 struct dom_sid alias_sid
;
302 struct dom_sid member_sid
;
303 struct dom_sid_buf buf1
, buf2
;
304 const char *member_dn
;
307 struct dom_sid
*members
;
308 bool is_member
= false;
314 alias_sid
= state
->obj
->cur
->object
.identifier
->sid
;
316 value
= dbwrap_record_get_value(rec
);
317 mem
= dssync_parse_mem(value
);
322 member_sid
= mem
->cur
->sid
;
323 member_dn
= mem
->cur
->dn
;
325 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
326 if (mem
->obj
== NULL
) {
327 DEBUG(0,("alias[%s] member[%s] can't resolve member - ignoring\n",
328 dom_sid_str_buf(&alias_sid
, &buf1
),
329 is_null_sid(&member_sid
)?
330 dom_sid_str_buf(&member_sid
, &buf2
):
335 switch (mem
->obj
->type
) {
336 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
337 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
338 DEBUG(0, ("alias[%s] ignore distribution group [%s]\n",
339 dom_sid_str_buf(&alias_sid
, &buf1
),
346 DEBUG(0,("alias[%s] member[%s]\n",
347 dom_sid_str_buf(&alias_sid
, &buf1
),
348 dom_sid_str_buf(&member_sid
, &buf2
)));
350 status
= pdb_enum_aliasmem(&alias_sid
, talloc_tos(),
351 &members
, &num_members
);
352 if (!NT_STATUS_IS_OK(status
)) {
353 DEBUG(0, ("Could not find current alias members %s - %s\n",
354 dom_sid_str_buf(&alias_sid
, &buf1
),
359 for (i
=0; i
< num_members
; i
++) {
362 match
= dom_sid_equal(&members
[i
], &member_sid
);
369 status
= NT_STATUS_OK
;
371 if (!is_member
&& mem
->active
) {
373 pdb_add_aliasmem(&alias_sid
, &member_sid
);
374 } else if (is_member
&& !mem
->active
) {
376 pdb_del_aliasmem(&alias_sid
, &member_sid
);
378 if (!NT_STATUS_IS_OK(status
)) {
379 DEBUG(0, ("Could not %s %s as alias members of %s - %s\n",
381 dom_sid_str_buf(&member_sid
, &buf1
),
382 dom_sid_str_buf(&alias_sid
, &buf2
),
390 static int dssync_passdb_traverse_aliases(struct db_record
*rec
,
393 struct dssync_passdb_traverse_aliases
*state
=
394 (struct dssync_passdb_traverse_aliases
*)private_data
;
395 struct dssync_passdb
*pctx
=
396 talloc_get_type_abort(state
->ctx
->private_data
,
397 struct dssync_passdb
);
398 struct dssync_passdb_traverse_amembers mstate
;
399 struct dssync_passdb_obj
*obj
;
404 if (pctx
->methods
== NULL
) {
408 value
= dbwrap_record_get_value(rec
);
409 obj
= dssync_parse_obj(value
);
415 mstate
.ctx
= state
->ctx
;
416 mstate
.name
= "members";
418 status
= dbwrap_traverse_read(obj
->members
,
419 dssync_passdb_traverse_amembers
,
421 if (!NT_STATUS_IS_OK(status
)) {
428 struct dssync_passdb_traverse_gmembers
{
429 struct dssync_context
*ctx
;
430 struct dssync_passdb_obj
*obj
;
435 struct dssync_passdb_traverse_groups
{
436 struct dssync_context
*ctx
;
441 static int dssync_passdb_traverse_gmembers(struct db_record
*rec
,
444 struct dssync_passdb_traverse_gmembers
*state
=
445 (struct dssync_passdb_traverse_gmembers
*)private_data
;
446 struct dssync_passdb
*pctx
=
447 talloc_get_type_abort(state
->ctx
->private_data
,
448 struct dssync_passdb
);
449 struct dssync_passdb_mem
*mem
;
451 char *nt_member
= NULL
;
453 struct dom_sid group_sid
;
454 struct dom_sid member_sid
;
455 struct dom_sid_buf buf1
, buf2
;
456 struct samu
*member
= NULL
;
457 const char *member_dn
= NULL
;
461 bool is_unix_member
= false;
466 group_sid
= state
->obj
->cur
->object
.identifier
->sid
;
468 status
= dom_sid_split_rid(talloc_tos(), &group_sid
, NULL
, &rid
);
469 if (!NT_STATUS_IS_OK(status
)) {
473 value
= dbwrap_record_get_value(rec
);
475 mem
= dssync_parse_mem(value
);
480 member_sid
= mem
->cur
->sid
;
481 member_dn
= mem
->cur
->dn
;
483 mem
->obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &mem
->cur
->guid
);
484 if (mem
->obj
== NULL
) {
485 DEBUG(0,("group[%s] member[%s] can't resolve member - ignoring\n",
486 dom_sid_str_buf(&group_sid
, &buf1
),
487 is_null_sid(&member_sid
)?
488 dom_sid_str_buf(&member_sid
, &buf2
):
493 member_sid
= mem
->obj
->cur
->object
.identifier
->sid
;
494 member_dn
= mem
->obj
->cur
->object
.identifier
->dn
;
496 switch (mem
->obj
->type
) {
497 case ATYPE_SECURITY_LOCAL_GROUP
:
498 case ATYPE_SECURITY_GLOBAL_GROUP
:
499 DEBUG(0, ("Group[%s] ignore member group [%s]\n",
500 dom_sid_str_buf(&group_sid
, &buf1
),
501 dom_sid_str_buf(&member_sid
, &buf2
)));
504 case ATYPE_DISTRIBUTION_LOCAL_GROUP
:
505 case ATYPE_DISTRIBUTION_GLOBAL_GROUP
:
506 DEBUG(0, ("Group[%s] ignore distribution group [%s]\n",
507 dom_sid_str_buf(&group_sid
, &buf1
),
514 map
= talloc_zero(NULL
, GROUP_MAP
);
519 if (!get_domain_group_from_sid(group_sid
, map
)) {
520 DEBUG(0, ("Could not find global group %s\n",
521 dom_sid_str_buf(&group_sid
, &buf1
)));
522 //return NT_STATUS_NO_SUCH_GROUP;
527 if (!(grp
= getgrgid(map
->gid
))) {
528 DEBUG(0, ("Could not find unix group %lu\n",
529 (unsigned long)map
->gid
));
530 //return NT_STATUS_NO_SUCH_GROUP;
537 DEBUG(0,("Group members of %s: ", grp
->gr_name
));
539 if ( !(member
= samu_new(talloc_tos())) ) {
540 //return NT_STATUS_NO_MEMORY;
544 if (!pdb_getsampwsid(member
, &member_sid
)) {
545 DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
546 dom_sid_str_buf(&member_sid
, &buf1
),
552 if (pdb_get_group_rid(member
) == rid
) {
553 DEBUGADD(0,("%s(primary),", pdb_get_username(member
)));
558 DEBUGADD(0,("%s,", pdb_get_username(member
)));
559 nt_member
= talloc_strdup(talloc_tos(), pdb_get_username(member
));
564 unix_members
= grp
->gr_mem
;
566 while (*unix_members
) {
567 if (strcmp(*unix_members
, nt_member
) == 0) {
568 is_unix_member
= true;
574 if (!is_unix_member
&& mem
->active
) {
575 smb_add_user_group(grp
->gr_name
, nt_member
);
576 } else if (is_unix_member
&& !mem
->active
) {
577 smb_delete_user_group(grp
->gr_name
, nt_member
);
583 static int dssync_passdb_traverse_groups(struct db_record
*rec
,
586 struct dssync_passdb_traverse_groups
*state
=
587 (struct dssync_passdb_traverse_groups
*)private_data
;
588 struct dssync_passdb
*pctx
=
589 talloc_get_type_abort(state
->ctx
->private_data
,
590 struct dssync_passdb
);
591 struct dssync_passdb_traverse_gmembers mstate
;
592 struct dssync_passdb_obj
*obj
;
597 if (pctx
->methods
== NULL
) {
601 value
= dbwrap_record_get_value(rec
);
603 obj
= dssync_parse_obj(value
);
609 mstate
.ctx
= state
->ctx
;
610 mstate
.name
= "members";
612 status
= dbwrap_traverse_read(obj
->members
,
613 dssync_passdb_traverse_gmembers
,
615 if (!NT_STATUS_IS_OK(status
)) {
622 static NTSTATUS
passdb_finish(struct dssync_context
*ctx
, TALLOC_CTX
*mem_ctx
,
623 struct replUpToDateVectorBlob
*new_utdv
)
625 struct dssync_passdb
*pctx
=
626 talloc_get_type_abort(ctx
->private_data
,
627 struct dssync_passdb
);
628 struct dssync_passdb_traverse_aliases astate
;
629 struct dssync_passdb_traverse_groups gstate
;
634 astate
.name
= "aliases";
635 status
= dbwrap_traverse_read(pctx
->aliases
,
636 dssync_passdb_traverse_aliases
,
638 if (!NT_STATUS_IS_OK(status
)) {
639 return NT_STATUS_INTERNAL_ERROR
;
644 gstate
.name
= "groups";
645 status
= dbwrap_traverse_read(pctx
->groups
,
646 dssync_passdb_traverse_groups
,
648 if (!NT_STATUS_IS_OK(status
)) {
649 return NT_STATUS_INTERNAL_ERROR
;
652 TALLOC_FREE(pctx
->methods
);
658 /****************************************************************
659 ****************************************************************/
661 static NTSTATUS
smb_create_user(TALLOC_CTX
*mem_ctx
,
664 struct passwd
**passwd_p
)
666 struct passwd
*passwd
;
667 char *add_script
= NULL
;
669 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
675 /* Create appropriate user */
676 if (acct_flags
& ACB_NORMAL
) {
677 add_script
= lp_add_user_script(mem_ctx
);
678 } else if ( (acct_flags
& ACB_WSTRUST
) ||
679 (acct_flags
& ACB_SVRTRUST
) ||
680 (acct_flags
& ACB_DOMTRUST
) ) {
681 add_script
= lp_add_machine_script(mem_ctx
);
683 DEBUG(1, ("Unknown user type: %s\n",
684 pdb_encode_acct_ctrl(acct_flags
, NEW_PW_FORMAT_SPACE_PADDED_LEN
)));
685 return NT_STATUS_UNSUCCESSFUL
;
689 return NT_STATUS_NO_MEMORY
;
694 add_script
= talloc_all_string_sub(mem_ctx
, add_script
,
697 return NT_STATUS_NO_MEMORY
;
699 add_ret
= smbrun(add_script
, NULL
, NULL
);
700 DEBUG(add_ret
? 0 : 1,("fetch_account: Running the command `%s' "
701 "gave %d\n", add_script
, add_ret
));
703 smb_nscd_flush_user_cache();
707 /* try and find the possible unix account again */
708 passwd
= Get_Pwnam_alloc(mem_ctx
, account
);
710 return NT_STATUS_NO_SUCH_USER
;
718 static struct drsuapi_DsReplicaAttribute
*find_drsuapi_attr(
719 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
724 for (i
= 0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
725 struct drsuapi_DsReplicaAttribute
*attr
;
727 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
729 if (attr
->attid
== attid
) {
737 static NTSTATUS
find_drsuapi_attr_string(TALLOC_CTX
*mem_ctx
,
738 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
743 struct drsuapi_DsReplicaAttribute
*attr
;
747 attr
= find_drsuapi_attr(cur
, attid
);
749 return NT_STATUS_PROPSET_NOT_FOUND
;
752 array
= talloc_array(mem_ctx
, char *, attr
->value_ctr
.num_values
);
754 return NT_STATUS_NO_MEMORY
;
757 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
758 const DATA_BLOB
*blob
;
761 blob
= attr
->value_ctr
.values
[a
].blob
;
764 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
767 ret
= pull_string_talloc(array
, NULL
, 0, &array
[a
],
768 blob
->data
, blob
->length
,
772 return NT_STATUS_INTERNAL_ERROR
;
776 *_count
= attr
->value_ctr
.num_values
;
781 static NTSTATUS
find_drsuapi_attr_int32(TALLOC_CTX
*mem_ctx
,
782 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
787 struct drsuapi_DsReplicaAttribute
*attr
;
791 attr
= find_drsuapi_attr(cur
, attid
);
793 return NT_STATUS_PROPSET_NOT_FOUND
;
796 array
= talloc_array(mem_ctx
, int32_t, attr
->value_ctr
.num_values
);
798 return NT_STATUS_NO_MEMORY
;
801 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
802 const DATA_BLOB
*blob
;
804 blob
= attr
->value_ctr
.values
[a
].blob
;
807 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
810 if (blob
->length
!= 4) {
811 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
814 array
[a
] = IVAL(blob
->data
, 0);
817 *_count
= attr
->value_ctr
.num_values
;
822 static NTSTATUS
find_drsuapi_attr_blob(TALLOC_CTX
*mem_ctx
,
823 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
828 struct drsuapi_DsReplicaAttribute
*attr
;
832 attr
= find_drsuapi_attr(cur
, attid
);
834 return NT_STATUS_PROPSET_NOT_FOUND
;
837 array
= talloc_array(mem_ctx
, DATA_BLOB
, attr
->value_ctr
.num_values
);
839 return NT_STATUS_NO_MEMORY
;
842 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
843 const DATA_BLOB
*blob
;
845 blob
= attr
->value_ctr
.values
[a
].blob
;
848 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
851 array
[a
] = data_blob_talloc(array
, blob
->data
, blob
->length
);
852 if (array
[a
].length
!= blob
->length
) {
853 return NT_STATUS_NO_MEMORY
;
856 *_count
= attr
->value_ctr
.num_values
;
861 static NTSTATUS
find_drsuapi_attr_int64(TALLOC_CTX
*mem_ctx
,
862 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
867 struct drsuapi_DsReplicaAttribute
*attr
;
871 attr
= find_drsuapi_attr(cur
, attid
);
873 return NT_STATUS_PROPSET_NOT_FOUND
;
876 array
= talloc_array(mem_ctx
, int64_t, attr
->value_ctr
.num_values
);
878 return NT_STATUS_NO_MEMORY
;
881 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
882 const DATA_BLOB
*blob
;
884 blob
= attr
->value_ctr
.values
[a
].blob
;
887 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
890 if (blob
->length
!= 8) {
891 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
894 array
[a
] = BVAL(blob
->data
, 0);
896 *_count
= attr
->value_ctr
.num_values
;
901 static NTSTATUS
find_drsuapi_attr_dn(TALLOC_CTX
*mem_ctx
,
902 const struct drsuapi_DsReplicaObjectListItemEx
*cur
,
905 struct drsuapi_DsReplicaObjectIdentifier3
**_array
)
907 struct drsuapi_DsReplicaAttribute
*attr
;
908 struct drsuapi_DsReplicaObjectIdentifier3
*array
;
911 attr
= find_drsuapi_attr(cur
, attid
);
913 return NT_STATUS_PROPSET_NOT_FOUND
;
916 array
= talloc_array(mem_ctx
,
917 struct drsuapi_DsReplicaObjectIdentifier3
,
918 attr
->value_ctr
.num_values
);
920 return NT_STATUS_NO_MEMORY
;
923 for (a
= 0; a
< attr
->value_ctr
.num_values
; a
++) {
924 const DATA_BLOB
*blob
;
925 enum ndr_err_code ndr_err
;
928 blob
= attr
->value_ctr
.values
[a
].blob
;
931 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
934 /* windows sometimes sends an extra two pad bytes here */
935 ndr_err
= ndr_pull_struct_blob(blob
, array
, &array
[a
],
936 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
937 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
938 status
= ndr_map_error2ntstatus(ndr_err
);
942 *_count
= attr
->value_ctr
.num_values
;
947 #define GET_BLOB_EX(attr, needed) do { \
950 DATA_BLOB *_vals = NULL; \
951 attr = data_blob_null; \
952 _status = find_drsuapi_attr_blob(mem_ctx, cur, \
953 DRSUAPI_ATTID_ ## attr, \
955 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
957 _status = NT_STATUS_OK; \
961 if (!NT_STATUS_IS_OK(_status)) { \
962 DEBUG(0,(__location__ "attr[%s] %s\n", \
963 #attr, nt_errstr(_status))); \
968 talloc_free(_vals); \
969 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
970 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
972 } else if (_cnt > 1) { \
973 talloc_free(_vals); \
974 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
975 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
978 (void)talloc_steal(mem_ctx, _vals[0].data); \
980 talloc_free(_vals); \
983 #define GET_STRING_EX(attr, needed) do { \
986 char **_vals = NULL; \
988 _status = find_drsuapi_attr_string(mem_ctx, cur, \
989 DRSUAPI_ATTID_ ## attr, \
991 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
993 _status = NT_STATUS_OK; \
997 if (!NT_STATUS_IS_OK(_status)) { \
998 DEBUG(0,(__location__ "attr[%s] %s\n", \
999 #attr, nt_errstr(_status))); \
1004 talloc_free(_vals); \
1005 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1006 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1008 } else if (_cnt > 1) { \
1009 talloc_free(_vals); \
1010 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1011 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1013 attr = talloc_move(mem_ctx, &_vals[0]); \
1015 talloc_free(_vals); \
1018 #define GET_UINT32_EX(attr, needed) do { \
1021 int32_t*_vals = NULL; \
1023 _status = find_drsuapi_attr_int32(mem_ctx, cur, \
1024 DRSUAPI_ATTID_ ## attr, \
1026 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1028 _status = NT_STATUS_OK; \
1032 if (!NT_STATUS_IS_OK(_status)) { \
1033 DEBUG(0,(__location__ "attr[%s] %s\n", \
1034 #attr, nt_errstr(_status))); \
1039 talloc_free(_vals); \
1040 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1041 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1043 } else if (_cnt > 1) { \
1044 talloc_free(_vals); \
1045 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1046 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1048 attr = (uint32_t)_vals[0]; \
1050 talloc_free(_vals); \
1053 #define GET_UINT64_EX(attr, needed) do { \
1056 int64_t *_vals = NULL; \
1058 _status = find_drsuapi_attr_int64(mem_ctx, cur, \
1059 DRSUAPI_ATTID_ ## attr, \
1061 if (NT_STATUS_EQUAL(_status, NT_STATUS_PROPSET_NOT_FOUND)) { \
1063 _status = NT_STATUS_OK; \
1067 if (!NT_STATUS_IS_OK(_status)) { \
1068 DEBUG(0,(__location__ "attr[%s] %s\n", \
1069 #attr, nt_errstr(_status))); \
1074 talloc_free(_vals); \
1075 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1076 return NT_STATUS_OBJECT_NAME_NOT_FOUND; \
1078 } else if (_cnt > 1) { \
1079 talloc_free(_vals); \
1080 DEBUG(0,(__location__ "attr[%s] count[%u]\n", #attr, _cnt)); \
1081 return NT_STATUS_INTERNAL_DB_CORRUPTION; \
1083 attr = (uint64_t)_vals[0]; \
1085 talloc_free(_vals); \
1088 #define GET_BLOB(attr) GET_BLOB_EX(attr, false)
1089 #define GET_STRING(attr) GET_STRING_EX(attr, false)
1090 #define GET_UINT32(attr) GET_UINT32_EX(attr, false)
1091 #define GET_UINT64(attr) GET_UINT64_EX(attr, false)
1093 /* Convert a struct samu_DELTA to a struct samu. */
1094 #define STRING_CHANGED (old_string && !new_string) ||\
1095 (!old_string && new_string) ||\
1096 (old_string && new_string && (strcmp(old_string, new_string) != 0))
1098 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
1100 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
1102 /****************************************************************
1103 ****************************************************************/
1105 static NTSTATUS
sam_account_from_object(struct samu
*account
,
1106 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1108 TALLOC_CTX
*mem_ctx
= account
;
1109 const char *old_string
, *new_string
;
1110 struct dom_sid_buf buf
;
1111 time_t unix_time
, stored_time
;
1117 NTTIME accountExpires
;
1118 const char *sAMAccountName
;
1119 const char *displayName
;
1120 const char *homeDirectory
;
1121 const char *homeDrive
;
1122 const char *scriptPath
;
1123 const char *profilePath
;
1124 const char *description
;
1125 const char *userWorkstations
;
1126 DATA_BLOB userParameters
;
1127 struct dom_sid objectSid
;
1128 uint32_t primaryGroupID
;
1129 uint32_t userAccountControl
;
1130 DATA_BLOB logonHours
;
1131 uint32_t badPwdCount
;
1132 uint32_t logonCount
;
1133 DATA_BLOB unicodePwd
;
1137 uint32_t acct_flags
;
1138 uint32_t units_per_week
;
1140 objectSid
= cur
->object
.identifier
->sid
;
1141 GET_STRING_EX(sAMAccountName
, true);
1142 DEBUG(0,("sam_account_from_object(%s, %s) start\n",
1144 dom_sid_str_buf(&objectSid
, &buf
)));
1145 GET_UINT64(lastLogon
);
1146 GET_UINT64(lastLogoff
);
1147 GET_UINT64(pwdLastSet
);
1148 GET_UINT64(accountExpires
);
1149 GET_STRING(displayName
);
1150 GET_STRING(homeDirectory
);
1151 GET_STRING(homeDrive
);
1152 GET_STRING(scriptPath
);
1153 GET_STRING(profilePath
);
1154 GET_STRING(description
);
1155 GET_STRING(userWorkstations
);
1156 GET_BLOB(userParameters
);
1157 GET_UINT32(primaryGroupID
);
1158 GET_UINT32(userAccountControl
);
1159 GET_BLOB(logonHours
);
1160 GET_UINT32(badPwdCount
);
1161 GET_UINT32(logonCount
);
1162 GET_BLOB(unicodePwd
);
1165 status
= dom_sid_split_rid(mem_ctx
, &objectSid
, NULL
, &rid
);
1166 if (!NT_STATUS_IS_OK(status
)) {
1169 acct_flags
= ds_uf2acb(userAccountControl
);
1171 /* Username, fullname, home dir, dir drive, logon script, acct
1172 desc, workstations, profile. */
1174 if (sAMAccountName
) {
1175 old_string
= pdb_get_nt_username(account
);
1176 new_string
= sAMAccountName
;
1178 if (STRING_CHANGED
) {
1179 pdb_set_nt_username(account
, new_string
, PDB_CHANGED
);
1182 /* Unix username is the same - for sanity */
1183 old_string
= pdb_get_username( account
);
1184 if (STRING_CHANGED
) {
1185 pdb_set_username(account
, new_string
, PDB_CHANGED
);
1190 old_string
= pdb_get_fullname(account
);
1191 new_string
= displayName
;
1194 pdb_set_fullname(account
, new_string
, PDB_CHANGED
);
1197 if (homeDirectory
) {
1198 old_string
= pdb_get_homedir(account
);
1199 new_string
= homeDirectory
;
1202 pdb_set_homedir(account
, new_string
, PDB_CHANGED
);
1206 old_string
= pdb_get_dir_drive(account
);
1207 new_string
= homeDrive
;
1210 pdb_set_dir_drive(account
, new_string
, PDB_CHANGED
);
1214 old_string
= pdb_get_logon_script(account
);
1215 new_string
= scriptPath
;
1218 pdb_set_logon_script(account
, new_string
, PDB_CHANGED
);
1222 old_string
= pdb_get_acct_desc(account
);
1223 new_string
= description
;
1226 pdb_set_acct_desc(account
, new_string
, PDB_CHANGED
);
1229 if (userWorkstations
) {
1230 old_string
= pdb_get_workstations(account
);
1231 new_string
= userWorkstations
;
1234 pdb_set_workstations(account
, new_string
, PDB_CHANGED
);
1238 old_string
= pdb_get_profile_path(account
);
1239 new_string
= profilePath
;
1242 pdb_set_profile_path(account
, new_string
, PDB_CHANGED
);
1245 if (userParameters
.data
) {
1246 char *newstr
= NULL
;
1247 old_string
= pdb_get_munged_dial(account
);
1249 if (userParameters
.length
!= 0) {
1250 newstr
= base64_encode_data_blob(talloc_tos(),
1252 SMB_ASSERT(newstr
!= NULL
);
1255 if (STRING_CHANGED_NC(old_string
, newstr
))
1256 pdb_set_munged_dial(account
, newstr
, PDB_CHANGED
);
1257 TALLOC_FREE(newstr
);
1260 /* User and group sid */
1261 if (rid
!= 0 && pdb_get_user_rid(account
) != rid
) {
1262 pdb_set_user_sid_from_rid(account
, rid
, PDB_CHANGED
);
1264 if (primaryGroupID
!= 0 && pdb_get_group_rid(account
) != primaryGroupID
) {
1265 pdb_set_group_sid_from_rid(account
, primaryGroupID
, PDB_CHANGED
);
1268 /* Logon and password information */
1269 if (!nt_time_is_zero(&lastLogon
)) {
1270 unix_time
= nt_time_to_unix(lastLogon
);
1271 stored_time
= pdb_get_logon_time(account
);
1272 if (stored_time
!= unix_time
)
1273 pdb_set_logon_time(account
, unix_time
, PDB_CHANGED
);
1276 if (!nt_time_is_zero(&lastLogoff
)) {
1277 unix_time
= nt_time_to_unix(lastLogoff
);
1278 stored_time
= pdb_get_logoff_time(account
);
1279 if (stored_time
!= unix_time
)
1280 pdb_set_logoff_time(account
, unix_time
,PDB_CHANGED
);
1284 units_per_week
= logonHours
.length
* 8;
1286 if (pdb_get_logon_divs(account
) != units_per_week
) {
1287 pdb_set_logon_divs(account
, units_per_week
, PDB_CHANGED
);
1290 /* Logon Hours Len */
1291 if (units_per_week
/8 != pdb_get_hours_len(account
)) {
1292 pdb_set_hours_len(account
, units_per_week
/8, PDB_CHANGED
);
1296 if (logonHours
.data
) {
1297 char oldstr
[44], newstr
[44];
1298 pdb_sethexhours(oldstr
, pdb_get_hours(account
));
1299 pdb_sethexhours(newstr
, logonHours
.data
);
1300 if (!strequal(oldstr
, newstr
)) {
1301 pdb_set_hours(account
, logonHours
.data
,
1302 logonHours
.length
, PDB_CHANGED
);
1306 if (pdb_get_bad_password_count(account
) != badPwdCount
)
1307 pdb_set_bad_password_count(account
, badPwdCount
, PDB_CHANGED
);
1309 if (pdb_get_logon_count(account
) != logonCount
)
1310 pdb_set_logon_count(account
, logonCount
, PDB_CHANGED
);
1312 if (!nt_time_is_zero(&pwdLastSet
)) {
1313 unix_time
= nt_time_to_unix(pwdLastSet
);
1314 stored_time
= pdb_get_pass_last_set_time(account
);
1315 if (stored_time
!= unix_time
)
1316 pdb_set_pass_last_set_time(account
, unix_time
, PDB_CHANGED
);
1318 /* no last set time, make it now */
1319 pdb_set_pass_last_set_time(account
, time(NULL
), PDB_CHANGED
);
1322 if (!nt_time_is_zero(&accountExpires
)) {
1323 unix_time
= nt_time_to_unix(accountExpires
);
1324 stored_time
= pdb_get_kickoff_time(account
);
1325 if (stored_time
!= unix_time
)
1326 pdb_set_kickoff_time(account
, unix_time
, PDB_CHANGED
);
1329 /* Decode hashes from password hash
1330 Note that win2000 may send us all zeros for the hashes if it doesn't
1331 think this channel is secure enough - don't set the passwords at all
1334 if (dBCSPwd
.length
== 16 && !all_zero(dBCSPwd
.data
, 16)) {
1335 pdb_set_lanman_passwd(account
, dBCSPwd
.data
, PDB_CHANGED
);
1338 if (unicodePwd
.length
== 16 && !all_zero(unicodePwd
.data
, 16)) {
1339 pdb_set_nt_passwd(account
, unicodePwd
.data
, PDB_CHANGED
);
1344 /* TODO: account expiry time */
1346 pdb_set_acct_ctrl(account
, acct_flags
, PDB_CHANGED
);
1348 pdb_set_domain(account
, lp_workgroup(), PDB_CHANGED
);
1350 DEBUG(0,("sam_account_from_object(%s, %s) done\n",
1352 dom_sid_str_buf(&objectSid
, &buf
)));
1353 return NT_STATUS_OK
;
1356 /****************************************************************
1357 ****************************************************************/
1359 static NTSTATUS
handle_account_object(struct dssync_passdb
*pctx
,
1360 TALLOC_CTX
*mem_ctx
,
1361 struct dssync_passdb_obj
*obj
)
1363 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1366 struct samu
*sam_account
=NULL
;
1369 struct dom_sid user_sid
;
1370 struct dom_sid group_sid
;
1371 struct dom_sid_buf buf
;
1372 struct passwd
*passwd
= NULL
;
1373 uint32_t acct_flags
;
1376 const char *sAMAccountName
;
1377 uint32_t userAccountControl
;
1379 user_sid
= cur
->object
.identifier
->sid
;
1380 GET_STRING_EX(sAMAccountName
, true);
1381 GET_UINT32_EX(userAccountControl
, true);
1383 status
= dom_sid_split_rid(mem_ctx
, &user_sid
, NULL
, &rid
);
1384 if (!NT_STATUS_IS_OK(status
)) {
1388 fstrcpy(account
, sAMAccountName
);
1389 if (rid
== DOMAIN_RID_GUEST
) {
1391 * pdb_getsampwsid() has special handling for DOMAIN_RID_GUEST
1392 * that's why we need to ignore it here.
1394 * pdb_smbpasswd.c also has some DOMAIN_RID_GUEST related
1397 DEBUG(0,("Ignore %s - %s\n",
1399 dom_sid_str_buf(&user_sid
, &buf
)));
1400 return NT_STATUS_OK
;
1402 DEBUG(0,("Creating account: %s\n", account
));
1404 if ( !(sam_account
= samu_new(mem_ctx
)) ) {
1405 return NT_STATUS_NO_MEMORY
;
1408 acct_flags
= ds_uf2acb(userAccountControl
);
1409 status
= smb_create_user(sam_account
, acct_flags
, account
, &passwd
);
1410 if (!NT_STATUS_IS_OK(status
)) {
1411 DEBUG(0,("Could not create posix account info for '%s'- %s\n",
1412 account
, nt_errstr(status
)));
1413 TALLOC_FREE(sam_account
);
1417 DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
1418 dom_sid_str_buf(&user_sid
, &buf
),
1420 if (!pdb_getsampwsid(sam_account
, &user_sid
)) {
1421 sam_account_from_object(sam_account
, cur
);
1422 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
1423 dom_sid_str_buf(&user_sid
, &buf
),
1424 pdb_get_username(sam_account
)));
1425 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account
))) {
1426 DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
1428 TALLOC_FREE(sam_account
);
1429 return NT_STATUS_ACCESS_DENIED
;
1432 sam_account_from_object(sam_account
, cur
);
1433 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
1434 dom_sid_str_buf(&user_sid
, &buf
),
1435 pdb_get_username(sam_account
)));
1436 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account
))) {
1437 DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
1439 TALLOC_FREE(sam_account
);
1440 return NT_STATUS_ACCESS_DENIED
;
1444 if (pdb_get_group_sid(sam_account
) == NULL
) {
1445 TALLOC_FREE(sam_account
);
1446 return NT_STATUS_UNSUCCESSFUL
;
1449 group_sid
= *pdb_get_group_sid(sam_account
);
1451 map
= talloc_zero(NULL
, GROUP_MAP
);
1453 return NT_STATUS_NO_MEMORY
;
1456 if (!pdb_getgrsid(map
, group_sid
)) {
1457 DEBUG(0, ("Primary group of %s has no mapping!\n",
1458 pdb_get_username(sam_account
)));
1460 if (map
->gid
!= passwd
->pw_gid
) {
1461 if (!(grp
= getgrgid(map
->gid
))) {
1462 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
1463 (unsigned long)map
->gid
, pdb_get_username(sam_account
),
1464 dom_sid_str_buf(&group_sid
, &buf
)));
1466 smb_set_primary_group(grp
->gr_name
, pdb_get_username(sam_account
));
1474 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
1475 pdb_get_username(sam_account
)));
1478 TALLOC_FREE(sam_account
);
1479 return NT_STATUS_OK
;
1482 /****************************************************************
1483 ****************************************************************/
1485 static NTSTATUS
handle_alias_object(struct dssync_passdb
*pctx
,
1486 TALLOC_CTX
*mem_ctx
,
1487 struct dssync_passdb_obj
*obj
)
1489 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1491 struct group
*grp
= NULL
;
1492 struct dom_sid group_sid
;
1494 struct dom_sid
*dom_sid
= NULL
;
1495 struct dom_sid_buf sid_str
;
1499 const char *sAMAccountName
;
1500 const char *description
;
1502 uint32_t num_members
= 0;
1503 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1505 group_sid
= cur
->object
.identifier
->sid
;
1506 GET_STRING_EX(sAMAccountName
, true);
1507 GET_STRING(description
);
1509 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1510 &num_members
, &members
);
1511 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1512 status
= NT_STATUS_OK
;
1514 if (!NT_STATUS_IS_OK(status
)) {
1518 dom_sid_split_rid(mem_ctx
, &group_sid
, &dom_sid
, &rid
);
1520 map
= talloc_zero(mem_ctx
, GROUP_MAP
);
1522 status
= NT_STATUS_NO_MEMORY
;
1526 map
->nt_name
= talloc_strdup(map
, sAMAccountName
);
1527 if (map
->nt_name
== NULL
) {
1528 status
= NT_STATUS_NO_MEMORY
;
1533 map
->comment
= talloc_strdup(map
, description
);
1535 map
->comment
= talloc_strdup(map
, "");
1537 if (map
->comment
== NULL
) {
1538 status
= NT_STATUS_NO_MEMORY
;
1542 DEBUG(0,("Creating alias[%s] - %s members[%u]\n",
1544 dom_sid_str_buf(&group_sid
, &sid_str
),
1547 status
= dssync_insert_obj(pctx
, pctx
->aliases
, obj
);
1548 if (!NT_STATUS_IS_OK(status
)) {
1552 if (pdb_getgrsid(map
, group_sid
)) {
1553 if (map
->gid
!= -1) {
1554 grp
= getgrgid(map
->gid
);
1562 /* No group found from mapping, find it from its name. */
1563 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1565 /* No appropriate group found, create one */
1567 DEBUG(0, ("Creating unix group: '%s'\n",
1570 if (smb_create_group(map
->nt_name
, &gid
) != 0) {
1571 status
= NT_STATUS_ACCESS_DENIED
;
1575 if ((grp
= getgrgid(gid
)) == NULL
) {
1576 status
= NT_STATUS_ACCESS_DENIED
;
1582 map
->gid
= grp
->gr_gid
;
1583 map
->sid
= group_sid
;
1585 if (dom_sid_equal(dom_sid
, &global_sid_Builtin
)) {
1587 * pdb_ldap does not like SID_NAME_WKN_GRP...
1589 * map.sid_name_use = SID_NAME_WKN_GRP;
1591 map
->sid_name_use
= SID_NAME_ALIAS
;
1593 map
->sid_name_use
= SID_NAME_ALIAS
;
1597 pdb_add_group_mapping_entry(map
);
1599 pdb_update_group_mapping_entry(map
);
1602 for (i
=0; i
< num_members
; i
++) {
1603 struct dssync_passdb_mem
*mem
;
1605 status
= dssync_create_mem(pctx
, obj
,
1608 if (!NT_STATUS_IS_OK(status
)) {
1613 status
= NT_STATUS_OK
;
1620 /****************************************************************
1621 ****************************************************************/
1623 static NTSTATUS
handle_group_object(struct dssync_passdb
*pctx
,
1624 TALLOC_CTX
*mem_ctx
,
1625 struct dssync_passdb_obj
*obj
)
1627 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1629 struct group
*grp
= NULL
;
1630 struct dom_sid group_sid
;
1631 struct dom_sid_buf sid_str
;
1635 const char *sAMAccountName
;
1636 const char *description
;
1638 uint32_t num_members
= 0;
1639 struct drsuapi_DsReplicaObjectIdentifier3
*members
= NULL
;
1641 group_sid
= cur
->object
.identifier
->sid
;
1642 GET_STRING_EX(sAMAccountName
, true);
1643 GET_STRING(description
);
1645 status
= find_drsuapi_attr_dn(obj
, cur
, DRSUAPI_ATTID_member
,
1646 &num_members
, &members
);
1647 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROPSET_NOT_FOUND
)) {
1648 status
= NT_STATUS_OK
;
1650 if (!NT_STATUS_IS_OK(status
)) {
1654 map
= talloc_zero(NULL
, GROUP_MAP
);
1656 return NT_STATUS_NO_MEMORY
;
1659 map
->nt_name
= talloc_strdup(map
, sAMAccountName
);
1660 if (!map
->nt_name
) {
1661 status
= NT_STATUS_NO_MEMORY
;
1665 map
->comment
= talloc_strdup(map
, description
);
1667 map
->comment
= talloc_strdup(map
, "");
1669 if (!map
->comment
) {
1670 status
= NT_STATUS_NO_MEMORY
;
1674 DEBUG(0,("Creating group[%s] - %s members [%u]\n",
1676 dom_sid_str_buf(&group_sid
, &sid_str
),
1679 status
= dssync_insert_obj(pctx
, pctx
->groups
, obj
);
1680 if (!NT_STATUS_IS_OK(status
)) {
1684 if (pdb_getgrsid(map
, group_sid
)) {
1685 if (map
->gid
!= -1) {
1686 grp
= getgrgid(map
->gid
);
1694 /* No group found from mapping, find it from its name. */
1695 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1697 /* No appropriate group found, create one */
1699 DEBUG(0, ("Creating unix group: '%s'\n",
1702 if (smb_create_group(map
->nt_name
, &gid
) != 0) {
1703 status
= NT_STATUS_ACCESS_DENIED
;
1707 if ((grp
= getgrnam(map
->nt_name
)) == NULL
) {
1708 status
= NT_STATUS_ACCESS_DENIED
;
1714 map
->gid
= grp
->gr_gid
;
1715 map
->sid
= group_sid
;
1716 map
->sid_name_use
= SID_NAME_DOM_GRP
;
1719 pdb_add_group_mapping_entry(map
);
1721 pdb_update_group_mapping_entry(map
);
1724 for (i
=0; i
< num_members
; i
++) {
1725 struct dssync_passdb_mem
*mem
;
1727 status
= dssync_create_mem(pctx
, obj
,
1730 if (!NT_STATUS_IS_OK(status
)) {
1735 status
= NT_STATUS_OK
;
1742 /****************************************************************
1743 ****************************************************************/
1745 static NTSTATUS
handle_interdomain_trust_object(struct dssync_passdb
*pctx
,
1746 TALLOC_CTX
*mem_ctx
,
1747 struct dssync_passdb_obj
*obj
)
1749 struct drsuapi_DsReplicaObjectListItemEx
*cur
= obj
->cur
;
1750 DEBUG(0,("trust: %s\n", cur
->object
.identifier
->dn
));
1751 return NT_STATUS_NOT_IMPLEMENTED
;
1754 /****************************************************************
1755 ****************************************************************/
1757 struct dssync_object_table_t
{
1759 NTSTATUS (*fn
) (struct dssync_passdb
*pctx
,
1760 TALLOC_CTX
*mem_ctx
,
1761 struct dssync_passdb_obj
*obj
);
1764 static const struct dssync_object_table_t dssync_object_table
[] = {
1765 { ATYPE_NORMAL_ACCOUNT
, handle_account_object
},
1766 { ATYPE_WORKSTATION_TRUST
, handle_account_object
},
1767 { ATYPE_SECURITY_LOCAL_GROUP
, handle_alias_object
},
1768 { ATYPE_SECURITY_GLOBAL_GROUP
, handle_group_object
},
1769 { ATYPE_INTERDOMAIN_TRUST
, handle_interdomain_trust_object
},
1772 /****************************************************************
1773 ****************************************************************/
1775 static NTSTATUS
parse_object(struct dssync_passdb
*pctx
,
1776 TALLOC_CTX
*mem_ctx
,
1777 struct drsuapi_DsReplicaObjectListItemEx
*cur
)
1779 NTSTATUS status
= NT_STATUS_OK
;
1783 struct drsuapi_DsReplicaAttribute
*attr
;
1786 uint32_t sam_type
= 0;
1788 DEBUG(3, ("parsing object '%s'\n", cur
->object
.identifier
->dn
));
1790 for (i
=0; i
< cur
->object
.attribute_ctr
.num_attributes
; i
++) {
1792 attr
= &cur
->object
.attribute_ctr
.attributes
[i
];
1794 if (attr
->value_ctr
.num_values
!= 1) {
1798 if (!attr
->value_ctr
.values
[0].blob
) {
1802 blob
= attr
->value_ctr
.values
[0].blob
;
1804 switch (attr
->attid
) {
1805 case DRSUAPI_ATTID_sAMAccountName
:
1806 pull_string_talloc(mem_ctx
, NULL
, 0, &name
,
1807 blob
->data
, blob
->length
,
1810 case DRSUAPI_ATTID_sAMAccountType
:
1811 sam_type
= IVAL(blob
->data
, 0);
1818 for (a
=0; a
< ARRAY_SIZE(dssync_object_table
); a
++) {
1819 if (sam_type
== dssync_object_table
[a
].type
) {
1820 if (dssync_object_table
[a
].fn
) {
1821 struct dssync_passdb_obj
*obj
= NULL
;
1822 status
= dssync_create_obj(pctx
, pctx
->all
,
1823 sam_type
, cur
, &obj
);
1824 if (!NT_STATUS_IS_OK(status
)) {
1827 status
= dssync_object_table
[a
].fn(pctx
,
1838 static NTSTATUS
parse_link(struct dssync_passdb
*pctx
,
1839 TALLOC_CTX
*mem_ctx
,
1840 struct drsuapi_DsReplicaLinkedAttribute
*cur
)
1842 struct drsuapi_DsReplicaObjectIdentifier3
*id3
;
1843 const DATA_BLOB
*blob
;
1844 enum ndr_err_code ndr_err
;
1846 bool active
= false;
1847 struct dssync_passdb_mem
*mem
;
1848 struct dssync_passdb_obj
*obj
;
1850 if (cur
->attid
!= DRSUAPI_ATTID_member
) {
1851 return NT_STATUS_OK
;
1854 if (cur
->flags
& DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
) {
1858 DEBUG(3, ("parsing link '%s' - %s\n",
1859 cur
->identifier
->dn
, active
?"adding":"deleting"));
1861 blob
= cur
->value
.blob
;
1864 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1867 obj
= dssync_search_obj_by_guid(pctx
, pctx
->all
, &cur
->identifier
->guid
);
1869 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1872 id3
= talloc_zero(obj
, struct drsuapi_DsReplicaObjectIdentifier3
);
1874 return NT_STATUS_NO_MEMORY
;
1877 /* windows sometimes sends an extra two pad bytes here */
1878 ndr_err
= ndr_pull_struct_blob(blob
, id3
, id3
,
1879 (ndr_pull_flags_fn_t
)ndr_pull_drsuapi_DsReplicaObjectIdentifier3
);
1880 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1881 status
= ndr_map_error2ntstatus(ndr_err
);
1885 status
= dssync_create_mem(pctx
, obj
,
1888 if (!NT_STATUS_IS_OK(status
)) {
1892 return NT_STATUS_OK
;
1895 /****************************************************************
1896 ****************************************************************/
1898 static NTSTATUS
passdb_process_objects(struct dssync_context
*ctx
,
1899 TALLOC_CTX
*mem_ctx
,
1900 struct drsuapi_DsReplicaObjectListItemEx
*cur
,
1901 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1903 NTSTATUS status
= NT_STATUS_OK
;
1904 struct dssync_passdb
*pctx
=
1905 talloc_get_type_abort(ctx
->private_data
,
1906 struct dssync_passdb
);
1908 for (; cur
; cur
= cur
->next_object
) {
1909 status
= parse_object(pctx
, mem_ctx
, cur
);
1910 if (!NT_STATUS_IS_OK(status
)) {
1919 /****************************************************************
1920 ****************************************************************/
1922 static NTSTATUS
passdb_process_links(struct dssync_context
*ctx
,
1923 TALLOC_CTX
*mem_ctx
,
1925 struct drsuapi_DsReplicaLinkedAttribute
*links
,
1926 struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
)
1928 NTSTATUS status
= NT_STATUS_OK
;
1929 struct dssync_passdb
*pctx
=
1930 talloc_get_type_abort(ctx
->private_data
,
1931 struct dssync_passdb
);
1934 for (i
= 0; i
< count
; i
++) {
1935 status
= parse_link(pctx
, mem_ctx
, &links
[i
]);
1936 if (!NT_STATUS_IS_OK(status
)) {
1945 /****************************************************************
1946 ****************************************************************/
1948 const struct dssync_ops libnet_dssync_passdb_ops
= {
1949 .startup
= passdb_startup
,
1950 .process_objects
= passdb_process_objects
,
1951 .process_links
= passdb_process_links
,
1952 .finish
= passdb_finish
,