/* reply to a GETDC request */ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, struct nbtd_interface *iface, struct nbt_dgram_packet *packet, const struct socket_address *src, struct nbt_netlogon_packet *netlogon) { struct nbt_name *name = &packet->data.msg.dest_name; struct nbtd_interface *reply_iface = nbtd_find_reply_iface(iface, src->addr, false); struct nbt_netlogon_response_from_pdc *pdc; struct ldb_context *samctx; struct nbt_netlogon_response netlogon_response; /* only answer getdc requests on the PDC or LOGON names */ if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) { return; } samctx = iface->nbtsrv->sam_ctx; if (lpcfg_server_role(iface->nbtsrv->task->lp_ctx) != ROLE_DOMAIN_CONTROLLER || !samdb_is_pdc(samctx)) { DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n")); return; } if (strcasecmp_m(name->name, lpcfg_workgroup(iface->nbtsrv->task->lp_ctx)) != 0) { DEBUG(5,("GetDC requested for a domian %s that we don't host\n", name->name)); return; } /* setup a GETDC reply */ ZERO_STRUCT(netlogon_response); netlogon_response.response_type = NETLOGON_GET_PDC; pdc = &netlogon_response.data.get_pdc; pdc->command = NETLOGON_RESPONSE_FROM_PDC; pdc->pdc_name = lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx); pdc->unicode_pdc_name = pdc->pdc_name; pdc->domain_name = lpcfg_workgroup(iface->nbtsrv->task->lp_ctx); pdc->nt_version = 1; pdc->lmnt_token = 0xFFFF; pdc->lm20_token = 0xFFFF; dgram_mailslot_netlogon_reply(reply_iface->dgmsock, packet, lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx), netlogon->req.pdc.mailslot_name, &netlogon_response); }
static bool test_set_option(struct torture_context *tctx) { struct loadparm_context *lp_ctx = loadparm_init(tctx); torture_assert(tctx, lpcfg_set_option(lp_ctx, "workgroup=werkgroep"), "lpcfg_set_option failed"); torture_assert_str_equal(tctx, "WERKGROEP", lpcfg_workgroup(lp_ctx), "workgroup"); return true; }
static bool test_NetrGetJoinableOus2(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct wkssvc_NetrGetJoinableOus2 r; uint32_t num_ous = 0; const char **ous = NULL; struct dcerpc_binding_handle *b = p->binding_handle; r.in.server_name = dcerpc_server_name(p); r.in.domain_name = lpcfg_workgroup(tctx->lp_ctx); r.in.Account = NULL; r.in.EncryptedPassword = NULL; r.in.num_ous = r.out.num_ous = &num_ous; r.out.ous = &ous; torture_comment(tctx, "Testing NetrGetJoinableOus2\n"); status = dcerpc_wkssvc_NetrGetJoinableOus2_r(b, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "NetrGetJoinableOus2 failed"); torture_assert_werr_equal(tctx, r.out.result, WERR_RPC_E_REMOTE_DISABLED, "NetrGetJoinableOus2 failed"); return true; }
static bool test_NetrJoinDomain(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct wkssvc_NetrJoinDomain r; struct cli_credentials *creds = cmdline_credentials; const char *user = cli_credentials_get_username(creds); const char *admin_account = NULL; struct dcerpc_binding_handle *b = p->binding_handle; admin_account = talloc_asprintf(tctx, "%s\\%s", lpcfg_workgroup(tctx->lp_ctx), user); r.in.server_name = dcerpc_server_name(p); r.in.domain_name = lpcfg_dnsdomain(tctx->lp_ctx); r.in.account_ou = NULL; r.in.Account = admin_account; r.in.password = NULL; r.in.join_flags = 0; torture_comment(tctx, "Testing NetrJoinDomain\n"); status = dcerpc_wkssvc_NetrJoinDomain_r(b, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "NetrJoinDomain failed"); torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED, "NetrJoinDomain failed"); return true; }
static bool test_NetrValidateName2(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct wkssvc_NetrValidateName2 r; uint16_t levels[] = {0,1,2,3,4,5}; int i; struct dcerpc_binding_handle *b = p->binding_handle; for (i=0; i<ARRAY_SIZE(levels); i++) { r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.name = lpcfg_workgroup(tctx->lp_ctx); r.in.Account = NULL; r.in.EncryptedPassword = NULL; r.in.name_type = levels[i]; torture_comment(tctx, "Testing NetrValidateName2 level %u\n", r.in.name_type); status = dcerpc_wkssvc_NetrValidateName2_r(b, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "NetrValidateName2 failed"); torture_assert_werr_equal(tctx, r.out.result, WERR_RPC_E_REMOTE_DISABLED, "NetrValidateName2 failed"); } return true; }
static bool try_failed_login(struct torture_context *tctx, struct smbcli_state *cli) { NTSTATUS status; struct smb_composite_sesssetup setup; struct smbcli_session *session; struct smbcli_session_options options; lpcfg_smbcli_session_options(tctx->lp_ctx, &options); session = smbcli_session_init(cli->transport, cli, false, options); setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); setup.in.credentials = cli_credentials_init(session); setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx); cli_credentials_set_conf(setup.in.credentials, tctx->lp_ctx); cli_credentials_set_domain(setup.in.credentials, "INVALID-DOMAIN", CRED_SPECIFIED); cli_credentials_set_username(setup.in.credentials, "INVALID-USERNAME", CRED_SPECIFIED); cli_credentials_set_password(setup.in.credentials, "INVALID-PASSWORD", CRED_SPECIFIED); status = smb_composite_sesssetup(session, &setup); talloc_free(session); if (NT_STATUS_IS_OK(status)) { printf("Allowed session setup with invalid credentials?!\n"); return false; } return true; }
/* test nbt dgram operations */ bool torture_nbt_browse(struct torture_context *torture) { const char *address; struct nbt_name name; TALLOC_CTX *mem_ctx = talloc_new(NULL); NTSTATUS status; bool ret = true; name.name = lpcfg_workgroup(); name.type = NBT_NAME_BROWSER; name.scope = NULL; /* do an initial name resolution to find its IP */ status = resolve_name(&name, mem_ctx, &address, torture->ev); if (!NT_STATUS_IS_OK(status)) { printf("Failed to resolve %s - %s\n", name.name, nt_errstr(status)); talloc_free(mem_ctx); return false; } talloc_free(mem_ctx); return ret; }
bool torture_usermod(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; struct policy_handle h; struct lsa_String domain_name; struct dom_sid2 sid; uint32_t rid; int i; char *name; TALLOC_CTX *mem_ctx; bool ret = true; struct dcerpc_binding_handle *b; mem_ctx = talloc_init("test_userdel"); status = torture_rpc_connection(torture, &p, &ndr_table_samr); torture_assert_ntstatus_ok(torture, status, "RPC connect"); b = p->binding_handle; domain_name.string = lpcfg_workgroup(torture->lp_ctx); name = talloc_strdup(mem_ctx, TEST_USERNAME); if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) { ret = false; goto done; } if (!test_user_create(torture, b, mem_ctx, &h, name, &rid)) { ret = false; goto done; } for (i = USER_FIELD_FIRST; i <= USER_FIELD_LAST; i++) { struct libnet_rpc_usermod m; if (!test_usermod(torture, p, mem_ctx, &h, i, &m, &name)) { ret = false; goto cleanup; } if (!test_compare(torture, p, mem_ctx, &h, &m, name)) { ret = false; goto cleanup; } } cleanup: if (!test_user_cleanup(torture, b, mem_ctx, &h, TEST_USERNAME)) { ret = false; goto done; } done: talloc_free(mem_ctx); return ret; }
/* setup the OS, Lanman and domain portions of a session setup reply */ static void sesssetup_common_strings(struct smbsrv_request *req, char **os, char **lanman, char **domain) { (*os) = talloc_asprintf(req, "Unix"); (*lanman) = talloc_asprintf(req, "Samba %s", SAMBA_VERSION_STRING); (*domain) = talloc_asprintf(req, "%s", lpcfg_workgroup(req->smb_conn->lp_ctx)); }
static bool test_do_global_parameter_var(struct torture_context *tctx) { struct loadparm_context *lp_ctx = loadparm_init(tctx); torture_assert(tctx, lpcfg_do_global_parameter_var(lp_ctx, "workgroup", "werk%s%d", "groep", 42), "lpcfg_set_cmdline failed"); torture_assert_str_equal(tctx, lpcfg_workgroup(lp_ctx), "WERKGROEP42", "workgroup"); return true; }
static bool test_set_cmdline(struct torture_context *tctx) { struct loadparm_context *lp_ctx = loadparm_init(tctx); torture_assert(tctx, lpcfg_set_cmdline(lp_ctx, "workgroup", "werkgroep"), "lpcfg_set_cmdline failed"); torture_assert(tctx, lpcfg_do_global_parameter(lp_ctx, "workgroup", "barbla"), "lpcfg_set_option failed"); torture_assert_str_equal(tctx, "WERKGROEP", lpcfg_workgroup(lp_ctx), "workgroup"); return true; }
bool torture_domain_open_samr(struct torture_context *torture) { NTSTATUS status; struct libnet_context *ctx; TALLOC_CTX *mem_ctx; struct policy_handle domain_handle, handle; struct libnet_DomainOpen io; struct samr_Close r; const char *domain_name; bool ret = true; mem_ctx = talloc_init("test_domainopen_lsa"); ctx = libnet_context_init(torture->ev, torture->lp_ctx); ctx->cred = cmdline_credentials; /* 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 = lpcfg_workgroup(torture->lp_ctx); /* * Testing synchronous version */ torture_comment(torture, "opening domain\n"); io.in.type = DOMAIN_SAMR; io.in.domain_name = domain_name; io.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; status = libnet_DomainOpen(ctx, mem_ctx, &io); if (!NT_STATUS_IS_OK(status)) { torture_comment(torture, "Composite domain open failed for domain '%s' - %s\n", domain_name, nt_errstr(status)); ret = false; goto done; } domain_handle = ctx->samr.handle; r.in.handle = &domain_handle; r.out.handle = &handle; torture_comment(torture, "closing domain handle\n"); torture_assert_ntstatus_ok(torture, dcerpc_samr_Close_r(ctx->samr.pipe->binding_handle, mem_ctx, &r), "Close failed"); torture_assert_ntstatus_ok(torture, r.out.result, "Close failed"); done: talloc_free(mem_ctx); talloc_free(ctx); return ret; }
static bool test_session_reauth1(struct torture_context *tctx, struct smbcli_state *cli) { NTSTATUS status; struct smb_composite_sesssetup io; int fnum, num; const int dlen = 255; char *data; char fname[256]; char buf[dlen+1]; bool ok = true; uint16_t vuid1 = cli->session->vuid; data = generate_random_str(tctx, dlen); torture_assert(tctx, (data != NULL), "memory allocation failed"); snprintf(fname, sizeof(fname), "raw_session_reconnect_%.8s.dat", data); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, 0); torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ok, done, "create file"); torture_assert_goto(tctx, fnum > 0, ok, done, "create file"); num = smbcli_smbwrite(cli->tree, fnum, data, 0, dlen); torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "write file"); ZERO_STRUCT(io); io.in.sesskey = cli->transport->negotiate.sesskey; io.in.capabilities = cli->transport->negotiate.capabilities; io.in.credentials = cmdline_credentials; io.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); io.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx); status = smb_composite_sesssetup(cli->session, &io); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "setup2"); torture_assert_int_equal_goto(tctx, io.out.vuid, vuid1, ok, done, "setup2"); buf[dlen] = '\0'; num = smbcli_read(cli->tree, fnum, &buf, 0, dlen); torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "read file"); torture_assert_str_equal_goto(tctx, buf, data, ok, done, "read file"); done: talloc_free(data); if (fnum > 0) { status = smbcli_close(cli->tree, fnum); torture_assert_ntstatus_ok(tctx, status, "close"); } return ok; }
bool torture_useradd(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; struct policy_handle h; struct lsa_String domain_name; struct dom_sid2 sid; const char *name = TEST_USERNAME; TALLOC_CTX *mem_ctx; bool ret = true; struct dcerpc_binding_handle *b; mem_ctx = talloc_init("test_useradd"); status = torture_rpc_connection(torture, &p, &ndr_table_samr); torture_assert_ntstatus_ok(torture, status, "RPC connect failed"); b = p->binding_handle; domain_name.string = lpcfg_workgroup(torture->lp_ctx); if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) { ret = false; goto done; } if (!test_useradd(torture, p, mem_ctx, &h, name)) { ret = false; goto done; } if (!test_user_cleanup(torture, b, mem_ctx, &h, name)) { ret = false; goto done; } if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) { ret = false; goto done; } if (!test_useradd_async(torture, p, mem_ctx, &h, name)) { ret = false; goto done; } if (!test_user_cleanup(torture, b, mem_ctx, &h, name)) { ret = false; goto done; } done: talloc_free(mem_ctx); return ret; }
const char *lpcfg_sam_name(struct loadparm_context *lp_ctx) { switch (lpcfg_server_role(lp_ctx)) { case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: return lpcfg_workgroup(lp_ctx); default: return lpcfg_netbios_name(lp_ctx); } }
/** * Specifies default values for domain, workstation and realm * from the smb.conf configuration file * * @param cred Credentials structure to fill in */ _PUBLIC_ void cli_credentials_set_conf(struct cli_credentials *cred, struct loadparm_context *lp_ctx) { cli_credentials_set_username(cred, "", CRED_UNINITIALISED); if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) { cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_UNINITIALISED); } if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) { cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED); } if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_UNINITIALISED); } }
bool torture_groupinfo(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx; bool ret = true; struct policy_handle h; struct lsa_String name; struct dom_sid2 sid; uint32_t rid; struct dcerpc_binding_handle *b; mem_ctx = talloc_init("test_userinfo"); status = torture_rpc_connection(torture, &p, &ndr_table_samr); if (!NT_STATUS_IS_OK(status)) { return false; } b = p->binding_handle; name.string = lpcfg_workgroup(torture->lp_ctx); /* * Testing synchronous version */ if (!test_domain_open(torture, b, &name, mem_ctx, &h, &sid)) { ret = false; goto done; } if (!test_group_create(torture, b, mem_ctx, &h, TEST_GROUPNAME, &rid)) { ret = false; goto done; } if (!test_groupinfo(torture, p, mem_ctx, &h, &sid, TEST_GROUPNAME, &rid)) { ret = false; goto done; } if (!test_group_cleanup(torture, b, mem_ctx, &h, TEST_GROUPNAME)) { ret = false; goto done; } done: talloc_free(mem_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 = lpcfg_workgroup(torture->lp_ctx); ctx = libnet_context_init(torture->ev, torture->lp_ctx); if (ctx == NULL) { torture_comment(torture, "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)) { torture_comment(torture, "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; torture_assert_ntstatus_ok(torture, dcerpc_lsa_Close_r(ctx->lsa.pipe->binding_handle, ctx, &lsa_close), "failed to close domain on lsa service"); torture_assert_ntstatus_ok(torture, lsa_close.out.result, "failed to close domain on lsa service"); done: talloc_free(ctx); return ret; }
static bool test_NetrWkstaUserGetInfo(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct wkssvc_NetrWkstaUserGetInfo r; union wkssvc_NetrWkstaUserInfo info; const char *dom = lpcfg_workgroup(tctx->lp_ctx); struct cli_credentials *creds = cmdline_credentials; const char *user = cli_credentials_get_username(creds); int i; struct dcerpc_binding_handle *b = p->binding_handle; const struct { const char *unknown; uint32_t level; WERROR result; } tests[] = { { NULL, 0, WERR_NO_SUCH_LOGON_SESSION }, { NULL, 1, WERR_NO_SUCH_LOGON_SESSION }, { NULL, 1101, WERR_OK }, { dom, 0, WERR_INVALID_PARAM }, { dom, 1, WERR_INVALID_PARAM }, { dom, 1101, WERR_INVALID_PARAM }, { user, 0, WERR_INVALID_PARAM }, { user, 1, WERR_INVALID_PARAM }, { user, 1101, WERR_INVALID_PARAM }, }; for (i=0; i<ARRAY_SIZE(tests); i++) { r.in.unknown = tests[i].unknown; r.in.level = tests[i].level; r.out.info = &info; torture_comment(tctx, "Testing NetrWkstaUserGetInfo level %u\n", r.in.level); status = dcerpc_wkssvc_NetrWkstaUserGetInfo_r(b, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "NetrWkstaUserGetInfo failed"); torture_assert_werr_equal(tctx, r.out.result, tests[i].result, "NetrWkstaUserGetInfo failed"); } return true; }
/* reopen a connection */ static void reopen_connection(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *private_data) { struct benchopen_state *state = (struct benchopen_state *)private_data; struct composite_context *ctx; struct smb_composite_connect *io = &state->reconnect; char *host, *share; state->te = NULL; if (!torture_get_conn_index(state->client_num, state->mem_ctx, state->tctx, &host, &share)) { DEBUG(0,("Can't find host/share for reconnect?!\n")); exit(1); } io->in.dest_host = state->dest_host; io->in.dest_ports = state->dest_ports; io->in.socket_options = lpcfg_socket_options(state->tctx->lp_ctx); io->in.called_name = state->called_name; io->in.service = share; io->in.service_type = state->service_type; io->in.credentials = cmdline_credentials; io->in.fallback_to_anonymous = false; io->in.workgroup = lpcfg_workgroup(state->tctx->lp_ctx); io->in.gensec_settings = lpcfg_gensec_settings(state->mem_ctx, state->tctx->lp_ctx); lpcfg_smbcli_options(state->tctx->lp_ctx, &io->in.options); lpcfg_smbcli_session_options(state->tctx->lp_ctx, &io->in.session_options); /* kill off the remnants of the old connection */ talloc_free(state->tree); state->tree = NULL; state->open_fnum = -1; state->close_fnum = -1; ctx = smb_composite_connect_send(io, state->mem_ctx, lpcfg_resolve_context(state->tctx->lp_ctx), state->ev); if (ctx == NULL) { DEBUG(0,("Failed to setup async reconnect\n")); exit(1); } ctx->async.fn = reopen_connection_complete; ctx->async.private_data = state; }
static bool torture_winbind_struct_domain_name(struct torture_context *torture) { const char *expected; char *domain; torture_comment(torture, "Running WINBINDD_DOMAIN_NAME (struct based)\n"); expected = torture_setting_string(torture, "winbindd_netbios_domain", lpcfg_workgroup(torture->lp_ctx)); get_winbind_domain(torture, &domain); torture_assert_str_equal(torture, domain, expected, "winbindd's netbios domain doesn't match"); return true; }
static bool test_NetrLogonDomainNameDel(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct wkssvc_NetrLogonDomainNameDel r; struct dcerpc_binding_handle *b = p->binding_handle; r.in.domain_name = lpcfg_workgroup(tctx->lp_ctx); torture_comment(tctx, "Testing NetrLogonDomainNameDel\n"); status = dcerpc_wkssvc_NetrLogonDomainNameDel_r(b, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "NetrLogonDomainNameDel failed"); torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED, "NetrLogonDomainNameDel failed"); return true; }
bool wb_samba3_split_username(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, const char *domuser, char **domain, char **user) { char *p = strchr(domuser, *lpcfg_winbind_separator(lp_ctx)); if (p == NULL) { *domain = talloc_strdup(mem_ctx, lpcfg_workgroup(lp_ctx)); } else { *domain = talloc_strndup(mem_ctx, domuser, PTR_DIFF(p, domuser)); domuser = p+1; } *user = talloc_strdup(mem_ctx, domuser); return ((*domain != NULL) && (*user != NULL)); }
bool torture_rpc_connect_dc_info(struct torture_context *torture) { const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_DC_INFO; NTSTATUS status; struct dcerpc_binding *binding; const char *domain_name; status = torture_rpc_binding(torture, &binding); if (!NT_STATUS_IS_OK(status)) { return false; } /* 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 = lpcfg_workgroup(torture->lp_ctx); return torture_rpc_connect(torture, level, NULL, domain_name); }
bool torture_userdel(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; struct policy_handle h; struct lsa_String domain_name; struct dom_sid2 sid; uint32_t rid; const char *name = TEST_USERNAME; TALLOC_CTX *mem_ctx; bool ret = true; struct dcerpc_binding_handle *b; mem_ctx = talloc_init("test_userdel"); status = torture_rpc_connection(torture, &p, &ndr_table_samr); if (!NT_STATUS_IS_OK(status)) { return false; } b = p->binding_handle; domain_name.string = lpcfg_workgroup(torture->lp_ctx); if (!test_domain_open(torture, b, &domain_name, mem_ctx, &h, &sid)) { ret = false; goto done; } if (!test_user_create(torture, b, mem_ctx, &h, name, &rid)) { ret = false; goto done; } if (!test_userdel(torture, p, mem_ctx, &h, name)) { ret = false; goto done; } done: talloc_free(mem_ctx); return ret; }
bool torture_creategroup(struct torture_context *torture) { bool ret = true; NTSTATUS status; TALLOC_CTX *mem_ctx = NULL; struct libnet_context *ctx; struct libnet_CreateGroup req; mem_ctx = talloc_init("test_creategroup"); ctx = libnet_context_init(torture->ev, torture->lp_ctx); ctx->cred = popt_get_cmdline_credentials(); req.in.group_name = TEST_GROUPNAME; req.in.domain_name = lpcfg_workgroup(torture->lp_ctx); req.out.error_string = NULL; status = libnet_CreateGroup(ctx, mem_ctx, &req); if (!NT_STATUS_IS_OK(status)) { torture_comment(torture, "libnet_CreateGroup call failed: %s\n", nt_errstr(status)); ret = false; goto done; } if (!test_group_cleanup(torture, ctx->samr.pipe->binding_handle, mem_ctx, &ctx->samr.handle, TEST_GROUPNAME)) { torture_comment(torture, "cleanup failed\n"); ret = false; goto done; } if (!test_samr_close_handle(torture, ctx->samr.pipe->binding_handle, mem_ctx, &ctx->samr.handle)) { torture_comment(torture, "domain close failed\n"); ret = false; } done: talloc_free(ctx); talloc_free(mem_ctx); return ret; }
bool torture_domainopen(struct torture_context *torture) { NTSTATUS status; struct libnet_context *net_ctx; TALLOC_CTX *mem_ctx; bool ret = true; struct policy_handle h; struct lsa_String name; mem_ctx = talloc_init("test_domain_open"); net_ctx = libnet_context_init(torture->ev, torture->lp_ctx); status = torture_rpc_connection(torture, &net_ctx->samr.pipe, &ndr_table_samr); if (!NT_STATUS_IS_OK(status)) { return false; } name.string = lpcfg_workgroup(torture->lp_ctx); /* * Testing synchronous version */ if (!test_domainopen(torture, net_ctx, mem_ctx, &name, &h)) { ret = false; goto done; } if (!test_cleanup(torture, net_ctx->samr.pipe->binding_handle, mem_ctx, &h)) { ret = false; goto done; } done: talloc_free(mem_ctx); return ret; }
static bool torture_rpc_spoolss_access_setup_common(struct torture_context *tctx, struct torture_access_context *t) { void *testuser; const char *testuser_passwd; struct cli_credentials *test_credentials; struct dom_sid *test_sid; struct dcerpc_pipe *p; const char *printername; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_pipe *spoolss_pipe; testuser = torture_create_testuser_max_pwlen(tctx, t->user.username, torture_setting_string(tctx, "workgroup", NULL), ACB_NORMAL, &testuser_passwd, 32); if (!testuser) { torture_fail(tctx, "Failed to create test user"); } test_credentials = cli_credentials_init(tctx); cli_credentials_set_workstation(test_credentials, "localhost", CRED_SPECIFIED); cli_credentials_set_domain(test_credentials, lpcfg_workgroup(tctx->lp_ctx), CRED_SPECIFIED); cli_credentials_set_username(test_credentials, t->user.username, CRED_SPECIFIED); cli_credentials_set_password(test_credentials, testuser_passwd, CRED_SPECIFIED); test_sid = discard_const_p(struct dom_sid, torture_join_user_sid(testuser)); if (t->user.num_builtin_memberships) { struct dcerpc_pipe *samr_pipe = torture_join_samr_pipe(testuser); torture_assert(tctx, spoolss_access_setup_membership(tctx, samr_pipe, t->user.num_builtin_memberships, t->user.builtin_memberships, test_sid), "failed to setup membership"); } if (t->user.num_privs) { struct dcerpc_pipe *lsa_pipe; torture_assert_ntstatus_ok(tctx, torture_rpc_connection(tctx, &lsa_pipe, &ndr_table_lsarpc), "Error connecting to server"); torture_assert(tctx, spoolss_access_setup_privs(tctx, lsa_pipe, t->user.num_privs, t->user.privs, test_sid, &t->user.privs_present), "failed to setup privs"); talloc_free(lsa_pipe); } torture_assert_ntstatus_ok(tctx, torture_rpc_connection(tctx, &spoolss_pipe, &ndr_table_spoolss), "Error connecting to server"); torture_assert(tctx, test_EnumPrinters_findone(tctx, spoolss_pipe, &printername), "failed to enumerate printers"); if (t->user.sd && printername) { torture_assert(tctx, spoolss_access_setup_sd(tctx, spoolss_pipe, printername, test_sid, &t->sd_orig), "failed to setup sd"); } talloc_free(spoolss_pipe); torture_assert_ntstatus_ok(tctx, dcerpc_pipe_connect(tctx, &p, binding, &ndr_table_spoolss, test_credentials, tctx->ev, tctx->lp_ctx), "Error connecting to server"); t->spoolss_pipe = p; t->printername = printername; t->user.testuser = testuser; return true; }
/* do some samr ops using the schannel connection */ static bool test_samr_ops(struct torture_context *tctx, struct dcerpc_binding_handle *b) { struct samr_GetDomPwInfo r; struct samr_PwInfo info; struct samr_Connect connect_r; struct samr_OpenDomain opendom; int i; struct lsa_String name; struct policy_handle handle; struct policy_handle domain_handle; name.string = lpcfg_workgroup(tctx->lp_ctx); r.in.domain_name = &name; r.out.info = &info; connect_r.in.system_name = 0; connect_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; connect_r.out.connect_handle = &handle; torture_comment(tctx, "Testing Connect and OpenDomain on BUILTIN\n"); torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &connect_r), "Connect failed"); if (!NT_STATUS_IS_OK(connect_r.out.result)) { if (NT_STATUS_EQUAL(connect_r.out.result, NT_STATUS_ACCESS_DENIED)) { torture_comment(tctx, "Connect failed (expected, schannel mapped to anonymous): %s\n", nt_errstr(connect_r.out.result)); } else { torture_comment(tctx, "Connect failed - %s\n", nt_errstr(connect_r.out.result)); return false; } } else { opendom.in.connect_handle = &handle; opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; opendom.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32"); opendom.out.domain_handle = &domain_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &opendom), "OpenDomain failed"); if (!NT_STATUS_IS_OK(opendom.out.result)) { torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(opendom.out.result)); return false; } } torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string); /* do several ops to test credential chaining */ for (i=0;i<5;i++) { torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r), "GetDomPwInfo failed"); if (!NT_STATUS_IS_OK(r.out.result)) { if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) { torture_comment(tctx, "GetDomPwInfo op %d failed - %s\n", i, nt_errstr(r.out.result)); return false; } } } return true; }
/* connect to a share - used when a tree_connect operation comes in. */ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_tcon *tcon) { NTSTATUS status; struct cvfs_private *p; const char *host, *user, *pass, *domain, *remote_share; struct smb_composite_connect io; struct composite_context *creq; struct share_config *scfg = ntvfs->ctx->config; struct cli_credentials *credentials; bool machine_account; bool s4u2proxy; const char* sharename; switch (tcon->generic.level) { case RAW_TCON_TCON: sharename = tcon->tcon.in.service; break; case RAW_TCON_TCONX: sharename = tcon->tconx.in.path; break; case RAW_TCON_SMB2: sharename = tcon->smb2.in.path; break; default: return NT_STATUS_INVALID_LEVEL; } if (strncmp(sharename, "\\\\", 2) == 0) { char *str = strchr(sharename+2, '\\'); if (str) { sharename = str + 1; } } /* Here we need to determine which server to connect to. * For now we use parametric options, type cifs. * Later we will use security=server and auth_server.c. */ host = share_string_option(scfg, CIFS_SERVER, NULL); user = share_string_option(scfg, CIFS_USER, NULL); pass = share_string_option(scfg, CIFS_PASSWORD, NULL); domain = share_string_option(scfg, CIFS_DOMAIN, NULL); remote_share = share_string_option(scfg, CIFS_SHARE, NULL); if (!remote_share) { remote_share = sharename; } machine_account = share_bool_option(scfg, CIFS_USE_MACHINE_ACCT, CIFS_USE_MACHINE_ACCT_DEFAULT); s4u2proxy = share_bool_option(scfg, CIFS_USE_S4U2PROXY, CIFS_USE_S4U2PROXY_DEFAULT); p = talloc_zero(ntvfs, struct cvfs_private); if (!p) { return NT_STATUS_NO_MEMORY; } ntvfs->private_data = p; if (!host) { DEBUG(1,("CIFS backend: You must supply server\n")); return NT_STATUS_INVALID_PARAMETER; } if (user && pass) { DEBUG(5, ("CIFS backend: Using specified password\n")); credentials = cli_credentials_init(p); if (!credentials) { return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx); cli_credentials_set_username(credentials, user, CRED_SPECIFIED); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } cli_credentials_set_password(credentials, pass, CRED_SPECIFIED); } else if (machine_account) { DEBUG(5, ("CIFS backend: Using machine account\n")); credentials = cli_credentials_init(p); cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } } else if (req->session_info->credentials) { DEBUG(5, ("CIFS backend: Using delegated credentials\n")); credentials = req->session_info->credentials; } else if (s4u2proxy) { struct ccache_container *ccc = NULL; const char *err_str = NULL; int ret; char *impersonate_principal; char *self_service; char *target_service; impersonate_principal = talloc_asprintf(req, "%s@%s", req->session_info->info->account_name, req->session_info->info->domain_name); self_service = talloc_asprintf(req, "cifs/%s", lpcfg_netbios_name(ntvfs->ctx->lp_ctx)); target_service = talloc_asprintf(req, "cifs/%s", host); DEBUG(5, ("CIFS backend: Using S4U2Proxy credentials\n")); credentials = cli_credentials_init(p); cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED); cli_credentials_set_impersonate_principal(credentials, impersonate_principal, self_service); cli_credentials_set_target_service(credentials, target_service); ret = cli_credentials_get_ccache(credentials, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, &ccc, &err_str); if (ret != 0) { status = NT_STATUS_CROSSREALM_DELEGATION_FAILURE; DEBUG(1,("S4U2Proxy: cli_credentials_get_ccache() gave: ret[%d] str[%s] - %s\n", ret, err_str, nt_errstr(status))); return status; } } else { DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n")); return NT_STATUS_INTERNAL_ERROR; } /* connect to the server, using the smbd event context */ io.in.dest_host = host; io.in.dest_ports = lpcfg_smb_ports(ntvfs->ctx->lp_ctx); io.in.socket_options = lpcfg_socket_options(ntvfs->ctx->lp_ctx); io.in.called_name = host; io.in.credentials = credentials; io.in.fallback_to_anonymous = false; io.in.workgroup = lpcfg_workgroup(ntvfs->ctx->lp_ctx); io.in.service = remote_share; io.in.service_type = "?????"; io.in.gensec_settings = lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx); lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &io.in.options); lpcfg_smbcli_session_options(ntvfs->ctx->lp_ctx, &io.in.session_options); if (!(ntvfs->ctx->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS)) { io.in.options.use_level2_oplocks = false; } creq = smb_composite_connect_send(&io, p, lpcfg_resolve_context(ntvfs->ctx->lp_ctx), ntvfs->ctx->event_ctx); status = smb_composite_connect_recv(creq, p); NT_STATUS_NOT_OK_RETURN(status); p->tree = io.out.tree; p->transport = p->tree->session->transport; SETUP_PID; p->ntvfs = ntvfs; ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type); ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); if (tcon->generic.level == RAW_TCON_TCONX) { tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; } /* we need to receive oplock break requests from the server */ smbcli_oplock_handler(p->transport, oplock_handler, p); p->map_generic = share_bool_option(scfg, CIFS_MAP_GENERIC, CIFS_MAP_GENERIC_DEFAULT); p->map_trans2 = share_bool_option(scfg, CIFS_MAP_TRANS2, CIFS_MAP_TRANS2_DEFAULT); return NT_STATUS_OK; }