diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc_smb.c | 15 | ||||
-rw-r--r-- | source4/torture/raw/notify.c | 4 | ||||
-rw-r--r-- | source4/torture/raw/qfileinfo.c | 181 | ||||
-rw-r--r-- | source4/torture/raw/qfsinfo.c | 2 | ||||
-rw-r--r-- | source4/torture/raw/raw.c | 1 | ||||
-rw-r--r-- | source4/torture/raw/search.c | 4 | ||||
-rw-r--r-- | source4/torture/util_smb.c | 4 |
7 files changed, 148 insertions, 63 deletions
diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c index 1eead06a48..7f0bcf0485 100644 --- a/source4/librpc/rpc/dcerpc_smb.c +++ b/source4/librpc/rpc/dcerpc_smb.c @@ -561,3 +561,18 @@ struct smbcli_tree *dcerpc_smb_tree(struct dcerpc_connection *c) return smb->tree; } + +/* + return the SMB fnum used for a dcerpc over SMB pipe (hack for torture operations) +*/ +uint16_t dcerpc_smb_fnum(struct dcerpc_connection *c) +{ + struct smb_private *smb; + + if (c->transport.transport != NCACN_NP) return 0; + + smb = talloc_get_type(c->transport.private, struct smb_private); + if (!smb) return 0; + + return smb->fnum; +} diff --git a/source4/torture/raw/notify.c b/source4/torture/raw/notify.c index 51e73f1115..74f33f0dbd 100644 --- a/source4/torture/raw/notify.c +++ b/source4/torture/raw/notify.c @@ -45,7 +45,7 @@ }} while (0) #define CHECK_WSTR(field, value, flags) do { \ - if (!field.s || strcmp(field.s, value) || wire_bad_flags(&field, flags, cli)) { \ + if (!field.s || strcmp(field.s, value) || wire_bad_flags(&field, flags, cli->transport)) { \ printf("(%d) %s [%s] != %s\n", __LINE__, #field, field.s, value); \ ret = False; \ goto done; \ @@ -278,7 +278,7 @@ static BOOL check_rename_reply(struct smbcli_state *cli, if ((actions[i].name.s == NULL) || (strcmp(actions[i].name.s, name) != 0) || (wire_bad_flags(&actions[i].name, STR_UNICODE, - cli))) { + cli->transport))) { printf("(%d) name [%s] != %s\n", line, actions[i].name.s, name); return False; diff --git a/source4/torture/raw/qfileinfo.c b/source4/torture/raw/qfileinfo.c index d7199972ca..fad32f6a9e 100644 --- a/source4/torture/raw/qfileinfo.c +++ b/source4/torture/raw/qfileinfo.c @@ -23,6 +23,8 @@ #include "libcli/raw/libcliraw.h" #include "libcli/libcli.h" #include "torture/util.h" +#include "librpc/rpc/dcerpc.h" +#include "torture/rpc/rpc.h" static struct { const char *name; @@ -67,6 +69,8 @@ static struct { { NULL, } }; +static bool is_ipc; + /* compare a dos time (2 second resolution) to a nt time */ @@ -100,6 +104,9 @@ static union smb_fileinfo *fnum_find(const char *name) static union smb_fileinfo *fname_find(const char *name) { int i; + if (is_ipc) { + return NULL; + } for (i=0; levels[i].name; i++) { if (NT_STATUS_IS_OK(levels[i].fname_status) && strcmp(name, levels[i].name) == 0 && @@ -153,56 +160,39 @@ static union smb_fileinfo *fname_find(const char *name) for each call we test that it succeeds, and where possible test for consistency between the calls. */ -BOOL torture_raw_qfileinfo(struct torture_context *torture) +static BOOL torture_raw_qfileinfo_internals(struct torture_context *torture, TALLOC_CTX *mem_ctx, + struct smbcli_tree *tree, int fnum, const char *fname) { - struct smbcli_state *cli; int i; BOOL ret = True; int count; union smb_fileinfo *s1, *s2; - TALLOC_CTX *mem_ctx; - int fnum; - const char *fname = "\\torture_qfileinfo.txt"; NTTIME correct_time; uint64_t correct_size; uint32_t correct_attrib; const char *correct_name; BOOL skip_streams = False; - if (!torture_open_connection(&cli, 0)) { - return False; - } - - mem_ctx = talloc_init("torture_qfileinfo"); - - fnum = create_complex_file(cli, mem_ctx, fname); - if (fnum == -1) { - printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); - ret = False; - goto done; - } - - /* scan all the fileinfo and pathinfo levels */ for (i=0; levels[i].name; i++) { if (!levels[i].only_paths) { levels[i].fnum_finfo.generic.level = levels[i].level; levels[i].fnum_finfo.generic.in.file.fnum = fnum; - levels[i].fnum_status = smb_raw_fileinfo(cli->tree, mem_ctx, + levels[i].fnum_status = smb_raw_fileinfo(tree, mem_ctx, &levels[i].fnum_finfo); } if (!levels[i].only_handles) { levels[i].fname_finfo.generic.level = levels[i].level; levels[i].fname_finfo.generic.in.file.path = talloc_strdup(mem_ctx, fname); - levels[i].fname_status = smb_raw_pathinfo(cli->tree, mem_ctx, + levels[i].fname_status = smb_raw_pathinfo(tree, mem_ctx, &levels[i].fname_finfo); } } /* check for completely broken levels */ for (count=i=0; levels[i].name; i++) { - uint32_t cap = cli->transport->negotiate.capabilities; + uint32_t cap = tree->session->transport->negotiate.capabilities; /* see if this server claims to support this level */ if ((cap & levels[i].capability_mask) != levels[i].capability_mask) { continue; @@ -213,7 +203,7 @@ BOOL torture_raw_qfileinfo(struct torture_context *torture) levels[i].name, nt_errstr(levels[i].fnum_status)); count++; } - if (!levels[i].only_handles && !NT_STATUS_IS_OK(levels[i].fname_status)) { + if (!(is_ipc || levels[i].only_handles) && !NT_STATUS_IS_OK(levels[i].fname_status)) { printf("ERROR: level %s failed - %s\n", levels[i].name, nt_errstr(levels[i].fname_status)); count++; @@ -232,8 +222,10 @@ BOOL torture_raw_qfileinfo(struct torture_context *torture) /* see if we can do streams */ s1 = fnum_find("STREAM_INFO"); if (!s1 || s1->stream_info.out.num_streams == 0) { - printf("STREAM_INFO broken (%d) - skipping streams checks\n", - s1 ? s1->stream_info.out.num_streams : -1); + if (!is_ipc) { + printf("STREAM_INFO broken (%d) - skipping streams checks\n", + s1 ? s1->stream_info.out.num_streams : -1); + } skip_streams = True; } @@ -511,14 +503,14 @@ BOOL torture_raw_qfileinfo(struct torture_context *torture) #define NAME_CHECK(sname, stype, tfield, flags) do { \ s1 = fnum_find(sname); \ if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \ - wire_bad_flags(&s1->stype.out.tfield, flags, cli))) { \ + wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \ printf("(%d) handle %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \ s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \ ret = False; \ } \ s1 = fname_find(sname); \ if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \ - wire_bad_flags(&s1->stype.out.tfield, flags, cli))) { \ + wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \ printf("(%d) path %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \ s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \ ret = False; \ @@ -546,42 +538,44 @@ BOOL torture_raw_qfileinfo(struct torture_context *torture) ret = False; } } - if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE, cli)) { + if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE, tree->session->transport)) { printf("Should not null terminate all_info/fname\n"); ret = False; } } s1 = fnum_find("ALT_NAME_INFO"); - correct_name = s1->alt_name_info.out.fname.s; - printf("alt_name: %s\n", correct_name); - - NAME_CHECK("ALT_NAME_INFO", alt_name_info, fname, STR_UNICODE); - NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE); - - /* and make sure we can open by alternate name */ - smbcli_close(cli->tree, fnum); - fnum = smbcli_nt_create_full(cli->tree, correct_name, 0, - SEC_RIGHTS_FILE_ALL, - FILE_ATTRIBUTE_NORMAL, - NTCREATEX_SHARE_ACCESS_DELETE| - NTCREATEX_SHARE_ACCESS_READ| - NTCREATEX_SHARE_ACCESS_WRITE, - NTCREATEX_DISP_OVERWRITE_IF, - 0, 0); - if (fnum == -1) { - printf("Unable to open by alt_name - %s\n", smbcli_errstr(cli->tree)); - ret = False; - } - - if (!skip_streams) { - correct_name = "::$DATA"; - printf("stream_name: %s\n", correct_name); - - NAME_CHECK("STREAM_INFO", stream_info, streams[0].stream_name, STR_UNICODE); - NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE); + if (s1) { + correct_name = s1->alt_name_info.out.fname.s; + printf("alt_name: %s\n", correct_name); + + NAME_CHECK("ALT_NAME_INFO", alt_name_info, fname, STR_UNICODE); + NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE); + + /* and make sure we can open by alternate name */ + smbcli_close(tree, fnum); + fnum = smbcli_nt_create_full(tree, correct_name, 0, + SEC_RIGHTS_FILE_ALL, + FILE_ATTRIBUTE_NORMAL, + NTCREATEX_SHARE_ACCESS_DELETE| + NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE, + NTCREATEX_DISP_OVERWRITE_IF, + 0, 0); + if (fnum == -1) { + printf("Unable to open by alt_name - %s\n", smbcli_errstr(tree)); + ret = False; + } + + if (!skip_streams) { + correct_name = "::$DATA"; + printf("stream_name: %s\n", correct_name); + + NAME_CHECK("STREAM_INFO", stream_info, streams[0].stream_name, STR_UNICODE); + NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE); + } } - + /* make sure the EAs look right */ s1 = fnum_find("ALL_EAS"); s2 = fnum_find("ALL_INFO"); @@ -714,10 +708,85 @@ BOOL torture_raw_qfileinfo(struct torture_context *torture) done: + + return ret; +} + +/* basic testing of all RAW_FILEINFO_* calls + for each call we test that it succeeds, and where possible test + for consistency between the calls. +*/ +BOOL torture_raw_qfileinfo(struct torture_context *torture) +{ + struct smbcli_state *cli; + BOOL ret = True; + TALLOC_CTX *mem_ctx; + int fnum; + const char *fname = "\\torture_qfileinfo.txt"; + + is_ipc = 0; + + if (!torture_open_connection(&cli, 0)) { + return False; + } + + mem_ctx = talloc_init("torture_qfileinfo"); + + fnum = create_complex_file(cli, mem_ctx, fname); + if (fnum == -1) { + printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); + ret = False; + goto done; + } + + ret = torture_raw_qfileinfo_internals(torture, mem_ctx, cli->tree, fnum, fname); + smbcli_close(cli->tree, fnum); smbcli_unlink(cli->tree, fname); +done: torture_close_connection(cli); talloc_free(mem_ctx); return ret; } + +BOOL torture_raw_qfileinfo_pipe(struct torture_context *torture) +{ + TALLOC_CTX *mem_ctx; + BOOL ret = True; + int fnum; + const char *fname = "\\lsass"; + struct smbcli_state *cli; + struct dcerpc_pipe *p; + struct smbcli_tree *ipc_tree; + NTSTATUS status; + + is_ipc = True; + + if (!torture_open_connection(&cli, 0)) { + return False; + } + + mem_ctx = talloc_init("torture_qfileinfo_pipe"); + + if (!(p = dcerpc_pipe_init(mem_ctx, + cli->tree->session->transport->socket->event.ctx))) { + return False; + } + + status = dcerpc_pipe_open_smb(p, cli->tree, fname); + if (!NT_STATUS_IS_OK(status)) { + d_printf("dcerpc_pipe_open_smb failed: %s\n", + nt_errstr(status)); + talloc_free(p); + return False; + } + + ipc_tree = dcerpc_smb_tree(p->conn); + fnum = dcerpc_smb_fnum(p->conn); + + ret = torture_raw_qfileinfo_internals(torture, mem_ctx, ipc_tree, fnum, fname); + + talloc_free(p); + return ret; +} diff --git a/source4/torture/raw/qfsinfo.c b/source4/torture/raw/qfsinfo.c index 175a4ed15a..50a5a6609a 100644 --- a/source4/torture/raw/qfsinfo.c +++ b/source4/torture/raw/qfsinfo.c @@ -289,7 +289,7 @@ BOOL torture_raw_qfsinfo(struct torture_context *torture) #define STR_CHECK(sname, stype, field, flags) do { \ s1 = find(sname); \ if (s1) { \ - if (s1->stype.out.field.s && wire_bad_flags(&s1->stype.out.field, flags, cli)) { \ + if (s1->stype.out.field.s && wire_bad_flags(&s1->stype.out.field, flags, cli->transport)) { \ printf("(%d) incorrect string termination in %s/%s\n", \ __LINE__, #stype, #field); \ ret = False; \ diff --git a/source4/torture/raw/raw.c b/source4/torture/raw/raw.c index eb89193f47..bdf4072a62 100644 --- a/source4/torture/raw/raw.c +++ b/source4/torture/raw/raw.c @@ -34,6 +34,7 @@ NTSTATUS torture_raw_init(void) torture_suite_add_simple_test(suite, "BENCH-OPEN", torture_bench_open); torture_suite_add_simple_test(suite, "QFSINFO", torture_raw_qfsinfo); torture_suite_add_simple_test(suite, "QFILEINFO", torture_raw_qfileinfo); + torture_suite_add_simple_test(suite, "QFILEINFO-IPC", torture_raw_qfileinfo_pipe); torture_suite_add_simple_test(suite, "SFILEINFO", torture_raw_sfileinfo); torture_suite_add_simple_test(suite, "SFILEINFO-BUG", torture_raw_sfileinfo_bug); torture_suite_add_simple_test(suite, "SEARCH", torture_raw_search); diff --git a/source4/torture/raw/search.c b/source4/torture/raw/search.c index 09b7ff7dc7..1fb35e8b19 100644 --- a/source4/torture/raw/search.c +++ b/source4/torture/raw/search.c @@ -391,7 +391,7 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) if (s) { \ if (!s->sname1.field1.s || \ strcmp(s->sname1.field1.s, v.sname2.out.field2.s) || \ - wire_bad_flags(&s->sname1.field1, flags, cli)) { \ + wire_bad_flags(&s->sname1.field1, flags, cli->transport)) { \ printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \ __location__, \ #sname1, #field1, s->sname1.field1.s, \ @@ -405,7 +405,7 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) if (s) { \ if (!s->sname1.field1.s || \ strcmp(s->sname1.field1.s, fname) || \ - wire_bad_flags(&s->sname1.field1, flags, cli)) { \ + wire_bad_flags(&s->sname1.field1, flags, cli->transport)) { \ printf("(%s) %s/%s [%s] != %s\n", \ __location__, \ #sname1, #field1, s->sname1.field1.s, \ diff --git a/source4/torture/util_smb.c b/source4/torture/util_smb.c index c47741c5b9..4cadbe20fe 100644 --- a/source4/torture/util_smb.c +++ b/source4/torture/util_smb.c @@ -282,7 +282,7 @@ void *shm_setup(int size) check that a wire string matches the flags specified not 100% accurate, but close enough for testing */ -bool wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_state *cli) +bool wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_transport *transport) { bool server_unicode; int len; @@ -290,7 +290,7 @@ bool wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_state len = strlen(str->s); if (flags & STR_TERMINATE) len++; - server_unicode = (cli->transport->negotiate.capabilities&CAP_UNICODE)?True:False; + server_unicode = (transport->negotiate.capabilities&CAP_UNICODE)?True:False; if (getenv("CLI_FORCE_ASCII") || !lp_unicode()) { server_unicode = False; } |