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

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

readded windows file descriptor hack
copyright notices

File size: 6.7 KB
Line 
1#!/usr/bin/env python
2
3# Copyright (C) 2011 Timothy D. Morgan
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; version 3 of the License.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17#
18# $Id: $
19
20## @package pyregfi.winsec
21# Low-level data structures for winsec library
22#
23
24import sys
25import os
26import uuid
27import ctypes
28import ctypes.util
29from ctypes import *
30from .structures import regfi
31
32is_win32 = hasattr(ctypes, 'windll')
33WINSEC_MAX_SUBAUTHS = 15
34
35if is_win32:
36    libc = cdll.msvcrt
37else:
38    libc = cdll.LoadLibrary("libc.so.6")
39
40class WINSEC_UUID(Structure):
41    pass
42
43class WINSEC_DOM_SID(Structure):
44    pass
45
46class WINSEC_ACE(Structure):
47    pass
48
49class WINSEC_ACL(Structure):
50    pass
51
52class WINSEC_DESC(Structure):
53    pass
54
55WINSEC_UUID._fields_ = [('time_low', c_uint32),
56                        ('time_mid', c_uint16),
57                        ('time_hi_and_version', c_uint16),
58                        ('clock_seq', c_uint8*2),
59                        ('node', c_uint8*6),
60                        ]
61
62WINSEC_DOM_SID._fields_ = [('sid_rev_num', c_uint8),
63                           ('num_auths', c_uint8),
64                           ('id_auths', c_uint8*6),
65                           ('sub_auths', c_uint32*WINSEC_MAX_SUBAUTHS),
66                           ]
67
68WINSEC_ACE._fields_ = [('type', c_uint8),
69                       ('flags', c_uint8),
70                       ('size', c_uint16),
71                       ('access_mask', c_uint32),
72                       ('obj_flags', c_uint32),
73                       ('obj_guid', POINTER(WINSEC_UUID)),
74                       ('inh_guid', POINTER(WINSEC_UUID)),
75                       ('trustee', POINTER(WINSEC_DOM_SID)),
76                       ]
77
78WINSEC_ACL._fields_ = [('revision', c_uint16),
79                       ('size', c_uint16),
80                       ('num_aces', c_uint32),
81                       ('aces', POINTER(POINTER(WINSEC_ACE))),
82                       ]
83
84WINSEC_DESC._fields_ = [('revision', c_uint8),
85                        ('sbz1', c_uint8),
86                        ('control', c_uint16),
87                        ('off_owner_sid', c_uint32),
88                        ('off_grp_sid', c_uint32),
89                        ('off_sacl', c_uint32),
90                        ('off_dacl', c_uint32),
91                        ('owner_sid', POINTER(WINSEC_DOM_SID)),
92                        ('grp_sid', POINTER(WINSEC_DOM_SID)),
93                        ('sacl', POINTER(WINSEC_ACL)),
94                        ('dacl', POINTER(WINSEC_ACL)),
95                        ]
96regfi.winsec_sid2str.argtypes = [POINTER(WINSEC_DOM_SID)]
97regfi.winsec_sid2str.restype = POINTER(c_char)
98
99
100def _guid2uuid(guid):
101    if not guid:
102        return None
103    return uuid.UUID(fields=(guid.contents.time_low,
104                             guid.contents.time_mid,
105                             guid.contents.time_hi_and_version,
106                             guid.contents.clock_seq[0],
107                             guid.contents.clock_seq[1],
108                             guid.contents.node[0]<<40
109                             ^ guid.contents.node[1]<<32
110                             ^ guid.contents.node[2]<<24
111                             ^ guid.contents.node[3]<<16
112                             ^ guid.contents.node[4]<<8
113                             ^ guid.contents.node[5]))
114
115## Represents a Microsoft access control entry, which are elements of access
116#  control lists.  For more information, see:
117#    http://msdn.microsoft.com/en-us/library/aa374868%28v=vs.85%29.aspx
118#
119#  @note
120#  This interface is subject to change
121class ACE(object):
122    ## The type of entry as an integer
123    type = 1234
124   
125    ## The flags as an integer
126    flags = 0x1234
127
128    ## The access mask/permissions as an integer
129    access_mask = 0x1234
130
131    ## The trustee's SID as a string
132    trustee = "S-1-2..."
133   
134    ## The object GUID as a Python UUID
135    # May be None
136    object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
137
138    ## The inherited object GUID as a Python UUID
139    # May be None
140    inherited_object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
141
142    def __init__(self, ace):
143        # Just copy all of the values out so we don't need to manage memory
144        self.object = _guid2uuid(ace.obj_guid)
145        self.inherited_object = _guid2uuid(ace.inh_guid)
146
147        c_str = regfi.winsec_sid2str(ace.trustee)
148        self.trustee = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
149        libc.free(c_str)
150
151        self.type = int(ace.type)
152        self.flags = int(ace.flags)
153        self.access_mask = int(ace.access_mask)
154
155
156## A Microsoft security descriptor
157# For more information, see:
158#   http://msdn.microsoft.com/en-us/library/aa379563%28v=vs.85%29.aspx
159#
160class SecurityDescriptor(object):
161    ## The security descriptor's owner SID, as a string
162    owner = "S-1-2-..."
163
164    ## The security descriptor's group SID, as a string
165    group = "S-1-2-..."
166
167    ## The system access control list represented as a list of @ref ACE objects.
168    #
169    # Is set to None if a sacl isn't defined
170    sacl = []
171
172    ## The discretionary access control list represented as a list of @ref ACE objects
173    #
174    # Is set to None if a dacl isn't defined
175    dacl = []
176
177    def __init__(self, sec_desc):
178        c_str = regfi.winsec_sid2str(sec_desc.owner_sid)
179        self.owner = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
180        libc.free(c_str)
181       
182        c_str = regfi.winsec_sid2str(sec_desc.grp_sid)
183        self.group = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
184        libc.free(c_str)
185
186        self.sacl = None
187        if sec_desc.sacl:
188            self.sacl = []
189            for i in range(0,sec_desc.sacl.contents.num_aces):
190                self.sacl.append(ACE(sec_desc.sacl.contents.aces[i].contents))
191
192        self.dacl = None
193        if sec_desc.dacl:
194            self.dacl = []
195            for i in range(0,sec_desc.dacl.contents.num_aces):
196                self.dacl.append(ACE(sec_desc.dacl.contents.aces[i].contents))
197
198
199# Free class objects used for documentation
200del ACE.type,ACE.flags,ACE.access_mask,ACE.object,ACE.inherited_object
201del SecurityDescriptor.owner,SecurityDescriptor.group,SecurityDescriptor.sacl,SecurityDescriptor.dacl
Note: See TracBrowser for help on using the repository browser.