static int ejs_mkdir(MprVarHandle eid, int argc, MprVar **argv) { struct smbcli_tree *tree; NTSTATUS result; if (argc != 2) { ejsSetErrorMsg(eid, "mkdir(): invalid number of args"); return -1; } if (!IS_TREE_HANDLE(argv[0])) { ejsSetErrorMsg(eid, "first arg is not a tree handle"); return -1; } tree = argv[0]->ptr; if (!mprVarIsString(argv[1]->type)) { ejsSetErrorMsg(eid, "arg 2 must be a string"); return -1; } result = smbcli_mkdir(tree, argv[1]->string); mpr_Return(eid, mprNTSTATUS(result)); return 0; }
static void test_mask(int argc, char *argv[], TALLOC_CTX *mem_ctx, struct smbcli_state *cli) { char *mask, *file; int l1, l2, i, l; int mc_len = strlen(maskchars); int fc_len = strlen(filechars); smbcli_mkdir(cli->tree, "\\masktest"); smbcli_unlink(cli->tree, "\\masktest\\*"); if (argc >= 2) { while (argc >= 2) { mask = talloc_strdup(mem_ctx, "\\masktest\\"); file = talloc_strdup(mem_ctx, "\\masktest\\"); mask = talloc_strdup_append(mask, argv[0]); file = talloc_strdup_append(file, argv[1]); testpair(mem_ctx, cli, mask, file); argv += 2; argc -= 2; } goto finished; } while (1) { l1 = 1 + random() % max_length; l2 = 1 + random() % max_length; mask = talloc_strdup(mem_ctx, "\\masktest\\"); file = talloc_strdup(mem_ctx, "\\masktest\\"); mask = talloc_realloc_size(mem_ctx, mask, strlen(mask)+l1+1); file = talloc_realloc_size(mem_ctx, file, strlen(file)+l2+1); l = strlen(mask); for (i=0;i<l1;i++) { mask[i+l] = maskchars[random() % mc_len]; } mask[l+l1] = 0; for (i=0;i<l2;i++) { file[i+l] = filechars[random() % fc_len]; } file[l+l2] = 0; if (ISDOT(file+l) || ISDOTDOT(file+l) || ISDOTDOT(mask+l)) { continue; } if (strspn(file+l, ".") == strlen(file+l)) continue; testpair(mem_ctx, cli, mask, file); if (NumLoops && (--NumLoops == 0)) break; } finished: smbcli_rmdir(cli->tree, "\\masktest"); talloc_free(mem_ctx); }
bool torture_samba3_caseinsensitive(struct torture_context *torture) { struct smbcli_state *cli; TALLOC_CTX *mem_ctx; NTSTATUS status; const char *dirname = "insensitive"; const char *ucase_dirname = "InSeNsItIvE"; const char *fname = "foo"; char *fpath; int fnum; int counter = 0; bool ret = true; if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) { d_printf("talloc_init failed\n"); return false; } if (!torture_open_connection(&cli, torture, 0)) { goto done; } smbcli_deltree(cli->tree, dirname); status = smbcli_mkdir(cli->tree, dirname); if (!NT_STATUS_IS_OK(status)) { d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status)); goto done; } if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) { goto done; } fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { d_printf("Could not create file %s: %s\n", fpath, smbcli_errstr(cli->tree)); goto done; } smbcli_close(cli->tree, fnum); smbcli_list(cli->tree, talloc_asprintf( mem_ctx, "%s\\*", ucase_dirname), FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN |FILE_ATTRIBUTE_SYSTEM, count_fn, (void *)&counter); if (counter == 3) { ret = true; } else { d_fprintf(stderr, "expected 3 entries, got %d\n", counter); ret = false; } done: talloc_free(mem_ctx); return ret; }
/** setup a directory ready for a test */ _PUBLIC_ bool torture_setup_dir(struct smbcli_state *cli, const char *dname) { smb_raw_exit(cli->session); if (smbcli_deltree(cli->tree, dname) == -1 || NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) { printf("Unable to setup %s - %s\n", dname, smbcli_errstr(cli->tree)); return false; } return true; }
NTSTATUS gp_push_gpt(struct gp_context *gp_ctx, const char *local_path, const char *file_sys_path) { NTSTATUS status; char *share_path; if (gp_ctx->cli == NULL) { status = gp_cli_connect(gp_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to create cli connection to DC\n")); return status; } } share_path = gp_get_share_path(gp_ctx, file_sys_path); DEBUG(5, ("Copying %s to %s on sysvol\n", local_path, share_path)); smbcli_mkdir(gp_ctx->cli->tree, share_path); status = push_recursive(gp_ctx, local_path, share_path, 0); talloc_free(share_path); return status; }
/**************************************************************************** check for existance of a nttrans call ****************************************************************************/ static bool scan_nttrans(struct smbcli_state *cli, int op, int level, int fnum, int dnum, const char *fname) { int data_len = 0; int param_len = 0; int rparam_len, rdata_len; uint8_t *param, *data; NTSTATUS status; TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("scan_nttrans"); param = talloc_array(mem_ctx, uint8_t, PARAM_SIZE); data = talloc_array(mem_ctx, uint8_t, PARAM_SIZE); memset(data, 0, PARAM_SIZE); data_len = 4; /* try with a info level only */ param_len = 2; SSVAL(param, 0, level); status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a file descriptor */ param_len = 6; SSVAL(param, 0, fnum); SSVAL(param, 2, level); SSVAL(param, 4, 0); status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a notify style */ param_len = 6; SSVAL(param, 0, dnum); SSVAL(param, 2, dnum); SSVAL(param, 4, level); status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a file name */ param_len = 6; SSVAL(param, 0, level); SSVAL(param, 2, 0); SSVAL(param, 4, 0); param_len += push_string( ¶m[6], fname, PARAM_SIZE, STR_TERMINATE | STR_UNICODE); status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try with a new file name */ param_len = 6; SSVAL(param, 0, level); SSVAL(param, 2, 0); SSVAL(param, 4, 0); param_len += push_string( ¶m[6], "\\newfile.dat", PARAM_SIZE, STR_TERMINATE | STR_UNICODE); status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); smbcli_unlink(cli->tree, "\\newfile.dat"); smbcli_rmdir(cli->tree, "\\newfile.dat"); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } /* try dfs style */ smbcli_mkdir(cli->tree, "\\testdir"); param_len = 2; SSVAL(param, 0, level); param_len += push_string(¶m[2], "\\testdir", PARAM_SIZE, STR_TERMINATE | STR_UNICODE); status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len, &rparam_len, &rdata_len); smbcli_rmdir(cli->tree, "\\testdir"); if (NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return true; } talloc_free(mem_ctx); return false; }
/* test how many open files this server supports on the one socket */ bool run_maxfidtest(struct torture_context *tctx, struct smbcli_state *cli, int dummy) { #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d" char *fname; int fnums[0x11000], i; int retries=4, maxfid; bool correct = true; if (retries <= 0) { torture_comment(tctx, "failed to connect\n"); return false; } if (smbcli_deltree(cli->tree, "\\maxfid") == -1) { torture_comment(tctx, "Failed to deltree \\maxfid - %s\n", smbcli_errstr(cli->tree)); return false; } if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) { torture_comment(tctx, "Failed to mkdir \\maxfid, error=%s\n", smbcli_errstr(cli->tree)); return false; } torture_comment(tctx, "Testing maximum number of open files\n"); for (i=0; i<0x11000; i++) { if (i % 1000 == 0) { asprintf(&fname, "\\maxfid\\fid%d", i/1000); if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) { torture_comment(tctx, "Failed to mkdir %s, error=%s\n", fname, smbcli_errstr(cli->tree)); return false; } free(fname); } asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid()); if ((fnums[i] = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) == -1) { torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); torture_comment(tctx, "maximum fnum is %d\n", i); break; } free(fname); if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%6d\r", i); fflush(stdout); } } torture_comment(tctx, "%6d\n", i); i--; maxfid = i; torture_comment(tctx, "cleaning up\n"); for (i=0;i<maxfid/2;i++) { asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid()); if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) { torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree)); } if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) { torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); correct = false; } free(fname); asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid()); if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) { torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree)); } if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) { torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree)); correct = false; } free(fname); if (torture_setting_bool(tctx, "progress", true)) { torture_comment(tctx, "%6d %6d\r", i, maxfid-i); fflush(stdout); } } torture_comment(tctx, "%6d\n", 0); if (smbcli_deltree(cli->tree, "\\maxfid") == -1) { torture_comment(tctx, "Failed to deltree \\maxfid - %s\n", smbcli_errstr(cli->tree)); return false; } torture_comment(tctx, "maxfid test finished\n"); if (!torture_close_connection(cli)) { correct = false; } return correct; #undef MAXFID_TEMPLATE }
bool torture_samba3_closeerr(struct torture_context *tctx) { struct smbcli_state *cli = NULL; bool result = false; NTSTATUS status; const char *dname = "closeerr.dir"; const char *fname = "closeerr.dir\\closerr.txt"; int fnum; if (!torture_open_connection(&cli, tctx, 0)) { goto fail; } smbcli_deltree(cli->tree, dname); torture_assert_ntstatus_ok( tctx, smbcli_mkdir(cli->tree, dname), talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n", smbcli_errstr(cli->tree))); fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "smbcli_open failed: %s\n", smbcli_errstr(cli->tree))); smbcli_close(cli->tree, fnum); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "smbcli_open failed: %s\n", smbcli_errstr(cli->tree))); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "setting delete_on_close on file failed !"); status = smbcli_chmod(cli->tree, dname, 0); torture_assert_ntstatus_ok(tctx, status, "smbcli_chmod on file failed !"); status = smbcli_close(cli->tree, fnum); smbcli_chmod(cli->tree, dname, UNIX_R_USR|UNIX_W_USR|UNIX_X_USR); smbcli_deltree(cli->tree, dname); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_ACCESS_DENIED, "smbcli_close"); result = true; fail: if (cli) { torture_close_connection(cli); } return result; }
bool torture_dirtest2(struct torture_context *tctx, struct smbcli_state *cli) { int i; int fnum, num_seen; bool correct = true; extern int torture_entries; if (!torture_setup_dir(cli, "\\LISTDIR")) { return false; } torture_comment(tctx, "Creating %d files\n", torture_entries); /* Create torture_entries files and torture_entries directories. */ for (i=0;i<torture_entries;i++) { char *fname; asprintf(&fname, "\\LISTDIR\\f%d", i); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_ARCHIVE, NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); if (fnum == -1) { fprintf(stderr,"(%s) Failed to open %s, error=%s\n", __location__, fname, smbcli_errstr(cli->tree)); return false; } free(fname); smbcli_close(cli->tree, fnum); } for (i=0;i<torture_entries;i++) { char *fname; asprintf(&fname, "\\LISTDIR\\d%d", i); if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) { fprintf(stderr,"(%s) Failed to open %s, error=%s\n", __location__, fname, smbcli_errstr(cli->tree)); return false; } free(fname); } /* Now ensure that doing an old list sees both files and directories. */ num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL); torture_comment(tctx, "num_seen = %d\n", num_seen ); /* We should see (torture_entries) each of files & directories + . and .. */ if (num_seen != (2*torture_entries)+2) { correct = false; fprintf(stderr,"(%s) entry count mismatch, should be %d, was %d\n", __location__, (2*torture_entries)+2, num_seen); } /* Ensure if we have the "must have" bits we only see the * relevant entries. */ num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL); torture_comment(tctx, "num_seen = %d\n", num_seen ); if (num_seen != torture_entries+2) { correct = false; fprintf(stderr,"(%s) entry count mismatch, should be %d, was %d\n", __location__, torture_entries+2, num_seen); } num_seen = smbcli_list_old(cli->tree, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, NULL); torture_comment(tctx, "num_seen = %d\n", num_seen ); if (num_seen != torture_entries) { correct = false; fprintf(stderr,"(%s) entry count mismatch, should be %d, was %d\n", __location__, torture_entries, num_seen); } /* Delete everything. */ if (smbcli_deltree(cli->tree, "\\LISTDIR") == -1) { fprintf(stderr,"(%s) Failed to deltree %s, error=%s\n", "\\LISTDIR", __location__, smbcli_errstr(cli->tree)); return false; } #if 0 torture_comment(tctx, "Matched %d\n", smbcli_list(cli->tree, "a*.*", 0, list_fn, NULL)); torture_comment(tctx, "Matched %d\n", smbcli_list(cli->tree, "b*.*", 0, list_fn, NULL)); torture_comment(tctx, "Matched %d\n", smbcli_list(cli->tree, "xyzabc", 0, list_fn, NULL)); #endif return correct; }
bool torture_samba3_posixtimedlock(struct torture_context *tctx) { struct smbcli_state *cli; NTSTATUS status; bool ret = true; const char *dirname = "posixlock"; const char *fname = "locked"; const char *fpath; const char *localdir; const char *localname; int fnum = -1; int fd = -1; struct flock posix_lock; union smb_lock io; struct smb_lock_entry lock_entry; struct smbcli_request *req; struct lock_result_state lock_result; struct tevent_timer *te; if (!torture_open_connection(&cli, tctx, 0)) { ret = false; goto done; } smbcli_deltree(cli->tree, dirname); status = smbcli_mkdir(cli->tree, dirname); if (!NT_STATUS_IS_OK(status)) { torture_warning(tctx, "smbcli_mkdir failed: %s\n", nt_errstr(status)); ret = false; goto done; } if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) { torture_warning(tctx, "talloc failed\n"); ret = false; goto done; } fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { torture_warning(tctx, "Could not create file %s: %s\n", fpath, smbcli_errstr(cli->tree)); ret = false; goto done; } if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) { torture_warning(tctx, "Need 'localdir' setting\n"); ret = false; goto done; } if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname, fname))) { torture_warning(tctx, "talloc failed\n"); ret = false; goto done; } /* * Lock a byte range from posix */ fd = open(localname, O_RDWR); if (fd == -1) { torture_warning(tctx, "open(%s) failed: %s\n", localname, strerror(errno)); goto done; } posix_lock.l_type = F_WRLCK; posix_lock.l_whence = SEEK_SET; posix_lock.l_start = 0; posix_lock.l_len = 1; if (fcntl(fd, F_SETLK, &posix_lock) == -1) { torture_warning(tctx, "fcntl failed: %s\n", strerror(errno)); ret = false; goto done; } /* * Try a cifs brlock without timeout to see if posix locking = yes */ io.lockx.in.ulock_cnt = 0; io.lockx.in.lock_cnt = 1; lock_entry.count = 1; lock_entry.offset = 0; lock_entry.pid = cli->tree->session->pid; io.lockx.level = RAW_LOCK_LOCKX; io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; io.lockx.in.timeout = 0; io.lockx.in.locks = &lock_entry; io.lockx.in.file.fnum = fnum; status = smb_raw_lock(cli->tree, &io); ret = true; CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); if (!ret) { goto done; } /* * Now fire off a timed brlock, unlock the posix lock and see if the * timed lock gets through. */ io.lockx.in.timeout = 5000; req = smb_raw_lock_send(cli->tree, &io); if (req == NULL) { torture_warning(tctx, "smb_raw_lock_send failed\n"); ret = false; goto done; } lock_result.done = false; req->async.fn = receive_lock_result; req->async.private_data = &lock_result; te = tevent_add_timer(req->transport->socket->event.ctx, tctx, timeval_current_ofs(1, 0), close_locked_file, &fd); if (te == NULL) { torture_warning(tctx, "tevent_add_timer failed\n"); ret = false; goto done; } while ((fd != -1) || (!lock_result.done)) { if (tevent_loop_once(req->transport->socket->event.ctx) == -1) { torture_warning(tctx, "tevent_loop_once failed: %s\n", strerror(errno)); ret = false; goto done; } } CHECK_STATUS(lock_result.status, NT_STATUS_OK); done: if (fnum != -1) { smbcli_close(cli->tree, fnum); } if (fd != -1) { close(fd); } smbcli_deltree(cli->tree, dirname); return ret; }
bool torture_samba3_checkfsp(struct torture_context *torture) { struct smbcli_state *cli; const char *fname = "test.txt"; const char *dirname = "testdir"; int fnum; NTSTATUS status; bool ret = true; TALLOC_CTX *mem_ctx; ssize_t nread; char buf[16]; struct smbcli_tree *tree2; if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) { d_printf("talloc_init failed\n"); return false; } if (!torture_open_connection_share( torture, &cli, torture, torture_setting_string(torture, "host", NULL), torture_setting_string(torture, "share", NULL), torture->ev)) { d_printf("torture_open_connection_share failed\n"); ret = false; goto done; } smbcli_deltree(cli->tree, dirname); status = torture_second_tcon(torture, cli->session, torture_setting_string(torture, "share", NULL), &tree2); CHECK_STATUS(status, NT_STATUS_OK); if (!NT_STATUS_IS_OK(status)) goto done; /* Try a read on an invalid FID */ nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf)); CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE); /* Try a read on a directory handle */ status = smbcli_mkdir(cli->tree, dirname); if (!NT_STATUS_IS_OK(status)) { d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status)); ret = false; goto done; } /* Open the directory */ { union smb_open io; io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = dirname; status = smb_raw_open(cli->tree, mem_ctx, &io); if (!NT_STATUS_IS_OK(status)) { d_printf("smb_open on the directory failed: %s\n", nt_errstr(status)); ret = false; goto done; } fnum = io.ntcreatex.out.file.fnum; } /* Try a read on the directory */ nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf)); if (nread >= 0) { d_printf("smbcli_read on a directory succeeded, expected " "failure\n"); ret = false; } CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_DEVICE_REQUEST); /* Same test on the second tcon */ nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf)); if (nread >= 0) { d_printf("smbcli_read on a directory succeeded, expected " "failure\n"); ret = false; } CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE); smbcli_close(cli->tree, fnum); /* Try a normal file read on a second tcon */ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { d_printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = false; goto done; } nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf)); CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE); smbcli_close(cli->tree, fnum); done: smbcli_deltree(cli->tree, dirname); torture_close_connection(cli); talloc_free(mem_ctx); return ret; }
bool torture_samba3_badpath(struct torture_context *torture) { struct smbcli_state *cli_nt; struct smbcli_state *cli_dos; const char *fname = "test.txt"; const char *fname1 = "test1.txt"; const char *dirname = "testdir"; char *fpath; char *fpath1; int fnum; NTSTATUS status; bool ret = true; TALLOC_CTX *mem_ctx; bool nt_status_support; if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) { d_printf("talloc_init failed\n"); return false; } nt_status_support = lp_nt_status_support(torture->lp_ctx); if (!lp_set_cmdline(torture->lp_ctx, "nt status support", "yes")) { printf("Could not set 'nt status support = yes'\n"); goto fail; } if (!torture_open_connection(&cli_nt, torture, 0)) { goto fail; } if (!lp_set_cmdline(torture->lp_ctx, "nt status support", "no")) { printf("Could not set 'nt status support = yes'\n"); goto fail; } if (!torture_open_connection(&cli_dos, torture, 1)) { goto fail; } if (!lp_set_cmdline(torture->lp_ctx, "nt status support", nt_status_support ? "yes":"no")) { printf("Could not reset 'nt status support = yes'"); goto fail; } smbcli_deltree(cli_nt->tree, dirname); status = smbcli_mkdir(cli_nt->tree, dirname); if (!NT_STATUS_IS_OK(status)) { d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status)); ret = false; goto done; } status = smbcli_chkpath(cli_nt->tree, dirname); CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_chkpath(cli_nt->tree, talloc_asprintf(mem_ctx, "%s\\bla", dirname)); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); status = smbcli_chkpath(cli_dos->tree, talloc_asprintf(mem_ctx, "%s\\bla", dirname)); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, talloc_asprintf(mem_ctx, "%s\\bla\\blub", dirname)); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND); status = smbcli_chkpath(cli_dos->tree, talloc_asprintf(mem_ctx, "%s\\bla\\blub", dirname)); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) { goto fail; } fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { d_printf("Could not create file %s: %s\n", fpath, smbcli_errstr(cli_nt->tree)); goto fail; } smbcli_close(cli_nt->tree, fnum); if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) { goto fail; } fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE); if (fnum == -1) { d_printf("Could not create file %s: %s\n", fpath1, smbcli_errstr(cli_nt->tree)); goto fail; } smbcli_close(cli_nt->tree, fnum); /* * Do a whole bunch of error code checks on chkpath */ status = smbcli_chkpath(cli_nt->tree, fpath); CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY); status = smbcli_chkpath(cli_dos->tree, fpath); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, ".."); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = smbcli_chkpath(cli_dos->tree, ".."); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = smbcli_chkpath(cli_nt->tree, "."); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "."); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "\t"); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "\t"); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "\t\\bla"); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "\t\\bla"); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "<"); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "<"); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); status = smbcli_chkpath(cli_nt->tree, "<\\bla"); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_chkpath(cli_dos->tree, "<\\bla"); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath)); /* * .... And the same gang against getatr. Note that the DOS error codes * differ.... */ status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OK); status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); /* Try the same set with openX. */ status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath)); status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID); status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname)); /* Let's test EEXIST error code mapping. */ status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED) || !torture_setting_bool(torture, "samba3", false)) { /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */ CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); } status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL); if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported)) || !torture_setting_bool(torture, "samba3", false)) { /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */ CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); } status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists)); /* Try the rename test. */ { union smb_rename io; memset(&io, '\0', sizeof(io)); io.rename.in.pattern1 = fpath1; io.rename.in.pattern2 = fpath; /* Try with SMBmv rename. */ status = smb_raw_rename(cli_nt->tree, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); status = smb_raw_rename(cli_dos->tree, &io); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename)); /* Try with NT rename. */ io.generic.level = RAW_RENAME_NTRENAME; io.ntrename.in.old_name = fpath1; io.ntrename.in.new_name = fpath; io.ntrename.in.attrib = 0; io.ntrename.in.cluster_size = 0; io.ntrename.in.flags = RENAME_FLAG_RENAME; status = smb_raw_rename(cli_nt->tree, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION); status = smb_raw_rename(cli_dos->tree, &io); CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename)); } goto done; fail: ret = false; done: if (cli_nt != NULL) { smbcli_deltree(cli_nt->tree, dirname); torture_close_connection(cli_nt); } if (cli_dos != NULL) { torture_close_connection(cli_dos); } talloc_free(mem_ctx); return ret; }
static NTSTATUS push_recursive (struct gp_context *gp_ctx, const char *local_path, const char *remote_path, int depth) { DIR *dir; struct dirent *dirent; char *entry_local_path; char *entry_remote_path; int local_fd, remote_fd; int buf[1024]; int nread, total_read; struct stat s; dir = opendir(local_path); while ((dirent = readdir(dir)) != NULL) { if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) { continue; } entry_local_path = talloc_asprintf(gp_ctx, "%s/%s", local_path, dirent->d_name); NT_STATUS_HAVE_NO_MEMORY(entry_local_path); entry_remote_path = talloc_asprintf(gp_ctx, "%s\\%s", remote_path, dirent->d_name); NT_STATUS_HAVE_NO_MEMORY(entry_remote_path); if (stat(dirent->d_name, &s) != 0) { return NT_STATUS_UNSUCCESSFUL; } if (s.st_mode & S_IFDIR) { DEBUG(6, ("Pushing directory %s to %s on sysvol\n", entry_local_path, entry_remote_path)); smbcli_mkdir(gp_ctx->cli->tree, entry_remote_path); if (depth < GP_MAX_DEPTH) { push_recursive(gp_ctx, entry_local_path, entry_remote_path, depth+1); } } else { DEBUG(6, ("Pushing file %s to %s on sysvol\n", entry_local_path, entry_remote_path)); remote_fd = smbcli_open(gp_ctx->cli->tree, entry_remote_path, O_WRONLY | O_CREAT, 0); if (remote_fd < 0) { talloc_free(entry_local_path); talloc_free(entry_remote_path); DEBUG(0, ("Failed to create remote file: %s\n", entry_remote_path)); return NT_STATUS_UNSUCCESSFUL; } local_fd = open(entry_local_path, O_RDONLY); if (local_fd < 0) { talloc_free(entry_local_path); talloc_free(entry_remote_path); DEBUG(0, ("Failed to open local file: %s\n", entry_local_path)); return NT_STATUS_UNSUCCESSFUL; } total_read = 0; while ((nread = read(local_fd, &buf, sizeof(buf)))) { smbcli_write(gp_ctx->cli->tree, remote_fd, 0, &buf, total_read, nread); total_read += nread; } close(local_fd); smbcli_close(gp_ctx->cli->tree, remote_fd); } talloc_free(entry_local_path); talloc_free(entry_remote_path); } closedir(dir); return NT_STATUS_OK; }