3 # Copyright (C) 2020 by Ronnie Sahlberg<ronniesahlberg@gmail.com>
9 from smb2.header import Direction
10 from smb2.timestamps import WinToTimeval, TimevalToWin
11 from smb2.unicode import UCS2toUTF8, UTF8toUCS2
14 # SMB2 FILE INFORMATION CLASSES
20 class FileInfoClass(Enum):
21 BASIC_INFORMATION = 0x04
22 STANDARD_INFORMATION = 0x05
23 INTERNAL_INFORMATION = 0x06
25 ACCESS_INFORMATION = 0x08
26 NAME_INFORMATION = 0x09
27 POSITION_INFORMATION = 0x0e
28 MODE_INFORMATION = 0x10
29 ALIGNMENT_INFORMATION = 0x11
30 ALL_INFORMATION = 0x12
32 def decode_basic_info(buf):
34 info.update({'creation_time': WinToTimeval(struct.unpack_from('<Q', buf, 0)[0])})
35 info.update({'last_access_time': WinToTimeval(struct.unpack_from('<Q', buf, 8)[0])})
36 info.update({'last_write_time': WinToTimeval(struct.unpack_from('<Q', buf, 16)[0])})
37 info.update({'change_time': WinToTimeval(struct.unpack_from('<Q', buf, 24)[0])})
38 info.update({'file_attributes': struct.unpack_from('<I', buf, 32)[0]})
42 def encode_basic_info(info):
44 struct.pack_into('<Q', buf, 0, TimevalToWin(info['creation_time']))
45 struct.pack_into('<Q', buf, 8, TimevalToWin(info['last_access_time']))
46 struct.pack_into('<Q', buf, 16, TimevalToWin(info['last_write_time']))
47 struct.pack_into('<Q', buf, 24, TimevalToWin(info['change_time']))
48 struct.pack_into('<I', buf, 32, info['file_attributes'])
51 def decode_standard_info(buf):
53 info.update({'allocation_size': struct.unpack_from('<Q', buf, 0)[0]})
54 info.update({'end_of_file': struct.unpack_from('<Q', buf, 8)[0]})
55 info.update({'number_of_links': struct.unpack_from('<I', buf, 16)[0]})
56 info.update({'delete_pending': struct.unpack_from('<B', buf, 20)[0]})
57 info.update({'directory': struct.unpack_from('<B', buf, 21)[0]})
60 def encode_standard_info(info):
62 struct.pack_into('<Q', buf, 0, info['allocation_size'])
63 struct.pack_into('<Q', buf, 8, info['end_of_file'])
64 struct.pack_into('<I', buf, 16, info['number_of_links'])
65 struct.pack_into('<B', buf, 20, info['delete_pending'])
66 struct.pack_into('<B', buf, 21, info['directory'])
69 def decode_internal_info(buf):
71 info.update({'index_number': struct.unpack_from('<Q', buf, 0)[0]})
74 def encode_internal_info(info):
76 struct.pack_into('<Q', buf, 0, info['index_number'])
79 def decode_ea_info(buf):
81 info.update({'ea_size': struct.unpack_from('<I', buf, 0)[0]})
84 def encode_ea_info(info):
86 struct.pack_into('<I', buf, 0, info['ea_size'])
89 def decode_access_info(buf):
91 info.update({'access_flags': struct.unpack_from('<I', buf, 0)[0]})
94 def encode_access_info(info):
96 struct.pack_into('<I', buf, 0, info['access_flags'])
99 def decode_position_info(buf):
101 info.update({'current_byte_offset': struct.unpack_from('<Q', buf, 0)[0]})
104 def encode_position_info(info):
106 struct.pack_into('<Q', buf, 0, info['current_byte_offset'])
109 def decode_mode_info(buf):
111 info.update({'mode': struct.unpack_from('<I', buf, 0)[0]})
114 def encode_mode_info(info):
116 struct.pack_into('<I', buf, 0, info['mode'])
119 def decode_alignment_info(buf):
121 info.update({'alignment_requirement': struct.unpack_from('<I', buf, 0)[0]})
124 def encode_alignment_info(info):
126 struct.pack_into('<I', buf, 0, info['alignment_requirement'])
129 def decode_name_info(buf):
131 _len = struct.unpack_from('<I', buf, 0)[0]
133 info.update({'name': UCS2toUTF8(buf[4:4 + _len])})
136 def encode_name_info(info):
139 _c = UTF8toUCS2(hdr['name'])
140 struct.pack_into('<I', buf, 0, len(_c))
144 def decode_all_info(buf):
146 info.update(decode_basic_info(buf[:40]))
147 info.update(decode_standard_info(buf[40:64]))
148 info.update(decode_internal_info(buf[64:72]))
149 info.update(decode_ea_info(buf[72:76]))
150 info.update(decode_access_info(buf[76:80]))
151 info.update(decode_position_info(buf[80:88]))
152 info.update(decode_mode_info(buf[88:92]))
153 info.update(decode_alignment_info(buf[92:96]))
154 info.update(decode_name_info(buf[96:]))
157 def encode_all_info(info):
159 buf = buf + encode_basic_info(info)
160 buf = buf + encode_standard_info(info)
161 buf = buf + encode_internal_info(info)
162 buf = buf + encode_ea_info(info)
163 buf = buf + encode_access_info(info)
164 buf = buf + encode_position_info(info)
165 buf = buf + encode_mode_info(info)
166 buf = buf + encode_alignment_info(info)
167 buf = buf + encode_name_info(info)
171 FileInfoClass.BASIC_INFORMATION: (encode_basic_info, decode_basic_info),
172 FileInfoClass.STANDARD_INFORMATION: (encode_standard_info, decode_standard_info),
173 FileInfoClass.INTERNAL_INFORMATION: (encode_internal_info, decode_internal_info),
174 FileInfoClass.EA_INFORMATION: (encode_ea_info, decode_ea_info),
175 FileInfoClass.ACCESS_INFORMATION: (encode_access_info, decode_access_info),
176 FileInfoClass.POSITION_INFORMATION: (encode_position_info, decode_position_info),
177 FileInfoClass.MODE_INFORMATION: (encode_mode_info, decode_mode_info),
178 FileInfoClass.ALIGNMENT_INFORMATION: (encode_alignment_info, decode_alignment_info),
179 FileInfoClass.NAME_INFORMATION: (encode_name_info, decode_name_info),
180 FileInfoClass.ALL_INFORMATION: (encode_all_info, decode_all_info),
183 class FileInfo(object):
188 def __init__(self, **kwargs):
195 def decode(fic, buf):
196 if fic in file_coders:
197 return file_coders[fic][1](buf)
199 print('Unknown FileInfoClass', fic)
203 def encode(fic, info):
204 if fic in file_coders:
205 return file_coders[fic][0](info)
207 print('Unknown FileInfoClass', fic)