static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, struct dom_sid *sid, const char *name) { struct policy_handle pol; enum lsa_SidType *sid_types; NTSTATUS status, result; struct dom_sid *sids; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* maybe its a raw SID */ if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) { return NT_STATUS_OK; } status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(status) ) return status; status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, NULL, 1, &sids, &sid_types); if ( NT_STATUS_IS_OK(status) ) sid_copy( sid, &sids[0] ); dcerpc_lsa_Close(b, mem_ctx, &pol, &result); return status; }
static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, struct dom_sid *sid, fstring name) { struct policy_handle pol; enum lsa_SidType *sid_types = NULL; NTSTATUS status, result; char **domains = NULL, **names = NULL; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(status) ) return status; status = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types); if ( NT_STATUS_IS_OK(status) ) { if ( *domains[0] ) fstr_sprintf( name, "%s\\%s", domains[0], names[0] ); else fstrcpy( name, names[0] ); } dcerpc_lsa_Close(b, mem_ctx, &pol, &result); return status; }
/* convert a single name to a sid in a domain */ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *domain_name, const char *name, uint32_t flags, struct dom_sid *psid, enum lsa_SidType *ptype) { struct rpc_pipe_client *lsa_pipe; struct policy_handle lsa_policy; struct dom_sid sid; enum lsa_SidType type; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_name_to_sid\n")); ZERO_STRUCT(lsa_policy); tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; status = rpc_name_to_sid(tmp_ctx, lsa_pipe, &lsa_policy, domain_name, name, flags, &sid, &type); if (!NT_STATUS_IS_OK(status)) { goto done; } if (psid) { sid_copy(psid, &sid); } if (ptype) { *ptype = type; } done: if (b && is_valid_policy_hnd(&lsa_policy)) { dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); } TALLOC_FREE(tmp_ctx); return status; }
/* get a list of trusted domains - builtin domain */ static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct netr_DomainTrustList *ptrust_list) { struct rpc_pipe_client *lsa_pipe; struct policy_handle lsa_policy; struct netr_DomainTrust *trusts = NULL; uint32_t num_trusts = 0; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("samr: trusted domains\n")); ZERO_STRUCT(lsa_policy); if (ptrust_list) { ZERO_STRUCTP(ptrust_list); } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; status = rpc_trusted_domains(tmp_ctx, lsa_pipe, &lsa_policy, &num_trusts, &trusts); if (!NT_STATUS_IS_OK(status)) { goto done; } if (ptrust_list) { ptrust_list->count = num_trusts; ptrust_list->array = talloc_move(mem_ctx, &trusts); } done: if (b && is_valid_policy_hnd(&lsa_policy)) { dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); } TALLOC_FREE(tmp_ctx); return status; }
BOOL torture_domain_open_lsa(struct torture_context *torture) { NTSTATUS status; BOOL ret = True; struct libnet_context *ctx; struct libnet_DomainOpen r; struct lsa_Close close; struct dcerpc_binding *binding; struct policy_handle h; const char *bindstr; bindstr = torture_setting_string(torture, "binding", NULL); status = dcerpc_parse_binding(torture, bindstr, &binding); if (!NT_STATUS_IS_OK(status)) { d_printf("failed to parse binding string\n"); return False; } ctx = libnet_context_init(NULL); if (ctx == NULL) { d_printf("failed to create libnet context\n"); return False; } ctx->cred = cmdline_credentials; ZERO_STRUCT(r); r.in.type = DOMAIN_LSA; r.in.domain_name = binding->host; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; status = libnet_DomainOpen(ctx, torture, &r); if (!NT_STATUS_IS_OK(status)) { d_printf("failed to open domain on lsa service: %s\n", nt_errstr(status)); ret = False; goto done; } ZERO_STRUCT(close); close.in.handle = &ctx->lsa.handle; close.out.handle = &h; status = dcerpc_lsa_Close(ctx->lsa.pipe, ctx, &close); if (!NT_STATUS_IS_OK(status)) { d_printf("failed to close domain on lsa service: %s\n", nt_errstr(status)); ret = False; } done: talloc_free(ctx); return ret; }
BOOL torture_domain_open_lsa(struct torture_context *torture) { NTSTATUS status; BOOL ret = True; struct libnet_context *ctx; struct libnet_DomainOpen r; struct lsa_Close lsa_close; struct policy_handle h; const char *domain_name; /* we're accessing domain controller so the domain name should be passed (it's going to be resolved to dc name and address) instead of specific server name. */ domain_name = lp_workgroup(); ctx = libnet_context_init(NULL); if (ctx == NULL) { d_printf("failed to create libnet context\n"); return False; } ctx->cred = cmdline_credentials; ZERO_STRUCT(r); r.in.type = DOMAIN_LSA; r.in.domain_name = domain_name; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; status = libnet_DomainOpen(ctx, torture, &r); if (!NT_STATUS_IS_OK(status)) { d_printf("failed to open domain on lsa service: %s\n", nt_errstr(status)); ret = False; goto done; } ZERO_STRUCT(lsa_close); lsa_close.in.handle = &ctx->lsa.handle; lsa_close.out.handle = &h; status = dcerpc_lsa_Close(ctx->lsa.pipe, ctx, &lsa_close); if (!NT_STATUS_IS_OK(status)) { d_printf("failed to close domain on lsa service: %s\n", nt_errstr(status)); ret = False; } done: talloc_free(ctx); return ret; }
static NTSTATUS close_handle(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *bind_hnd, struct policy_handle *pol_hnd) { NTSTATUS status; NTSTATUS result; status = dcerpc_lsa_Close(bind_hnd, mem_ctx, pol_hnd, &result); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_lsa_Close failed with error [%s].\n", nt_errstr(status))); return status; } if (!NT_STATUS_IS_OK(result)) { DEBUG(0, ("lsa close failed with error [%s].\n", nt_errstr(result))); return result; } return NT_STATUS_OK; }
int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) { /* libsmb variables */ struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; enum netr_SchannelType sec_channel_type; struct rpc_pipe_client *pipe_hnd = NULL; struct dcerpc_binding_handle *b = NULL; /* rpc variables */ struct policy_handle lsa_pol, sam_pol, domain_pol, user_pol; struct dom_sid *domain_sid; uint32 user_rid; /* Password stuff */ char *clear_trust_password = NULL; struct samr_CryptPassword crypt_pwd; uchar md4_trust_password[16]; union samr_UserInfo set_info; /* Misc */ NTSTATUS status, result; int retval = 1; const char *domain = NULL; char *acct_name; struct lsa_String lsa_acct_name; uint32 acct_flags=0; uint32_t access_granted = 0; union lsa_PolicyInformation *info = NULL; struct samr_Ids user_rids; struct samr_Ids name_types; /* check what type of join */ if (argc >= 0) { sec_channel_type = get_sec_channel_type(argv[0]); } else { sec_channel_type = get_sec_channel_type(NULL); } switch (sec_channel_type) { case SEC_CHAN_WKSTA: acb_info = ACB_WSTRUST; break; case SEC_CHAN_BDC: acb_info = ACB_SVRTRUST; break; #if 0 case SEC_CHAN_DOMAIN: acb_info = ACB_DOMTRUST; break; #endif default: DEBUG(0,("secure channel type %d not yet supported\n", sec_channel_type)); break; } /* Make authenticated connection to remote machine */ status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli); if (!NT_STATUS_IS_OK(status)) { return 1; } if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) { DEBUG(0, ("Could not initialise talloc context\n")); goto done; } /* Fetch domain sid */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", nt_errstr(status) )); goto done; } b = pipe_hnd->binding_handle; CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol), "error opening lsa policy handle"); CHECK_DCERPC_ERR(dcerpc_lsa_QueryInfoPolicy(b, mem_ctx, &lsa_pol, LSA_POLICY_INFO_ACCOUNT_DOMAIN, &info, &result), "error querying info policy"); domain = info->account_domain.name.string; domain_sid = info->account_domain.sid; dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result); TALLOC_FREE(pipe_hnd); /* Done with this pipe */ /* Bail out if domain didn't get set. */ if (!domain) { DEBUG(0, ("Could not get domain name.\n")); goto done; } /* Create domain user */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", nt_errstr(status) )); goto done; } b = pipe_hnd->binding_handle; CHECK_DCERPC_ERR(dcerpc_samr_Connect2(b, mem_ctx, pipe_hnd->desthost, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, &sam_pol, &result), "could not connect to SAM database"); CHECK_DCERPC_ERR(dcerpc_samr_OpenDomain(b, mem_ctx, &sam_pol, SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 | SAMR_DOMAIN_ACCESS_CREATE_USER | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, domain_sid, &domain_pol, &result), "could not open domain"); /* Create domain user */ if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } strlower_m(acct_name); init_lsa_String(&lsa_acct_name, acct_name); acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE | SEC_STD_WRITE_DAC | SEC_STD_DELETE | SAMR_USER_ACCESS_SET_PASSWORD | SAMR_USER_ACCESS_GET_ATTRIBUTES | SAMR_USER_ACCESS_SET_ATTRIBUTES; DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); status = dcerpc_samr_CreateUser2(b, mem_ctx, &domain_pol, &lsa_acct_name, acb_info, acct_flags, &user_pol, &access_granted, &user_rid, &result); if (!NT_STATUS_IS_OK(status)) { goto done; } if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) { status = result; d_fprintf(stderr,_("Creation of workstation account failed\n")); /* If NT_STATUS_ACCESS_DENIED then we have a valid username/password combo but the user does not have administrator access. */ if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) d_fprintf(stderr, _("User specified does not have " "administrator privileges\n")); goto done; } /* We *must* do this.... don't ask... */ if (NT_STATUS_IS_OK(result)) { dcerpc_samr_Close(b, mem_ctx, &user_pol, &result); } CHECK_DCERPC_ERR_DEBUG(dcerpc_samr_LookupNames(b, mem_ctx, &domain_pol, 1, &lsa_acct_name, &user_rids, &name_types, &result), ("error looking up rid for user %s: %s/%s\n", acct_name, nt_errstr(status), nt_errstr(result))); if (user_rids.count != 1) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } if (name_types.count != 1) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } if (name_types.ids[0] != SID_NAME_USER) { DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0])); goto done; } user_rid = user_rids.ids[0]; /* Open handle on user */ CHECK_DCERPC_ERR_DEBUG( dcerpc_samr_OpenUser(b, mem_ctx, &domain_pol, SEC_FLAG_MAXIMUM_ALLOWED, user_rid, &user_pol, &result), ("could not re-open existing user %s: %s/%s\n", acct_name, nt_errstr(status), nt_errstr(result))); /* Create a random machine account password */ clear_trust_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); E_md4hash(clear_trust_password, md4_trust_password); /* Set password on machine account */ init_samr_CryptPassword(clear_trust_password, &cli->user_session_key, &crypt_pwd); set_info.info24.password = crypt_pwd; set_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON; CHECK_DCERPC_ERR(dcerpc_samr_SetUserInfo2(b, mem_ctx, &user_pol, 24, &set_info, &result), "error setting trust account password"); /* Why do we have to try to (re-)set the ACB to be the same as what we passed in the samr_create_dom_user() call? When a NT workstation is joined to a domain by an administrator the acb_info is set to 0x80. For a normal user with "Add workstations to the domain" rights the acb_info is 0x84. I'm not sure whether it is supposed to make a difference or not. NT seems to cope with either value so don't bomb out if the set userinfo2 level 0x10 fails. -tpot */ set_info.info16.acct_flags = acb_info; /* Ignoring the return value is necessary for joining a domain as a normal user with "Add workstation to domain" privilege. */ status = dcerpc_samr_SetUserInfo(b, mem_ctx, &user_pol, 16, &set_info, &result); dcerpc_samr_Close(b, mem_ctx, &user_pol, &result); TALLOC_FREE(pipe_hnd); /* Done with this pipe */ /* Now check the whole process from top-to-bottom */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", nt_errstr(status) )); goto done; } status = rpccli_netlogon_setup_creds(pipe_hnd, cli->desthost, /* server name */ domain, /* domain */ global_myname(), /* client name */ global_myname(), /* machine account name */ md4_trust_password, sec_channel_type, &neg_flags); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n", nt_errstr(status))); if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && (sec_channel_type == SEC_CHAN_BDC) ) { d_fprintf(stderr, _("Please make sure that no computer " "account\nnamed like this machine " "(%s) exists in the domain\n"), global_myname()); } goto done; } /* We can only check the schannel connection if the client is allowed to do this and the server supports it. If not, just assume success (after all the rpccli_netlogon_setup_creds() succeeded, and we'll do the same again (setup creds) in net_rpc_join_ok(). JRA. */ if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) { struct rpc_pipe_client *netlogon_schannel_pipe; status = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon.syntax_id, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc, &netlogon_schannel_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n", nt_errstr(status))); if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && (sec_channel_type == SEC_CHAN_BDC) ) { d_fprintf(stderr, _("Please make sure that no " "computer account\nnamed " "like this machine (%s) " "exists in the domain\n"), global_myname()); } goto done; } TALLOC_FREE(netlogon_schannel_pipe); } TALLOC_FREE(pipe_hnd); /* Now store the secret in the secrets database */ strupper_m(CONST_DISCARD(char *, domain)); if (!secrets_store_domain_sid(domain, domain_sid)) { DEBUG(0, ("error storing domain sid for %s\n", domain)); goto done; } if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) { DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain)); } /* double-check, connection from scratch */ status = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss); retval = NT_STATUS_IS_OK(status) ? 0 : -1; done: /* Display success or failure */ if (domain) { if (retval != 0) { fprintf(stderr,_("Unable to join domain %s.\n"),domain); } else { printf(_("Joined domain %s.\n"),domain); } } cli_shutdown(cli); TALLOC_FREE(clear_trust_password); return retval; }
static NTSTATUS net_scan_dc_noad(struct net_context *c, struct cli_state *cli, struct net_dc_info *dc_info) { TALLOC_CTX *mem_ctx = talloc_tos(); struct rpc_pipe_client *pipe_hnd = NULL; struct dcerpc_binding_handle *b; NTSTATUS status, result; struct policy_handle pol; union lsa_PolicyInformation *info; ZERO_STRUCTP(dc_info); ZERO_STRUCT(pol); status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { return status; } b = pipe_hnd->binding_handle; status = dcerpc_lsa_open_policy(b, mem_ctx, false, SEC_FLAG_MAXIMUM_ALLOWED, &pol, &result); if (!NT_STATUS_IS_OK(status)) { goto done; } if (!NT_STATUS_IS_OK(result)) { status = result; goto done; } status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx, &pol, LSA_POLICY_INFO_ACCOUNT_DOMAIN, &info, &result); if (!NT_STATUS_IS_OK(status)) { goto done; } if (!NT_STATUS_IS_OK(result)) { status = result; goto done; } dc_info->netbios_domain_name = talloc_strdup(mem_ctx, info->account_domain.name.string); if (dc_info->netbios_domain_name == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } done: if (is_valid_policy_hnd(&pol)) { dcerpc_lsa_Close(b, mem_ctx, &pol, &result); } TALLOC_FREE(pipe_hnd); return status; }
NTSTATUS net_rpc_lookup_name(struct net_context *c, TALLOC_CTX *mem_ctx, struct cli_state *cli, const char *name, const char **ret_domain, const char **ret_name, struct dom_sid *ret_sid, enum lsa_SidType *ret_type) { struct rpc_pipe_client *lsa_pipe = NULL; struct policy_handle pol; NTSTATUS status, result; const char **dom_names; struct dom_sid *sids; enum lsa_SidType *types; struct dcerpc_binding_handle *b; ZERO_STRUCT(pol); status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &lsa_pipe); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Could not initialise lsa pipe\n")); return status; } b = lsa_pipe->binding_handle; status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, "open_policy %s: %s\n", _("failed"), nt_errstr(status)); return status; } status = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1, &name, &dom_names, 1, &sids, &types); if (!NT_STATUS_IS_OK(status)) { /* This can happen easily, don't log an error */ goto done; } if (ret_domain != NULL) { *ret_domain = dom_names[0]; } if (ret_name != NULL) { *ret_name = talloc_strdup(mem_ctx, name); } if (ret_sid != NULL) { sid_copy(ret_sid, &sids[0]); } if (ret_type != NULL) { *ret_type = types[0]; } done: if (is_valid_policy_hnd(&pol)) { dcerpc_lsa_Close(b, mem_ctx, &pol, &result); } TALLOC_FREE(lsa_pipe); return status; }
static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid, uint32 *rids, size_t num_rids, char **pdomain_name, char ***pnames, enum lsa_SidType **ptypes) { struct rpc_pipe_client *lsa_pipe; struct policy_handle lsa_policy; enum lsa_SidType *types = NULL; char *domain_name = NULL; char **names = NULL; TALLOC_CTX *tmp_ctx; NTSTATUS status, result; struct dcerpc_binding_handle *b = NULL; DEBUG(3,("sam_rids_to_names for %s\n", domain->name)); ZERO_STRUCT(lsa_policy); /* Paranoia check */ if (!sid_check_is_builtin(domain_sid) && !sid_check_is_domain(domain_sid) && !sid_check_is_unix_users(domain_sid) && !sid_check_is_unix_groups(domain_sid) && !sid_check_is_in_wellknown_domain(domain_sid)) { DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to " "lookup SID %s\n", sid_string_dbg(domain_sid))); return NT_STATUS_NONE_MAPPED; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy); if (!NT_STATUS_IS_OK(status)) { goto done; } b = lsa_pipe->binding_handle; status = rpc_rids_to_names(tmp_ctx, lsa_pipe, &lsa_policy, domain, domain_sid, rids, num_rids, &domain_name, &names, &types); if (!NT_STATUS_IS_OK(status)) { goto done; } if (pdomain_name) { *pdomain_name = talloc_move(mem_ctx, &domain_name); } if (ptypes) { *ptypes = talloc_move(mem_ctx, &types); } if (pnames) { *pnames = talloc_move(mem_ctx, &names); } done: if (b && is_valid_policy_hnd(&lsa_policy)) { dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result); } TALLOC_FREE(tmp_ctx); return status; }
static bool test_handles_mixed_shared(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5, *p6; struct policy_handle handle; struct policy_handle handle2; struct samr_Connect r; struct lsa_Close lc; struct samr_Close sc; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-MIXED-SHARED\n"); if (lp_parm_bool(-1, "torture", "samba4", False)) { torture_comment(torture, "Mixed shared-policy-handle test against Samba4 - skipping\n"); return true; } torture_comment(torture, "connect samr pipe1\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); transport = p1->conn->transport.transport, assoc_group_id = p1->assoc_group_id; torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); torture_comment(torture, "connect lsa pipe2\n"); status = torture_rpc_connection_transport(mem_ctx, &p2, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &handle; torture_comment(torture, "samr_Connect to open a policy handle on samr p1\n"); status = dcerpc_samr_Connect(p1, mem_ctx, &r); torture_assert_ntstatus_ok(torture, status, "opening policy handle on p1"); lc.in.handle = &handle; lc.out.handle = &handle2; sc.in.handle = &handle; sc.out.handle = &handle2; torture_comment(torture, "use policy handle on lsa p2 - should fail\n"); status = dcerpc_lsa_Close(p2, mem_ctx, &lc); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing handle on lsa p2"); torture_assert_int_equal(torture, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing handle on lsa p2"); torture_comment(torture, "closing policy handle on samr p1\n"); status = dcerpc_samr_Close(p1, mem_ctx, &sc); torture_assert_ntstatus_ok(torture, status, "closing policy handle on p1"); talloc_free(p1); talloc_free(p2); msleep(10); torture_comment(torture, "connect samr pipe3 - should fail\n"); status = torture_rpc_connection_transport(mem_ctx, &p3, &dcerpc_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe3"); torture_comment(torture, "connect lsa pipe4 - should fail\n"); status = torture_rpc_connection_transport(mem_ctx, &p4, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe4"); torture_comment(torture, "connect samr pipe5 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(mem_ctx, &p5, &dcerpc_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe5"); torture_comment(torture, "connect lsa pipe6 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(mem_ctx, &p6, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe6"); talloc_free(mem_ctx); return true; }
static bool test_handles_lsa(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2; struct policy_handle handle; struct policy_handle handle2; struct lsa_ObjectAttribute attr; struct lsa_QosInfo qos; struct lsa_OpenPolicy r; struct lsa_Close c; uint16_t system_name = '\\'; TALLOC_CTX *mem_ctx = talloc_new(torture); torture_comment(torture, "RPC-HANDLE-LSARPC\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); status = torture_rpc_connection(mem_ctx, &p2, &dcerpc_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); qos.len = 0; qos.impersonation_level = 2; qos.context_mode = 1; qos.effective_only = 0; attr.len = 0; attr.root_dir = NULL; attr.object_name = NULL; attr.attributes = 0; attr.sec_desc = NULL; attr.sec_qos = &qos; r.in.system_name = &system_name; r.in.attr = &attr; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { torture_comment(torture, "lsa_OpenPolicy not supported - skipping\n"); talloc_free(mem_ctx); return true; } c.in.handle = &handle; c.out.handle = &handle2; status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2"); torture_assert_int_equal(torture, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2"); status = dcerpc_lsa_Close(p1, mem_ctx, &c); torture_assert_ntstatus_ok(torture, status, "closing policy handle on p1"); status = dcerpc_lsa_Close(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); talloc_free(mem_ctx); return true; }
static bool test_handles_lsa_shared(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5; struct policy_handle handle; struct policy_handle handle2; struct lsa_ObjectAttribute attr; struct lsa_QosInfo qos; struct lsa_OpenPolicy r; struct lsa_Close c; struct lsa_QuerySecurity qsec; uint16_t system_name = '\\'; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-LSARPC-SHARED\n"); if (lp_parm_bool(-1, "torture", "samba4", False)) { torture_comment(torture, "LSA shared-policy-handle test against Samba4 - skipping\n"); return true; } torture_comment(torture, "connect lsa pipe1\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); transport = p1->conn->transport.transport, assoc_group_id = p1->assoc_group_id; torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); torture_comment(torture, "connect lsa pipe2\n"); status = torture_rpc_connection_transport(mem_ctx, &p2, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); qos.len = 0; qos.impersonation_level = 2; qos.context_mode = 1; qos.effective_only = 0; attr.len = 0; attr.root_dir = NULL; attr.object_name = NULL; attr.attributes = 0; attr.sec_desc = NULL; attr.sec_qos = &qos; r.in.system_name = &system_name; r.in.attr = &attr; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; torture_comment(torture, "open lsa policy handle\n"); status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { torture_comment(torture, "lsa_OpenPolicy not supported - skipping\n"); talloc_free(mem_ctx); return true; } /* * connect p3 after the policy handle is opened */ torture_comment(torture, "connect lsa pipe3 after the policy handle is opened\n"); status = torture_rpc_connection_transport(mem_ctx, &p3, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe3"); qsec.in.handle = &handle; qsec.in.sec_info = 0; c.in.handle = &handle; c.out.handle = &handle2; /* * use policy handle on all 3 connections */ torture_comment(torture, "use the policy handle on p1,p2,p3\n"); status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p1"); status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p2"); status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p3"); /* * close policy handle on connection 2 and the others get a fault */ torture_comment(torture, "close the policy handle on p2 others get a fault\n"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "closing policy handle on p2"); status = dcerpc_lsa_Close(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); status = dcerpc_lsa_Close(p3, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p3"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p3"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2 again"); /* * open a new policy handle on p3 */ torture_comment(torture, "open a new policy handle on p3\n"); status = dcerpc_lsa_OpenPolicy(p3, mem_ctx, &r); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "open policy handle on p3"); /* * use policy handle on all 3 connections */ torture_comment(torture, "use the policy handle on p1,p2,p3\n"); status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p1"); status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p2"); status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p3"); /* * close policy handle on connection 2 and the others get a fault */ torture_comment(torture, "close the policy handle on p2 others get a fault\n"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "closing policy handle on p2"); status = dcerpc_lsa_Close(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); status = dcerpc_lsa_Close(p3, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p3"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p3"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2 again"); /* * open a new policy handle */ torture_comment(torture, "open a new policy handle on p1 and use it\n"); status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "open 2nd policy handle on p1"); status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "QuerySecurity handle on p1"); /* close first connection */ torture_comment(torture, "disconnect p1\n"); talloc_free(p1); msleep(5); /* * and it's still available on p2,p3 */ torture_comment(torture, "use policy handle on p2,p3\n"); status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "QuerySecurity handle on p2 after p1 was disconnected"); status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "QuerySecurity handle on p3 after p1 was disconnected"); /* * now open p4 * and use the handle on it */ torture_comment(torture, "connect lsa pipe4 and use policy handle\n"); status = torture_rpc_connection_transport(mem_ctx, &p4, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe4"); status = dcerpc_lsa_QuerySecurity(p4, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "using policy handle on p4"); /* * now close p2,p3,p4 * without closing the policy handle */ torture_comment(torture, "disconnect p2,p3,p4\n"); talloc_free(p2); talloc_free(p3); talloc_free(p4); msleep(10); /* * now open p5 */ torture_comment(torture, "connect lsa pipe5 - should fail\n"); status = torture_rpc_connection_transport(mem_ctx, &p5, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe5"); talloc_free(mem_ctx); return true; }
static NTSTATUS rpc_rights_revoke_internal(struct net_context *c, const struct dom_sid *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv ) { struct policy_handle dom_pol; NTSTATUS status, result; struct lsa_RightSet rights; struct dom_sid sid; int i; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; if (argc < 2 ) { d_printf("%s\n%s", _("Usage:"), _(" net rpc rights revoke <name|SID> <rights...>\n")); return NT_STATUS_OK; } status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]); if (!NT_STATUS_IS_OK(status)) return status; status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &dom_pol); if (!NT_STATUS_IS_OK(status)) return status; rights.count = argc-1; rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count); if (!rights.names) { return NT_STATUS_NO_MEMORY; } for (i=0; i<argc-1; i++) { init_lsa_StringLarge(&rights.names[i], argv[i+1]); } status = dcerpc_lsa_RemoveAccountRights(b, mem_ctx, &dom_pol, &sid, false, &rights, &result); if (!NT_STATUS_IS_OK(status)) goto done; if (!NT_STATUS_IS_OK(result)) { status = result; goto done; } d_printf(_("Successfully revoked rights.\n")); done: if ( !NT_STATUS_IS_OK(status) ) { d_fprintf(stderr,_("Failed to revoke privileges for %s (%s)\n"), argv[0], nt_errstr(status)); } dcerpc_lsa_Close(b, mem_ctx, &dom_pol, &result); return status; }
static NTSTATUS rpc_rights_list_internal(struct net_context *c, const struct dom_sid *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv ) { struct policy_handle pol; NTSTATUS status, result; struct dom_sid sid; fstring privname; struct lsa_String lsa_name; struct lsa_StringLarge *description = NULL; uint16_t lang_id = 0; uint16_t lang_id_sys = 0; uint16_t lang_id_desc; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(status) ) return status; /* backwards compatibility; just list available privileges if no arguement */ if (argc == 0) { status = enum_privileges(pipe_hnd, mem_ctx, &pol ); goto done; } if (strequal(argv[0], "privileges")) { int i = 1; if (argv[1] == NULL) { status = enum_privileges(pipe_hnd, mem_ctx, &pol ); goto done; } while ( argv[i] != NULL ) { fstrcpy(privname, argv[i]); init_lsa_String(&lsa_name, argv[i]); i++; /* verify that this is a valid privilege for error reporting */ status = dcerpc_lsa_LookupPrivDisplayName(b, mem_ctx, &pol, &lsa_name, lang_id, lang_id_sys, &description, &lang_id_desc, &result); if (!NT_STATUS_IS_OK(status)) { continue; } status = result; if ( !NT_STATUS_IS_OK(result) ) { if ( NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_PRIVILEGE)) d_fprintf(stderr, _("No such privilege " "exists: %s.\n"), privname); else d_fprintf(stderr, _("Error resolving " "privilege display name " "[%s].\n"), nt_errstr(result)); continue; } status = enum_accounts_for_privilege(pipe_hnd, mem_ctx, &pol, privname); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Error enumerating " "accounts for privilege %s [%s].\n"), privname, nt_errstr(status)); continue; } } goto done; } /* special case to enumerate all privileged SIDs with associated rights */ if (strequal( argv[0], "accounts")) { int i = 1; if (argv[1] == NULL) { status = enum_privileges_for_accounts(pipe_hnd, mem_ctx, &pol); goto done; } while (argv[i] != NULL) { status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[i]); if (!NT_STATUS_IS_OK(status)) { goto done; } status = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid); if (!NT_STATUS_IS_OK(status)) { goto done; } i++; } goto done; } /* backward comaptibility: if no keyword provided, treat the key as an account name */ if (argc > 1) { d_printf("%s net rpc rights list [[accounts|privileges] " "[name|SID]]\n", _("Usage:")); status = NT_STATUS_OK; goto done; } status = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]); if (!NT_STATUS_IS_OK(status)) { goto done; } status = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid ); done: dcerpc_lsa_Close(b, mem_ctx, &pol, &result); return status; }