Message ID | 20190129065357.3935-2-lsahlber@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | smbinfo: Add more File*Information classes | expand |
An additional minor patch to add help text for the most important of the newly added info classes (fileallinfo). See attached. Also (minor/trivial point) note that in Ronnie's patch, there is a little bit of extra whitespace. On Tue, Jan 29, 2019 at 12:54 AM Ronnie Sahlberg <lsahlber@redhat.com> wrote: > > Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> > --- > smbinfo.c | 483 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > smbinfo.rst | 34 ++++- > 2 files changed, 497 insertions(+), 20 deletions(-) > > diff --git a/smbinfo.c b/smbinfo.c > index b1c129b..de9ebf6 100644 > --- a/smbinfo.c > +++ b/smbinfo.c > @@ -66,6 +66,447 @@ usage(char *name) > } > > static void > +win_to_timeval(uint64_t smb2_time, struct timeval *tv) > +{ > + tv->tv_usec = (smb2_time / 10) % 1000000; > + tv->tv_sec = (smb2_time - 116444736000000000) / 10000000; > +} > + > +struct bit_string { > + unsigned int bit; > + char *string; > +}; > + > +struct bit_string directory_access_mask[] = { > + { 0x00000001, "LIST_DIRECTORY" }, > + { 0x00000002, "ADD_FILE" }, > + { 0x00000004, "ADD_SUBDIRECTORY" }, > + { 0x00000008, "READ_EA" }, > + { 0x00000010, "WRITE_EA" }, > + { 0x00000020, "TRAVERSE" }, > + { 0x00000040, "DELETE_CHILD" }, > + { 0x00000080, "READ_ATTRIBUTES" }, > + { 0x00000100, "WRITE_ATTRIBUTES" }, > + { 0x00010000, "DELETE" }, > + { 0x00020000, "READ_CONTROL" }, > + { 0x00040000, "WRITE_DAC" }, > + { 0x00080000, "WRITE_OWNER" }, > + { 0x00100000, "SYNCHRONIZER" }, > + { 0x01000000, "ACCESS_SYSTEM_SECURITY" }, > + { 0x02000000, "MAXIMUM_ALLOWED" }, > + { 0x10000000, "GENERIC_ALL" }, > + { 0x20000000, "GENERIC_EXECUTE" }, > + { 0x40000000, "GENERIC_WRITE" }, > + { 0x80000000, "GENERIC_READ" }, > + { 0, NULL } > +}; > + > +struct bit_string file_access_mask[] = { > + { 0x00000001, "READ_DATA" }, > + { 0x00000002, "WRITE_DATA" }, > + { 0x00000004, "APPEND_DATA" }, > + { 0x00000008, "READ_EA" }, > + { 0x00000010, "WRITE_EA" }, > + { 0x00000020, "EXECUTE" }, > + { 0x00000040, "DELETE_CHILD" }, > + { 0x00000080, "READ_ATTRIBUTES" }, > + { 0x00000100, "WRITE_ATTRIBUTES" }, > + { 0x00010000, "DELETE" }, > + { 0x00020000, "READ_CONTROL" }, > + { 0x00040000, "WRITE_DAC" }, > + { 0x00080000, "WRITE_OWNER" }, > + { 0x00100000, "SYNCHRONIZER" }, > + { 0x01000000, "ACCESS_SYSTEM_SECURITY" }, > + { 0x02000000, "MAXIMUM_ALLOWED" }, > + { 0x10000000, "GENERIC_ALL" }, > + { 0x20000000, "GENERIC_EXECUTE" }, > + { 0x40000000, "GENERIC_WRITE" }, > + { 0x80000000, "GENERIC_READ" }, > + { 0, NULL } > +}; > + > +static void > +print_bits(uint32_t mask, struct bit_string *bs) > +{ > + while (bs->string) { > + if (mask & bs->bit) > + printf("%s ", bs->string); > + bs++; > + } > +} > + > +static void > +print_fileaccessinfo(uint8_t *sd, int type) > +{ > + uint32_t access_flags; > + > + memcpy(&access_flags, &sd[0], 4); > + access_flags = le32toh(access_flags); > + > + if (type == S_IFDIR) { > + printf("Directory access flags 0x%08x: ", access_flags); > + print_bits(access_flags, directory_access_mask); > + } else { > + printf("File/Printer access flags 0x%08x: ", access_flags); > + print_bits(access_flags, file_access_mask); > + } > + printf("\n"); > +} > + > +static void > +fileaccessinfo(int f) > +{ > + struct smb_query_info *qi; > + struct stat st; > + > + fstat(f, &st); > + > + qi = malloc(sizeof(struct smb_query_info) + 4); > + memset(qi, 0, sizeof(qi) + 4); > + qi->info_type = 0x01; > + qi->file_info_class = 8; > + qi->additional_information = 0; > + qi->input_buffer_length = 4; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_fileaccessinfo((uint8_t *)(&qi[1]), st.st_mode & S_IFMT); > + free(qi); > +} > + > +static void > +print_filealigninfo(uint8_t *sd) > +{ > + uint32_t mask; > + > + memcpy(&mask, &sd[0], 4); > + mask = le32toh(mask); > + > + printf("File alignment: "); > + if (mask == 0) > + printf("BYTE_ALIGNMENT"); > + else if (mask == 1) > + printf("WORD_ALIGNMENT"); > + else if (mask == 3) > + printf("LONG_ALIGNMENT"); > + else if (mask == 7) > + printf("QUAD_ALIGNMENT"); > + else if (mask == 15) > + printf("OCTA_ALIGNMENT"); > + else if (mask == 31) > + printf("32_bit_ALIGNMENT"); > + else if (mask == 63) > + printf("64_bit_ALIGNMENT"); > + else if (mask == 127) > + printf("128_bit_ALIGNMENT"); > + else if (mask == 255) > + printf("254_bit_ALIGNMENT"); > + else if (mask == 511) > + printf("512_bit_ALIGNMENT"); > + > + printf("\n"); > +} > + > +static void > +filealigninfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 4); > + memset(qi, 0, sizeof(qi) + 4); > + qi->info_type = 0x01; > + qi->file_info_class = 17; > + qi->additional_information = 0; > + qi->input_buffer_length = 4; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_filealigninfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +struct bit_string file_attributes_mask[] = { > + { 0x00000001, "READ_ONLY" }, > + { 0x00000002, "HIDDEN" }, > + { 0x00000004, "SYSTEM" }, > + { 0x00000010, "DIRECTORY" }, > + { 0x00000020, "ARCHIVE" }, > + { 0x00000080, "NORMAL" }, > + { 0x00000100, "TEMPORARY" }, > + { 0x00000200, "SPARSE_FILE" }, > + { 0x00000400, "REPARSE_POINT" }, > + { 0x00000800, "COMPRESSED" }, > + { 0x00001000, "OFFLINE" }, > + { 0x00002000, "NOT_CONTENT_INDEXED" }, > + { 0x00004000, "ENCRYPTED" }, > + { 0x00008000, "INTEGRITY_STREAM" }, > + { 0x00020000, "NO_SCRUB_DATA" }, > + { 0, NULL } > +}; > + > +static void > +print_filebasicinfo(uint8_t *sd) > +{ > + struct timeval tv; > + uint64_t u64; > + uint32_t u32; > + > + memcpy(&u64, &sd[0], 8); > + win_to_timeval(le64toh(u64), &tv); > + printf("Creation Time %s", ctime(&tv.tv_sec)); > + > + memcpy(&u64, &sd[8], 8); > + win_to_timeval(le64toh(u64), &tv); > + printf("Last Access Time %s", ctime(&tv.tv_sec)); > + > + memcpy(&u64, &sd[16], 8); > + win_to_timeval(le64toh(u64), &tv); > + printf("Last Write Time %s", ctime(&tv.tv_sec)); > + > + memcpy(&u64, &sd[24], 8); > + win_to_timeval(le64toh(u64), &tv); > + printf("Last Change Time %s", ctime(&tv.tv_sec)); > + > + memcpy(&u32, &sd[32], 4); > + u32 = le32toh(u32); > + printf("File Attributes 0x%08x: ", u32); > + print_bits(u32, file_attributes_mask); > + printf("\n"); > +} > + > +static void > +filebasicinfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 40); > + memset(qi, 0, sizeof(qi) + 40); > + qi->info_type = 0x01; > + qi->file_info_class = 4; > + qi->additional_information = 0; > + qi->input_buffer_length = 40; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_filebasicinfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +static void > +print_filestandardinfo(uint8_t *sd) > +{ > + uint64_t u64; > + uint32_t u32; > + > + memcpy(&u64, &sd[0], 8); > + printf("Allocation Size %" PRIu64 "\n", le64toh(u64)); > + > + memcpy(&u64, &sd[8], 8); > + printf("End Of File %" PRIu64 "\n", le64toh(u64)); > + > + memcpy(&u32, &sd[16], 4); > + printf("Number Of Links %" PRIu32 "\n", le32toh(u32)); > + > + printf("Delete Pending %d\n", sd[20]); > + printf("Delete Directory %d\n", sd[21]); > +} > + > +static void > +filestandardinfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 24); > + memset(qi, 0, sizeof(qi) + 24); > + qi->info_type = 0x01; > + qi->file_info_class = 5; > + qi->additional_information = 0; > + qi->input_buffer_length = 24; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_filestandardinfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +static void > +print_fileinternalinfo(uint8_t *sd) > +{ > + uint64_t u64; > + > + memcpy(&u64, &sd[0], 8); > + printf("Index Number %" PRIu64 "\n", le64toh(u64)); > +} > + > +static void > +fileinternalinfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 8); > + memset(qi, 0, sizeof(qi) + 8); > + qi->info_type = 0x01; > + qi->file_info_class = 6; > + qi->additional_information = 0; > + qi->input_buffer_length = 8; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_fileinternalinfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +struct bit_string file_mode_mask[] = { > + { 0x00000002, "WRITE_THROUGH" }, > + { 0x00000004, "SEQUENTIAL_ONLY" }, > + { 0x00000008, "NO_INTERMEDIATE_BUFFERING" }, > + { 0x00000010, "SYNCHRONOUS_IO_ALERT" }, > + { 0x00000020, "SYNCHRONOUS_IO_NONALERT" }, > + { 0x00001000, "DELETE_ON_CLOSE" }, > + { 0, NULL } > +}; > + > +static void > +print_filemodeinfo(uint8_t *sd) > +{ > + uint32_t u32; > + > + memcpy(&u32, &sd[32], 4); > + u32 = le32toh(u32); > + printf("Mode 0x%08x: ", u32); > + print_bits(u32, file_mode_mask); > + printf("\n"); > +} > + > +static void > +filemodeinfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 4); > + memset(qi, 0, sizeof(qi) + 4); > + qi->info_type = 0x01; > + qi->file_info_class = 16; > + qi->additional_information = 0; > + qi->input_buffer_length = 4; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_filemodeinfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +static void > +print_filepositioninfo(uint8_t *sd) > +{ > + uint64_t u64; > + > + memcpy(&u64, &sd[0], 8); > + printf("Current Byte Offset %" PRIu64 "\n", le64toh(u64)); > +} > + > +static void > +filepositioninfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 8); > + memset(qi, 0, sizeof(qi) + 8); > + qi->info_type = 0x01; > + qi->file_info_class = 14; > + qi->additional_information = 0; > + qi->input_buffer_length = 8; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_filepositioninfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +static void > +print_fileeainfo(uint8_t *sd) > +{ > + uint32_t u32; > + > + memcpy(&u32, &sd[0], 4); > + printf("Ea Size %" PRIu32 "\n", le32toh(u32)); > +} > + > +static void > +fileeainfo(int f) > +{ > + struct smb_query_info *qi; > + > + qi = malloc(sizeof(struct smb_query_info) + 4); > + memset(qi, 0, sizeof(qi) + 4); > + qi->info_type = 0x01; > + qi->file_info_class = 7; > + qi->additional_information = 0; > + qi->input_buffer_length = 4; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_fileeainfo((uint8_t *)(&qi[1])); > + free(qi); > +} > + > +static void > +fileallinfo(int f) > +{ > + struct smb_query_info *qi; > + struct stat st; > + > + fstat(f, &st); > + > + qi = malloc(sizeof(struct smb_query_info) + INPUT_BUFFER_LENGTH); > + memset(qi, 0, sizeof(qi) + INPUT_BUFFER_LENGTH); > + qi->info_type = 0x01; > + qi->file_info_class = 18; > + qi->additional_information = 0; > + qi->input_buffer_length = INPUT_BUFFER_LENGTH; > + > + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { > + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); > + exit(1); > + } > + > + print_filebasicinfo((uint8_t *)(&qi[1])); > + print_filestandardinfo((uint8_t *)(&qi[1]) + 40); > + print_fileinternalinfo((uint8_t *)(&qi[1]) + 64); > + print_fileeainfo((uint8_t *)(&qi[1]) + 72); > + print_fileaccessinfo((uint8_t *)(&qi[1]) + 76, st.st_mode & S_IFMT); > + print_filepositioninfo((uint8_t *)(&qi[1]) + 80); > + print_filemodeinfo((uint8_t *)(&qi[1]) + 88); > + print_filealigninfo((uint8_t *)(&qi[1]) + 92); > + // SMB2 servers like Win16 does not seem to return name info > + free(qi); > +} > + > +static void > print_sid(unsigned char *sd) > { > int i; > @@ -152,10 +593,13 @@ print_sd(uint8_t *sd) > } > } > > -void secdesc(int f) { > +static void > +secdesc(int f) > +{ > struct smb_query_info *qi; > > qi = malloc(sizeof(struct smb_query_info) + INPUT_BUFFER_LENGTH); > + memset(qi, 0, sizeof(qi) + INPUT_BUFFER_LENGTH); > qi->info_type = 0x03; > qi->file_info_class = 0; > qi->additional_information = 0x00000007; /* Owner, Group, Dacl */ > @@ -167,13 +611,7 @@ void secdesc(int f) { > } > > print_sd((uint8_t *)(&qi[1])); > -} > - > -void > -win_to_timeval(uint64_t smb2_time, struct timeval *tv) > -{ > - tv->tv_usec = (smb2_time / 10) % 1000000; > - tv->tv_sec = (smb2_time - 116444736000000000) / 10000000; > + free(qi); > } > > static void > @@ -236,7 +674,9 @@ print_quota(unsigned char *sd) > } > } > > -void quota(int f) { > +static void > +quota(int f) > +{ > struct smb_query_info *qi; > char *buf; > int i; > @@ -264,6 +704,7 @@ void quota(int f) { > } > > print_quota((unsigned char *)(&qi[1])); > + free(qi); > } > > int main(int argc, char *argv[]) > @@ -290,11 +731,29 @@ int main(int argc, char *argv[]) > } > > > - if (!strcmp(argv[1], "secdesc")) { > + if (!strcmp(argv[1], "fileaccessinfo")) > + fileaccessinfo(f); > + else if (!strcmp(argv[1], "filealigninfo")) > + filealigninfo(f); > + else if (!strcmp(argv[1], "fileallinfo")) > + fileallinfo(f); > + else if (!strcmp(argv[1], "filebasicinfo")) > + filebasicinfo(f); > + else if (!strcmp(argv[1], "fileeainfo")) > + fileeainfo(f); > + else if (!strcmp(argv[1], "fileinternalinfo")) > + fileinternalinfo(f); > + else if (!strcmp(argv[1], "filemodeinfo")) > + filemodeinfo(f); > + else if (!strcmp(argv[1], "filepositioninfo")) > + filepositioninfo(f); > + else if (!strcmp(argv[1], "filestandardinfo")) > + filestandardinfo(f); > + else if (!strcmp(argv[1], "secdesc")) > secdesc(f); > - } else if (!strcmp(argv[1], "quota")) { > + else if (!strcmp(argv[1], "quota")) > quota(f); > - } else { > + else { > fprintf(stderr, "Unknown command %s\n", argv[optind]); > exit(1); > } > diff --git a/smbinfo.rst b/smbinfo.rst > index e37c709..2119f93 100644 > --- a/smbinfo.rst > +++ b/smbinfo.rst > @@ -39,14 +39,23 @@ OPTIONS > COMMAND > ******* > > -`secdesc`: Print the security descriptor in the form > -- Revision > -- Control > -- Owner SID > -- Group SID > -- ACL > -- File types > -- File flags > +`fileaccessinfo`: Prints the FileAccessInformation class > + > +`filealigninfo`: Prints the FileAlignmentInformation class > + > +`fileallinfo`: Prints the FileAllInformation class > + > +`filebasicinfo`: Prints the FileBasicInformation class > + > +`fileeainfo`: Prints the FileEaInformation class > + > +`fileinternalinfo`: Prints the FileInternalInformation class > + > +`filemodeinfo`: Prints the FileModeInformation class > + > +`filepositioninfo`: Prints the FilePositionInformation class > + > +`filestandardinfo`: Prints the FileStandardInformation class > > `quota`: Print the quota for the volume in the form > - SID Length > @@ -56,6 +65,15 @@ COMMAND > - Quota Limit > - SID > > +`secdesc`: Print the security descriptor in the form > +- Revision > +- Control > +- Owner SID > +- Group SID > +- ACL > +- File types > +- File flags > + > ***** > NOTES > ***** > -- > 2.13.6 >
diff --git a/smbinfo.c b/smbinfo.c index b1c129b..de9ebf6 100644 --- a/smbinfo.c +++ b/smbinfo.c @@ -66,6 +66,447 @@ usage(char *name) } static void +win_to_timeval(uint64_t smb2_time, struct timeval *tv) +{ + tv->tv_usec = (smb2_time / 10) % 1000000; + tv->tv_sec = (smb2_time - 116444736000000000) / 10000000; +} + +struct bit_string { + unsigned int bit; + char *string; +}; + +struct bit_string directory_access_mask[] = { + { 0x00000001, "LIST_DIRECTORY" }, + { 0x00000002, "ADD_FILE" }, + { 0x00000004, "ADD_SUBDIRECTORY" }, + { 0x00000008, "READ_EA" }, + { 0x00000010, "WRITE_EA" }, + { 0x00000020, "TRAVERSE" }, + { 0x00000040, "DELETE_CHILD" }, + { 0x00000080, "READ_ATTRIBUTES" }, + { 0x00000100, "WRITE_ATTRIBUTES" }, + { 0x00010000, "DELETE" }, + { 0x00020000, "READ_CONTROL" }, + { 0x00040000, "WRITE_DAC" }, + { 0x00080000, "WRITE_OWNER" }, + { 0x00100000, "SYNCHRONIZER" }, + { 0x01000000, "ACCESS_SYSTEM_SECURITY" }, + { 0x02000000, "MAXIMUM_ALLOWED" }, + { 0x10000000, "GENERIC_ALL" }, + { 0x20000000, "GENERIC_EXECUTE" }, + { 0x40000000, "GENERIC_WRITE" }, + { 0x80000000, "GENERIC_READ" }, + { 0, NULL } +}; + +struct bit_string file_access_mask[] = { + { 0x00000001, "READ_DATA" }, + { 0x00000002, "WRITE_DATA" }, + { 0x00000004, "APPEND_DATA" }, + { 0x00000008, "READ_EA" }, + { 0x00000010, "WRITE_EA" }, + { 0x00000020, "EXECUTE" }, + { 0x00000040, "DELETE_CHILD" }, + { 0x00000080, "READ_ATTRIBUTES" }, + { 0x00000100, "WRITE_ATTRIBUTES" }, + { 0x00010000, "DELETE" }, + { 0x00020000, "READ_CONTROL" }, + { 0x00040000, "WRITE_DAC" }, + { 0x00080000, "WRITE_OWNER" }, + { 0x00100000, "SYNCHRONIZER" }, + { 0x01000000, "ACCESS_SYSTEM_SECURITY" }, + { 0x02000000, "MAXIMUM_ALLOWED" }, + { 0x10000000, "GENERIC_ALL" }, + { 0x20000000, "GENERIC_EXECUTE" }, + { 0x40000000, "GENERIC_WRITE" }, + { 0x80000000, "GENERIC_READ" }, + { 0, NULL } +}; + +static void +print_bits(uint32_t mask, struct bit_string *bs) +{ + while (bs->string) { + if (mask & bs->bit) + printf("%s ", bs->string); + bs++; + } +} + +static void +print_fileaccessinfo(uint8_t *sd, int type) +{ + uint32_t access_flags; + + memcpy(&access_flags, &sd[0], 4); + access_flags = le32toh(access_flags); + + if (type == S_IFDIR) { + printf("Directory access flags 0x%08x: ", access_flags); + print_bits(access_flags, directory_access_mask); + } else { + printf("File/Printer access flags 0x%08x: ", access_flags); + print_bits(access_flags, file_access_mask); + } + printf("\n"); +} + +static void +fileaccessinfo(int f) +{ + struct smb_query_info *qi; + struct stat st; + + fstat(f, &st); + + qi = malloc(sizeof(struct smb_query_info) + 4); + memset(qi, 0, sizeof(qi) + 4); + qi->info_type = 0x01; + qi->file_info_class = 8; + qi->additional_information = 0; + qi->input_buffer_length = 4; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_fileaccessinfo((uint8_t *)(&qi[1]), st.st_mode & S_IFMT); + free(qi); +} + +static void +print_filealigninfo(uint8_t *sd) +{ + uint32_t mask; + + memcpy(&mask, &sd[0], 4); + mask = le32toh(mask); + + printf("File alignment: "); + if (mask == 0) + printf("BYTE_ALIGNMENT"); + else if (mask == 1) + printf("WORD_ALIGNMENT"); + else if (mask == 3) + printf("LONG_ALIGNMENT"); + else if (mask == 7) + printf("QUAD_ALIGNMENT"); + else if (mask == 15) + printf("OCTA_ALIGNMENT"); + else if (mask == 31) + printf("32_bit_ALIGNMENT"); + else if (mask == 63) + printf("64_bit_ALIGNMENT"); + else if (mask == 127) + printf("128_bit_ALIGNMENT"); + else if (mask == 255) + printf("254_bit_ALIGNMENT"); + else if (mask == 511) + printf("512_bit_ALIGNMENT"); + + printf("\n"); +} + +static void +filealigninfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 4); + memset(qi, 0, sizeof(qi) + 4); + qi->info_type = 0x01; + qi->file_info_class = 17; + qi->additional_information = 0; + qi->input_buffer_length = 4; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_filealigninfo((uint8_t *)(&qi[1])); + free(qi); +} + +struct bit_string file_attributes_mask[] = { + { 0x00000001, "READ_ONLY" }, + { 0x00000002, "HIDDEN" }, + { 0x00000004, "SYSTEM" }, + { 0x00000010, "DIRECTORY" }, + { 0x00000020, "ARCHIVE" }, + { 0x00000080, "NORMAL" }, + { 0x00000100, "TEMPORARY" }, + { 0x00000200, "SPARSE_FILE" }, + { 0x00000400, "REPARSE_POINT" }, + { 0x00000800, "COMPRESSED" }, + { 0x00001000, "OFFLINE" }, + { 0x00002000, "NOT_CONTENT_INDEXED" }, + { 0x00004000, "ENCRYPTED" }, + { 0x00008000, "INTEGRITY_STREAM" }, + { 0x00020000, "NO_SCRUB_DATA" }, + { 0, NULL } +}; + +static void +print_filebasicinfo(uint8_t *sd) +{ + struct timeval tv; + uint64_t u64; + uint32_t u32; + + memcpy(&u64, &sd[0], 8); + win_to_timeval(le64toh(u64), &tv); + printf("Creation Time %s", ctime(&tv.tv_sec)); + + memcpy(&u64, &sd[8], 8); + win_to_timeval(le64toh(u64), &tv); + printf("Last Access Time %s", ctime(&tv.tv_sec)); + + memcpy(&u64, &sd[16], 8); + win_to_timeval(le64toh(u64), &tv); + printf("Last Write Time %s", ctime(&tv.tv_sec)); + + memcpy(&u64, &sd[24], 8); + win_to_timeval(le64toh(u64), &tv); + printf("Last Change Time %s", ctime(&tv.tv_sec)); + + memcpy(&u32, &sd[32], 4); + u32 = le32toh(u32); + printf("File Attributes 0x%08x: ", u32); + print_bits(u32, file_attributes_mask); + printf("\n"); +} + +static void +filebasicinfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 40); + memset(qi, 0, sizeof(qi) + 40); + qi->info_type = 0x01; + qi->file_info_class = 4; + qi->additional_information = 0; + qi->input_buffer_length = 40; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_filebasicinfo((uint8_t *)(&qi[1])); + free(qi); +} + +static void +print_filestandardinfo(uint8_t *sd) +{ + uint64_t u64; + uint32_t u32; + + memcpy(&u64, &sd[0], 8); + printf("Allocation Size %" PRIu64 "\n", le64toh(u64)); + + memcpy(&u64, &sd[8], 8); + printf("End Of File %" PRIu64 "\n", le64toh(u64)); + + memcpy(&u32, &sd[16], 4); + printf("Number Of Links %" PRIu32 "\n", le32toh(u32)); + + printf("Delete Pending %d\n", sd[20]); + printf("Delete Directory %d\n", sd[21]); +} + +static void +filestandardinfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 24); + memset(qi, 0, sizeof(qi) + 24); + qi->info_type = 0x01; + qi->file_info_class = 5; + qi->additional_information = 0; + qi->input_buffer_length = 24; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_filestandardinfo((uint8_t *)(&qi[1])); + free(qi); +} + +static void +print_fileinternalinfo(uint8_t *sd) +{ + uint64_t u64; + + memcpy(&u64, &sd[0], 8); + printf("Index Number %" PRIu64 "\n", le64toh(u64)); +} + +static void +fileinternalinfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 8); + memset(qi, 0, sizeof(qi) + 8); + qi->info_type = 0x01; + qi->file_info_class = 6; + qi->additional_information = 0; + qi->input_buffer_length = 8; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_fileinternalinfo((uint8_t *)(&qi[1])); + free(qi); +} + +struct bit_string file_mode_mask[] = { + { 0x00000002, "WRITE_THROUGH" }, + { 0x00000004, "SEQUENTIAL_ONLY" }, + { 0x00000008, "NO_INTERMEDIATE_BUFFERING" }, + { 0x00000010, "SYNCHRONOUS_IO_ALERT" }, + { 0x00000020, "SYNCHRONOUS_IO_NONALERT" }, + { 0x00001000, "DELETE_ON_CLOSE" }, + { 0, NULL } +}; + +static void +print_filemodeinfo(uint8_t *sd) +{ + uint32_t u32; + + memcpy(&u32, &sd[32], 4); + u32 = le32toh(u32); + printf("Mode 0x%08x: ", u32); + print_bits(u32, file_mode_mask); + printf("\n"); +} + +static void +filemodeinfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 4); + memset(qi, 0, sizeof(qi) + 4); + qi->info_type = 0x01; + qi->file_info_class = 16; + qi->additional_information = 0; + qi->input_buffer_length = 4; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_filemodeinfo((uint8_t *)(&qi[1])); + free(qi); +} + +static void +print_filepositioninfo(uint8_t *sd) +{ + uint64_t u64; + + memcpy(&u64, &sd[0], 8); + printf("Current Byte Offset %" PRIu64 "\n", le64toh(u64)); +} + +static void +filepositioninfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 8); + memset(qi, 0, sizeof(qi) + 8); + qi->info_type = 0x01; + qi->file_info_class = 14; + qi->additional_information = 0; + qi->input_buffer_length = 8; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_filepositioninfo((uint8_t *)(&qi[1])); + free(qi); +} + +static void +print_fileeainfo(uint8_t *sd) +{ + uint32_t u32; + + memcpy(&u32, &sd[0], 4); + printf("Ea Size %" PRIu32 "\n", le32toh(u32)); +} + +static void +fileeainfo(int f) +{ + struct smb_query_info *qi; + + qi = malloc(sizeof(struct smb_query_info) + 4); + memset(qi, 0, sizeof(qi) + 4); + qi->info_type = 0x01; + qi->file_info_class = 7; + qi->additional_information = 0; + qi->input_buffer_length = 4; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_fileeainfo((uint8_t *)(&qi[1])); + free(qi); +} + +static void +fileallinfo(int f) +{ + struct smb_query_info *qi; + struct stat st; + + fstat(f, &st); + + qi = malloc(sizeof(struct smb_query_info) + INPUT_BUFFER_LENGTH); + memset(qi, 0, sizeof(qi) + INPUT_BUFFER_LENGTH); + qi->info_type = 0x01; + qi->file_info_class = 18; + qi->additional_information = 0; + qi->input_buffer_length = INPUT_BUFFER_LENGTH; + + if (ioctl(f, CIFS_QUERY_INFO, qi) < 0) { + fprintf(stderr, "ioctl failed with %s\n", strerror(errno)); + exit(1); + } + + print_filebasicinfo((uint8_t *)(&qi[1])); + print_filestandardinfo((uint8_t *)(&qi[1]) + 40); + print_fileinternalinfo((uint8_t *)(&qi[1]) + 64); + print_fileeainfo((uint8_t *)(&qi[1]) + 72); + print_fileaccessinfo((uint8_t *)(&qi[1]) + 76, st.st_mode & S_IFMT); + print_filepositioninfo((uint8_t *)(&qi[1]) + 80); + print_filemodeinfo((uint8_t *)(&qi[1]) + 88); + print_filealigninfo((uint8_t *)(&qi[1]) + 92); + // SMB2 servers like Win16 does not seem to return name info + free(qi); +} + +static void print_sid(unsigned char *sd) { int i; @@ -152,10 +593,13 @@ print_sd(uint8_t *sd) } } -void secdesc(int f) { +static void +secdesc(int f) +{ struct smb_query_info *qi; qi = malloc(sizeof(struct smb_query_info) + INPUT_BUFFER_LENGTH); + memset(qi, 0, sizeof(qi) + INPUT_BUFFER_LENGTH); qi->info_type = 0x03; qi->file_info_class = 0; qi->additional_information = 0x00000007; /* Owner, Group, Dacl */ @@ -167,13 +611,7 @@ void secdesc(int f) { } print_sd((uint8_t *)(&qi[1])); -} - -void -win_to_timeval(uint64_t smb2_time, struct timeval *tv) -{ - tv->tv_usec = (smb2_time / 10) % 1000000; - tv->tv_sec = (smb2_time - 116444736000000000) / 10000000; + free(qi); } static void @@ -236,7 +674,9 @@ print_quota(unsigned char *sd) } } -void quota(int f) { +static void +quota(int f) +{ struct smb_query_info *qi; char *buf; int i; @@ -264,6 +704,7 @@ void quota(int f) { } print_quota((unsigned char *)(&qi[1])); + free(qi); } int main(int argc, char *argv[]) @@ -290,11 +731,29 @@ int main(int argc, char *argv[]) } - if (!strcmp(argv[1], "secdesc")) { + if (!strcmp(argv[1], "fileaccessinfo")) + fileaccessinfo(f); + else if (!strcmp(argv[1], "filealigninfo")) + filealigninfo(f); + else if (!strcmp(argv[1], "fileallinfo")) + fileallinfo(f); + else if (!strcmp(argv[1], "filebasicinfo")) + filebasicinfo(f); + else if (!strcmp(argv[1], "fileeainfo")) + fileeainfo(f); + else if (!strcmp(argv[1], "fileinternalinfo")) + fileinternalinfo(f); + else if (!strcmp(argv[1], "filemodeinfo")) + filemodeinfo(f); + else if (!strcmp(argv[1], "filepositioninfo")) + filepositioninfo(f); + else if (!strcmp(argv[1], "filestandardinfo")) + filestandardinfo(f); + else if (!strcmp(argv[1], "secdesc")) secdesc(f); - } else if (!strcmp(argv[1], "quota")) { + else if (!strcmp(argv[1], "quota")) quota(f); - } else { + else { fprintf(stderr, "Unknown command %s\n", argv[optind]); exit(1); } diff --git a/smbinfo.rst b/smbinfo.rst index e37c709..2119f93 100644 --- a/smbinfo.rst +++ b/smbinfo.rst @@ -39,14 +39,23 @@ OPTIONS COMMAND ******* -`secdesc`: Print the security descriptor in the form -- Revision -- Control -- Owner SID -- Group SID -- ACL -- File types -- File flags +`fileaccessinfo`: Prints the FileAccessInformation class + +`filealigninfo`: Prints the FileAlignmentInformation class + +`fileallinfo`: Prints the FileAllInformation class + +`filebasicinfo`: Prints the FileBasicInformation class + +`fileeainfo`: Prints the FileEaInformation class + +`fileinternalinfo`: Prints the FileInternalInformation class + +`filemodeinfo`: Prints the FileModeInformation class + +`filepositioninfo`: Prints the FilePositionInformation class + +`filestandardinfo`: Prints the FileStandardInformation class `quota`: Print the quota for the volume in the form - SID Length @@ -56,6 +65,15 @@ COMMAND - Quota Limit - SID +`secdesc`: Print the security descriptor in the form +- Revision +- Control +- Owner SID +- Group SID +- ACL +- File types +- File flags + ***** NOTES *****
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> --- smbinfo.c | 483 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- smbinfo.rst | 34 ++++- 2 files changed, 497 insertions(+), 20 deletions(-)