libsmb: Move cli_raw_ioctl() to torture3
[samba.git] / source3 / torture / torture.c
index acf245f3cb5bf9ab69a2590b5de692f0c33955be..bfce1c9dcd659df64c6d52b885678b7b082a8565 100644 (file)
@@ -656,6 +656,54 @@ static bool check_error(int line, NTSTATUS status,
        return True;
 }
 
+NTSTATUS cli_qpathinfo1(struct cli_state *cli,
+                       const char *fname,
+                       time_t *change_time,
+                       time_t *access_time,
+                       time_t *write_time,
+                       off_t *size,
+                       uint32_t *pattr)
+{
+       int timezone = smb1cli_conn_server_time_zone(cli->conn);
+       time_t (*date_fn)(const void *buf, int serverzone) = NULL;
+       uint8_t *rdata = NULL;
+       uint32_t num_rdata;
+       NTSTATUS status;
+
+       status = cli_qpathinfo(talloc_tos(),
+                              cli,
+                              fname,
+                              SMB_INFO_STANDARD,
+                              22,
+                              CLI_BUFFER_SIZE,
+                              &rdata,
+                              &num_rdata);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       if (cli->win95) {
+               date_fn = make_unix_date;
+       } else {
+               date_fn = make_unix_date2;
+       }
+
+       if (change_time) {
+               *change_time = date_fn(rdata + 0, timezone);
+       }
+       if (access_time) {
+               *access_time = date_fn(rdata + 4, timezone);
+       }
+       if (write_time) {
+               *write_time = date_fn(rdata + 8, timezone);
+       }
+       if (size) {
+               *size = PULL_LE_U32(rdata, 12);
+       }
+       if (pattr) {
+               *pattr = PULL_LE_U16(rdata, l1_attrFile);
+       }
+       return NT_STATUS_OK;
+}
 
 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
 {
@@ -5846,7 +5894,7 @@ static bool run_deletetest(int dummy)
 
   fail:
        /* FIXME: This will crash if we aborted before cli2 got
-        * intialized, because these functions don't handle
+        * initialized, because these functions don't handle
         * uninitialized connections. */
 
        if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
@@ -9852,6 +9900,42 @@ static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
 }
 
 
+/*
+   send a raw ioctl - used by the torture code
+*/
+static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
+                             uint16_t fnum,
+                             uint32_t code,
+                             DATA_BLOB *blob)
+{
+       uint16_t vwv[3];
+       NTSTATUS status;
+
+       PUSH_LE_U16(vwv + 0, 0, fnum);
+       PUSH_LE_U16(vwv + 1, 0, code >> 16);
+       PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
+
+       status = cli_smb(talloc_tos(),
+                        cli,
+                        SMBioctl,
+                        0,
+                        3,
+                        vwv,
+                        0,
+                        NULL,
+                        NULL,
+                        0,
+                        NULL,
+                        NULL,
+                        NULL,
+                        NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       *blob = data_blob_null;
+       return NT_STATUS_OK;
+}
+
 /*
   sees what IOCTLs are supported
  */
@@ -9908,7 +9992,7 @@ bool torture_ioctl_test(int dummy)
 
 
 /*
-  tries varients of chkpath
+  tries variants of chkpath
  */
 bool torture_chkpath_test(int dummy)
 {
@@ -10073,7 +10157,7 @@ static bool run_eatest(int dummy)
        }
 
        /* Setting EA's to zero length deletes them. Test this */
-       printf("Now deleting all EA's - case indepenent....\n");
+       printf("Now deleting all EA's - case independent....\n");
 
 #if 1
        cli_set_ea_path(cli, fname, "", "", 0);
@@ -10176,7 +10260,7 @@ static bool run_dirtest1(int dummy)
                correct = False;
 
        /* Ensure if we have the "must have" bits we only see the
-        * relevent entries.
+        * relevant entries.
         */
        num_seen = 0;
        cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
@@ -10955,9 +11039,6 @@ static bool run_mangle1(int dummy)
        uint16_t fnum;
        fstring alt_name;
        NTSTATUS status;
-       time_t change_time, access_time, write_time;
-       off_t size;
-       uint32_t attr;
 
        printf("starting mangle1 test\n");
        if (!torture_open_connection(&cli, 0)) {
@@ -10991,8 +11072,7 @@ static bool run_mangle1(int dummy)
        }
        cli_close(cli, fnum);
 
-       status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
-                               &write_time, &size, &attr);
+       status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
                         nt_errstr(status));
