File: winsec.py

package info (click to toggle)
reglookup 1.0.1%2Bsvn296-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 948 kB
  • sloc: ansic: 6,676; python: 3,762; makefile: 40; sh: 27
file content (201 lines) | stat: -rw-r--r-- 6,823 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/env python

# Copyright (C) 2011 Timothy D. Morgan
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# $Id: $

## @package pyregfi.winsec
# Low-level data structures for winsec library
#

import sys
import os
import uuid
import ctypes
import ctypes.util
from ctypes import *
from .structures import regfi

is_win32 = hasattr(ctypes, 'windll')
WINSEC_MAX_SUBAUTHS = 15

if is_win32:
    libc = cdll.msvcrt
else:
    libc = cdll.LoadLibrary("libc.so.6")

class WINSEC_UUID(Structure):
    pass

class WINSEC_DOM_SID(Structure):
    pass

class WINSEC_ACE(Structure):
    pass

class WINSEC_ACL(Structure):
    pass

class WINSEC_DESC(Structure):
    pass

WINSEC_UUID._fields_ = [('time_low', c_uint32),
                        ('time_mid', c_uint16),
                        ('time_hi_and_version', c_uint16),
                        ('clock_seq', c_uint8*2),
                        ('node', c_uint8*6),
                        ]

WINSEC_DOM_SID._fields_ = [('sid_rev_num', c_uint8),
                           ('num_auths', c_uint8),
                           ('id_auths', c_uint8*6),
                           ('sub_auths', c_uint32*WINSEC_MAX_SUBAUTHS),
                           ]

WINSEC_ACE._fields_ = [('type', c_uint8),
                       ('flags', c_uint8),
                       ('size', c_uint16),
                       ('access_mask', c_uint32),
                       ('obj_flags', c_uint32),
                       ('obj_guid', POINTER(WINSEC_UUID)),
                       ('inh_guid', POINTER(WINSEC_UUID)),
                       ('trustee', POINTER(WINSEC_DOM_SID)),
                       ]

WINSEC_ACL._fields_ = [('revision', c_uint16),
                       ('size', c_uint16),
                       ('num_aces', c_uint32),
                       ('aces', POINTER(POINTER(WINSEC_ACE))),
                       ]

WINSEC_DESC._fields_ = [('revision', c_uint8),
                        ('sbz1', c_uint8),
                        ('control', c_uint16),
                        ('off_owner_sid', c_uint32),
                        ('off_grp_sid', c_uint32),
                        ('off_sacl', c_uint32),
                        ('off_dacl', c_uint32),
                        ('owner_sid', POINTER(WINSEC_DOM_SID)),
                        ('grp_sid', POINTER(WINSEC_DOM_SID)),
                        ('sacl', POINTER(WINSEC_ACL)),
                        ('dacl', POINTER(WINSEC_ACL)),
                        ]
regfi.winsec_sid2str.argtypes = [POINTER(WINSEC_DOM_SID)]
regfi.winsec_sid2str.restype = POINTER(c_char)


def _guid2uuid(guid):
    if not guid:
        return None
    return uuid.UUID(fields=(guid.contents.time_low,
                             guid.contents.time_mid,
                             guid.contents.time_hi_and_version,
                             guid.contents.clock_seq[0],
                             guid.contents.clock_seq[1],
                             guid.contents.node[0]<<40
                             ^ guid.contents.node[1]<<32
                             ^ guid.contents.node[2]<<24
                             ^ guid.contents.node[3]<<16
                             ^ guid.contents.node[4]<<8
                             ^ guid.contents.node[5]))

## Represents a Microsoft access control entry, which are elements of access
#  control lists.  For more information, see: 
#    http://msdn.microsoft.com/en-us/library/aa374868%28v=vs.85%29.aspx
#
#  @note
#  This interface is subject to change
class ACE(object):
    ## The type of entry as an integer
    type = 1234
    
    ## The flags as an integer
    flags = 0x1234

    ## The access mask/permissions as an integer
    access_mask = 0x1234

    ## The trustee's SID as a string
    trustee = "S-1-2..."
    
    ## The object GUID as a Python UUID
    # May be None
    object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))

    ## The inherited object GUID as a Python UUID
    # May be None
    inherited_object = uuid.UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))

    def __init__(self, ace):
        # Just copy all of the values out so we don't need to manage memory
        self.object = _guid2uuid(ace.obj_guid)
        self.inherited_object = _guid2uuid(ace.inh_guid)

        c_str = regfi.winsec_sid2str(ace.trustee)
        self.trustee = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
        libc.free(c_str)

        self.type = int(ace.type)
        self.flags = int(ace.flags)
        self.access_mask = int(ace.access_mask)


## A Microsoft security descriptor
# For more information, see:
#   http://msdn.microsoft.com/en-us/library/aa379563%28v=vs.85%29.aspx
#
class SecurityDescriptor(object):
    ## The security descriptor's owner SID, as a string
    owner = "S-1-2-..."

    ## The security descriptor's group SID, as a string
    group = "S-1-2-..."

    ## The system access control list represented as a list of @ref ACE objects.
    # 
    # Is set to None if a sacl isn't defined
    sacl = []

    ## The discretionary access control list represented as a list of @ref ACE objects
    #
    # Is set to None if a dacl isn't defined
    dacl = []

    def __init__(self, sec_desc):
        c_str = regfi.winsec_sid2str(sec_desc.owner_sid)
        self.owner = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
        libc.free(c_str)
        
        c_str = regfi.winsec_sid2str(sec_desc.grp_sid)
        self.group = ctypes.cast(c_str, c_char_p).value.decode('utf-8', 'replace')
        libc.free(c_str)

        self.sacl = None
        if sec_desc.sacl:
            self.sacl = []
            for i in range(0,sec_desc.sacl.contents.num_aces):
                self.sacl.append(ACE(sec_desc.sacl.contents.aces[i].contents))

        self.dacl = None
        if sec_desc.dacl:
            self.dacl = []
            for i in range(0,sec_desc.dacl.contents.num_aces):
                self.dacl.append(ACE(sec_desc.dacl.contents.aces[i].contents))


# Free class objects used for documentation
del ACE.type,ACE.flags,ACE.access_mask,ACE.object,ACE.inherited_object
del SecurityDescriptor.owner,SecurityDescriptor.group,SecurityDescriptor.sacl,SecurityDescriptor.dacl