r14173: change smb interface structures to always use
[jelmer/samba4-debian.git] / source / libcli / smb2 / getinfo.c
index fe27cc711b3083917f1f14b529e39c4b7a4f6117..3710fdfa081e0224a27b6ee46732ab070220a61e 100644 (file)
@@ -41,9 +41,9 @@ struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getin
        SSVAL(req->out.body, 0x02, io->in.level);
        SIVAL(req->out.body, 0x04, io->in.max_response_size);
        SIVAL(req->out.body, 0x08, io->in.unknown1);
-       SIVAL(req->out.body, 0x0C, io->in.flags);
-       SIVAL(req->out.body, 0x10, io->in.unknown3);
-       SIVAL(req->out.body, 0x14, io->in.unknown4);
+       SIVAL(req->out.body, 0x0C, io->in.unknown2);
+       SIVAL(req->out.body, 0x10, io->in.flags);
+       SIVAL(req->out.body, 0x14, io->in.flags2);
        smb2_push_handle(req->out.body+0x18, &io->in.handle);
 
        smb2_transport_send(req);
@@ -87,203 +87,55 @@ NTSTATUS smb2_getinfo(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
 
 
 /*
-  parse a returned getinfo data blob
+  map a generic info level to a SMB2 info level
 */
-NTSTATUS smb2_getinfo_parse(TALLOC_CTX *mem_ctx, 
-                           uint16_t level,
-                           DATA_BLOB blob,
-                           union smb2_fileinfo *io)
+uint16_t smb2_getinfo_map_level(uint16_t level, uint8_t class)
 {
-       switch (level) {
-       case SMB2_GETINFO_FILE_BASIC_INFO:
-               if (blob.length != 0x28) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->basic_info.create_time = smbcli_pull_nttime(blob.data, 0x00);
-               io->basic_info.access_time = smbcli_pull_nttime(blob.data, 0x08);
-               io->basic_info.write_time  = smbcli_pull_nttime(blob.data, 0x10);
-               io->basic_info.change_time = smbcli_pull_nttime(blob.data, 0x18);
-               io->basic_info.file_attr   = IVAL(blob.data, 0x20);
-               io->basic_info.unknown     = IVAL(blob.data, 0x24);
-               break;
-
-       case SMB2_GETINFO_FILE_SIZE_INFO:
-               if (blob.length != 0x18) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->size_info.alloc_size     = BVAL(blob.data, 0x00);
-               io->size_info.size           = BVAL(blob.data, 0x08);
-               io->size_info.nlink          = IVAL(blob.data, 0x10);
-               io->size_info.delete_pending = CVAL(blob.data, 0x14);
-               io->size_info.directory      = CVAL(blob.data, 0x15);
-               break;
-
-       case SMB2_GETINFO_FILE_ID:
-               if (blob.length != 0x8) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->file_id.file_id = BVAL(blob.data, 0x00);
-               break;
-
-       case SMB2_GETINFO_FILE_EA_SIZE:
-               if (blob.length != 0x4) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->ea_size.ea_size = IVAL(blob.data, 0x00);
-               break;
-
-       case SMB2_GETINFO_FILE_ACCESS_INFO:
-               if (blob.length != 0x4) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->access_info.access_mask = IVAL(blob.data, 0x00);
-               break;
-
-       case SMB2_GETINFO_FILE_0E:
-               if (blob.length != 0x8) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->unknown0e.unknown1     = IVAL(blob.data, 0x00);
-               io->unknown0e.unknown2     = IVAL(blob.data, 0x04);
-               break;
-
-       case SMB2_GETINFO_FILE_ALL_EAS:
-               return ea_pull_list_chained(&blob, mem_ctx, 
-                                           &io->all_eas.num_eas,
-                                           &io->all_eas.eas);
-
-       case SMB2_GETINFO_FILE_10:
-               if (blob.length != 0x4) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->unknown10.unknown     = IVAL(blob.data, 0x00);
-               break;
-
-       case SMB2_GETINFO_FILE_11:
-               if (blob.length != 0x4) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->unknown11.unknown     = IVAL(blob.data, 0x00);
-               break;
-
-       case SMB2_GETINFO_FILE_ALL_INFO: {
-               uint32_t nlen;
-               ssize_t size;
-               void *vstr;
-               if (blob.length < 0x64) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->all_info.create_time    = smbcli_pull_nttime(blob.data, 0x00);
-               io->all_info.access_time    = smbcli_pull_nttime(blob.data, 0x08);
-               io->all_info.write_time     = smbcli_pull_nttime(blob.data, 0x10);
-               io->all_info.change_time    = smbcli_pull_nttime(blob.data, 0x18);
-               io->all_info.file_attr      = IVAL(blob.data, 0x20);
-               io->all_info.unknown1       = IVAL(blob.data, 0x24);
-               io->all_info.alloc_size     = BVAL(blob.data, 0x28);
-               io->all_info.size           = BVAL(blob.data, 0x30);
-               io->all_info.nlink          = IVAL(blob.data, 0x38);
-               io->all_info.delete_pending = CVAL(blob.data, 0x3C);
-               io->all_info.directory      = CVAL(blob.data, 0x3D);
-               io->all_info.file_id        = BVAL(blob.data, 0x40);
-               io->all_info.ea_size        = IVAL(blob.data, 0x48);
-               io->all_info.access_mask    = IVAL(blob.data, 0x4C);
-               io->all_info.unknown5       = BVAL(blob.data, 0x50);
-               io->all_info.unknown6       = BVAL(blob.data, 0x58);
-               nlen                        = IVAL(blob.data, 0x60);
-               if (nlen > blob.length - 0x64) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               size = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, 
-                                            blob.data+0x64, nlen, &vstr);
-               if (size == -1) {
-                       return NT_STATUS_ILLEGAL_CHARACTER;
-               }
-               io->all_info.fname = vstr;
-               break;
+       if (class == SMB2_GETINFO_FILE && 
+           level == RAW_FILEINFO_SEC_DESC) {
+               return SMB2_GETINFO_SECURITY;
        }
+       if ((level & 0xFF) == class) {
+               return level;
+       } else if (level > 1000) {
+               return ((level-1000)<<8) | class;
+       }
+       DEBUG(0,("Unable to map SMB2 info level 0x%04x of class %d\n", level, class));
+       return 0;       
+}
 
-       case SMB2_GETINFO_FILE_SHORT_INFO: {
-               uint32_t nlen;
-               ssize_t size;
-               void *vstr;
-               if (blob.length < 0x04) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               nlen                     = IVAL(blob.data, 0x00);
-               if (nlen > blob.length - 0x04) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               size = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, 
-                                            blob.data+0x04, nlen, &vstr);
-               if (size == -1) {
-                       return NT_STATUS_ILLEGAL_CHARACTER;
-               }
-               io->short_info.short_name = vstr;
-               break;
+/*
+  level specific getinfo call - async send
+*/
+struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fileinfo *io)
+{
+       struct smb2_getinfo b;
+       uint16_t smb2_level = smb2_getinfo_map_level(io->generic.level, SMB2_GETINFO_FILE);
+       
+       if (smb2_level == 0) {
+               return NULL;
        }
 
-       case SMB2_GETINFO_FILE_STREAM_INFO:
-               return smbcli_parse_stream_info(blob, mem_ctx, &io->stream_info);
-
-       case SMB2_GETINFO_FILE_EOF_INFO:
-               if (blob.length != 0x10) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->eof_info.size     = BVAL(blob.data, 0x00);
-               io->eof_info.unknown  = BVAL(blob.data, 0x08);
-               break;
-
-       case SMB2_GETINFO_FILE_STANDARD_INFO:
-               if (blob.length != 0x38) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->standard_info.create_time = smbcli_pull_nttime(blob.data, 0x00);
-               io->standard_info.access_time = smbcli_pull_nttime(blob.data, 0x08);
-               io->standard_info.write_time  = smbcli_pull_nttime(blob.data, 0x10);
-               io->standard_info.change_time = smbcli_pull_nttime(blob.data, 0x18);
-               io->standard_info.alloc_size  = BVAL(blob.data, 0x20);
-               io->standard_info.size        = BVAL(blob.data, 0x28);
-               io->standard_info.file_attr   = IVAL(blob.data, 0x30);
-               io->standard_info.unknown     = IVAL(blob.data, 0x34);
-               break;
-
-       case SMB2_GETINFO_FILE_ATTRIB_INFO:
-               if (blob.length != 0x08) {
-                       return NT_STATUS_INFO_LENGTH_MISMATCH;
-               }
-               io->attrib_info.file_attr   = IVAL(blob.data, 0x00);
-               io->attrib_info.unknown     = IVAL(blob.data, 0x04);
-               break;
-
-       case SMB2_GETINFO_SECURITY: {
-               struct ndr_pull *ndr;
-               NTSTATUS status;
-               ndr = ndr_pull_init_blob(&blob, mem_ctx);
-               if (!ndr) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-               io->security.sd = talloc(mem_ctx, struct security_descriptor);
-               if (io->security.sd == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-               status = ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, io->security.sd);
-               talloc_free(ndr);
-               return status;
+       ZERO_STRUCT(b);
+       b.in.max_response_size = 0x10000;
+       b.in.handle            = io->generic.file.handle;
+       b.in.level             = smb2_level;
+
+       if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
+               b.in.flags = io->query_secdesc.in.secinfo_flags;
        }
-               
-       default:
-               return NT_STATUS_INVALID_INFO_CLASS;
+       if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) {
+               b.in.flags2 = io->all_eas.in.continue_flags;
        }
 
-       return NT_STATUS_OK;
+       return smb2_getinfo_send(tree, &b);
 }
 
