8225eacd58886966f543891ae0276b2b7f406005
[jelmer/samba4-debian.git] / source / scripting / python / samba / samba3.py
1 #!/usr/bin/python
2
3 # Unix SMB/CIFS implementation.
4 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
5 #   
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10 #   
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #   
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 """Support for reading Samba 3 data files."""
21
22 REGISTRY_VALUE_PREFIX = "SAMBA_REGVAL"
23 REGISTRY_DB_VERSION = 1
24
25 import os
26 import tdb
27
28 class Registry:
29     """Simple read-only support for reading the Samba3 registry."""
30     def __init__(self, file):
31         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
32
33     def close(self):
34         self.tdb.close()
35
36     def __len__(self):
37         """Return the number of keys."""
38         return len(self.keys())
39
40     def keys(self):
41         """Return list with all the keys."""
42         return [k.rstrip("\x00") for k in self.tdb.keys() if not k.startswith(REGISTRY_VALUE_PREFIX)]
43
44     def subkeys(self, key):
45         data = self.tdb.get("%s\x00" % key)
46         if data is None:
47             return []
48         # FIXME: Parse data
49         return []
50
51     def values(self, key):
52         """Return a dictionary with the values set for a specific key."""
53         data = self.tdb.get("%s/%s\x00" % (REGISTRY_VALUE_PREFIX, key))
54         if data is None:
55             return {}
56         # FIXME: Parse data
57         return {}
58
59
60 class PolicyDatabase:
61     def __init__(self, file):
62         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
63         self.min_password_length = self.tdb.fetch_uint32("min password length\x00")
64         self.password_history = self.tdb.fetch_uint32("password history\x00")
65         self.user_must_logon_to_change_password = self.tdb.fetch_uint32("user must logon to change pasword\x00")
66         self.maximum_password_age = self.tdb.fetch_uint32("maximum password age\x00")
67         self.minimum_password_age = self.tdb.fetch_uint32("minimum password age\x00")
68         self.lockout_duration = self.tdb.fetch_uint32("lockout duration\x00")
69         self.reset_count_minutes = self.tdb.fetch_uint32("reset count minutes\x00")
70         self.bad_lockout_minutes = self.tdb.fetch_uint32("bad lockout minutes\x00")
71         self.disconnect_time = self.tdb.fetch_int32("disconnect time\x00")
72         self.refuse_machine_password_change = self.tdb.fetch_uint32("refuse machine password change\x00")
73
74         # FIXME: Read privileges as well
75
76
77 GROUPDB_DATABASE_VERSION_V1 = 1 # native byte format.
78 GROUPDB_DATABASE_VERSION_V2 = 2 # le format.
79
80 GROUP_PREFIX = "UNIXGROUP/"
81
82 # Alias memberships are stored reverse, as memberships. The performance
83 # critical operation is to determine the aliases a SID is member of, not
84 # listing alias members. So we store a list of alias SIDs a SID is member of
85 # hanging of the member as key.
86 MEMBEROF_PREFIX = "MEMBEROF/"
87
88 class GroupMappingDatabase:
89     def __init__(self, file): 
90         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
91
92
93 # High water mark keys
94 HWM_GROUP = "GROUP HWM"
95 HWM_USER = "USER HWM"
96
97 # idmap version determines auto-conversion
98 IDMAP_VERSION = 2
99
100 class IdmapDatabase:
101     def __init__(self, file):
102         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
103         assert self.tdb.fetch_int32("IDMAP_VERSION") == IDMAP_VERSION
104
105
106 class SecretsDatabase:
107     def __init__(self, file):
108         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
109         self.domains = {}
110         for k, v in self.tdb.items():
111             if k == "SECRETS/AUTH_PASSWORD":
112                 self.auth_password = v
113             elif k == "SECRETS/AUTH_DOMAIN":
114                 self.auth_domain = v
115             elif k == "SECRETS/AUTH_USER":
116                 self.auth_user = v
117             elif k.startswith("SECRETS/SID/"):
118                 pass # FIXME
119             elif k.startswith("SECRETS/DOMGUID/"):
120                 pass # FIXME
121             elif k.startswith("SECRETS/LDAP_BIND_PW/"):
122                 pass # FIXME
123             elif k.startswith("SECRETS/AFS_KEYFILE/"):
124                 pass # FIXME
125             elif k.startswith("SECRETS/MACHINE_SEC_CHANNEL_TYPE/"):
126                 pass # FIXME
127             elif k.startswith("SECRETS/MACHINE_LAST_CHANGE_TIME/"):
128                 pass # FIXME
129             elif k.startswith("SECRETS/MACHINE_PASSWORD/"):
130                 pass # FIXME
131             elif k.startswith("SECRETS/$MACHINE.ACC/"):
132                 pass # FIXME
133             elif k.startswith("SECRETS/$DOMTRUST.ACC/"):
134                 pass # FIXME
135             elif k == "INFO/random_seed":
136                 self.random_seed = v
137             else:
138                 raise "Unknown key %s in secrets database" % k
139
140 SHARE_DATABASE_VERSION_V1 = 1
141 SHARE_DATABASE_VERSION_V2 = 2
142
143 class ShareInfoDatabase:
144     def __init__(self, file):
145         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
146         assert self.tdb.fetch_int32("INFO/version") in (SHARE_DATABASE_VERSION_V1, SHARE_DATABASE_VERSION_V2)
147
148     def get_secdesc(self, name):
149         secdesc = self.tdb.get("SECDESC/%s" % name)
150         # FIXME: Run ndr_pull_security_descriptor
151
152
153 ACB_DISABLED = 0x00000001
154 ACB_HOMDIRREQ = 0x00000002
155 ACB_PWNOTREQ = 0x00000004
156 ACB_TEMPDUP = 0x00000008
157 ACB_NORMAL = 0x00000010
158 ACB_MNS = 0x00000020
159 ACB_DOMTRUST = 0x00000040
160 ACB_WSTRUST = 0x00000080
161 ACB_SVRTRUST = 0x00000100
162 ACB_PWNOEXP = 0x00000200
163 ACB_AUTOLOCK = 0x00000400
164 ACB_ENC_TXT_PWD_ALLOWED = 0x00000800
165 ACB_SMARTCARD_REQUIRED = 0x00001000
166 ACB_TRUSTED_FOR_DELEGATION = 0x00002000
167 ACB_NOT_DELEGATED = 0x00004000
168 ACB_USE_DES_KEY_ONLY = 0x00008000
169 ACB_DONT_REQUIRE_PREAUTH = 0x00010000
170 ACB_PW_EXPIRED = 0x00020000
171 ACB_NO_AUTH_DATA_REQD = 0x00080000
172
173 acb_info_mapping = {
174         'N': ACB_PWNOTREQ,  # 'N'o password. 
175         'D': ACB_DISABLED,  # 'D'isabled.
176                 'H': ACB_HOMDIRREQ, # 'H'omedir required.
177                 'T': ACB_TEMPDUP,   # 'T'emp account.
178                 'U': ACB_NORMAL,    # 'U'ser account (normal).
179                 'M': ACB_MNS,       # 'M'NS logon user account. What is this ?
180                 'W': ACB_WSTRUST,   # 'W'orkstation account.
181                 'S': ACB_SVRTRUST,  # 'S'erver account. 
182                 'L': ACB_AUTOLOCK,  # 'L'ocked account.
183                 'X': ACB_PWNOEXP,   # No 'X'piry on password
184                 'I': ACB_DOMTRUST,  # 'I'nterdomain trust account.
185         ' ': 0
186         }
187
188
189 class Smbpasswd:
190     def __init__(self, file):
191         pass
192
193
194 class TdbSam:
195     def __init__(self, file):
196         self.tdb = tdb.Tdb(file, flags=os.O_RDONLY)
197
198
199 class WinsDatabase:
200     def __init__(self, file):
201         pass
202
203
204 class Samba3:
205     def __init__(self, smbconfpath, libdir):
206         self.smbconfpath = smbconfpath
207         self.libdir = libdir
208
209     def get_policy_db(self):
210         return PolicyDatabase(os.path.join(libdir, "account_policy.tdb"))
211     
212     def get_registry(self):
213         return Registry(os.path.join(libdir, "registry.tdb"))
214
215     def get_secrets_db(self):
216         return SecretsDatabase(os.path.join(libdir, "secrets.tdb"))
217
218     def get_shares_db(self):
219         return ShareInfoDatabase(os.path.join(libdir, "share_info.tdb"))
220
221     def get_idmap_db(self):
222         return IdmapDatabase(os.path.join(libdir, "winbindd_idmap.tdb"))
223
224     def get_wins_db(self):
225         return WinsDatabase(os.path.join(libdir, "wins.dat"))
226
227     def get_groupmapping_db(self):
228         return GroupMappingDatabase(os.path.join(libdir, "group_mapping.tdb"))