source: trunk/python/pyregfi/winsec.py @ 255

Last change on this file since 255 was 255, checked in by tim, 13 years ago

fixed error condition deadlock in regfi
prevented early garbage collection of hive file handles
fixed module imports under python3

File size: 5.7 KB
Line 
1#!/usr/bin/env python
2
3## @package pyregfi.winsec
4# Low-level data structures for winsec library
5#
6
7import sys
8import os
9import uuid
10import ctypes
11import ctypes.util
12from ctypes import *
13from .structures import regfi
14
15is_win32 = hasattr(ctypes, 'windll')
16WINSEC_MAX_SUBAUTHS = 15
17
18if is_win32:
19    libc = cdll.msvcrt
20else:
21    libc = cdll.LoadLibrary("libc.so.6")
22
23class WINSEC_UUID(Structure):
24    pass
25
26class WINSEC_DOM_SID(Structure):
27    pass
28
29class WINSEC_ACE(Structure):
30    pass
31
32class WINSEC_ACL(Structure):
33    pass
34
35class WINSEC_DESC(Structure):
36    pass
37
38WINSEC_UUID._fields_ = [('time_low', c_uint32),
39                        ('time_mid', c_uint16),
40                        ('time_hi_and_version', c_uint16),
41                        ('clock_seq', c_uint8*2),
42                        ('node', c_uint8*6),
43                        ]
44
45WINSEC_DOM_SID._fields_ = [('sid_rev_num', c_uint8),
46                           ('num_auths', c_uint8),
47                           ('id_auths', c_uint8*6),
48                           ('sub_auths', c_uint32*WINSEC_MAX_SUBAUTHS),
49                           ]
50
51WINSEC_ACE._fields_ = [('type', c_uint8),
52                       ('flags', c_uint8),
53                       ('size', c_uint16),
54                       ('access_mask', c_uint32),
55                       ('obj_flags', c_uint32),
56                       ('obj_guid', POINTER(WINSEC_UUID)),
57                       ('inh_guid', POINTER(WINSEC_UUID)),
58                       ('trustee', POINTER(WINSEC_DOM_SID)),
59                       ]
60
61WINSEC_ACL._fields_ = [('revision', c_uint16),
62                       ('size', c_uint16),
63                       ('num_aces', c_uint32),
64                       ('aces', POINTER(POINTER(WINSEC_ACE))),
65                       ]
66
67WINSEC_DESC._fields_ = [('revision', c_uint8),
68                        ('sbz1', c_uint8),
69                        ('control', c_uint16),
70                        ('off_owner_sid', c_uint32),
71                        ('off_grp_sid', c_uint32),
72                        ('off_sacl', c_uint32),
73                        ('off_dacl', c_uint32),
74                        ('owner_sid', POINTER(WINSEC_DOM_SID)),
75                        ('grp_sid', POINTER(WINSEC_DOM_SID)),
76                        ('sacl', POINTER(WINSEC_ACL)),
77                        ('dacl', POINTER(WINSEC_ACL)),
78                        ]
79regfi.winsec_sid2str.argtypes = [POINTER(WINSEC_DOM_SID)]
80regfi.winsec_sid2str.restype = POINTER(c_char)
81
82
83def _guid2uuid(guid):
84    if not guid:
85        return None
86    return uuid.UUID(fields=(guid.contents.time_low,
87                             guid.contents.time_mid,
88                             guid.contents.time_hi_and_version,
89                             guid.contents.clock_seq[0],
90                             guid.contents.clock_seq[1],
91                             guid.contents.node[0]<<40
92                             ^ guid.contents.node[1]<<32
93                             ^ guid.contents.node[2]<<24
94                             ^ guid.contents.node[3]<<16
95                             ^ guid.contents.node[4]<<8
96                             ^ guid.contents.node[5]))
97
98## Represents a Microsoft access control entry, which are elements of access
99#  control lists
100#
101#  @note
102#  This interface is subject to change
103class ACE(object):
104    ## The type of entry as an integer
105    type = 1234
106   
107    ## The flags as an integer
108    flags = 0x1234
109
110    ## The access mask/permissions as an integer
111    access_mask = 0x1234
112
113    ## The trustee's SID as a string
114    trustee = "S-1-2..."
115   
116    ## The object GUID as a Python UUID
117    # May be None
118    object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
119
120    ## The inherited object GUID as a Python UUID
121    # May be None
122    inherited_object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
123
124    def __init__(self, ace):
125        # Just copy all of the values out so we don't need to manage memory
126        self.object = _guid2uuid(ace.obj_guid)
127        self.inherited_object = _guid2uuid(ace.inh_guid)
128
129        c_str = regfi.winsec_sid2str(ace.trustee)
130        self.trustee = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
131        libc.free(c_str)
132
133        self.type = int(ace.type)
134        self.flags = int(ace.flags)
135        self.access_mask = int(ace.access_mask)
136
137
138class SecurityDescriptor(object):
139    ## The security descriptor's owner SID, as a string
140    owner = "S-1-2-..."
141
142    ## The security descriptor's group SID, as a string
143    group = "S-1-2-..."
144
145    ## A list of @ref ACE objects which represents the System ACL
146    # May be None if a sacl isn't defined
147    sacl = []
148
149    ## A list of @ref ACE objects which represents the User ACL
150    # May be None if a dacl isn't defined
151    dacl = []
152
153    def __init__(self, sec_desc):
154        c_str = regfi.winsec_sid2str(sec_desc.owner_sid)
155        self.owner = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
156        libc.free(c_str)
157       
158        c_str = regfi.winsec_sid2str(sec_desc.grp_sid)
159        self.group = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
160        libc.free(c_str)
161
162        # XXX: add checks for NULL pointers
163        self.sacl = None
164        if sec_desc.sacl:
165            self.sacl = []
166            for i in range(0,sec_desc.sacl.contents.num_aces):
167                self.sacl.append(ACE(sec_desc.sacl.contents.aces[i].contents))
168
169        self.dacl = None
170        if sec_desc.dacl:
171            self.dacl = []
172            for i in range(0,sec_desc.dacl.contents.num_aces):
173                self.dacl.append(ACE(sec_desc.dacl.contents.aces[i].contents))
174
175
176# Free class objects used for documentation
177del ACE.type,ACE.flags,ACE.access_mask,ACE.object,ACE.inherited_object
178del SecurityDescriptor.owner,SecurityDescriptor.group,SecurityDescriptor.sacl,SecurityDescriptor.dacl
Note: See TracBrowser for help on using the repository browser.