s3: smbclient: Implement "volume" command over SMB2.
authorJeremy Allison <jra@samba.org>
Tue, 14 Nov 2017 23:42:14 +0000 (15:42 -0800)
committerAndreas Schneider <asn@cryptomilk.org>
Wed, 15 Nov 2017 14:56:24 +0000 (15:56 +0100)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13140

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/libsmb/cli_smb2_fnum.c
source3/libsmb/cli_smb2_fnum.h
source3/libsmb/clifsinfo.c

index cb5c6fef4c02a55a17fda84736c099314397595c..628b17b293b681fd86d7a00f902a8f4e6a5f848f 100644 (file)
@@ -2168,6 +2168,136 @@ fail:
        return status;
 }
 
+/***************************************************************
+ Wrapper that allows SMB2 to query file system volume info.
+ Synchronous only.
+***************************************************************/
+
+NTSTATUS cli_smb2_get_fs_volume_info(struct cli_state *cli,
+                                TALLOC_CTX *mem_ctx,
+                                char **_volume_name,
+                                uint32_t *pserial_number,
+                                time_t *pdate)
+{
+       NTSTATUS status;
+       uint16_t fnum = 0xffff;
+       DATA_BLOB outbuf = data_blob_null;
+       struct smb2_hnd *ph = NULL;
+       uint32_t nlen;
+       char *volume_name = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       if (smbXcli_conn_has_async_calls(cli->conn)) {
+               /*
+                * Can't use sync call while an async call is in flight
+                */
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
+       }
+
+       if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
+       }
+
+       /* First open the top level directory. */
+       status =
+           cli_smb2_create_fnum(cli, "", 0,               /* create_flags */
+                                FILE_READ_ATTRIBUTES,     /* desired_access */
+                                FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
+                                FILE_SHARE_READ | FILE_SHARE_WRITE |
+                                    FILE_SHARE_DELETE, /* share_access */
+                                FILE_OPEN,             /* create_disposition */
+                                FILE_DIRECTORY_FILE,   /* create_options */
+                                &fnum,
+                                NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               goto fail;
+       }
+
+       status = map_fnum_to_smb2_handle(cli, fnum, &ph);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto fail;
+       }
+
+       /* getinfo on the returned handle with info_type SMB2_GETINFO_FS (2),
+          level 1 (SMB_FS_VOLUME_INFORMATION). */
+
+       status = smb2cli_query_info(cli->conn,
+                               cli->timeout,
+                               cli->smb2.session,
+                               cli->smb2.tcon,
+                               SMB2_GETINFO_FS, /* in_info_type */
+                               /* in_file_info_class */
+                               SMB_FS_VOLUME_INFORMATION - 1000,
+                               0xFFFF, /* in_max_output_length */
+                               NULL, /* in_input_buffer */
+                               0, /* in_additional_info */
+                               0, /* in_flags */
+                               ph->fid_persistent,
+                               ph->fid_volatile,
+                               frame,
+                               &outbuf);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto fail;
+       }
+
+       if (outbuf.length < 24) {
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto fail;
+       }
+
+       if (pdate) {
+               struct timespec ts;
+               ts = interpret_long_date((char *)outbuf.data);
+               *pdate = ts.tv_sec;
+       }
+       if (pserial_number) {
+               *pserial_number = IVAL(outbuf.data,8);
+       }
+       nlen = IVAL(outbuf.data,12);
+       if (nlen + 18 < 18) {
+               /* Integer wrap. */
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto fail;
+       }
+       /*
+        * The next check is safe as we know outbuf.length >= 24
+        * from above.
+        */
+       if (nlen > (outbuf.length - 18)) {
+               status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               goto fail;
+       }
+
+       clistr_pull_talloc(mem_ctx,
+                       (const char *)outbuf.data,
+                       0,
+                       &volume_name,
+                       outbuf.data + 18,
+                       nlen,
+                       STR_UNICODE);
+       if (volume_name == NULL) {
+               status = map_nt_error_from_unix(errno);
+               goto fail;
+       }
+
+       *_volume_name = volume_name;
+
+fail:
+
+       if (fnum != 0xffff) {
+               cli_smb2_close_fnum(cli, fnum);
+       }
+
+       cli->raw_status = status;
+
+       TALLOC_FREE(frame);
+       return status;
+}
+
+
 /***************************************************************
  Wrapper that allows SMB2 to query a security descriptor.
  Synchronous only.
index 793efc719eaf89f8a555806016271b2d3c4b4a55..3d9b6eb3fe64e3cce17535e27010d796d04dd25f 100644 (file)
@@ -142,6 +142,11 @@ NTSTATUS cli_smb2_get_fs_full_size_info(struct cli_state *cli,
                        uint64_t *actual_allocation_units,
                        uint64_t *sectors_per_allocation_unit,
                        uint64_t *bytes_per_sector);
+NTSTATUS cli_smb2_get_fs_volume_info(struct cli_state *cli,
+                       TALLOC_CTX *mem_ctx,
+                       char **_volume_name,
+                       uint32_t *pserial_number,
+                       time_t *pdate);
 NTSTATUS cli_smb2_query_security_descriptor(struct cli_state *cli,
                        uint16_t fnum,
                        uint32_t sec_info,
index 462363900223674325c10d8dbbec76d847d31858..09c0d9535f1d165db3f861197de9115194746a78 100644 (file)
@@ -375,6 +375,14 @@ NTSTATUS cli_get_fs_volume_info(struct cli_state *cli,
        unsigned int nlen;
        char *volume_name = NULL;
 
+       if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+               return cli_smb2_get_fs_volume_info(cli,
+                                               mem_ctx,
+                                               _volume_name,
+                                               pserial_number,
+                                               pdate);
+       }
+
        SSVAL(setup, 0, TRANSACT2_QFSINFO);
        SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);