-
 /*
   recv a getinfo reply and parse the level info
 */
-NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
-                                uint16_t level, union smb2_fileinfo *io)
+NTSTATUS smb2_getinfo_file_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
+                               union smb_fileinfo *io)
 {
        struct smb2_getinfo b;
        NTSTATUS status;
@@ -291,7 +143,7 @@ NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
        status = smb2_getinfo_recv(req, mem_ctx, &b);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       status = smb2_getinfo_parse(mem_ctx, level, b.out.blob, io);
+       status = smb_raw_fileinfo_passthru_parse(&b.out.blob, mem_ctx, io->generic.level, io);
        data_blob_free(&b.out.blob);
 
        return status;
@@ -300,19 +152,59 @@ NTSTATUS smb2_getinfo_level_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
 /*
   level specific getinfo call
 */
-NTSTATUS smb2_getinfo_level(struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
-                           struct smb2_handle handle,
-                           uint16_t level, union smb2_fileinfo *io)
+NTSTATUS smb2_getinfo_file(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, 
+                          union smb_fileinfo *io)
 {
-       struct smb2_getinfo b;
-       struct smb2_request *req;
+       struct smb2_request *req = smb2_getinfo_file_send(tree, io);
+       return smb2_getinfo_file_recv(req, mem_ctx, io);
+}
 
+
+/*
+  level specific getinfo call - async send
+*/
+struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsinfo *io)
+{
+       struct smb2_getinfo b;
+       uint16_t smb2_level = smb2_getinfo_map_level(io->generic.level, SMB2_GETINFO_FS);
+       
+       if (smb2_level == 0) {
+               return NULL;
+       }
+       
        ZERO_STRUCT(b);
        b.in.max_response_size = 0x10000;
-       b.in.handle            = handle;
-       b.in.level             = level;
+       b.in.handle            = io->generic.handle;
+       b.in.level             = smb2_level;
 
-       req = smb2_getinfo_send(tree, &b);
-       
-       return smb2_getinfo_level_recv(req, mem_ctx, level, io);
+       return smb2_getinfo_send(tree, &b);
 }
+
+/*
+  recv a getinfo reply and parse the level info
+*/
+NTSTATUS smb2_getinfo_fs_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
+                               union smb_fsinfo *io)
+{
+       struct smb2_getinfo b;
+       NTSTATUS status;
+
+       status = smb2_getinfo_recv(req, mem_ctx, &b);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       status = smb_raw_fsinfo_passthru_parse(b.out.blob, mem_ctx, io->generic.level, io);
+       data_blob_free(&b.out.blob);
+
+       return status;
+}
+
+/*
+  level specific getinfo call
+*/
+NTSTATUS smb2_getinfo_fs(struct smb2_tree *tree, TALLOC_CTX *mem_ctx, 
+                          union smb_fsinfo *io)
+{
+       struct smb2_request *req = smb2_getinfo_fs_send(tree, io);
+       return smb2_getinfo_fs_recv(req, mem_ctx, io);
+}
+