diff options
42 files changed, 965 insertions, 1955 deletions
diff --git a/libcli/util/ntstatus.h b/libcli/util/ntstatus.h index fa4553df1e..139562d8c2 100644 --- a/libcli/util/ntstatus.h +++ b/libcli/util/ntstatus.h @@ -592,6 +592,7 @@ typedef uint32_t NTSTATUS; #define NT_STATUS_TOO_MANY_LINKS NT_STATUS(0xC0000000 | 0x0265) #define NT_STATUS_QUOTA_LIST_INCONSISTENT NT_STATUS(0xC0000000 | 0x0266) #define NT_STATUS_FILE_IS_OFFLINE NT_STATUS(0xC0000000 | 0x0267) +#define NT_STATUS_DS_BUSY NT_STATUS(0xC0000000 | 0x02a5) #define NT_STATUS_DS_NO_MORE_RIDS NT_STATUS(0xC0000000 | 0x02a8) #define NT_STATUS_NOT_A_REPARSE_POINT NT_STATUS(0xC0000000 | 0x0275) #define NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED NT_STATUS(0xC0000000 | 0x02E9) diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl index 764958937f..e9b5170e9d 100644 --- a/librpc/idl/netlogon.idl +++ b/librpc/idl/netlogon.idl @@ -436,7 +436,7 @@ interface netlogon boolean8 lm_password_present; boolean8 password_expired; lsa_String comment; - lsa_String parameters; + lsa_BinaryString parameters; uint16 country_code; uint16 code_page; netr_USER_PRIVATE_INFO user_private_info; diff --git a/source3/librpc/idl/samr.idl b/librpc/idl/samr.idl index f47e0994dc..ee179407d4 100644 --- a/source3/librpc/idl/samr.idl +++ b/librpc/idl/samr.idl @@ -417,7 +417,7 @@ import "misc.idl", "lsa.idl", "security.idl"; /************************/ /* Function 0x09 */ /* - only levels 1, 3, 4, 6, 7, 9, 12 are valid for this + only levels 1, 3, 4, 6, 7, 9, 12 are valid for this call in w2k3 */ NTSTATUS samr_SetDomainInfo( @@ -436,14 +436,10 @@ import "misc.idl", "lsa.idl", "security.idl"; [out,ref] policy_handle *group_handle, [out,ref] uint32 *rid ); - + /************************/ /* Function 0x0b */ - - const int MAX_SAM_ENTRIES_W2K = 0x400; /* 1024 */ - const int MAX_SAM_ENTRIES_W95 = 50; - NTSTATUS samr_EnumDomainGroups( [in] policy_handle *domain_handle, [in,out,ref] uint32 *resume_handle, @@ -853,7 +849,7 @@ import "misc.idl", "lsa.idl", "security.idl"; typedef struct { samr_AcctFlags acct_flags; } samr_UserInfo16; - + typedef struct { NTTIME acct_expiry; } samr_UserInfo17; @@ -1135,7 +1131,7 @@ import "misc.idl", "lsa.idl", "security.idl"; this seems to be an alphabetic search function. The returned index is the index for samr_QueryDisplayInfo needed to get names occurring after the specified name. The supplied name does not need to exist - in the database (for example you can supply just a first letter for + in the database (for example you can supply just a first letter for searching starting at that letter) The level corresponds to the samr_QueryDisplayInfo level @@ -1330,7 +1326,7 @@ import "misc.idl", "lsa.idl", "security.idl"; /************************/ /* Function 0x3a */ /* - seems to be an exact alias for samr_SetUserInfo() + seems to be an exact alias for samr_SetUserInfo() */ [public] NTSTATUS samr_SetUserInfo2( [in,ref] policy_handle *user_handle, @@ -1434,10 +1430,9 @@ import "misc.idl", "lsa.idl", "security.idl"; NTSTATUS samr_RidToSid( [in,ref] policy_handle *domain_handle, [in] uint32 rid, - [out,ref] dom_sid2 *sid + [out,ref] dom_sid2 **sid ); - /************************/ /* Function 0x42 */ diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index 38aee2c9d1..a3107d4672 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -702,7 +702,7 @@ sub Interface($$$) $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); $self->indent; $self->pidl("PyErr_SetNTSTATUS(status);"); - $self->pidl("return;"); + $self->pidl("return NULL;"); $self->deindent; $self->pidl("}"); @@ -1181,7 +1181,6 @@ sub Parse($$$$$) $self->pidl("{"); $self->indent; $self->pidl("PyObject *m;"); - $self->pidl("NTSTATUS status;"); $self->pidl(""); foreach (@{$self->{ready_types}}) { diff --git a/source3/Makefile.in b/source3/Makefile.in index be075ad685..c048e193a6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1225,7 +1225,7 @@ samba3-idl:: ../librpc/idl/initshutdown.idl ../librpc/idl/srvsvc.idl ../librpc/idl/svcctl.idl \ ../librpc/idl/eventlog.idl ../librpc/idl/wkssvc.idl ../librpc/idl/netlogon.idl \ ../librpc/idl/notify.idl ../librpc/idl/epmapper.idl librpc/idl/messaging.idl \ - ../librpc/idl/xattr.idl ../librpc/idl/misc.idl librpc/idl/samr.idl \ + ../librpc/idl/xattr.idl ../librpc/idl/misc.idl ../librpc/idl/samr.idl \ ../librpc/idl/security.idl ../librpc/idl/dssetup.idl ../librpc/idl/krb5pac.idl \ ../librpc/idl/ntsvcs.idl librpc/idl/libnetapi.idl ../librpc/idl/drsuapi.idl \ ../librpc/idl/drsblobs.idl ../librpc/idl/nbt.idl \ diff --git a/source3/libnet/libnet_samsync_passdb.c b/source3/libnet/libnet_samsync_passdb.c index 1faef7b3eb..7ace77cace 100644 --- a/source3/libnet/libnet_samsync_passdb.c +++ b/source3/libnet/libnet_samsync_passdb.c @@ -118,12 +118,12 @@ static NTSTATUS sam_account_from_delta(struct samu *account, pdb_set_profile_path(account, new_string, PDB_CHANGED); } - if (r->parameters.string) { + if (r->parameters.array) { DATA_BLOB mung; char *newstr; old_string = pdb_get_munged_dial(account); - mung.length = r->parameters.length; - mung.data = (uint8 *) r->parameters.string; + mung.length = r->parameters.length * 2; + mung.data = (uint8_t *) r->parameters.array; newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(talloc_tos(), mung); diff --git a/source3/librpc/gen_ndr/cli_samr.c b/source3/librpc/gen_ndr/cli_samr.c index 179bd0007f..7edb790286 100644 --- a/source3/librpc/gen_ndr/cli_samr.c +++ b/source3/librpc/gen_ndr/cli_samr.c @@ -2838,7 +2838,7 @@ NTSTATUS rpccli_samr_RidToSid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *domain_handle /* [in] [ref] */, uint32_t rid /* [in] */, - struct dom_sid2 *sid /* [out] [ref] */) + struct dom_sid2 **sid /* [out] [ref] */) { struct samr_RidToSid r; NTSTATUS status; diff --git a/source3/librpc/gen_ndr/cli_samr.h b/source3/librpc/gen_ndr/cli_samr.h index 7216d0cf3d..b57d63334e 100644 --- a/source3/librpc/gen_ndr/cli_samr.h +++ b/source3/librpc/gen_ndr/cli_samr.h @@ -375,7 +375,7 @@ NTSTATUS rpccli_samr_RidToSid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *domain_handle /* [in] [ref] */, uint32_t rid /* [in] */, - struct dom_sid2 *sid /* [out] [ref] */); + struct dom_sid2 **sid /* [out] [ref] */); NTSTATUS rpccli_samr_SetDsrmPassword(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct lsa_String *name /* [in] [unique] */, diff --git a/source3/librpc/gen_ndr/ndr_netlogon.c b/source3/librpc/gen_ndr/ndr_netlogon.c index 6575dbcb91..ac23c36a7c 100644 --- a/source3/librpc/gen_ndr/ndr_netlogon.c +++ b/source3/librpc/gen_ndr/ndr_netlogon.c @@ -2513,7 +2513,7 @@ static enum ndr_err_code ndr_push_netr_DELTA_USER(struct ndr_push *ndr, int ndr_ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->lm_password_present)); NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->password_expired)); NDR_CHECK(ndr_push_lsa_String(ndr, NDR_SCALARS, &r->comment)); - NDR_CHECK(ndr_push_lsa_String(ndr, NDR_SCALARS, &r->parameters)); + NDR_CHECK(ndr_push_lsa_BinaryString(ndr, NDR_SCALARS, &r->parameters)); NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->country_code)); NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->code_page)); NDR_CHECK(ndr_push_netr_USER_PRIVATE_INFO(ndr, NDR_SCALARS, &r->user_private_info)); @@ -2540,7 +2540,7 @@ static enum ndr_err_code ndr_push_netr_DELTA_USER(struct ndr_push *ndr, int ndr_ NDR_CHECK(ndr_push_samr_Password(ndr, NDR_BUFFERS, &r->lmpassword)); NDR_CHECK(ndr_push_samr_Password(ndr, NDR_BUFFERS, &r->ntpassword)); NDR_CHECK(ndr_push_lsa_String(ndr, NDR_BUFFERS, &r->comment)); - NDR_CHECK(ndr_push_lsa_String(ndr, NDR_BUFFERS, &r->parameters)); + NDR_CHECK(ndr_push_lsa_BinaryString(ndr, NDR_BUFFERS, &r->parameters)); NDR_CHECK(ndr_push_netr_USER_PRIVATE_INFO(ndr, NDR_BUFFERS, &r->user_private_info)); NDR_CHECK(ndr_push_sec_desc_buf(ndr, NDR_BUFFERS, &r->sdbuf)); NDR_CHECK(ndr_push_lsa_String(ndr, NDR_BUFFERS, &r->profile_path)); @@ -2578,7 +2578,7 @@ static enum ndr_err_code ndr_pull_netr_DELTA_USER(struct ndr_pull *ndr, int ndr_ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->lm_password_present)); NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->password_expired)); NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_SCALARS, &r->comment)); - NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_SCALARS, &r->parameters)); + NDR_CHECK(ndr_pull_lsa_BinaryString(ndr, NDR_SCALARS, &r->parameters)); NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->country_code)); NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->code_page)); NDR_CHECK(ndr_pull_netr_USER_PRIVATE_INFO(ndr, NDR_SCALARS, &r->user_private_info)); @@ -2605,7 +2605,7 @@ static enum ndr_err_code ndr_pull_netr_DELTA_USER(struct ndr_pull *ndr, int ndr_ NDR_CHECK(ndr_pull_samr_Password(ndr, NDR_BUFFERS, &r->lmpassword)); NDR_CHECK(ndr_pull_samr_Password(ndr, NDR_BUFFERS, &r->ntpassword)); NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_BUFFERS, &r->comment)); - NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_BUFFERS, &r->parameters)); + NDR_CHECK(ndr_pull_lsa_BinaryString(ndr, NDR_BUFFERS, &r->parameters)); NDR_CHECK(ndr_pull_netr_USER_PRIVATE_INFO(ndr, NDR_BUFFERS, &r->user_private_info)); NDR_CHECK(ndr_pull_sec_desc_buf(ndr, NDR_BUFFERS, &r->sdbuf)); NDR_CHECK(ndr_pull_lsa_String(ndr, NDR_BUFFERS, &r->profile_path)); @@ -2643,7 +2643,7 @@ _PUBLIC_ void ndr_print_netr_DELTA_USER(struct ndr_print *ndr, const char *name, ndr_print_uint8(ndr, "lm_password_present", r->lm_password_present); ndr_print_uint8(ndr, "password_expired", r->password_expired); ndr_print_lsa_String(ndr, "comment", &r->comment); - ndr_print_lsa_String(ndr, "parameters", &r->parameters); + ndr_print_lsa_BinaryString(ndr, "parameters", &r->parameters); ndr_print_uint16(ndr, "country_code", r->country_code); ndr_print_uint16(ndr, "code_page", r->code_page); ndr_print_netr_USER_PRIVATE_INFO(ndr, "user_private_info", &r->user_private_info); diff --git a/source3/librpc/gen_ndr/ndr_samr.c b/source3/librpc/gen_ndr/ndr_samr.c index f83d0f0875..e1b8fd17f9 100644 --- a/source3/librpc/gen_ndr/ndr_samr.c +++ b/source3/librpc/gen_ndr/ndr_samr.c @@ -11907,7 +11907,10 @@ static enum ndr_err_code ndr_push_samr_RidToSid(struct ndr_push *ndr, int flags, if (r->out.sid == NULL) { return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer"); } - NDR_CHECK(ndr_push_dom_sid2(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.sid)); + NDR_CHECK(ndr_push_unique_ptr(ndr, *r->out.sid)); + if (*r->out.sid) { + NDR_CHECK(ndr_push_dom_sid2(ndr, NDR_SCALARS|NDR_BUFFERS, *r->out.sid)); + } NDR_CHECK(ndr_push_NTSTATUS(ndr, NDR_SCALARS, r->out.result)); } return NDR_ERR_SUCCESS; @@ -11915,8 +11918,10 @@ static enum ndr_err_code ndr_push_samr_RidToSid(struct ndr_push *ndr, int flags, static enum ndr_err_code ndr_pull_samr_RidToSid(struct ndr_pull *ndr, int flags, struct samr_RidToSid *r) { + uint32_t _ptr_sid; TALLOC_CTX *_mem_save_domain_handle_0; TALLOC_CTX *_mem_save_sid_0; + TALLOC_CTX *_mem_save_sid_1; if (flags & NDR_IN) { ZERO_STRUCT(r->out); @@ -11937,7 +11942,18 @@ static enum ndr_err_code ndr_pull_samr_RidToSid(struct ndr_pull *ndr, int flags, } _mem_save_sid_0 = NDR_PULL_GET_MEM_CTX(ndr); NDR_PULL_SET_MEM_CTX(ndr, r->out.sid, LIBNDR_FLAG_REF_ALLOC); - NDR_CHECK(ndr_pull_dom_sid2(ndr, NDR_SCALARS|NDR_BUFFERS, r->out.sid)); + NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sid)); + if (_ptr_sid) { + NDR_PULL_ALLOC(ndr, *r->out.sid); + } else { + *r->out.sid = NULL; + } + if (*r->out.sid) { + _mem_save_sid_1 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, *r->out.sid, 0); + NDR_CHECK(ndr_pull_dom_sid2(ndr, NDR_SCALARS|NDR_BUFFERS, *r->out.sid)); + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sid_1, 0); + } NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sid_0, LIBNDR_FLAG_REF_ALLOC); NDR_CHECK(ndr_pull_NTSTATUS(ndr, NDR_SCALARS, &r->out.result)); } @@ -11966,7 +11982,12 @@ _PUBLIC_ void ndr_print_samr_RidToSid(struct ndr_print *ndr, const char *name, i ndr->depth++; ndr_print_ptr(ndr, "sid", r->out.sid); ndr->depth++; - ndr_print_dom_sid2(ndr, "sid", r->out.sid); + ndr_print_ptr(ndr, "sid", *r->out.sid); + ndr->depth++; + if (*r->out.sid) { + ndr_print_dom_sid2(ndr, "sid", *r->out.sid); + } + ndr->depth--; ndr->depth--; ndr_print_NTSTATUS(ndr, "result", r->out.result); ndr->depth--; diff --git a/source3/librpc/gen_ndr/netlogon.h b/source3/librpc/gen_ndr/netlogon.h index e1dc69cca0..51cca4083b 100644 --- a/source3/librpc/gen_ndr/netlogon.h +++ b/source3/librpc/gen_ndr/netlogon.h @@ -327,7 +327,7 @@ struct netr_DELTA_USER { uint8_t lm_password_present; uint8_t password_expired; struct lsa_String comment; - struct lsa_String parameters; + struct lsa_BinaryString parameters; uint16_t country_code; uint16_t code_page; struct netr_USER_PRIVATE_INFO user_private_info; diff --git a/source3/librpc/gen_ndr/samr.h b/source3/librpc/gen_ndr/samr.h index 8c8f3f70f9..d900c29d5e 100644 --- a/source3/librpc/gen_ndr/samr.h +++ b/source3/librpc/gen_ndr/samr.h @@ -33,8 +33,6 @@ #define GENERIC_RIGHTS_ALIAS_READ ( (STANDARD_RIGHTS_READ_ACCESS|SAMR_ALIAS_ACCESS_GET_MEMBERS) ) #define GENERIC_RIGHTS_ALIAS_WRITE ( (STANDARD_RIGHTS_WRITE_ACCESS|SAMR_ALIAS_ACCESS_REMOVE_MEMBER|SAMR_ALIAS_ACCESS_ADD_MEMBER|SAMR_ALIAS_ACCESS_SET_INFO) ) #define GENERIC_RIGHTS_ALIAS_EXECUTE ( (STANDARD_RIGHTS_EXECUTE_ACCESS|SAMR_ALIAS_ACCESS_LOOKUP_INFO) ) -#define MAX_SAM_ENTRIES_W2K ( 0x400 ) -#define MAX_SAM_ENTRIES_W95 ( 50 ) #define SAMR_ENUM_USERS_MULTIPLIER ( 54 ) #define PASS_MUST_CHANGE_AT_NEXT_LOGON ( 0x01 ) #define PASS_DONT_CHANGE_AT_NEXT_LOGON ( 0x00 ) @@ -1747,7 +1745,7 @@ struct samr_RidToSid { } in; struct { - struct dom_sid2 *sid;/* [ref] */ + struct dom_sid2 **sid;/* [ref] */ NTSTATUS result; } out; diff --git a/source3/librpc/gen_ndr/srv_samr.c b/source3/librpc/gen_ndr/srv_samr.c index 3e3a1cc6c1..f4facd2914 100644 --- a/source3/librpc/gen_ndr/srv_samr.c +++ b/source3/librpc/gen_ndr/srv_samr.c @@ -5202,7 +5202,7 @@ static bool api_samr_RidToSid(pipes_struct *p) } ZERO_STRUCT(r->out); - r->out.sid = talloc_zero(r, struct dom_sid2); + r->out.sid = talloc_zero(r, struct dom_sid2 *); if (r->out.sid == NULL) { talloc_free(r); return false; diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c index 1ba230cefe..465d88a9b6 100644 --- a/source3/libsmb/nterr.c +++ b/source3/libsmb/nterr.c @@ -532,6 +532,7 @@ static const nt_err_code_struct nt_errs[] = { "NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS }, { "NT_STATUS_QUOTA_LIST_INCONSISTENT", NT_STATUS_QUOTA_LIST_INCONSISTENT }, { "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE }, + { "NT_STATUS_DS_BUSY", NT_STATUS_DS_BUSY }, { "NT_STATUS_DS_NO_MORE_RIDS", NT_STATUS_DS_NO_MORE_RIDS }, { "NT_STATUS_NOT_A_REPARSE_POINT", NT_STATUS_NOT_A_REPARSE_POINT }, { "NT_STATUS_DOWNGRADE_DETECTED", NT_STATUS_DOWNGRADE_DETECTED }, diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index c573173900..62ac1cb5c3 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -45,6 +45,9 @@ #define DISP_INFO_CACHE_TIMEOUT 10 +#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */ +#define MAX_SAM_ENTRIES_W95 50 + typedef struct disp_info { DOM_SID sid; /* identify which domain this is. */ bool builtin_domain; /* Quick flag to check if this is the builtin domain. */ diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index d966e50159..7dea342a53 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -636,6 +636,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, return NT_STATUS_OK; } +#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */ + NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 num_sids, const DOM_SID *sids, diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 69e456274c..2161286e08 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -657,6 +657,28 @@ uint32_t samdb_result_acct_flags(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ct return acct_flags; } +struct lsa_BinaryString samdb_result_parameters(TALLOC_CTX *mem_ctx, + struct ldb_message *msg, + const char *attr) +{ + struct lsa_BinaryString s; + const struct ldb_val *val = ldb_msg_find_ldb_val(msg, attr); + + ZERO_STRUCT(s); + + if (!val) { + return s; + } + + s.array = talloc_array(mem_ctx, uint16_t, val->length/2); + if (!s.array) { + return s; + } + s.length = s.size = val->length/2; + memcpy(s.array, val->data, val->length); + + return s; +} /* Find an attribute, with a particular value */ @@ -897,6 +919,17 @@ int samdb_msg_add_logon_hours(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, } /* + add a parameters element to a message +*/ +int samdb_msg_add_parameters(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, + const char *attr_name, struct lsa_BinaryString *parameters) +{ + struct ldb_val val; + val.length = parameters->length * 2; + val.data = (uint8_t *)parameters->array; + return ldb_msg_add_value(msg, attr_name, &val, NULL); +} +/* add a general value element to a message */ int samdb_msg_add_value(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, diff --git a/source4/libcli/util/nterr.c b/source4/libcli/util/nterr.c index e95f0228c1..e94ed36d39 100644 --- a/source4/libcli/util/nterr.c +++ b/source4/libcli/util/nterr.c @@ -548,6 +548,7 @@ static const nt_err_code_struct nt_errs[] = { "NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED", NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED }, { "NT_STATUS_OBJECTID_NOT_FOUND", NT_STATUS_OBJECTID_NOT_FOUND }, { "NT_STATUS_DOWNGRADE_DETECTED", NT_STATUS_DOWNGRADE_DETECTED }, + { "NT_STATUS_DS_BUSY", NT_STATUS_DS_BUSY }, { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES }, { "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED }, { "STATUS_NOTIFY_CLEANUP", STATUS_NOTIFY_CLEANUP }, diff --git a/source4/libnet/groupinfo.c b/source4/libnet/groupinfo.c index 1da6646702..5c94c34b1d 100644 --- a/source4/libnet/groupinfo.c +++ b/source4/libnet/groupinfo.c @@ -83,8 +83,8 @@ static void continue_groupinfo_lookup(struct rpc_request *req) if (s->monitor_fn) { msg.type = mon_SamrLookupName; msg_lookup = talloc(s, struct msg_rpc_lookup_name); - msg_lookup->rid = s->lookup.out.rids.ids; - msg_lookup->count = s->lookup.out.rids.count; + msg_lookup->rid = s->lookup.out.rids->ids; + msg_lookup->count = s->lookup.out.rids->count; msg.data = (void*)msg_lookup; msg.data_size = sizeof(*msg_lookup); @@ -94,7 +94,7 @@ static void continue_groupinfo_lookup(struct rpc_request *req) /* have we actually got name resolved - we're looking for only one at the moment */ - if (s->lookup.out.rids.count == 0) { + if (s->lookup.out.rids->count == 0) { composite_error(c, NT_STATUS_NO_SUCH_USER); } @@ -103,7 +103,7 @@ static void continue_groupinfo_lookup(struct rpc_request *req) /* prepare parameters for LookupNames */ s->opengroup.in.domain_handle = &s->domain_handle; s->opengroup.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - s->opengroup.in.rid = s->lookup.out.rids.ids[0]; + s->opengroup.in.rid = s->lookup.out.rids->ids[0]; s->opengroup.out.group_handle = &s->group_handle; /* send request */ @@ -152,6 +152,8 @@ static void continue_groupinfo_opengroup(struct rpc_request *req) /* prepare parameters for QueryGroupInfo call */ s->querygroupinfo.in.group_handle = &s->group_handle; s->querygroupinfo.in.level = s->level; + s->querygroupinfo.out.info = talloc(s, union samr_GroupInfo *); + if (composite_nomem(s->querygroupinfo.out.info, c)) return; /* queue rpc call, set event handling and new state */ querygroup_req = dcerpc_samr_QueryGroupInfo_send(s->pipe, c, &s->querygroupinfo); @@ -185,7 +187,7 @@ static void continue_groupinfo_getgroup(struct rpc_request *req) return; } - s->info = talloc_steal(s, s->querygroupinfo.out.info); + s->info = talloc_steal(s, *s->querygroupinfo.out.info); /* issue a monitor message */ if (s->monitor_fn) { @@ -301,7 +303,11 @@ struct composite_context *libnet_rpc_groupinfo_send(struct dcerpc_pipe *p, s->lookup.in.names[0].string = talloc_strdup(s, io->in.groupname); if (composite_nomem(s->lookup.in.names[0].string, c)) return c; - + s->lookup.out.rids = talloc_zero(s, struct samr_Ids); + s->lookup.out.types = talloc_zero(s, struct samr_Ids); + if (composite_nomem(s->lookup.out.rids, c)) return c; + if (composite_nomem(s->lookup.out.types, c)) return c; + /* send request */ lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookup); if (composite_nomem(lookup_req, c)) return c; diff --git a/source4/libnet/groupman.c b/source4/libnet/groupman.c index 58d5742336..4dfb2d8aab 100644 --- a/source4/libnet/groupman.c +++ b/source4/libnet/groupman.c @@ -174,6 +174,10 @@ struct composite_context* libnet_rpc_groupdel_send(struct dcerpc_pipe *p, s->lookupname.in.num_names = 1; s->lookupname.in.names = talloc_zero(s, struct lsa_String); s->lookupname.in.names->string = io->in.groupname; + s->lookupname.out.rids = talloc_zero(s, struct samr_Ids); + s->lookupname.out.types = talloc_zero(s, struct samr_Ids); + if (composite_nomem(s->lookupname.out.rids, c)) return c; + if (composite_nomem(s->lookupname.out.types, c)) return c; /* send the request */ lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); @@ -205,12 +209,12 @@ static void continue_groupdel_name_found(struct rpc_request *req) /* what to do when there's no group account to delete and what if there's more than one rid resolved */ - if (!s->lookupname.out.rids.count) { + if (!s->lookupname.out.rids->count) { c->status = NT_STATUS_NO_SUCH_GROUP; composite_error(c, c->status); return; - } else if (!s->lookupname.out.rids.count > 1) { + } else if (!s->lookupname.out.rids->count > 1) { c->status = NT_STATUS_INVALID_ACCOUNT_NAME; composite_error(c, c->status); return; @@ -218,7 +222,7 @@ static void continue_groupdel_name_found(struct rpc_request *req) /* prepare the arguments for rpc call */ s->opengroup.in.domain_handle = &s->domain_handle; - s->opengroup.in.rid = s->lookupname.out.rids.ids[0]; + s->opengroup.in.rid = s->lookupname.out.rids->ids[0]; s->opengroup.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; s->opengroup.out.group_handle = &s->group_handle; diff --git a/source4/libnet/libnet_domain.c b/source4/libnet/libnet_domain.c index ccdfdaf134..eb6920d88e 100644 --- a/source4/libnet/libnet_domain.c +++ b/source4/libnet/libnet_domain.c @@ -40,6 +40,7 @@ struct domain_open_samr_state { uint32_t access_mask; struct policy_handle connect_handle; struct policy_handle domain_handle; + struct dom_sid2 *domain_sid; /* information about the progress */ void (*monitor_fn)(struct monitor_msg*); @@ -159,6 +160,8 @@ static void continue_domain_open_connect(struct rpc_request *req) /* prepare for samr_LookupDomain call */ r->in.connect_handle = &s->connect_handle; r->in.domain_name = &s->domain_name; + r->out.sid = talloc(s, struct dom_sid2 *); + if (composite_nomem(r->out.sid, c)) return; lookup_req = dcerpc_samr_LookupDomain_send(s->pipe, c, r); if (composite_nomem(lookup_req, c)) return; @@ -209,7 +212,7 @@ static void continue_domain_open_lookup(struct rpc_request *req) /* prepare for samr_OpenDomain call */ r->in.connect_handle = &s->connect_handle; r->in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r->in.sid = s->lookup.out.sid; + r->in.sid = *s->lookup.out.sid; r->out.domain_handle = &s->domain_handle; opendom_req = dcerpc_samr_OpenDomain_send(s->pipe, c, r); @@ -361,7 +364,7 @@ NTSTATUS libnet_DomainOpenSamr_recv(struct composite_context *c, struct libnet_c libnet functions */ ctx->samr.connect_handle = s->connect_handle; ctx->samr.handle = s->domain_handle; - ctx->samr.sid = talloc_steal(ctx, s->lookup.out.sid); + ctx->samr.sid = talloc_steal(ctx, *s->lookup.out.sid); ctx->samr.name = talloc_steal(ctx, s->domain_name.string); ctx->samr.access_mask = s->access_mask; } @@ -998,6 +1001,10 @@ static void continue_samr_connect(struct rpc_request *req) s->enumdom.in.resume_handle = &s->resume_handle; s->enumdom.in.buf_size = s->buf_size; s->enumdom.out.resume_handle = &s->resume_handle; + s->enumdom.out.num_entries = talloc(s, uint32_t); + if (composite_nomem(s->enumdom.out.num_entries, c)) return; + s->enumdom.out.sam = talloc(s, struct samr_SamArray *); + if (composite_nomem(s->enumdom.out.sam, c)) return; enumdom_req = dcerpc_samr_EnumDomains_send(s->ctx->samr.pipe, c, &s->enumdom); if (composite_nomem(enumdom_req, c)) return; @@ -1113,16 +1120,16 @@ static struct domainlist* get_domain_list(TALLOC_CTX *mem_ctx, struct domain_lis /* prepare domains array */ if (s->domains == NULL) { s->domains = talloc_array(mem_ctx, struct domainlist, - s->enumdom.out.num_entries); + *s->enumdom.out.num_entries); } else { s->domains = talloc_realloc(mem_ctx, s->domains, struct domainlist, - s->count + s->enumdom.out.num_entries); + s->count + *s->enumdom.out.num_entries); } /* copy domain names returned from samr_EnumDomains call */ - for (i = s->count; i < s->count + s->enumdom.out.num_entries; i++) + for (i = s->count; i < s->count + *s->enumdom.out.num_entries; i++) { - struct lsa_String *domain_name = &s->enumdom.out.sam->entries[i - s->count].name; + struct lsa_String *domain_name = &(*s->enumdom.out.sam)->entries[i - s->count].name; /* strdup name as a child of allocated array to make it follow the array in case of talloc_steal or talloc_free */ @@ -1131,7 +1138,7 @@ static struct domainlist* get_domain_list(TALLOC_CTX *mem_ctx, struct domain_lis } /* number of entries returned (domains enumerated) */ - s->count += s->enumdom.out.num_entries; + s->count += *s->enumdom.out.num_entries; return s->domains; } diff --git a/source4/libnet/libnet_group.c b/source4/libnet/libnet_group.c index eded378511..af5fe4d5d3 100644 --- a/source4/libnet/libnet_group.c +++ b/source4/libnet/libnet_group.c @@ -518,6 +518,10 @@ static void continue_domain_queried(struct rpc_request *req) s->group_list.in.max_size = s->page_size; s->group_list.in.resume_handle = &s->resume_index; s->group_list.out.resume_handle = &s->resume_index; + s->group_list.out.num_entries = talloc(s, uint32_t); + if (composite_nomem(s->group_list.out.num_entries, c)) return; + s->group_list.out.sam = talloc(s, struct samr_SamArray *); + if (composite_nomem(s->group_list.out.sam, c)) return; /* send the request */ enum_req = dcerpc_samr_EnumDomainGroups_send(s->ctx->samr.pipe, c, &s->group_list); @@ -549,6 +553,10 @@ static void continue_samr_domain_opened(struct composite_context *ctx) s->group_list.in.max_size = s->page_size; s->group_list.in.resume_handle = &s->resume_index; s->group_list.out.resume_handle = &s->resume_index; + s->group_list.out.num_entries = talloc(s, uint32_t); + if (composite_nomem(s->group_list.out.num_entries, c)) return; + s->group_list.out.sam = talloc(s, struct samr_SamArray *); + if (composite_nomem(s->group_list.out.sam, c)) return; /* send the request */ enum_req = dcerpc_samr_EnumDomainGroups_send(s->ctx->samr.pipe, c, &s->group_list); @@ -587,15 +595,15 @@ static void continue_groups_enumerated(struct rpc_request *req) /* get enumerated accounts counter and resume handle (the latter allows making subsequent call to continue enumeration) */ s->resume_index = *s->group_list.out.resume_handle; - s->count = s->group_list.out.num_entries; + s->count = *s->group_list.out.num_entries; /* prepare returned group accounts array */ - s->groups = talloc_array(c, struct grouplist, s->group_list.out.sam->count); + s->groups = talloc_array(c, struct grouplist, (*s->group_list.out.sam)->count); if (composite_nomem(s->groups, c)) return; - for (i = 0; i < s->group_list.out.sam->count; i++) { + for (i = 0; i < (*s->group_list.out.sam)->count; i++) { struct dom_sid *group_sid; - struct samr_SamEntry *entry = &s->group_list.out.sam->entries[i]; + struct samr_SamEntry *entry = &(*s->group_list.out.sam)->entries[i]; struct dom_sid *domain_sid = (*s->query_domain.out.info)->domain.sid; /* construct group sid from returned rid and queried domain sid */ diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index 0ed5e8ae26..70fcb4a894 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -444,13 +444,16 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru struct samr_OpenDomain od; struct policy_handle d_handle; struct samr_LookupNames ln; + struct samr_Ids rids, types; struct samr_OpenUser ou; struct samr_CreateUser2 cu; struct policy_handle *u_handle = NULL; struct samr_QueryUserInfo qui; + union samr_UserInfo *uinfo; struct samr_UserInfo21 u_info21; union libnet_SetPassword r2; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; struct lsa_String samr_account_name; uint32_t acct_flags, old_acct_flags; @@ -559,9 +562,11 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru if (!connect_with_info->out.domain_sid) { struct lsa_String name; struct samr_LookupDomain l; + struct dom_sid2 *sid = NULL; name.string = connect_with_info->out.domain_name; l.in.connect_handle = &p_handle; l.in.domain_name = &name; + l.out.sid = &sid; status = dcerpc_samr_LookupDomain(samr_pipe, tmp_ctx, &l); if (!NT_STATUS_IS_OK(status)) { @@ -571,7 +576,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru talloc_free(tmp_ctx); return status; } - connect_with_info->out.domain_sid = l.out.sid; + connect_with_info->out.domain_sid = *l.out.sid; } /* prepare samr_OpenDomain */ @@ -611,6 +616,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru ln.in.domain_handle = &d_handle; ln.in.num_names = 1; ln.in.names = talloc_array(tmp_ctx, struct lsa_String, 1); + ln.out.rids = &rids; + ln.out.types = &types; if (!ln.in.names) { r->out.error_string = NULL; talloc_free(tmp_ctx); @@ -630,10 +637,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru } /* check if we got one RID for the user */ - if (ln.out.rids.count != 1) { + if (ln.out.rids->count != 1) { r->out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] returns %d RIDs", - r->in.account_name, ln.out.rids.count); + r->in.account_name, ln.out.rids->count); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; } @@ -642,7 +649,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru ZERO_STRUCTP(u_handle); ou.in.domain_handle = &d_handle; ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - ou.in.rid = ln.out.rids.ids[0]; + ou.in.rid = ln.out.rids->ids[0]; rid = ou.in.rid; ou.out.user_handle = u_handle; @@ -694,6 +701,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru /* prepare samr_QueryUserInfo (get flags) */ qui.in.user_handle = u_handle; qui.in.level = 16; + qui.out.info = &uinfo; status = dcerpc_samr_QueryUserInfo(samr_pipe, tmp_ctx, &qui); if (!NT_STATUS_IS_OK(status)) { @@ -705,7 +713,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return status; } - if (!qui.out.info) { + if (!uinfo) { status = NT_STATUS_INVALID_PARAMETER; r->out.error_string = talloc_asprintf(mem_ctx, @@ -715,7 +723,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return status; } - old_acct_flags = (qui.out.info->info16.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST | ACB_DOMTRUST)); + old_acct_flags = (uinfo->info16.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST | ACB_DOMTRUST)); /* Possibly bail if the account is of the wrong type */ if (old_acct_flags != r->in.acct_type) { @@ -771,17 +779,18 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return NT_STATUS_USER_EXISTS; } } else { - acct_flags = qui.out.info->info16.acct_flags; + acct_flags = uinfo->info16.acct_flags; } acct_flags = (acct_flags & ~(ACB_DISABLED|ACB_PWNOTREQ)); /* Find out what password policy this user has */ pwp.in.user_handle = u_handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(samr_pipe, tmp_ctx, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } /* Grab a password of that minimum length */ diff --git a/source4/libnet/libnet_passwd.c b/source4/libnet/libnet_passwd.c index de2ed01abd..976606e72c 100644 --- a/source4/libnet/libnet_passwd.c +++ b/source4/libnet/libnet_passwd.c @@ -50,6 +50,8 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT struct samr_Password nt_verifier, lm_verifier; uint8_t old_nt_hash[16], new_nt_hash[16]; uint8_t old_lm_hash[16], new_lm_hash[16]; + struct samr_DomInfo1 *dominfo = NULL; + struct samr_ChangeReject *reject = NULL; /* prepare connect to the SAMR pipe of the users domain PDC */ c.level = LIBNET_RPC_CONNECT_PDC; @@ -92,6 +94,8 @@ static NTSTATUS libnet_ChangePassword_samr(struct libnet_context *ctx, TALLOC_CT pw3.in.lm_password = &lm_pass; pw3.in.lm_verifier = &lm_verifier; pw3.in.password3 = NULL; + pw3.out.dominfo = &dominfo; + pw3.out.reject = &reject; /* 2. try samr_ChangePasswordUser3 */ status = dcerpc_samr_ChangePasswordUser3(c.out.dcerpc_pipe, mem_ctx, &pw3); @@ -527,10 +531,12 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * struct samr_Connect sc; struct policy_handle p_handle; struct samr_LookupDomain ld; + struct dom_sid2 *sid = NULL; struct lsa_String d_name; struct samr_OpenDomain od; struct policy_handle d_handle; struct samr_LookupNames ln; + struct samr_Ids rids, types; struct samr_OpenUser ou; struct policy_handle u_handle; union libnet_SetPassword r2; @@ -568,6 +574,7 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * d_name.string = r->samr.in.domain_name; ld.in.connect_handle = &p_handle; ld.in.domain_name = &d_name; + ld.out.sid = &sid; /* 3. do a samr_LookupDomain to get the domain sid */ status = dcerpc_samr_LookupDomain(c.out.dcerpc_pipe, mem_ctx, &ld); @@ -582,7 +589,7 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * ZERO_STRUCT(d_handle); od.in.connect_handle = &p_handle; od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - od.in.sid = ld.out.sid; + od.in.sid = *ld.out.sid; od.out.domain_handle = &d_handle; /* 4. do a samr_OpenDomain to get a domain handle */ @@ -598,6 +605,8 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * ln.in.domain_handle = &d_handle; ln.in.num_names = 1; ln.in.names = talloc_array(mem_ctx, struct lsa_String, 1); + ln.out.rids = &rids; + ln.out.types = &types; if (!ln.in.names) { r->samr.out.error_string = "Out of Memory"; return NT_STATUS_NO_MEMORY; @@ -614,10 +623,10 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * } /* check if we got one RID for the user */ - if (ln.out.rids.count != 1) { + if (ln.out.rids->count != 1) { r->samr.out.error_string = talloc_asprintf(mem_ctx, "samr_LookupNames for [%s] returns %d RIDs", - r->samr.in.account_name, ln.out.rids.count); + r->samr.in.account_name, ln.out.rids->count); status = NT_STATUS_INVALID_PARAMETER; goto disconnect; } @@ -626,7 +635,7 @@ static NTSTATUS libnet_SetPassword_samr(struct libnet_context *ctx, TALLOC_CTX * ZERO_STRUCT(u_handle); ou.in.domain_handle = &d_handle; ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - ou.in.rid = ln.out.rids.ids[0]; + ou.in.rid = ln.out.rids->ids[0]; ou.out.user_handle = &u_handle; /* 6. do a samr_OpenUser to get a user handle */ diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c index 8b7dd1f598..160b4b3e19 100644 --- a/source4/libnet/libnet_samsync_ldb.c +++ b/source4/libnet/libnet_samsync_ldb.c @@ -384,7 +384,11 @@ static NTSTATUS samsync_ldb_handle_user(TALLOC_CTX *mem_ctx, } ADD_OR_DEL(string, "comment", comment.string); - ADD_OR_DEL(string, "userParameters", parameters.string); + + if (samdb_msg_add_parameters(state->sam_ldb, mem_ctx, msg, "userParameters", &user->parameters) != 0) { + return NT_STATUS_NO_MEMORY; + } + ADD_OR_DEL(uint, "countryCode", country_code); ADD_OR_DEL(uint, "codePage", code_page); diff --git a/source4/libnet/libnet_user.c b/source4/libnet/libnet_user.c index c768319452..8606d0856e 100644 --- a/source4/libnet/libnet_user.c +++ b/source4/libnet/libnet_user.c @@ -1032,6 +1032,10 @@ static void continue_domain_queried(struct rpc_request *req) s->user_list.in.resume_handle = &s->resume_index; s->user_list.in.acct_flags = ACB_NORMAL; s->user_list.out.resume_handle = &s->resume_index; + s->user_list.out.num_entries = talloc(s, uint32_t); + if (composite_nomem(s->user_list.out.num_entries, c)) return; + s->user_list.out.sam = talloc(s, struct samr_SamArray *); + if (composite_nomem(s->user_list.out.sam, c)) return; /* send the request */ enum_req = dcerpc_samr_EnumDomainUsers_send(s->ctx->samr.pipe, c, &s->user_list); @@ -1064,6 +1068,10 @@ static void continue_samr_domain_opened(struct composite_context *ctx) s->user_list.in.resume_handle = &s->resume_index; s->user_list.in.acct_flags = ACB_NORMAL; s->user_list.out.resume_handle = &s->resume_index; + s->user_list.out.sam = talloc(s, struct samr_SamArray *); + if (composite_nomem(s->user_list.out.sam, c)) return; + s->user_list.out.num_entries = talloc(s, uint32_t); + if (composite_nomem(s->user_list.out.num_entries, c)) return; /* send the request */ enum_req = dcerpc_samr_EnumDomainUsers_send(s->ctx->samr.pipe, c, &s->user_list); @@ -1102,15 +1110,15 @@ static void continue_users_enumerated(struct rpc_request *req) /* get enumerated accounts counter and resume handle (the latter allows making subsequent call to continue enumeration) */ s->resume_index = *s->user_list.out.resume_handle; - s->count = s->user_list.out.num_entries; + s->count = *s->user_list.out.num_entries; /* prepare returned user accounts array */ - s->users = talloc_array(c, struct userlist, s->user_list.out.sam->count); + s->users = talloc_array(c, struct userlist, (*s->user_list.out.sam)->count); if (composite_nomem(s->users, c)) return; - for (i = 0; i < s->user_list.out.sam->count; i++) { + for (i = 0; i < (*s->user_list.out.sam)->count; i++) { struct dom_sid *user_sid; - struct samr_SamEntry *entry = &s->user_list.out.sam->entries[i]; + struct samr_SamEntry *entry = &(*s->user_list.out.sam)->entries[i]; struct dom_sid *domain_sid = (*s->query_domain.out.info)->domain.sid; /* construct user sid from returned rid and queried domain sid */ diff --git a/source4/libnet/userinfo.c b/source4/libnet/userinfo.c index e8b6b090c7..710154d41e 100644 --- a/source4/libnet/userinfo.c +++ b/source4/libnet/userinfo.c @@ -82,8 +82,8 @@ static void continue_userinfo_lookup(struct rpc_request *req) if (s->monitor_fn) { msg.type = mon_SamrLookupName; msg_lookup = talloc(s, struct msg_rpc_lookup_name); - msg_lookup->rid = s->lookup.out.rids.ids; - msg_lookup->count = s->lookup.out.rids.count; + msg_lookup->rid = s->lookup.out.rids->ids; + msg_lookup->count = s->lookup.out.rids->count; msg.data = (void*)msg_lookup; msg.data_size = sizeof(*msg_lookup); @@ -93,7 +93,7 @@ static void continue_userinfo_lookup(struct rpc_request *req) /* have we actually got name resolved - we're looking for only one at the moment */ - if (s->lookup.out.rids.count == 0) { + if (s->lookup.out.rids->count == 0) { composite_error(c, NT_STATUS_NO_SUCH_USER); } @@ -102,7 +102,7 @@ static void continue_userinfo_lookup(struct rpc_request *req) /* prepare parameters for LookupNames */ s->openuser.in.domain_handle = &s->domain_handle; s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - s->openuser.in.rid = s->lookup.out.rids.ids[0]; + s->openuser.in.rid = s->lookup.out.rids->ids[0]; s->openuser.out.user_handle = &s->user_handle; /* send request */ @@ -151,6 +151,8 @@ static void continue_userinfo_openuser(struct rpc_request *req) /* prepare parameters for QueryUserInfo call */ s->queryuserinfo.in.user_handle = &s->user_handle; s->queryuserinfo.in.level = s->level; + s->queryuserinfo.out.info = talloc(s, union samr_UserInfo *); + if (composite_nomem(s->queryuserinfo.out.info, c)) return; /* queue rpc call, set event handling and new state */ queryuser_req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuserinfo); @@ -184,7 +186,7 @@ static void continue_userinfo_getuser(struct rpc_request *req) return; } - s->info = talloc_steal(s, s->queryuserinfo.out.info); + s->info = talloc_steal(s, *(s->queryuserinfo.out.info)); /* issue a monitor message */ if (s->monitor_fn) { @@ -297,6 +299,10 @@ struct composite_context *libnet_rpc_userinfo_send(struct dcerpc_pipe *p, s->lookup.in.num_names = 1; s->lookup.in.names = talloc_array(s, struct lsa_String, 1); if (composite_nomem(s->lookup.in.names, c)) return c; + s->lookup.out.rids = talloc_zero(s, struct samr_Ids); + s->lookup.out.types = talloc_zero(s, struct samr_Ids); + if (composite_nomem(s->lookup.out.rids, c)) return c; + if (composite_nomem(s->lookup.out.types, c)) return c; s->lookup.in.names[0].string = talloc_strdup(s, io->in.username); if (composite_nomem(s->lookup.in.names[0].string, c)) return c; diff --git a/source4/libnet/userman.c b/source4/libnet/userman.c index 398d9f2cb0..c638d8af32 100644 --- a/source4/libnet/userman.c +++ b/source4/libnet/userman.c @@ -236,12 +236,12 @@ static void continue_userdel_name_found(struct rpc_request *req) /* what to do when there's no user account to delete and what if there's more than one rid resolved */ - if (!s->lookupname.out.rids.count) { + if (!s->lookupname.out.rids->count) { c->status = NT_STATUS_NO_SUCH_USER; composite_error(c, c->status); return; - } else if (!s->lookupname.out.rids.count > 1) { + } else if (!s->lookupname.out.rids->count > 1) { c->status = NT_STATUS_INVALID_ACCOUNT_NAME; composite_error(c, c->status); return; @@ -251,8 +251,8 @@ static void continue_userdel_name_found(struct rpc_request *req) if (s->monitor_fn) { struct msg_rpc_lookup_name msg_lookup; - msg_lookup.rid = s->lookupname.out.rids.ids; - msg_lookup.count = s->lookupname.out.rids.count; + msg_lookup.rid = s->lookupname.out.rids->ids; + msg_lookup.count = s->lookupname.out.rids->count; msg.type = mon_SamrLookupName; msg.data = (void*)&msg_lookup; @@ -262,7 +262,7 @@ static void continue_userdel_name_found(struct rpc_request *req) /* prepare the arguments for rpc call */ s->openuser.in.domain_handle = &s->domain_handle; - s->openuser.in.rid = s->lookupname.out.rids.ids[0]; + s->openuser.in.rid = s->lookupname.out.rids->ids[0]; s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; s->openuser.out.user_handle = &s->user_handle; @@ -393,6 +393,10 @@ struct composite_context *libnet_rpc_userdel_send(struct dcerpc_pipe *p, s->lookupname.in.num_names = 1; s->lookupname.in.names = talloc_zero(s, struct lsa_String); s->lookupname.in.names->string = io->in.username; + s->lookupname.out.rids = talloc_zero(s, struct samr_Ids); + s->lookupname.out.types = talloc_zero(s, struct samr_Ids); + if (composite_nomem(s->lookupname.out.rids, c)) return c; + if (composite_nomem(s->lookupname.out.types, c)) return c; /* send the request */ lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); @@ -500,12 +504,12 @@ static void continue_usermod_name_found(struct rpc_request *req) /* what to do when there's no user account to delete and what if there's more than one rid resolved */ - if (!s->lookupname.out.rids.count) { + if (!s->lookupname.out.rids->count) { c->status = NT_STATUS_NO_SUCH_USER; composite_error(c, c->status); return; - } else if (!s->lookupname.out.rids.count > 1) { + } else if (!s->lookupname.out.rids->count > 1) { c->status = NT_STATUS_INVALID_ACCOUNT_NAME; composite_error(c, c->status); return; @@ -515,8 +519,8 @@ static void continue_usermod_name_found(struct rpc_request *req) if (s->monitor_fn) { struct msg_rpc_lookup_name msg_lookup; - msg_lookup.rid = s->lookupname.out.rids.ids; - msg_lookup.count = s->lookupname.out.rids.count; + msg_lookup.rid = s->lookupname.out.rids->ids; + msg_lookup.count = s->lookupname.out.rids->count; msg.type = mon_SamrLookupName; msg.data = (void*)&msg_lookup; @@ -526,7 +530,7 @@ static void continue_usermod_name_found(struct rpc_request *req) /* prepare the next rpc call */ s->openuser.in.domain_handle = &s->domain_handle; - s->openuser.in.rid = s->lookupname.out.rids.ids[0]; + s->openuser.in.rid = s->lookupname.out.rids->ids[0]; s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; s->openuser.out.user_handle = &s->user_handle; @@ -679,6 +683,9 @@ static NTSTATUS usermod_change(struct composite_context *c, if (!do_set) { s->queryuser.in.user_handle = &s->user_handle; s->queryuser.in.level = level; + s->queryuser.out.info = talloc(s, union samr_UserInfo *); + if (composite_nomem(s->queryuser.out.info, c)) return; + /* send query user info request to retrieve complete data of a particular info level */ @@ -751,7 +758,7 @@ static void continue_usermod_user_queried(struct rpc_request *req) /* get returned user data and make a change (potentially one of many) */ - s->info = *s->queryuser.out.info; + s->info = *(*s->queryuser.out.info); usermod_setfields(s, &level, i, true); @@ -834,6 +841,10 @@ struct composite_context *libnet_rpc_usermod_send(struct dcerpc_pipe *p, s->lookupname.in.num_names = 1; s->lookupname.in.names = talloc_zero(s, struct lsa_String); s->lookupname.in.names->string = io->in.username; + s->lookupname.out.rids = talloc_zero(s, struct samr_Ids); + s->lookupname.out.types = talloc_zero(s, struct samr_Ids); + if (composite_nomem(s->lookupname.out.rids, c)) return c; + if (composite_nomem(s->lookupname.out.types, c)) return c; /* send the rpc request */ lookup_req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname); diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl deleted file mode 100644 index 47882dfb84..0000000000 --- a/source4/librpc/idl/samr.idl +++ /dev/null @@ -1,1424 +0,0 @@ -#include "idl_types.h" - -/* - samr interface definition -*/ -import "misc.idl", "lsa.idl", "security.idl"; - -/* - Thanks to Todd Sabin for some information from his samr.idl in acltools -*/ - -[ uuid("12345778-1234-abcd-ef00-0123456789ac"), - version(1.0), - endpoint("ncacn_np:[\\pipe\\samr]","ncacn_ip_tcp:", "ncalrpc:"), - pointer_default(unique) -] interface samr -{ - typedef bitmap security_secinfo security_secinfo; - - /* account control (acct_flags) bits */ - typedef [public,bitmap32bit] bitmap { - ACB_DISABLED = 0x00000001, /* 1 = User account disabled */ - ACB_HOMDIRREQ = 0x00000002, /* 1 = Home directory required */ - ACB_PWNOTREQ = 0x00000004, /* 1 = User password not required */ - ACB_TEMPDUP = 0x00000008, /* 1 = Temporary duplicate account */ - ACB_NORMAL = 0x00000010, /* 1 = Normal user account */ - ACB_MNS = 0x00000020, /* 1 = MNS logon user account */ - ACB_DOMTRUST = 0x00000040, /* 1 = Interdomain trust account */ - ACB_WSTRUST = 0x00000080, /* 1 = Workstation trust account */ - ACB_SVRTRUST = 0x00000100, /* 1 = Server trust account */ - ACB_PWNOEXP = 0x00000200, /* 1 = User password does not expire */ - ACB_AUTOLOCK = 0x00000400, /* 1 = Account auto locked */ - ACB_ENC_TXT_PWD_ALLOWED = 0x00000800, /* 1 = Encryped text password is allowed */ - ACB_SMARTCARD_REQUIRED = 0x00001000, /* 1 = Smart Card required */ - ACB_TRUSTED_FOR_DELEGATION = 0x00002000, /* 1 = Trusted for Delegation */ - ACB_NOT_DELEGATED = 0x00004000, /* 1 = Not delegated */ - ACB_USE_DES_KEY_ONLY = 0x00008000, /* 1 = Use DES key only */ - ACB_DONT_REQUIRE_PREAUTH = 0x00010000, /* 1 = Preauth not required */ - ACB_PW_EXPIRED = 0x00020000, /* 1 = Password Expired */ - ACB_NO_AUTH_DATA_REQD = 0x00080000 /* 1 = No authorization data required */ - } samr_AcctFlags; - - typedef [bitmap32bit] bitmap { - SAMR_ACCESS_CONNECT_TO_SERVER = 0x00000001, - SAMR_ACCESS_SHUTDOWN_SERVER = 0x00000002, - SAMR_ACCESS_INITIALIZE_SERVER = 0x00000004, - SAMR_ACCESS_CREATE_DOMAIN = 0x00000008, - SAMR_ACCESS_ENUM_DOMAINS = 0x00000010, - SAMR_ACCESS_OPEN_DOMAIN = 0x00000020 - } samr_ConnectAccessMask; - - typedef [bitmap32bit] bitmap { - SAMR_USER_ACCESS_GET_NAME_ETC = 0x00000001, - SAMR_USER_ACCESS_GET_LOCALE = 0x00000002, - SAMR_USER_ACCESS_SET_LOC_COM = 0x00000004, - SAMR_USER_ACCESS_GET_LOGONINFO = 0x00000008, - SAMR_USER_ACCESS_GET_ATTRIBUTES = 0x00000010, - SAMR_USER_ACCESS_SET_ATTRIBUTES = 0x00000020, - SAMR_USER_ACCESS_CHANGE_PASSWORD = 0x00000040, - SAMR_USER_ACCESS_SET_PASSWORD = 0x00000080, - SAMR_USER_ACCESS_GET_GROUPS = 0x00000100, - SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP = 0x00000200, - SAMR_USER_ACCESS_CHANGE_GROUP_MEMBERSHIP = 0x00000400 - } samr_UserAccessMask; - - typedef [bitmap32bit] bitmap { - SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 = 0x00000001, - SAMR_DOMAIN_ACCESS_SET_INFO_1 = 0x00000002, - SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 = 0x00000004, - SAMR_DOMAIN_ACCESS_SET_INFO_2 = 0x00000008, - SAMR_DOMAIN_ACCESS_CREATE_USER = 0x00000010, - SAMR_DOMAIN_ACCESS_CREATE_GROUP = 0x00000020, - SAMR_DOMAIN_ACCESS_CREATE_ALIAS = 0x00000040, - SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS = 0x00000080, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS = 0x00000100, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT = 0x00000200, - SAMR_DOMAIN_ACCESS_SET_INFO_3 = 0x00000400 - } samr_DomainAccessMask; - - typedef [bitmap32bit] bitmap { - SAMR_GROUP_ACCESS_LOOKUP_INFO = 0x00000001, - SAMR_GROUP_ACCESS_SET_INFO = 0x00000002, - SAMR_GROUP_ACCESS_ADD_MEMBER = 0x00000004, - SAMR_GROUP_ACCESS_REMOVE_MEMBER = 0x00000008, - SAMR_GROUP_ACCESS_GET_MEMBERS = 0x00000010 - } samr_GroupAccessMask; - - typedef [bitmap32bit] bitmap { - SAMR_ALIAS_ACCESS_ADD_MEMBER = 0x00000001, - SAMR_ALIAS_ACCESS_REMOVE_MEMBER = 0x00000002, - SAMR_ALIAS_ACCESS_GET_MEMBERS = 0x00000004, - SAMR_ALIAS_ACCESS_LOOKUP_INFO = 0x00000008, - SAMR_ALIAS_ACCESS_SET_INFO = 0x00000010 - } samr_AliasAccessMask; - - /******************/ - /* Function: 0x00 */ - NTSTATUS samr_Connect ( - /* notice the lack of [string] */ - [in,unique] uint16 *system_name, - [in] samr_ConnectAccessMask access_mask, - [out,ref] policy_handle *connect_handle - ); - - - /******************/ - /* Function: 0x01 */ - [public] NTSTATUS samr_Close ( - [in,out,ref] policy_handle *handle - ); - - /******************/ - /* Function: 0x02 */ - - NTSTATUS samr_SetSecurity ( - [in,ref] policy_handle *handle, - [in] security_secinfo sec_info, - [in,ref] sec_desc_buf *sdbuf - ); - - /******************/ - /* Function: 0x03 */ - - NTSTATUS samr_QuerySecurity ( - [in,ref] policy_handle *handle, - [in] security_secinfo sec_info, - [out,unique] sec_desc_buf *sdbuf - ); - - /******************/ - /* Function: 0x04 */ - - /* - shutdown the SAM - once you call this the SAM will be dead - */ - NTSTATUS samr_Shutdown ( - [in,ref] policy_handle *connect_handle - ); - - /******************/ - /* Function: 0x05 */ - NTSTATUS samr_LookupDomain ( - [in,ref] policy_handle *connect_handle, - [in,ref] lsa_String *domain_name, - [out,unique] dom_sid2 *sid - ); - - - /******************/ - /* Function: 0x06 */ - - typedef struct { - uint32 idx; - lsa_String name; - } samr_SamEntry; - - typedef struct { - uint32 count; - [size_is(count)] samr_SamEntry *entries; - } samr_SamArray; - - NTSTATUS samr_EnumDomains ( - [in,ref] policy_handle *connect_handle, - [in,out,ref] uint32 *resume_handle, - [in] uint32 buf_size, - [out,unique] samr_SamArray *sam, - [out] uint32 num_entries - ); - - - /************************/ - /* Function 0x07 */ - [public] NTSTATUS samr_OpenDomain( - [in,ref] policy_handle *connect_handle, - [in] samr_DomainAccessMask access_mask, - [in,ref] dom_sid2 *sid, - [out,ref] policy_handle *domain_handle - ); - - /************************/ - /* Function 0x08 */ - /* server roles */ - typedef [v1_enum] enum { - SAMR_ROLE_STANDALONE = 0, - SAMR_ROLE_DOMAIN_MEMBER = 1, - SAMR_ROLE_DOMAIN_BDC = 2, - SAMR_ROLE_DOMAIN_PDC = 3 - } samr_Role; - - /* password properties flags */ - typedef [public,bitmap32bit] bitmap { - DOMAIN_PASSWORD_COMPLEX = 0x00000001, - DOMAIN_PASSWORD_NO_ANON_CHANGE = 0x00000002, - DOMAIN_PASSWORD_NO_CLEAR_CHANGE = 0x00000004, - DOMAIN_PASSWORD_LOCKOUT_ADMINS = 0x00000008, - DOMAIN_PASSWORD_STORE_CLEARTEXT = 0x00000010, - DOMAIN_REFUSE_PASSWORD_CHANGE = 0x00000020 - } samr_PasswordProperties; - - typedef struct { - uint16 min_password_length; - uint16 password_history_length; - samr_PasswordProperties password_properties; - /* yes, these are signed. They are in negative 100ns */ - dlong max_password_age; - dlong min_password_age; - } samr_DomInfo1; - - typedef struct { - NTTIME force_logoff_time; - lsa_String oem_information; /* comment */ - lsa_String domain_name; - lsa_String primary; /* PDC name if this is a BDC */ - udlong sequence_num; - uint32 unknown2; - samr_Role role; - uint32 unknown3; - uint32 num_users; - uint32 num_groups; - uint32 num_aliases; - } samr_DomGeneralInformation; - - typedef struct { - NTTIME force_logoff_time; - } samr_DomInfo3; - - typedef struct { - lsa_String oem_information; /* comment */ - } samr_DomOEMInformation; - - typedef struct { - lsa_String domain_name; - } samr_DomInfo5; - - typedef struct { - lsa_String primary; - } samr_DomInfo6; - - typedef struct { - samr_Role role; - } samr_DomInfo7; - - typedef struct { - hyper sequence_num; - NTTIME domain_create_time; - } samr_DomInfo8; - - typedef struct { - uint32 unknown; /* w2k3 returns 1 */ - } samr_DomInfo9; - - typedef struct { - samr_DomGeneralInformation general; - hyper lockout_duration; - hyper lockout_window; - uint16 lockout_threshold; - } samr_DomGeneralInformation2; - - typedef struct { - hyper lockout_duration; - hyper lockout_window; - uint16 lockout_threshold; - } samr_DomInfo12; - - typedef struct { - hyper sequence_num; - NTTIME domain_create_time; - uint32 unknown1; - uint32 unknown2; - } samr_DomInfo13; - - typedef [switch_type(uint16)] union { - [case(1)] samr_DomInfo1 info1; - [case(2)] samr_DomGeneralInformation general; - [case(3)] samr_DomInfo3 info3; - [case(4)] samr_DomOEMInformation oem; - [case(5)] samr_DomInfo5 info5; - [case(6)] samr_DomInfo6 info6; - [case(7)] samr_DomInfo7 info7; - [case(8)] samr_DomInfo8 info8; - [case(9)] samr_DomInfo9 info9; - [case(11)] samr_DomGeneralInformation2 general2; - [case(12)] samr_DomInfo12 info12; - [case(13)] samr_DomInfo13 info13; - } samr_DomainInfo; - - NTSTATUS samr_QueryDomainInfo( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [out,switch_is(level),unique] samr_DomainInfo *info - ); - - /************************/ - /* Function 0x09 */ - /* - only levels 1, 3, 4, 6, 7, 9, 12 are valid for this - call in w2k3 - */ - NTSTATUS samr_SetDomainInfo( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [in,switch_is(level),ref] samr_DomainInfo *info - ); - - - /************************/ - /* Function 0x0a */ - NTSTATUS samr_CreateDomainGroup( - [in,ref] policy_handle *domain_handle, - [in,ref] lsa_String *name, - [in] samr_GroupAccessMask access_mask, - [out,ref] policy_handle *group_handle, - [out,ref] uint32 *rid - ); - - - /************************/ - /* Function 0x0b */ - NTSTATUS samr_EnumDomainGroups( - [in,ref] policy_handle *domain_handle, - [in,out,ref] uint32 *resume_handle, - [in] uint32 max_size, - [out,unique] samr_SamArray *sam, - [out] uint32 num_entries - ); - - /************************/ - /* Function 0x0c */ - NTSTATUS samr_CreateUser( - [in,ref] policy_handle *domain_handle, - [in,ref] lsa_String *account_name, - [in] samr_UserAccessMask access_mask, - [out,ref] policy_handle *user_handle, - [out,ref] uint32 *rid - ); - - /************************/ - /* Function 0x0d */ - - - /* w2k3 treats max_size as max_users*54 and sets the - resume_handle as the rid of the last user sent - */ - const int SAMR_ENUM_USERS_MULTIPLIER = 54; - - NTSTATUS samr_EnumDomainUsers( - [in,ref] policy_handle *domain_handle, - [in,out,ref] uint32 *resume_handle, - [in] samr_AcctFlags acct_flags, - [in] uint32 max_size, - [out,unique] samr_SamArray *sam, - [out] uint32 num_entries - ); - - /************************/ - /* Function 0x0e */ - NTSTATUS samr_CreateDomAlias( - [in,ref] policy_handle *domain_handle, - [in,ref] lsa_String *alias_name, - [in] samr_AliasAccessMask access_mask, - [out,ref] policy_handle *alias_handle, - [out,ref] uint32 *rid - ); - - /************************/ - /* Function 0x0f */ - NTSTATUS samr_EnumDomainAliases( - [in,ref] policy_handle *domain_handle, - [in,out,ref] uint32 *resume_handle, - [in] samr_AcctFlags acct_flags, - [out,unique] samr_SamArray *sam, - [out] uint32 num_entries - ); - - /************************/ - /* Function 0x10 */ - - typedef struct { - [range(0,1024)] uint32 count; - [size_is(count)] uint32 *ids; - } samr_Ids; - - NTSTATUS samr_GetAliasMembership( - [in,ref] policy_handle *domain_handle, - [in,ref] lsa_SidArray *sids, - [out,ref] samr_Ids *rids - ); - - /************************/ - /* Function 0x11 */ - - [public] NTSTATUS samr_LookupNames( - [in,ref] policy_handle *domain_handle, - [in,range(0,1000)] uint32 num_names, - [in,size_is(1000),length_is(num_names)] lsa_String names[], - [out] samr_Ids rids, - [out] samr_Ids types - ); - - - /************************/ - /* Function 0x12 */ - NTSTATUS samr_LookupRids( - [in,ref] policy_handle *domain_handle, - [in,range(0,1000)] uint32 num_rids, - [in,size_is(1000),length_is(num_rids)] uint32 rids[], - [out] lsa_Strings names, - [out] samr_Ids types - ); - - /************************/ - /* Function 0x13 */ - NTSTATUS samr_OpenGroup( - [in,ref] policy_handle *domain_handle, - [in] samr_GroupAccessMask access_mask, - [in] uint32 rid, - [out,ref] policy_handle *group_handle - ); - - /* Group attributes */ - typedef [public,bitmap32bit] bitmap { - SE_GROUP_MANDATORY = 0x00000001, - SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002, - SE_GROUP_ENABLED = 0x00000004, - SE_GROUP_OWNER = 0x00000008, - SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010, - SE_GROUP_RESOURCE = 0x20000000, - SE_GROUP_LOGON_ID = 0xC0000000 - } samr_GroupAttrs; - - /************************/ - /* Function 0x14 */ - - typedef struct { - lsa_String name; - samr_GroupAttrs attributes; - uint32 num_members; - lsa_String description; - } samr_GroupInfoAll; - - typedef struct { - samr_GroupAttrs attributes; - } samr_GroupInfoAttributes; - - typedef struct { - lsa_String description; - } samr_GroupInfoDescription; - - typedef enum { - GROUPINFOALL = 1, - GROUPINFONAME = 2, - GROUPINFOATTRIBUTES = 3, - GROUPINFODESCRIPTION = 4, - GROUPINFOALL2 = 5 - } samr_GroupInfoEnum; - - typedef [switch_type(samr_GroupInfoEnum)] union { - [case(GROUPINFOALL)] samr_GroupInfoAll all; - [case(GROUPINFONAME)] lsa_String name; - [case(GROUPINFOATTRIBUTES)] samr_GroupInfoAttributes attributes; - [case(GROUPINFODESCRIPTION)] lsa_String description; - [case(GROUPINFOALL2)] samr_GroupInfoAll all2; - } samr_GroupInfo; - - NTSTATUS samr_QueryGroupInfo( - [in,ref] policy_handle *group_handle, - [in] samr_GroupInfoEnum level, - [out,switch_is(level),unique] samr_GroupInfo *info - ); - - /************************/ - /* Function 0x15 */ - NTSTATUS samr_SetGroupInfo( - [in,ref] policy_handle *group_handle, - [in] samr_GroupInfoEnum level, - [in,switch_is(level),ref] samr_GroupInfo *info - ); - - /************************/ - /* Function 0x16 */ - NTSTATUS samr_AddGroupMember( - [in,ref] policy_handle *group_handle, - [in] uint32 rid, - [in] uint32 flags - ); - - /************************/ - /* Function 0x17 */ - NTSTATUS samr_DeleteDomainGroup( - [in,out,ref] policy_handle *group_handle - ); - - /************************/ - /* Function 0x18 */ - NTSTATUS samr_DeleteGroupMember( - [in,ref] policy_handle *group_handle, - [in] uint32 rid - ); - - - /************************/ - /* Function 0x19 */ - typedef struct { - uint32 count; - [size_is(count)] uint32 *rids; - [size_is(count)] uint32 *types; - } samr_RidTypeArray; - - NTSTATUS samr_QueryGroupMember( - [in,ref] policy_handle *group_handle, - [out,unique] samr_RidTypeArray *rids - ); - - - /************************/ - /* Function 0x1a */ - - /* - win2003 seems to accept any data at all for the two integers - below, and doesn't seem to do anything with them that I can - see. Weird. I really expected the first integer to be a rid - and the second to be the attributes for that rid member. - */ - NTSTATUS samr_SetMemberAttributesOfGroup( - [in,ref] policy_handle *group_handle, - [in] uint32 unknown1, - [in] uint32 unknown2 - ); - - - /************************/ - /* Function 0x1b */ - NTSTATUS samr_OpenAlias ( - [in,ref] policy_handle *domain_handle, - [in] samr_AliasAccessMask access_mask, - [in] uint32 rid, - [out,ref] policy_handle *alias_handle - ); - - - /************************/ - /* Function 0x1c */ - - typedef struct { - lsa_String name; - uint32 num_members; - lsa_String description; - } samr_AliasInfoAll; - - typedef enum { - ALIASINFOALL = 1, - ALIASINFONAME = 2, - ALIASINFODESCRIPTION = 3 - } samr_AliasInfoEnum; - - typedef [switch_type(samr_AliasInfoEnum)] union { - [case(ALIASINFOALL)] samr_AliasInfoAll all; - [case(ALIASINFONAME)] lsa_String name; - [case(ALIASINFODESCRIPTION)] lsa_String description; - } samr_AliasInfo; - - NTSTATUS samr_QueryAliasInfo( - [in,ref] policy_handle *alias_handle, - [in] samr_AliasInfoEnum level, - [out,switch_is(level),unique] samr_AliasInfo *info - ); - - /************************/ - /* Function 0x1d */ - NTSTATUS samr_SetAliasInfo( - [in,ref] policy_handle *alias_handle, - [in] samr_AliasInfoEnum level, - [in,switch_is(level),ref] samr_AliasInfo *info - ); - - /************************/ - /* Function 0x1e */ - NTSTATUS samr_DeleteDomAlias( - [in,out,ref] policy_handle *alias_handle - ); - - /************************/ - /* Function 0x1f */ - NTSTATUS samr_AddAliasMember( - [in,ref] policy_handle *alias_handle, - [in,ref] dom_sid2 *sid - ); - - /************************/ - /* Function 0x20 */ - NTSTATUS samr_DeleteAliasMember( - [in,ref] policy_handle *alias_handle, - [in,ref] dom_sid2 *sid - ); - - /************************/ - /* Function 0x21 */ - NTSTATUS samr_GetMembersInAlias( - [in,ref] policy_handle *alias_handle, - [out,ref] lsa_SidArray *sids - ); - - /************************/ - /* Function 0x22 */ - [public] NTSTATUS samr_OpenUser( - [in,ref] policy_handle *domain_handle, - [in] samr_UserAccessMask access_mask, - [in] uint32 rid, - [out,ref] policy_handle *user_handle - ); - - /************************/ - /* Function 0x23 */ - NTSTATUS samr_DeleteUser( - [in,out,ref] policy_handle *user_handle - ); - - /************************/ - /* Function 0x24 */ - typedef struct { - lsa_String account_name; - lsa_String full_name; - uint32 primary_gid; - lsa_String description; - lsa_String comment; - } samr_UserInfo1; - - typedef struct { - lsa_String comment; - lsa_String unknown; /* settable, but doesn't stick. probably obsolete */ - uint16 country_code; - uint16 code_page; - } samr_UserInfo2; - - /* this is also used in samr and netlogon */ - typedef [public, flag(NDR_PAHEX)] struct { - uint16 units_per_week; - [size_is(1260), length_is(units_per_week/8)] uint8 *bits; - } samr_LogonHours; - - typedef struct { - lsa_String account_name; - lsa_String full_name; - uint32 rid; - uint32 primary_gid; - lsa_String home_directory; - lsa_String home_drive; - lsa_String logon_script; - lsa_String profile_path; - lsa_String workstations; - NTTIME last_logon; - NTTIME last_logoff; - NTTIME last_password_change; - NTTIME allow_password_change; - NTTIME force_password_change; - samr_LogonHours logon_hours; - uint16 bad_password_count; - uint16 logon_count; - samr_AcctFlags acct_flags; - } samr_UserInfo3; - - typedef struct { - samr_LogonHours logon_hours; - } samr_UserInfo4; - - typedef struct { - lsa_String account_name; - lsa_String full_name; - uint32 rid; - uint32 primary_gid; - lsa_String home_directory; - lsa_String home_drive; - lsa_String logon_script; - lsa_String profile_path; - lsa_String description; - lsa_String workstations; - NTTIME last_logon; - NTTIME last_logoff; - samr_LogonHours logon_hours; - uint16 bad_password_count; - uint16 logon_count; - NTTIME last_password_change; - NTTIME acct_expiry; - samr_AcctFlags acct_flags; - } samr_UserInfo5; - - typedef struct { - lsa_String account_name; - lsa_String full_name; - } samr_UserInfo6; - - typedef struct { - lsa_String account_name; - } samr_UserInfo7; - - typedef struct { - lsa_String full_name; - } samr_UserInfo8; - - typedef struct { - uint32 primary_gid; - } samr_UserInfo9; - - typedef struct { - lsa_String home_directory; - lsa_String home_drive; - } samr_UserInfo10; - - typedef struct { - lsa_String logon_script; - } samr_UserInfo11; - - typedef struct { - lsa_String profile_path; - } samr_UserInfo12; - - typedef struct { - lsa_String description; - } samr_UserInfo13; - - typedef struct { - lsa_String workstations; - } samr_UserInfo14; - - typedef struct { - samr_AcctFlags acct_flags; - } samr_UserInfo16; - - typedef struct { - NTTIME acct_expiry; - } samr_UserInfo17; - - typedef [public, flag(NDR_PAHEX)] struct { - uint8 hash[16]; - } samr_Password; - - typedef struct { - samr_Password lm_pwd; - samr_Password nt_pwd; - boolean8 lm_pwd_active; - boolean8 nt_pwd_active; - } samr_UserInfo18; - - typedef struct { - lsa_String parameters; - } samr_UserInfo20; - - /* this defines the bits used for fields_present in info21 */ - typedef [bitmap32bit] bitmap { - SAMR_FIELD_ACCOUNT_NAME = 0x00000001, - SAMR_FIELD_FULL_NAME = 0x00000002, - SAMR_FIELD_RID = 0x00000004, - SAMR_FIELD_PRIMARY_GID = 0x00000008, - SAMR_FIELD_DESCRIPTION = 0x00000010, - SAMR_FIELD_COMMENT = 0x00000020, - SAMR_FIELD_HOME_DIRECTORY = 0x00000040, - SAMR_FIELD_HOME_DRIVE = 0x00000080, - SAMR_FIELD_LOGON_SCRIPT = 0x00000100, - SAMR_FIELD_PROFILE_PATH = 0x00000200, - SAMR_FIELD_WORKSTATIONS = 0x00000400, - SAMR_FIELD_LAST_LOGON = 0x00000800, - SAMR_FIELD_LAST_LOGOFF = 0x00001000, - SAMR_FIELD_LOGON_HOURS = 0x00002000, - SAMR_FIELD_BAD_PWD_COUNT = 0x00004000, - SAMR_FIELD_NUM_LOGONS = 0x00008000, - SAMR_FIELD_ALLOW_PWD_CHANGE = 0x00010000, - SAMR_FIELD_FORCE_PWD_CHANGE = 0x00020000, - SAMR_FIELD_LAST_PWD_CHANGE = 0x00040000, - SAMR_FIELD_ACCT_EXPIRY = 0x00080000, - SAMR_FIELD_ACCT_FLAGS = 0x00100000, - SAMR_FIELD_PARAMETERS = 0x00200000, - SAMR_FIELD_COUNTRY_CODE = 0x00400000, - SAMR_FIELD_CODE_PAGE = 0x00800000, - SAMR_FIELD_PASSWORD = 0x01000000, /* either of these */ - SAMR_FIELD_PASSWORD2 = 0x02000000, /* two bits seems to work */ - SAMR_FIELD_PRIVATE_DATA = 0x04000000, - SAMR_FIELD_EXPIRED_FLAG = 0x08000000, - SAMR_FIELD_SEC_DESC = 0x10000000, - SAMR_FIELD_OWF_PWD = 0x20000000 - } samr_FieldsPresent; - - /* used for 'password_expired' in samr_UserInfo21 */ - const int PASS_MUST_CHANGE_AT_NEXT_LOGON = 0x01; - const int PASS_DONT_CHANGE_AT_NEXT_LOGON = 0x00; - - typedef struct { - NTTIME last_logon; - NTTIME last_logoff; - NTTIME last_password_change; - NTTIME acct_expiry; - NTTIME allow_password_change; - NTTIME force_password_change; - lsa_String account_name; - lsa_String full_name; - lsa_String home_directory; - lsa_String home_drive; - lsa_String logon_script; - lsa_String profile_path; - lsa_String description; - lsa_String workstations; - lsa_String comment; - lsa_String parameters; - lsa_String unknown1; - lsa_String unknown2; - lsa_String unknown3; - uint32 buf_count; - [size_is(buf_count)] uint8 *buffer; - uint32 rid; - uint32 primary_gid; - samr_AcctFlags acct_flags; - samr_FieldsPresent fields_present; - samr_LogonHours logon_hours; - uint16 bad_password_count; - uint16 logon_count; - uint16 country_code; - uint16 code_page; - uint8 nt_password_set; - uint8 lm_password_set; - uint8 password_expired; - uint8 unknown4; - } samr_UserInfo21; - - typedef [public, flag(NDR_PAHEX)] struct { - uint8 data[516]; - } samr_CryptPassword; - - typedef struct { - samr_UserInfo21 info; - samr_CryptPassword password; - } samr_UserInfo23; - - typedef struct { - samr_CryptPassword password; - uint8 pw_len; - } samr_UserInfo24; - - typedef [flag(NDR_PAHEX)] struct { - uint8 data[532]; - } samr_CryptPasswordEx; - - typedef struct { - samr_UserInfo21 info; - samr_CryptPasswordEx password; - } samr_UserInfo25; - - typedef struct { - samr_CryptPasswordEx password; - uint8 pw_len; - } samr_UserInfo26; - - typedef [switch_type(uint16)] union { - [case(1)] samr_UserInfo1 info1; - [case(2)] samr_UserInfo2 info2; - [case(3)] samr_UserInfo3 info3; - [case(4)] samr_UserInfo4 info4; - [case(5)] samr_UserInfo5 info5; - [case(6)] samr_UserInfo6 info6; - [case(7)] samr_UserInfo7 info7; - [case(8)] samr_UserInfo8 info8; - [case(9)] samr_UserInfo9 info9; - [case(10)] samr_UserInfo10 info10; - [case(11)] samr_UserInfo11 info11; - [case(12)] samr_UserInfo12 info12; - [case(13)] samr_UserInfo13 info13; - [case(14)] samr_UserInfo14 info14; - [case(16)] samr_UserInfo16 info16; - [case(17)] samr_UserInfo17 info17; - [case(18)] samr_UserInfo18 info18; - [case(20)] samr_UserInfo20 info20; - [case(21)] samr_UserInfo21 info21; - [case(23)] samr_UserInfo23 info23; - [case(24)] samr_UserInfo24 info24; - [case(25)] samr_UserInfo25 info25; - [case(26)] samr_UserInfo26 info26; - } samr_UserInfo; - - [public] NTSTATUS samr_QueryUserInfo( - [in,ref] policy_handle *user_handle, - [in] uint16 level, - [out,unique,switch_is(level)] samr_UserInfo *info - ); - - - /************************/ - /* Function 0x25 */ - [public] NTSTATUS samr_SetUserInfo( - [in,ref] policy_handle *user_handle, - [in] uint16 level, - [in,ref,switch_is(level)] samr_UserInfo *info - ); - - /************************/ - /* Function 0x26 */ - /* - this is a password change interface that doesn't give - the server the plaintext password. Depricated. - */ - NTSTATUS samr_ChangePasswordUser( - [in,ref] policy_handle *user_handle, - [in] boolean8 lm_present, - [in,unique] samr_Password *old_lm_crypted, - [in,unique] samr_Password *new_lm_crypted, - [in] boolean8 nt_present, - [in,unique] samr_Password *old_nt_crypted, - [in,unique] samr_Password *new_nt_crypted, - [in] boolean8 cross1_present, - [in,unique] samr_Password *nt_cross, - [in] boolean8 cross2_present, - [in,unique] samr_Password *lm_cross - ); - - /************************/ - /* Function 0x27 */ - - typedef [public] struct { - uint32 rid; - samr_GroupAttrs attributes; - } samr_RidWithAttribute; - - typedef [public] struct { - uint32 count; - [size_is(count)] samr_RidWithAttribute *rids; - } samr_RidWithAttributeArray; - - NTSTATUS samr_GetGroupsForUser( - [in,ref] policy_handle *user_handle, - [out,unique] samr_RidWithAttributeArray *rids - ); - - /************************/ - /* Function 0x28 */ - - typedef struct { - uint32 idx; - uint32 rid; - samr_AcctFlags acct_flags; - lsa_String account_name; - lsa_String description; - lsa_String full_name; - } samr_DispEntryGeneral; - - typedef struct { - uint32 count; - [size_is(count)] samr_DispEntryGeneral *entries; - } samr_DispInfoGeneral; - - typedef struct { - uint32 idx; - uint32 rid; - samr_AcctFlags acct_flags; - lsa_String account_name; - lsa_String description; - } samr_DispEntryFull; - - typedef struct { - uint32 count; - [size_is(count)] samr_DispEntryFull *entries; - } samr_DispInfoFull; - - typedef struct { - uint32 idx; - uint32 rid; - samr_GroupAttrs acct_flags; - lsa_String account_name; - lsa_String description; - } samr_DispEntryFullGroup; - - typedef struct { - uint32 count; - [size_is(count)] samr_DispEntryFullGroup *entries; - } samr_DispInfoFullGroups; - - typedef struct { - uint32 idx; - lsa_AsciiStringLarge account_name; - } samr_DispEntryAscii; - - typedef struct { - uint32 count; - [size_is(count)] samr_DispEntryAscii *entries; - } samr_DispInfoAscii; - - typedef [switch_type(uint16)] union { - [case(1)] samr_DispInfoGeneral info1;/* users */ - [case(2)] samr_DispInfoFull info2; /* trust accounts? */ - [case(3)] samr_DispInfoFullGroups info3; /* groups */ - [case(4)] samr_DispInfoAscii info4; /* users */ - [case(5)] samr_DispInfoAscii info5; /* groups */ - } samr_DispInfo; - - NTSTATUS samr_QueryDisplayInfo( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [in] uint32 start_idx, - [in] uint32 max_entries, - [in] uint32 buf_size, - [out] uint32 total_size, - [out] uint32 returned_size, - [out,switch_is(level)] samr_DispInfo info - ); - - - /************************/ - /* Function 0x29 */ - - /* - this seems to be an alphabetic search function. The returned index - is the index for samr_QueryDisplayInfo needed to get names occurring - after the specified name. The supplied name does not need to exist - in the database (for example you can supply just a first letter for - searching starting at that letter) - - The level corresponds to the samr_QueryDisplayInfo level - */ - NTSTATUS samr_GetDisplayEnumerationIndex( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [in] lsa_String name, - [out] uint32 idx - ); - - - - /************************/ - /* Function 0x2a */ - - /* - w2k3 returns NT_STATUS_NOT_IMPLEMENTED for this - */ - NTSTATUS samr_TestPrivateFunctionsDomain( - [in,ref] policy_handle *domain_handle - ); - - - /************************/ - /* Function 0x2b */ - - /* - w2k3 returns NT_STATUS_NOT_IMPLEMENTED for this - */ - NTSTATUS samr_TestPrivateFunctionsUser( - [in,ref] policy_handle *user_handle - ); - - - /************************/ - /* Function 0x2c */ - - typedef struct { - uint16 min_password_length; - samr_PasswordProperties password_properties; - } samr_PwInfo; - - [public] NTSTATUS samr_GetUserPwInfo( - [in,ref] policy_handle *user_handle, - [out] samr_PwInfo info - ); - - /************************/ - /* Function 0x2d */ - NTSTATUS samr_RemoveMemberFromForeignDomain( - [in,ref] policy_handle *domain_handle, - [in,ref] dom_sid2 *sid - ); - - /************************/ - /* Function 0x2e */ - - /* - how is this different from QueryDomainInfo ?? - */ - NTSTATUS samr_QueryDomainInfo2( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [out,unique,switch_is(level)] samr_DomainInfo *info - ); - - /************************/ - /* Function 0x2f */ - - /* - how is this different from QueryUserInfo ?? - */ - NTSTATUS samr_QueryUserInfo2( - [in,ref] policy_handle *user_handle, - [in] uint16 level, - [out,unique,switch_is(level)] samr_UserInfo *info - ); - - /************************/ - /* Function 0x30 */ - - /* - how is this different from QueryDisplayInfo?? - */ - NTSTATUS samr_QueryDisplayInfo2( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [in] uint32 start_idx, - [in] uint32 max_entries, - [in] uint32 buf_size, - [out] uint32 total_size, - [out] uint32 returned_size, - [out,switch_is(level)] samr_DispInfo info - ); - - /************************/ - /* Function 0x31 */ - - /* - how is this different from GetDisplayEnumerationIndex ?? - */ - NTSTATUS samr_GetDisplayEnumerationIndex2( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [in] lsa_String name, - [out] uint32 idx - ); - - - /************************/ - /* Function 0x32 */ - NTSTATUS samr_CreateUser2( - [in,ref] policy_handle *domain_handle, - [in,ref] lsa_String *account_name, - [in] samr_AcctFlags acct_flags, - [in] samr_UserAccessMask access_mask, - [out,ref] policy_handle *user_handle, - [out,ref] uint32 *access_granted, - [out,ref] uint32 *rid - ); - - - /************************/ - /* Function 0x33 */ - - /* - another duplicate. There must be a reason .... - */ - NTSTATUS samr_QueryDisplayInfo3( - [in,ref] policy_handle *domain_handle, - [in] uint16 level, - [in] uint32 start_idx, - [in] uint32 max_entries, - [in] uint32 buf_size, - [out] uint32 total_size, - [out] uint32 returned_size, - [out,switch_is(level)] samr_DispInfo info - ); - - /************************/ - /* Function 0x34 */ - NTSTATUS samr_AddMultipleMembersToAlias( - [in,ref] policy_handle *alias_handle, - [in,ref] lsa_SidArray *sids - ); - - /************************/ - /* Function 0x35 */ - NTSTATUS samr_RemoveMultipleMembersFromAlias( - [in,ref] policy_handle *alias_handle, - [in,ref] lsa_SidArray *sids - ); - - /************************/ - /* Function 0x36 */ - - NTSTATUS samr_OemChangePasswordUser2( - [in,unique] lsa_AsciiString *server, - [in,ref] lsa_AsciiString *account, - [in,unique] samr_CryptPassword *password, - [in,unique] samr_Password *hash - ); - - /************************/ - /* Function 0x37 */ - NTSTATUS samr_ChangePasswordUser2( - [in,unique] lsa_String *server, - [in,ref] lsa_String *account, - [in,unique] samr_CryptPassword *nt_password, - [in,unique] samr_Password *nt_verifier, - [in] boolean8 lm_change, - [in,unique] samr_CryptPassword *lm_password, - [in,unique] samr_Password *lm_verifier - ); - - /************************/ - /* Function 0x38 */ - NTSTATUS samr_GetDomPwInfo( - [in,unique] lsa_String *domain_name, - [out] samr_PwInfo info - ); - - /************************/ - /* Function 0x39 */ - NTSTATUS samr_Connect2( - [in,unique,string,charset(UTF16)] uint16 *system_name, - [in] samr_ConnectAccessMask access_mask, - [out,ref] policy_handle *connect_handle - ); - - /************************/ - /* Function 0x3a */ - /* - seems to be an exact alias for samr_SetUserInfo() - */ - [public] NTSTATUS samr_SetUserInfo2( - [in,ref] policy_handle *user_handle, - [in] uint16 level, - [in,ref,switch_is(level)] samr_UserInfo *info - ); - - /************************/ - /* Function 0x3b */ - /* - this one is mysterious. I have a few guesses, but nothing working yet - */ - NTSTATUS samr_SetBootKeyInformation( - [in,ref] policy_handle *connect_handle, - [in] uint32 unknown1, - [in] uint32 unknown2, - [in] uint32 unknown3 - ); - - /************************/ - /* Function 0x3c */ - NTSTATUS samr_GetBootKeyInformation( - [in,ref] policy_handle *domain_handle, - [out] uint32 unknown - ); - - /************************/ - /* Function 0x3d */ - NTSTATUS samr_Connect3( - [in,unique,string,charset(UTF16)] uint16 *system_name, - /* this unknown value seems to be completely ignored by w2k3 */ - [in] uint32 unknown, - [in] samr_ConnectAccessMask access_mask, - [out,ref] policy_handle *connect_handle - ); - - /************************/ - /* Function 0x3e */ - - typedef enum { - SAMR_CONNECT_PRE_W2K = 1, - SAMR_CONNECT_W2K = 2, - SAMR_CONNECT_AFTER_W2K = 3 - } samr_ConnectVersion; - - NTSTATUS samr_Connect4( - [in,unique,string,charset(UTF16)] uint16 *system_name, - [in] samr_ConnectVersion client_version, - [in] samr_ConnectAccessMask access_mask, - [out,ref] policy_handle *connect_handle - ); - - /************************/ - /* Function 0x3f */ - - typedef enum samr_RejectReason samr_RejectReason; - - typedef struct { - samr_RejectReason reason; - uint32 unknown1; - uint32 unknown2; - } samr_ChangeReject; - - NTSTATUS samr_ChangePasswordUser3( - [in,unique] lsa_String *server, - [in,ref] lsa_String *account, - [in,unique] samr_CryptPassword *nt_password, - [in,unique] samr_Password *nt_verifier, - [in] boolean8 lm_change, - [in,unique] samr_CryptPassword *lm_password, - [in,unique] samr_Password *lm_verifier, - [in,unique] samr_CryptPassword *password3, - [out,unique] samr_DomInfo1 *dominfo, - [out,unique] samr_ChangeReject *reject - ); - - /************************/ - /* Function 0x40 */ - - typedef struct { - samr_ConnectVersion client_version; /* w2k3 gives 3 */ - uint32 unknown2; /* w2k3 gives 0 */ - } samr_ConnectInfo1; - - typedef union { - [case(1)] samr_ConnectInfo1 info1; - } samr_ConnectInfo; - - [public] NTSTATUS samr_Connect5( - [in,unique,string,charset(UTF16)] uint16 *system_name, - [in] samr_ConnectAccessMask access_mask, - [in,out] uint32 level, - [in,out,switch_is(level),ref] samr_ConnectInfo *info, - [out,ref] policy_handle *connect_handle - ); - - /************************/ - /* Function 0x41 */ - NTSTATUS samr_RidToSid( - [in,ref] policy_handle *domain_handle, - [in] uint32 rid, - [out,unique] dom_sid2 *sid - ); - - - /************************/ - /* Function 0x42 */ - - /* - this should set the DSRM password for the server, which is used - when booting into Directory Services Recovery Mode on a DC. Win2003 - gives me NT_STATUS_NOT_SUPPORTED - */ - - NTSTATUS samr_SetDsrmPassword( - [in,unique] lsa_String *name, - [in] uint32 unknown, - [in,unique] samr_Password *hash - ); - - - /************************/ - /* Function 0x43 */ - /************************/ - typedef [bitmap32bit] bitmap { - SAMR_VALIDATE_FIELD_PASSWORD_LAST_SET = 0x00000001, - SAMR_VALIDATE_FIELD_BAD_PASSWORD_TIME = 0x00000002, - SAMR_VALIDATE_FIELD_LOCKOUT_TIME = 0x00000004, - SAMR_VALIDATE_FIELD_BAD_PASSWORD_COUNT = 0x00000008, - SAMR_VALIDATE_FIELD_PASSWORD_HISTORY_LENGTH = 0x00000010, - SAMR_VALIDATE_FIELD_PASSWORD_HISTORY = 0x00000020 - } samr_ValidateFieldsPresent; - - typedef enum { - NetValidateAuthentication = 1, - NetValidatePasswordChange= 2, - NetValidatePasswordReset = 3 - } samr_ValidatePasswordLevel; - - /* NetApi maps samr_ValidationStatus errors to WERRORs. Haven't - * identified the mapping of - * - NERR_PasswordFilterError - * - NERR_PasswordExpired and - * - NERR_PasswordCantChange - * yet - Guenther - */ - - typedef enum { - SAMR_VALIDATION_STATUS_SUCCESS = 0, - SAMR_VALIDATION_STATUS_PASSWORD_MUST_CHANGE = 1, - SAMR_VALIDATION_STATUS_ACCOUNT_LOCKED_OUT = 2, - SAMR_VALIDATION_STATUS_BAD_PASSWORD = 4, - SAMR_VALIDATION_STATUS_PWD_HISTORY_CONFLICT = 5, - SAMR_VALIDATION_STATUS_PWD_TOO_SHORT = 6, - SAMR_VALIDATION_STATUS_PWD_TOO_LONG = 7, - SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH = 8, - SAMR_VALIDATION_STATUS_PASSWORD_TOO_RECENT = 9 - } samr_ValidationStatus; - - typedef struct { - uint32 length; - [size_is(length)] uint8 *data; - } samr_ValidationBlob; - - typedef struct { - samr_ValidateFieldsPresent fields_present; - NTTIME_hyper last_password_change; - NTTIME_hyper bad_password_time; - NTTIME_hyper lockout_time; - uint32 bad_pwd_count; - uint32 pwd_history_len; - [size_is(pwd_history_len)] samr_ValidationBlob *pwd_history; - } samr_ValidatePasswordInfo; - - typedef struct { - samr_ValidatePasswordInfo info; - samr_ValidationStatus status; - } samr_ValidatePasswordRepCtr; - - typedef [switch_type(uint16)] union { - [case(1)] samr_ValidatePasswordRepCtr ctr1; - [case(2)] samr_ValidatePasswordRepCtr ctr2; - [case(3)] samr_ValidatePasswordRepCtr ctr3; - } samr_ValidatePasswordRep; - - typedef struct { - samr_ValidatePasswordInfo info; - lsa_StringLarge password; - lsa_StringLarge account; - samr_ValidationBlob hash; - boolean8 pwd_must_change_at_next_logon; - boolean8 clear_lockout; - } samr_ValidatePasswordReq3; - - typedef struct { - samr_ValidatePasswordInfo info; - lsa_StringLarge password; - lsa_StringLarge account; - samr_ValidationBlob hash; - boolean8 password_matched; - } samr_ValidatePasswordReq2; - - typedef struct { - samr_ValidatePasswordInfo info; - boolean8 password_matched; - } samr_ValidatePasswordReq1; - - typedef [switch_type(uint16)] union { - [case(1)] samr_ValidatePasswordReq1 req1; - [case(2)] samr_ValidatePasswordReq2 req2; - [case(3)] samr_ValidatePasswordReq3 req3; - } samr_ValidatePasswordReq; - - NTSTATUS samr_ValidatePassword( - [in] samr_ValidatePasswordLevel level, - [in,switch_is(level)] samr_ValidatePasswordReq req, - [out,unique,switch_is(level)] samr_ValidatePasswordRep *rep - ); -} diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index b3118d772d..c093b536da 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -37,26 +37,28 @@ #include "../lib/util/util_ldb.h" #include "param/param.h" -/* these query macros make samr_Query[User|Group]Info a bit easier to read */ +/* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */ #define QUERY_STRING(msg, field, attr) \ - r->out.info->field.string = samdb_result_string(msg, attr, ""); + info->field.string = samdb_result_string(msg, attr, ""); #define QUERY_UINT(msg, field, attr) \ - r->out.info->field = samdb_result_uint(msg, attr, 0); + info->field = samdb_result_uint(msg, attr, 0); #define QUERY_RID(msg, field, attr) \ - r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0); + info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0); #define QUERY_UINT64(msg, field, attr) \ - r->out.info->field = samdb_result_uint64(msg, attr, 0); + info->field = samdb_result_uint64(msg, attr, 0); #define QUERY_APASSC(msg, field, attr) \ - r->out.info->field = samdb_result_allow_password_change(sam_ctx, mem_ctx, \ - a_state->domain_state->domain_dn, msg, attr); + info->field = samdb_result_allow_password_change(sam_ctx, mem_ctx, \ + a_state->domain_state->domain_dn, msg, attr); #define QUERY_FPASSC(msg, field, attr) \ - r->out.info->field = samdb_result_force_password_change(sam_ctx, mem_ctx, \ - a_state->domain_state->domain_dn, msg); + info->field = samdb_result_force_password_change(sam_ctx, mem_ctx, \ + a_state->domain_state->domain_dn, msg); #define QUERY_LHOURS(msg, field, attr) \ - r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr); + info->field = samdb_result_logon_hours(mem_ctx, msg, attr); #define QUERY_AFLAGS(msg, field, attr) \ - r->out.info->field = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, a_state->domain_state->domain_dn); + info->field = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, a_state->domain_state->domain_dn); +#define QUERY_PARAMETERS(msg, field, attr) \ + info->field = samdb_result_parameters(mem_ctx, msg, attr); /* these are used to make the Set[User|Group]Info code easier to follow */ @@ -136,6 +138,16 @@ set_el->flags = LDB_FLAG_MOD_REPLACE; \ } while (0) +#define SET_PARAMETERS(msg, field, attr) do { \ + struct ldb_message_element *set_el; \ + if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \ + return NT_STATUS_NO_MEMORY; \ + } \ + set_el = ldb_msg_find_element(msg, attr); \ + set_el->flags = LDB_FLAG_MOD_REPLACE; \ +} while (0) + + /* samr_Connect @@ -217,7 +229,7 @@ static NTSTATUS dcesrv_samr_QuerySecurity(struct dcesrv_call_state *dce_call, TA struct dcesrv_handle *h; struct sec_desc_buf *sd; - r->out.sdbuf = NULL; + *r->out.sdbuf = NULL; DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY); @@ -228,7 +240,7 @@ static NTSTATUS dcesrv_samr_QuerySecurity(struct dcesrv_call_state *dce_call, TA sd->sd = samdb_default_security_descriptor(mem_ctx); - r->out.sdbuf = sd; + *r->out.sdbuf = sd; return NT_STATUS_OK; } @@ -265,7 +277,7 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL int ret; struct ldb_dn *partitions_basedn; - r->out.sid = NULL; + *r->out.sid = NULL; DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT); @@ -307,7 +319,7 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_NO_SUCH_DOMAIN; } - r->out.sid = sid; + *r->out.sid = sid; return NT_STATUS_OK; } @@ -332,8 +344,8 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL struct ldb_dn *partitions_basedn; *r->out.resume_handle = 0; - r->out.sam = NULL; - r->out.num_entries = 0; + *r->out.sam = NULL; + *r->out.num_entries = 0; DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT); @@ -389,9 +401,9 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL } } - r->out.sam = array; - r->out.num_entries = i; - array->count = r->out.num_entries; + *r->out.sam = array; + *r->out.num_entries = i; + array->count = *r->out.num_entries; return NT_STATUS_OK; } @@ -765,18 +777,19 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, { struct dcesrv_handle *h; struct samr_domain_state *d_state; + union samr_DomainInfo *info; struct ldb_message **dom_msgs; const char * const *attrs = NULL; - r->out.info = NULL; + *r->out.info = NULL; DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); d_state = h->data; - r->out.info = talloc(mem_ctx, union samr_DomainInfo); - if (!r->out.info) { + info = talloc(mem_ctx, union samr_DomainInfo); + if (!info) { return NT_STATUS_NO_MEMORY; } @@ -881,47 +894,49 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, } } - ZERO_STRUCTP(r->out.info); + *r->out.info = info; + + ZERO_STRUCTP(info); switch (r->in.level) { case 1: return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs, - &r->out.info->info1); + &info->info1); case 2: return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs, - &r->out.info->general); + &info->general); case 3: return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs, - &r->out.info->info3); + &info->info3); case 4: return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs, - &r->out.info->oem); + &info->oem); case 5: return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs, - &r->out.info->info5); + &info->info5); case 6: return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs, - &r->out.info->info6); + &info->info6); case 7: return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs, - &r->out.info->info7); + &info->info7); case 8: return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs, - &r->out.info->info8); + &info->info8); case 9: return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs, - &r->out.info->info9); + &info->info9); case 11: return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs, - &r->out.info->general2); + &info->general2); case 12: return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs, - &r->out.info->info12); + &info->info12); case 13: return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs, - &r->out.info->info13); + &info->info13); } - + return NT_STATUS_INVALID_INFO_CLASS; } @@ -1135,10 +1150,11 @@ static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, int ldb_cnt, count, i, first; struct samr_SamEntry *entries; const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL }; + struct samr_SamArray *sam; *r->out.resume_handle = 0; - r->out.sam = NULL; - r->out.num_entries = 0; + *r->out.sam = NULL; + *r->out.num_entries = 0; DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); @@ -1189,20 +1205,22 @@ static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, /* return the rest, limit by max_size. Note that we use the w2k3 element size value of 54 */ - r->out.num_entries = count - first; - r->out.num_entries = MIN(r->out.num_entries, + *r->out.num_entries = count - first; + *r->out.num_entries = MIN(*r->out.num_entries, 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER)); - r->out.sam = talloc(mem_ctx, struct samr_SamArray); - if (!r->out.sam) { + sam = talloc(mem_ctx, struct samr_SamArray); + if (!sam) { return NT_STATUS_NO_MEMORY; } - r->out.sam->entries = entries+first; - r->out.sam->count = r->out.num_entries; + sam->entries = entries+first; + sam->count = *r->out.num_entries; + + *r->out.sam = sam; - if (r->out.num_entries < count - first) { - *r->out.resume_handle = entries[first+r->out.num_entries-1].idx; + if (*r->out.num_entries < count - first) { + *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx; return STATUS_MORE_ENTRIES; } @@ -1492,10 +1510,11 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, int ret, num_filtered_entries, i, first; struct samr_SamEntry *entries; const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL }; + struct samr_SamArray *sam; *r->out.resume_handle = 0; - r->out.sam = NULL; - r->out.num_entries = 0; + *r->out.sam = NULL; + *r->out.num_entries = 0; DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); @@ -1539,24 +1558,26 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, /* return the rest, limit by max_size. Note that we use the w2k3 element size value of 54 */ - r->out.num_entries = num_filtered_entries - first; - r->out.num_entries = MIN(r->out.num_entries, + *r->out.num_entries = num_filtered_entries - first; + *r->out.num_entries = MIN(*r->out.num_entries, 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER)); - r->out.sam = talloc(mem_ctx, struct samr_SamArray); - if (!r->out.sam) { + sam = talloc(mem_ctx, struct samr_SamArray); + if (!sam) { return NT_STATUS_NO_MEMORY; } - r->out.sam->entries = entries+first; - r->out.sam->count = r->out.num_entries; + sam->entries = entries+first; + sam->count = *r->out.num_entries; + + *r->out.sam = sam; if (first == num_filtered_entries) { return NT_STATUS_OK; } - if (r->out.num_entries < num_filtered_entries - first) { - *r->out.resume_handle = entries[first+r->out.num_entries-1].idx; + if (*r->out.num_entries < num_filtered_entries - first) { + *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx; return STATUS_MORE_ENTRIES; } @@ -1685,10 +1706,11 @@ static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call int ldb_cnt, count, i, first; struct samr_SamEntry *entries; const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL }; + struct samr_SamArray *sam; *r->out.resume_handle = 0; - r->out.sam = NULL; - r->out.num_entries = 0; + *r->out.sam = NULL; + *r->out.num_entries = 0; DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); @@ -1748,20 +1770,22 @@ static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call return NT_STATUS_OK; } - r->out.num_entries = count - first; - r->out.num_entries = MIN(r->out.num_entries, 1000); + *r->out.num_entries = count - first; + *r->out.num_entries = MIN(*r->out.num_entries, 1000); - r->out.sam = talloc(mem_ctx, struct samr_SamArray); - if (!r->out.sam) { + sam = talloc(mem_ctx, struct samr_SamArray); + if (!sam) { return NT_STATUS_NO_MEMORY; } - r->out.sam->entries = entries+first; - r->out.sam->count = r->out.num_entries; + sam->entries = entries+first; + sam->count = *r->out.num_entries; + + *r->out.sam = sam; - if (r->out.num_entries < count - first) { + if (*r->out.num_entries < count - first) { *r->out.resume_handle = - entries[first+r->out.num_entries-1].idx; + entries[first+*r->out.num_entries-1].idx; return STATUS_MORE_ENTRIES; } @@ -1859,8 +1883,8 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL const char * const attrs[] = { "sAMAccountType", "objectSid", NULL }; int count; - ZERO_STRUCT(r->out.rids); - ZERO_STRUCT(r->out.types); + ZERO_STRUCTP(r->out.rids); + ZERO_STRUCTP(r->out.types); DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); @@ -1870,13 +1894,13 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_OK; } - r->out.rids.ids = talloc_array(mem_ctx, uint32_t, r->in.num_names); - r->out.types.ids = talloc_array(mem_ctx, uint32_t, r->in.num_names); - if (!r->out.rids.ids || !r->out.types.ids) { + r->out.rids->ids = talloc_array(mem_ctx, uint32_t, r->in.num_names); + r->out.types->ids = talloc_array(mem_ctx, uint32_t, r->in.num_names); + if (!r->out.rids->ids || !r->out.types->ids) { return NT_STATUS_NO_MEMORY; } - r->out.rids.count = r->in.num_names; - r->out.types.count = r->in.num_names; + r->out.rids->count = r->in.num_names; + r->out.types->count = r->in.num_names; num_mapped = 0; @@ -1885,8 +1909,8 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL struct dom_sid *sid; uint32_t atype, rtype; - r->out.rids.ids[i] = 0; - r->out.types.ids[i] = SID_NAME_UNKNOWN; + r->out.rids->ids[i] = 0; + r->out.types->ids[i] = SID_NAME_UNKNOWN; count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, "sAMAccountName=%s", @@ -1915,8 +1939,8 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL continue; } - r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1]; - r->out.types.ids[i] = rtype; + r->out.rids->ids[i] = sid->sub_auths[sid->num_auths-1]; + r->out.types->ids[i] = rtype; num_mapped++; } @@ -1940,8 +1964,8 @@ static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLO struct lsa_String *names; uint32_t *ids; - ZERO_STRUCT(r->out.names); - ZERO_STRUCT(r->out.types); + ZERO_STRUCTP(r->out.names); + ZERO_STRUCTP(r->out.types); DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN); @@ -2002,11 +2026,11 @@ static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLO } } - r->out.names.names = names; - r->out.names.count = r->in.num_rids; + r->out.names->names = names; + r->out.names->count = r->in.num_rids; - r->out.types.ids = ids; - r->out.types.count = r->in.num_rids; + r->out.types->ids = ids; + r->out.types->count = r->in.num_rids; return status; } @@ -2103,8 +2127,9 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T const char * const attrs[4] = { "sAMAccountName", "description", "numMembers", NULL }; int ret; + union samr_GroupInfo *info; - r->out.info = NULL; + *r->out.info = NULL; DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP); @@ -2127,17 +2152,16 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T msg = res->msgs[0]; /* allocate the info structure */ - r->out.info = talloc(mem_ctx, union samr_GroupInfo); - if (r->out.info == NULL) { + info = talloc_zero(mem_ctx, union samr_GroupInfo); + if (info == NULL) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(r->out.info); /* Fill in the level */ switch (r->in.level) { case GROUPINFOALL: QUERY_STRING(msg, all.name, "sAMAccountName"); - r->out.info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */ + info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */ QUERY_UINT (msg, all.num_members, "numMembers") QUERY_STRING(msg, all.description, "description"); break; @@ -2145,22 +2169,24 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T QUERY_STRING(msg, name, "sAMAccountName"); break; case GROUPINFOATTRIBUTES: - r->out.info->attributes.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */ + info->attributes.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */ break; case GROUPINFODESCRIPTION: QUERY_STRING(msg, description, "description"); break; case GROUPINFOALL2: QUERY_STRING(msg, all2.name, "sAMAccountName"); - r->out.info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */ + info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */ QUERY_UINT (msg, all2.num_members, "numMembers") QUERY_STRING(msg, all2.description, "description"); break; default: - r->out.info = NULL; + talloc_free(info); return NT_STATUS_INVALID_INFO_CLASS; } - + + *r->out.info = info; + return NT_STATUS_OK; } @@ -2467,7 +2493,7 @@ static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, } } - r->out.rids = array; + *r->out.rids = array; return NT_STATUS_OK; } @@ -2574,8 +2600,9 @@ static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, T const char * const attrs[4] = { "sAMAccountName", "description", "numMembers", NULL }; int ret; + union samr_AliasInfo *info; - r->out.info = NULL; + *r->out.info = NULL; DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS); @@ -2590,11 +2617,10 @@ static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, T msg = res[0]; /* allocate the info structure */ - r->out.info = talloc(mem_ctx, union samr_AliasInfo); - if (r->out.info == NULL) { + info = talloc_zero(mem_ctx, union samr_AliasInfo); + if (info == NULL) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(r->out.info); switch(r->in.level) { case ALIASINFOALL: @@ -2609,10 +2635,12 @@ static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, T QUERY_STRING(msg, description, "description"); break; default: - r->out.info = NULL; + talloc_free(info); return NT_STATUS_INVALID_INFO_CLASS; } - + + *r->out.info = info; + return NT_STATUS_OK; } @@ -2989,8 +3017,9 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA struct ldb_context *sam_ctx; const char * const *attrs = NULL; + union samr_UserInfo *info; - r->out.info = NULL; + *r->out.info = NULL; DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER); @@ -3175,11 +3204,10 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA msg = res[0]; /* allocate the info structure */ - r->out.info = talloc(mem_ctx, union samr_UserInfo); - if (r->out.info == NULL) { + info = talloc_zero(mem_ctx, union samr_UserInfo); + if (info == NULL) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(r->out.info); /* fill in the reply */ switch (r->in.level) { @@ -3290,7 +3318,7 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA break; case 20: - QUERY_STRING(msg, info20.parameters, "userParameters"); + QUERY_PARAMETERS(msg, info20.parameters, "userParameters"); break; case 21: @@ -3309,11 +3337,11 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA QUERY_STRING(msg, info21.description, "description"); QUERY_STRING(msg, info21.workstations, "userWorkstations"); QUERY_STRING(msg, info21.comment, "comment"); - QUERY_STRING(msg, info21.parameters, "userParameters"); + QUERY_PARAMETERS(msg, info21.parameters, "userParameters"); QUERY_RID (msg, info21.rid, "objectSid"); QUERY_UINT (msg, info21.primary_gid, "primaryGroupID"); QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl"); - r->out.info->info21.fields_present = 0x00FFFFFF; + info->info21.fields_present = 0x00FFFFFF; QUERY_LHOURS(msg, info21.logon_hours, "logonHours"); QUERY_UINT (msg, info21.bad_password_count, "badPwdCount"); QUERY_UINT (msg, info21.logon_count, "logonCount"); @@ -3323,10 +3351,12 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA default: - r->out.info = NULL; + talloc_free(info); return NT_STATUS_INVALID_INFO_CLASS; } - + + *r->out.info = info; + return NT_STATUS_OK; } @@ -3416,7 +3446,7 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL break; case 20: - SET_STRING(msg, info20.parameters, "userParameters"); + SET_PARAMETERS(msg, info20.parameters, "userParameters"); break; case 21: @@ -3446,7 +3476,7 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL IFSET(SAMR_FIELD_ACCT_FLAGS) SET_AFLAGS(msg, info21.acct_flags, "userAccountControl"); IFSET(SAMR_FIELD_PARAMETERS) - SET_STRING(msg, info21.parameters, "userParameters"); + SET_PARAMETERS(msg, info21.parameters, "userParameters"); IFSET(SAMR_FIELD_COUNTRY_CODE) SET_UINT (msg, info21.country_code, "countryCode"); IFSET(SAMR_FIELD_CODE_PAGE) @@ -3477,7 +3507,7 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL IFSET(SAMR_FIELD_ACCT_FLAGS) SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl"); IFSET(SAMR_FIELD_PARAMETERS) - SET_STRING(msg, info23.info.parameters, "userParameters"); + SET_PARAMETERS(msg, info23.info.parameters, "userParameters"); IFSET(SAMR_FIELD_COUNTRY_CODE) SET_UINT (msg, info23.info.country_code, "countryCode"); IFSET(SAMR_FIELD_CODE_PAGE) @@ -3533,7 +3563,7 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL IFSET(SAMR_FIELD_ACCT_FLAGS) SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl"); IFSET(SAMR_FIELD_PARAMETERS) - SET_STRING(msg, info25.info.parameters, "userParameters"); + SET_PARAMETERS(msg, info25.info.parameters, "userParameters"); IFSET(SAMR_FIELD_COUNTRY_CODE) SET_UINT (msg, info25.info.country_code, "countryCode"); IFSET(SAMR_FIELD_CODE_PAGE) @@ -3650,7 +3680,7 @@ static NTSTATUS dcesrv_samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, } } - r->out.rids = array; + *r->out.rids = array; return NT_STATUS_OK; } @@ -3808,65 +3838,65 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, count += 1; } - r->out.total_size = count; + *r->out.total_size = count; if (r->in.start_idx >= count) { - r->out.returned_size = 0; + *r->out.returned_size = 0; switch(r->in.level) { case 1: - r->out.info.info1.count = r->out.returned_size; - r->out.info.info1.entries = NULL; + r->out.info->info1.count = *r->out.returned_size; + r->out.info->info1.entries = NULL; break; case 2: - r->out.info.info2.count = r->out.returned_size; - r->out.info.info2.entries = NULL; + r->out.info->info2.count = *r->out.returned_size; + r->out.info->info2.entries = NULL; break; case 3: - r->out.info.info3.count = r->out.returned_size; - r->out.info.info3.entries = NULL; + r->out.info->info3.count = *r->out.returned_size; + r->out.info->info3.entries = NULL; break; case 4: - r->out.info.info4.count = r->out.returned_size; - r->out.info.info4.entries = NULL; + r->out.info->info4.count = *r->out.returned_size; + r->out.info->info4.entries = NULL; break; case 5: - r->out.info.info5.count = r->out.returned_size; - r->out.info.info5.entries = NULL; + r->out.info->info5.count = *r->out.returned_size; + r->out.info->info5.entries = NULL; break; } } else { - r->out.returned_size = MIN(count - r->in.start_idx, + *r->out.returned_size = MIN(count - r->in.start_idx, r->in.max_entries); switch(r->in.level) { case 1: - r->out.info.info1.count = r->out.returned_size; - r->out.info.info1.entries = + r->out.info->info1.count = *r->out.returned_size; + r->out.info->info1.entries = &(entriesGeneral[r->in.start_idx]); break; case 2: - r->out.info.info2.count = r->out.returned_size; - r->out.info.info2.entries = + r->out.info->info2.count = *r->out.returned_size; + r->out.info->info2.entries = &(entriesFull[r->in.start_idx]); break; case 3: - r->out.info.info3.count = r->out.returned_size; - r->out.info.info3.entries = + r->out.info->info3.count = *r->out.returned_size; + r->out.info->info3.entries = &(entriesFullGroup[r->in.start_idx]); break; case 4: - r->out.info.info4.count = r->out.returned_size; - r->out.info.info4.entries = + r->out.info->info4.count = *r->out.returned_size; + r->out.info->info4.entries = &(entriesAscii[r->in.start_idx]); break; case 5: - r->out.info.info5.count = r->out.returned_size; - r->out.info.info5.entries = + r->out.info->info5.count = *r->out.returned_size; + r->out.info->info5.entries = &(entriesAscii[r->in.start_idx]); break; } } - return (r->out.returned_size < (count - r->in.start_idx)) ? + return (*r->out.returned_size < (count - r->in.start_idx)) ? STATUS_MORE_ENTRIES : NT_STATUS_OK; } @@ -3910,18 +3940,18 @@ static NTSTATUS dcesrv_samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TA struct dcesrv_handle *h; struct samr_account_state *a_state; - ZERO_STRUCT(r->out.info); + ZERO_STRUCTP(r->out.info); DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER); a_state = h->data; - r->out.info.min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, - a_state->domain_state->domain_dn, "minPwdLength", - NULL); - r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, - a_state->account_dn, - "pwdProperties", NULL); + r->out.info->min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, + a_state->domain_state->domain_dn, "minPwdLength", + NULL); + r->out.info->password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, + a_state->account_dn, + "pwdProperties", NULL); return NT_STATUS_OK; } @@ -4008,11 +4038,10 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, ZERO_STRUCT(r1.out); r1.in.domain_handle = r->in.domain_handle; r1.in.level = r->in.level; - + r1.out.info = r->out.info; + status = dcesrv_samr_QueryDomainInfo(dce_call, mem_ctx, &r1); - r->out.info = r1.out.info; - return status; } @@ -4028,13 +4057,11 @@ static NTSTATUS dcesrv_samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, T struct samr_QueryUserInfo r1; NTSTATUS status; - ZERO_STRUCT(r1.out); r1.in.user_handle = r->in.user_handle; r1.in.level = r->in.level; + r1.out.info = r->out.info; status = dcesrv_samr_QueryUserInfo(dce_call, mem_ctx, &r1); - - r->out.info = r1.out.info; return status; } @@ -4054,14 +4081,12 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call q.in.start_idx = r->in.start_idx; q.in.max_entries = r->in.max_entries; q.in.buf_size = r->in.buf_size; - ZERO_STRUCT(q.out); + q.out.total_size = r->out.total_size; + q.out.returned_size = r->out.returned_size; + q.out.info = r->out.info; result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q); - r->out.total_size = q.out.total_size; - r->out.returned_size = q.out.returned_size; - r->out.info = q.out.info; - return result; } @@ -4090,14 +4115,12 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call q.in.start_idx = r->in.start_idx; q.in.max_entries = r->in.max_entries; q.in.buf_size = r->in.buf_size; - ZERO_STRUCT(q.out); + q.out.total_size = r->out.total_size; + q.out.returned_size = r->out.returned_size; + q.out.info = r->out.info; result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q); - r->out.total_size = q.out.total_size; - r->out.returned_size = q.out.returned_size; - r->out.info = q.out.info; - return result; } @@ -4138,7 +4161,7 @@ static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TAL const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL }; struct ldb_context *sam_ctx; - ZERO_STRUCT(r->out.info); + ZERO_STRUCTP(r->out.info); sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); if (sam_ctx == NULL) { @@ -4156,8 +4179,8 @@ static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_INTERNAL_DB_CORRUPTION; } - r->out.info.min_password_length = samdb_result_uint(msgs[0], "minPwdLength", 0); - r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1); + r->out.info->min_password_length = samdb_result_uint(msgs[0], "minPwdLength", 0); + r->out.info->password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1); talloc_free(msgs); @@ -4267,9 +4290,9 @@ static NTSTATUS dcesrv_samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_ status = dcesrv_samr_Connect(dce_call, mem_ctx, &c); - r->out.info->info1.client_version = SAMR_CONNECT_AFTER_W2K; - r->out.info->info1.unknown2 = 0; - r->out.level = r->in.level; + r->out.info_out->info1.client_version = SAMR_CONNECT_AFTER_W2K; + r->out.info_out->info1.unknown2 = 0; + *r->out.level_out = r->in.level_in; return status; } @@ -4289,8 +4312,8 @@ static NTSTATUS dcesrv_samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_ d_state = h->data; /* form the users SID */ - r->out.sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid); - if (!r->out.sid) { + *r->out.sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid); + if (!*r->out.sid) { return NT_STATUS_NO_MEMORY; } diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index 1eb6a4f37c..ff8215a673 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -352,7 +352,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, uint8_t new_nt_hash[16], new_lm_hash[16]; struct samr_Password nt_verifier, lm_verifier; - ZERO_STRUCT(r->out); + *r->out.dominfo = NULL; + *r->out.reject = NULL; if (r->in.nt_password == NULL || r->in.nt_verifier == NULL) { @@ -495,8 +496,8 @@ failed: talloc_free(sam_ctx); reject = talloc(mem_ctx, struct samr_ChangeReject); - r->out.dominfo = dominfo; - r->out.reject = reject; + *r->out.dominfo = dominfo; + *r->out.reject = reject; if (reject == NULL) { return status; @@ -518,6 +519,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TAL struct samr_ChangePasswordUser2 *r) { struct samr_ChangePasswordUser3 r2; + struct samr_DomInfo1 *dominfo = NULL; + struct samr_ChangeReject *reject = NULL; r2.in.server = r->in.server; r2.in.account = r->in.account; @@ -527,6 +530,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TAL r2.in.lm_password = r->in.lm_password; r2.in.lm_verifier = r->in.lm_verifier; r2.in.password3 = NULL; + r2.out.dominfo = &dominfo; + r2.out.reject = &reject; return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2); } diff --git a/source4/torture/libnet/libnet_domain.c b/source4/torture/libnet/libnet_domain.c index 7d5be368c2..3c28d1a019 100644 --- a/source4/torture/libnet/libnet_domain.c +++ b/source4/torture/libnet/libnet_domain.c @@ -35,12 +35,13 @@ static bool test_opendomain_samr(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, struct lsa_String *domname, - uint32_t *access_mask, struct dom_sid **sid) + uint32_t *access_mask, struct dom_sid **sid_p) { NTSTATUS status; struct policy_handle h, domain_handle; struct samr_Connect r1; struct samr_LookupDomain r2; + struct dom_sid2 *sid = NULL; struct samr_OpenDomain r3; printf("connecting\n"); @@ -59,6 +60,7 @@ static bool test_opendomain_samr(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r2.in.connect_handle = &h; r2.in.domain_name = domname; + r2.out.sid = &sid; printf("domain lookup on %s\n", domname->string); @@ -70,7 +72,7 @@ static bool test_opendomain_samr(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r3.in.connect_handle = &h; r3.in.access_mask = *access_mask; - r3.in.sid = *sid = r2.out.sid; + r3.in.sid = *sid_p = *r2.out.sid; r3.out.domain_handle = &domain_handle; printf("opening domain\n"); diff --git a/source4/torture/libnet/libnet_group.c b/source4/torture/libnet/libnet_group.c index 12b8167a86..9c9ecfd525 100644 --- a/source4/torture/libnet/libnet_group.c +++ b/source4/torture/libnet/libnet_group.c @@ -42,12 +42,15 @@ static bool test_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct lsa_String names[2]; uint32_t rid; struct policy_handle group_handle; + struct samr_Ids rids, types; names[0].string = groupname; r1.in.domain_handle = domain_handle; r1.in.num_names = 1; r1.in.names = names; + r1.out.rids = &rids; + r1.out.types = &types; printf("group account lookup '%s'\n", groupname); @@ -57,7 +60,7 @@ static bool test_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return false; } - rid = r1.out.rids.ids[0]; + rid = r1.out.rids->ids[0]; r2.in.domain_handle = domain_handle; r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; @@ -139,6 +142,7 @@ static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle h, domain_handle; struct samr_Connect r1; struct samr_LookupDomain r2; + struct dom_sid2 *sid = NULL; struct samr_OpenDomain r3; printf("connecting\n"); @@ -155,6 +159,7 @@ static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r2.in.connect_handle = &h; r2.in.domain_name = domname; + r2.out.sid = &sid; printf("domain lookup on %s\n", domname->string); @@ -166,7 +171,7 @@ static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r3.in.connect_handle = &h; r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r3.in.sid = r2.out.sid; + r3.in.sid = *r2.out.sid; r3.out.domain_handle = &domain_handle; printf("opening domain\n"); diff --git a/source4/torture/libnet/libnet_user.c b/source4/torture/libnet/libnet_user.c index 6d3e682976..18007dccad 100644 --- a/source4/torture/libnet/libnet_user.c +++ b/source4/torture/libnet/libnet_user.c @@ -40,12 +40,15 @@ static bool test_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct lsa_String names[2]; uint32_t rid; struct policy_handle user_handle; + struct samr_Ids rids, types; names[0].string = username; r1.in.domain_handle = domain_handle; r1.in.num_names = 1; r1.in.names = names; + r1.out.rids = &rids; + r1.out.types = &types; printf("user account lookup '%s'\n", username); @@ -55,7 +58,7 @@ static bool test_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return false; } - rid = r1.out.rids.ids[0]; + rid = r1.out.rids->ids[0]; r2.in.domain_handle = domain_handle; r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; @@ -92,6 +95,7 @@ static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle h, domain_handle; struct samr_Connect r1; struct samr_LookupDomain r2; + struct dom_sid2 *sid = NULL; struct samr_OpenDomain r3; printf("connecting\n"); @@ -108,6 +112,7 @@ static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r2.in.connect_handle = &h; r2.in.domain_name = domname; + r2.out.sid = &sid; printf("domain lookup on %s\n", domname->string); @@ -119,7 +124,7 @@ static bool test_opendomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r3.in.connect_handle = &h; r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r3.in.sid = r2.out.sid; + r3.in.sid = *r2.out.sid; r3.out.domain_handle = &domain_handle; printf("opening domain\n"); diff --git a/source4/torture/libnet/utils.c b/source4/torture/libnet/utils.c index 54c5f2c29c..942540c80e 100644 --- a/source4/torture/libnet/utils.c +++ b/source4/torture/libnet/utils.c @@ -32,12 +32,13 @@ bool test_opendomain(struct torture_context *tctx, struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle, struct lsa_String *domname, - struct dom_sid2 *sid) + struct dom_sid2 *sid_p) { NTSTATUS status; struct policy_handle h, domain_handle; struct samr_Connect r1; struct samr_LookupDomain r2; + struct dom_sid2 *sid = NULL; struct samr_OpenDomain r3; torture_comment(tctx, "connecting\n"); @@ -51,6 +52,7 @@ bool test_opendomain(struct torture_context *tctx, r2.in.connect_handle = &h; r2.in.domain_name = domname; + r2.out.sid = &sid; torture_comment(tctx, "domain lookup on %s\n", domname->string); @@ -59,7 +61,7 @@ bool test_opendomain(struct torture_context *tctx, r3.in.connect_handle = &h; r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r3.in.sid = r2.out.sid; + r3.in.sid = *r2.out.sid; r3.out.domain_handle = &domain_handle; torture_comment(tctx, "opening domain\n"); @@ -68,7 +70,7 @@ bool test_opendomain(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "OpenDomain failed"); *handle = domain_handle; - *sid = *r2.out.sid; + *sid_p = **r2.out.sid; return true; } @@ -84,19 +86,22 @@ bool test_user_cleanup(struct torture_context *tctx, struct dcerpc_pipe *p, struct lsa_String names[2]; uint32_t rid; struct policy_handle user_handle; + struct samr_Ids rids, types; names[0].string = name; r1.in.domain_handle = domain_handle; r1.in.num_names = 1; r1.in.names = names; + r1.out.rids = &rids; + r1.out.types = &types; torture_comment(tctx, "user account lookup '%s'\n", name); status = dcerpc_samr_LookupNames(p, mem_ctx, &r1); torture_assert_ntstatus_ok(tctx, status, "LookupNames failed"); - rid = r1.out.rids.ids[0]; + rid = r1.out.rids->ids[0]; r2.in.domain_handle = domain_handle; r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; @@ -174,12 +179,15 @@ bool test_group_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct lsa_String names[2]; uint32_t rid; struct policy_handle group_handle; + struct samr_Ids rids, types; names[0].string = name; r1.in.domain_handle = domain_handle; r1.in.num_names = 1; r1.in.names = names; + r1.out.rids = &rids; + r1.out.types = &types; printf("group account lookup '%s'\n", name); @@ -189,7 +197,7 @@ bool test_group_cleanup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return false; } - rid = r1.out.rids.ids[0]; + rid = r1.out.rids->ids[0]; r2.in.domain_handle = domain_handle; r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index c2b849127f..1148262dfe 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -355,7 +355,7 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, char **domain, struct dcerpc_pipe **result_pipe, struct policy_handle **result_handle, - struct dom_sid **sid) + struct dom_sid **sid_p) { struct dcerpc_pipe *samr_pipe; NTSTATUS status; @@ -365,7 +365,10 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, struct samr_Connect2 conn; struct samr_EnumDomains enumdom; uint32_t resume_handle = 0; + uint32_t num_entries = 0; + struct samr_SamArray *sam = NULL; struct samr_LookupDomain l; + struct dom_sid2 *sid = NULL; int dom_idx; struct lsa_String domain_name; struct lsa_String user_name; @@ -423,6 +426,8 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, enumdom.in.resume_handle = &resume_handle; enumdom.in.buf_size = (uint32_t)-1; enumdom.out.resume_handle = &resume_handle; + enumdom.out.num_entries = &num_entries; + enumdom.out.sam = &sam; status = dcerpc_samr_EnumDomains(samr_pipe, mem_ctx, &enumdom); if (!NT_STATUS_IS_OK(status)) { @@ -430,20 +435,21 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, goto fail; } - if (enumdom.out.num_entries != 2) { + if (*enumdom.out.num_entries != 2) { d_printf("samr_EnumDomains returned %d entries, expected 2\n", - enumdom.out.num_entries); + *enumdom.out.num_entries); status = NT_STATUS_UNSUCCESSFUL; goto fail; } - dom_idx = strequal(enumdom.out.sam->entries[0].name.string, + dom_idx = strequal(sam->entries[0].name.string, "builtin") ? 1:0; l.in.connect_handle = &conn_handle; - domain_name.string = enumdom.out.sam->entries[dom_idx].name.string; + domain_name.string = sam->entries[dom_idx].name.string; *domain = talloc_strdup(mem_ctx, domain_name.string); l.in.domain_name = &domain_name; + l.out.sid = &sid; status = dcerpc_samr_LookupDomain(samr_pipe, mem_ctx, &l); if (!NT_STATUS_IS_OK(status)) { @@ -453,7 +459,7 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, o.in.connect_handle = &conn_handle; o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - o.in.sid = l.out.sid; + o.in.sid = *l.out.sid; o.out.domain_handle = &domain_handle; status = dcerpc_samr_OpenDomain(samr_pipe, mem_ctx, &o); @@ -477,10 +483,13 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { struct samr_LookupNames ln; struct samr_OpenUser ou; + struct samr_Ids rids, types; ln.in.domain_handle = &domain_handle; ln.in.num_names = 1; ln.in.names = &user_name; + ln.out.rids = &rids; + ln.out.types = &types; status = dcerpc_samr_LookupNames(samr_pipe, mem_ctx, &ln); if (!NT_STATUS_IS_OK(status)) { @@ -491,7 +500,7 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, ou.in.domain_handle = &domain_handle; ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - user_rid = ou.in.rid = ln.out.rids.ids[0]; + user_rid = ou.in.rid = ln.out.rids->ids[0]; ou.out.user_handle = user_handle; status = dcerpc_samr_OpenUser(samr_pipe, mem_ctx, &ou); @@ -509,8 +518,8 @@ static NTSTATUS get_usr_handle(struct smbcli_state *cli, *result_pipe = samr_pipe; *result_handle = user_handle; - if (sid != NULL) { - *sid = dom_sid_add_rid(mem_ctx, l.out.sid, user_rid); + if (sid_p != NULL) { + *sid_p = dom_sid_add_rid(mem_ctx, *l.out.sid, user_rid); } return NT_STATUS_OK; @@ -555,6 +564,7 @@ static bool create_user(TALLOC_CTX *mem_ctx, struct smbcli_state *cli, struct samr_SetUserInfo sui; struct samr_QueryUserInfo qui; union samr_UserInfo u_info; + union samr_UserInfo *info; DATA_BLOB session_key; @@ -597,6 +607,7 @@ static bool create_user(TALLOC_CTX *mem_ctx, struct smbcli_state *cli, qui.in.user_handle = wks_handle; qui.in.level = 21; + qui.out.info = &info; status = dcerpc_samr_QueryUserInfo(samr_pipe, tmp_ctx, &qui); if (!NT_STATUS_IS_OK(status)) { @@ -604,14 +615,14 @@ static bool create_user(TALLOC_CTX *mem_ctx, struct smbcli_state *cli, goto done; } - qui.out.info->info21.allow_password_change = 0; - qui.out.info->info21.force_password_change = 0; - qui.out.info->info21.account_name.string = NULL; - qui.out.info->info21.rid = 0; - qui.out.info->info21.acct_expiry = 0; - qui.out.info->info21.fields_present = 0x81827fa; /* copy usrmgr.exe */ + info->info21.allow_password_change = 0; + info->info21.force_password_change = 0; + info->info21.account_name.string = NULL; + info->info21.rid = 0; + info->info21.acct_expiry = 0; + info->info21.fields_present = 0x81827fa; /* copy usrmgr.exe */ - u_info.info21 = qui.out.info->info21; + u_info.info21 = info->info21; sui.in.user_handle = wks_handle; sui.in.info = &u_info; sui.in.level = 21; @@ -721,9 +732,11 @@ static bool join3(struct smbcli_state *cli, { struct samr_QueryUserInfo q; + union samr_UserInfo *info; q.in.user_handle = wks_handle; q.in.level = 21; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(samr_pipe, mem_ctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -732,7 +745,7 @@ static bool join3(struct smbcli_state *cli, goto done; } - last_password_change = q.out.info->info21.last_password_change; + last_password_change = info->info21.last_password_change; } cli_credentials_set_domain(wks_creds, dom_name, CRED_SPECIFIED); @@ -830,9 +843,11 @@ static bool join3(struct smbcli_state *cli, { struct samr_QueryUserInfo q; + union samr_UserInfo *info; q.in.user_handle = wks_handle; q.in.level = 21; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(samr_pipe, mem_ctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -843,7 +858,7 @@ static bool join3(struct smbcli_state *cli, if (use_level25) { if (last_password_change - == q.out.info->info21.last_password_change) { + == info->info21.last_password_change) { d_printf("(%s) last_password_change unchanged " "during join, level25 must change " "it\n", __location__); @@ -852,7 +867,7 @@ static bool join3(struct smbcli_state *cli, } else { if (last_password_change - != q.out.info->info21.last_password_change) { + != info->info21.last_password_change) { d_printf("(%s) last_password_change changed " "during join, level24 doesn't " "change it\n", __location__); diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 23c288bfcc..87690178a7 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -59,6 +59,13 @@ static void init_lsa_String(struct lsa_String *string, const char *s) string->string = s; } +static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length) +{ + string->length = length; + string->size = length; + string->array = (uint16_t *)discard_const(s); +} + bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *handle) { @@ -131,18 +138,20 @@ static bool test_QuerySecurity(struct dcerpc_pipe *p, NTSTATUS status; struct samr_QuerySecurity r; struct samr_SetSecurity s; + struct sec_desc_buf *sdbuf = NULL; r.in.handle = handle; r.in.sec_info = 7; + r.out.sdbuf = &sdbuf; status = dcerpc_samr_QuerySecurity(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "QuerySecurity"); - torture_assert(tctx, r.out.sdbuf != NULL, "sdbuf is NULL"); + torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL"); s.in.handle = handle; s.in.sec_info = 7; - s.in.sdbuf = r.out.sdbuf; + s.in.sdbuf = sdbuf; if (torture_setting_bool(tctx, "samba4", false)) { torture_skip(tctx, "skipping SetSecurity test against Samba4\n"); @@ -168,6 +177,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx struct samr_QueryUserInfo q; struct samr_QueryUserInfo q0; union samr_UserInfo u; + union samr_UserInfo *info; bool ret = true; const char *test_account_name; @@ -184,7 +194,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx s2.in.info = &u; q.in.user_handle = handle; - q.out.info = &u; + q.out.info = &info; q0 = q; #define TESTCALL(call, r) \ @@ -204,6 +214,14 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx break; \ } +#define MEM_EQUAL(s1, s2, length, field) \ + if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \ + torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \ + #field, (const char *)s2, __location__); \ + ret = false; \ + break; \ + } + #define INT_EQUAL(i1, i2, field) \ if (i1 != i2) { \ torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \ @@ -218,7 +236,7 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx TESTCALL(QueryUserInfo, q) \ s.in.level = lvl1; \ s2.in.level = lvl1; \ - u = *q.out.info; \ + u = *info; \ if (lvl1 == 21) { \ ZERO_STRUCT(u.info21); \ u.info21.fields_present = fpval; \ @@ -228,21 +246,45 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx TESTCALL(SetUserInfo2, s2) \ init_lsa_String(&u.info ## lvl1.field1, ""); \ TESTCALL(QueryUserInfo, q); \ - u = *q.out.info; \ + u = *info; \ STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \ q.in.level = lvl2; \ TESTCALL(QueryUserInfo, q) \ - u = *q.out.info; \ + u = *info; \ STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \ } while (0) +#define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \ + torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \ + q.in.level = lvl1; \ + TESTCALL(QueryUserInfo, q) \ + s.in.level = lvl1; \ + s2.in.level = lvl1; \ + u = *info; \ + if (lvl1 == 21) { \ + ZERO_STRUCT(u.info21); \ + u.info21.fields_present = fpval; \ + } \ + init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \ + TESTCALL(SetUserInfo, s) \ + TESTCALL(SetUserInfo2, s2) \ + init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \ + TESTCALL(QueryUserInfo, q); \ + u = *info; \ + MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \ + q.in.level = lvl2; \ + TESTCALL(QueryUserInfo, q) \ + u = *info; \ + MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \ + } while (0) + #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \ torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \ q.in.level = lvl1; \ TESTCALL(QueryUserInfo, q) \ s.in.level = lvl1; \ s2.in.level = lvl1; \ - u = *q.out.info; \ + u = *info; \ if (lvl1 == 21) { \ uint8_t *bits = u.info21.logon_hours.bits; \ ZERO_STRUCT(u.info21); \ @@ -257,11 +299,11 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx TESTCALL(SetUserInfo2, s2) \ u.info ## lvl1.field1 = 0; \ TESTCALL(QueryUserInfo, q); \ - u = *q.out.info; \ + u = *info; \ INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \ q.in.level = lvl2; \ TESTCALL(QueryUserInfo, q) \ - u = *q.out.info; \ + u = *info; \ INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \ } while (0) @@ -359,10 +401,10 @@ static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14", SAMR_FIELD_WORKSTATIONS); - TEST_USERINFO_STRING(20, parameters, 21, parameters, "xx20-21 parameters", 0); - TEST_USERINFO_STRING(21, parameters, 21, parameters, "xx21-21 parameters", + TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0); + TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters", SAMR_FIELD_PARAMETERS); - TEST_USERINFO_STRING(21, parameters, 20, parameters, "xx21-20 parameters", + TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters", SAMR_FIELD_PARAMETERS); TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0); @@ -512,12 +554,14 @@ static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx DATA_BLOB session_key; char *newpass; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; int policy_min_pw_len = 0; pwp.in.user_handle = handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } newpass = samr_rand_pass(tctx, policy_min_pw_len); @@ -564,12 +608,14 @@ static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *t DATA_BLOB session_key; char *newpass; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; int policy_min_pw_len = 0; pwp.in.user_handle = handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } newpass = samr_rand_pass(tctx, policy_min_pw_len); @@ -643,12 +689,14 @@ static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tc char *newpass; struct MD5Context ctx; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; int policy_min_pw_len = 0; pwp.in.user_handle = handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } if (makeshort && policy_min_pw_len) { newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1); @@ -725,12 +773,14 @@ static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *t uint8_t confounder[16]; char *newpass; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; int policy_min_pw_len = 0; pwp.in.user_handle = handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } newpass = samr_rand_pass(tctx, policy_min_pw_len); @@ -796,6 +846,7 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct NTSTATUS status; struct samr_SetAliasInfo r; struct samr_QueryAliasInfo q; + union samr_AliasInfo *info; uint16_t levels[] = {2, 3}; int i; bool ret = true; @@ -826,6 +877,7 @@ static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tct q.in.alias_handle = handle; q.in.level = levels[i]; + q.out.info = &info; status = dcerpc_samr_QueryAliasInfo(p, tctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -842,11 +894,13 @@ static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context struct policy_handle *user_handle) { struct samr_GetGroupsForUser r; + struct samr_RidWithAttributeArray *rids = NULL; NTSTATUS status; torture_comment(tctx, "testing GetGroupsForUser\n"); r.in.user_handle = user_handle; + r.out.rids = &rids; status = dcerpc_samr_GetGroupsForUser(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser"); @@ -860,8 +914,11 @@ static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tct { NTSTATUS status; struct samr_GetDomPwInfo r; + struct samr_PwInfo info; r.in.domain_name = domain_name; + r.out.info = &info; + torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string); status = dcerpc_samr_GetDomPwInfo(p, tctx, &r); @@ -893,10 +950,12 @@ static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tc { NTSTATUS status; struct samr_GetUserPwInfo r; + struct samr_PwInfo info; torture_comment(tctx, "Testing GetUserPwInfo\n"); r.in.user_handle = handle; + r.out.info = &info; status = dcerpc_samr_GetUserPwInfo(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo"); @@ -911,15 +970,18 @@ static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *t NTSTATUS status; struct samr_LookupNames n; struct lsa_String sname[2]; + struct samr_Ids rids, types; init_lsa_String(&sname[0], name); n.in.domain_handle = domain_handle; n.in.num_names = 1; n.in.names = sname; + n.out.rids = &rids; + n.out.types = &types; status = dcerpc_samr_LookupNames(p, tctx, &n); if (NT_STATUS_IS_OK(status)) { - *rid = n.out.rids.ids[0]; + *rid = n.out.rids->ids[0]; } else { return status; } @@ -1071,6 +1133,7 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex char *newpass; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; int policy_min_pw_len = 0; status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle); @@ -1078,10 +1141,11 @@ static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_contex return false; } pwp.in.user_handle = &user_handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } newpass = samr_rand_pass(tctx, policy_min_pw_len); @@ -1346,12 +1410,14 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co uint8_t old_lm_hash[16], new_lm_hash[16]; struct samr_GetDomPwInfo dom_pw_info; + struct samr_PwInfo info; int policy_min_pw_len = 0; struct lsa_String domain_name; domain_name.string = ""; dom_pw_info.in.domain_name = &domain_name; + dom_pw_info.out.info = &info; torture_comment(tctx, "Testing OemChangePasswordUser2\n"); @@ -1362,7 +1428,7 @@ static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_co status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = dom_pw_info.out.info.min_password_length; + policy_min_pw_len = dom_pw_info.out.info->min_password_length; } newpass = samr_rand_pass(tctx, policy_min_pw_len); @@ -1515,11 +1581,13 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte uint8_t old_lm_hash[16], new_lm_hash[16]; struct samr_GetDomPwInfo dom_pw_info; + struct samr_PwInfo info; struct lsa_String domain_name; domain_name.string = ""; dom_pw_info.in.domain_name = &domain_name; + dom_pw_info.out.info = &info; torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name); @@ -1531,7 +1599,7 @@ static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_conte int policy_min_pw_len = 0; status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = dom_pw_info.out.info.min_password_length; + policy_min_pw_len = dom_pw_info.out.info->min_password_length; } newpass = samr_rand_pass(tctx, policy_min_pw_len); @@ -1594,6 +1662,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct uint8_t old_nt_hash[16], new_nt_hash[16]; uint8_t old_lm_hash[16], new_lm_hash[16]; NTTIME t; + struct samr_DomInfo1 *dominfo = NULL; + struct samr_ChangeReject *reject = NULL; torture_comment(tctx, "Testing ChangePasswordUser3\n"); @@ -1641,6 +1711,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct r.in.lm_password = &lm_pass; r.in.lm_verifier = &lm_verifier; r.in.password3 = NULL; + r.out.dominfo = &dominfo; + r.out.reject = &reject; status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r); if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) && @@ -1670,6 +1742,8 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct r.in.lm_password = &lm_pass; r.in.lm_verifier = &lm_verifier; r.in.password3 = NULL; + r.out.dominfo = &dominfo; + r.out.reject = &reject; status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r); if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) && @@ -1712,21 +1786,23 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct r.in.lm_password = &lm_pass; r.in.lm_verifier = &lm_verifier; r.in.password3 = NULL; + r.out.dominfo = &dominfo; + r.out.reject = &reject; unix_to_nt_time(&t, time(NULL)); status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r); if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) - && r.out.dominfo - && r.out.reject + && dominfo + && reject && handle_reject_reason - && (!null_nttime(last_password_change) || !r.out.dominfo->min_password_age)) { - if (r.out.dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) { + && (!null_nttime(last_password_change) || !dominfo->min_password_age)) { + if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) { - if (r.out.reject && (r.out.reject->reason != SAMR_REJECT_OTHER)) { + if (reject && (reject->reason != SAMR_REJECT_OTHER)) { printf("expected SAMR_REJECT_OTHER (%d), got %d\n", - SAMR_REJECT_OTHER, r.out.reject->reason); + SAMR_REJECT_OTHER, reject->reason); return false; } } @@ -1740,54 +1816,54 @@ bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tct Guenther */ - if ((r.out.dominfo->min_password_age > 0) && !null_nttime(last_password_change) && - (last_password_change + r.out.dominfo->min_password_age > t)) { + if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) && + (last_password_change + dominfo->min_password_age > t)) { - if (r.out.reject->reason != SAMR_REJECT_OTHER) { + if (reject->reason != SAMR_REJECT_OTHER) { printf("expected SAMR_REJECT_OTHER (%d), got %d\n", - SAMR_REJECT_OTHER, r.out.reject->reason); + SAMR_REJECT_OTHER, reject->reason); return false; } - } else if ((r.out.dominfo->min_password_length > 0) && - (strlen(newpass) < r.out.dominfo->min_password_length)) { + } else if ((dominfo->min_password_length > 0) && + (strlen(newpass) < dominfo->min_password_length)) { - if (r.out.reject->reason != SAMR_REJECT_TOO_SHORT) { + if (reject->reason != SAMR_REJECT_TOO_SHORT) { printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n", - SAMR_REJECT_TOO_SHORT, r.out.reject->reason); + SAMR_REJECT_TOO_SHORT, reject->reason); return false; } - } else if ((r.out.dominfo->password_history_length > 0) && + } else if ((dominfo->password_history_length > 0) && strequal(oldpass, newpass)) { - if (r.out.reject->reason != SAMR_REJECT_IN_HISTORY) { + if (reject->reason != SAMR_REJECT_IN_HISTORY) { printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n", - SAMR_REJECT_IN_HISTORY, r.out.reject->reason); + SAMR_REJECT_IN_HISTORY, reject->reason); return false; } - } else if (r.out.dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) { + } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) { - if (r.out.reject->reason != SAMR_REJECT_COMPLEXITY) { + if (reject->reason != SAMR_REJECT_COMPLEXITY) { printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n", - SAMR_REJECT_COMPLEXITY, r.out.reject->reason); + SAMR_REJECT_COMPLEXITY, reject->reason); return false; } } - if (r.out.reject->reason == SAMR_REJECT_TOO_SHORT) { + if (reject->reason == SAMR_REJECT_TOO_SHORT) { /* retry with adjusted size */ return test_ChangePasswordUser3(p, tctx, account_string, - r.out.dominfo->min_password_length, + dominfo->min_password_length, password, NULL, 0, false); } } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) { - if (r.out.reject && r.out.reject->reason != SAMR_REJECT_OTHER) { + if (reject && reject->reason != SAMR_REJECT_OTHER) { printf("expected SAMR_REJECT_OTHER (%d), got %d\n", - SAMR_REJECT_OTHER, r.out.reject->reason); + SAMR_REJECT_OTHER, reject->reason); return false; } /* Perhaps the server has a 'min password age' set? */ @@ -1823,6 +1899,8 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex char *oldpass; uint8_t old_nt_hash[16], new_nt_hash[16]; NTTIME t; + struct samr_DomInfo1 *dominfo = NULL; + struct samr_ChangeReject *reject = NULL; new_random_pass = samr_very_rand_pass(tctx, 128); @@ -1889,15 +1967,17 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex r.in.lm_password = NULL; r.in.lm_verifier = NULL; r.in.password3 = NULL; + r.out.dominfo = &dominfo; + r.out.reject = &reject; unix_to_nt_time(&t, time(NULL)); status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r); if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) { - if (r.out.reject && r.out.reject->reason != SAMR_REJECT_OTHER) { + if (reject && reject->reason != SAMR_REJECT_OTHER) { printf("expected SAMR_REJECT_OTHER (%d), got %d\n", - SAMR_REJECT_OTHER, r.out.reject->reason); + SAMR_REJECT_OTHER, reject->reason); return false; } /* Perhaps the server has a 'min password age' set? */ @@ -1925,15 +2005,17 @@ bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_contex r.in.lm_password = NULL; r.in.lm_verifier = NULL; r.in.password3 = NULL; + r.out.dominfo = &dominfo; + r.out.reject = &reject; unix_to_nt_time(&t, time(NULL)); status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r); if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) { - if (r.out.reject && r.out.reject->reason != SAMR_REJECT_OTHER) { + if (reject && reject->reason != SAMR_REJECT_OTHER) { printf("expected SAMR_REJECT_OTHER (%d), got %d\n", - SAMR_REJECT_OTHER, r.out.reject->reason); + SAMR_REJECT_OTHER, reject->reason); return false; } /* Perhaps the server has a 'min password age' set? */ @@ -2061,6 +2143,7 @@ static bool test_user_ops(struct dcerpc_pipe *p, { char *password = NULL; struct samr_QueryUserInfo q; + union samr_UserInfo *info; NTSTATUS status; bool ret = true; @@ -2176,6 +2259,7 @@ static bool test_user_ops(struct dcerpc_pipe *p, q.in.user_handle = user_handle; q.in.level = 5; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, tctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -2184,15 +2268,15 @@ static bool test_user_ops(struct dcerpc_pipe *p, ret = false; } else { uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED); - if ((q.out.info->info5.acct_flags) != expected_flags) { + if ((info->info5.acct_flags) != expected_flags) { printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n", - q.out.info->info5.acct_flags, + info->info5.acct_flags, expected_flags); ret = false; } - if (q.out.info->info5.rid != rid) { + if (info->info5.rid != rid) { printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n", - q.out.info->info5.rid, rid); + info->info5.rid, rid); } } @@ -2481,6 +2565,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, /* set samr_SetDomainInfo level 1 with min_length 5 */ { struct samr_QueryDomainInfo r; + union samr_DomainInfo *info = NULL; struct samr_SetDomainInfo s; uint16_t len_old, len; uint32_t pwd_prop_old; @@ -2491,6 +2576,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.domain_handle = domain_handle; r.in.level = 1; + r.out.info = &info; printf("testing samr_QueryDomainInfo level 1\n"); status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r); @@ -2500,7 +2586,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, s.in.domain_handle = domain_handle; s.in.level = 1; - s.in.info = r.out.info; + s.in.info = info; /* remember the old min length, so we can reset it */ len_old = s.in.info->info1.min_password_length; @@ -2540,13 +2626,17 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, NTSTATUS status; struct samr_OpenUser r; struct samr_QueryUserInfo q; + union samr_UserInfo *info; struct samr_LookupNames n; struct policy_handle user_handle; + struct samr_Ids rids, types; n.in.domain_handle = domain_handle; n.in.num_names = 1; n.in.names = talloc_array(mem_ctx, struct lsa_String, 1); n.in.names[0].string = acct_name; + n.out.rids = &rids; + n.out.types = &types; status = dcerpc_samr_LookupNames(p, mem_ctx, &n); if (!NT_STATUS_IS_OK(status)) { @@ -2556,17 +2646,18 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.domain_handle = domain_handle; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r.in.rid = n.out.rids.ids[0]; + r.in.rid = n.out.rids->ids[0]; r.out.user_handle = &user_handle; status = dcerpc_samr_OpenUser(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { - printf("OpenUser(%u) failed - %s\n", n.out.rids.ids[0], nt_errstr(status)); + printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status)); return false; } q.in.user_handle = &user_handle; q.in.level = 5; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -2577,7 +2668,7 @@ static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, printf("calling test_ChangePasswordUser3 with too early password change\n"); if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, - q.out.info->info5.last_password_change, true)) { + info->info5.last_password_change, true)) { ret = false; } } @@ -2607,6 +2698,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, NTSTATUS status; struct samr_CreateUser r; struct samr_QueryUserInfo q; + union samr_UserInfo *info; struct samr_DeleteUser d; uint32_t rid; @@ -2654,6 +2746,7 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, } else { q.in.user_handle = &user_handle; q.in.level = 16; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -2661,9 +2754,9 @@ static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx, q.in.level, nt_errstr(status)); ret = false; } else { - if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) { + if ((info->info16.acct_flags & acct_flags) != acct_flags) { printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n", - q.out.info->info16.acct_flags, + info->info16.acct_flags, acct_flags); ret = false; } @@ -2705,6 +2798,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx NTSTATUS status; struct samr_CreateUser2 r; struct samr_QueryUserInfo q; + union samr_UserInfo *info; struct samr_DeleteUser d; struct policy_handle user_handle; uint32_t rid; @@ -2783,6 +2877,7 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx if (NT_STATUS_IS_OK(status)) { q.in.user_handle = &user_handle; q.in.level = 5; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -2794,31 +2889,31 @@ static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx if (acct_flags == ACB_NORMAL) { expected_flags |= ACB_PW_EXPIRED; } - if ((q.out.info->info5.acct_flags) != expected_flags) { + if ((info->info5.acct_flags) != expected_flags) { printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n", - q.out.info->info5.acct_flags, + info->info5.acct_flags, expected_flags); ret = false; } switch (acct_flags) { case ACB_SVRTRUST: - if (q.out.info->info5.primary_gid != DOMAIN_RID_DCS) { + if (info->info5.primary_gid != DOMAIN_RID_DCS) { printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n", - DOMAIN_RID_DCS, q.out.info->info5.primary_gid); + DOMAIN_RID_DCS, info->info5.primary_gid); ret = false; } break; case ACB_WSTRUST: - if (q.out.info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) { + if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) { printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n", - DOMAIN_RID_DOMAIN_MEMBERS, q.out.info->info5.primary_gid); + DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid); ret = false; } break; case ACB_NORMAL: - if (q.out.info->info5.primary_gid != DOMAIN_RID_USERS) { + if (info->info5.primary_gid != DOMAIN_RID_USERS) { printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n", - DOMAIN_RID_USERS, q.out.info->info5.primary_gid); + DOMAIN_RID_USERS, info->info5.primary_gid); ret = false; } break; @@ -2852,6 +2947,7 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct samr_QueryAliasInfo r; + union samr_AliasInfo *info; uint16_t levels[] = {1, 2, 3}; int i; bool ret = true; @@ -2861,6 +2957,7 @@ static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.alias_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -2878,6 +2975,7 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct samr_QueryGroupInfo r; + union samr_GroupInfo *info; uint16_t levels[] = {1, 2, 3, 4, 5}; int i; bool ret = true; @@ -2887,6 +2985,7 @@ static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.group_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -2904,11 +3003,13 @@ static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct samr_QueryGroupMember r; + struct samr_RidTypeArray *rids = NULL; bool ret = true; printf("Testing QueryGroupMember\n"); r.in.group_handle = handle; + r.out.rids = &rids; status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -2925,6 +3026,7 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct samr_QueryGroupInfo r; + union samr_GroupInfo *info; struct samr_SetGroupInfo s; uint16_t levels[] = {1, 2, 3, 4}; uint16_t set_ok[] = {0, 1, 1, 1}; @@ -2936,6 +3038,7 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.group_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -2948,7 +3051,7 @@ static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, s.in.group_handle = handle; s.in.level = levels[i]; - s.in.info = r.out.info; + s.in.info = *r.out.info; #if 0 /* disabled this, as it changes the name only from the point of view of samr, @@ -2990,6 +3093,7 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct samr_QueryUserInfo r; + union samr_UserInfo *info; uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 20, 21}; int i; @@ -3000,6 +3104,7 @@ static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.user_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3017,6 +3122,7 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct samr_QueryUserInfo2 r; + union samr_UserInfo *info; uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 20, 21}; int i; @@ -3027,6 +3133,7 @@ static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.user_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3174,6 +3281,7 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx, NTSTATUS status; struct samr_OpenUser r; struct samr_QueryUserInfo q; + union samr_UserInfo *info; struct policy_handle user_handle; bool ret = true; @@ -3192,6 +3300,7 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx, q.in.user_handle = &user_handle; q.in.level = 16; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, tctx, &q); if (!NT_STATUS_IS_OK(status)) { @@ -3199,9 +3308,9 @@ static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx, nt_errstr(status)); ret = false; } else { - if ((acct_flag_mask & q.out.info->info16.acct_flags) == 0) { + if ((acct_flag_mask & info->info16.acct_flags) == 0) { printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n", - acct_flag_mask, q.out.info->info16.acct_flags, rid); + acct_flag_mask, info->info16.acct_flags, rid); ret = false; } } @@ -3223,6 +3332,11 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context * bool ret = true; struct samr_LookupNames n; struct samr_LookupRids lr ; + struct lsa_Strings names; + struct samr_Ids rids, types; + struct samr_SamArray *sam = NULL; + uint32_t num_entries = 0; + uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST, ACB_DISABLED, ACB_NORMAL | ACB_DISABLED, ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST, @@ -3236,6 +3350,8 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context * r.in.acct_flags = mask = masks[mask_idx]; r.in.max_size = (uint32_t)-1; r.out.resume_handle = &resume_handle; + r.out.num_entries = &num_entries; + r.out.sam = &sam; status = dcerpc_samr_EnumDomainUsers(p, tctx, &r); if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && @@ -3244,18 +3360,18 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context * return false; } - torture_assert(tctx, r.out.sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL"); + torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL"); - if (r.out.sam->count == 0) { + if (sam->count == 0) { continue; } - for (i=0;i<r.out.sam->count;i++) { + for (i=0;i<sam->count;i++) { if (mask) { - if (!check_mask(p, tctx, handle, r.out.sam->entries[i].idx, mask)) { + if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) { ret = false; } - } else if (!test_OpenUser(p, tctx, handle, r.out.sam->entries[i].idx)) { + } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) { ret = false; } } @@ -3263,10 +3379,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context * printf("Testing LookupNames\n"); n.in.domain_handle = handle; - n.in.num_names = r.out.sam->count; - n.in.names = talloc_array(tctx, struct lsa_String, r.out.sam->count); - for (i=0;i<r.out.sam->count;i++) { - n.in.names[i].string = r.out.sam->entries[i].name.string; + n.in.num_names = sam->count; + n.in.names = talloc_array(tctx, struct lsa_String, sam->count); + n.out.rids = &rids; + n.out.types = &types; + for (i=0;i<sam->count;i++) { + n.in.names[i].string = sam->entries[i].name.string; } status = dcerpc_samr_LookupNames(p, tctx, &n); if (!NT_STATUS_IS_OK(status)) { @@ -3277,10 +3395,12 @@ static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context * printf("Testing LookupRids\n"); lr.in.domain_handle = handle; - lr.in.num_rids = r.out.sam->count; - lr.in.rids = talloc_array(tctx, uint32_t, r.out.sam->count); - for (i=0;i<r.out.sam->count;i++) { - lr.in.rids[i] = r.out.sam->entries[i].idx; + lr.in.num_rids = sam->count; + lr.in.rids = talloc_array(tctx, uint32_t, sam->count); + lr.out.names = &names; + lr.out.types = &types; + for (i=0;i<sam->count;i++) { + lr.in.rids[i] = sam->entries[i].idx; } status = dcerpc_samr_LookupRids(p, tctx, &lr); torture_assert_ntstatus_ok(tctx, status, "LookupRids"); @@ -3337,6 +3457,8 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, NTSTATUS status; struct samr_EnumDomainGroups r; uint32_t resume_handle=0; + struct samr_SamArray *sam = NULL; + uint32_t num_entries = 0; int i; bool ret = true; @@ -3346,6 +3468,8 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.resume_handle = &resume_handle; r.in.max_size = (uint32_t)-1; r.out.resume_handle = &resume_handle; + r.out.num_entries = &num_entries; + r.out.sam = &sam; status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3353,12 +3477,12 @@ static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return false; } - if (!r.out.sam) { + if (!sam) { return false; } - for (i=0;i<r.out.sam->count;i++) { - if (!test_OpenGroup(p, mem_ctx, handle, r.out.sam->entries[i].idx)) { + for (i=0;i<sam->count;i++) { + if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) { ret = false; } } @@ -3372,6 +3496,8 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, NTSTATUS status; struct samr_EnumDomainAliases r; uint32_t resume_handle=0; + struct samr_SamArray *sam = NULL; + uint32_t num_entries = 0; int i; bool ret = true; @@ -3379,7 +3505,9 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.domain_handle = handle; r.in.resume_handle = &resume_handle; - r.in.acct_flags = (uint32_t)-1; + r.in.max_size = (uint32_t)-1; + r.out.sam = &sam; + r.out.num_entries = &num_entries; r.out.resume_handle = &resume_handle; status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r); @@ -3388,12 +3516,12 @@ static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return false; } - if (!r.out.sam) { + if (!sam) { return false; } - for (i=0;i<r.out.sam->count;i++) { - if (!test_OpenAlias(p, mem_ctx, handle, r.out.sam->entries[i].idx)) { + for (i=0;i<sam->count;i++) { + if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) { ret = false; } } @@ -3409,14 +3537,19 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *m bool ret = true; uint16_t levels[] = {1, 2, 3, 4, 5}; uint16_t ok_lvl[] = {1, 1, 1, 0, 0}; + struct lsa_String name; + uint32_t idx = 0; int i; for (i=0;i<ARRAY_SIZE(levels);i++) { printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]); + init_lsa_String(&name, TEST_ACCOUNT_NAME); + r.in.domain_handle = handle; r.in.level = levels[i]; - init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME); + r.in.name = &name; + r.out.idx = &idx; status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r); @@ -3428,7 +3561,7 @@ static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *m ret = false; } - init_lsa_String(&r.in.name, "zzzzzzzz"); + init_lsa_String(&name, "zzzzzzzz"); status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r); @@ -3450,14 +3583,19 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX * bool ret = true; uint16_t levels[] = {1, 2, 3, 4, 5}; uint16_t ok_lvl[] = {1, 1, 1, 0, 0}; + struct lsa_String name; + uint32_t idx = 0; int i; for (i=0;i<ARRAY_SIZE(levels);i++) { printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]); + init_lsa_String(&name, TEST_ACCOUNT_NAME); + r.in.domain_handle = handle; r.in.level = levels[i]; - init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME); + r.in.name = &name; + r.out.idx = &idx; status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r); if (ok_lvl[i] && @@ -3468,7 +3606,7 @@ static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX * ret = false; } - init_lsa_String(&r.in.name, "zzzzzzzz"); + init_lsa_String(&name, "zzzzzzzz"); status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r); if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) { @@ -3502,6 +3640,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct { struct samr_OpenUser r; struct samr_QueryUserInfo q; + union samr_UserInfo *info; struct policy_handle user_handle; int i, ret = true; NTSTATUS status; @@ -3510,16 +3649,16 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct for (i = 0; ; i++) { switch (querydisplayinfo->in.level) { case 1: - if (i >= querydisplayinfo->out.info.info1.count) { + if (i >= querydisplayinfo->out.info->info1.count) { return ret; } - r.in.rid = querydisplayinfo->out.info.info1.entries[i].rid; + r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid; break; case 2: - if (i >= querydisplayinfo->out.info.info2.count) { + if (i >= querydisplayinfo->out.info->info2.count) { return ret; } - r.in.rid = querydisplayinfo->out.info.info2.entries[i].rid; + r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid; break; case 3: /* Groups */ @@ -3543,6 +3682,7 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct q.in.user_handle = &user_handle; q.in.level = 21; + q.out.info = &info; status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q); if (!NT_STATUS_IS_OK(status)) { printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status)); @@ -3551,41 +3691,41 @@ static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct switch (querydisplayinfo->in.level) { case 1: - if (seen_testuser && strcmp(q.out.info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) { + if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) { *seen_testuser = true; } - STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].full_name, - q.out.info->info21.full_name, q.out.info->info21.account_name); - STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].account_name, - q.out.info->info21.account_name, q.out.info->info21.account_name); - STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].description, - q.out.info->info21.description, q.out.info->info21.account_name); - INT_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].rid, - q.out.info->info21.rid, q.out.info->info21.account_name); - INT_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].acct_flags, - q.out.info->info21.acct_flags, q.out.info->info21.account_name); + STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name, + info->info21.full_name, info->info21.account_name); + STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name, + info->info21.account_name, info->info21.account_name); + STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description, + info->info21.description, info->info21.account_name); + INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid, + info->info21.rid, info->info21.account_name); + INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags, + info->info21.acct_flags, info->info21.account_name); break; case 2: - STRING_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].account_name, - q.out.info->info21.account_name, q.out.info->info21.account_name); - STRING_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].description, - q.out.info->info21.description, q.out.info->info21.account_name); - INT_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].rid, - q.out.info->info21.rid, q.out.info->info21.account_name); - INT_EQUAL_QUERY((querydisplayinfo->out.info.info2.entries[i].acct_flags & ~ACB_NORMAL), - q.out.info->info21.acct_flags, q.out.info->info21.account_name); + STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name, + info->info21.account_name, info->info21.account_name); + STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description, + info->info21.description, info->info21.account_name); + INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid, + info->info21.rid, info->info21.account_name); + INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL), + info->info21.acct_flags, info->info21.account_name); - if (!(querydisplayinfo->out.info.info2.entries[i].acct_flags & ACB_NORMAL)) { + if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) { printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n", - q.out.info->info21.account_name.string); + info->info21.account_name.string); } - if (!(q.out.info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) { + if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) { printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n", - q.out.info->info21.account_name.string, - querydisplayinfo->out.info.info2.entries[i].acct_flags, - q.out.info->info21.acct_flags); + info->info21.account_name.string, + querydisplayinfo->out.info->info2.entries[i].acct_flags, + info->info21.acct_flags); return false; } @@ -3605,10 +3745,15 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, NTSTATUS status; struct samr_QueryDisplayInfo r; struct samr_QueryDomainInfo dom_info; + union samr_DomainInfo *info = NULL; bool ret = true; uint16_t levels[] = {1, 2, 3, 4, 5}; int i; bool seen_testuser = false; + uint32_t total_size; + uint32_t returned_size; + union samr_DispInfo disp_info; + for (i=0;i<ARRAY_SIZE(levels);i++) { printf("Testing QueryDisplayInfo level %u\n", levels[i]); @@ -3620,6 +3765,9 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.level = levels[i]; r.in.max_entries = 2; r.in.buf_size = (uint32_t)-1; + r.out.total_size = &total_size; + r.out.returned_size = &returned_size; + r.out.info = &disp_info; status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r); if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) { @@ -3632,27 +3780,29 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) { ret = false; } - r.in.start_idx += r.out.info.info1.count; + r.in.start_idx += r.out.info->info1.count; break; case 2: if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) { ret = false; } - r.in.start_idx += r.out.info.info2.count; + r.in.start_idx += r.out.info->info2.count; break; case 3: - r.in.start_idx += r.out.info.info3.count; + r.in.start_idx += r.out.info->info3.count; break; case 4: - r.in.start_idx += r.out.info.info4.count; + r.in.start_idx += r.out.info->info4.count; break; case 5: - r.in.start_idx += r.out.info.info5.count; + r.in.start_idx += r.out.info->info5.count; break; } } dom_info.in.domain_handle = handle; dom_info.in.level = 2; + dom_info.out.info = &info; + /* Check number of users returned is correct */ status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info); if (!NT_STATUS_IS_OK(status)) { @@ -3664,17 +3814,17 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, switch (r.in.level) { case 1: case 4: - if (dom_info.out.info->general.num_users < r.in.start_idx) { + if (info->general.num_users < r.in.start_idx) { printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n", - r.in.start_idx, dom_info.out.info->general.num_groups, - dom_info.out.info->general.domain_name.string); + r.in.start_idx, info->general.num_groups, + info->general.domain_name.string); ret = false; } if (!seen_testuser) { struct policy_handle user_handle; if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) { printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n", - dom_info.out.info->general.domain_name.string); + info->general.domain_name.string); ret = false; test_samr_handle_Close(p, mem_ctx, &user_handle); } @@ -3682,10 +3832,10 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, break; case 3: case 5: - if (dom_info.out.info->general.num_groups != r.in.start_idx) { + if (info->general.num_groups != r.in.start_idx) { printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n", - r.in.start_idx, dom_info.out.info->general.num_groups, - dom_info.out.info->general.domain_name.string); + r.in.start_idx, info->general.num_groups, + info->general.domain_name.string); ret = false; } @@ -3705,6 +3855,9 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, bool ret = true; uint16_t levels[] = {1, 2, 3, 4, 5}; int i; + uint32_t total_size; + uint32_t returned_size; + union samr_DispInfo info; for (i=0;i<ARRAY_SIZE(levels);i++) { printf("Testing QueryDisplayInfo2 level %u\n", levels[i]); @@ -3714,6 +3867,9 @@ static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, r.in.start_idx = 0; r.in.max_entries = 1000; r.in.buf_size = (uint32_t)-1; + r.out.total_size = &total_size; + r.out.returned_size = &returned_size; + r.out.info = &info; status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3734,6 +3890,9 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context bool ret = true; uint16_t levels[] = {1, 2, 3, 4, 5}; int i; + uint32_t total_size; + uint32_t returned_size; + union samr_DispInfo info; for (i=0;i<ARRAY_SIZE(levels);i++) { torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]); @@ -3743,6 +3902,9 @@ static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context r.in.start_idx = 0; r.in.max_entries = 1000; r.in.buf_size = (uint32_t)-1; + r.out.total_size = &total_size; + r.out.returned_size = &returned_size; + r.out.info = &info; status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3762,6 +3924,9 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me NTSTATUS status; struct samr_QueryDisplayInfo r; bool ret = true; + uint32_t total_size; + uint32_t returned_size; + union samr_DispInfo info; printf("Testing QueryDisplayInfo continuation\n"); @@ -3770,14 +3935,17 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me r.in.start_idx = 0; r.in.max_entries = 1; r.in.buf_size = (uint32_t)-1; + r.out.total_size = &total_size; + r.out.returned_size = &returned_size; + r.out.info = &info; do { status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r); - if (NT_STATUS_IS_OK(status) && r.out.returned_size != 0) { - if (r.out.info.info1.entries[0].idx != r.in.start_idx + 1) { + if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) { + if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) { printf("expected idx %d but got %d\n", r.in.start_idx + 1, - r.out.info.info1.entries[0].idx); + r.out.info->info1.entries[0].idx); break; } } @@ -3791,7 +3959,7 @@ static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *me r.in.start_idx++; } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) || NT_STATUS_IS_OK(status)) && - r.out.returned_size != 0); + *r.out.returned_size != 0); return ret; } @@ -3801,6 +3969,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context * { NTSTATUS status; struct samr_QueryDomainInfo r; + union samr_DomainInfo *info = NULL; struct samr_SetDomainInfo s; uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13}; uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0}; @@ -3827,6 +3996,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context * r.in.domain_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryDomainInfo(p, tctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3838,40 +4008,40 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context * switch (levels[i]) { case 2: - if (strcmp(r.out.info->general.oem_information.string, domain_comment) != 0) { + if (strcmp(info->general.oem_information.string, domain_comment) != 0) { printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n", - levels[i], r.out.info->general.oem_information.string, domain_comment); + levels[i], info->general.oem_information.string, domain_comment); ret = false; } - if (!r.out.info->general.primary.string) { + if (!info->general.primary.string) { printf("QueryDomainInfo level %u returned no PDC name\n", levels[i]); ret = false; - } else if (r.out.info->general.role == SAMR_ROLE_DOMAIN_PDC) { - if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->general.primary.string) != 0) { + } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) { + if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) { printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n", - levels[i], r.out.info->general.primary.string, dcerpc_server_name(p)); + levels[i], info->general.primary.string, dcerpc_server_name(p)); } } break; case 4: - if (strcmp(r.out.info->oem.oem_information.string, domain_comment) != 0) { + if (strcmp(info->oem.oem_information.string, domain_comment) != 0) { printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n", - levels[i], r.out.info->oem.oem_information.string, domain_comment); + levels[i], info->oem.oem_information.string, domain_comment); ret = false; } break; case 6: - if (!r.out.info->info6.primary.string) { + if (!info->info6.primary.string) { printf("QueryDomainInfo level %u returned no PDC name\n", levels[i]); ret = false; } break; case 11: - if (strcmp(r.out.info->general2.general.oem_information.string, domain_comment) != 0) { + if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) { printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n", - levels[i], r.out.info->general2.general.oem_information.string, domain_comment); + levels[i], info->general2.general.oem_information.string, domain_comment); ret = false; } break; @@ -3881,7 +4051,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context * s.in.domain_handle = handle; s.in.level = levels[i]; - s.in.info = r.out.info; + s.in.info = info; status = dcerpc_samr_SetDomainInfo(p, tctx, &s); if (set_ok[i]) { @@ -3918,6 +4088,7 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context { NTSTATUS status; struct samr_QueryDomainInfo2 r; + union samr_DomainInfo *info = NULL; uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13}; int i; bool ret = true; @@ -3927,6 +4098,7 @@ static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context r.in.domain_handle = handle; r.in.level = levels[i]; + r.out.info = &info; status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -3949,8 +4121,13 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx, struct samr_QueryDisplayInfo q2; NTSTATUS status; uint32_t resume_handle=0; + struct samr_SamArray *sam = NULL; + uint32_t num_entries = 0; int i; bool ret = true; + uint32_t total_size; + uint32_t returned_size; + union samr_DispInfo info; int num_names = 0; const char **names = NULL; @@ -3961,6 +4138,8 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx, q1.in.resume_handle = &resume_handle; q1.in.max_size = 5; q1.out.resume_handle = &resume_handle; + q1.out.num_entries = &num_entries; + q1.out.sam = &sam; status = STATUS_MORE_ENTRIES; while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { @@ -3970,22 +4149,25 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx, !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) break; - for (i=0; i<q1.out.num_entries; i++) { + for (i=0; i<*q1.out.num_entries; i++) { add_string_to_array(tctx, - q1.out.sam->entries[i].name.string, + sam->entries[i].name.string, &names, &num_names); } } torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups"); - torture_assert(tctx, q1.out.sam, "EnumDomainGroups failed to return q1.out.sam"); + torture_assert(tctx, sam, "EnumDomainGroups failed to return sam"); q2.in.domain_handle = handle; q2.in.level = 5; q2.in.start_idx = 0; q2.in.max_entries = 5; q2.in.buf_size = (uint32_t)-1; + q2.out.total_size = &total_size; + q2.out.returned_size = &returned_size; + q2.out.info = &info; status = STATUS_MORE_ENTRIES; while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { @@ -3995,9 +4177,9 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx, !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) break; - for (i=0; i<q2.out.info.info5.count; i++) { + for (i=0; i<q2.out.info->info5.count; i++) { int j; - const char *name = q2.out.info.info5.entries[i].account_name.string; + const char *name = q2.out.info->info5.entries[i].account_name.string; bool found = false; for (j=0; j<num_names; j++) { if (names[j] == NULL) @@ -4015,7 +4197,7 @@ static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx, ret = false; } } - q2.in.start_idx += q2.out.info.info5.count; + q2.in.start_idx += q2.out.info->info5.count; } if (!NT_STATUS_IS_OK(status)) { @@ -4076,7 +4258,7 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx, struct samr_RidToSid r; NTSTATUS status; bool ret = true; - struct dom_sid *calc_sid; + struct dom_sid *calc_sid, *out_sid; int rids[] = { 0, 42, 512, 10200 }; int i; @@ -4086,6 +4268,7 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx, calc_sid = dom_sid_dup(tctx, domain_sid); r.in.domain_handle = domain_handle; r.in.rid = rids[i]; + r.out.sid = &out_sid; status = dcerpc_samr_RidToSid(p, tctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -4094,9 +4277,9 @@ static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx, } else { calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]); - if (!dom_sid_equal(calc_sid, r.out.sid)) { + if (!dom_sid_equal(calc_sid, out_sid)) { printf("RidToSid for %d failed - got %s, expected %s\n", rids[i], - dom_sid_string(tctx, r.out.sid), + dom_sid_string(tctx, out_sid), dom_sid_string(tctx, calc_sid)); ret = false; } @@ -4112,10 +4295,12 @@ static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_con struct samr_GetBootKeyInformation r; NTSTATUS status; bool ret = true; + uint32_t unknown = 0; torture_comment(tctx, "Testing GetBootKeyInformation\n"); r.in.domain_handle = domain_handle; + r.out.unknown = &unknown; status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -4134,6 +4319,7 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t struct samr_AddGroupMember r; struct samr_DeleteGroupMember d; struct samr_QueryGroupMember q; + struct samr_RidTypeArray *rids = NULL; struct samr_SetMemberAttributesOfGroup s; uint32_t rid; @@ -4173,6 +4359,7 @@ static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *t } q.in.group_handle = group_handle; + q.out.rids = &rids; status = dcerpc_samr_QueryGroupMember(p, tctx, &q); torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember"); @@ -4388,6 +4575,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct { NTSTATUS status; struct samr_LookupDomain r; + struct dom_sid2 *sid = NULL; struct lsa_String n1; struct lsa_String n2; bool ret = true; @@ -4397,6 +4585,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct /* check for correct error codes */ r.in.connect_handle = handle; r.in.domain_name = &n2; + r.out.sid = &sid; n2.string = NULL; status = dcerpc_samr_LookupDomain(p, tctx, &r); @@ -4419,7 +4608,7 @@ static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tct ret = false; } - if (!test_OpenDomain(p, tctx, handle, r.out.sid, which_ops)) { + if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops)) { ret = false; } @@ -4433,6 +4622,8 @@ static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx NTSTATUS status; struct samr_EnumDomains r; uint32_t resume_handle = 0; + uint32_t num_entries = 0; + struct samr_SamArray *sam = NULL; int i; bool ret = true; @@ -4440,17 +4631,19 @@ static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx r.in.resume_handle = &resume_handle; r.in.buf_size = (uint32_t)-1; r.out.resume_handle = &resume_handle; + r.out.num_entries = &num_entries; + r.out.sam = &sam; status = dcerpc_samr_EnumDomains(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "EnumDomains"); - if (!r.out.sam) { + if (!*r.out.sam) { return false; } - for (i=0;i<r.out.sam->count;i++) { + for (i=0;i<sam->count;i++) { if (!test_LookupDomain(p, tctx, handle, - r.out.sam->entries[i].name.string, which_ops)) { + sam->entries[i].name.string, which_ops)) { ret = false; } } @@ -4473,6 +4666,7 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx, struct samr_Connect5 r5; union samr_ConnectInfo info; struct policy_handle h; + uint32_t level_out = 0; bool ret = true, got_handle = false; torture_comment(tctx, "testing samr_Connect\n"); @@ -4553,9 +4747,10 @@ static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx, r5.in.system_name = ""; r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - r5.in.level = 1; - r5.in.info = &info; - r5.out.info = &info; + r5.in.level_in = 1; + r5.out.level_out = &level_out; + r5.in.info_in = &info; + r5.out.info_out = &info; r5.out.connect_handle = &h; status = dcerpc_samr_Connect5(p, tctx, &r5); diff --git a/source4/torture/rpc/samr_accessmask.c b/source4/torture/rpc/samr_accessmask.c index bfff8c9267..9a8e442019 100644 --- a/source4/torture/rpc/samr_accessmask.c +++ b/source4/torture/rpc/samr_accessmask.c @@ -52,13 +52,15 @@ static NTSTATUS torture_samr_Connect5(struct torture_context *tctx, NTSTATUS status; struct samr_Connect5 r5; union samr_ConnectInfo info; + uint32_t level_out = 0; info.info1.client_version = 0; info.info1.unknown2 = 0; r5.in.system_name = ""; - r5.in.level = 1; - r5.in.info = &info; - r5.out.info = &info; + r5.in.level_in = 1; + r5.in.info_in = &info; + r5.out.info_out = &info; + r5.out.level_out = &level_out; r5.out.connect_handle = h; r5.in.access_mask = mask; @@ -147,6 +149,8 @@ static bool test_samr_accessmask_EnumDomains(struct torture_context *tctx, int i; uint32_t mask; uint32_t resume_handle = 0; + struct samr_SamArray *sam = NULL; + uint32_t num_entries = 0; printf("testing which bits in Connect5 accessmask allows us to EnumDomains\n"); mask = 1; @@ -170,6 +174,8 @@ static bool test_samr_accessmask_EnumDomains(struct torture_context *tctx, ed.in.resume_handle = &resume_handle; ed.in.buf_size = (uint32_t)-1; ed.out.resume_handle = &resume_handle; + ed.out.num_entries = &num_entries; + ed.out.sam = &sam; status = dcerpc_samr_EnumDomains(p, tctx, &ed); if (!NT_STATUS_IS_OK(status)) { @@ -195,6 +201,8 @@ static bool test_samr_accessmask_EnumDomains(struct torture_context *tctx, ed.in.resume_handle = &resume_handle; ed.in.buf_size = (uint32_t)-1; ed.out.resume_handle = &resume_handle; + ed.out.num_entries = &num_entries; + ed.out.sam = &sam; status = dcerpc_samr_EnumDomains(p, tctx, &ed); if(!NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) { @@ -236,7 +244,7 @@ static bool test_samr_connect_user_acl(struct torture_context *tctx, struct samr_SetSecurity ss; struct security_ace ace; struct security_descriptor *sd; - struct sec_desc_buf sdb; + struct sec_desc_buf sdb, *sdbuf = NULL; bool ret = true; int sd_size; struct dcerpc_pipe *test_p; @@ -255,6 +263,7 @@ static bool test_samr_connect_user_acl(struct torture_context *tctx, /* get the current ACL for the SAMR policy handle */ qs.in.handle = &ch; qs.in.sec_info = SECINFO_DACL; + qs.out.sdbuf = &sdbuf; status = dcerpc_samr_QuerySecurity(p, tctx, &qs); if (!NT_STATUS_IS_OK(status)) { printf("QuerySecurity failed - %s\n", nt_errstr(status)); @@ -262,13 +271,13 @@ static bool test_samr_connect_user_acl(struct torture_context *tctx, } /* how big is the security descriptor? */ - sd_size = qs.out.sdbuf->sd_size; + sd_size = sdbuf->sd_size; /* add an ACE to the security descriptor to deny the user the * 'connect to server' right */ - sd = qs.out.sdbuf->sd; + sd = sdbuf->sd; ace.type = SEC_ACE_TYPE_ACCESS_DENIED; ace.flags = 0; ace.access_mask = SAMR_ACCESS_CONNECT_TO_SERVER; @@ -314,7 +323,7 @@ static bool test_samr_connect_user_acl(struct torture_context *tctx, printf("QuerySecurity failed - %s\n", nt_errstr(status)); ret = false; } - if (sd_size != qs.out.sdbuf->sd_size) { + if (sd_size != sdbuf->sd_size) { printf("security descriptor changed\n"); ret = false; } @@ -387,6 +396,7 @@ static bool test_samr_accessmask_LookupDomain(struct torture_context *tctx, { NTSTATUS status; struct samr_LookupDomain ld; + struct dom_sid2 *sid = NULL; struct policy_handle ch; struct lsa_String dn; int i; @@ -412,6 +422,7 @@ static bool test_samr_accessmask_LookupDomain(struct torture_context *tctx, ld.in.connect_handle = &ch; ld.in.domain_name = &dn; + ld.out.sid = &sid; dn.string = lp_workgroup(tctx->lp_ctx); status = dcerpc_samr_LookupDomain(p, tctx, &ld); @@ -471,6 +482,7 @@ static bool test_samr_accessmask_OpenDomain(struct torture_context *tctx, { NTSTATUS status; struct samr_LookupDomain ld; + struct dom_sid2 *sid = NULL; struct samr_OpenDomain od; struct policy_handle ch; struct policy_handle dh; @@ -488,6 +500,7 @@ static bool test_samr_accessmask_OpenDomain(struct torture_context *tctx, ld.in.connect_handle = &ch; ld.in.domain_name = &dn; + ld.out.sid = &sid; dn.string = lp_workgroup(tctx->lp_ctx); status = dcerpc_samr_LookupDomain(p, tctx, &ld); if (!NT_STATUS_IS_OK(status)) { @@ -517,7 +530,7 @@ static bool test_samr_accessmask_OpenDomain(struct torture_context *tctx, od.in.connect_handle = &ch; od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - od.in.sid = ld.out.sid; + od.in.sid = *ld.out.sid; od.out.domain_handle = &dh; status = dcerpc_samr_OpenDomain(p, tctx, &od); diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c index 12ddc934c9..a3fc6f740f 100644 --- a/source4/torture/rpc/samsync.c +++ b/source4/torture/rpc/samsync.c @@ -151,17 +151,19 @@ struct samsync_trusted_domain { static struct policy_handle *samsync_open_domain(TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state, const char *domain, - struct dom_sid **sid) + struct dom_sid **sid_p) { struct lsa_String name; struct samr_OpenDomain o; struct samr_LookupDomain l; + struct dom_sid2 *sid = NULL; struct policy_handle *domain_handle = talloc(mem_ctx, struct policy_handle); NTSTATUS nt_status; name.string = domain; l.in.connect_handle = samsync_state->connect_handle; l.in.domain_name = &name; + l.out.sid = &sid; nt_status = dcerpc_samr_LookupDomain(samsync_state->p_samr, mem_ctx, &l); if (!NT_STATUS_IS_OK(nt_status)) { @@ -171,11 +173,11 @@ static struct policy_handle *samsync_open_domain(TALLOC_CTX *mem_ctx, o.in.connect_handle = samsync_state->connect_handle; o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - o.in.sid = l.out.sid; + o.in.sid = *l.out.sid; o.out.domain_handle = domain_handle; if (sid) { - *sid = l.out.sid; + *sid_p = *l.out.sid; } nt_status = dcerpc_samr_OpenDomain(samsync_state->p_samr, mem_ctx, &o); @@ -192,10 +194,12 @@ static struct sec_desc_buf *samsync_query_samr_sec_desc(TALLOC_CTX *mem_ctx, struct policy_handle *handle) { struct samr_QuerySecurity r; + struct sec_desc_buf *sdbuf = NULL; NTSTATUS status; r.in.handle = handle; r.in.sec_info = 0x7; + r.out.sdbuf = &sdbuf; status = dcerpc_samr_QuerySecurity(samsync_state->p_samr, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -203,7 +207,7 @@ static struct sec_desc_buf *samsync_query_samr_sec_desc(TALLOC_CTX *mem_ctx, return NULL; } - return r.out.sdbuf; + return sdbuf; } static struct sec_desc_buf *samsync_query_lsa_sec_desc(TALLOC_CTX *mem_ctx, @@ -260,6 +264,15 @@ static struct sec_desc_buf *samsync_query_lsa_sec_desc(TALLOC_CTX *mem_ctx, } \ } while (0) +#define TEST_BINARY_STRING_EQUAL(s1, s2) do {\ + if (!((!s1.array || s1.array[0]=='\0') && (!s2.array || s2.array[0]=='\0')) \ + && memcmp(s1.array, s2.array, s1.length * 2) != 0) {\ + printf("%s: string mismatch: " #s1 ":%s != " #s2 ": %s\n", \ + __location__, (const char *)s1.array, (const char *)s2.array);\ + ret = false;\ + } \ +} while (0) + #define TEST_SID_EQUAL(s1, s2) do {\ if (!dom_sid_equal(s1, s2)) {\ printf("%s: dom_sid mismatch: " #s1 ":%s != " #s2 ": %s\n", \ @@ -294,6 +307,7 @@ static bool samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *sam struct netr_DELTA_DOMAIN *domain = delta->delta_union.domain; struct dom_sid *dom_sid; struct samr_QueryDomainInfo q[14]; /* q[0] will be unused simple for clarity */ + union samr_DomainInfo *info[14]; uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13}; NTSTATUS nt_status; int i; @@ -341,8 +355,10 @@ static bool samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *sam (long long)samsync_state->seq_num[database_id]); for (i=0;i<ARRAY_SIZE(levels);i++) { + q[levels[i]].in.domain_handle = samsync_state->domain_handle[database_id]; q[levels[i]].in.level = levels[i]; + q[levels[i]].out.info = &info[levels[i]]; nt_status = dcerpc_samr_QueryDomainInfo(samsync_state->p_samr, mem_ctx, &q[levels[i]]); @@ -353,23 +369,23 @@ static bool samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *sam } } - TEST_STRING_EQUAL(q[5].out.info->info5.domain_name, domain->domain_name); + TEST_STRING_EQUAL(info[5]->info5.domain_name, domain->domain_name); - TEST_STRING_EQUAL(q[2].out.info->general.oem_information, domain->oem_information); - TEST_STRING_EQUAL(q[4].out.info->oem.oem_information, domain->oem_information); - TEST_TIME_EQUAL(q[2].out.info->general.force_logoff_time, domain->force_logoff_time); - TEST_TIME_EQUAL(q[3].out.info->info3.force_logoff_time, domain->force_logoff_time); + TEST_STRING_EQUAL(info[2]->general.oem_information, domain->oem_information); + TEST_STRING_EQUAL(info[4]->oem.oem_information, domain->oem_information); + TEST_TIME_EQUAL(info[2]->general.force_logoff_time, domain->force_logoff_time); + TEST_TIME_EQUAL(info[3]->info3.force_logoff_time, domain->force_logoff_time); - TEST_TIME_EQUAL(q[1].out.info->info1.min_password_length, domain->min_password_length); - TEST_TIME_EQUAL(q[1].out.info->info1.password_history_length, domain->password_history_length); - TEST_TIME_EQUAL(q[1].out.info->info1.max_password_age, domain->max_password_age); - TEST_TIME_EQUAL(q[1].out.info->info1.min_password_age, domain->min_password_age); + TEST_TIME_EQUAL(info[1]->info1.min_password_length, domain->min_password_length); + TEST_TIME_EQUAL(info[1]->info1.password_history_length, domain->password_history_length); + TEST_TIME_EQUAL(info[1]->info1.max_password_age, domain->max_password_age); + TEST_TIME_EQUAL(info[1]->info1.min_password_age, domain->min_password_age); - TEST_UINT64_EQUAL(q[8].out.info->info8.sequence_num, + TEST_UINT64_EQUAL(info[8]->info8.sequence_num, domain->sequence_num); - TEST_TIME_EQUAL(q[8].out.info->info8.domain_create_time, + TEST_TIME_EQUAL(info[8]->info8.domain_create_time, domain->domain_create_time); - TEST_TIME_EQUAL(q[13].out.info->info13.domain_create_time, + TEST_TIME_EQUAL(info[13]->info13.domain_create_time, domain->domain_create_time); TEST_SEC_DESC_EQUAL(domain->sdbuf, samr, samsync_state->domain_handle[database_id]); @@ -425,9 +441,12 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct struct samr_OpenUser r; struct samr_QueryUserInfo q; + union samr_UserInfo *info; struct policy_handle user_handle; struct samr_GetGroupsForUser getgroups; + struct samr_RidWithAttributeArray *rids; + if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { printf("SamSync needs domain information before the users\n"); return false; @@ -446,6 +465,7 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct q.in.user_handle = &user_handle; q.in.level = 21; + q.out.info = &info; TEST_SEC_DESC_EQUAL(user->sdbuf, samr, &user_handle); @@ -457,6 +477,7 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct } getgroups.in.user_handle = &user_handle; + getgroups.out.rids = &rids; nt_status = dcerpc_samr_GetGroupsForUser(samsync_state->p_samr, mem_ctx, &getgroups); if (!NT_STATUS_IS_OK(nt_status)) { @@ -480,67 +501,67 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct return false; } - TEST_STRING_EQUAL(q.out.info->info21.account_name, user->account_name); - TEST_STRING_EQUAL(q.out.info->info21.full_name, user->full_name); - TEST_INT_EQUAL(q.out.info->info21.rid, user->rid); - TEST_INT_EQUAL(q.out.info->info21.primary_gid, user->primary_gid); - TEST_STRING_EQUAL(q.out.info->info21.home_directory, user->home_directory); - TEST_STRING_EQUAL(q.out.info->info21.home_drive, user->home_drive); - TEST_STRING_EQUAL(q.out.info->info21.logon_script, user->logon_script); - TEST_STRING_EQUAL(q.out.info->info21.description, user->description); - TEST_STRING_EQUAL(q.out.info->info21.workstations, user->workstations); + TEST_STRING_EQUAL(info->info21.account_name, user->account_name); + TEST_STRING_EQUAL(info->info21.full_name, user->full_name); + TEST_INT_EQUAL(info->info21.rid, user->rid); + TEST_INT_EQUAL(info->info21.primary_gid, user->primary_gid); + TEST_STRING_EQUAL(info->info21.home_directory, user->home_directory); + TEST_STRING_EQUAL(info->info21.home_drive, user->home_drive); + TEST_STRING_EQUAL(info->info21.logon_script, user->logon_script); + TEST_STRING_EQUAL(info->info21.description, user->description); + TEST_STRING_EQUAL(info->info21.workstations, user->workstations); - TEST_TIME_EQUAL(q.out.info->info21.last_logon, user->last_logon); - TEST_TIME_EQUAL(q.out.info->info21.last_logoff, user->last_logoff); + TEST_TIME_EQUAL(info->info21.last_logon, user->last_logon); + TEST_TIME_EQUAL(info->info21.last_logoff, user->last_logoff); - TEST_INT_EQUAL(q.out.info->info21.logon_hours.units_per_week, + TEST_INT_EQUAL(info->info21.logon_hours.units_per_week, user->logon_hours.units_per_week); if (ret) { - if (memcmp(q.out.info->info21.logon_hours.bits, user->logon_hours.bits, - q.out.info->info21.logon_hours.units_per_week/8) != 0) { + if (memcmp(info->info21.logon_hours.bits, user->logon_hours.bits, + info->info21.logon_hours.units_per_week/8) != 0) { printf("Logon hours mismatch\n"); ret = false; } } - TEST_INT_EQUAL(q.out.info->info21.bad_password_count, + TEST_INT_EQUAL(info->info21.bad_password_count, user->bad_password_count); - TEST_INT_EQUAL(q.out.info->info21.logon_count, + TEST_INT_EQUAL(info->info21.logon_count, user->logon_count); - TEST_TIME_EQUAL(q.out.info->info21.last_password_change, + TEST_TIME_EQUAL(info->info21.last_password_change, user->last_password_change); - TEST_TIME_EQUAL(q.out.info->info21.acct_expiry, + TEST_TIME_EQUAL(info->info21.acct_expiry, user->acct_expiry); - TEST_INT_EQUAL((q.out.info->info21.acct_flags & ~ACB_PW_EXPIRED), user->acct_flags); + TEST_INT_EQUAL((info->info21.acct_flags & ~ACB_PW_EXPIRED), user->acct_flags); if (user->acct_flags & ACB_PWNOEXP) { - if (q.out.info->info21.acct_flags & ACB_PW_EXPIRED) { + if (info->info21.acct_flags & ACB_PW_EXPIRED) { printf("ACB flags mismatch: both expired and no expiry!\n"); ret = false; } - if (q.out.info->info21.force_password_change != (NTTIME)0x7FFFFFFFFFFFFFFFULL) { + if (info->info21.force_password_change != (NTTIME)0x7FFFFFFFFFFFFFFFULL) { printf("ACB flags mismatch: no password expiry, but force password change 0x%016llx (%lld) != 0x%016llx (%lld)\n", - (unsigned long long)q.out.info->info21.force_password_change, - (unsigned long long)q.out.info->info21.force_password_change, + (unsigned long long)info->info21.force_password_change, + (unsigned long long)info->info21.force_password_change, (unsigned long long)0x7FFFFFFFFFFFFFFFULL, (unsigned long long)0x7FFFFFFFFFFFFFFFULL ); ret = false; } } - TEST_INT_EQUAL(q.out.info->info21.nt_password_set, user->nt_password_present); - TEST_INT_EQUAL(q.out.info->info21.lm_password_set, user->lm_password_present); - TEST_INT_EQUAL(q.out.info->info21.password_expired, user->password_expired); + TEST_INT_EQUAL(info->info21.nt_password_set, user->nt_password_present); + TEST_INT_EQUAL(info->info21.lm_password_set, user->lm_password_present); + TEST_INT_EQUAL(info->info21.password_expired, user->password_expired); - TEST_STRING_EQUAL(q.out.info->info21.comment, user->comment); - TEST_STRING_EQUAL(q.out.info->info21.parameters, user->parameters); + TEST_STRING_EQUAL(info->info21.comment, user->comment); + TEST_BINARY_STRING_EQUAL(info->info21.parameters, user->parameters); - TEST_INT_EQUAL(q.out.info->info21.country_code, user->country_code); - TEST_INT_EQUAL(q.out.info->info21.code_page, user->code_page); + TEST_INT_EQUAL(info->info21.country_code, user->country_code); + TEST_INT_EQUAL(info->info21.code_page, user->code_page); - TEST_STRING_EQUAL(q.out.info->info21.profile_path, user->profile_path); + TEST_STRING_EQUAL(info->info21.profile_path, user->profile_path); if (user->lm_password_present) { sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0); @@ -619,7 +640,7 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) { - if (q.out.info->info21.acct_flags & ACB_PW_EXPIRED) { + if (info->info21.acct_flags & ACB_PW_EXPIRED) { return true; } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { @@ -654,7 +675,7 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct TEST_TIME_EQUAL(user->last_logon, info3->base.last_logon); TEST_TIME_EQUAL(user->acct_expiry, info3->base.acct_expiry); TEST_TIME_EQUAL(user->last_password_change, info3->base.last_password_change); - TEST_TIME_EQUAL(q.out.info->info21.force_password_change, info3->base.force_password_change); + TEST_TIME_EQUAL(info->info21.force_password_change, info3->base.force_password_change); /* Does the concept of a logoff time ever really * exist? (not in any sensible way, according to the @@ -667,28 +688,28 @@ static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ct TEST_TIME_EQUAL(user->last_logoff, info3->base.last_logoff); } - TEST_INT_EQUAL(getgroups.out.rids->count, info3->base.groups.count); - if (getgroups.out.rids->count == info3->base.groups.count) { + TEST_INT_EQUAL(rids->count, info3->base.groups.count); + if (rids->count == info3->base.groups.count) { int i, j; - int count = getgroups.out.rids->count; - bool *matched = talloc_zero_array(mem_ctx, bool, getgroups.out.rids->count); + int count = rids->count; + bool *matched = talloc_zero_array(mem_ctx, bool, rids->count); for (i = 0; i < count; i++) { for (j = 0; j < count; j++) { - if ((getgroups.out.rids->rids[i].rid == + if ((rids->rids[i].rid == info3->base.groups.rids[j].rid) - && (getgroups.out.rids->rids[i].attributes == + && (rids->rids[i].attributes == info3->base.groups.rids[j].attributes)) { matched[i] = true; } } } - for (i = 0; i < getgroups.out.rids->count; i++) { + for (i = 0; i < rids->count; i++) { if (matched[i] == false) { ret = false; printf("Could not find group RID %u found in getgroups in NETLOGON reply\n", - getgroups.out.rids->rids[i].rid); + rids->rids[i].rid); } } } @@ -711,6 +732,7 @@ static bool samsync_handle_alias(TALLOC_CTX *mem_ctx, struct samsync_state *sams struct samr_OpenAlias r; struct samr_QueryAliasInfo q; + union samr_AliasInfo *info; struct policy_handle alias_handle; if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { @@ -731,6 +753,7 @@ static bool samsync_handle_alias(TALLOC_CTX *mem_ctx, struct samsync_state *sams q.in.alias_handle = &alias_handle; q.in.level = 1; + q.out.info = &info; TEST_SEC_DESC_EQUAL(alias->sdbuf, samr, &alias_handle); @@ -745,8 +768,8 @@ static bool samsync_handle_alias(TALLOC_CTX *mem_ctx, struct samsync_state *sams return false; } - TEST_STRING_EQUAL(q.out.info->all.name, alias->alias_name); - TEST_STRING_EQUAL(q.out.info->all.description, alias->description); + TEST_STRING_EQUAL(info->all.name, alias->alias_name); + TEST_STRING_EQUAL(info->all.description, alias->description); return ret; } @@ -760,6 +783,7 @@ static bool samsync_handle_group(TALLOC_CTX *mem_ctx, struct samsync_state *sams struct samr_OpenGroup r; struct samr_QueryGroupInfo q; + union samr_GroupInfo *info; struct policy_handle group_handle; if (!samsync_state->domain_name || !samsync_state->domain_handle[database_id]) { @@ -780,6 +804,7 @@ static bool samsync_handle_group(TALLOC_CTX *mem_ctx, struct samsync_state *sams q.in.group_handle = &group_handle; q.in.level = 1; + q.out.info = &info; TEST_SEC_DESC_EQUAL(group->sdbuf, samr, &group_handle); @@ -794,9 +819,9 @@ static bool samsync_handle_group(TALLOC_CTX *mem_ctx, struct samsync_state *sams return false; } - TEST_STRING_EQUAL(q.out.info->all.name, group->group_name); - TEST_INT_EQUAL(q.out.info->all.attributes, group->attributes); - TEST_STRING_EQUAL(q.out.info->all.description, group->description); + TEST_STRING_EQUAL(info->all.name, group->group_name); + TEST_INT_EQUAL(info->all.attributes, group->attributes); + TEST_STRING_EQUAL(info->all.description, group->description); return ret; } diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index ca1655729b..451990a71b 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -128,6 +128,7 @@ static bool test_samr_ops(struct torture_context *tctx, { NTSTATUS status; struct samr_GetDomPwInfo r; + struct samr_PwInfo info; struct samr_Connect connect; struct samr_OpenDomain opendom; int i; @@ -137,6 +138,7 @@ static bool test_samr_ops(struct torture_context *tctx, name.string = lp_workgroup(tctx->lp_ctx); r.in.domain_name = &name; + r.out.info = &info; connect.in.system_name = 0; connect.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c index 3408a1924c..3b56d5b0ad 100644 --- a/source4/torture/rpc/testjoin.c +++ b/source4/torture/rpc/testjoin.c @@ -59,6 +59,7 @@ static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle user_handle; uint32_t rid; struct samr_LookupNames n; + struct samr_Ids rids, types; struct lsa_String sname; struct samr_OpenUser r; @@ -67,10 +68,12 @@ static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, n.in.domain_handle = handle; n.in.num_names = 1; n.in.names = &sname; + n.out.rids = &rids; + n.out.types = &types; status = dcerpc_samr_LookupNames(p, mem_ctx, &n); if (NT_STATUS_IS_OK(status)) { - rid = n.out.rids.ids[0]; + rid = n.out.rids->ids[0]; } else { return status; } @@ -113,7 +116,9 @@ struct test_join *torture_create_testuser(struct torture_context *torture, struct samr_CreateUser2 r; struct samr_OpenDomain o; struct samr_LookupDomain l; + struct dom_sid2 *sid = NULL; struct samr_GetUserPwInfo pwp; + struct samr_PwInfo info; struct samr_SetUserInfo s; union samr_UserInfo u; struct policy_handle handle; @@ -172,6 +177,7 @@ struct test_join *torture_create_testuser(struct torture_context *torture, name.string = domain; l.in.connect_handle = &handle; l.in.domain_name = &name; + l.out.sid = &sid; status = dcerpc_samr_LookupDomain(join->p, join, &l); if (!NT_STATUS_IS_OK(status)) { @@ -179,14 +185,14 @@ struct test_join *torture_create_testuser(struct torture_context *torture, goto failed; } - talloc_steal(join, l.out.sid); - join->dom_sid = l.out.sid; + talloc_steal(join, *l.out.sid); + join->dom_sid = *l.out.sid; join->dom_netbios_name = talloc_strdup(join, domain); if (!join->dom_netbios_name) goto failed; o.in.connect_handle = &handle; o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - o.in.sid = l.out.sid; + o.in.sid = *l.out.sid; o.out.domain_handle = &domain_handle; status = dcerpc_samr_OpenDomain(join->p, join, &o); @@ -224,10 +230,11 @@ again: join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid); pwp.in.user_handle = &join->user_handle; + pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo(join->p, join, &pwp); if (NT_STATUS_IS_OK(status)) { - policy_min_pw_len = pwp.out.info.min_password_length; + policy_min_pw_len = pwp.out.info->min_password_length; } random_pw = generate_random_str(join, MAX(8, policy_min_pw_len)); diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c index 48a2a4d882..a50a0fe473 100644 --- a/source4/winbind/wb_async_helpers.c +++ b/source4/winbind/wb_async_helpers.c @@ -325,6 +325,8 @@ struct samr_getuserdomgroups_state { int num_rids; uint32_t *rids; + struct samr_RidWithAttributeArray *rid_array; + struct policy_handle *user_handle; struct samr_OpenUser o; struct samr_GetGroupsForUser g; @@ -386,6 +388,7 @@ static void samr_usergroups_recv_open(struct rpc_request *req) if (!composite_is_ok(state->ctx)) return; state->g.in.user_handle = state->user_handle; + state->g.out.rids = &state->rid_array; req = dcerpc_samr_GetGroupsForUser_send(state->samr_pipe, state, &state->g); @@ -438,7 +441,7 @@ NTSTATUS wb_samr_userdomgroups_recv(struct composite_context *ctx, NTSTATUS status = composite_wait(ctx); if (!NT_STATUS_IS_OK(status)) goto done; - *num_rids = state->g.out.rids->count; + *num_rids = state->rid_array->count; *rids = talloc_array(mem_ctx, uint32_t, *num_rids); if (*rids == NULL) { status = NT_STATUS_NO_MEMORY; @@ -446,7 +449,7 @@ NTSTATUS wb_samr_userdomgroups_recv(struct composite_context *ctx, } for (i=0; i<*num_rids; i++) { - (*rids)[i] = state->g.out.rids->rids[i].rid; + (*rids)[i] = state->rid_array->rids[i].rid; } done: |