13 FULL_CONTROL = 0x001f01ff
15 ALL_READ_BITS = 0x00020089
19 TRAV_EXEC = 0x00100020
20 LIST_READ = 0x00100001
21 READ_ATTR = 0x00100080
22 READ_XATT = 0x00100008
23 CREA_WRIT = 0x00100002
24 CREA_APPE = 0x00100004
25 WRIT_ATTR = 0x00100100
26 WRIT_XATT = 0x00100010
28 READ_PERM = 0x00120000
29 CHAN_PERM = 0x00140000
30 TAKE_OWNR = 0x00180000
33 def __init__(self, root, sd, is_dir):
37 self.tf.grid(columnspan=5, rowspan=5, padx=5, pady=5)
40 Label(self.tf, text='Owner: %s' % (self.sd.owner)).grid(row=0, column=0, columnspan=6, sticky='W')
43 Label(self.tf, text='Group: %s' % (self.sd.group)).grid(row=1, column=0, columnspan=6, sticky='W')
45 self.sb = Scrollbar(self.tf, orient=VERTICAL)
46 self.lb = Listbox(self.tf, height=5, selectmode=SINGLE,
47 yscrollcommand=self.sb.set)
48 self.sb.config(command=self.lb.yview)
49 self.sb.grid(row=2, column=1, sticky='NS')
50 self.lb.grid(row=2, column=0, sticky='W')
53 for idx, item in enumerate(self.sd.dacl.ace):
54 if item.type != 0 and item.type != 1:
56 sid = '%s %s' % ("ALLOW" if item.type == 0 else "DENY", item.sid)
59 self.lb.insert(idx, sid)
60 if not self.lb.curselection():
61 self.lb.selection_set(idx)
62 self.lb.config(width=max)
63 self.lb.bind("<Double-Button-1>", self.select_sid)
65 self.bas = Button(self.tf, text='Basic', relief=SUNKEN,
66 command=self.click_bas)
67 self.bas.grid(row=2, column=2, sticky='NW')
69 self.adv = Button(self.tf, text='Advanced',
70 command=self.click_adv)
71 self.adv.grid(row=2, column=3, sticky='NW')
74 self.bf_bas = Frame(master=self.tf, bd=1)
75 self.bf_bas.grid(row=3, column=0, columnspan=4, padx=5, pady=5)
76 self.bf_bas_name = Label(self.bf_bas, text='')
77 self.bf_bas_name.grid(row=0, column=0, columnspan=2, sticky='W')
80 self.bf_bas_fc=Checkbutton(self.bf_bas, text='Full Control')
81 self.bf_bas_fc.grid(row=row, column=0, sticky='W')
82 self.bf_bas_fc.config(state=DISABLED)
85 self.bf_bas_mo=Checkbutton(self.bf_bas, text='Modify')
86 self.bf_bas_mo.grid(row=row, column=0, sticky='W')
87 self.bf_bas_mo.config(state=DISABLED)
90 self.bf_bas_re=Checkbutton(self.bf_bas, text='Read & Execute')
91 self.bf_bas_re.grid(row=row, column=0, sticky='W')
92 self.bf_bas_re.config(state=DISABLED)
95 self.bf_bas_rd=Checkbutton(self.bf_bas, text='Read')
96 self.bf_bas_rd.grid(row=row, column=0, sticky='W')
97 self.bf_bas_rd.config(state=DISABLED)
100 self.bf_bas_wr=Checkbutton(self.bf_bas, text='Write')
101 self.bf_bas_wr.grid(row=row, column=0, sticky='W')
102 self.bf_bas_wr.config(state=DISABLED)
105 self.bf_bas_sp=Checkbutton(self.bf_bas, text='Special')
106 self.bf_bas_sp.grid(row=row, column=0, sticky='W')
107 self.bf_bas_sp.config(state=DISABLED)
114 self.bf_adv = Frame(master=self.tf, bd=1)
115 self.bf_adv.grid(row=3, column=0, columnspan=4, padx=5, pady=5)
116 self.bf_adv_name = Label(self.bf_adv, text='')
117 self.bf_adv_name.grid(row=0, column=0, columnspan=2, sticky='W')
120 self.bf_adv_fc=Checkbutton(self.bf_adv, text='Full Control')
121 self.bf_adv_fc.grid(row=row, column=0, sticky='W')
122 self.bf_adv_fc.config(state=DISABLED)
125 self.bf_adv_te=Checkbutton(self.bf_adv, text='Traverse-folder/execute-file')
126 self.bf_adv_te.grid(row=row, column=0, sticky='W')
127 self.bf_adv_te.config(state=DISABLED)
130 self.bf_adv_lr=Checkbutton(self.bf_adv, text='List-folder/read-data')
131 self.bf_adv_lr.grid(row=row, column=0, sticky='W')
132 self.bf_adv_lr.config(state=DISABLED)
135 self.bf_adv_ra=Checkbutton(self.bf_adv, text='Read-Attributes')
136 self.bf_adv_ra.grid(row=row, column=0, sticky='W')
137 self.bf_adv_ra.config(state=DISABLED)
140 self.bf_adv_re=Checkbutton(self.bf_adv, text='Read-Extended-Attributes')
141 self.bf_adv_re.grid(row=row, column=0, sticky='W')
142 self.bf_adv_re.config(state=DISABLED)
145 self.bf_adv_cw=Checkbutton(self.bf_adv, text='Create-files/write-data')
146 self.bf_adv_cw.grid(row=row, column=0, sticky='W')
147 self.bf_adv_cw.config(state=DISABLED)
150 self.bf_adv_ca=Checkbutton(self.bf_adv, text='Create-folders/append-data')
151 self.bf_adv_ca.grid(row=row, column=0, sticky='W')
152 self.bf_adv_ca.config(state=DISABLED)
156 self.bf_adv_wa=Checkbutton(self.bf_adv, text='Write-Attributes')
157 self.bf_adv_wa.grid(row=row, column=1, sticky='W')
158 self.bf_adv_wa.config(state=DISABLED)
161 self.bf_adv_we=Checkbutton(self.bf_adv, text='Write-Extended-Attributes')
162 self.bf_adv_we.grid(row=row, column=1, sticky='W')
163 self.bf_adv_we.config(state=DISABLED)
166 self.bf_adv_de=Checkbutton(self.bf_adv, text='Delete')
167 self.bf_adv_de.grid(row=row, column=1, sticky='W')
168 self.bf_adv_de.config(state=DISABLED)
171 self.bf_adv_rp=Checkbutton(self.bf_adv, text='Read-Permissions')
172 self.bf_adv_rp.grid(row=row, column=1, sticky='W')
173 self.bf_adv_rp.config(state=DISABLED)
176 self.bf_adv_cp=Checkbutton(self.bf_adv, text='Change-Permissions')
177 self.bf_adv_cp.grid(row=row, column=1, sticky='W')
178 self.bf_adv_cp.config(state=DISABLED)
181 self.bf_adv_to=Checkbutton(self.bf_adv, text='Take-Ownership')
182 self.bf_adv_to.grid(row=row, column=1, sticky='W')
183 self.bf_adv_to.config(state=DISABLED)
186 self.bf_adv.grid_remove()
188 def select_sid(self, event):
192 self.adv.config(relief=RAISED)
193 self.bas.config(relief=SUNKEN)
194 self.bf_adv.grid_remove()
200 self.adv.config(relief=SUNKEN)
201 self.bas.config(relief=RAISED)
202 self.bf_bas.grid_remove()
205 self.show_bas = False
207 def update_bf_adv(self):
208 ace = self.sd.dacl.ace[self.lb.curselection()[0]]
209 self.bf_adv_name.config(text='Advanced Permissions for %s' % (ace.sid))
210 if ace.mask == FULL_CONTROL:
211 self.bf_adv_fc.select()
213 self.bf_adv_fc.deselect()
214 if ace.mask & TRAV_EXEC == TRAV_EXEC:
215 self.bf_adv_te.select()
217 self.bf_adv_te.deselect()
218 if ace.mask & LIST_READ == LIST_READ:
219 self.bf_adv_lr.select()
221 self.bf_adv_lr.deselect()
222 if ace.mask & READ_ATTR == READ_ATTR:
223 self.bf_adv_ra.select()
225 self.bf_adv_ra.deselect()
226 if ace.mask & READ_XATT == READ_XATT:
227 self.bf_adv_re.select()
229 self.bf_adv_re.deselect()
230 if ace.mask & CREA_WRIT == CREA_WRIT:
231 self.bf_adv_cw.select()
233 self.bf_adv_cw.deselect()
234 if ace.mask & CREA_APPE == CREA_APPE:
235 self.bf_adv_ca.select()
237 self.bf_adv_ca.deselect()
238 if ace.mask & WRIT_ATTR == WRIT_ATTR:
239 self.bf_adv_wa.select()
241 self.bf_adv_wa.deselect()
242 if ace.mask & WRIT_XATT == WRIT_XATT:
243 self.bf_adv_we.select()
245 self.bf_adv_we.deselect()
246 if ace.mask & DELE == DELE:
247 self.bf_adv_de.select()
249 self.bf_adv_de.deselect()
250 if ace.mask & READ_PERM == READ_PERM:
251 self.bf_adv_rp.select()
253 self.bf_adv_rp.deselect()
254 if ace.mask & CHAN_PERM == CHAN_PERM:
255 self.bf_adv_rp.select()
257 self.bf_adv_rp.deselect()
258 if ace.mask & TAKE_OWNR == TAKE_OWNR:
259 self.bf_adv_to.select()
261 self.bf_adv_to.deselect()
263 def update_bf_bas(self):
264 ace = self.sd.dacl.ace[self.lb.curselection()[0]]
265 self.bf_bas_name.config(text='Permissions for %s' % (ace.sid))
267 if ace.mask == FULL_CONTROL:
268 self.bf_bas_fc.select()
271 self.bf_bas_fc.deselect()
272 if ace.mask & CHANGE == CHANGE:
273 self.bf_bas_mo.select()
276 self.bf_bas_mo.deselect()
277 if ace.mask & EREAD == EREAD:
278 self.bf_bas_re.select()
281 self.bf_bas_re.deselect()
282 if ace.mask & ALL_READ_BITS == ALL_READ_BITS:
283 self.bf_bas_rd.select()
284 tmp &= ~ALL_READ_BITS
286 self.bf_bas_rd.deselect()
287 if ace.mask & EWRITE == EWRITE:
288 self.bf_bas_wr.select()
291 self.bf_bas_wr.deselect()
293 self.bf_bas_sp.select()
295 self.bf_bas_sp.deselect()
297 CIFS_QUERY_INFO = 0xc018cf07
300 print "Usage: %s <filename>" % (sys.argv[0])
306 SID implements a Windows Security Identifier as per MS-DTYP:2.4.2.
308 def __init__(self, buf):
309 self.sub_authority_count = buf[1]
310 self.buffer = buf[:8 + self.sub_authority_count * 4]
311 self.revision = self.buffer[0]
312 if self.revision != 1:
313 raise ValueError('SID Revision %d not supported' %
315 self.identifier_authority = 0
316 for x in self.buffer[2:8]:
317 self.identifier_authority = self.identifier_authority * 256 + x
318 self.sub_authority = []
319 for i in range(self.sub_authority_count):
320 self.sub_authority.append(struct.unpack_from('<I', self.buffer, 8 + 4 * i)[0])
323 s = "S-%u-%u" % (self.revision, self.identifier_authority)
325 for x in self.sub_authority:
332 ACE implements a Windows ACE as per MS-DTYP:2.4.4.
334 def __init__(self, buf):
337 self.size = struct.unpack_from('<H', buf, 2)[0]
338 self.raw = buf[:self.size]
339 if self.type in [0, 1]:
340 self.mask = struct.unpack_from('<I', buf, 4)[0]
341 self.sid = SID(buf[8:])
344 s = 'Type:0x%02x ' % (self.type)
345 s += 'Flags:0x%02x ' % (self.flags)
346 if self.type in [0, 1]:
347 s += 'Mask:0x%02x SID:%s' % (self.mask, self.sid)
349 for i in self.raw[4:]:
354 class Type(enum.Enum):
364 ACL implements a Windows ACL as per MS-DTYP:2.4.5.
366 def __init__(self, buf):
367 self.revision = buf[0]
368 if self.revision != 2 and self.revision != 4:
369 raise ValueError('ACL Revision %d '
370 'not supported' % (self.revision))
371 acl = buf[8:8 + struct.unpack_from('<H', buf, 2)[0]]
373 for i in range(struct.unpack_from('<H', buf, 4)[0]):
379 s = 'Revision:0x%02x\n' % (self.revision)
385 class SecurityDescriptor:
387 SecurityDescriptor implements a Windows Security Descriptor as per
390 def __init__(self, buf):
391 self.revision = buf[0]
392 if self.revision != 1:
393 raise ValueError('Security Descriptor Revision %d '
394 'not supported' % (self.revision))
395 self.control = struct.unpack_from('<H', buf, 2)
397 self.owner = SID(buf[struct.unpack_from('<I', buf, 4)[0]:])
398 self.group = SID(buf[struct.unpack_from('<I', buf, 8)[0]:])
400 self.dacl = ACL(buf[struct.unpack_from('<I', buf, 16)[0]:])
403 s = 'Revision:%u\n' % (self.revision)
404 s += 'Control:0x%04x\n' % (self.control)
405 s += 'Owner:%s\n' % (self.owner)
406 s += 'Group:%s\n' % (self.group)
407 s += 'DACL:\n%s' % (self.dacl)
412 if len(sys.argv) != 2:
415 buf = array.array('B', [0] * 16384)
417 struct.pack_into('<I', buf, 0, 3) # InfoType: Security
418 struct.pack_into('<I', buf, 8, 7) # AddInfo: Group/Owner/Dacl
419 struct.pack_into('<I', buf, 16, 16384) # InputBufferLength
421 f = os.open(sys.argv[1], os.O_RDONLY)
423 fcntl.ioctl(f, CIFS_QUERY_INFO, buf, 1)
426 s = struct.unpack_from('<I', buf, 16)
428 sd = SecurityDescriptor(buf[24:24 + s[0]])
431 app = App(root, sd, stat.S_ISDIR(st.st_mode))
435 if __name__ == "__main__":