@@ -14645,6 +14725,395 @@ static bool run_local_canonicalize_path(int dummy)
        }
        return true;
 }
+struct session_setup_nt1_truncated_state {
+       uint16_t vwv[13];
+       uint8_t bytes[20];
+};
+
+static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
+
+static struct tevent_req *smb1_session_setup_nt1_truncated_send(
+               TALLOC_CTX *mem_ctx,
+               struct tevent_context *ev,
+               struct smbXcli_conn *conn)
+{
+       uint16_t *vwv = NULL;
+       uint8_t *bytes = NULL;
+       const char *pass = "12345678";
+       const char *uname = "z";
+       struct session_setup_nt1_truncated_state *state = NULL;
+       struct tevent_req *req = NULL;
+       struct tevent_req *subreq = NULL;
+
+       req = tevent_req_create(mem_ctx,
+                               &state,
+                               struct session_setup_nt1_truncated_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       vwv = &state->vwv[0];
+       bytes = &state->bytes[0];
+
+       SCVAL(vwv+0,  0, 0xff);
+       SCVAL(vwv+0,  1, 0);
+       SSVAL(vwv+1,  0, 0);
+       SSVAL(vwv+2,  0, 8192);
+       SSVAL(vwv+3,  0, 2);
+       SSVAL(vwv+4,  0, 1);
+       SIVAL(vwv+5,  0, 0);
+       SSVAL(vwv+7,  0, strlen(pass)); /* OEMPasswordLen */
+       SSVAL(vwv+8,  0, 0); /* UnicodePasswordLen */
+       SSVAL(vwv+9,  0, 0); /* reserved */
+       SSVAL(vwv+10, 0, 0); /* reserved */
+       SIVAL(vwv+11, 0, CAP_STATUS32);
+
+       memcpy(bytes, pass, strlen(pass));
+       bytes += strlen(pass);
+       memcpy(bytes, uname, strlen(uname)+1);
+
+       subreq = smb1cli_req_send(state, ev, conn,
+                                 SMBsesssetupX,
+                                 0, /*  additional_flags */
+                                 0, /*  clear_flags */
+                                 0, /*  additional_flags2 */
+                                 0, /*  clear_flags2 */
+                                 10000, /* timeout_msec */
+                                 getpid(),
+                                 NULL, /* tcon */
+                                 NULL, /* session */
+                                 13, /* wct */
+                                 state->vwv,
+                                 strlen(pass), /* Truncate length at password. */
+                                 state->bytes);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq,
+                               smb1_session_setup_nt1_truncated_done,
+                               req);
+       return req;
+}
+
+static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq,
+               struct tevent_req);
+       struct session_setup_nt1_truncated_state *state =
+               tevent_req_data(req,
+               struct session_setup_nt1_truncated_state);
+       NTSTATUS status;
+       struct smb1cli_req_expected_response expected[] = {
+       {
+               .status = NT_STATUS_OK,
+               .wct    = 3,
+       },
+       };
+
+       status = smb1cli_req_recv(subreq, state,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL, /* pvwv_offset */
+                                 NULL,
+                                 NULL,
+                                 NULL, /* pbytes_offset */
+                                 NULL,
+                                 expected, ARRAY_SIZE(expected));
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+       tevent_req_done(req);
+}
+
+static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+static bool run_smb1_truncated_sesssetup(int dummy)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       struct smbXcli_conn *conn;
+       struct sockaddr_storage ss;
+       NTSTATUS status;
+       int fd;
+       bool ok;
+
+       printf("Starting send truncated SMB1 sesssetup.\n");
+
+       ok = resolve_name(host, &ss, 0x20, true);
+       if (!ok) {
+               d_fprintf(stderr, "Could not resolve name %s\n", host);
+               return false;
+       }
+
+       status = open_socket_out(&ss, 445, 10000, &fd);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "open_socket_out failed: %s\n",
+                         nt_errstr(status));
+               return false;
+       }
+
+       conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
+                                  NULL, 0, NULL);
+       if (conn == NULL) {
+               d_fprintf(stderr, "smbXcli_conn_create failed\n");
+               return false;
+       }
+
+       status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "smbXcli_negprot failed!\n");
+               return false;
+       }
+
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               d_fprintf(stderr, "samba_tevent_context_init failed\n");
+               return false;
+       }
+
+       req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
+       if (req == NULL) {
+               d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
+               return false;
+       }
+
+       ok = tevent_req_poll_ntstatus(req, ev, &status);
+       if (!ok) {
+               d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
+                       nt_errstr(status));
+               return false;
+       }
+
+       status = smb1_session_setup_nt1_truncated_recv(req);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
+                         "%s, expected NT_STATUS_OK\n",
+                         nt_errstr(status));
+               return false;
+       }
+
+       TALLOC_FREE(conn);
+       return true;
+}
+
+struct smb1_negotiate_exit_state {
+       int dummy;
+};
+
+static void smb1_negotiate_exit_done(struct tevent_req *subreq);
+
+static struct tevent_req *smb1_negotiate_exit_send(
+               TALLOC_CTX *mem_ctx,
+               struct tevent_context *ev,
+               struct smbXcli_conn *conn)
+{
+       struct smb1_negotiate_exit_state *state = NULL;
+       struct tevent_req *req = NULL;
+       struct tevent_req *subreq = NULL;
+
+       req = tevent_req_create(mem_ctx,
+                               &state,
+                               struct smb1_negotiate_exit_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       subreq = smb1cli_req_send(state, ev, conn,
+                                 SMBexit,
+                                 0, /*  additional_flags */
+                                 0, /*  clear_flags */
+                                 0, /*  additional_flags2 */
+                                 0, /*  clear_flags2 */
+                                 10000, /* timeout_msec */
+                                 getpid(),
+                                 NULL, /* tcon */
+                                 NULL, /* session */
+                                 0, /* wct */
+                                 NULL,
+                                 0,
+                                 NULL);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq,
+                               smb1_negotiate_exit_done,
+                               req);
+       return req;
+}
+
+static void smb1_negotiate_exit_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq,
+               struct tevent_req);
+       struct smb1_negotiate_exit_state *state =
+               tevent_req_data(req,
+               struct smb1_negotiate_exit_state);
+       NTSTATUS status;
+       struct smb1cli_req_expected_response expected[] = {
+       {
+               .status = NT_STATUS_OK,
+               .wct    = 0,
+       },
+       };
+
+       status = smb1cli_req_recv(subreq, state,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 NULL, /* pvwv_offset */
+                                 NULL,
+                                 NULL,
+                                 NULL, /* pbytes_offset */
+                                 NULL,
+                                 expected, ARRAY_SIZE(expected));
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+       tevent_req_done(req);
+}
+
+static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct smbXcli_conn *conn)
+{
+       struct tevent_req *req;
+       bool ok;
+       NTSTATUS status;
+       NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
+
+       req = smb1_negotiate_exit_send(ev, ev, conn);
+       if (req == NULL) {
+               d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
+               return false;
+       }
+
+       ok = tevent_req_poll_ntstatus(req, ev, &status);
+       if (!ok) {
+               d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
+                       nt_errstr(status));
+               return false;
+       }
+
+       status = smb1_negotiate_exit_recv(req);
+       if (!NT_STATUS_EQUAL(status, expected_status)) {
+               d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
+                         "%s, expected ERRSRV, ERRinvnid\n",
+                         nt_errstr(status));
+               return false;
+       }
+       return true;
+}
+
+static bool run_smb1_negotiate_exit(int dummy)
+{
+       struct tevent_context *ev;
+       struct smbXcli_conn *conn;
+       struct sockaddr_storage ss;
+       NTSTATUS status;
+       int fd;
+       bool ok;
+
+       printf("Starting send SMB1 negotiate+exit.\n");
+
+       ok = resolve_name(host, &ss, 0x20, true);
+       if (!ok) {
+               d_fprintf(stderr, "Could not resolve name %s\n", host);
+               return false;
+       }
+
+       status = open_socket_out(&ss, 445, 10000, &fd);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "open_socket_out failed: %s\n",
+                         nt_errstr(status));
+               return false;
+       }
+
+       conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
+                                  NULL, 0, NULL);
+       if (conn == NULL) {
+               d_fprintf(stderr, "smbXcli_conn_create failed\n");
+               return false;
+       }
+
+       status = smbXcli_negprot(conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "smbXcli_negprot failed!\n");
+               return false;
+       }
+
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               d_fprintf(stderr, "samba_tevent_context_init failed\n");
+               return false;
+       }
+
+       /*
+        * Call do_smb1_exit twice to catch a server crash, the
+        * server sends the first return code then crashes.
+        */
+       ok = do_smb1_exit(ev, ev, conn);
+       if (!ok) {
+               d_fprintf(stderr, "do_smb1_exit (1) failed\n");
+               return false;
+       }
+       ok = do_smb1_exit(ev, ev, conn);
+       if (!ok) {
+               d_fprintf(stderr, "do_smb1_exit (2) failed\n");
+               return false;
+       }
+
+       TALLOC_FREE(conn);
+       return true;
+}
+
+static bool run_smb1_negotiate_tcon(int dummy)
+{
+       struct cli_state *cli = NULL;
+       uint16_t cnum = 0;
+       uint16_t max_xmit = 0;
+       NTSTATUS status;
+
+       printf("Starting send SMB1 negotiate+tcon.\n");
+       cli = open_nbt_connection();
+       if (cli == NULL) {
+               d_fprintf(stderr, "open_nbt_connection failed!\n");
+               return false;
+       }
+       smbXcli_conn_set_sockopt(cli->conn, sockops);
+
+       status = smbXcli_negprot(cli->conn, 0, PROTOCOL_NT1, PROTOCOL_NT1);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
+                       nt_errstr(status));
+               return false;
+       }
+        status = cli_raw_tcon(cli,
+                             share,
+                             "",
+                             "?????",
+                             &max_xmit,
+                             &cnum);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
+               d_fprintf(stderr, "cli_raw_tcon failed - got %s "
+                       "(should get NT_STATUS_ACCESS_DENIED)!\n",
+                       nt_errstr(status));
+               return false;
+       }
+       return true;
+}
 
 static bool run_ign_bad_negprot(int dummy)
 {
@@ -14721,6 +15190,7 @@ static bool run_ign_bad_negprot(int dummy)
        return true;
 }
 
