signing: disable signing if authentication failed but guest login is enabled
[scrambla.git] / smb2 / file_info.py
1 # coding: utf-8
2
3 # Copyright (C) 2020 by Ronnie Sahlberg<ronniesahlberg@gmail.com>
4 #
5
6 import struct
7 from enum import Enum
8
9 from smb2.header import Direction
10 from smb2.timestamps import WinToTimeval, TimevalToWin
11 from smb2.unicode import UCS2toUTF8, UTF8toUCS2
12
13 #
14 # SMB2 FILE INFORMATION CLASSES
15 #
16
17 #
18 # INFO CLASS
19 #
20 class FileInfoClass(Enum):
21     BASIC_INFORMATION             = 0x04
22     STANDARD_INFORMATION          = 0x05
23     INTERNAL_INFORMATION          = 0x06
24     EA_INFORMATION                = 0x07
25     ACCESS_INFORMATION            = 0x08
26     NAME_INFORMATION              = 0x09
27     POSITION_INFORMATION          = 0x0e
28     MODE_INFORMATION              = 0x10
29     ALIGNMENT_INFORMATION         = 0x11
30     ALL_INFORMATION               = 0x12
31
32 def decode_basic_info(buf):
33     info = {}
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]})
39     
40     return info
41
42 def encode_basic_info(info):
43     buf = bytearray(40)
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'])
49     return buf
50
51 def decode_standard_info(buf):
52     info = {}
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]})
58     return info
59
60 def encode_standard_info(info):
61     buf = bytearray(24)
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'])
67     return buf
68
69 def decode_internal_info(buf):
70     info = {}
71     info.update({'index_number': struct.unpack_from('<Q', buf, 0)[0]})
72     return info
73
74 def encode_internal_info(info):
75     buf = bytearray(8)
76     struct.pack_into('<Q', buf, 0, info['index_number'])
77     return buf
78
79 def decode_ea_info(buf):
80     info = {}
81     info.update({'ea_size': struct.unpack_from('<I', buf, 0)[0]})
82     return info
83
84 def encode_ea_info(info):
85     buf = bytearray(4)
86     struct.pack_into('<I', buf, 0, info['ea_size'])
87     return buf
88
89 def decode_access_info(buf):
90     info = {}
91     info.update({'access_flags': struct.unpack_from('<I', buf, 0)[0]})
92     return info
93
94 def encode_access_info(info):
95     buf = bytearray(4)
96     struct.pack_into('<I', buf, 0, info['access_flags'])
97     return buf
98
99 def decode_position_info(buf):
100     info = {}
101     info.update({'current_byte_offset': struct.unpack_from('<Q', buf, 0)[0]})
102     return info
103
104 def encode_position_info(info):
105     buf = bytearray(8)
106     struct.pack_into('<Q', buf, 0, info['current_byte_offset'])
107     return buf
108
109 def decode_mode_info(buf):
110     info = {}
111     info.update({'mode': struct.unpack_from('<I', buf, 0)[0]})
112     return info
113
114 def encode_mode_info(info):
115     buf = bytearray(4)
116     struct.pack_into('<I', buf, 0, info['mode'])
117     return buf
118
119 def decode_alignment_info(buf):
120     info = {}
121     info.update({'alignment_requirement': struct.unpack_from('<I', buf, 0)[0]})
122     return info
123
124 def encode_alignment_info(info):
125     buf = bytearray(4)
126     struct.pack_into('<I', buf, 0, info['alignment_requirement'])
127     return buf
128
129 def decode_name_info(buf):
130     info = {}
131     _len = struct.unpack_from('<I', buf, 0)[0]
132     if _len:
133         info.update({'name': UCS2toUTF8(buf[4:4 + _len])})
134     return info
135
136 def encode_name_info(info):
137     buf = bytearray(4)
138     if 'name' in info:
139         _c = UTF8toUCS2(hdr['name'])
140         struct.pack_into('<I', buf, 0, len(_c))
141         buf = buf + _c
142     return buf
143
144 def decode_all_info(buf):
145     info = {}
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:]))
155     return info
156
157 def encode_all_info(info):
158     buf = bytearray(0)
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)
168     return buf
169
170 file_coders = {
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),
181     }
182
183 class FileInfo(object):
184     """
185     A class for FileInfo
186     """
187
188     def __init__(self, **kwargs):
189         True
190
191     def __del__(self):
192         True
193
194     @staticmethod
195     def decode(fic, buf):
196         if fic in file_coders:
197             return file_coders[fic][1](buf)
198
199         print('Unknown FileInfoClass', fic)
200         return {}
201         
202     @staticmethod
203     def encode(fic, info):
204         if fic in file_coders:
205             return file_coders[fic][0](info)
206
207         print('Unknown FileInfoClass', fic)
208         return bytearray(0)
209