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; }
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; status = torture_rpc_binding(torture, &binding); if (!NT_STATUS_IS_OK(status)) { return false; } bindstr = dcerpc_binding_string(torture, binding); return torture_rpc_connect(torture, level, bindstr, NULL); }
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; }
/** * open a rpc connection to the chosen binding string */ _PUBLIC_ NTSTATUS torture_rpc_connection_with_binding(struct torture_context *tctx, struct dcerpc_binding *binding, struct dcerpc_pipe **p, const struct ndr_interface_table *table) { NTSTATUS status; dcerpc_init(); status = dcerpc_pipe_connect_b(tctx, p, binding, table, popt_get_cmdline_credentials(), tctx->ev, tctx->lp_ctx); if (NT_STATUS_IS_ERR(status)) { torture_warning(tctx, "Failed to connect to remote server: %s %s\n", dcerpc_binding_string(tctx, binding), nt_errstr(status)); } return status; }
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; }
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; }
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; }
_PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx, const char *machine_name, uint32_t acct_flags, struct cli_credentials **machine_credentials) { NTSTATUS status; struct libnet_context *libnet_ctx; struct libnet_JoinDomain *libnet_r; struct test_join *tj; struct samr_SetUserInfo s; union samr_UserInfo u; const char *binding_str = NULL; struct dcerpc_binding *binding = NULL; enum dcerpc_transport_t transport; tj = talloc_zero(tctx, struct test_join); if (!tj) return NULL; binding_str = torture_setting_string(tctx, "binding", NULL); if (binding_str == NULL) { const char *host = torture_setting_string(tctx, "host", NULL); binding_str = talloc_asprintf(tj, "ncacn_np:%s", host); } status = dcerpc_parse_binding(tj, binding_str, &binding); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_parse_binding(%s) failed - %s\n", binding_str, nt_errstr(status))); talloc_free(tj); return NULL; } transport = dcerpc_binding_get_transport(binding); switch (transport) { case NCALRPC: case NCACN_UNIX_STREAM: break; default: dcerpc_binding_set_transport(binding, NCACN_NP); dcerpc_binding_set_flags(binding, 0, DCERPC_AUTH_OPTIONS); break; } libnet_r = talloc_zero(tj, struct libnet_JoinDomain); if (!libnet_r) { talloc_free(tj); return NULL; } libnet_ctx = libnet_context_init(tctx->ev, tctx->lp_ctx); if (!libnet_ctx) { talloc_free(tj); return NULL; } tj->libnet_r = libnet_r; libnet_ctx->cred = cmdline_credentials; libnet_r->in.binding = dcerpc_binding_string(libnet_r, binding); if (libnet_r->in.binding == NULL) { talloc_free(tj); return NULL; } libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED; libnet_r->in.netbios_name = machine_name; libnet_r->in.account_name = talloc_asprintf(libnet_r, "%s$", machine_name); if (!libnet_r->in.account_name) { talloc_free(tj); return NULL; } libnet_r->in.acct_type = acct_flags; libnet_r->in.recreate_account = true; status = libnet_JoinDomain(libnet_ctx, libnet_r, libnet_r); if (!NT_STATUS_IS_OK(status)) { if (libnet_r->out.error_string) { DEBUG(0, ("Domain join failed - %s\n", libnet_r->out.error_string)); } else { DEBUG(0, ("Domain join failed - %s\n", nt_errstr(status))); } talloc_free(tj); return NULL; } tj->p = libnet_r->out.samr_pipe; tj->user_handle = *libnet_r->out.user_handle; tj->dom_sid = libnet_r->out.domain_sid; talloc_steal(tj, libnet_r->out.domain_sid); tj->dom_netbios_name = libnet_r->out.domain_name; talloc_steal(tj, libnet_r->out.domain_name); tj->dom_dns_name = libnet_r->out.realm; talloc_steal(tj, libnet_r->out.realm); tj->user_guid = libnet_r->out.account_guid; tj->netbios_name = talloc_strdup(tj, machine_name); if (!tj->netbios_name) { talloc_free(tj); return NULL; } ZERO_STRUCT(u); s.in.user_handle = &tj->user_handle; s.in.info = &u; s.in.level = 21; u.info21.fields_present = SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME; u.info21.comment.string = talloc_asprintf(tj, "Tortured by Samba4: %s", timestring(tj, time(NULL))); u.info21.full_name.string = talloc_asprintf(tj, "Torture account for Samba4: %s", timestring(tj, time(NULL))); u.info21.description.string = talloc_asprintf(tj, "Samba4 torture account created by host %s: %s", lpcfg_netbios_name(tctx->lp_ctx), timestring(tj, time(NULL))); status = dcerpc_samr_SetUserInfo_r(tj->p->binding_handle, tj, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(status)); } if (!NT_STATUS_IS_OK(s.out.result)) { printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(s.out.result)); } *machine_credentials = cli_credentials_init(tj); cli_credentials_set_conf(*machine_credentials, tctx->lp_ctx); cli_credentials_set_workstation(*machine_credentials, machine_name, CRED_SPECIFIED); cli_credentials_set_domain(*machine_credentials, libnet_r->out.domain_name, CRED_SPECIFIED); if (libnet_r->out.realm) { cli_credentials_set_realm(*machine_credentials, libnet_r->out.realm, CRED_SPECIFIED); } cli_credentials_set_username(*machine_credentials, libnet_r->in.account_name, CRED_SPECIFIED); cli_credentials_set_password(*machine_credentials, libnet_r->out.join_password, CRED_SPECIFIED); cli_credentials_set_kvno(*machine_credentials, libnet_r->out.kvno); if (acct_flags & ACB_SVRTRUST) { cli_credentials_set_secure_channel_type(*machine_credentials, SEC_CHAN_BDC); } else if (acct_flags & ACB_WSTRUST) { cli_credentials_set_secure_channel_type(*machine_credentials, SEC_CHAN_WKSTA); } else { DEBUG(0, ("Invalid account type specificed to torture_join_domain\n")); talloc_free(*machine_credentials); return NULL; } return tj; }
bool torture_rpc_mgmt(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx, *loop_ctx; bool ret = true; const struct ndr_interface_list *l; struct dcerpc_binding *b; mem_ctx = talloc_init("torture_rpc_mgmt"); status = torture_rpc_binding(torture, &b); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return false; } for (l=ndr_table_list();l;l=l->next) { loop_ctx = talloc_named(mem_ctx, 0, "torture_rpc_mgmt 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); status = dcerpc_epm_map_binding(loop_ctx, b, l->table, NULL, torture->lp_ctx); 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; } lp_set_cmdline(torture->lp_ctx, "torture:binding", dcerpc_binding_string(loop_ctx, b)); status = torture_rpc_connection(torture, &p, &ndr_table_mgmt); if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { printf("Interface not available - skipping\n"); talloc_free(loop_ctx); continue; } if (!NT_STATUS_IS_OK(status)) { talloc_free(loop_ctx); ret = false; continue; } if (!test_is_server_listening(p, loop_ctx)) { ret = false; } if (!test_stop_server_listening(p, loop_ctx)) { ret = false; } if (!test_inq_stats(p, loop_ctx)) { ret = false; } if (!test_inq_princ_name(p, loop_ctx)) { ret = false; } if (!test_inq_if_ids(torture, p, loop_ctx, NULL, NULL)) { ret = false; } } return ret; }