static bool parse_target(struct loadparm_context *lp_ctx, const char *target) { char *host = NULL, *share = NULL; struct dcerpc_binding *binding_struct; NTSTATUS status; /* see if its a RPC transport specifier */ if (!smbcli_parse_unc(target, NULL, &host, &share)) { status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct); if (NT_STATUS_IS_ERR(status)) { d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target); return false; } lp_set_cmdline(lp_ctx, "torture:host", binding_struct->host); if (lp_parm_string(lp_ctx, NULL, "torture", "share") == NULL) lp_set_cmdline(lp_ctx, "torture:share", "IPC$"); lp_set_cmdline(lp_ctx, "torture:binding", target); } else { lp_set_cmdline(lp_ctx, "torture:host", host); lp_set_cmdline(lp_ctx, "torture:share", share); lp_set_cmdline(lp_ctx, "torture:binding", host); } return true; }
static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s) { struct composite_context *c = s->creq; struct composite_context *creq; char *binding_str; binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[seal,target_hostname=%s]", s->source_dsa.address, s->source_dsa.dns_name); if (composite_nomem(binding_str, c)) return; c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi.binding); talloc_free(binding_str); if (!composite_is_ok(c)) return; if (DEBUGLEVEL >= 10) { c->status = dcerpc_binding_set_flags(s->drsuapi.binding, DCERPC_DEBUG_PRINT_BOTH, 0); if (!composite_is_ok(c)) return; } creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &ndr_table_drsuapi, s->libnet->cred, s->libnet->event_ctx, s->libnet->lp_ctx); composite_continue(c, creq, unbecomeDC_drsuapi_connect_recv, s); }
static struct dcerpc_binding *init_domain_binding(struct init_domain_state *state, const struct dcerpc_interface_table *table) { struct dcerpc_binding *binding; NTSTATUS status; /* Make a binding string */ { char *s = talloc_asprintf(state, "ncacn_np:%s", state->domain->dc_name); if (s == NULL) return NULL; status = dcerpc_parse_binding(state, s, &binding); talloc_free(s); if (!NT_STATUS_IS_OK(status)) { return NULL; } } /* Alter binding to contain hostname, but also address (so we don't look it up twice) */ binding->target_hostname = state->domain->dc_name; binding->host = state->domain->dc_address; /* This shouldn't make a network call, as the mappings for named pipes are well known */ status = dcerpc_epm_map_binding(binding, binding, table, state->service->task->event_ctx); if (!NT_STATUS_IS_OK(status)) { return NULL; } return binding; }
static bool test_Insert(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct epm_Insert r; struct dcerpc_binding *bd; r.in.num_ents = 1; r.in.entries = talloc_array(tctx, struct epm_entry_t, 1); ZERO_STRUCT(r.in.entries[0].object); r.in.entries[0].annotation = "smbtorture endpoint"; status = dcerpc_parse_binding(tctx, "ncalrpc:[SMBTORTURE]", &bd); torture_assert_ntstatus_ok(tctx, status, "Unable to generate dcerpc_binding struct"); r.in.entries[0].tower = talloc(tctx, struct epm_twr_t); status = dcerpc_binding_build_tower(tctx, bd, &r.in.entries[0].tower->tower); torture_assert_ntstatus_ok(tctx, status, "Unable to build tower from binding struct"); r.in.replace = 0; status = dcerpc_epm_Insert(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "Insert failed"); torture_assert(tctx, r.out.result == 0, "Insert failed"); if (!test_Delete(p, tctx, r.in.entries)) { return false; } return true; }
/* test two schannel connections */ bool torture_rpc_schannel2(struct torture_context *torture) { struct test_join *join_ctx; NTSTATUS status; const char *binding = torture_setting_string(torture, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p1 = NULL, *p2 = NULL; struct cli_credentials *credentials1, *credentials2; uint32_t dcerpc_flags = DCERPC_SCHANNEL | DCERPC_SIGN; join_ctx = torture_join_domain(torture, talloc_asprintf(torture, "%s2", TEST_MACHINE_NAME), ACB_WSTRUST, &credentials1); torture_assert(torture, join_ctx != NULL, "Failed to join domain with acct_flags=ACB_WSTRUST"); credentials2 = cli_credentials_shallow_copy(torture, credentials1); cli_credentials_set_netlogon_creds(credentials1, NULL); cli_credentials_set_netlogon_creds(credentials2, NULL); status = dcerpc_parse_binding(torture, binding, &b); torture_assert_ntstatus_ok(torture, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(torture, status, "set flags"); torture_comment(torture, "Opening first connection\n"); status = dcerpc_pipe_connect_b(torture, &p1, b, &ndr_table_netlogon, credentials1, torture->ev, torture->lp_ctx); torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel"); torture_comment(torture, "Opening second connection\n"); status = dcerpc_pipe_connect_b(torture, &p2, b, &ndr_table_netlogon, credentials2, torture->ev, torture->lp_ctx); torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel"); cli_credentials_set_netlogon_creds(credentials1, NULL); cli_credentials_set_netlogon_creds(credentials2, NULL); torture_comment(torture, "Testing logon on pipe1\n"); if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL)) return false; torture_comment(torture, "Testing logon on pipe2\n"); if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL)) return false; torture_comment(torture, "Again on pipe1\n"); if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL)) return false; torture_comment(torture, "Again on pipe2\n"); if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL)) return false; torture_leave_domain(torture, join_ctx); return true; }
WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s, const struct repsFromTo1 *rft, struct dreplsrv_out_connection **_conn) { struct dreplsrv_out_connection *cur, *conn = NULL; const char *hostname; if (!rft->other_info) { return WERR_FOOBAR; } if (!rft->other_info->dns_name) { return WERR_FOOBAR; } hostname = rft->other_info->dns_name; for (cur = s->connections; cur; cur = cur->next) { if (strcmp(cur->binding->host, hostname) == 0) { conn = cur; break; } } if (!conn) { NTSTATUS nt_status; char *binding_str; conn = talloc_zero(s, struct dreplsrv_out_connection); W_ERROR_HAVE_NO_MEMORY(conn); conn->service = s; binding_str = talloc_asprintf(conn, "ncacn_ip_tcp:%s[krb5,seal]", hostname); W_ERROR_HAVE_NO_MEMORY(binding_str); nt_status = dcerpc_parse_binding(conn, binding_str, &conn->binding); talloc_free(binding_str); if (!NT_STATUS_IS_OK(nt_status)) { return ntstatus_to_werror(nt_status); } /* use the GC principal for DRS replication */ nt_status = dreplsrv_get_target_principal(s, conn->binding, rft, &conn->binding->target_principal); if (!NT_STATUS_IS_OK(nt_status)) { return ntstatus_to_werror(nt_status); } DLIST_ADD_END(s->connections, conn, struct dreplsrv_out_connection *); DEBUG(4,("dreplsrv_out_connection_attach(%s): create\n", conn->binding->host)); } else {
BOOL torture_listshares(struct torture_context *torture) { struct libnet_ListShares share; NTSTATUS status; uint32_t levels[] = { 0, 1, 2, 501, 502 }; int i; BOOL ret = True; struct libnet_context* libnetctx; const char *binding; struct dcerpc_binding *bind; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("test_listshares"); binding = torture_setting_string(torture, "binding", NULL); status = dcerpc_parse_binding(mem_ctx, binding, &bind); if (!NT_STATUS_IS_OK(status)) { printf("Error while parsing the binding string\n"); ret = False; goto done; } libnetctx = libnet_context_init(NULL); if (!libnetctx) { printf("Couldn't allocate libnet context\n"); ret = False; goto done; } libnetctx->cred = cmdline_credentials; printf("Testing libnet_ListShare\n"); share.in.server_name = talloc_asprintf(mem_ctx, "%s", bind->host); for (i = 0; i < ARRAY_SIZE(levels); i++) { share.in.level = levels[i]; printf("testing libnet_ListShare level %u\n", share.in.level); status = libnet_ListShares(libnetctx, mem_ctx, &share); if (!NT_STATUS_IS_OK(status)) { printf("libnet_ListShare level %u failed - %s\n", share.in.level, share.out.error_string); ret = False; goto done; } printf("listing shares:\n"); test_displayshares(share); } 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 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; }
static bool test_Insert_noreplace(struct torture_context *tctx, struct dcerpc_pipe *p) { bool ok; NTSTATUS status; struct epm_Insert r; struct dcerpc_binding *b; struct dcerpc_binding_handle *h = p->binding_handle; torture_comment(tctx, "Testing epm_Insert(noreplace) and epm_Delete\n"); if (torture_setting_bool(tctx, "samba4", false)) { torture_skip(tctx, "Skip Insert test against Samba4"); } r.in.num_ents = 1; r.in.entries = talloc_array(tctx, struct epm_entry_t, 1); ZERO_STRUCT(r.in.entries[0].object); r.in.entries[0].annotation = "smbtorture endpoint"; status = dcerpc_parse_binding(tctx, "ncalrpc:[SMBTORTURE]", &b); torture_assert_ntstatus_ok(tctx, status, "Unable to generate dcerpc_binding struct"); r.in.entries[0].tower = talloc(tctx, struct epm_twr_t); status = dcerpc_binding_build_tower(tctx, b, &r.in.entries[0].tower->tower); torture_assert_ntstatus_ok(tctx, status, "Unable to build tower from binding struct"); r.in.replace = 0; status = dcerpc_epm_Insert_r(h, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "epm_Insert failed"); torture_assert(tctx, r.out.result == 0, "epm_Insert failed"); ok = test_Delete(tctx, h, "smbtorture", b); if (!ok) { return false; } return true; }
BOOL torture_rpc_connect_binding(struct torture_context *torture) { const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_BINDING; NTSTATUS status; struct dcerpc_binding *binding; 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; } return torture_rpc_connect(torture, level, bindstr, NULL); }
BOOL torture_delshare(struct torture_context *torture) { struct dcerpc_pipe *p; struct dcerpc_binding *bind; struct libnet_context* libnetctx; const char *host, *binding; TALLOC_CTX *mem_ctx; NTSTATUS status; BOOL ret = True; struct libnet_DelShare share; mem_ctx = talloc_init("test_listshares"); host = torture_setting_string(torture, "host", NULL); binding = torture_setting_string(torture, "binding", NULL); status = dcerpc_parse_binding(mem_ctx, binding, &bind); if (!NT_STATUS_IS_OK(status)) { printf("Error while parsing the binding string\n"); ret = False; goto done; } libnetctx = libnet_context_init(NULL); libnetctx->cred = cmdline_credentials; status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_srvsvc); if (!test_addshare(p, mem_ctx, host, TEST_SHARENAME)) { ret = False; goto done; } share.in.server_name = bind->host; share.in.share_name = TEST_SHARENAME; status = libnet_DelShare(libnetctx, mem_ctx, &share); if (!NT_STATUS_IS_OK(status)) { ret = False; goto done; } done: talloc_free(mem_ctx); return ret; }
static BOOL test_Insert(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; struct epm_Insert r; struct dcerpc_binding *bd; r.in.num_ents = 1; r.in.entries = talloc_array(mem_ctx, struct epm_entry_t, 1); ZERO_STRUCT(r.in.entries[0].object); r.in.entries[0].annotation = "smbtorture endpoint"; status = dcerpc_parse_binding(mem_ctx, "ncalrpc:[SMBTORTURE]", &bd); if (NT_STATUS_IS_ERR(status)) { printf("Unable to generate dcerpc_binding struct\n"); return False; } r.in.entries[0].tower = talloc(mem_ctx, struct epm_twr_t); status = dcerpc_binding_build_tower(mem_ctx, bd, &r.in.entries[0].tower->tower); if (NT_STATUS_IS_ERR(status)) { printf("Unable to build tower from binding struct\n"); return False; } r.in.replace = 0; status = dcerpc_epm_Insert(p, mem_ctx, &r); if (NT_STATUS_IS_ERR(status)) { printf("Insert failed - %s\n", nt_errstr(status)); return False; } if (r.out.result != 0) { printf("Insert failed - %d\n", r.out.result); printf("NOT CONSIDERING AS A FAILURE\n"); return True; } if (!test_Delete(p, mem_ctx, r.in.entries)) { return False; } return True; }
static bool test_BindingString(struct torture_context *tctx, const void *test_data) { const char *binding = test_data; struct dcerpc_binding *b, *b2; const char *s, *s2; struct epm_tower tower; TALLOC_CTX *mem_ctx = tctx; /* Parse */ torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(mem_ctx, binding, &b), "Error parsing binding string"); s = dcerpc_binding_string(mem_ctx, b); torture_assert(tctx, s != NULL, "Error converting binding back to string"); torture_assert_casestr_equal(tctx, binding, s, "Mismatch while comparing original and regenerated binding strings"); /* Generate protocol towers */ torture_assert_ntstatus_ok(tctx, dcerpc_binding_build_tower(mem_ctx, b, &tower), "Error generating protocol tower"); /* Convert back to binding and then back to string and compare */ torture_assert_ntstatus_ok(tctx, dcerpc_binding_from_tower(mem_ctx, &tower, &b2), "Error generating binding from tower for original binding"); /* Compare to a stripped down version of the binding string because * the protocol tower doesn't contain the extra option data */ b->options = NULL; b->flags = 0; s = dcerpc_binding_string(mem_ctx, b); torture_assert(tctx, s != NULL, "Error converting binding back to string for (stripped down)"); s2 = dcerpc_binding_string(mem_ctx, b2); torture_assert(tctx, s != NULL, "Error converting binding back to string"); if (is_ipaddress(b->host)) torture_assert_casestr_equal(tctx, s, s2, "Mismatch while comparing original and from protocol tower generated binding strings"); return true; }
static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s) { struct composite_context *c = s->creq; struct composite_context *creq; char *binding_str; binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[seal]", s->source_dsa.dns_name); if (composite_nomem(binding_str, c)) return; c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi.binding); talloc_free(binding_str); if (!composite_is_ok(c)) return; creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &ndr_table_drsuapi, s->libnet->cred, s->libnet->event_ctx, s->libnet->lp_ctx); composite_continue(c, creq, unbecomeDC_drsuapi_connect_recv, s); }
static struct dcerpc_binding *init_domain_binding(struct init_domain_state *state, const struct ndr_interface_table *table) { struct dcerpc_binding *binding; enum dcerpc_transport_t transport; char *s; NTSTATUS status; /* Make a binding string */ if ((lpcfg_server_role(state->service->task->lp_ctx) != ROLE_DOMAIN_MEMBER) && dom_sid_equal(state->domain->info->sid, state->service->primary_sid) && state->service->sec_channel_type != SEC_CHAN_RODC) { s = talloc_asprintf(state, "ncalrpc:%s[target_hostname=%s]", state->domain->dc_address, state->domain->dc_name); if (s == NULL) return NULL; } else { s = talloc_asprintf(state, "ncacn_np:%s[target_hostname=%s]", state->domain->dc_address, state->domain->dc_name); if (s == NULL) return NULL; } status = dcerpc_parse_binding(state, s, &binding); talloc_free(s); if (!NT_STATUS_IS_OK(status)) { return NULL; } transport = dcerpc_binding_get_transport(binding); if (transport == NCALRPC) { return binding; } /* This shouldn't make a network call, as the mappings for named pipes are well known */ status = dcerpc_epm_map_binding(binding, binding, table, state->service->task->event_ctx, state->service->task->lp_ctx); if (!NT_STATUS_IS_OK(status)) { return NULL; } return binding; }
static bool test_no_transport(struct torture_context *tctx) { const char *binding = "somehost"; struct dcerpc_binding *b; const char *s; /* Parse */ torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, binding, &b), "Error parsing binding string"); torture_assert(tctx, b->transport == NCA_UNKNOWN, "invalid transport"); s = dcerpc_binding_string(tctx, b); torture_assert(tctx, s != NULL, "Error converting binding back to string"); torture_assert_casestr_equal(tctx, binding, s, "Mismatch while comparing original and regenerated binding strings"); return true; }
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 *bindstr; const char *domain_name; 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; } /* 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(); return torture_rpc_connect(torture, level, NULL, domain_name); }
/** * Obtain the DCE/RPC binding context associated with a torture context. * * @param tctx Torture context * @param binding Pointer to store DCE/RPC binding */ NTSTATUS torture_rpc_binding(struct torture_context *tctx, struct dcerpc_binding **binding) { NTSTATUS status; const char *binding_string = torture_setting_string(tctx, "binding", NULL); if (binding_string == NULL) { torture_comment(tctx, "You must specify a DCE/RPC binding string\n"); return NT_STATUS_INVALID_PARAMETER; } status = dcerpc_parse_binding(tctx, binding_string, binding); if (NT_STATUS_IS_ERR(status)) { DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding_string)); return status; } return NT_STATUS_OK; }
static struct DsGetinfoTest *test_create_context(struct torture_context *tctx) { NTSTATUS status; struct DsGetinfoTest *ctx; struct drsuapi_DsBindInfo28 *our_bind_info28; struct drsuapi_DsBindInfoCtr *our_bind_info_ctr; const char *binding = torture_setting_string(tctx, "binding", NULL); ctx = talloc_zero(tctx, struct DsGetinfoTest); if (!ctx) return NULL; status = dcerpc_parse_binding(ctx, binding, &ctx->drsuapi_binding); if (!NT_STATUS_IS_OK(status)) { printf("Bad binding string %s\n", binding); return NULL; } ctx->drsuapi_binding->flags |= DCERPC_SIGN | DCERPC_SEAL; /* ctx->admin ...*/ ctx->admin.credentials = cmdline_credentials; our_bind_info28 = &ctx->admin.drsuapi.our_bind_info28; our_bind_info28->supported_extensions = 0xFFFFFFFF; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; our_bind_info28->site_guid = GUID_zero(); our_bind_info28->pid = 0; our_bind_info28->repl_epoch = 1; our_bind_info_ctr = &ctx->admin.drsuapi.our_bind_info_ctr; our_bind_info_ctr->length = 28; our_bind_info_ctr->info.info28 = *our_bind_info28; GUID_from_string(DRSUAPI_DS_BIND_GUID, &ctx->admin.drsuapi.bind_guid); ctx->admin.drsuapi.req.in.bind_guid = &ctx->admin.drsuapi.bind_guid; ctx->admin.drsuapi.req.in.bind_info = our_bind_info_ctr; ctx->admin.drsuapi.req.out.bind_handle = &ctx->admin.drsuapi.bind_handle; return ctx; }
static bool test_Map_full(struct torture_context *tctx, struct dcerpc_pipe *p) { const struct ndr_syntax_id obj = { { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} }, 2 }; struct dcerpc_binding_handle *h = p->binding_handle; const char *annotation = "SMBTORTURE"; struct dcerpc_binding *b; NTSTATUS status; bool ok; status = dcerpc_parse_binding(tctx, "ncacn_ip_tcp:216.83.154.106[41768]", &b); torture_assert_ntstatus_ok(tctx, status, "Unable to generate dcerpc_binding struct"); b->object = obj; ok = test_Insert(tctx, h, obj, annotation, b); if (!ok) { return false; } ok = test_Map_tcpip(tctx, h, obj); if (!ok) { return false; } ok = test_Delete(tctx, h, annotation, b); if (!ok) { return false; } return true; }
NTSTATUS dcerpc_binding_vector_create(TALLOC_CTX *mem_ctx, const struct ndr_interface_table *iface, uint16_t port, const char *ncalrpc, struct dcerpc_binding_vector **pbvec) { struct dcerpc_binding_vector *bvec; uint32_t ep_count; uint32_t count = 0; uint32_t i; NTSTATUS status; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } ep_count = iface->endpoints->count; bvec = talloc_zero(tmp_ctx, struct dcerpc_binding_vector); if (bvec == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } bvec->bindings = talloc_zero_array(bvec, struct dcerpc_binding, ep_count); if (bvec->bindings == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } for (i = 0; i < ep_count; i++) { struct dcerpc_binding *b; b = talloc_zero(bvec->bindings, struct dcerpc_binding); if (b == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } status = dcerpc_parse_binding(b, iface->endpoints->names[i], &b); if (!NT_STATUS_IS_OK(status)) { status = NT_STATUS_UNSUCCESSFUL; goto done; } b->object = iface->syntax_id; switch (b->transport) { case NCACN_NP: b->host = talloc_asprintf(b, "\\\\%s", lp_netbios_name()); if (b->host == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } break; case NCACN_IP_TCP: if (port == 0) { talloc_free(b); continue; } b->endpoint = talloc_asprintf(b, "%u", port); if (b->endpoint == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } break; case NCALRPC: if (ncalrpc == NULL) { talloc_free(b); continue; } b->endpoint = talloc_asprintf(b, "%s/%s", lp_ncalrpc_dir(), ncalrpc); if (b->endpoint == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } break; default: talloc_free(b); continue; } bvec->bindings[count] = *b; count++; } bvec->count = count; *pbvec = talloc_move(mem_ctx, &bvec); status = NT_STATUS_OK; done: talloc_free(tmp_ctx); return status; }
static bool test_schannel_anonymous_setPassword(struct torture_context *tctx, uint32_t dcerpc_flags, bool use2) { NTSTATUS status, result; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct cli_credentials *credentials; bool ok = true; credentials = cli_credentials_init(NULL); torture_assert(tctx, credentials != NULL, "Bad credentials"); cli_credentials_set_anonymous(credentials); status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_netlogon, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel"); if (use2) { struct netr_ServerPasswordSet2 r = {}; struct netr_Authenticator credential = {}; struct netr_Authenticator return_authenticator = {}; struct netr_CryptPassword new_password = {}; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); r.in.secure_channel_type = 0; r.in.computer_name = TEST_MACHINE_NAME; r.in.credential = &credential; r.in.new_password = &new_password; r.out.return_authenticator = &return_authenticator; status = dcerpc_netr_ServerPasswordSet2_r(p->binding_handle, tctx, &r); result = r.out.result; } else { struct netr_ServerPasswordSet r = {}; struct netr_Authenticator credential = {}; struct netr_Authenticator return_authenticator = {}; struct samr_Password new_password = {}; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); r.in.secure_channel_type = 0; r.in.computer_name = TEST_MACHINE_NAME; r.in.credential = &credential; r.in.new_password = &new_password; r.out.return_authenticator = &return_authenticator; status = dcerpc_netr_ServerPasswordSet_r(p->binding_handle, tctx, &r); result = r.out.result; } torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet failed"); if (NT_STATUS_IS_OK(result)) { torture_fail(tctx, "unexpectedly received NT_STATUS_OK"); } return ok; }
/* test a schannel connection with the given flags */ static bool test_schannel(struct torture_context *tctx, uint16_t acct_flags, uint32_t dcerpc_flags, int i) { struct test_join *join_ctx; NTSTATUS status; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct dcerpc_pipe *p_netlogon = NULL; struct dcerpc_pipe *p_netlogon2 = NULL; struct dcerpc_pipe *p_netlogon3 = NULL; struct dcerpc_pipe *p_samr2 = NULL; struct dcerpc_pipe *p_lsa = NULL; struct netlogon_creds_CredentialState *creds; struct cli_credentials *credentials; enum dcerpc_transport_t transport; join_ctx = torture_join_domain(tctx, talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i), acct_flags, &credentials); torture_assert(tctx, join_ctx != NULL, "Failed to join domain"); status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect to samr with schannel"); torture_assert(tctx, test_samr_ops(tctx, p->binding_handle), "Failed to process schannel secured SAMR ops"); /* Also test that when we connect to the netlogon pipe, that * the credentials we setup on the first pipe are valid for * the second */ /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_secondary_auth_connection(p, b, &ndr_table_netlogon, credentials, tctx->lp_ctx, tctx, &p_netlogon); torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection"); creds = cli_credentials_get_netlogon_creds(credentials); torture_assert(tctx, (creds != NULL), "schannel creds"); /* checks the capabilities */ torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured capability ops (on fresh connection)"); /* do a couple of logins */ torture_assert(tctx, test_netlogon_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops"); torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops"); /* we *MUST* use ncacn_np for openpolicy etc. */ transport = dcerpc_binding_get_transport(b); status = dcerpc_binding_set_transport(b, NCACN_NP); torture_assert_ntstatus_ok(tctx, status, "set transport"); /* Swap the binding details from SAMR to LSARPC */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); torture_assert_ntstatus_ok(tctx, dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc, credentials, tctx->ev, tctx->lp_ctx), "failed to connect lsarpc with schannel"); torture_assert(tctx, test_lsa_ops(tctx, p_lsa), "Failed to process schannel secured LSA ops"); talloc_free(p_lsa); p_lsa = NULL; /* we *MUST* use ncacn_ip_tcp for lookupsids3/lookupnames4 */ status = dcerpc_binding_set_transport(b, NCACN_IP_TCP); torture_assert_ntstatus_ok(tctx, status, "set transport"); torture_assert_ntstatus_ok(tctx, dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx), "failed to call epm map"); torture_assert_ntstatus_ok(tctx, dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc, credentials, tctx->ev, tctx->lp_ctx), "failed to connect lsarpc with schannel"); torture_assert(tctx, test_many_LookupSids(p_lsa, tctx, NULL), "LsaLookupSids3 failed!\n"); status = dcerpc_binding_set_transport(b, transport); torture_assert_ntstatus_ok(tctx, status, "set transport"); /* Drop the socket, we want to start from scratch */ talloc_free(p); p = NULL; /* Now see what we are still allowed to do */ status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect with schannel"); /* do a some SAMR operations. We have *not* done a new serverauthenticate */ torture_assert (tctx, test_samr_ops(tctx, p_samr2->binding_handle), "Failed to process schannel secured SAMR ops (on fresh connection)"); /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_secondary_auth_connection(p_samr2, b, &ndr_table_netlogon, credentials, tctx->lp_ctx, tctx, &p_netlogon2); torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection"); /* checks the capabilities */ torture_assert(tctx, test_netlogon_capabilities(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured capability ops (on fresh connection)"); /* Try the schannel-only SamLogonEx operation */ torture_assert(tctx, test_netlogon_ex_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops (on fresh connection)"); /* And the more traditional style, proving that the * credentials chaining state is fully present */ torture_assert(tctx, test_netlogon_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops (on fresh connection)"); /* Drop the socket, we want to start from scratch (again) */ talloc_free(p_samr2); /* We don't want schannel for this test */ status = dcerpc_binding_set_flags(b, 0, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel"); torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds), "Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)"); /* Required because the previous call will mark the current context as having failed */ tctx->last_result = TORTURE_OK; tctx->last_reason = NULL; torture_assert(tctx, test_netlogon_ops(p_netlogon3, tctx, credentials, creds), "Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth"); torture_leave_domain(tctx, join_ctx); return true; }
BOOL torture_rpc_scanner(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx, *loop_ctx; BOOL ret = True; const struct dcerpc_interface_list *l; const char *binding = torture_setting_string(torture, "binding", NULL); struct dcerpc_binding *b; mem_ctx = talloc_init("torture_rpc_scanner"); if (!binding) { talloc_free(mem_ctx); printf("You must supply a ncacn binding string\n"); return False; } status = dcerpc_parse_binding(mem_ctx, binding, &b); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); printf("Failed to parse binding '%s'\n", binding); return False; } for (l=librpc_dcerpc_pipes();l;l=l->next) { loop_ctx = talloc_named(mem_ctx, 0, "torture_rpc_scanner loop context"); /* some interfaces are not mappable */ if (l->table->num_calls == 0 || strcmp(l->table->name, "mgmt") == 0) { talloc_free(loop_ctx); continue; } printf("\nTesting pipe '%s'\n", l->table->name); if (b->transport == NCACN_IP_TCP) { status = dcerpc_epm_map_binding(mem_ctx, b, l->table, NULL); if (!NT_STATUS_IS_OK(status)) { printf("Failed to map port for uuid %s\n", GUID_string(loop_ctx, &l->table->syntax_id.uuid)); talloc_free(loop_ctx); continue; } } else { b->endpoint = talloc_strdup(b, l->table->name); } lp_set_cmdline("torture:binding", dcerpc_binding_string(mem_ctx, b)); status = torture_rpc_connection(loop_ctx, &p, &dcerpc_table_mgmt); if (!NT_STATUS_IS_OK(status)) { talloc_free(loop_ctx); ret = False; continue; } if (!test_inq_if_ids(p, mem_ctx, l->table)) { ret = False; } } return ret; }
BOOL torture_domain_list(struct torture_context *torture) { BOOL ret = True; NTSTATUS status; TALLOC_CTX *mem_ctx = NULL; const char *bindstr; struct dcerpc_binding *binding; struct libnet_context *ctx; struct libnet_DomainList r; int i; 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"); ret = False; goto done; } ctx->cred = cmdline_credentials; mem_ctx = talloc_init("torture_domain_close_samr"); /* * querying the domain list using default buffer size */ ZERO_STRUCT(r); r.in.hostname = binding->host; status = libnet_DomainList(ctx, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { ret = False; goto done; } d_printf("Received list or domains (everything in one piece):\n"); for (i = 0; i < r.out.count; i++) { d_printf("Name[%d]: %s\n", i, r.out.domains[i].name); } /* * querying the domain list using specified (much smaller) buffer size */ ctx->samr.buf_size = 32; ZERO_STRUCT(r); r.in.hostname = binding->host; status = libnet_DomainList(ctx, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { ret = False; goto done; } d_printf("Received list or domains (collected in more than one round):\n"); for (i = 0; i < r.out.count; i++) { d_printf("Name[%d]: %s\n", i, r.out.domains[i].name); } done: d_printf("\nStatus: %s\n", nt_errstr(status)); talloc_free(mem_ctx); talloc_free(ctx); return ret; }
BOOL torture_domain_close_samr(struct torture_context *torture) { BOOL ret = True; NTSTATUS status; TALLOC_CTX *mem_ctx = NULL; struct libnet_context *ctx; struct lsa_String domain_name; struct dcerpc_binding *binding; const char *bindstr; uint32_t access_mask; struct policy_handle h; struct dcerpc_pipe *p; struct libnet_DomainClose r; 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"); ret = False; goto done; } ctx->cred = cmdline_credentials; mem_ctx = talloc_init("torture_domain_close_samr"); status = dcerpc_pipe_connect(mem_ctx, &p, bindstr, &dcerpc_table_samr, ctx->cred, NULL); if (!NT_STATUS_IS_OK(status)) { d_printf("failed to connect to server %s: %s\n", bindstr, nt_errstr(status)); ret = False; goto done; } domain_name.string = lp_workgroup(); if (!test_opendomain_samr(p, torture, &h, &domain_name, &access_mask)) { d_printf("failed to open domain on samr service\n"); ret = False; goto done; } ctx->samr.pipe = p; ctx->samr.name = domain_name.string; ctx->samr.access_mask = access_mask; ctx->samr.handle = h; /* we have to use pipe's event context, otherwise the call will hang indefinitely - this wouldn't be the case if pipe was opened by means of libnet call */ ctx->event_ctx = p->conn->event_ctx; ZERO_STRUCT(r); r.in.type = DOMAIN_SAMR; r.in.domain_name = domain_name.string; status = libnet_DomainClose(ctx, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { ret = False; goto done; } done: talloc_free(mem_ctx); talloc_free(ctx); return ret; }
/* test a schannel connection with the given flags */ static bool test_schannel(struct torture_context *tctx, uint16_t acct_flags, uint32_t dcerpc_flags, int i) { struct test_join *join_ctx; NTSTATUS status; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct dcerpc_pipe *p_netlogon = NULL; struct dcerpc_pipe *p_netlogon2 = NULL; struct dcerpc_pipe *p_netlogon3 = NULL; struct dcerpc_pipe *p_samr2 = NULL; struct dcerpc_pipe *p_lsa = NULL; struct netlogon_creds_CredentialState *creds; struct cli_credentials *credentials; join_ctx = torture_join_domain(tctx, talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i), acct_flags, &credentials); torture_assert(tctx, join_ctx != NULL, "Failed to join domain"); status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= dcerpc_flags; status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect with schannel"); torture_assert(tctx, test_samr_ops(tctx, p->binding_handle), "Failed to process schannel secured SAMR ops"); /* Also test that when we connect to the netlogon pipe, that * the credentials we setup on the first pipe are valid for * the second */ /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); status = dcerpc_secondary_connection(p, &p_netlogon, b); torture_assert_ntstatus_ok(tctx, status, "seconday connection"); status = dcerpc_bind_auth(p_netlogon, &ndr_table_netlogon, credentials, lpcfg_gensec_settings(tctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), NULL); torture_assert_ntstatus_ok(tctx, status, "bind auth"); status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, tctx, &creds); torture_assert_ntstatus_ok(tctx, status, "schannel creds"); /* do a couple of logins */ torture_assert(tctx, test_netlogon_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops"); torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops"); /* Swap the binding details from SAMR to LSARPC */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm map"); status = dcerpc_secondary_connection(p, &p_lsa, b); torture_assert_ntstatus_ok(tctx, status, "seconday connection"); status = dcerpc_bind_auth(p_lsa, &ndr_table_lsarpc, credentials, lpcfg_gensec_settings(tctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn), NULL); torture_assert_ntstatus_ok(tctx, status, "bind auth"); torture_assert(tctx, test_lsa_ops(tctx, p_lsa), "Failed to process schannel secured LSA ops"); /* Drop the socket, we want to start from scratch */ talloc_free(p); p = NULL; /* Now see what we are still allowed to do */ status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); b->flags &= ~DCERPC_AUTH_OPTIONS; b->flags |= dcerpc_flags; status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect with schannel"); /* do a some SAMR operations. We have *not* done a new serverauthenticate */ torture_assert (tctx, test_samr_ops(tctx, p_samr2->binding_handle), "Failed to process schannel secured SAMR ops (on fresh connection)"); /* Swap the binding details from SAMR to NETLOGON */ status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "epm"); status = dcerpc_secondary_connection(p_samr2, &p_netlogon2, b); torture_assert_ntstatus_ok(tctx, status, "seconday connection"); /* and now setup an SCHANNEL bind on netlogon */ status = dcerpc_bind_auth(p_netlogon2, &ndr_table_netlogon, credentials, lpcfg_gensec_settings(tctx, tctx->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p_samr2->conn), NULL); torture_assert_ntstatus_ok(tctx, status, "auth failed"); /* Try the schannel-only SamLogonEx operation */ torture_assert(tctx, test_netlogon_ex_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON EX ops (on fresh connection)"); /* And the more traditional style, proving that the * credentials chaining state is fully present */ torture_assert(tctx, test_netlogon_ops(p_netlogon2, tctx, credentials, creds), "Failed to process schannel secured NETLOGON ops (on fresh connection)"); /* Drop the socket, we want to start from scratch (again) */ talloc_free(p_samr2); /* We don't want schannel for this test */ b->flags &= ~DCERPC_AUTH_OPTIONS; status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel"); torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds), "Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)"); /* Required because the previous call will mark the current context as having failed */ tctx->last_result = TORTURE_OK; tctx->last_reason = NULL; torture_assert(tctx, test_netlogon_ops(p_netlogon3, tctx, credentials, creds), "Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth"); torture_leave_domain(tctx, join_ctx); return true; }
/* spoolss_RemoteFindFirstPrinterChangeNotifyEx */ static WERROR dcesrv_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r) { struct dcerpc_pipe *p; char *binding_string; struct dcerpc_binding *binding; NTSTATUS status; struct spoolss_ReplyOpenPrinter rop; struct cli_credentials *creds; struct policy_handle notify_handle; DEBUG(2, ("Received RFFPCNex from %s\n", r->in.local_machine)); /* * TODO: for now just open a connection to the client and drop it again * to keep the w2k3 PrintServer * happy to allow one to open the Add Printer GUI * and the torture suite passing */ if (strncmp(r->in.local_machine, "\\\\", 2)) { return WERR_INVALID_COMPUTERNAME; } binding_string = talloc_asprintf(mem_ctx, "ncacn_np:%s", r->in.local_machine+2); if (binding_string == NULL) { return WERR_NOMEM; } status = dcerpc_parse_binding(mem_ctx, binding_string, &binding); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } creds = cli_credentials_init_anon(mem_ctx); /* FIXME: Use machine credentials instead ? */ status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_spoolss, creds, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx); if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("unable to call back to %s\n", r->in.local_machine)); return WERR_SERVER_UNAVAILABLE; } ZERO_STRUCT(rop); rop.in.server_name = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx); W_ERROR_HAVE_NO_MEMORY(rop.in.server_name); rop.in.printer_local = 0; rop.in.type = REG_NONE; rop.in.bufsize = 0; rop.in.buffer = NULL; rop.out.handle = ¬ify_handle; status = dcerpc_spoolss_ReplyOpenPrinter_r(p->binding_handle, mem_ctx, &rop); if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("unable to open remote printer %s\n", r->in.local_machine)); return WERR_SERVER_UNAVAILABLE; } talloc_free(p); return WERR_OK; }
static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version) { NTSTATUS status; const struct ndr_interface_table *table; struct dcesrv_remote_private *priv; const char *binding = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "binding"); const char *user, *pass, *domain; struct cli_credentials *credentials; bool must_free_credentials = true; bool machine_account; struct dcerpc_binding *b; struct composite_context *pipe_conn_req; machine_account = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "use_machine_account", false); priv = talloc(dce_call->conn, struct dcesrv_remote_private); if (!priv) { return NT_STATUS_NO_MEMORY; } priv->c_pipe = NULL; dce_call->context->private_data = priv; if (!binding) { DEBUG(0,("You must specify a DCE/RPC binding string\n")); return NT_STATUS_INVALID_PARAMETER; } user = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "user"); pass = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "password"); domain = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dceprc_remote", "domain"); table = ndr_table_by_syntax(&iface->syntax_id); if (!table) { dce_call->fault_code = DCERPC_FAULT_UNK_IF; return NT_STATUS_NET_WRITE_FAULT; } if (user && pass) { DEBUG(5, ("dcerpc_remote: RPC Proxy: Using specified account\n")); credentials = cli_credentials_init(priv); if (!credentials) { return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(credentials, dce_call->conn->dce_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, ("dcerpc_remote: RPC Proxy: Using machine account\n")); credentials = cli_credentials_init(priv); cli_credentials_set_conf(credentials, dce_call->conn->dce_ctx->lp_ctx); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } status = cli_credentials_set_machine_account(credentials, dce_call->conn->dce_ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } } else if (dce_call->conn->auth_state.session_info->credentials) { DEBUG(5, ("dcerpc_remote: RPC Proxy: Using delegated credentials\n")); credentials = dce_call->conn->auth_state.session_info->credentials; must_free_credentials = false; } else { DEBUG(1,("dcerpc_remote: RPC Proxy: You must supply binding, user and password or have delegated credentials\n")); return NT_STATUS_INVALID_PARAMETER; } /* parse binding string to the structure */ status = dcerpc_parse_binding(dce_call->context, binding, &b); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding)); return status; } /* If we already have a remote association group ID, then use that */ if (dce_call->context->assoc_group->proxied_id != 0) { status = dcerpc_binding_set_assoc_group_id(b, dce_call->context->assoc_group->proxied_id); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_binding_set_assoc_group_id() - %s'\n", nt_errstr(status))); return status; } } status = dcerpc_binding_set_abstract_syntax(b, &iface->syntax_id); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_binding_set_abstract_syntax() - %s'\n", nt_errstr(status))); return status; } DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(dce_call->context, b))); pipe_conn_req = dcerpc_pipe_connect_b_send(dce_call->context, b, table, credentials, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx); status = dcerpc_pipe_connect_b_recv(pipe_conn_req, dce_call->context, &(priv->c_pipe)); if (must_free_credentials) { talloc_free(credentials); } if (!NT_STATUS_IS_OK(status)) { return status; } if (dce_call->context->assoc_group->proxied_id == 0) { dce_call->context->assoc_group->proxied_id = dcerpc_binding_get_assoc_group_id(priv->c_pipe->binding); } if (!NT_STATUS_IS_OK(status)) { return status; } return NT_STATUS_OK; }
static bool test_parse_check_results(struct torture_context *tctx) { struct dcerpc_binding *b; struct GUID uuid; torture_assert_ntstatus_ok(tctx, GUID_from_string("308FB580-1EB2-11CA-923B-08002B1075A7", &uuid), "parsing uuid"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_np:$SERVER", &b), "parse"); torture_assert(tctx, b->transport == NCACN_NP, "ncacn_np expected"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_ip_tcp:$SERVER", &b), "parse"); torture_assert(tctx, b->transport == NCACN_IP_TCP, "ncacn_ip_tcp expected"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_np:$SERVER[rpcecho]", &b), "parse"); torture_assert_str_equal(tctx, b->endpoint, "rpcecho", "endpoint"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_np:$SERVER[/pipe/rpcecho]", &b), "parse"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_np:$SERVER[/pipe/rpcecho,sign,seal]", &b), "parse"); torture_assert(tctx, b->flags == DCERPC_SIGN+DCERPC_SEAL, "sign+seal flags"); torture_assert_str_equal(tctx, b->endpoint, "/pipe/rpcecho", "endpoint"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_np:$SERVER[,sign]", &b), "parse"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_ip_tcp:$SERVER[,sign]", &b), "parse"); torture_assert(tctx, b->endpoint == NULL, "endpoint"); torture_assert(tctx, b->flags == DCERPC_SIGN, "sign flag"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncalrpc:", &b), "parse"); torture_assert(tctx, b->transport == NCALRPC, "ncalrpc expected"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_np:$SERVER", &b), "parse"); torture_assert(tctx, GUID_equal(&b->object.uuid, &uuid), "object uuid"); torture_assert_int_equal(tctx, b->object.if_version, 0, "object version"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "308FB580-1EB2-11CA-923B-08002B1075A7@ncacn_ip_tcp:$SERVER", &b), "parse"); torture_assert_ntstatus_ok(tctx, dcerpc_parse_binding(tctx, "ncacn_ip_tcp:$SERVER[,sign,localaddress=192.168.1.1]", &b), "parse"); torture_assert(tctx, b->transport == NCACN_IP_TCP, "ncacn_ip_tcp expected"); torture_assert(tctx, b->flags == (DCERPC_SIGN | DCERPC_LOCALADDRESS), "sign flag"); torture_assert_str_equal(tctx, b->localaddress, "192.168.1.1", "localaddress"); torture_assert_str_equal(tctx, "ncacn_ip_tcp:$SERVER[,sign,localaddress=192.168.1.1]", dcerpc_binding_string(tctx, b), "back to string"); return true; }