diff options
Diffstat (limited to 'source4/torture/rpc')
-rw-r--r-- | source4/torture/rpc/rpc.c | 2 | ||||
-rw-r--r-- | source4/torture/rpc/samba3rpc.c | 286 |
2 files changed, 265 insertions, 23 deletions
diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c index eaa2932587..f22c206cad 100644 --- a/source4/torture/rpc/rpc.c +++ b/source4/torture/rpc/rpc.c @@ -130,6 +130,8 @@ NTSTATUS torture_rpc_init(void) register_torture_op("RPC-NETLOGSAMBA3", torture_netlogon_samba3); register_torture_op("RPC-SAMBA3SESSIONKEY", torture_samba3_sessionkey); register_torture_op("RPC-SAMBA3-SRVSVC", torture_samba3_rpc_srvsvc); + register_torture_op("RPC-SAMBA3-GETUSERNAME", + torture_samba3_rpc_getusername); register_torture_op("RPC-DRSUAPI", torture_rpc_drsuapi); register_torture_op("RPC-CRACKNAMES", torture_rpc_drsuapi_cracknames); register_torture_op("RPC-ROT", torture_rpc_rot); diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 6bc8fe6d4b..9d69a1709a 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -21,7 +21,9 @@ */ #include "includes.h" +#include "libcli/raw/libcliraw.h" #include "torture/torture.h" +#include "torture/util.h" #include "librpc/gen_ndr/ndr_lsa.h" #include "librpc/gen_ndr/ndr_lsa_c.h" #include "librpc/gen_ndr/ndr_samr.h" @@ -39,6 +41,21 @@ #include "libcli/auth/libcli_auth.h" #include "libcli/auth/credentials.h" #include "lib/crypto/crypto.h" +#include "libcli/security/proto.h" + +static struct cli_credentials *create_anon_creds(TALLOC_CTX *mem_ctx) +{ + struct cli_credentials *result; + + if (!(result = cli_credentials_init(mem_ctx))) { + return NULL; + } + + cli_credentials_set_conf(result); + cli_credentials_set_anonymous(result); + + return result; +} /* * This tests a RPC call using an invalid vuid @@ -128,15 +145,11 @@ BOOL torture_bind_authcontext(struct torture_context *torture) goto done; } - anon_creds = cli_credentials_init(mem_ctx); - if (anon_creds == NULL) { - d_printf("cli_credentials_init failed\n"); + if (!(anon_creds = create_anon_creds(mem_ctx))) { + d_printf("create_anon_creds failed\n"); goto done; } - cli_credentials_set_conf(anon_creds); - cli_credentials_set_anonymous(anon_creds); - setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; setup.in.workgroup = ""; @@ -986,15 +999,11 @@ BOOL torture_netlogon_samba3(struct torture_context *torture) return False; } - anon_creds = cli_credentials_init(mem_ctx); - if (anon_creds == NULL) { - d_printf("cli_credentials_init failed\n"); + if (!(anon_creds = create_anon_creds(mem_ctx))) { + d_printf("create_anon_creds failed\n"); goto done; } - cli_credentials_set_conf(anon_creds); - cli_credentials_set_anonymous(anon_creds); - status = smbcli_full_connection(mem_ctx, &cli, lp_parm_string(-1, "torture", "host"), "IPC$", NULL, anon_creds, NULL); @@ -1148,15 +1157,11 @@ BOOL torture_samba3_sessionkey(struct torture_context *torture) return False; } - anon_creds = cli_credentials_init(mem_ctx); - if (anon_creds == NULL) { - d_printf("cli_credentials_init failed\n"); + if (!(anon_creds = create_anon_creds(mem_ctx))) { + d_printf("create_anon_creds failed\n"); goto done; } - cli_credentials_set_conf(anon_creds); - cli_credentials_set_anonymous(anon_creds); - ret = True; if (!lp_parm_bool(-1, "target", "samba3", False)) { @@ -1214,6 +1219,235 @@ BOOL torture_samba3_sessionkey(struct torture_context *torture) return ret; } +/* + * 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) +{ + struct dcerpc_pipe *result; + NTSTATUS status; + + if (!(result = dcerpc_pipe_init( + mem_ctx, tree->session->transport->socket->event.ctx))) { + return NULL; + } + + status = dcerpc_pipe_open_smb(result->conn, 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; + } + + 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 result; +} + +/* + * Sane wrapper around lsa_LookupNames + */ + +static struct dom_sid *name2sid(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe *p, + const char *name, + const char *domain) +{ + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + struct lsa_OpenPolicy2 r; + struct lsa_Close c; + NTSTATUS status; + struct policy_handle handle; + struct lsa_LookupNames l; + struct lsa_TransSidArray sids; + struct lsa_String lsa_name; + uint32_t count = 1; + struct dom_sid *result; + TALLOC_CTX *tmp_ctx; + + if (!(tmp_ctx = talloc_new(mem_ctx))) { + return NULL; + } + + qos.len = 0; + qos.impersonation_level = 2; + qos.context_mode = 1; + qos.effective_only = 0; + + attr.len = 0; + attr.root_dir = NULL; + attr.object_name = NULL; + attr.attributes = 0; + attr.sec_desc = NULL; + attr.sec_qos = &qos; + + r.in.system_name = "\\"; + r.in.attr = &attr; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.out.handle = &handle; + + status = dcerpc_lsa_OpenPolicy2(p, tmp_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenPolicy2 failed - %s\n", nt_errstr(status)); + talloc_free(tmp_ctx); + return NULL; + } + + sids.count = 0; + sids.sids = NULL; + + lsa_name.string = talloc_asprintf(tmp_ctx, "%s\\%s", domain, name); + + l.in.handle = &handle; + l.in.num_names = 1; + l.in.names = &lsa_name; + l.in.sids = &sids; + l.in.level = 1; + l.in.count = &count; + l.out.count = &count; + l.out.sids = &sids; + + status = dcerpc_lsa_LookupNames(p, tmp_ctx, &l); + if (!NT_STATUS_IS_OK(status)) { + printf("LookupNames failed - %s\n", nt_errstr(status)); + talloc_free(tmp_ctx); + return False; + } + + result = dom_sid_add_rid(mem_ctx, l.out.domains->domains[0].sid, + l.out.sids->sids[0].rid); + + c.in.handle = &handle; + c.out.handle = &handle; + + status = dcerpc_lsa_Close(p, tmp_ctx, &c); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_lsa_Close failed - %s\n", nt_errstr(status)); + talloc_free(tmp_ctx); + return NULL; + } + + talloc_free(tmp_ctx); + return result; +} + +/* + * Find out the user SID on this connection + */ + +static struct dom_sid *whoami(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree) +{ + struct dcerpc_pipe *lsa; + struct lsa_GetUserName r; + NTSTATUS status; + 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"); + return NULL; + } + + r.in.system_name = "\\"; + r.in.account_name = NULL; + authority_name_p.string = NULL; + r.in.authority_name = &authority_name_p; + + status = dcerpc_lsa_GetUserName(lsa, mem_ctx, &r); + + if (!NT_STATUS_IS_OK(status)) { + printf("GetUserName failed - %s\n", nt_errstr(status)); + talloc_free(lsa); + return NULL; + } + + result = name2sid(mem_ctx, lsa, r.out.account_name->string, + r.out.authority_name->string->string); + + talloc_free(lsa); + return result; +} + +/* + * Test the getusername behaviour + */ + +BOOL torture_samba3_rpc_getusername(struct torture_context *torture) +{ + NTSTATUS status; + struct smbcli_state *cli; + TALLOC_CTX *mem_ctx; + BOOL ret = True; + struct dom_sid *user_sid; + struct cli_credentials *anon_creds; + + if (!(mem_ctx = talloc_new(torture))) { + return False; + } + + status = smbcli_full_connection( + mem_ctx, &cli, lp_parm_string(-1, "torture", "host"), + "IPC$", NULL, cmdline_credentials, NULL); + if (!NT_STATUS_IS_OK(status)) { + d_printf("smbcli_full_connection failed: %s\n", + nt_errstr(status)); + ret = False; + goto done; + } + + if (!(user_sid = whoami(mem_ctx, cli->tree))) { + d_printf("whoami on auth'ed connection failed\n"); + ret = False; + } + + talloc_free(cli); + + if (!(anon_creds = create_anon_creds(mem_ctx))) { + d_printf("create_anon_creds failed\n"); + ret = False; + goto done; + } + + status = smbcli_full_connection( + mem_ctx, &cli, lp_parm_string(-1, "torture", "host"), + "IPC$", NULL, anon_creds, NULL); + if (!NT_STATUS_IS_OK(status)) { + d_printf("anon smbcli_full_connection failed: %s\n", + nt_errstr(status)); + ret = False; + goto done; + } + + if (!(user_sid = whoami(mem_ctx, cli->tree))) { + d_printf("whoami on anon connection failed\n"); + 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", + dom_sid_string(mem_ctx, user_sid)); + ret = False; + } + + done: + talloc_free(mem_ctx); + return ret; +} + static BOOL test_NetShareGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *sharename) { @@ -1303,20 +1537,26 @@ static BOOL test_NetShareEnum(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, BOOL torture_samba3_rpc_srvsvc(struct torture_context *torture) { - NTSTATUS status; struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx; BOOL ret = True; const char *sharename = NULL; + struct smbcli_state *cli; if (!(mem_ctx = talloc_new(torture))) { return False; } - status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_srvsvc); - if (!NT_STATUS_IS_OK(status)) { - printf("torture_rpc_connection failed: %s\n", - nt_errstr(status)); + if (!(torture_open_connection_share( + mem_ctx, &cli, lp_parm_string(-1, "torture", "host"), + "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"); ret = False; goto done; } |