This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "libcli/raw/libcliraw.h"
+#include "libcli/rap/rap.h"
#include "torture/torture.h"
#include "torture/util.h"
+#include "torture/rap/proto.h"
#include "librpc/gen_ndr/ndr_lsa.h"
#include "librpc/gen_ndr/ndr_lsa_c.h"
#include "librpc/gen_ndr/ndr_samr.h"
#include "librpc/gen_ndr/ndr_netlogon_c.h"
#include "librpc/gen_ndr/ndr_srvsvc.h"
#include "librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "librpc/gen_ndr/ndr_spoolss.h"
+#include "librpc/gen_ndr/ndr_spoolss_c.h"
+#include "librpc/gen_ndr/ndr_winreg.h"
+#include "librpc/gen_ndr/ndr_winreg_c.h"
+#include "librpc/gen_ndr/ndr_wkssvc.h"
+#include "librpc/gen_ndr/ndr_wkssvc_c.h"
#include "lib/cmdline/popt_common.h"
#include "librpc/rpc/dcerpc.h"
#include "torture/rpc/rpc.h"
#include "libcli/composite/composite.h"
#include "libcli/smb_composite/smb_composite.h"
#include "libcli/auth/libcli_auth.h"
-#include "libcli/auth/credentials.h"
#include "lib/crypto/crypto.h"
#include "libcli/security/proto.h"
struct lsa_ObjectAttribute objectattr;
struct lsa_OpenPolicy2 openpolicy;
struct policy_handle handle;
- struct lsa_Close close;
+ struct lsa_Close close_handle;
struct smbcli_session *tmp;
struct smbcli_session *session2;
struct smbcli_state *cli;
}
status = smbcli_full_connection(mem_ctx, &cli,
- lp_parm_string(-1, "torture", "host"),
+ torture_setting_string(torture, "host", NULL),
"IPC$", NULL, cmdline_credentials,
NULL);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
- status = dcerpc_pipe_open_smb(lsa_pipe->conn, cli->tree, "\\lsarpc");
+ status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
goto done;
}
- close.in.handle = &handle;
- close.out.handle = &handle;
+ close_handle.in.handle = &handle;
+ close_handle.out.handle = &handle;
- status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close);
+ status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close_handle);
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_lsa_Close failed: %s\n",
nt_errstr(status));
nt_errstr(status));
goto done;
}
+ session2->vuid = setup.out.vuid;
tmp = cli->tree->session;
cli->tree->session = session2;
struct lsa_OpenPolicy2 openpolicy;
struct lsa_QueryInfoPolicy query;
struct policy_handle handle;
- struct lsa_Close close;
+ struct lsa_Close close_handle;
if ((mem_ctx = talloc_init("bindtest")) == NULL) {
d_printf("talloc_init failed\n");
goto done;
}
- status = dcerpc_pipe_open_smb(lsa_pipe->conn, cli->tree, "\\lsarpc");
+ status = dcerpc_pipe_open_smb(lsa_pipe, cli->tree, "\\lsarpc");
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
goto done;
}
- close.in.handle = &handle;
- close.out.handle = &handle;
+ close_handle.in.handle = &handle;
+ close_handle.out.handle = &handle;
- status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close);
+ status = dcerpc_lsa_Close(lsa_pipe, mem_ctx, &close_handle);
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_lsa_Close failed: %s\n",
nt_errstr(status));
}
status = smbcli_full_connection(mem_ctx, &cli,
- lp_parm_string(-1, "torture", "host"),
+ torture_setting_string(torture, "host", NULL),
"IPC$", NULL, cmdline_credentials,
NULL);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- status = dcerpc_pipe_open_smb(samr_pipe->conn, cli->tree, "\\samr");
+ status = dcerpc_pipe_open_smb(samr_pipe, cli->tree, "\\samr");
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
union samr_UserInfo u_info;
DATA_BLOB session_key;
- encode_pw_buffer(u_info.info24.password.data, password,
+
+ ZERO_STRUCT(u_info);
+ encode_pw_buffer(u_info.info23.password.data, password,
STR_UNICODE);
- u_info.info24.pw_len = strlen_m(password)*2;
status = dcerpc_fetch_session_key(samr_pipe, &session_key);
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_fetch_session_key failed\n");
goto done;
}
- arcfour_crypt_blob(u_info.info24.password.data, 516,
+ arcfour_crypt_blob(u_info.info23.password.data, 516,
&session_key);
+ u_info.info23.info.password_expired = 0;
+ u_info.info23.info.fields_present = SAMR_FIELD_PASSWORD |
+ SAMR_FIELD_PASSWORD2 |
+ SAMR_FIELD_EXPIRED_FLAG;
sui2.in.user_handle = wks_handle;
sui2.in.info = &u_info;
- sui2.in.level = 24;
+ sui2.in.level = 23;
status = dcerpc_samr_SetUserInfo2(samr_pipe, tmp_ctx, &sui2);
if (!NT_STATUS_IS_OK(status)) {
- d_printf("samr_SetUserInfo(24) failed: %s\n",
+ d_printf("samr_SetUserInfo(23) failed: %s\n",
nt_errstr(status));
goto done;
}
qui.out.info->info21.force_password_change = 0;
qui.out.info->info21.account_name.string = NULL;
qui.out.info->info21.rid = 0;
+ qui.out.info->info21.acct_expiry = 0;
qui.out.info->info21.fields_present = 0x81827fa; /* copy usrmgr.exe */
u_info.info21 = qui.out.info->info21;
goto done;
}
- status = dcerpc_pipe_open_smb(net_pipe->conn, cli->tree, "\\netlogon");
+ status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
goto done;
}
- status = dcerpc_pipe_open_smb(net_pipe->conn, cli->tree, "\\netlogon");
+ status = dcerpc_pipe_open_smb(net_pipe, cli->tree, "\\netlogon");
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
const char *wks_name;
int i;
- wks_name = lp_parm_string(-1, "torture", "wksname");
+ wks_name = torture_setting_string(torture, "wksname", NULL);
if (wks_name == NULL) {
wks_name = get_myname();
}
- mem_ctx = talloc_init("torture_bind_authcontext");
+ mem_ctx = talloc_init("torture_netlogon_samba3");
if (mem_ctx == NULL) {
d_printf("talloc_init failed\n");
}
status = smbcli_full_connection(mem_ctx, &cli,
- lp_parm_string(-1, "torture", "host"),
+ torture_setting_string(torture, "host", NULL),
"IPC$", NULL, anon_creds, NULL);
if (!NT_STATUS_IS_OK(status)) {
d_printf("smbcli_full_connection failed: %s\n",
struct cli_credentials *anon_creds;
const char *wks_name;
- wks_name = lp_parm_string(-1, "torture", "wksname");
- if (wks_name == NULL) {
- wks_name = get_myname();
- }
+ wks_name = torture_setting_string(torture, "wksname", get_myname());
mem_ctx = talloc_init("torture_samba3_sessionkey");
ret = True;
- if (!lp_parm_bool(-1, "target", "samba3", False)) {
+ if (!torture_setting_bool(torture, "samba3", False)) {
/* Samba3 in the build farm right now does this happily. Need
* to fix :-) */
* open pipe and bind, given an IPC$ context
*/
-static struct dcerpc_pipe *pipe_bind_smb(TALLOC_CTX *mem_ctx,
- struct smbcli_tree *tree,
- const char *pipe_name,
- const struct dcerpc_interface_table *iface)
+static NTSTATUS pipe_bind_smb(TALLOC_CTX *mem_ctx,
+ struct smbcli_tree *tree,
+ const char *pipe_name,
+ const struct dcerpc_interface_table *iface,
+ struct dcerpc_pipe **p)
{
struct dcerpc_pipe *result;
NTSTATUS status;
if (!(result = dcerpc_pipe_init(
mem_ctx, tree->session->transport->socket->event.ctx))) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
- status = dcerpc_pipe_open_smb(result->conn, tree, pipe_name);
+ status = dcerpc_pipe_open_smb(result, tree, pipe_name);
if (!NT_STATUS_IS_OK(status)) {
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
talloc_free(result);
- return NULL;
+ return status;
}
status = dcerpc_bind_auth_none(result, iface);
if (!NT_STATUS_IS_OK(status)) {
d_printf("schannel bind failed: %s\n", nt_errstr(status));
talloc_free(result);
- return NULL;
+ return status;
}
- return result;
+ *p = result;
+ return NT_STATUS_OK;
}
/*
status = dcerpc_lsa_LookupNames(p, tmp_ctx, &l);
if (!NT_STATUS_IS_OK(status)) {
- printf("LookupNames failed - %s\n", nt_errstr(status));
+ printf("LookupNames of %s failed - %s\n", lsa_name.string,
+ nt_errstr(status));
talloc_free(tmp_ctx);
- return False;
+ return NULL;
}
result = dom_sid_add_rid(mem_ctx, l.out.domains->domains[0].sid,
struct lsa_StringPointer authority_name_p;
struct dom_sid *result;
- if (!(lsa = pipe_bind_smb(mem_ctx, tree, "\\pipe\\lsarpc",
- &dcerpc_table_lsarpc))) {
- d_printf("Could not bind to LSA\n");
+ status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\lsarpc",
+ &dcerpc_table_lsarpc, &lsa);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) Could not bind to LSA: %s\n",
+ __location__, nt_errstr(status));
return NULL;
}
status = dcerpc_lsa_GetUserName(lsa, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
- printf("GetUserName failed - %s\n", nt_errstr(status));
+ printf("(%s) GetUserName failed - %s\n",
+ __location__, nt_errstr(status));
talloc_free(lsa);
return NULL;
}
status = smb_raw_tcon(result, tmp_ctx, &tcon);
if (!NT_STATUS_IS_OK(status)) {
- d_printf("smb_raw_tcon failed: %s\n", nt_errstr(status));
+ d_printf("(%s) smb_raw_tcon failed: %s\n", __location__,
+ nt_errstr(status));
talloc_free(tmp_ctx);
return status;
}
}
status = smbcli_full_connection(
- mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
"IPC$", NULL, cmdline_credentials, NULL);
if (!NT_STATUS_IS_OK(status)) {
- d_printf("smbcli_full_connection failed: %s\n",
- nt_errstr(status));
+ d_printf("(%s) smbcli_full_connection failed: %s\n",
+ __location__, nt_errstr(status));
ret = False;
goto done;
}
if (!(user_sid = whoami(mem_ctx, cli->tree))) {
- d_printf("whoami on auth'ed connection failed\n");
+ d_printf("(%s) whoami on auth'ed connection failed\n",
+ __location__);
ret = False;
}
talloc_free(cli);
if (!(anon_creds = create_anon_creds(mem_ctx))) {
- d_printf("create_anon_creds failed\n");
+ d_printf("(%s) create_anon_creds failed\n", __location__);
ret = False;
goto done;
}
status = smbcli_full_connection(
- mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
"IPC$", NULL, anon_creds, NULL);
if (!NT_STATUS_IS_OK(status)) {
- d_printf("anon smbcli_full_connection failed: %s\n",
- nt_errstr(status));
+ d_printf("(%s) anon smbcli_full_connection failed: %s\n",
+ __location__, nt_errstr(status));
ret = False;
goto done;
}
if (!(user_sid = whoami(mem_ctx, cli->tree))) {
- d_printf("whoami on anon connection failed\n");
+ d_printf("(%s) whoami on anon connection failed\n",
+ __location__);
ret = False;
goto done;
}
if (!dom_sid_equal(user_sid,
dom_sid_parse_talloc(mem_ctx, "s-1-5-7"))) {
- d_printf("Anon lsa_GetUserName returned %s, expected S-1-5-7",
+ d_printf("(%s) Anon lsa_GetUserName returned %s, expected "
+ "S-1-5-7", __location__,
dom_sid_string(mem_ctx, user_sid));
ret = False;
}
if (!(user_creds = cli_credentials_init(mem_ctx))) {
- d_printf("cli_credentials_init failed\n");
+ d_printf("(%s) cli_credentials_init failed\n", __location__);
ret = False;
goto done;
}
cli_credentials_get_username(user_creds),
cli_credentials_get_password(user_creds),
&domain_name, &created_sid)) {
- d_printf("create_user failed\n");
+ d_printf("(%s) create_user failed\n", __location__);
ret = False;
goto done;
}
session2 = smbcli_session_init(cli->transport, mem_ctx, False);
if (session2 == NULL) {
- d_printf("smbcli_session_init failed\n");
+ d_printf("(%s) smbcli_session_init failed\n",
+ __location__);
goto done;
}
status = smb_composite_sesssetup(session2, &setup);
if (!NT_STATUS_IS_OK(status)) {
- d_printf("anon session setup failed: %s\n",
- nt_errstr(status));
+ d_printf("(%s) session setup with new user failed: "
+ "%s\n", __location__, nt_errstr(status));
ret = False;
goto done;
}
+ session2->vuid = setup.out.vuid;
if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx, session2,
"IPC$", &tree))) {
- d_printf("secondary_tcon failed\n");
+ d_printf("(%s) secondary_tcon failed\n",
+ __location__);
ret = False;
goto done;
}
if (!(user_sid = whoami(mem_ctx, tree))) {
- d_printf("whoami on user connection failed\n");
+ d_printf("(%s) whoami on user connection failed\n",
+ __location__);
ret = False;
goto delete;
}
delete:
if (!delete_user(cli, cmdline_credentials,
cli_credentials_get_username(user_creds))) {
- d_printf("delete_user failed\n");
+ d_printf("(%s) delete_user failed\n", __location__);
ret = False;
}
BOOL ret = True;
const char *sharename = NULL;
struct smbcli_state *cli;
+ NTSTATUS status;
if (!(mem_ctx = talloc_new(torture))) {
return False;
}
if (!(torture_open_connection_share(
- mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
"IPC$", NULL))) {
talloc_free(mem_ctx);
return False;
}
- if (!(p = pipe_bind_smb(mem_ctx, cli->tree, "\\pipe\\srvsvc",
- &dcerpc_table_srvsvc))) {
- d_printf("could not bind to srvsvc pipe\n");
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\pipe\\srvsvc",
+ &dcerpc_table_srvsvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) could not bind to srvsvc pipe: %s\n",
+ __location__, nt_errstr(status));
ret = False;
goto done;
}
return NULL;
}
- if (!(p = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
- &dcerpc_table_srvsvc))) {
- d_printf("could not bind to srvsvc pipe\n");
+ status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
+ &dcerpc_table_srvsvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) could not bind to srvsvc pipe: %s\n",
+ __location__, nt_errstr(status));
talloc_free(tmp_ctx);
return NULL;
}
return NT_STATUS_UNSUCCESSFUL;
}
- if (!(p = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
- &dcerpc_table_srvsvc))) {
- d_printf("could not bind to srvsvc pipe\n");
+ status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
+ &dcerpc_table_srvsvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) could not bind to srvsvc pipe: %s\n",
+ __location__, nt_errstr(status));
talloc_free(tmp_ctx);
return NT_STATUS_UNSUCCESSFUL;
}
struct security_descriptor *orig_sd,
struct smbcli_session *session,
const char *sharename, const struct dom_sid *user_sid,
- unsigned int access, NTSTATUS expected_tcon,
+ unsigned int access_mask, NTSTATUS expected_tcon,
NTSTATUS expected_mkdir)
{
TALLOC_CTX *tmp_ctx;
dom_sid_string(mem_ctx, dom_sid_add_rid(mem_ctx, domain_sid,
DOMAIN_RID_USERS)),
dom_sid_string(mem_ctx, user_sid),
- SEC_ACE_TYPE_ACCESS_ALLOWED, access, 0, NULL);
+ SEC_ACE_TYPE_ACCESS_ALLOWED, access_mask, 0, NULL);
if (sd == NULL) {
d_printf("security_descriptor_create failed\n");
talloc_free(tmp_ctx);
status = smbcli_mkdir(tree, "sharesec_testdir");
if (!NT_STATUS_EQUAL(status, expected_mkdir)) {
- d_printf("Expected %s, got %s\n", nt_errstr(expected_mkdir),
- nt_errstr(status));
+ d_printf("(%s) Expected %s, got %s\n", __location__,
+ nt_errstr(expected_mkdir), nt_errstr(status));
ret = False;
}
}
if (!(torture_open_connection_share(
- mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
"IPC$", NULL))) {
d_printf("IPC$ connection failed\n");
talloc_free(mem_ctx);
return False;
}
- sd = get_sharesec(mem_ctx, cli->session, lp_parm_string(-1, "torture",
- "share"));
+ sd = get_sharesec(mem_ctx, cli->session, torture_setting_string(torture,
+ "share", NULL));
ret &= try_tcon(mem_ctx, sd, cli->session,
- lp_parm_string(-1, "torture", "share"),
+ torture_setting_string(torture, "share", NULL),
user_sid, 0, NT_STATUS_ACCESS_DENIED, NT_STATUS_OK);
ret &= try_tcon(mem_ctx, sd, cli->session,
- lp_parm_string(-1, "torture", "share"),
+ torture_setting_string(torture, "share", NULL),
user_sid, SEC_FILE_READ_DATA, NT_STATUS_OK,
- NT_STATUS_NETWORK_ACCESS_DENIED);
+ NT_STATUS_MEDIA_WRITE_PROTECTED);
ret &= try_tcon(mem_ctx, sd, cli->session,
- lp_parm_string(-1, "torture", "share"),
+ torture_setting_string(torture, "share", NULL),
user_sid, SEC_FILE_ALL, NT_STATUS_OK, NT_STATUS_OK);
talloc_free(mem_ctx);
return ret;
}
+
+BOOL torture_samba3_rpc_lsa(struct torture_context *torture)
+{
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = True;
+ struct smbcli_state *cli;
+ struct dcerpc_pipe *p;
+ struct policy_handle lsa_handle;
+ NTSTATUS status;
+ struct dom_sid *domain_sid;
+
+ if (!(mem_ctx = talloc_new(torture))) {
+ return False;
+ }
+
+ if (!(torture_open_connection_share(
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
+ "IPC$", NULL))) {
+ d_printf("IPC$ connection failed\n");
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\lsarpc",
+ &dcerpc_table_lsarpc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
+ nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ {
+ struct lsa_ObjectAttribute attr;
+ struct lsa_OpenPolicy2 o;
+ o.in.system_name = talloc_asprintf(
+ mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ ZERO_STRUCT(attr);
+ o.in.attr = &attr;
+ o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ o.out.handle = &lsa_handle;
+ status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &o);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_lsa_OpenPolicy2 failed: %s\n",
+ __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+#if 0
+ p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
+#endif
+
+ {
+ int i;
+ int levels[] = { 2,3,5,6 };
+
+ for (i=0; i<ARRAY_SIZE(levels); i++) {
+ struct lsa_QueryInfoPolicy r;
+ r.in.handle = &lsa_handle;
+ r.in.level = levels[i];
+ status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_lsa_QueryInfoPolicy %d "
+ "failed: %s\n", __location__,
+ levels[i], nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ if (levels[i] == 5) {
+ domain_sid = r.out.info->account_domain.sid;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static NTSTATUS get_servername(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree,
+ char **name)
+{
+ struct rap_WserverGetInfo r;
+ NTSTATUS status;
+ char servername[17];
+
+ r.in.level = 0;
+ r.in.bufsize = 0xffff;
+
+ status = smbcli_rap_netservergetinfo(tree, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ memcpy(servername, r.out.info.info0.name, 16);
+ servername[16] = '\0';
+
+ if (pull_ascii_talloc(mem_ctx, name, servername) < 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS find_printers(TALLOC_CTX *ctx, struct smbcli_tree *tree,
+ const char ***printers, int *num_printers)
+{
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ struct dcerpc_pipe *p;
+ struct srvsvc_NetShareEnum r;
+ struct srvsvc_NetShareCtr1 c1_in;
+ struct srvsvc_NetShareCtr1 *c1;
+ int i;
+
+ mem_ctx = talloc_new(ctx);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = pipe_bind_smb(mem_ctx, tree, "\\srvsvc", &dcerpc_table_srvsvc,
+ &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("could not bind to srvsvc pipe\n");
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ r.in.server_unc = talloc_asprintf(
+ mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ r.in.level = 1;
+ ZERO_STRUCT(c1_in);
+ r.in.ctr.ctr1 = &c1_in;
+ r.in.max_buffer = (uint32_t)-1;
+ r.in.resume_handle = NULL;
+
+ status = dcerpc_srvsvc_NetShareEnum(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("NetShareEnum level %u failed - %s\n",
+ r.in.level, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ *printers = NULL;
+ *num_printers = 0;
+ c1 = r.out.ctr.ctr1;
+ for (i=0; i<c1->count; i++) {
+ if (c1->array[i].type != STYPE_PRINTQ) {
+ continue;
+ }
+ if (!add_string_to_array(ctx, c1->array[i].name,
+ printers, num_printers)) {
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+}
+
+static BOOL enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe,
+ const char *servername, int level, int *num_printers)
+{
+ struct spoolss_EnumPrinters r;
+ NTSTATUS status;
+ DATA_BLOB blob;
+
+ r.in.flags = PRINTER_ENUM_LOCAL;
+ r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", servername);
+ r.in.level = level;
+ r.in.buffer = NULL;
+ r.in.offered = 0;
+
+ status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s\n",
+ __location__, nt_errstr(status));
+ return False;
+ }
+
+ if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+ d_printf("(%s) EnumPrinters unexpected return code %s, should "
+ "be WERR_INSUFFICIENT_BUFFER\n", __location__,
+ win_errstr(r.out.result));
+ return False;
+ }
+
+ blob = data_blob_talloc_zero(mem_ctx, r.out.needed);
+ if (blob.data == NULL) {
+ d_printf("(%s) data_blob_talloc failed\n", __location__);
+ return False;
+ }
+
+ r.in.buffer = &blob;
+ r.in.offered = r.out.needed;
+
+ status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_spoolss_EnumPrinters failed: %s, "
+ "%s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ return False;
+ }
+
+ *num_printers = r.out.count;
+
+ return True;
+}
+
+static NTSTATUS getprinterinfo(TALLOC_CTX *ctx, struct dcerpc_pipe *pipe,
+ struct policy_handle *handle, int level,
+ union spoolss_PrinterInfo **res)
+{
+ TALLOC_CTX *mem_ctx;
+ struct spoolss_GetPrinter r;
+ DATA_BLOB blob;
+ NTSTATUS status;
+
+ mem_ctx = talloc_new(ctx);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ r.in.handle = handle;
+ r.in.level = level;
+ r.in.buffer = NULL;
+ r.in.offered = 0;
+
+ status = dcerpc_spoolss_GetPrinter(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s\n",
+ __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+ printf("GetPrinter unexpected return code %s, should "
+ "be WERR_INSUFFICIENT_BUFFER\n",
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ r.in.handle = handle;
+ r.in.level = level;
+ blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
+ if (blob.data == NULL) {
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ memset(blob.data, 0, blob.length);
+ r.in.buffer = &blob;
+ r.in.offered = r.out.needed;
+
+ status = dcerpc_spoolss_GetPrinter(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s, "
+ "%s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return NT_STATUS_IS_OK(status) ?
+ NT_STATUS_UNSUCCESSFUL : status;
+ }
+
+ if (res != NULL) {
+ *res = talloc_steal(ctx, r.out.info);
+ }
+
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+}
+
+BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
+{
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = True;
+ struct smbcli_state *cli;
+ struct dcerpc_pipe *p;
+ NTSTATUS status;
+ struct policy_handle server_handle, printer_handle;
+ const char **printers;
+ int num_printers;
+ struct spoolss_UserLevel1 userlevel1;
+ char *servername;
+
+ if (!(mem_ctx = talloc_new(torture))) {
+ return False;
+ }
+
+ if (!(torture_open_connection_share(
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
+ "IPC$", NULL))) {
+ d_printf("IPC$ connection failed\n");
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = get_servername(mem_ctx, cli->tree, &servername);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "(%s) get_servername returned %s\n",
+ __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (!NT_STATUS_IS_OK(find_printers(mem_ctx, cli->tree,
+ &printers, &num_printers))) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (num_printers == 0) {
+ d_printf("Did not find printers\n");
+ talloc_free(mem_ctx);
+ return True;
+ }
+
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\spoolss",
+ &dcerpc_table_spoolss, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
+ nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ ZERO_STRUCT(userlevel1);
+ userlevel1.client = talloc_asprintf(
+ mem_ctx, "\\\\%s", lp_netbios_name());
+ userlevel1.user = cli_credentials_get_username(cmdline_credentials);
+ userlevel1.build = 2600;
+ userlevel1.major = 3;
+ userlevel1.minor = 0;
+ userlevel1.processor = 0;
+
+ {
+ struct spoolss_OpenPrinterEx r;
+
+ ZERO_STRUCT(r);
+ r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s",
+ servername);
+ r.in.datatype = NULL;
+ r.in.access_mask = 0;
+ r.in.level = 1;
+ r.in.userlevel.level1 = &userlevel1;
+ r.out.handle = &server_handle;
+
+ status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
+ "%s, %s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ struct spoolss_ClosePrinter r;
+
+ r.in.handle = &server_handle;
+ r.out.handle = &server_handle;
+
+ status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
+ "%s, %s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ struct spoolss_OpenPrinterEx r;
+
+ ZERO_STRUCT(r);
+ r.in.printername = talloc_asprintf(
+ mem_ctx, "\\\\%s\\%s", servername, printers[0]);
+ r.in.datatype = NULL;
+ r.in.access_mask = 0;
+ r.in.level = 1;
+ r.in.userlevel.level1 = &userlevel1;
+ r.out.handle = &printer_handle;
+
+ status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
+ "%s, %s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ int i;
+
+ for (i=0; i<8; i++) {
+ status = getprinterinfo(mem_ctx, p, &printer_handle,
+ i, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) getprinterinfo %d failed: %s\n",
+ __location__, i, nt_errstr(status));
+ ret = False;
+ }
+ }
+ }
+
+ {
+ struct spoolss_ClosePrinter r;
+
+ r.in.handle = &printer_handle;
+ r.out.handle = &printer_handle;
+
+ status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
+ "%s\n", __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ int num_enumerated;
+ if (!enumprinters(mem_ctx, p, servername, 1,
+ &num_enumerated)) {
+ d_printf("(%s) enumprinters failed\n", __location__);
+ talloc_free(mem_ctx);
+ return False;
+ }
+ if (num_printers != num_enumerated) {
+ d_printf("(%s) netshareenum gave %d printers, "
+ "enumprinters lvl 1 gave %d\n", __location__,
+ num_printers, num_enumerated);
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ int num_enumerated;
+ if (!enumprinters(mem_ctx, p, servername, 2,
+ &num_enumerated)) {
+ d_printf("(%s) enumprinters failed\n", __location__);
+ talloc_free(mem_ctx);
+ return False;
+ }
+ if (num_printers != num_enumerated) {
+ d_printf("(%s) netshareenum gave %d printers, "
+ "enumprinters lvl 2 gave %d\n", __location__,
+ num_printers, num_enumerated);
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+BOOL torture_samba3_rpc_wkssvc(struct torture_context *torture)
+{
+ TALLOC_CTX *mem_ctx;
+ struct smbcli_state *cli;
+ struct dcerpc_pipe *p;
+ NTSTATUS status;
+ char *servername;
+
+ if (!(mem_ctx = talloc_new(torture))) {
+ return False;
+ }
+
+ if (!(torture_open_connection_share(
+ mem_ctx, &cli, torture_setting_string(torture, "host", NULL),
+ "IPC$", NULL))) {
+ d_printf("IPC$ connection failed\n");
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = get_servername(mem_ctx, cli->tree, &servername);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "(%s) get_servername returned %s\n",
+ __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\wkssvc",
+ &dcerpc_table_wkssvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
+ nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ {
+ struct wkssvc_NetWkstaInfo100 wks100;
+ union wkssvc_NetWkstaInfo info;
+ struct wkssvc_NetWkstaGetInfo r;
+
+ r.in.server_name = "\\foo";
+ r.in.level = 100;
+ info.info100 = &wks100;
+ r.out.info = &info;
+
+ status = dcerpc_wkssvc_NetWkstaGetInfo(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_wkssvc_NetWksGetInfo failed: "
+ "%s, %s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (strcmp(servername,
+ r.out.info->info100->server_name) != 0) {
+ d_printf("(%s) servername inconsistency: RAP=%s, "
+ "dcerpc_wkssvc_NetWksGetInfo=%s",
+ __location__, servername,
+ r.out.info->info100->server_name);
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ talloc_free(mem_ctx);
+ return True;
+}
+
+static NTSTATUS winreg_close(struct dcerpc_pipe *p,
+ struct policy_handle *handle)
+{
+ struct winreg_CloseKey c;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+
+ c.in.handle = c.out.handle = handle;
+
+ if (!(mem_ctx = talloc_new(p))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = dcerpc_winreg_CloseKey(p, mem_ctx, &c);
+ talloc_free(mem_ctx);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!W_ERROR_IS_OK(c.out.result)) {
+ return werror_to_ntstatus(c.out.result);
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS enumvalues(struct dcerpc_pipe *p, struct policy_handle *handle,
+ TALLOC_CTX *mem_ctx)
+{
+ uint32_t enum_index = 0;
+
+ while (1) {
+ struct winreg_EnumValue r;
+ struct winreg_StringBuf name;
+ enum winreg_Type type = 0;
+ uint8_t buf8[1024];
+ NTSTATUS status;
+ uint32_t size, length;
+
+ r.in.handle = handle;
+ r.in.enum_index = enum_index;
+ name.name = "";
+ name.size = 1024;
+ r.in.name = r.out.name = &name;
+ size = 1024;
+ length = 5;
+ r.in.type = &type;
+ r.in.value = buf8;
+ r.in.size = &size;
+ r.in.length = &length;
+
+ status = dcerpc_winreg_EnumValue(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ return NT_STATUS_OK;
+ }
+ enum_index += 1;
+ }
+}
+
+static NTSTATUS enumkeys(struct dcerpc_pipe *p, struct policy_handle *handle,
+ TALLOC_CTX *mem_ctx, int depth)
+{
+ struct winreg_EnumKey r;
+ struct winreg_StringBuf class, name;
+ NTSTATUS status;
+ NTTIME t = 0;
+
+ if (depth <= 0) {
+ return NT_STATUS_OK;
+ }
+
+ class.name = "";
+ class.size = 1024;
+
+ r.in.handle = handle;
+ r.in.enum_index = 0;
+ r.in.name = &name;
+ r.in.keyclass = &class;
+ r.out.name = &name;
+ r.in.last_changed_time = &t;
+
+ do {
+ TALLOC_CTX *tmp_ctx;
+ struct winreg_OpenKey o;
+ struct policy_handle key_handle;
+ int i;
+
+ if (!(tmp_ctx = talloc_new(mem_ctx))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ name.name = NULL;
+ name.size = 1024;
+
+ status = dcerpc_winreg_EnumKey(p, tmp_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ /* We're done enumerating */
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+ }
+
+ for (i=0; i<10-depth; i++)
+ printf(" ");
+ printf("%s\n", r.out.name->name);
+
+
+ o.in.parent_handle = handle;
+ o.in.keyname.name = r.out.name->name;
+ o.in.unknown = 0;
+ o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ o.out.handle = &key_handle;
+
+ status = dcerpc_winreg_OpenKey(p, tmp_ctx, &o);
+ if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(o.out.result)) {
+ enumkeys(p, &key_handle, tmp_ctx, depth-1);
+ enumvalues(p, &key_handle, tmp_ctx);
+ status = winreg_close(p, &key_handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ talloc_free(tmp_ctx);
+
+ r.in.enum_index += 1;
+ } while(True);
+
+ return NT_STATUS_OK;
+}
+
+typedef NTSTATUS (*winreg_open_fn)(struct dcerpc_pipe *, TALLOC_CTX *, void *);
+
+static BOOL test_Open3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+ const char *name, winreg_open_fn open_fn)
+{
+ struct policy_handle handle;
+ struct winreg_OpenHKLM r;
+ NTSTATUS status;
+
+ r.in.system_name = 0;
+ r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ r.out.handle = &handle;
+
+ status = open_fn(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) %s failed: %s, %s\n", __location__, name,
+ nt_errstr(status), win_errstr(r.out.result));
+ return False;
+ }
+
+ enumkeys(p, &handle, mem_ctx, 4);
+
+ status = winreg_close(p, &handle);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_CloseKey failed: %s\n",
+ __location__, nt_errstr(status));
+ return False;
+ }
+
+ return True;
+}
+
+BOOL torture_samba3_rpc_winreg(struct torture_context *torture)
+{
+ NTSTATUS status;
+ struct dcerpc_pipe *p;
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = True;
+ struct {
+ const char *name;
+ winreg_open_fn fn;
+ } open_fns[] = {
+ {"OpenHKLM", (winreg_open_fn)dcerpc_winreg_OpenHKLM },
+ {"OpenHKU", (winreg_open_fn)dcerpc_winreg_OpenHKU },
+ {"OpenHKPD", (winreg_open_fn)dcerpc_winreg_OpenHKPD },
+ {"OpenHKPT", (winreg_open_fn)dcerpc_winreg_OpenHKPT },
+ {"OpenHKCR", (winreg_open_fn)dcerpc_winreg_OpenHKCR }};
+#if 0
+ int i;
+#endif
+
+ mem_ctx = talloc_init("torture_rpc_winreg");
+
+ status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_winreg);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+#if 1
+ ret = test_Open3(p, mem_ctx, open_fns[0].name, open_fns[0].fn);
+#else
+ for (i = 0; i < ARRAY_SIZE(open_fns); i++) {
+ if (!test_Open3(p, mem_ctx, open_fns[i].name, open_fns[i].fn))
+ ret = False;
+ }
+#endif
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}