+
 static double create_procs(bool (*fn)(int), bool *result)
 {
        int i, status;
@@ -15373,6 +15843,18 @@ static struct {
                .name  = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
                .fn    = run_smb2_dfs_filename_leading_backslash,
        },
+       {
+               .name  = "SMB1-TRUNCATED-SESSSETUP",
+               .fn    = run_smb1_truncated_sesssetup,
+       },
+       {
+               .name  = "SMB1-NEGOTIATE-EXIT",
+               .fn    = run_smb1_negotiate_exit,
+       },
+       {
+               .name  = "SMB1-NEGOTIATE-TCON",
+               .fn    = run_smb1_negotiate_tcon,
+       },
        {
                .name  = "SMB1-DFS-PATHS",
                .fn    = run_smb1_dfs_paths,
@@ -15385,6 +15867,10 @@ static struct {
                .name  = "SMB1-DFS-OPERATIONS",
                .fn    = run_smb1_dfs_operations,
        },
+       {
+               .name  = "SMB1-DFS-BADPATH",
+               .fn    = run_smb1_dfs_check_badpath,
+       },
        {
                .name  = "CLEANUP1",
                .fn    = run_cleanup1,
@@ -15631,6 +16117,14 @@ static struct {
                .name  = "readdir-timestamp",
                .fn    = run_readdir_timestamp,
        },
+       {
+               .name  = "rpc-scale",
+               .fn    = run_rpc_scale,
+       },
+       {
+               .name  = "LOCAL-TDB-VALIDATE",
+               .fn    = run_tdb_validate,
+       },
        {
                .name = NULL,
        },